xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/Object/XCOFFObjectFile.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
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 "llvm/ADT/StringSwitch.h"
15 #include "llvm/MC/SubtargetFeature.h"
16 #include "llvm/Support/DataExtractor.h"
17 #include <cstddef>
18 #include <cstring>
19 
20 namespace llvm {
21 
22 using namespace XCOFF;
23 
24 namespace object {
25 
26 static const uint8_t FunctionSym = 0x20;
27 static const uint8_t SymTypeMask = 0x07;
28 static const uint16_t NoRelMask = 0x0001;
29 
30 // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
31 // 'M'. Returns a pointer to the underlying object on success.
32 template <typename T>
getObject(MemoryBufferRef M,const void * Ptr,const uint64_t Size=sizeof (T))33 static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr,
34                                      const uint64_t Size = sizeof(T)) {
35   uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr);
36   if (Error E = Binary::checkOffset(M, Addr, Size))
37     return std::move(E);
38   return reinterpret_cast<const T *>(Addr);
39 }
40 
getWithOffset(uintptr_t Base,ptrdiff_t Offset)41 static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) {
42   return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) +
43                                      Offset);
44 }
45 
viewAs(uintptr_t in)46 template <typename T> static const T *viewAs(uintptr_t in) {
47   return reinterpret_cast<const T *>(in);
48 }
49 
generateXCOFFFixedNameStringRef(const char * Name)50 static StringRef generateXCOFFFixedNameStringRef(const char *Name) {
51   auto NulCharPtr =
52       static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize));
53   return NulCharPtr ? StringRef(Name, NulCharPtr - Name)
54                     : StringRef(Name, XCOFF::NameSize);
55 }
56 
getName() const57 template <typename T> StringRef XCOFFSectionHeader<T>::getName() const {
58   const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
59   return generateXCOFFFixedNameStringRef(DerivedXCOFFSectionHeader.Name);
60 }
61 
getSectionType() const62 template <typename T> uint16_t XCOFFSectionHeader<T>::getSectionType() const {
63   const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
64   return DerivedXCOFFSectionHeader.Flags & SectionFlagsTypeMask;
65 }
66 
67 template <typename T>
isReservedSectionType() const68 bool XCOFFSectionHeader<T>::isReservedSectionType() const {
69   return getSectionType() & SectionFlagsReservedMask;
70 }
71 
isRelocationSigned() const72 bool XCOFFRelocation32::isRelocationSigned() const {
73   return Info & XR_SIGN_INDICATOR_MASK;
74 }
75 
isFixupIndicated() const76 bool XCOFFRelocation32::isFixupIndicated() const {
77   return Info & XR_FIXUP_INDICATOR_MASK;
78 }
79 
getRelocatedLength() const80 uint8_t XCOFFRelocation32::getRelocatedLength() const {
81   // The relocation encodes the bit length being relocated minus 1. Add back
82   // the 1 to get the actual length being relocated.
83   return (Info & XR_BIASED_LENGTH_MASK) + 1;
84 }
85 
checkSectionAddress(uintptr_t Addr,uintptr_t TableAddress) const86 void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
87                                           uintptr_t TableAddress) const {
88   if (Addr < TableAddress)
89     report_fatal_error("Section header outside of section header table.");
90 
91   uintptr_t Offset = Addr - TableAddress;
92   if (Offset >= getSectionHeaderSize() * getNumberOfSections())
93     report_fatal_error("Section header outside of section header table.");
94 
95   if (Offset % getSectionHeaderSize() != 0)
96     report_fatal_error(
97         "Section header pointer does not point to a valid section header.");
98 }
99 
100 const XCOFFSectionHeader32 *
toSection32(DataRefImpl Ref) const101 XCOFFObjectFile::toSection32(DataRefImpl Ref) const {
102   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
103 #ifndef NDEBUG
104   checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
105 #endif
106   return viewAs<XCOFFSectionHeader32>(Ref.p);
107 }
108 
109 const XCOFFSectionHeader64 *
toSection64(DataRefImpl Ref) const110 XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
111   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
112 #ifndef NDEBUG
113   checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
114 #endif
115   return viewAs<XCOFFSectionHeader64>(Ref.p);
116 }
117 
toSymbolEntry(DataRefImpl Ref) const118 const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const {
119   assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
120   assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!");
121 #ifndef NDEBUG
122   checkSymbolEntryPointer(Ref.p);
123 #endif
124   auto SymEntPtr = viewAs<XCOFFSymbolEntry>(Ref.p);
125   return SymEntPtr;
126 }
127 
fileHeader32() const128 const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
129   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
130   return static_cast<const XCOFFFileHeader32 *>(FileHeader);
131 }
132 
fileHeader64() const133 const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
134   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
135   return static_cast<const XCOFFFileHeader64 *>(FileHeader);
136 }
137 
138 const XCOFFSectionHeader32 *
sectionHeaderTable32() const139 XCOFFObjectFile::sectionHeaderTable32() const {
140   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
141   return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
142 }
143 
144 const XCOFFSectionHeader64 *
sectionHeaderTable64() const145 XCOFFObjectFile::sectionHeaderTable64() const {
146   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
147   return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
148 }
149 
moveSymbolNext(DataRefImpl & Symb) const150 void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
151   const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
152   SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1;
153 #ifndef NDEBUG
154   // This function is used by basic_symbol_iterator, which allows to
155   // point to the end-of-symbol-table address.
156   if (reinterpret_cast<uintptr_t>(SymEntPtr) != getEndOfSymbolTableAddress())
157     checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(SymEntPtr));
158 #endif
159   Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr);
160 }
161 
162 Expected<StringRef>
getStringTableEntry(uint32_t Offset) const163 XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const {
164   // The byte offset is relative to the start of the string table.
165   // A byte offset value of 0 is a null or zero-length symbol
166   // name. A byte offset in the range 1 to 3 (inclusive) points into the length
167   // field; as a soft-error recovery mechanism, we treat such cases as having an
168   // offset of 0.
169   if (Offset < 4)
170     return StringRef(nullptr, 0);
171 
172   if (StringTable.Data != nullptr && StringTable.Size > Offset)
173     return (StringTable.Data + Offset);
174 
175   return make_error<GenericBinaryError>("Bad offset for string table entry",
176                                         object_error::parse_failed);
177 }
178 
179 Expected<StringRef>
getCFileName(const XCOFFFileAuxEnt * CFileEntPtr) const180 XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const {
181   if (CFileEntPtr->NameInStrTbl.Magic !=
182       XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
183     return generateXCOFFFixedNameStringRef(CFileEntPtr->Name);
184   return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset);
185 }
186 
getSymbolName(DataRefImpl Symb) const187 Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
188   const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
189 
190   // A storage class value with the high-order bit on indicates that the name is
191   // a symbolic debugger stabstring.
192   if (SymEntPtr->StorageClass & 0x80)
193     return StringRef("Unimplemented Debug Name");
194 
195   if (SymEntPtr->NameInStrTbl.Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
196     return generateXCOFFFixedNameStringRef(SymEntPtr->SymbolName);
197 
198   return getStringTableEntry(SymEntPtr->NameInStrTbl.Offset);
199 }
200 
getSymbolAddress(DataRefImpl Symb) const201 Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
202   assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
203   return toSymbolEntry(Symb)->Value;
204 }
205 
getSymbolValueImpl(DataRefImpl Symb) const206 uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
207   assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
208   return toSymbolEntry(Symb)->Value;
209 }
210 
getCommonSymbolSizeImpl(DataRefImpl Symb) const211 uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
212   uint64_t Result = 0;
213   llvm_unreachable("Not yet implemented!");
214   return Result;
215 }
216 
217 Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const218 XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
219   llvm_unreachable("Not yet implemented!");
220   return SymbolRef::ST_Other;
221 }
222 
223 Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const224 XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
225   const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
226   int16_t SectNum = SymEntPtr->SectionNumber;
227 
228   if (isReservedSectionNumber(SectNum))
229     return section_end();
230 
231   Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum);
232   if (!ExpSec)
233     return ExpSec.takeError();
234 
235   return section_iterator(SectionRef(ExpSec.get(), this));
236 }
237 
moveSectionNext(DataRefImpl & Sec) const238 void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
239   const char *Ptr = reinterpret_cast<const char *>(Sec.p);
240   Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize());
241 }
242 
getSectionName(DataRefImpl Sec) const243 Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
244   return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec));
245 }
246 
getSectionAddress(DataRefImpl Sec) const247 uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
248   // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
249   // with MSVC.
250   if (is64Bit())
251     return toSection64(Sec)->VirtualAddress;
252 
253   return toSection32(Sec)->VirtualAddress;
254 }
255 
getSectionIndex(DataRefImpl Sec) const256 uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
257   // Section numbers in XCOFF are numbered beginning at 1. A section number of
258   // zero is used to indicate that a symbol is being imported or is undefined.
259   if (is64Bit())
260     return toSection64(Sec) - sectionHeaderTable64() + 1;
261   else
262     return toSection32(Sec) - sectionHeaderTable32() + 1;
263 }
264 
getSectionSize(DataRefImpl Sec) const265 uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
266   // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
267   // with MSVC.
268   if (is64Bit())
269     return toSection64(Sec)->SectionSize;
270 
271   return toSection32(Sec)->SectionSize;
272 }
273 
274 Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const275 XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
276   if (isSectionVirtual(Sec))
277     return ArrayRef<uint8_t>();
278 
279   uint64_t OffsetToRaw;
280   if (is64Bit())
281     OffsetToRaw = toSection64(Sec)->FileOffsetToRawData;
282   else
283     OffsetToRaw = toSection32(Sec)->FileOffsetToRawData;
284 
285   const uint8_t * ContentStart = base() + OffsetToRaw;
286   uint64_t SectionSize = getSectionSize(Sec);
287   if (checkOffset(Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize))
288     return make_error<BinaryError>();
289 
290   return makeArrayRef(ContentStart,SectionSize);
291 }
292 
getSectionAlignment(DataRefImpl Sec) const293 uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
294   uint64_t Result = 0;
295   llvm_unreachable("Not yet implemented!");
296   return Result;
297 }
298 
isSectionCompressed(DataRefImpl Sec) const299 bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
300   return false;
301 }
302 
isSectionText(DataRefImpl Sec) const303 bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
304   return getSectionFlags(Sec) & XCOFF::STYP_TEXT;
305 }
306 
isSectionData(DataRefImpl Sec) const307 bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
308   uint32_t Flags = getSectionFlags(Sec);
309   return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
310 }
311 
isSectionBSS(DataRefImpl Sec) const312 bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
313   uint32_t Flags = getSectionFlags(Sec);
314   return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
315 }
316 
isSectionVirtual(DataRefImpl Sec) const317 bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
318   return is64Bit() ? toSection64(Sec)->FileOffsetToRawData == 0
319                    : toSection32(Sec)->FileOffsetToRawData == 0;
320 }
321 
section_rel_begin(DataRefImpl Sec) const322 relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
323   if (is64Bit())
324     report_fatal_error("64-bit support not implemented yet");
325   const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
326   auto RelocationsOrErr = relocations(*SectionEntPtr);
327   if (Error E = RelocationsOrErr.takeError())
328     return relocation_iterator(RelocationRef());
329   DataRefImpl Ret;
330   Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
331   return relocation_iterator(RelocationRef(Ret, this));
332 }
333 
section_rel_end(DataRefImpl Sec) const334 relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const {
335   if (is64Bit())
336     report_fatal_error("64-bit support not implemented yet");
337   const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
338   auto RelocationsOrErr = relocations(*SectionEntPtr);
339   if (Error E = RelocationsOrErr.takeError())
340     return relocation_iterator(RelocationRef());
341   DataRefImpl Ret;
342   Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
343   return relocation_iterator(RelocationRef(Ret, this));
344 }
345 
moveRelocationNext(DataRefImpl & Rel) const346 void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
347   Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1);
348 }
349 
getRelocationOffset(DataRefImpl Rel) const350 uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
351   if (is64Bit())
352     report_fatal_error("64-bit support not implemented yet");
353   const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
354   const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32();
355   const uint32_t RelocAddress = Reloc->VirtualAddress;
356   const uint16_t NumberOfSections = getNumberOfSections();
357   for (uint16_t i = 0; i < NumberOfSections; ++i) {
358     // Find which section this relocation is belonging to, and get the
359     // relocation offset relative to the start of the section.
360     if (Sec32->VirtualAddress <= RelocAddress &&
361         RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) {
362       return RelocAddress - Sec32->VirtualAddress;
363     }
364     ++Sec32;
365   }
366   return InvalidRelocOffset;
367 }
368 
getRelocationSymbol(DataRefImpl Rel) const369 symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
370   if (is64Bit())
371     report_fatal_error("64-bit support not implemented yet");
372   const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
373   const uint32_t Index = Reloc->SymbolIndex;
374 
375   if (Index >= getLogicalNumberOfSymbolTableEntries32())
376     return symbol_end();
377 
378   DataRefImpl SymDRI;
379   SymDRI.p = reinterpret_cast<uintptr_t>(getPointerToSymbolTable() + Index);
380   return symbol_iterator(SymbolRef(SymDRI, this));
381 }
382 
getRelocationType(DataRefImpl Rel) const383 uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const {
384   if (is64Bit())
385     report_fatal_error("64-bit support not implemented yet");
386   return viewAs<XCOFFRelocation32>(Rel.p)->Type;
387 }
388 
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const389 void XCOFFObjectFile::getRelocationTypeName(
390     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
391   if (is64Bit())
392     report_fatal_error("64-bit support not implemented yet");
393   const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
394   StringRef Res = XCOFF::getRelocationTypeString(Reloc->Type);
395   Result.append(Res.begin(), Res.end());
396 }
397 
getSymbolFlags(DataRefImpl Symb) const398 Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
399   uint32_t Result = 0;
400   llvm_unreachable("Not yet implemented!");
401   return Result;
402 }
403 
symbol_begin() const404 basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
405   if (is64Bit())
406     report_fatal_error("64-bit support not implemented yet");
407   DataRefImpl SymDRI;
408   SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
409   return basic_symbol_iterator(SymbolRef(SymDRI, this));
410 }
411 
symbol_end() const412 basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
413   if (is64Bit())
414     report_fatal_error("64-bit support not implemented yet");
415   DataRefImpl SymDRI;
416   SymDRI.p = reinterpret_cast<uintptr_t>(
417       SymbolTblPtr + getLogicalNumberOfSymbolTableEntries32());
418   return basic_symbol_iterator(SymbolRef(SymDRI, this));
419 }
420 
section_begin() const421 section_iterator XCOFFObjectFile::section_begin() const {
422   DataRefImpl DRI;
423   DRI.p = getSectionHeaderTableAddress();
424   return section_iterator(SectionRef(DRI, this));
425 }
426 
section_end() const427 section_iterator XCOFFObjectFile::section_end() const {
428   DataRefImpl DRI;
429   DRI.p = getWithOffset(getSectionHeaderTableAddress(),
430                         getNumberOfSections() * getSectionHeaderSize());
431   return section_iterator(SectionRef(DRI, this));
432 }
433 
getBytesInAddress() const434 uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; }
435 
getFileFormatName() const436 StringRef XCOFFObjectFile::getFileFormatName() const {
437   return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000";
438 }
439 
getArch() const440 Triple::ArchType XCOFFObjectFile::getArch() const {
441   return is64Bit() ? Triple::ppc64 : Triple::ppc;
442 }
443 
getFeatures() const444 SubtargetFeatures XCOFFObjectFile::getFeatures() const {
445   return SubtargetFeatures();
446 }
447 
isRelocatableObject() const448 bool XCOFFObjectFile::isRelocatableObject() const {
449   if (is64Bit())
450     report_fatal_error("64-bit support not implemented yet");
451   return !(fileHeader32()->Flags & NoRelMask);
452 }
453 
getStartAddress() const454 Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
455   // TODO FIXME Should get from auxiliary_header->o_entry when support for the
456   // auxiliary_header is added.
457   return 0;
458 }
459 
mapDebugSectionName(StringRef Name) const460 StringRef XCOFFObjectFile::mapDebugSectionName(StringRef Name) const {
461   return StringSwitch<StringRef>(Name)
462       .Case("dwinfo", "debug_info")
463       .Case("dwline", "debug_line")
464       .Case("dwpbnms", "debug_pubnames")
465       .Case("dwpbtyp", "debug_pubtypes")
466       .Case("dwarnge", "debug_aranges")
467       .Case("dwabrev", "debug_abbrev")
468       .Case("dwstr", "debug_str")
469       .Case("dwrnges", "debug_ranges")
470       .Case("dwloc", "debug_loc")
471       .Case("dwframe", "debug_frame")
472       .Case("dwmac", "debug_macinfo")
473       .Default(Name);
474 }
475 
getFileHeaderSize() const476 size_t XCOFFObjectFile::getFileHeaderSize() const {
477   return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32);
478 }
479 
getSectionHeaderSize() const480 size_t XCOFFObjectFile::getSectionHeaderSize() const {
481   return is64Bit() ? sizeof(XCOFFSectionHeader64) :
482                      sizeof(XCOFFSectionHeader32);
483 }
484 
is64Bit() const485 bool XCOFFObjectFile::is64Bit() const {
486   return Binary::ID_XCOFF64 == getType();
487 }
488 
getMagic() const489 uint16_t XCOFFObjectFile::getMagic() const {
490   return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic;
491 }
492 
getSectionByNum(int16_t Num) const493 Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
494   if (Num <= 0 || Num > getNumberOfSections())
495     return errorCodeToError(object_error::invalid_section_index);
496 
497   DataRefImpl DRI;
498   DRI.p = getWithOffset(getSectionHeaderTableAddress(),
499                         getSectionHeaderSize() * (Num - 1));
500   return DRI;
501 }
502 
503 Expected<StringRef>
getSymbolSectionName(const XCOFFSymbolEntry * SymEntPtr) const504 XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const {
505   assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
506   int16_t SectionNum = SymEntPtr->SectionNumber;
507 
508   switch (SectionNum) {
509   case XCOFF::N_DEBUG:
510     return "N_DEBUG";
511   case XCOFF::N_ABS:
512     return "N_ABS";
513   case XCOFF::N_UNDEF:
514     return "N_UNDEF";
515   default:
516     Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
517     if (SecRef)
518       return generateXCOFFFixedNameStringRef(
519           getSectionNameInternal(SecRef.get()));
520     return SecRef.takeError();
521   }
522 }
523 
isReservedSectionNumber(int16_t SectionNumber)524 bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) {
525   return (SectionNumber <= 0 && SectionNumber >= -2);
526 }
527 
getNumberOfSections() const528 uint16_t XCOFFObjectFile::getNumberOfSections() const {
529   return is64Bit() ? fileHeader64()->NumberOfSections
530                    : fileHeader32()->NumberOfSections;
531 }
532 
getTimeStamp() const533 int32_t XCOFFObjectFile::getTimeStamp() const {
534   return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp;
535 }
536 
getOptionalHeaderSize() const537 uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
538   return is64Bit() ? fileHeader64()->AuxHeaderSize
539                    : fileHeader32()->AuxHeaderSize;
540 }
541 
getSymbolTableOffset32() const542 uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
543   return fileHeader32()->SymbolTableOffset;
544 }
545 
getRawNumberOfSymbolTableEntries32() const546 int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const {
547   // As far as symbol table size is concerned, if this field is negative it is
548   // to be treated as a 0. However since this field is also used for printing we
549   // don't want to truncate any negative values.
550   return fileHeader32()->NumberOfSymTableEntries;
551 }
552 
getLogicalNumberOfSymbolTableEntries32() const553 uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
554   return (fileHeader32()->NumberOfSymTableEntries >= 0
555               ? fileHeader32()->NumberOfSymTableEntries
556               : 0);
557 }
558 
getSymbolTableOffset64() const559 uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
560   return fileHeader64()->SymbolTableOffset;
561 }
562 
getNumberOfSymbolTableEntries64() const563 uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
564   return fileHeader64()->NumberOfSymTableEntries;
565 }
566 
getEndOfSymbolTableAddress() const567 uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const {
568   uint32_t NumberOfSymTableEntries =
569       is64Bit() ? getNumberOfSymbolTableEntries64()
570                 : getLogicalNumberOfSymbolTableEntries32();
571   return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr),
572                        XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries);
573 }
574 
checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const575 void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const {
576   if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr))
577     report_fatal_error("Symbol table entry is outside of symbol table.");
578 
579   if (SymbolEntPtr >= getEndOfSymbolTableAddress())
580     report_fatal_error("Symbol table entry is outside of symbol table.");
581 
582   ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) -
583                      reinterpret_cast<const char *>(SymbolTblPtr);
584 
585   if (Offset % XCOFF::SymbolTableEntrySize != 0)
586     report_fatal_error(
587         "Symbol table entry position is not valid inside of symbol table.");
588 }
589 
getSymbolIndex(uintptr_t SymbolEntPtr) const590 uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const {
591   return (reinterpret_cast<const char *>(SymbolEntPtr) -
592           reinterpret_cast<const char *>(SymbolTblPtr)) /
593          XCOFF::SymbolTableEntrySize;
594 }
595 
596 Expected<StringRef>
getSymbolNameByIndex(uint32_t Index) const597 XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const {
598   if (is64Bit())
599     report_fatal_error("64-bit symbol table support not implemented yet.");
600 
601   if (Index >= getLogicalNumberOfSymbolTableEntries32())
602     return errorCodeToError(object_error::invalid_symbol_index);
603 
604   DataRefImpl SymDRI;
605   SymDRI.p = reinterpret_cast<uintptr_t>(getPointerToSymbolTable() + Index);
606   return getSymbolName(SymDRI);
607 }
608 
getFlags() const609 uint16_t XCOFFObjectFile::getFlags() const {
610   return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
611 }
612 
getSectionNameInternal(DataRefImpl Sec) const613 const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const {
614   return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name;
615 }
616 
getSectionHeaderTableAddress() const617 uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
618   return reinterpret_cast<uintptr_t>(SectionHeaderTable);
619 }
620 
getSectionFlags(DataRefImpl Sec) const621 int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const {
622   return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags;
623 }
624 
XCOFFObjectFile(unsigned int Type,MemoryBufferRef Object)625 XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object)
626     : ObjectFile(Type, Object) {
627   assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64);
628 }
629 
sections64() const630 ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const {
631   assert(is64Bit() && "64-bit interface called for non 64-bit file.");
632   const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64();
633   return ArrayRef<XCOFFSectionHeader64>(TablePtr,
634                                         TablePtr + getNumberOfSections());
635 }
636 
sections32() const637 ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const {
638   assert(!is64Bit() && "32-bit interface called for non 32-bit file.");
639   const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32();
640   return ArrayRef<XCOFFSectionHeader32>(TablePtr,
641                                         TablePtr + getNumberOfSections());
642 }
643 
644 // In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO
645 // section header contains the actual count of relocation entries in the s_paddr
646 // field. STYP_OVRFLO headers contain the section index of their corresponding
647 // sections as their raw "NumberOfRelocations" field value.
getLogicalNumberOfRelocationEntries(const XCOFFSectionHeader32 & Sec) const648 Expected<uint32_t> XCOFFObjectFile::getLogicalNumberOfRelocationEntries(
649     const XCOFFSectionHeader32 &Sec) const {
650 
651   uint16_t SectionIndex = &Sec - sectionHeaderTable32() + 1;
652 
653   if (Sec.NumberOfRelocations < XCOFF::RelocOverflow)
654     return Sec.NumberOfRelocations;
655   for (const auto &Sec : sections32()) {
656     if (Sec.Flags == XCOFF::STYP_OVRFLO &&
657         Sec.NumberOfRelocations == SectionIndex)
658       return Sec.PhysicalAddress;
659   }
660   return errorCodeToError(object_error::parse_failed);
661 }
662 
663 Expected<ArrayRef<XCOFFRelocation32>>
relocations(const XCOFFSectionHeader32 & Sec) const664 XCOFFObjectFile::relocations(const XCOFFSectionHeader32 &Sec) const {
665   uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader),
666                                       Sec.FileOffsetToRelocationInfo);
667   auto NumRelocEntriesOrErr = getLogicalNumberOfRelocationEntries(Sec);
668   if (Error E = NumRelocEntriesOrErr.takeError())
669     return std::move(E);
670 
671   uint32_t NumRelocEntries = NumRelocEntriesOrErr.get();
672 
673   static_assert(
674       sizeof(XCOFFRelocation32) == XCOFF::RelocationSerializationSize32, "");
675   auto RelocationOrErr =
676       getObject<XCOFFRelocation32>(Data, reinterpret_cast<void *>(RelocAddr),
677                                    NumRelocEntries * sizeof(XCOFFRelocation32));
678   if (Error E = RelocationOrErr.takeError())
679     return std::move(E);
680 
681   const XCOFFRelocation32 *StartReloc = RelocationOrErr.get();
682 
683   return ArrayRef<XCOFFRelocation32>(StartReloc, StartReloc + NumRelocEntries);
684 }
685 
686 Expected<XCOFFStringTable>
parseStringTable(const XCOFFObjectFile * Obj,uint64_t Offset)687 XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
688   // If there is a string table, then the buffer must contain at least 4 bytes
689   // for the string table's size. Not having a string table is not an error.
690   if (Error E = Binary::checkOffset(
691           Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) {
692     consumeError(std::move(E));
693     return XCOFFStringTable{0, nullptr};
694   }
695 
696   // Read the size out of the buffer.
697   uint32_t Size = support::endian::read32be(Obj->base() + Offset);
698 
699   // If the size is less then 4, then the string table is just a size and no
700   // string data.
701   if (Size <= 4)
702     return XCOFFStringTable{4, nullptr};
703 
704   auto StringTableOrErr =
705       getObject<char>(Obj->Data, Obj->base() + Offset, Size);
706   if (Error E = StringTableOrErr.takeError())
707     return std::move(E);
708 
709   const char *StringTablePtr = StringTableOrErr.get();
710   if (StringTablePtr[Size - 1] != '\0')
711     return errorCodeToError(object_error::string_table_non_null_end);
712 
713   return XCOFFStringTable{Size, StringTablePtr};
714 }
715 
716 Expected<std::unique_ptr<XCOFFObjectFile>>
create(unsigned Type,MemoryBufferRef MBR)717 XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
718   // Can't use std::make_unique because of the private constructor.
719   std::unique_ptr<XCOFFObjectFile> Obj;
720   Obj.reset(new XCOFFObjectFile(Type, MBR));
721 
722   uint64_t CurOffset = 0;
723   const auto *Base = Obj->base();
724   MemoryBufferRef Data = Obj->Data;
725 
726   // Parse file header.
727   auto FileHeaderOrErr =
728       getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize());
729   if (Error E = FileHeaderOrErr.takeError())
730     return std::move(E);
731   Obj->FileHeader = FileHeaderOrErr.get();
732 
733   CurOffset += Obj->getFileHeaderSize();
734   // TODO FIXME we don't have support for an optional header yet, so just skip
735   // past it.
736   CurOffset += Obj->getOptionalHeaderSize();
737 
738   // Parse the section header table if it is present.
739   if (Obj->getNumberOfSections()) {
740     auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset,
741                                            Obj->getNumberOfSections() *
742                                                Obj->getSectionHeaderSize());
743     if (Error E = SecHeadersOrErr.takeError())
744       return std::move(E);
745     Obj->SectionHeaderTable = SecHeadersOrErr.get();
746   }
747 
748   // 64-bit object supports only file header and section headers for now.
749   if (Obj->is64Bit())
750     return std::move(Obj);
751 
752   // If there is no symbol table we are done parsing the memory buffer.
753   if (Obj->getLogicalNumberOfSymbolTableEntries32() == 0)
754     return std::move(Obj);
755 
756   // Parse symbol table.
757   CurOffset = Obj->fileHeader32()->SymbolTableOffset;
758   uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) *
759                              Obj->getLogicalNumberOfSymbolTableEntries32();
760   auto SymTableOrErr =
761       getObject<XCOFFSymbolEntry>(Data, Base + CurOffset, SymbolTableSize);
762   if (Error E = SymTableOrErr.takeError())
763     return std::move(E);
764   Obj->SymbolTblPtr = SymTableOrErr.get();
765   CurOffset += SymbolTableSize;
766 
767   // Parse String table.
768   Expected<XCOFFStringTable> StringTableOrErr =
769       parseStringTable(Obj.get(), CurOffset);
770   if (Error E = StringTableOrErr.takeError())
771     return std::move(E);
772   Obj->StringTable = StringTableOrErr.get();
773 
774   return std::move(Obj);
775 }
776 
777 Expected<std::unique_ptr<ObjectFile>>
createXCOFFObjectFile(MemoryBufferRef MemBufRef,unsigned FileType)778 ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
779                                   unsigned FileType) {
780   return XCOFFObjectFile::create(FileType, MemBufRef);
781 }
782 
getStorageClass() const783 XCOFF::StorageClass XCOFFSymbolRef::getStorageClass() const {
784   return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->StorageClass;
785 }
786 
getNumberOfAuxEntries() const787 uint8_t XCOFFSymbolRef::getNumberOfAuxEntries() const {
788   return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->NumberOfAuxEntries;
789 }
790 
791 // TODO: The function needs to return an error if there is no csect auxiliary
792 // entry.
getXCOFFCsectAuxEnt32() const793 const XCOFFCsectAuxEnt32 *XCOFFSymbolRef::getXCOFFCsectAuxEnt32() const {
794   assert(!OwningObjectPtr->is64Bit() &&
795          "32-bit interface called on 64-bit object file.");
796   assert(hasCsectAuxEnt() && "No Csect Auxiliary Entry is found.");
797 
798   // In XCOFF32, the csect auxilliary entry is always the last auxiliary
799   // entry for the symbol.
800   uintptr_t AuxAddr = getWithOffset(
801       SymEntDataRef.p, XCOFF::SymbolTableEntrySize * getNumberOfAuxEntries());
802 
803 #ifndef NDEBUG
804   OwningObjectPtr->checkSymbolEntryPointer(AuxAddr);
805 #endif
806 
807   return reinterpret_cast<const XCOFFCsectAuxEnt32 *>(AuxAddr);
808 }
809 
getType() const810 uint16_t XCOFFSymbolRef::getType() const {
811   return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SymbolType;
812 }
813 
getSectionNumber() const814 int16_t XCOFFSymbolRef::getSectionNumber() const {
815   return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SectionNumber;
816 }
817 
818 // TODO: The function name needs to be changed to express the purpose of the
819 // function.
hasCsectAuxEnt() const820 bool XCOFFSymbolRef::hasCsectAuxEnt() const {
821   XCOFF::StorageClass SC = getStorageClass();
822   return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT ||
823           SC == XCOFF::C_HIDEXT);
824 }
825 
isFunction() const826 bool XCOFFSymbolRef::isFunction() const {
827   if (OwningObjectPtr->is64Bit())
828     report_fatal_error("64-bit support is unimplemented yet.");
829 
830   if (getType() & FunctionSym)
831     return true;
832 
833   if (!hasCsectAuxEnt())
834     return false;
835 
836   const XCOFFCsectAuxEnt32 *CsectAuxEnt = getXCOFFCsectAuxEnt32();
837 
838   // A function definition should be a label definition.
839   if ((CsectAuxEnt->SymbolAlignmentAndType & SymTypeMask) != XCOFF::XTY_LD)
840     return false;
841 
842   if (CsectAuxEnt->StorageMappingClass != XCOFF::XMC_PR)
843     return false;
844 
845   int16_t SectNum = getSectionNumber();
846   Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum);
847   if (!SI)
848     return false;
849 
850   return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT);
851 }
852 
853 // Explictly instantiate template classes.
854 template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
855 template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
856 
doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes)857 bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) {
858   if (Bytes.size() < 4)
859     return false;
860 
861   return support::endian::read32be(Bytes.data()) == 0;
862 }
863 
TBVectorExt(StringRef TBvectorStrRef)864 TBVectorExt::TBVectorExt(StringRef TBvectorStrRef) {
865   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data());
866   Data = support::endian::read16be(Ptr);
867   VecParmsInfo = support::endian::read32be(Ptr + 2);
868 }
869 
870 #define GETVALUEWITHMASK(X) (Data & (TracebackTable::X))
871 #define GETVALUEWITHMASKSHIFT(X, S)                                            \
872   ((Data & (TracebackTable::X)) >> (TracebackTable::S))
getNumberOfVRSaved() const873 uint8_t TBVectorExt::getNumberOfVRSaved() const {
874   return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift);
875 }
876 
isVRSavedOnStack() const877 bool TBVectorExt::isVRSavedOnStack() const {
878   return GETVALUEWITHMASK(IsVRSavedOnStackMask);
879 }
880 
hasVarArgs() const881 bool TBVectorExt::hasVarArgs() const {
882   return GETVALUEWITHMASK(HasVarArgsMask);
883 }
getNumberOfVectorParms() const884 uint8_t TBVectorExt::getNumberOfVectorParms() const {
885   return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask,
886                                NumberOfVectorParmsShift);
887 }
888 
hasVMXInstruction() const889 bool TBVectorExt::hasVMXInstruction() const {
890   return GETVALUEWITHMASK(HasVMXInstructionMask);
891 }
892 #undef GETVALUEWITHMASK
893 #undef GETVALUEWITHMASKSHIFT
894 
getVectorParmsInfoString() const895 SmallString<32> TBVectorExt::getVectorParmsInfoString() const {
896   SmallString<32> ParmsType;
897   uint32_t Value = VecParmsInfo;
898   for (uint8_t I = 0; I < getNumberOfVectorParms(); ++I) {
899     if (I != 0)
900       ParmsType += ", ";
901     switch (Value & TracebackTable::ParmTypeMask) {
902     case TracebackTable::ParmTypeIsVectorCharBit:
903       ParmsType += "vc";
904       break;
905 
906     case TracebackTable::ParmTypeIsVectorShortBit:
907       ParmsType += "vs";
908       break;
909 
910     case TracebackTable::ParmTypeIsVectorIntBit:
911       ParmsType += "vi";
912       break;
913 
914     case TracebackTable::ParmTypeIsVectorFloatBit:
915       ParmsType += "vf";
916       break;
917     }
918     Value <<= 2;
919   }
920   return ParmsType;
921 }
922 
parseParmsTypeWithVecInfo(uint32_t Value,unsigned int ParmsNum)923 static SmallString<32> parseParmsTypeWithVecInfo(uint32_t Value,
924                                                  unsigned int ParmsNum) {
925   SmallString<32> ParmsType;
926   unsigned I = 0;
927   bool Begin = false;
928   while (I < ParmsNum || Value) {
929     if (Begin)
930       ParmsType += ", ";
931     else
932       Begin = true;
933 
934     switch (Value & TracebackTable::ParmTypeMask) {
935     case TracebackTable::ParmTypeIsFixedBits:
936       ParmsType += "i";
937       ++I;
938       break;
939     case TracebackTable::ParmTypeIsVectorBits:
940       ParmsType += "v";
941       break;
942     case TracebackTable::ParmTypeIsFloatingBits:
943       ParmsType += "f";
944       ++I;
945       break;
946     case TracebackTable::ParmTypeIsDoubleBits:
947       ParmsType += "d";
948       ++I;
949       break;
950     default:
951       assert(false && "Unrecognized bits in ParmsType.");
952     }
953     Value <<= 2;
954   }
955   assert(I == ParmsNum &&
956          "The total parameters number of fixed-point or floating-point "
957          "parameters not equal to the number in the parameter type!");
958   return ParmsType;
959 }
960 
create(const uint8_t * Ptr,uint64_t & Size)961 Expected<XCOFFTracebackTable> XCOFFTracebackTable::create(const uint8_t *Ptr,
962                                                           uint64_t &Size) {
963   Error Err = Error::success();
964   XCOFFTracebackTable TBT(Ptr, Size, Err);
965   if (Err)
966     return std::move(Err);
967   return TBT;
968 }
969 
XCOFFTracebackTable(const uint8_t * Ptr,uint64_t & Size,Error & Err)970 XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
971                                          Error &Err)
972     : TBPtr(Ptr) {
973   ErrorAsOutParameter EAO(&Err);
974   DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false,
975                    /*AddressSize=*/0);
976   DataExtractor::Cursor Cur(/*Offset=*/0);
977 
978   // Skip 8 bytes of mandatory fields.
979   DE.getU64(Cur);
980 
981   // Begin to parse optional fields.
982   if (Cur) {
983     unsigned ParmNum = getNumberOfFixedParms() + getNumberOfFPParms();
984 
985     // As long as there are no "fixed-point" or floating-point parameters, this
986     // field remains not present even when hasVectorInfo gives true and
987     // indicates the presence of vector parameters.
988     if (ParmNum > 0) {
989       uint32_t ParamsTypeValue = DE.getU32(Cur);
990       if (Cur)
991         ParmsType = hasVectorInfo()
992                         ? parseParmsTypeWithVecInfo(ParamsTypeValue, ParmNum)
993                         : parseParmsType(ParamsTypeValue, ParmNum);
994     }
995   }
996 
997   if (Cur && hasTraceBackTableOffset())
998     TraceBackTableOffset = DE.getU32(Cur);
999 
1000   if (Cur && isInterruptHandler())
1001     HandlerMask = DE.getU32(Cur);
1002 
1003   if (Cur && hasControlledStorage()) {
1004     NumOfCtlAnchors = DE.getU32(Cur);
1005     if (Cur && NumOfCtlAnchors) {
1006       SmallVector<uint32_t, 8> Disp;
1007       Disp.reserve(NumOfCtlAnchors.getValue());
1008       for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I)
1009         Disp.push_back(DE.getU32(Cur));
1010       if (Cur)
1011         ControlledStorageInfoDisp = std::move(Disp);
1012     }
1013   }
1014 
1015   if (Cur && isFuncNamePresent()) {
1016     uint16_t FunctionNameLen = DE.getU16(Cur);
1017     if (Cur)
1018       FunctionName = DE.getBytes(Cur, FunctionNameLen);
1019   }
1020 
1021   if (Cur && isAllocaUsed())
1022     AllocaRegister = DE.getU8(Cur);
1023 
1024   if (Cur && hasVectorInfo()) {
1025     StringRef VectorExtRef = DE.getBytes(Cur, 6);
1026     if (Cur)
1027       VecExt = TBVectorExt(VectorExtRef);
1028   }
1029 
1030   if (Cur && hasExtensionTable())
1031     ExtensionTable = DE.getU8(Cur);
1032 
1033   if (!Cur)
1034     Err = Cur.takeError();
1035   Size = Cur.tell();
1036 }
1037 
1038 #define GETBITWITHMASK(P, X)                                                   \
1039   (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X))
1040 #define GETBITWITHMASKSHIFT(P, X, S)                                           \
1041   ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >>           \
1042    (TracebackTable::S))
1043 
getVersion() const1044 uint8_t XCOFFTracebackTable::getVersion() const {
1045   return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift);
1046 }
1047 
getLanguageID() const1048 uint8_t XCOFFTracebackTable::getLanguageID() const {
1049   return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift);
1050 }
1051 
isGlobalLinkage() const1052 bool XCOFFTracebackTable::isGlobalLinkage() const {
1053   return GETBITWITHMASK(0, IsGlobaLinkageMask);
1054 }
1055 
isOutOfLineEpilogOrPrologue() const1056 bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const {
1057   return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask);
1058 }
1059 
hasTraceBackTableOffset() const1060 bool XCOFFTracebackTable::hasTraceBackTableOffset() const {
1061   return GETBITWITHMASK(0, HasTraceBackTableOffsetMask);
1062 }
1063 
isInternalProcedure() const1064 bool XCOFFTracebackTable::isInternalProcedure() const {
1065   return GETBITWITHMASK(0, IsInternalProcedureMask);
1066 }
1067 
hasControlledStorage() const1068 bool XCOFFTracebackTable::hasControlledStorage() const {
1069   return GETBITWITHMASK(0, HasControlledStorageMask);
1070 }
1071 
isTOCless() const1072 bool XCOFFTracebackTable::isTOCless() const {
1073   return GETBITWITHMASK(0, IsTOClessMask);
1074 }
1075 
isFloatingPointPresent() const1076 bool XCOFFTracebackTable::isFloatingPointPresent() const {
1077   return GETBITWITHMASK(0, IsFloatingPointPresentMask);
1078 }
1079 
isFloatingPointOperationLogOrAbortEnabled() const1080 bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const {
1081   return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask);
1082 }
1083 
isInterruptHandler() const1084 bool XCOFFTracebackTable::isInterruptHandler() const {
1085   return GETBITWITHMASK(0, IsInterruptHandlerMask);
1086 }
1087 
isFuncNamePresent() const1088 bool XCOFFTracebackTable::isFuncNamePresent() const {
1089   return GETBITWITHMASK(0, IsFunctionNamePresentMask);
1090 }
1091 
isAllocaUsed() const1092 bool XCOFFTracebackTable::isAllocaUsed() const {
1093   return GETBITWITHMASK(0, IsAllocaUsedMask);
1094 }
1095 
getOnConditionDirective() const1096 uint8_t XCOFFTracebackTable::getOnConditionDirective() const {
1097   return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask,
1098                              OnConditionDirectiveShift);
1099 }
1100 
isCRSaved() const1101 bool XCOFFTracebackTable::isCRSaved() const {
1102   return GETBITWITHMASK(0, IsCRSavedMask);
1103 }
1104 
isLRSaved() const1105 bool XCOFFTracebackTable::isLRSaved() const {
1106   return GETBITWITHMASK(0, IsLRSavedMask);
1107 }
1108 
isBackChainStored() const1109 bool XCOFFTracebackTable::isBackChainStored() const {
1110   return GETBITWITHMASK(4, IsBackChainStoredMask);
1111 }
1112 
isFixup() const1113 bool XCOFFTracebackTable::isFixup() const {
1114   return GETBITWITHMASK(4, IsFixupMask);
1115 }
1116 
getNumOfFPRsSaved() const1117 uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const {
1118   return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift);
1119 }
1120 
hasExtensionTable() const1121 bool XCOFFTracebackTable::hasExtensionTable() const {
1122   return GETBITWITHMASK(4, HasExtensionTableMask);
1123 }
1124 
hasVectorInfo() const1125 bool XCOFFTracebackTable::hasVectorInfo() const {
1126   return GETBITWITHMASK(4, HasVectorInfoMask);
1127 }
1128 
getNumOfGPRsSaved() const1129 uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const {
1130   return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift);
1131 }
1132 
getNumberOfFixedParms() const1133 uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const {
1134   return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask,
1135                              NumberOfFixedParmsShift);
1136 }
1137 
getNumberOfFPParms() const1138 uint8_t XCOFFTracebackTable::getNumberOfFPParms() const {
1139   return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask,
1140                              NumberOfFloatingPointParmsShift);
1141 }
1142 
hasParmsOnStack() const1143 bool XCOFFTracebackTable::hasParmsOnStack() const {
1144   return GETBITWITHMASK(4, HasParmsOnStackMask);
1145 }
1146 
1147 #undef GETBITWITHMASK
1148 #undef GETBITWITHMASKSHIFT
1149 } // namespace object
1150 } // namespace llvm
1151