Mercurial > hg > CbC > CbC_llvm
comparison lib/Object/XCOFFObjectFile.cpp @ 148:63bd29f05246
merged
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 14 Aug 2019 19:46:37 +0900 |
parents | c2174574ed3a |
children |
comparison
equal
deleted
inserted
replaced
146:3fc4d5c3e21e | 148:63bd29f05246 |
---|---|
1 //===--- XCOFFObjectFile.cpp - XCOFF object file implementation -----------===// | |
2 // | |
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
4 // See https://llvm.org/LICENSE.txt for license information. | |
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
6 // | |
7 //===----------------------------------------------------------------------===// | |
8 // | |
9 // This file defines the XCOFFObjectFile class. | |
10 // | |
11 //===----------------------------------------------------------------------===// | |
12 | |
13 #include "llvm/Object/XCOFFObjectFile.h" | |
14 #include <cstddef> | |
15 #include <cstring> | |
16 | |
17 namespace llvm { | |
18 namespace object { | |
19 | |
20 // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer | |
21 // 'M'. Returns a pointer to the underlying object on success. | |
22 template <typename T> | |
23 static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr, | |
24 const uint64_t Size = sizeof(T)) { | |
25 uintptr_t Addr = uintptr_t(Ptr); | |
26 if (std::error_code EC = Binary::checkOffset(M, Addr, Size)) | |
27 return errorCodeToError(EC); | |
28 return reinterpret_cast<const T *>(Addr); | |
29 } | |
30 | |
31 static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) { | |
32 return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) + | |
33 Offset); | |
34 } | |
35 | |
36 template <typename T> static const T *viewAs(uintptr_t in) { | |
37 return reinterpret_cast<const T *>(in); | |
38 } | |
39 | |
40 static StringRef generateStringRef(const char *Name) { | |
41 auto NulCharPtr = | |
42 static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize)); | |
43 return NulCharPtr ? StringRef(Name, NulCharPtr - Name) | |
44 : StringRef(Name, XCOFF::NameSize); | |
45 } | |
46 | |
47 void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr, | |
48 uintptr_t TableAddress) const { | |
49 if (Addr < TableAddress) | |
50 report_fatal_error("Section header outside of section header table."); | |
51 | |
52 uintptr_t Offset = Addr - TableAddress; | |
53 if (Offset >= getSectionHeaderSize() * getNumberOfSections()) | |
54 report_fatal_error("Section header outside of section header table."); | |
55 | |
56 if (Offset % getSectionHeaderSize() != 0) | |
57 report_fatal_error( | |
58 "Section header pointer does not point to a valid section header."); | |
59 } | |
60 | |
61 const XCOFFSectionHeader32 * | |
62 XCOFFObjectFile::toSection32(DataRefImpl Ref) const { | |
63 assert(!is64Bit() && "32-bit interface called on 64-bit object file."); | |
64 #ifndef NDEBUG | |
65 checkSectionAddress(Ref.p, getSectionHeaderTableAddress()); | |
66 #endif | |
67 return viewAs<XCOFFSectionHeader32>(Ref.p); | |
68 } | |
69 | |
70 const XCOFFSectionHeader64 * | |
71 XCOFFObjectFile::toSection64(DataRefImpl Ref) const { | |
72 assert(is64Bit() && "64-bit interface called on a 32-bit object file."); | |
73 #ifndef NDEBUG | |
74 checkSectionAddress(Ref.p, getSectionHeaderTableAddress()); | |
75 #endif | |
76 return viewAs<XCOFFSectionHeader64>(Ref.p); | |
77 } | |
78 | |
79 const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const { | |
80 assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); | |
81 assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!"); | |
82 auto SymEntPtr = viewAs<XCOFFSymbolEntry>(Ref.p); | |
83 return SymEntPtr; | |
84 } | |
85 | |
86 const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const { | |
87 assert(!is64Bit() && "32-bit interface called on 64-bit object file."); | |
88 return static_cast<const XCOFFFileHeader32 *>(FileHeader); | |
89 } | |
90 | |
91 const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const { | |
92 assert(is64Bit() && "64-bit interface called on a 32-bit object file."); | |
93 return static_cast<const XCOFFFileHeader64 *>(FileHeader); | |
94 } | |
95 | |
96 const XCOFFSectionHeader32 * | |
97 XCOFFObjectFile::sectionHeaderTable32() const { | |
98 assert(!is64Bit() && "32-bit interface called on 64-bit object file."); | |
99 return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable); | |
100 } | |
101 | |
102 const XCOFFSectionHeader64 * | |
103 XCOFFObjectFile::sectionHeaderTable64() const { | |
104 assert(is64Bit() && "64-bit interface called on a 32-bit object file."); | |
105 return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable); | |
106 } | |
107 | |
108 void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { | |
109 const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); | |
110 SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1; | |
111 Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr); | |
112 } | |
113 | |
114 Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const { | |
115 const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); | |
116 | |
117 if (SymEntPtr->NameInStrTbl.Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC) | |
118 return generateStringRef(SymEntPtr->SymbolName); | |
119 | |
120 // A storage class value with the high-order bit on indicates that the name is | |
121 // a symbolic debugger stabstring. | |
122 if (SymEntPtr->StorageClass & 0x80) | |
123 return StringRef("Unimplemented Debug Name"); | |
124 | |
125 uint32_t Offset = SymEntPtr->NameInStrTbl.Offset; | |
126 // The byte offset is relative to the start of the string table | |
127 // or .debug section. A byte offset value of 0 is a null or zero-length symbol | |
128 // name. A byte offset in the range 1 to 3 (inclusive) points into the length | |
129 // field; as a soft-error recovery mechanism, we treat such cases as having an | |
130 // offset of 0. | |
131 if (Offset < 4) | |
132 return StringRef(nullptr, 0); | |
133 | |
134 if (StringTable.Data != nullptr && StringTable.Size > Offset) | |
135 return (StringTable.Data + Offset); | |
136 | |
137 return make_error<GenericBinaryError>("Symbol Name parse failed", | |
138 object_error::parse_failed); | |
139 } | |
140 | |
141 Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { | |
142 uint64_t Result = 0; | |
143 llvm_unreachable("Not yet implemented!"); | |
144 return Result; | |
145 } | |
146 | |
147 uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { | |
148 return toSymbolEntry(Symb)->Value; | |
149 } | |
150 | |
151 uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { | |
152 uint64_t Result = 0; | |
153 llvm_unreachable("Not yet implemented!"); | |
154 return Result; | |
155 } | |
156 | |
157 Expected<SymbolRef::Type> | |
158 XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const { | |
159 llvm_unreachable("Not yet implemented!"); | |
160 return SymbolRef::ST_Other; | |
161 } | |
162 | |
163 Expected<section_iterator> | |
164 XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { | |
165 const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb); | |
166 int16_t SectNum = SymEntPtr->SectionNumber; | |
167 | |
168 if (isReservedSectionNumber(SectNum)) | |
169 return section_end(); | |
170 | |
171 Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum); | |
172 if (!ExpSec) | |
173 return ExpSec.takeError(); | |
174 | |
175 return section_iterator(SectionRef(ExpSec.get(), this)); | |
176 } | |
177 | |
178 void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const { | |
179 const char *Ptr = reinterpret_cast<const char *>(Sec.p); | |
180 Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize()); | |
181 } | |
182 | |
183 Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const { | |
184 return generateStringRef(getSectionNameInternal(Sec)); | |
185 } | |
186 | |
187 uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const { | |
188 // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t | |
189 // with MSVC. | |
190 if (is64Bit()) | |
191 return toSection64(Sec)->VirtualAddress; | |
192 | |
193 return toSection32(Sec)->VirtualAddress; | |
194 } | |
195 | |
196 uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const { | |
197 // Section numbers in XCOFF are numbered beginning at 1. A section number of | |
198 // zero is used to indicate that a symbol is being imported or is undefined. | |
199 if (is64Bit()) | |
200 return toSection64(Sec) - sectionHeaderTable64() + 1; | |
201 else | |
202 return toSection32(Sec) - sectionHeaderTable32() + 1; | |
203 } | |
204 | |
205 uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const { | |
206 // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t | |
207 // with MSVC. | |
208 if (is64Bit()) | |
209 return toSection64(Sec)->SectionSize; | |
210 | |
211 return toSection32(Sec)->SectionSize; | |
212 } | |
213 | |
214 Expected<ArrayRef<uint8_t>> | |
215 XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const { | |
216 llvm_unreachable("Not yet implemented!"); | |
217 } | |
218 | |
219 uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { | |
220 uint64_t Result = 0; | |
221 llvm_unreachable("Not yet implemented!"); | |
222 return Result; | |
223 } | |
224 | |
225 bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { | |
226 bool Result = false; | |
227 llvm_unreachable("Not yet implemented!"); | |
228 return Result; | |
229 } | |
230 | |
231 bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const { | |
232 return getSectionFlags(Sec) & XCOFF::STYP_TEXT; | |
233 } | |
234 | |
235 bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const { | |
236 uint32_t Flags = getSectionFlags(Sec); | |
237 return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA); | |
238 } | |
239 | |
240 bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const { | |
241 uint32_t Flags = getSectionFlags(Sec); | |
242 return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS); | |
243 } | |
244 | |
245 bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const { | |
246 bool Result = false; | |
247 llvm_unreachable("Not yet implemented!"); | |
248 return Result; | |
249 } | |
250 | |
251 relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const { | |
252 llvm_unreachable("Not yet implemented!"); | |
253 return relocation_iterator(RelocationRef()); | |
254 } | |
255 | |
256 relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const { | |
257 llvm_unreachable("Not yet implemented!"); | |
258 return relocation_iterator(RelocationRef()); | |
259 } | |
260 | |
261 void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { | |
262 llvm_unreachable("Not yet implemented!"); | |
263 return; | |
264 } | |
265 | |
266 uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { | |
267 llvm_unreachable("Not yet implemented!"); | |
268 uint64_t Result = 0; | |
269 return Result; | |
270 } | |
271 | |
272 symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { | |
273 llvm_unreachable("Not yet implemented!"); | |
274 return symbol_iterator(SymbolRef()); | |
275 } | |
276 | |
277 uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const { | |
278 llvm_unreachable("Not yet implemented!"); | |
279 uint64_t Result = 0; | |
280 return Result; | |
281 } | |
282 | |
283 void XCOFFObjectFile::getRelocationTypeName( | |
284 DataRefImpl Rel, SmallVectorImpl<char> &Result) const { | |
285 llvm_unreachable("Not yet implemented!"); | |
286 return; | |
287 } | |
288 | |
289 uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { | |
290 uint32_t Result = 0; | |
291 llvm_unreachable("Not yet implemented!"); | |
292 return Result; | |
293 } | |
294 | |
295 basic_symbol_iterator XCOFFObjectFile::symbol_begin() const { | |
296 assert(!is64Bit() && "64-bit support not implemented yet."); | |
297 DataRefImpl SymDRI; | |
298 SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr); | |
299 return basic_symbol_iterator(SymbolRef(SymDRI, this)); | |
300 } | |
301 | |
302 basic_symbol_iterator XCOFFObjectFile::symbol_end() const { | |
303 assert(!is64Bit() && "64-bit support not implemented yet."); | |
304 DataRefImpl SymDRI; | |
305 SymDRI.p = reinterpret_cast<uintptr_t>( | |
306 SymbolTblPtr + getLogicalNumberOfSymbolTableEntries32()); | |
307 return basic_symbol_iterator(SymbolRef(SymDRI, this)); | |
308 } | |
309 | |
310 section_iterator XCOFFObjectFile::section_begin() const { | |
311 DataRefImpl DRI; | |
312 DRI.p = getSectionHeaderTableAddress(); | |
313 return section_iterator(SectionRef(DRI, this)); | |
314 } | |
315 | |
316 section_iterator XCOFFObjectFile::section_end() const { | |
317 DataRefImpl DRI; | |
318 DRI.p = getWithOffset(getSectionHeaderTableAddress(), | |
319 getNumberOfSections() * getSectionHeaderSize()); | |
320 return section_iterator(SectionRef(DRI, this)); | |
321 } | |
322 | |
323 uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; } | |
324 | |
325 StringRef XCOFFObjectFile::getFileFormatName() const { | |
326 return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000"; | |
327 } | |
328 | |
329 Triple::ArchType XCOFFObjectFile::getArch() const { | |
330 return is64Bit() ? Triple::ppc64 : Triple::ppc; | |
331 } | |
332 | |
333 SubtargetFeatures XCOFFObjectFile::getFeatures() const { | |
334 llvm_unreachable("Not yet implemented!"); | |
335 return SubtargetFeatures(); | |
336 } | |
337 | |
338 bool XCOFFObjectFile::isRelocatableObject() const { | |
339 bool Result = false; | |
340 llvm_unreachable("Not yet implemented!"); | |
341 return Result; | |
342 } | |
343 | |
344 Expected<uint64_t> XCOFFObjectFile::getStartAddress() const { | |
345 // TODO FIXME Should get from auxiliary_header->o_entry when support for the | |
346 // auxiliary_header is added. | |
347 return 0; | |
348 } | |
349 | |
350 size_t XCOFFObjectFile::getFileHeaderSize() const { | |
351 return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32); | |
352 } | |
353 | |
354 size_t XCOFFObjectFile::getSectionHeaderSize() const { | |
355 return is64Bit() ? sizeof(XCOFFSectionHeader64) : | |
356 sizeof(XCOFFSectionHeader32); | |
357 } | |
358 | |
359 bool XCOFFObjectFile::is64Bit() const { | |
360 return Binary::ID_XCOFF64 == getType(); | |
361 } | |
362 | |
363 uint16_t XCOFFObjectFile::getMagic() const { | |
364 return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic; | |
365 } | |
366 | |
367 Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const { | |
368 if (Num <= 0 || Num > getNumberOfSections()) | |
369 return errorCodeToError(object_error::invalid_section_index); | |
370 | |
371 DataRefImpl DRI; | |
372 DRI.p = getWithOffset(getSectionHeaderTableAddress(), | |
373 getSectionHeaderSize() * (Num - 1)); | |
374 return DRI; | |
375 } | |
376 | |
377 Expected<StringRef> | |
378 XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const { | |
379 assert(!is64Bit() && "Symbol table support not implemented for 64-bit."); | |
380 int16_t SectionNum = SymEntPtr->SectionNumber; | |
381 | |
382 switch (SectionNum) { | |
383 case XCOFF::N_DEBUG: | |
384 return "N_DEBUG"; | |
385 case XCOFF::N_ABS: | |
386 return "N_ABS"; | |
387 case XCOFF::N_UNDEF: | |
388 return "N_UNDEF"; | |
389 default: | |
390 Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum); | |
391 if (SecRef) | |
392 return generateStringRef(getSectionNameInternal(SecRef.get())); | |
393 return SecRef.takeError(); | |
394 } | |
395 } | |
396 | |
397 bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) { | |
398 return (SectionNumber <= 0 && SectionNumber >= -2); | |
399 } | |
400 | |
401 uint16_t XCOFFObjectFile::getNumberOfSections() const { | |
402 return is64Bit() ? fileHeader64()->NumberOfSections | |
403 : fileHeader32()->NumberOfSections; | |
404 } | |
405 | |
406 int32_t XCOFFObjectFile::getTimeStamp() const { | |
407 return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp; | |
408 } | |
409 | |
410 uint16_t XCOFFObjectFile::getOptionalHeaderSize() const { | |
411 return is64Bit() ? fileHeader64()->AuxHeaderSize | |
412 : fileHeader32()->AuxHeaderSize; | |
413 } | |
414 | |
415 uint32_t XCOFFObjectFile::getSymbolTableOffset32() const { | |
416 return fileHeader32()->SymbolTableOffset; | |
417 } | |
418 | |
419 int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const { | |
420 // As far as symbol table size is concerned, if this field is negative it is | |
421 // to be treated as a 0. However since this field is also used for printing we | |
422 // don't want to truncate any negative values. | |
423 return fileHeader32()->NumberOfSymTableEntries; | |
424 } | |
425 | |
426 uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const { | |
427 return (fileHeader32()->NumberOfSymTableEntries >= 0 | |
428 ? fileHeader32()->NumberOfSymTableEntries | |
429 : 0); | |
430 } | |
431 | |
432 uint64_t XCOFFObjectFile::getSymbolTableOffset64() const { | |
433 return fileHeader64()->SymbolTableOffset; | |
434 } | |
435 | |
436 uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const { | |
437 return fileHeader64()->NumberOfSymTableEntries; | |
438 } | |
439 | |
440 uint16_t XCOFFObjectFile::getFlags() const { | |
441 return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags; | |
442 } | |
443 | |
444 const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const { | |
445 return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name; | |
446 } | |
447 | |
448 uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const { | |
449 return reinterpret_cast<uintptr_t>(SectionHeaderTable); | |
450 } | |
451 | |
452 int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const { | |
453 return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags; | |
454 } | |
455 | |
456 XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object) | |
457 : ObjectFile(Type, Object) { | |
458 assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64); | |
459 } | |
460 | |
461 ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const { | |
462 assert(is64Bit() && "64-bit interface called for non 64-bit file."); | |
463 const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64(); | |
464 return ArrayRef<XCOFFSectionHeader64>(TablePtr, | |
465 TablePtr + getNumberOfSections()); | |
466 } | |
467 | |
468 ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const { | |
469 assert(!is64Bit() && "32-bit interface called for non 32-bit file."); | |
470 const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32(); | |
471 return ArrayRef<XCOFFSectionHeader32>(TablePtr, | |
472 TablePtr + getNumberOfSections()); | |
473 } | |
474 | |
475 Expected<XCOFFStringTable> | |
476 XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) { | |
477 // If there is a string table, then the buffer must contain at least 4 bytes | |
478 // for the string table's size. Not having a string table is not an error. | |
479 if (auto EC = Binary::checkOffset( | |
480 Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) | |
481 return XCOFFStringTable{0, nullptr}; | |
482 | |
483 // Read the size out of the buffer. | |
484 uint32_t Size = support::endian::read32be(Obj->base() + Offset); | |
485 | |
486 // If the size is less then 4, then the string table is just a size and no | |
487 // string data. | |
488 if (Size <= 4) | |
489 return XCOFFStringTable{4, nullptr}; | |
490 | |
491 auto StringTableOrErr = | |
492 getObject<char>(Obj->Data, Obj->base() + Offset, Size); | |
493 if (Error E = StringTableOrErr.takeError()) | |
494 return std::move(E); | |
495 | |
496 const char *StringTablePtr = StringTableOrErr.get(); | |
497 if (StringTablePtr[Size - 1] != '\0') | |
498 return errorCodeToError(object_error::string_table_non_null_end); | |
499 | |
500 return XCOFFStringTable{Size, StringTablePtr}; | |
501 } | |
502 | |
503 Expected<std::unique_ptr<XCOFFObjectFile>> | |
504 XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) { | |
505 // Can't use make_unique because of the private constructor. | |
506 std::unique_ptr<XCOFFObjectFile> Obj; | |
507 Obj.reset(new XCOFFObjectFile(Type, MBR)); | |
508 | |
509 uint64_t CurOffset = 0; | |
510 const auto *Base = Obj->base(); | |
511 MemoryBufferRef Data = Obj->Data; | |
512 | |
513 // Parse file header. | |
514 auto FileHeaderOrErr = | |
515 getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize()); | |
516 if (Error E = FileHeaderOrErr.takeError()) | |
517 return std::move(E); | |
518 Obj->FileHeader = FileHeaderOrErr.get(); | |
519 | |
520 CurOffset += Obj->getFileHeaderSize(); | |
521 // TODO FIXME we don't have support for an optional header yet, so just skip | |
522 // past it. | |
523 CurOffset += Obj->getOptionalHeaderSize(); | |
524 | |
525 // Parse the section header table if it is present. | |
526 if (Obj->getNumberOfSections()) { | |
527 auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset, | |
528 Obj->getNumberOfSections() * | |
529 Obj->getSectionHeaderSize()); | |
530 if (Error E = SecHeadersOrErr.takeError()) | |
531 return std::move(E); | |
532 Obj->SectionHeaderTable = SecHeadersOrErr.get(); | |
533 } | |
534 | |
535 // 64-bit object supports only file header and section headers for now. | |
536 if (Obj->is64Bit()) | |
537 return std::move(Obj); | |
538 | |
539 // If there is no symbol table we are done parsing the memory buffer. | |
540 if (Obj->getLogicalNumberOfSymbolTableEntries32() == 0) | |
541 return std::move(Obj); | |
542 | |
543 // Parse symbol table. | |
544 CurOffset = Obj->fileHeader32()->SymbolTableOffset; | |
545 uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) * | |
546 Obj->getLogicalNumberOfSymbolTableEntries32(); | |
547 auto SymTableOrErr = | |
548 getObject<XCOFFSymbolEntry>(Data, Base + CurOffset, SymbolTableSize); | |
549 if (Error E = SymTableOrErr.takeError()) | |
550 return std::move(E); | |
551 Obj->SymbolTblPtr = SymTableOrErr.get(); | |
552 CurOffset += SymbolTableSize; | |
553 | |
554 // Parse String table. | |
555 Expected<XCOFFStringTable> StringTableOrErr = | |
556 parseStringTable(Obj.get(), CurOffset); | |
557 if (Error E = StringTableOrErr.takeError()) | |
558 return std::move(E); | |
559 Obj->StringTable = StringTableOrErr.get(); | |
560 | |
561 return std::move(Obj); | |
562 } | |
563 | |
564 Expected<std::unique_ptr<ObjectFile>> | |
565 ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef, | |
566 unsigned FileType) { | |
567 return XCOFFObjectFile::create(FileType, MemBufRef); | |
568 } | |
569 | |
570 StringRef XCOFFSectionHeader32::getName() const { | |
571 return generateStringRef(Name); | |
572 } | |
573 | |
574 StringRef XCOFFSectionHeader64::getName() const { | |
575 return generateStringRef(Name); | |
576 } | |
577 | |
578 } // namespace object | |
579 } // namespace llvm |