[x86] fix assert with horizontal math + broadcast of vector (PR43402)
[llvm-core.git] / lib / Object / XCOFFObjectFile.cpp
blob7bd0dd68b915185f3c8fe0f67a228d9fbb10169a
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.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Object/XCOFFObjectFile.h"
14 #include <cstddef>
15 #include <cstring>
17 namespace llvm {
18 namespace object {
20 enum {
21 FUNCTION_SYM = 0x20,
22 SYM_TYPE_MASK = 0x07
25 // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
26 // 'M'. Returns a pointer to the underlying object on success.
27 template <typename T>
28 static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr,
29 const uint64_t Size = sizeof(T)) {
30 uintptr_t Addr = uintptr_t(Ptr);
31 if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
32 return errorCodeToError(EC);
33 return reinterpret_cast<const T *>(Addr);
36 static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) {
37 return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) +
38 Offset);
41 template <typename T> static const T *viewAs(uintptr_t in) {
42 return reinterpret_cast<const T *>(in);
45 static StringRef generateXCOFFFixedNameStringRef(const char *Name) {
46 auto NulCharPtr =
47 static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize));
48 return NulCharPtr ? StringRef(Name, NulCharPtr - Name)
49 : StringRef(Name, XCOFF::NameSize);
52 void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
53 uintptr_t TableAddress) const {
54 if (Addr < TableAddress)
55 report_fatal_error("Section header outside of section header table.");
57 uintptr_t Offset = Addr - TableAddress;
58 if (Offset >= getSectionHeaderSize() * getNumberOfSections())
59 report_fatal_error("Section header outside of section header table.");
61 if (Offset % getSectionHeaderSize() != 0)
62 report_fatal_error(
63 "Section header pointer does not point to a valid section header.");
66 const XCOFFSectionHeader32 *
67 XCOFFObjectFile::toSection32(DataRefImpl Ref) const {
68 assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
69 #ifndef NDEBUG
70 checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
71 #endif
72 return viewAs<XCOFFSectionHeader32>(Ref.p);
75 const XCOFFSectionHeader64 *
76 XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
77 assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
78 #ifndef NDEBUG
79 checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
80 #endif
81 return viewAs<XCOFFSectionHeader64>(Ref.p);
84 const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const {
85 assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
86 assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!");
87 #ifndef NDEBUG
88 checkSymbolEntryPointer(Ref.p);
89 #endif
90 auto SymEntPtr = viewAs<XCOFFSymbolEntry>(Ref.p);
91 return SymEntPtr;
94 const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
95 assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
96 return static_cast<const XCOFFFileHeader32 *>(FileHeader);
99 const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
100 assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
101 return static_cast<const XCOFFFileHeader64 *>(FileHeader);
104 const XCOFFSectionHeader32 *
105 XCOFFObjectFile::sectionHeaderTable32() const {
106 assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
107 return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
110 const XCOFFSectionHeader64 *
111 XCOFFObjectFile::sectionHeaderTable64() const {
112 assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
113 return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
116 void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
117 const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
118 SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1;
119 #ifndef NDEBUG
120 // This function is used by basic_symbol_iterator, which allows to
121 // point to the end-of-symbol-table address.
122 if (reinterpret_cast<uintptr_t>(SymEntPtr) != getEndOfSymbolTableAddress())
123 checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(SymEntPtr));
124 #endif
125 Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr);
128 Expected<StringRef>
129 XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const {
130 // The byte offset is relative to the start of the string table.
131 // A byte offset value of 0 is a null or zero-length symbol
132 // name. A byte offset in the range 1 to 3 (inclusive) points into the length
133 // field; as a soft-error recovery mechanism, we treat such cases as having an
134 // offset of 0.
135 if (Offset < 4)
136 return StringRef(nullptr, 0);
138 if (StringTable.Data != nullptr && StringTable.Size > Offset)
139 return (StringTable.Data + Offset);
141 return make_error<GenericBinaryError>("Bad offset for string table entry",
142 object_error::parse_failed);
145 Expected<StringRef>
146 XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const {
147 if (CFileEntPtr->NameInStrTbl.Magic !=
148 XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
149 return generateXCOFFFixedNameStringRef(CFileEntPtr->Name);
150 return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset);
153 Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
154 const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
156 // A storage class value with the high-order bit on indicates that the name is
157 // a symbolic debugger stabstring.
158 if (SymEntPtr->StorageClass & 0x80)
159 return StringRef("Unimplemented Debug Name");
161 if (SymEntPtr->NameInStrTbl.Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
162 return generateXCOFFFixedNameStringRef(SymEntPtr->SymbolName);
164 return getStringTableEntry(SymEntPtr->NameInStrTbl.Offset);
167 Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
168 uint64_t Result = 0;
169 llvm_unreachable("Not yet implemented!");
170 return Result;
173 uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
174 assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
175 return toSymbolEntry(Symb)->Value;
178 uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
179 uint64_t Result = 0;
180 llvm_unreachable("Not yet implemented!");
181 return Result;
184 Expected<SymbolRef::Type>
185 XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
186 llvm_unreachable("Not yet implemented!");
187 return SymbolRef::ST_Other;
190 Expected<section_iterator>
191 XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
192 const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
193 int16_t SectNum = SymEntPtr->SectionNumber;
195 if (isReservedSectionNumber(SectNum))
196 return section_end();
198 Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum);
199 if (!ExpSec)
200 return ExpSec.takeError();
202 return section_iterator(SectionRef(ExpSec.get(), this));
205 void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
206 const char *Ptr = reinterpret_cast<const char *>(Sec.p);
207 Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize());
210 Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
211 return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec));
214 uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
215 // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
216 // with MSVC.
217 if (is64Bit())
218 return toSection64(Sec)->VirtualAddress;
220 return toSection32(Sec)->VirtualAddress;
223 uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
224 // Section numbers in XCOFF are numbered beginning at 1. A section number of
225 // zero is used to indicate that a symbol is being imported or is undefined.
226 if (is64Bit())
227 return toSection64(Sec) - sectionHeaderTable64() + 1;
228 else
229 return toSection32(Sec) - sectionHeaderTable32() + 1;
232 uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
233 // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
234 // with MSVC.
235 if (is64Bit())
236 return toSection64(Sec)->SectionSize;
238 return toSection32(Sec)->SectionSize;
241 Expected<ArrayRef<uint8_t>>
242 XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
243 llvm_unreachable("Not yet implemented!");
246 uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
247 uint64_t Result = 0;
248 llvm_unreachable("Not yet implemented!");
249 return Result;
252 bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
253 bool Result = false;
254 llvm_unreachable("Not yet implemented!");
255 return Result;
258 bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
259 return getSectionFlags(Sec) & XCOFF::STYP_TEXT;
262 bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
263 uint32_t Flags = getSectionFlags(Sec);
264 return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
267 bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
268 uint32_t Flags = getSectionFlags(Sec);
269 return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
272 bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
273 bool Result = false;
274 llvm_unreachable("Not yet implemented!");
275 return Result;
278 relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
279 llvm_unreachable("Not yet implemented!");
280 return relocation_iterator(RelocationRef());
283 relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const {
284 llvm_unreachable("Not yet implemented!");
285 return relocation_iterator(RelocationRef());
288 void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
289 llvm_unreachable("Not yet implemented!");
290 return;
293 uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
294 llvm_unreachable("Not yet implemented!");
295 uint64_t Result = 0;
296 return Result;
299 symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
300 llvm_unreachable("Not yet implemented!");
301 return symbol_iterator(SymbolRef());
304 uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const {
305 llvm_unreachable("Not yet implemented!");
306 uint64_t Result = 0;
307 return Result;
310 void XCOFFObjectFile::getRelocationTypeName(
311 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
312 llvm_unreachable("Not yet implemented!");
313 return;
316 uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
317 uint32_t Result = 0;
318 llvm_unreachable("Not yet implemented!");
319 return Result;
322 basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
323 assert(!is64Bit() && "64-bit support not implemented yet.");
324 DataRefImpl SymDRI;
325 SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
326 return basic_symbol_iterator(SymbolRef(SymDRI, this));
329 basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
330 assert(!is64Bit() && "64-bit support not implemented yet.");
331 DataRefImpl SymDRI;
332 SymDRI.p = reinterpret_cast<uintptr_t>(
333 SymbolTblPtr + getLogicalNumberOfSymbolTableEntries32());
334 return basic_symbol_iterator(SymbolRef(SymDRI, this));
337 section_iterator XCOFFObjectFile::section_begin() const {
338 DataRefImpl DRI;
339 DRI.p = getSectionHeaderTableAddress();
340 return section_iterator(SectionRef(DRI, this));
343 section_iterator XCOFFObjectFile::section_end() const {
344 DataRefImpl DRI;
345 DRI.p = getWithOffset(getSectionHeaderTableAddress(),
346 getNumberOfSections() * getSectionHeaderSize());
347 return section_iterator(SectionRef(DRI, this));
350 uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; }
352 StringRef XCOFFObjectFile::getFileFormatName() const {
353 return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000";
356 Triple::ArchType XCOFFObjectFile::getArch() const {
357 return is64Bit() ? Triple::ppc64 : Triple::ppc;
360 SubtargetFeatures XCOFFObjectFile::getFeatures() const {
361 llvm_unreachable("Not yet implemented!");
362 return SubtargetFeatures();
365 bool XCOFFObjectFile::isRelocatableObject() const {
366 bool Result = false;
367 llvm_unreachable("Not yet implemented!");
368 return Result;
371 Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
372 // TODO FIXME Should get from auxiliary_header->o_entry when support for the
373 // auxiliary_header is added.
374 return 0;
377 size_t XCOFFObjectFile::getFileHeaderSize() const {
378 return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32);
381 size_t XCOFFObjectFile::getSectionHeaderSize() const {
382 return is64Bit() ? sizeof(XCOFFSectionHeader64) :
383 sizeof(XCOFFSectionHeader32);
386 bool XCOFFObjectFile::is64Bit() const {
387 return Binary::ID_XCOFF64 == getType();
390 uint16_t XCOFFObjectFile::getMagic() const {
391 return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic;
394 Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
395 if (Num <= 0 || Num > getNumberOfSections())
396 return errorCodeToError(object_error::invalid_section_index);
398 DataRefImpl DRI;
399 DRI.p = getWithOffset(getSectionHeaderTableAddress(),
400 getSectionHeaderSize() * (Num - 1));
401 return DRI;
404 Expected<StringRef>
405 XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const {
406 assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
407 int16_t SectionNum = SymEntPtr->SectionNumber;
409 switch (SectionNum) {
410 case XCOFF::N_DEBUG:
411 return "N_DEBUG";
412 case XCOFF::N_ABS:
413 return "N_ABS";
414 case XCOFF::N_UNDEF:
415 return "N_UNDEF";
416 default:
417 Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
418 if (SecRef)
419 return generateXCOFFFixedNameStringRef(
420 getSectionNameInternal(SecRef.get()));
421 return SecRef.takeError();
425 bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) {
426 return (SectionNumber <= 0 && SectionNumber >= -2);
429 uint16_t XCOFFObjectFile::getNumberOfSections() const {
430 return is64Bit() ? fileHeader64()->NumberOfSections
431 : fileHeader32()->NumberOfSections;
434 int32_t XCOFFObjectFile::getTimeStamp() const {
435 return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp;
438 uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
439 return is64Bit() ? fileHeader64()->AuxHeaderSize
440 : fileHeader32()->AuxHeaderSize;
443 uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
444 return fileHeader32()->SymbolTableOffset;
447 int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const {
448 // As far as symbol table size is concerned, if this field is negative it is
449 // to be treated as a 0. However since this field is also used for printing we
450 // don't want to truncate any negative values.
451 return fileHeader32()->NumberOfSymTableEntries;
454 uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
455 return (fileHeader32()->NumberOfSymTableEntries >= 0
456 ? fileHeader32()->NumberOfSymTableEntries
457 : 0);
460 uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
461 return fileHeader64()->SymbolTableOffset;
464 uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
465 return fileHeader64()->NumberOfSymTableEntries;
468 uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const {
469 uint32_t NumberOfSymTableEntries =
470 is64Bit() ? getNumberOfSymbolTableEntries64()
471 : getLogicalNumberOfSymbolTableEntries32();
472 return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr),
473 XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries);
476 void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const {
477 if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr))
478 report_fatal_error("Symbol table entry is outside of symbol table.");
480 if (SymbolEntPtr >= getEndOfSymbolTableAddress())
481 report_fatal_error("Symbol table entry is outside of symbol table.");
483 ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) -
484 reinterpret_cast<const char *>(SymbolTblPtr);
486 if (Offset % XCOFF::SymbolTableEntrySize != 0)
487 report_fatal_error(
488 "Symbol table entry position is not valid inside of symbol table.");
491 uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const {
492 return (reinterpret_cast<const char *>(SymbolEntPtr) -
493 reinterpret_cast<const char *>(SymbolTblPtr)) /
494 XCOFF::SymbolTableEntrySize;
497 uint16_t XCOFFObjectFile::getFlags() const {
498 return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
501 const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const {
502 return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name;
505 uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
506 return reinterpret_cast<uintptr_t>(SectionHeaderTable);
509 int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const {
510 return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags;
513 XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object)
514 : ObjectFile(Type, Object) {
515 assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64);
518 ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const {
519 assert(is64Bit() && "64-bit interface called for non 64-bit file.");
520 const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64();
521 return ArrayRef<XCOFFSectionHeader64>(TablePtr,
522 TablePtr + getNumberOfSections());
525 ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const {
526 assert(!is64Bit() && "32-bit interface called for non 32-bit file.");
527 const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32();
528 return ArrayRef<XCOFFSectionHeader32>(TablePtr,
529 TablePtr + getNumberOfSections());
532 Expected<XCOFFStringTable>
533 XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
534 // If there is a string table, then the buffer must contain at least 4 bytes
535 // for the string table's size. Not having a string table is not an error.
536 if (auto EC = Binary::checkOffset(
537 Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4))
538 return XCOFFStringTable{0, nullptr};
540 // Read the size out of the buffer.
541 uint32_t Size = support::endian::read32be(Obj->base() + Offset);
543 // If the size is less then 4, then the string table is just a size and no
544 // string data.
545 if (Size <= 4)
546 return XCOFFStringTable{4, nullptr};
548 auto StringTableOrErr =
549 getObject<char>(Obj->Data, Obj->base() + Offset, Size);
550 if (Error E = StringTableOrErr.takeError())
551 return std::move(E);
553 const char *StringTablePtr = StringTableOrErr.get();
554 if (StringTablePtr[Size - 1] != '\0')
555 return errorCodeToError(object_error::string_table_non_null_end);
557 return XCOFFStringTable{Size, StringTablePtr};
560 Expected<std::unique_ptr<XCOFFObjectFile>>
561 XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
562 // Can't use std::make_unique because of the private constructor.
563 std::unique_ptr<XCOFFObjectFile> Obj;
564 Obj.reset(new XCOFFObjectFile(Type, MBR));
566 uint64_t CurOffset = 0;
567 const auto *Base = Obj->base();
568 MemoryBufferRef Data = Obj->Data;
570 // Parse file header.
571 auto FileHeaderOrErr =
572 getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize());
573 if (Error E = FileHeaderOrErr.takeError())
574 return std::move(E);
575 Obj->FileHeader = FileHeaderOrErr.get();
577 CurOffset += Obj->getFileHeaderSize();
578 // TODO FIXME we don't have support for an optional header yet, so just skip
579 // past it.
580 CurOffset += Obj->getOptionalHeaderSize();
582 // Parse the section header table if it is present.
583 if (Obj->getNumberOfSections()) {
584 auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset,
585 Obj->getNumberOfSections() *
586 Obj->getSectionHeaderSize());
587 if (Error E = SecHeadersOrErr.takeError())
588 return std::move(E);
589 Obj->SectionHeaderTable = SecHeadersOrErr.get();
592 // 64-bit object supports only file header and section headers for now.
593 if (Obj->is64Bit())
594 return std::move(Obj);
596 // If there is no symbol table we are done parsing the memory buffer.
597 if (Obj->getLogicalNumberOfSymbolTableEntries32() == 0)
598 return std::move(Obj);
600 // Parse symbol table.
601 CurOffset = Obj->fileHeader32()->SymbolTableOffset;
602 uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) *
603 Obj->getLogicalNumberOfSymbolTableEntries32();
604 auto SymTableOrErr =
605 getObject<XCOFFSymbolEntry>(Data, Base + CurOffset, SymbolTableSize);
606 if (Error E = SymTableOrErr.takeError())
607 return std::move(E);
608 Obj->SymbolTblPtr = SymTableOrErr.get();
609 CurOffset += SymbolTableSize;
611 // Parse String table.
612 Expected<XCOFFStringTable> StringTableOrErr =
613 parseStringTable(Obj.get(), CurOffset);
614 if (Error E = StringTableOrErr.takeError())
615 return std::move(E);
616 Obj->StringTable = StringTableOrErr.get();
618 return std::move(Obj);
621 Expected<std::unique_ptr<ObjectFile>>
622 ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
623 unsigned FileType) {
624 return XCOFFObjectFile::create(FileType, MemBufRef);
627 StringRef XCOFFSectionHeader32::getName() const {
628 return generateXCOFFFixedNameStringRef(Name);
631 StringRef XCOFFSectionHeader64::getName() const {
632 return generateXCOFFFixedNameStringRef(Name);
635 XCOFF::StorageClass XCOFFSymbolRef::getStorageClass() const {
636 return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->StorageClass;
639 uint8_t XCOFFSymbolRef::getNumberOfAuxEntries() const {
640 return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->NumberOfAuxEntries;
643 const XCOFFCsectAuxEnt32 *XCOFFSymbolRef::getXCOFFCsectAuxEnt32() const {
644 assert(!OwningObjectPtr->is64Bit() &&
645 "32-bit interface called on 64-bit object file.");
646 assert(hasCsectAuxEnt() && "No Csect Auxiliary Entry is found.");
648 // In XCOFF32, the csect auxilliary entry is always the last auxiliary
649 // entry for the symbol.
650 uintptr_t AuxAddr = getWithOffset(
651 SymEntDataRef.p, XCOFF::SymbolTableEntrySize * getNumberOfAuxEntries());
653 #ifndef NDEBUG
654 OwningObjectPtr->checkSymbolEntryPointer(AuxAddr);
655 #endif
657 return reinterpret_cast<const XCOFFCsectAuxEnt32 *>(AuxAddr);
660 uint16_t XCOFFSymbolRef::getType() const {
661 return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SymbolType;
664 int16_t XCOFFSymbolRef::getSectionNumber() const {
665 return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SectionNumber;
668 bool XCOFFSymbolRef::hasCsectAuxEnt() const {
669 XCOFF::StorageClass SC = getStorageClass();
670 return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT ||
671 SC == XCOFF::C_HIDEXT);
674 bool XCOFFSymbolRef::isFunction() const {
675 if (OwningObjectPtr->is64Bit())
676 report_fatal_error("64-bit support is unimplemented yet.");
678 if (getType() & FUNCTION_SYM)
679 return true;
681 if (!hasCsectAuxEnt())
682 return false;
684 const XCOFFCsectAuxEnt32 *CsectAuxEnt = getXCOFFCsectAuxEnt32();
686 // A function definition should be a label definition.
687 if ((CsectAuxEnt->SymbolAlignmentAndType & SYM_TYPE_MASK) != XCOFF::XTY_LD)
688 return false;
690 if (CsectAuxEnt->StorageMappingClass != XCOFF::XMC_PR)
691 return false;
693 int16_t SectNum = getSectionNumber();
694 Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum);
695 if (!SI)
696 return false;
698 return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT);
701 } // namespace object
702 } // namespace llvm