1 //===--- XCOFFObjectFile.cpp - XCOFF object file implementation -----------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines the XCOFFObjectFile class.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Object/XCOFFObjectFile.h"
20 enum { FUNCTION_SYM
= 0x20, SYM_TYPE_MASK
= 0x07, RELOC_OVERFLOW
= 65535 };
22 // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
23 // 'M'. Returns a pointer to the underlying object on success.
25 static Expected
<const T
*> getObject(MemoryBufferRef M
, const void *Ptr
,
26 const uint64_t Size
= sizeof(T
)) {
27 uintptr_t Addr
= uintptr_t(Ptr
);
28 if (std::error_code EC
= Binary::checkOffset(M
, Addr
, Size
))
29 return errorCodeToError(EC
);
30 return reinterpret_cast<const T
*>(Addr
);
33 static uintptr_t getWithOffset(uintptr_t Base
, ptrdiff_t Offset
) {
34 return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base
) +
38 template <typename T
> static const T
*viewAs(uintptr_t in
) {
39 return reinterpret_cast<const T
*>(in
);
42 static StringRef
generateXCOFFFixedNameStringRef(const char *Name
) {
44 static_cast<const char *>(memchr(Name
, '\0', XCOFF::NameSize
));
45 return NulCharPtr
? StringRef(Name
, NulCharPtr
- Name
)
46 : StringRef(Name
, XCOFF::NameSize
);
49 bool XCOFFRelocation32::isRelocationSigned() const {
50 return Info
& XR_SIGN_INDICATOR_MASK
;
53 bool XCOFFRelocation32::isFixupIndicated() const {
54 return Info
& XR_FIXUP_INDICATOR_MASK
;
57 uint8_t XCOFFRelocation32::getRelocatedLength() const {
58 // The relocation encodes the bit length being relocated minus 1. Add back
59 // the 1 to get the actual length being relocated.
60 return (Info
& XR_BIASED_LENGTH_MASK
) + 1;
63 void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr
,
64 uintptr_t TableAddress
) const {
65 if (Addr
< TableAddress
)
66 report_fatal_error("Section header outside of section header table.");
68 uintptr_t Offset
= Addr
- TableAddress
;
69 if (Offset
>= getSectionHeaderSize() * getNumberOfSections())
70 report_fatal_error("Section header outside of section header table.");
72 if (Offset
% getSectionHeaderSize() != 0)
74 "Section header pointer does not point to a valid section header.");
77 const XCOFFSectionHeader32
*
78 XCOFFObjectFile::toSection32(DataRefImpl Ref
) const {
79 assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
81 checkSectionAddress(Ref
.p
, getSectionHeaderTableAddress());
83 return viewAs
<XCOFFSectionHeader32
>(Ref
.p
);
86 const XCOFFSectionHeader64
*
87 XCOFFObjectFile::toSection64(DataRefImpl Ref
) const {
88 assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
90 checkSectionAddress(Ref
.p
, getSectionHeaderTableAddress());
92 return viewAs
<XCOFFSectionHeader64
>(Ref
.p
);
95 const XCOFFSymbolEntry
*XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref
) const {
96 assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
97 assert(Ref
.p
!= 0 && "Symbol table pointer can not be nullptr!");
99 checkSymbolEntryPointer(Ref
.p
);
101 auto SymEntPtr
= viewAs
<XCOFFSymbolEntry
>(Ref
.p
);
105 const XCOFFFileHeader32
*XCOFFObjectFile::fileHeader32() const {
106 assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
107 return static_cast<const XCOFFFileHeader32
*>(FileHeader
);
110 const XCOFFFileHeader64
*XCOFFObjectFile::fileHeader64() const {
111 assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
112 return static_cast<const XCOFFFileHeader64
*>(FileHeader
);
115 const XCOFFSectionHeader32
*
116 XCOFFObjectFile::sectionHeaderTable32() const {
117 assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
118 return static_cast<const XCOFFSectionHeader32
*>(SectionHeaderTable
);
121 const XCOFFSectionHeader64
*
122 XCOFFObjectFile::sectionHeaderTable64() const {
123 assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
124 return static_cast<const XCOFFSectionHeader64
*>(SectionHeaderTable
);
127 void XCOFFObjectFile::moveSymbolNext(DataRefImpl
&Symb
) const {
128 const XCOFFSymbolEntry
*SymEntPtr
= toSymbolEntry(Symb
);
129 SymEntPtr
+= SymEntPtr
->NumberOfAuxEntries
+ 1;
131 // This function is used by basic_symbol_iterator, which allows to
132 // point to the end-of-symbol-table address.
133 if (reinterpret_cast<uintptr_t>(SymEntPtr
) != getEndOfSymbolTableAddress())
134 checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(SymEntPtr
));
136 Symb
.p
= reinterpret_cast<uintptr_t>(SymEntPtr
);
140 XCOFFObjectFile::getStringTableEntry(uint32_t Offset
) const {
141 // The byte offset is relative to the start of the string table.
142 // A byte offset value of 0 is a null or zero-length symbol
143 // name. A byte offset in the range 1 to 3 (inclusive) points into the length
144 // field; as a soft-error recovery mechanism, we treat such cases as having an
147 return StringRef(nullptr, 0);
149 if (StringTable
.Data
!= nullptr && StringTable
.Size
> Offset
)
150 return (StringTable
.Data
+ Offset
);
152 return make_error
<GenericBinaryError
>("Bad offset for string table entry",
153 object_error::parse_failed
);
157 XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt
*CFileEntPtr
) const {
158 if (CFileEntPtr
->NameInStrTbl
.Magic
!=
159 XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC
)
160 return generateXCOFFFixedNameStringRef(CFileEntPtr
->Name
);
161 return getStringTableEntry(CFileEntPtr
->NameInStrTbl
.Offset
);
164 Expected
<StringRef
> XCOFFObjectFile::getSymbolName(DataRefImpl Symb
) const {
165 const XCOFFSymbolEntry
*SymEntPtr
= toSymbolEntry(Symb
);
167 // A storage class value with the high-order bit on indicates that the name is
168 // a symbolic debugger stabstring.
169 if (SymEntPtr
->StorageClass
& 0x80)
170 return StringRef("Unimplemented Debug Name");
172 if (SymEntPtr
->NameInStrTbl
.Magic
!= XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC
)
173 return generateXCOFFFixedNameStringRef(SymEntPtr
->SymbolName
);
175 return getStringTableEntry(SymEntPtr
->NameInStrTbl
.Offset
);
178 Expected
<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb
) const {
180 llvm_unreachable("Not yet implemented!");
184 uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb
) const {
185 assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
186 return toSymbolEntry(Symb
)->Value
;
189 uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb
) const {
191 llvm_unreachable("Not yet implemented!");
195 Expected
<SymbolRef::Type
>
196 XCOFFObjectFile::getSymbolType(DataRefImpl Symb
) const {
197 llvm_unreachable("Not yet implemented!");
198 return SymbolRef::ST_Other
;
201 Expected
<section_iterator
>
202 XCOFFObjectFile::getSymbolSection(DataRefImpl Symb
) const {
203 const XCOFFSymbolEntry
*SymEntPtr
= toSymbolEntry(Symb
);
204 int16_t SectNum
= SymEntPtr
->SectionNumber
;
206 if (isReservedSectionNumber(SectNum
))
207 return section_end();
209 Expected
<DataRefImpl
> ExpSec
= getSectionByNum(SectNum
);
211 return ExpSec
.takeError();
213 return section_iterator(SectionRef(ExpSec
.get(), this));
216 void XCOFFObjectFile::moveSectionNext(DataRefImpl
&Sec
) const {
217 const char *Ptr
= reinterpret_cast<const char *>(Sec
.p
);
218 Sec
.p
= reinterpret_cast<uintptr_t>(Ptr
+ getSectionHeaderSize());
221 Expected
<StringRef
> XCOFFObjectFile::getSectionName(DataRefImpl Sec
) const {
222 return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec
));
225 uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec
) const {
226 // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
229 return toSection64(Sec
)->VirtualAddress
;
231 return toSection32(Sec
)->VirtualAddress
;
234 uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec
) const {
235 // Section numbers in XCOFF are numbered beginning at 1. A section number of
236 // zero is used to indicate that a symbol is being imported or is undefined.
238 return toSection64(Sec
) - sectionHeaderTable64() + 1;
240 return toSection32(Sec
) - sectionHeaderTable32() + 1;
243 uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec
) const {
244 // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
247 return toSection64(Sec
)->SectionSize
;
249 return toSection32(Sec
)->SectionSize
;
252 Expected
<ArrayRef
<uint8_t>>
253 XCOFFObjectFile::getSectionContents(DataRefImpl Sec
) const {
254 llvm_unreachable("Not yet implemented!");
257 uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec
) const {
259 llvm_unreachable("Not yet implemented!");
263 bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec
) const {
265 llvm_unreachable("Not yet implemented!");
269 bool XCOFFObjectFile::isSectionText(DataRefImpl Sec
) const {
270 return getSectionFlags(Sec
) & XCOFF::STYP_TEXT
;
273 bool XCOFFObjectFile::isSectionData(DataRefImpl Sec
) const {
274 uint32_t Flags
= getSectionFlags(Sec
);
275 return Flags
& (XCOFF::STYP_DATA
| XCOFF::STYP_TDATA
);
278 bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec
) const {
279 uint32_t Flags
= getSectionFlags(Sec
);
280 return Flags
& (XCOFF::STYP_BSS
| XCOFF::STYP_TBSS
);
283 bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec
) const {
285 llvm_unreachable("Not yet implemented!");
289 relocation_iterator
XCOFFObjectFile::section_rel_begin(DataRefImpl Sec
) const {
290 llvm_unreachable("Not yet implemented!");
291 return relocation_iterator(RelocationRef());
294 relocation_iterator
XCOFFObjectFile::section_rel_end(DataRefImpl Sec
) const {
295 llvm_unreachable("Not yet implemented!");
296 return relocation_iterator(RelocationRef());
299 void XCOFFObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const {
300 llvm_unreachable("Not yet implemented!");
304 uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel
) const {
305 llvm_unreachable("Not yet implemented!");
310 symbol_iterator
XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel
) const {
311 llvm_unreachable("Not yet implemented!");
312 return symbol_iterator(SymbolRef());
315 uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel
) const {
316 llvm_unreachable("Not yet implemented!");
321 void XCOFFObjectFile::getRelocationTypeName(
322 DataRefImpl Rel
, SmallVectorImpl
<char> &Result
) const {
323 llvm_unreachable("Not yet implemented!");
327 uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb
) const {
329 llvm_unreachable("Not yet implemented!");
333 basic_symbol_iterator
XCOFFObjectFile::symbol_begin() const {
334 assert(!is64Bit() && "64-bit support not implemented yet.");
336 SymDRI
.p
= reinterpret_cast<uintptr_t>(SymbolTblPtr
);
337 return basic_symbol_iterator(SymbolRef(SymDRI
, this));
340 basic_symbol_iterator
XCOFFObjectFile::symbol_end() const {
341 assert(!is64Bit() && "64-bit support not implemented yet.");
343 SymDRI
.p
= reinterpret_cast<uintptr_t>(
344 SymbolTblPtr
+ getLogicalNumberOfSymbolTableEntries32());
345 return basic_symbol_iterator(SymbolRef(SymDRI
, this));
348 section_iterator
XCOFFObjectFile::section_begin() const {
350 DRI
.p
= getSectionHeaderTableAddress();
351 return section_iterator(SectionRef(DRI
, this));
354 section_iterator
XCOFFObjectFile::section_end() const {
356 DRI
.p
= getWithOffset(getSectionHeaderTableAddress(),
357 getNumberOfSections() * getSectionHeaderSize());
358 return section_iterator(SectionRef(DRI
, this));
361 uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; }
363 StringRef
XCOFFObjectFile::getFileFormatName() const {
364 return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000";
367 Triple::ArchType
XCOFFObjectFile::getArch() const {
368 return is64Bit() ? Triple::ppc64
: Triple::ppc
;
371 SubtargetFeatures
XCOFFObjectFile::getFeatures() const {
372 llvm_unreachable("Not yet implemented!");
373 return SubtargetFeatures();
376 bool XCOFFObjectFile::isRelocatableObject() const {
378 llvm_unreachable("Not yet implemented!");
382 Expected
<uint64_t> XCOFFObjectFile::getStartAddress() const {
383 // TODO FIXME Should get from auxiliary_header->o_entry when support for the
384 // auxiliary_header is added.
388 size_t XCOFFObjectFile::getFileHeaderSize() const {
389 return is64Bit() ? sizeof(XCOFFFileHeader64
) : sizeof(XCOFFFileHeader32
);
392 size_t XCOFFObjectFile::getSectionHeaderSize() const {
393 return is64Bit() ? sizeof(XCOFFSectionHeader64
) :
394 sizeof(XCOFFSectionHeader32
);
397 bool XCOFFObjectFile::is64Bit() const {
398 return Binary::ID_XCOFF64
== getType();
401 uint16_t XCOFFObjectFile::getMagic() const {
402 return is64Bit() ? fileHeader64()->Magic
: fileHeader32()->Magic
;
405 Expected
<DataRefImpl
> XCOFFObjectFile::getSectionByNum(int16_t Num
) const {
406 if (Num
<= 0 || Num
> getNumberOfSections())
407 return errorCodeToError(object_error::invalid_section_index
);
410 DRI
.p
= getWithOffset(getSectionHeaderTableAddress(),
411 getSectionHeaderSize() * (Num
- 1));
416 XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry
*SymEntPtr
) const {
417 assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
418 int16_t SectionNum
= SymEntPtr
->SectionNumber
;
420 switch (SectionNum
) {
428 Expected
<DataRefImpl
> SecRef
= getSectionByNum(SectionNum
);
430 return generateXCOFFFixedNameStringRef(
431 getSectionNameInternal(SecRef
.get()));
432 return SecRef
.takeError();
436 bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber
) {
437 return (SectionNumber
<= 0 && SectionNumber
>= -2);
440 uint16_t XCOFFObjectFile::getNumberOfSections() const {
441 return is64Bit() ? fileHeader64()->NumberOfSections
442 : fileHeader32()->NumberOfSections
;
445 int32_t XCOFFObjectFile::getTimeStamp() const {
446 return is64Bit() ? fileHeader64()->TimeStamp
: fileHeader32()->TimeStamp
;
449 uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
450 return is64Bit() ? fileHeader64()->AuxHeaderSize
451 : fileHeader32()->AuxHeaderSize
;
454 uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
455 return fileHeader32()->SymbolTableOffset
;
458 int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const {
459 // As far as symbol table size is concerned, if this field is negative it is
460 // to be treated as a 0. However since this field is also used for printing we
461 // don't want to truncate any negative values.
462 return fileHeader32()->NumberOfSymTableEntries
;
465 uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
466 return (fileHeader32()->NumberOfSymTableEntries
>= 0
467 ? fileHeader32()->NumberOfSymTableEntries
471 uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
472 return fileHeader64()->SymbolTableOffset
;
475 uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
476 return fileHeader64()->NumberOfSymTableEntries
;
479 uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const {
480 uint32_t NumberOfSymTableEntries
=
481 is64Bit() ? getNumberOfSymbolTableEntries64()
482 : getLogicalNumberOfSymbolTableEntries32();
483 return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr
),
484 XCOFF::SymbolTableEntrySize
* NumberOfSymTableEntries
);
487 void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr
) const {
488 if (SymbolEntPtr
< reinterpret_cast<uintptr_t>(SymbolTblPtr
))
489 report_fatal_error("Symbol table entry is outside of symbol table.");
491 if (SymbolEntPtr
>= getEndOfSymbolTableAddress())
492 report_fatal_error("Symbol table entry is outside of symbol table.");
494 ptrdiff_t Offset
= reinterpret_cast<const char *>(SymbolEntPtr
) -
495 reinterpret_cast<const char *>(SymbolTblPtr
);
497 if (Offset
% XCOFF::SymbolTableEntrySize
!= 0)
499 "Symbol table entry position is not valid inside of symbol table.");
502 uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr
) const {
503 return (reinterpret_cast<const char *>(SymbolEntPtr
) -
504 reinterpret_cast<const char *>(SymbolTblPtr
)) /
505 XCOFF::SymbolTableEntrySize
;
509 XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index
) const {
511 report_fatal_error("64-bit symbol table support not implemented yet.");
513 if (Index
>= getLogicalNumberOfSymbolTableEntries32())
514 return errorCodeToError(object_error::invalid_symbol_index
);
517 SymDRI
.p
= reinterpret_cast<uintptr_t>(getPointerToSymbolTable() + Index
);
518 return getSymbolName(SymDRI
);
521 uint16_t XCOFFObjectFile::getFlags() const {
522 return is64Bit() ? fileHeader64()->Flags
: fileHeader32()->Flags
;
525 const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec
) const {
526 return is64Bit() ? toSection64(Sec
)->Name
: toSection32(Sec
)->Name
;
529 uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
530 return reinterpret_cast<uintptr_t>(SectionHeaderTable
);
533 int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec
) const {
534 return is64Bit() ? toSection64(Sec
)->Flags
: toSection32(Sec
)->Flags
;
537 XCOFFObjectFile::XCOFFObjectFile(unsigned int Type
, MemoryBufferRef Object
)
538 : ObjectFile(Type
, Object
) {
539 assert(Type
== Binary::ID_XCOFF32
|| Type
== Binary::ID_XCOFF64
);
542 ArrayRef
<XCOFFSectionHeader64
> XCOFFObjectFile::sections64() const {
543 assert(is64Bit() && "64-bit interface called for non 64-bit file.");
544 const XCOFFSectionHeader64
*TablePtr
= sectionHeaderTable64();
545 return ArrayRef
<XCOFFSectionHeader64
>(TablePtr
,
546 TablePtr
+ getNumberOfSections());
549 ArrayRef
<XCOFFSectionHeader32
> XCOFFObjectFile::sections32() const {
550 assert(!is64Bit() && "32-bit interface called for non 32-bit file.");
551 const XCOFFSectionHeader32
*TablePtr
= sectionHeaderTable32();
552 return ArrayRef
<XCOFFSectionHeader32
>(TablePtr
,
553 TablePtr
+ getNumberOfSections());
556 // In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO
557 // section header contains the actual count of relocation entries in the s_paddr
558 // field. STYP_OVRFLO headers contain the section index of their corresponding
559 // sections as their raw "NumberOfRelocations" field value.
560 Expected
<uint32_t> XCOFFObjectFile::getLogicalNumberOfRelocationEntries(
561 const XCOFFSectionHeader32
&Sec
) const {
563 uint16_t SectionIndex
= &Sec
- sectionHeaderTable32() + 1;
565 if (Sec
.NumberOfRelocations
< RELOC_OVERFLOW
)
566 return Sec
.NumberOfRelocations
;
567 for (const auto &Sec
: sections32()) {
568 if (Sec
.Flags
== XCOFF::STYP_OVRFLO
&&
569 Sec
.NumberOfRelocations
== SectionIndex
)
570 return Sec
.PhysicalAddress
;
572 return errorCodeToError(object_error::parse_failed
);
575 Expected
<ArrayRef
<XCOFFRelocation32
>>
576 XCOFFObjectFile::relocations(const XCOFFSectionHeader32
&Sec
) const {
577 uintptr_t RelocAddr
= getWithOffset(reinterpret_cast<uintptr_t>(FileHeader
),
578 Sec
.FileOffsetToRelocationInfo
);
579 auto NumRelocEntriesOrErr
= getLogicalNumberOfRelocationEntries(Sec
);
580 if (Error E
= NumRelocEntriesOrErr
.takeError())
583 uint32_t NumRelocEntries
= NumRelocEntriesOrErr
.get();
585 auto RelocationOrErr
=
586 getObject
<XCOFFRelocation32
>(Data
, reinterpret_cast<void *>(RelocAddr
),
587 NumRelocEntries
* sizeof(XCOFFRelocation32
));
588 if (Error E
= RelocationOrErr
.takeError())
591 const XCOFFRelocation32
*StartReloc
= RelocationOrErr
.get();
593 return ArrayRef
<XCOFFRelocation32
>(StartReloc
, StartReloc
+ NumRelocEntries
);
596 Expected
<XCOFFStringTable
>
597 XCOFFObjectFile::parseStringTable(const XCOFFObjectFile
*Obj
, uint64_t Offset
) {
598 // If there is a string table, then the buffer must contain at least 4 bytes
599 // for the string table's size. Not having a string table is not an error.
600 if (auto EC
= Binary::checkOffset(
601 Obj
->Data
, reinterpret_cast<uintptr_t>(Obj
->base() + Offset
), 4))
602 return XCOFFStringTable
{0, nullptr};
604 // Read the size out of the buffer.
605 uint32_t Size
= support::endian::read32be(Obj
->base() + Offset
);
607 // If the size is less then 4, then the string table is just a size and no
610 return XCOFFStringTable
{4, nullptr};
612 auto StringTableOrErr
=
613 getObject
<char>(Obj
->Data
, Obj
->base() + Offset
, Size
);
614 if (Error E
= StringTableOrErr
.takeError())
617 const char *StringTablePtr
= StringTableOrErr
.get();
618 if (StringTablePtr
[Size
- 1] != '\0')
619 return errorCodeToError(object_error::string_table_non_null_end
);
621 return XCOFFStringTable
{Size
, StringTablePtr
};
624 Expected
<std::unique_ptr
<XCOFFObjectFile
>>
625 XCOFFObjectFile::create(unsigned Type
, MemoryBufferRef MBR
) {
626 // Can't use std::make_unique because of the private constructor.
627 std::unique_ptr
<XCOFFObjectFile
> Obj
;
628 Obj
.reset(new XCOFFObjectFile(Type
, MBR
));
630 uint64_t CurOffset
= 0;
631 const auto *Base
= Obj
->base();
632 MemoryBufferRef Data
= Obj
->Data
;
634 // Parse file header.
635 auto FileHeaderOrErr
=
636 getObject
<void>(Data
, Base
+ CurOffset
, Obj
->getFileHeaderSize());
637 if (Error E
= FileHeaderOrErr
.takeError())
639 Obj
->FileHeader
= FileHeaderOrErr
.get();
641 CurOffset
+= Obj
->getFileHeaderSize();
642 // TODO FIXME we don't have support for an optional header yet, so just skip
644 CurOffset
+= Obj
->getOptionalHeaderSize();
646 // Parse the section header table if it is present.
647 if (Obj
->getNumberOfSections()) {
648 auto SecHeadersOrErr
= getObject
<void>(Data
, Base
+ CurOffset
,
649 Obj
->getNumberOfSections() *
650 Obj
->getSectionHeaderSize());
651 if (Error E
= SecHeadersOrErr
.takeError())
653 Obj
->SectionHeaderTable
= SecHeadersOrErr
.get();
656 // 64-bit object supports only file header and section headers for now.
658 return std::move(Obj
);
660 // If there is no symbol table we are done parsing the memory buffer.
661 if (Obj
->getLogicalNumberOfSymbolTableEntries32() == 0)
662 return std::move(Obj
);
664 // Parse symbol table.
665 CurOffset
= Obj
->fileHeader32()->SymbolTableOffset
;
666 uint64_t SymbolTableSize
= (uint64_t)(sizeof(XCOFFSymbolEntry
)) *
667 Obj
->getLogicalNumberOfSymbolTableEntries32();
669 getObject
<XCOFFSymbolEntry
>(Data
, Base
+ CurOffset
, SymbolTableSize
);
670 if (Error E
= SymTableOrErr
.takeError())
672 Obj
->SymbolTblPtr
= SymTableOrErr
.get();
673 CurOffset
+= SymbolTableSize
;
675 // Parse String table.
676 Expected
<XCOFFStringTable
> StringTableOrErr
=
677 parseStringTable(Obj
.get(), CurOffset
);
678 if (Error E
= StringTableOrErr
.takeError())
680 Obj
->StringTable
= StringTableOrErr
.get();
682 return std::move(Obj
);
685 Expected
<std::unique_ptr
<ObjectFile
>>
686 ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef
,
688 return XCOFFObjectFile::create(FileType
, MemBufRef
);
691 StringRef
XCOFFSectionHeader32::getName() const {
692 return generateXCOFFFixedNameStringRef(Name
);
695 StringRef
XCOFFSectionHeader64::getName() const {
696 return generateXCOFFFixedNameStringRef(Name
);
699 XCOFF::StorageClass
XCOFFSymbolRef::getStorageClass() const {
700 return OwningObjectPtr
->toSymbolEntry(SymEntDataRef
)->StorageClass
;
703 uint8_t XCOFFSymbolRef::getNumberOfAuxEntries() const {
704 return OwningObjectPtr
->toSymbolEntry(SymEntDataRef
)->NumberOfAuxEntries
;
707 const XCOFFCsectAuxEnt32
*XCOFFSymbolRef::getXCOFFCsectAuxEnt32() const {
708 assert(!OwningObjectPtr
->is64Bit() &&
709 "32-bit interface called on 64-bit object file.");
710 assert(hasCsectAuxEnt() && "No Csect Auxiliary Entry is found.");
712 // In XCOFF32, the csect auxilliary entry is always the last auxiliary
713 // entry for the symbol.
714 uintptr_t AuxAddr
= getWithOffset(
715 SymEntDataRef
.p
, XCOFF::SymbolTableEntrySize
* getNumberOfAuxEntries());
718 OwningObjectPtr
->checkSymbolEntryPointer(AuxAddr
);
721 return reinterpret_cast<const XCOFFCsectAuxEnt32
*>(AuxAddr
);
724 uint16_t XCOFFSymbolRef::getType() const {
725 return OwningObjectPtr
->toSymbolEntry(SymEntDataRef
)->SymbolType
;
728 int16_t XCOFFSymbolRef::getSectionNumber() const {
729 return OwningObjectPtr
->toSymbolEntry(SymEntDataRef
)->SectionNumber
;
732 bool XCOFFSymbolRef::hasCsectAuxEnt() const {
733 XCOFF::StorageClass SC
= getStorageClass();
734 return (SC
== XCOFF::C_EXT
|| SC
== XCOFF::C_WEAKEXT
||
735 SC
== XCOFF::C_HIDEXT
);
738 bool XCOFFSymbolRef::isFunction() const {
739 if (OwningObjectPtr
->is64Bit())
740 report_fatal_error("64-bit support is unimplemented yet.");
742 if (getType() & FUNCTION_SYM
)
745 if (!hasCsectAuxEnt())
748 const XCOFFCsectAuxEnt32
*CsectAuxEnt
= getXCOFFCsectAuxEnt32();
750 // A function definition should be a label definition.
751 if ((CsectAuxEnt
->SymbolAlignmentAndType
& SYM_TYPE_MASK
) != XCOFF::XTY_LD
)
754 if (CsectAuxEnt
->StorageMappingClass
!= XCOFF::XMC_PR
)
757 int16_t SectNum
= getSectionNumber();
758 Expected
<DataRefImpl
> SI
= OwningObjectPtr
->getSectionByNum(SectNum
);
762 return (OwningObjectPtr
->getSectionFlags(SI
.get()) & XCOFF::STYP_TEXT
);
765 } // namespace object