[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / lib / Object / XCOFFObjectFile.cpp
blob98782c2701c1afc0e1d4f64c961d88038942a67b
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 { 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.
24 template <typename T>
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) +
35 Offset);
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) {
43 auto NulCharPtr =
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)
73 report_fatal_error(
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.");
80 #ifndef NDEBUG
81 checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
82 #endif
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.");
89 #ifndef NDEBUG
90 checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
91 #endif
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!");
98 #ifndef NDEBUG
99 checkSymbolEntryPointer(Ref.p);
100 #endif
101 auto SymEntPtr = viewAs<XCOFFSymbolEntry>(Ref.p);
102 return SymEntPtr;
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;
130 #ifndef NDEBUG
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));
135 #endif
136 Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr);
139 Expected<StringRef>
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
145 // offset of 0.
146 if (Offset < 4)
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);
156 Expected<StringRef>
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 {
179 uint64_t Result = 0;
180 llvm_unreachable("Not yet implemented!");
181 return Result;
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 {
190 uint64_t Result = 0;
191 llvm_unreachable("Not yet implemented!");
192 return Result;
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);
210 if (!ExpSec)
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
227 // with MSVC.
228 if (is64Bit())
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.
237 if (is64Bit())
238 return toSection64(Sec) - sectionHeaderTable64() + 1;
239 else
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
245 // with MSVC.
246 if (is64Bit())
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 {
258 uint64_t Result = 0;
259 llvm_unreachable("Not yet implemented!");
260 return Result;
263 bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
264 bool Result = false;
265 llvm_unreachable("Not yet implemented!");
266 return Result;
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 {
284 bool Result = false;
285 llvm_unreachable("Not yet implemented!");
286 return Result;
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!");
301 return;
304 uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
305 llvm_unreachable("Not yet implemented!");
306 uint64_t Result = 0;
307 return Result;
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!");
317 uint64_t Result = 0;
318 return Result;
321 void XCOFFObjectFile::getRelocationTypeName(
322 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
323 llvm_unreachable("Not yet implemented!");
324 return;
327 uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
328 uint32_t Result = 0;
329 llvm_unreachable("Not yet implemented!");
330 return Result;
333 basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
334 assert(!is64Bit() && "64-bit support not implemented yet.");
335 DataRefImpl SymDRI;
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.");
342 DataRefImpl SymDRI;
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 {
349 DataRefImpl DRI;
350 DRI.p = getSectionHeaderTableAddress();
351 return section_iterator(SectionRef(DRI, this));
354 section_iterator XCOFFObjectFile::section_end() const {
355 DataRefImpl DRI;
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 {
377 bool Result = false;
378 llvm_unreachable("Not yet implemented!");
379 return Result;
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.
385 return 0;
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);
409 DataRefImpl DRI;
410 DRI.p = getWithOffset(getSectionHeaderTableAddress(),
411 getSectionHeaderSize() * (Num - 1));
412 return DRI;
415 Expected<StringRef>
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) {
421 case XCOFF::N_DEBUG:
422 return "N_DEBUG";
423 case XCOFF::N_ABS:
424 return "N_ABS";
425 case XCOFF::N_UNDEF:
426 return "N_UNDEF";
427 default:
428 Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
429 if (SecRef)
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
468 : 0);
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)
498 report_fatal_error(
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;
508 Expected<StringRef>
509 XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const {
510 if (is64Bit())
511 report_fatal_error("64-bit symbol table support not implemented yet.");
513 if (Index >= getLogicalNumberOfSymbolTableEntries32())
514 return errorCodeToError(object_error::invalid_symbol_index);
516 DataRefImpl SymDRI;
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())
581 return std::move(E);
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())
589 return std::move(E);
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
608 // string data.
609 if (Size <= 4)
610 return XCOFFStringTable{4, nullptr};
612 auto StringTableOrErr =
613 getObject<char>(Obj->Data, Obj->base() + Offset, Size);
614 if (Error E = StringTableOrErr.takeError())
615 return std::move(E);
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())
638 return std::move(E);
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
643 // past it.
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())
652 return std::move(E);
653 Obj->SectionHeaderTable = SecHeadersOrErr.get();
656 // 64-bit object supports only file header and section headers for now.
657 if (Obj->is64Bit())
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();
668 auto SymTableOrErr =
669 getObject<XCOFFSymbolEntry>(Data, Base + CurOffset, SymbolTableSize);
670 if (Error E = SymTableOrErr.takeError())
671 return std::move(E);
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())
679 return std::move(E);
680 Obj->StringTable = StringTableOrErr.get();
682 return std::move(Obj);
685 Expected<std::unique_ptr<ObjectFile>>
686 ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
687 unsigned FileType) {
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());
717 #ifndef NDEBUG
718 OwningObjectPtr->checkSymbolEntryPointer(AuxAddr);
719 #endif
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)
743 return true;
745 if (!hasCsectAuxEnt())
746 return false;
748 const XCOFFCsectAuxEnt32 *CsectAuxEnt = getXCOFFCsectAuxEnt32();
750 // A function definition should be a label definition.
751 if ((CsectAuxEnt->SymbolAlignmentAndType & SYM_TYPE_MASK) != XCOFF::XTY_LD)
752 return false;
754 if (CsectAuxEnt->StorageMappingClass != XCOFF::XMC_PR)
755 return false;
757 int16_t SectNum = getSectionNumber();
758 Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum);
759 if (!SI)
760 return false;
762 return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT);
765 } // namespace object
766 } // namespace llvm