xref: /llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp (revision 69396896fb615067b04a3e0c220f93bc91a10eec)
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 uint16_t NoRelMask = 0x0001;
28 static const size_t SymbolAuxTypeOffset = 17;
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>
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 
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 
46 template <typename T> static const T *viewAs(uintptr_t in) {
47   return reinterpret_cast<const T *>(in);
48 }
49 
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 
57 template <typename T> StringRef XCOFFSectionHeader<T>::getName() const {
58   const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
59   return generateXCOFFFixedNameStringRef(DerivedXCOFFSectionHeader.Name);
60 }
61 
62 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>
68 bool XCOFFSectionHeader<T>::isReservedSectionType() const {
69   return getSectionType() & SectionFlagsReservedMask;
70 }
71 
72 bool XCOFFRelocation32::isRelocationSigned() const {
73   return Info & XR_SIGN_INDICATOR_MASK;
74 }
75 
76 bool XCOFFRelocation32::isFixupIndicated() const {
77   return Info & XR_FIXUP_INDICATOR_MASK;
78 }
79 
80 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 
86 uintptr_t
87 XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
88                                                uint32_t Distance) {
89   return getWithOffset(CurrentAddress, Distance * XCOFF::SymbolTableEntrySize);
90 }
91 
92 const XCOFF::SymbolAuxType *
93 XCOFFObjectFile::getSymbolAuxType(uintptr_t AuxEntryAddress) const {
94   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
95   return viewAs<XCOFF::SymbolAuxType>(
96       getWithOffset(AuxEntryAddress, SymbolAuxTypeOffset));
97 }
98 
99 void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
100                                           uintptr_t TableAddress) const {
101   if (Addr < TableAddress)
102     report_fatal_error("Section header outside of section header table.");
103 
104   uintptr_t Offset = Addr - TableAddress;
105   if (Offset >= getSectionHeaderSize() * getNumberOfSections())
106     report_fatal_error("Section header outside of section header table.");
107 
108   if (Offset % getSectionHeaderSize() != 0)
109     report_fatal_error(
110         "Section header pointer does not point to a valid section header.");
111 }
112 
113 const XCOFFSectionHeader32 *
114 XCOFFObjectFile::toSection32(DataRefImpl Ref) const {
115   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
116 #ifndef NDEBUG
117   checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
118 #endif
119   return viewAs<XCOFFSectionHeader32>(Ref.p);
120 }
121 
122 const XCOFFSectionHeader64 *
123 XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
124   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
125 #ifndef NDEBUG
126   checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
127 #endif
128   return viewAs<XCOFFSectionHeader64>(Ref.p);
129 }
130 
131 XCOFFSymbolRef XCOFFObjectFile::toSymbolRef(DataRefImpl Ref) const {
132   assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!");
133 #ifndef NDEBUG
134   checkSymbolEntryPointer(Ref.p);
135 #endif
136   return XCOFFSymbolRef(Ref, this);
137 }
138 
139 const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
140   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
141   return static_cast<const XCOFFFileHeader32 *>(FileHeader);
142 }
143 
144 const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
145   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
146   return static_cast<const XCOFFFileHeader64 *>(FileHeader);
147 }
148 
149 const XCOFFSectionHeader32 *
150 XCOFFObjectFile::sectionHeaderTable32() const {
151   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
152   return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
153 }
154 
155 const XCOFFSectionHeader64 *
156 XCOFFObjectFile::sectionHeaderTable64() const {
157   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
158   return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
159 }
160 
161 void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
162   uintptr_t NextSymbolAddr = getAdvancedSymbolEntryAddress(
163       Symb.p, toSymbolRef(Symb).getNumberOfAuxEntries() + 1);
164 #ifndef NDEBUG
165   // This function is used by basic_symbol_iterator, which allows to
166   // point to the end-of-symbol-table address.
167   if (NextSymbolAddr != getEndOfSymbolTableAddress())
168     checkSymbolEntryPointer(NextSymbolAddr);
169 #endif
170   Symb.p = NextSymbolAddr;
171 }
172 
173 Expected<StringRef>
174 XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const {
175   // The byte offset is relative to the start of the string table.
176   // A byte offset value of 0 is a null or zero-length symbol
177   // name. A byte offset in the range 1 to 3 (inclusive) points into the length
178   // field; as a soft-error recovery mechanism, we treat such cases as having an
179   // offset of 0.
180   if (Offset < 4)
181     return StringRef(nullptr, 0);
182 
183   if (StringTable.Data != nullptr && StringTable.Size > Offset)
184     return (StringTable.Data + Offset);
185 
186   return make_error<GenericBinaryError>("Bad offset for string table entry",
187                                         object_error::parse_failed);
188 }
189 
190 StringRef XCOFFObjectFile::getStringTable() const {
191   // If the size is less than or equal to 4, then the string table contains no
192   // string data.
193   return StringRef(StringTable.Data,
194                    StringTable.Size <= 4 ? 0 : StringTable.Size);
195 }
196 
197 Expected<StringRef>
198 XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const {
199   if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
200     return generateXCOFFFixedNameStringRef(CFileEntPtr->Name);
201   return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset);
202 }
203 
204 Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
205   return toSymbolRef(Symb).getName();
206 }
207 
208 Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
209   return toSymbolRef(Symb).getValue();
210 }
211 
212 uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
213   return toSymbolRef(Symb).getValue();
214 }
215 
216 uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
217   uint64_t Result = 0;
218   llvm_unreachable("Not yet implemented!");
219   return Result;
220 }
221 
222 Expected<SymbolRef::Type>
223 XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
224   // TODO: Return the correct symbol type.
225   return SymbolRef::ST_Other;
226 }
227 
228 Expected<section_iterator>
229 XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
230   const int16_t SectNum = toSymbolRef(Symb).getSectionNumber();
231 
232   if (isReservedSectionNumber(SectNum))
233     return section_end();
234 
235   Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum);
236   if (!ExpSec)
237     return ExpSec.takeError();
238 
239   return section_iterator(SectionRef(ExpSec.get(), this));
240 }
241 
242 void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
243   const char *Ptr = reinterpret_cast<const char *>(Sec.p);
244   Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize());
245 }
246 
247 Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
248   return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec));
249 }
250 
251 uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
252   // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
253   // with MSVC.
254   if (is64Bit())
255     return toSection64(Sec)->VirtualAddress;
256 
257   return toSection32(Sec)->VirtualAddress;
258 }
259 
260 uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
261   // Section numbers in XCOFF are numbered beginning at 1. A section number of
262   // zero is used to indicate that a symbol is being imported or is undefined.
263   if (is64Bit())
264     return toSection64(Sec) - sectionHeaderTable64() + 1;
265   else
266     return toSection32(Sec) - sectionHeaderTable32() + 1;
267 }
268 
269 uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
270   // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
271   // with MSVC.
272   if (is64Bit())
273     return toSection64(Sec)->SectionSize;
274 
275   return toSection32(Sec)->SectionSize;
276 }
277 
278 Expected<ArrayRef<uint8_t>>
279 XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
280   if (isSectionVirtual(Sec))
281     return ArrayRef<uint8_t>();
282 
283   uint64_t OffsetToRaw;
284   if (is64Bit())
285     OffsetToRaw = toSection64(Sec)->FileOffsetToRawData;
286   else
287     OffsetToRaw = toSection32(Sec)->FileOffsetToRawData;
288 
289   const uint8_t * ContentStart = base() + OffsetToRaw;
290   uint64_t SectionSize = getSectionSize(Sec);
291   if (checkOffset(Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize))
292     return make_error<BinaryError>();
293 
294   return makeArrayRef(ContentStart,SectionSize);
295 }
296 
297 uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
298   uint64_t Result = 0;
299   llvm_unreachable("Not yet implemented!");
300   return Result;
301 }
302 
303 bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
304   return false;
305 }
306 
307 bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
308   return getSectionFlags(Sec) & XCOFF::STYP_TEXT;
309 }
310 
311 bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
312   uint32_t Flags = getSectionFlags(Sec);
313   return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
314 }
315 
316 bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
317   uint32_t Flags = getSectionFlags(Sec);
318   return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
319 }
320 
321 bool XCOFFObjectFile::isDebugSection(DataRefImpl Sec) const {
322   uint32_t Flags = getSectionFlags(Sec);
323   return Flags & (XCOFF::STYP_DEBUG | XCOFF::STYP_DWARF);
324 }
325 
326 bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
327   return is64Bit() ? toSection64(Sec)->FileOffsetToRawData == 0
328                    : toSection32(Sec)->FileOffsetToRawData == 0;
329 }
330 
331 relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
332   if (is64Bit())
333     report_fatal_error("64-bit support not implemented yet");
334   const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
335   auto RelocationsOrErr = relocations(*SectionEntPtr);
336   if (Error E = RelocationsOrErr.takeError())
337     return relocation_iterator(RelocationRef());
338   DataRefImpl Ret;
339   Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
340   return relocation_iterator(RelocationRef(Ret, this));
341 }
342 
343 relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const {
344   if (is64Bit())
345     report_fatal_error("64-bit support not implemented yet");
346   const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
347   auto RelocationsOrErr = relocations(*SectionEntPtr);
348   if (Error E = RelocationsOrErr.takeError())
349     return relocation_iterator(RelocationRef());
350   DataRefImpl Ret;
351   Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
352   return relocation_iterator(RelocationRef(Ret, this));
353 }
354 
355 void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
356   Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1);
357 }
358 
359 uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
360   if (is64Bit())
361     report_fatal_error("64-bit support not implemented yet");
362   const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
363   const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32();
364   const uint32_t RelocAddress = Reloc->VirtualAddress;
365   const uint16_t NumberOfSections = getNumberOfSections();
366   for (uint16_t i = 0; i < NumberOfSections; ++i) {
367     // Find which section this relocation is belonging to, and get the
368     // relocation offset relative to the start of the section.
369     if (Sec32->VirtualAddress <= RelocAddress &&
370         RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) {
371       return RelocAddress - Sec32->VirtualAddress;
372     }
373     ++Sec32;
374   }
375   return InvalidRelocOffset;
376 }
377 
378 symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
379   if (is64Bit())
380     report_fatal_error("64-bit support not implemented yet");
381   const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
382   const uint32_t Index = Reloc->SymbolIndex;
383 
384   if (Index >= getLogicalNumberOfSymbolTableEntries32())
385     return symbol_end();
386 
387   DataRefImpl SymDRI;
388   SymDRI.p = getSymbolEntryAddressByIndex(Index);
389   return symbol_iterator(SymbolRef(SymDRI, this));
390 }
391 
392 uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const {
393   if (is64Bit())
394     report_fatal_error("64-bit support not implemented yet");
395   return viewAs<XCOFFRelocation32>(Rel.p)->Type;
396 }
397 
398 void XCOFFObjectFile::getRelocationTypeName(
399     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
400   if (is64Bit())
401     report_fatal_error("64-bit support not implemented yet");
402   const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
403   StringRef Res = XCOFF::getRelocationTypeString(Reloc->Type);
404   Result.append(Res.begin(), Res.end());
405 }
406 
407 Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
408   uint32_t Result = 0;
409   // TODO: Return correct symbol flags.
410   return Result;
411 }
412 
413 basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
414   DataRefImpl SymDRI;
415   SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
416   return basic_symbol_iterator(SymbolRef(SymDRI, this));
417 }
418 
419 basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
420   DataRefImpl SymDRI;
421   const uint32_t NumberOfSymbolTableEntries = getNumberOfSymbolTableEntries();
422   SymDRI.p = getSymbolEntryAddressByIndex(NumberOfSymbolTableEntries);
423   return basic_symbol_iterator(SymbolRef(SymDRI, this));
424 }
425 
426 section_iterator XCOFFObjectFile::section_begin() const {
427   DataRefImpl DRI;
428   DRI.p = getSectionHeaderTableAddress();
429   return section_iterator(SectionRef(DRI, this));
430 }
431 
432 section_iterator XCOFFObjectFile::section_end() const {
433   DataRefImpl DRI;
434   DRI.p = getWithOffset(getSectionHeaderTableAddress(),
435                         getNumberOfSections() * getSectionHeaderSize());
436   return section_iterator(SectionRef(DRI, this));
437 }
438 
439 uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; }
440 
441 StringRef XCOFFObjectFile::getFileFormatName() const {
442   return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000";
443 }
444 
445 Triple::ArchType XCOFFObjectFile::getArch() const {
446   return is64Bit() ? Triple::ppc64 : Triple::ppc;
447 }
448 
449 SubtargetFeatures XCOFFObjectFile::getFeatures() const {
450   return SubtargetFeatures();
451 }
452 
453 bool XCOFFObjectFile::isRelocatableObject() const {
454   if (is64Bit())
455     return !(fileHeader64()->Flags & NoRelMask);
456   return !(fileHeader32()->Flags & NoRelMask);
457 }
458 
459 Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
460   // TODO FIXME Should get from auxiliary_header->o_entry when support for the
461   // auxiliary_header is added.
462   return 0;
463 }
464 
465 StringRef XCOFFObjectFile::mapDebugSectionName(StringRef Name) const {
466   return StringSwitch<StringRef>(Name)
467       .Case("dwinfo", "debug_info")
468       .Case("dwline", "debug_line")
469       .Case("dwpbnms", "debug_pubnames")
470       .Case("dwpbtyp", "debug_pubtypes")
471       .Case("dwarnge", "debug_aranges")
472       .Case("dwabrev", "debug_abbrev")
473       .Case("dwstr", "debug_str")
474       .Case("dwrnges", "debug_ranges")
475       .Case("dwloc", "debug_loc")
476       .Case("dwframe", "debug_frame")
477       .Case("dwmac", "debug_macinfo")
478       .Default(Name);
479 }
480 
481 size_t XCOFFObjectFile::getFileHeaderSize() const {
482   return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32);
483 }
484 
485 size_t XCOFFObjectFile::getSectionHeaderSize() const {
486   return is64Bit() ? sizeof(XCOFFSectionHeader64) :
487                      sizeof(XCOFFSectionHeader32);
488 }
489 
490 bool XCOFFObjectFile::is64Bit() const {
491   return Binary::ID_XCOFF64 == getType();
492 }
493 
494 uint16_t XCOFFObjectFile::getMagic() const {
495   return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic;
496 }
497 
498 Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
499   if (Num <= 0 || Num > getNumberOfSections())
500     return errorCodeToError(object_error::invalid_section_index);
501 
502   DataRefImpl DRI;
503   DRI.p = getWithOffset(getSectionHeaderTableAddress(),
504                         getSectionHeaderSize() * (Num - 1));
505   return DRI;
506 }
507 
508 Expected<StringRef>
509 XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const {
510   const int16_t SectionNum = SymEntPtr.getSectionNumber();
511 
512   switch (SectionNum) {
513   case XCOFF::N_DEBUG:
514     return "N_DEBUG";
515   case XCOFF::N_ABS:
516     return "N_ABS";
517   case XCOFF::N_UNDEF:
518     return "N_UNDEF";
519   default:
520     Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
521     if (SecRef)
522       return generateXCOFFFixedNameStringRef(
523           getSectionNameInternal(SecRef.get()));
524     return SecRef.takeError();
525   }
526 }
527 
528 unsigned XCOFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
529   XCOFFSymbolRef XCOFFSymRef(Sym.getRawDataRefImpl(), this);
530   return XCOFFSymRef.getSectionNumber();
531 }
532 
533 bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) {
534   return (SectionNumber <= 0 && SectionNumber >= -2);
535 }
536 
537 uint16_t XCOFFObjectFile::getNumberOfSections() const {
538   return is64Bit() ? fileHeader64()->NumberOfSections
539                    : fileHeader32()->NumberOfSections;
540 }
541 
542 int32_t XCOFFObjectFile::getTimeStamp() const {
543   return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp;
544 }
545 
546 uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
547   return is64Bit() ? fileHeader64()->AuxHeaderSize
548                    : fileHeader32()->AuxHeaderSize;
549 }
550 
551 uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
552   return fileHeader32()->SymbolTableOffset;
553 }
554 
555 int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const {
556   // As far as symbol table size is concerned, if this field is negative it is
557   // to be treated as a 0. However since this field is also used for printing we
558   // don't want to truncate any negative values.
559   return fileHeader32()->NumberOfSymTableEntries;
560 }
561 
562 uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
563   return (fileHeader32()->NumberOfSymTableEntries >= 0
564               ? fileHeader32()->NumberOfSymTableEntries
565               : 0);
566 }
567 
568 uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
569   return fileHeader64()->SymbolTableOffset;
570 }
571 
572 uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
573   return fileHeader64()->NumberOfSymTableEntries;
574 }
575 
576 uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const {
577   return is64Bit() ? getNumberOfSymbolTableEntries64()
578                    : getLogicalNumberOfSymbolTableEntries32();
579 }
580 
581 uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const {
582   const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
583   return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr),
584                        XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries);
585 }
586 
587 void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const {
588   if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr))
589     report_fatal_error("Symbol table entry is outside of symbol table.");
590 
591   if (SymbolEntPtr >= getEndOfSymbolTableAddress())
592     report_fatal_error("Symbol table entry is outside of symbol table.");
593 
594   ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) -
595                      reinterpret_cast<const char *>(SymbolTblPtr);
596 
597   if (Offset % XCOFF::SymbolTableEntrySize != 0)
598     report_fatal_error(
599         "Symbol table entry position is not valid inside of symbol table.");
600 }
601 
602 uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const {
603   return (reinterpret_cast<const char *>(SymbolEntPtr) -
604           reinterpret_cast<const char *>(SymbolTblPtr)) /
605          XCOFF::SymbolTableEntrySize;
606 }
607 
608 uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const {
609   return getAdvancedSymbolEntryAddress(
610       reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index);
611 }
612 
613 Expected<StringRef>
614 XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const {
615   const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
616 
617   if (Index >= NumberOfSymTableEntries)
618     return errorCodeToError(object_error::invalid_symbol_index);
619 
620   DataRefImpl SymDRI;
621   SymDRI.p = getSymbolEntryAddressByIndex(Index);
622   return getSymbolName(SymDRI);
623 }
624 
625 uint16_t XCOFFObjectFile::getFlags() const {
626   return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
627 }
628 
629 const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const {
630   return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name;
631 }
632 
633 uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
634   return reinterpret_cast<uintptr_t>(SectionHeaderTable);
635 }
636 
637 int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const {
638   return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags;
639 }
640 
641 XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object)
642     : ObjectFile(Type, Object) {
643   assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64);
644 }
645 
646 ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const {
647   assert(is64Bit() && "64-bit interface called for non 64-bit file.");
648   const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64();
649   return ArrayRef<XCOFFSectionHeader64>(TablePtr,
650                                         TablePtr + getNumberOfSections());
651 }
652 
653 ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const {
654   assert(!is64Bit() && "32-bit interface called for non 32-bit file.");
655   const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32();
656   return ArrayRef<XCOFFSectionHeader32>(TablePtr,
657                                         TablePtr + getNumberOfSections());
658 }
659 
660 // In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO
661 // section header contains the actual count of relocation entries in the s_paddr
662 // field. STYP_OVRFLO headers contain the section index of their corresponding
663 // sections as their raw "NumberOfRelocations" field value.
664 Expected<uint32_t> XCOFFObjectFile::getLogicalNumberOfRelocationEntries(
665     const XCOFFSectionHeader32 &Sec) const {
666 
667   uint16_t SectionIndex = &Sec - sectionHeaderTable32() + 1;
668 
669   if (Sec.NumberOfRelocations < XCOFF::RelocOverflow)
670     return Sec.NumberOfRelocations;
671   for (const auto &Sec : sections32()) {
672     if (Sec.Flags == XCOFF::STYP_OVRFLO &&
673         Sec.NumberOfRelocations == SectionIndex)
674       return Sec.PhysicalAddress;
675   }
676   return errorCodeToError(object_error::parse_failed);
677 }
678 
679 Expected<ArrayRef<XCOFFRelocation32>>
680 XCOFFObjectFile::relocations(const XCOFFSectionHeader32 &Sec) const {
681   uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader),
682                                       Sec.FileOffsetToRelocationInfo);
683   auto NumRelocEntriesOrErr = getLogicalNumberOfRelocationEntries(Sec);
684   if (Error E = NumRelocEntriesOrErr.takeError())
685     return std::move(E);
686 
687   uint32_t NumRelocEntries = NumRelocEntriesOrErr.get();
688 
689   static_assert(
690       sizeof(XCOFFRelocation32) == XCOFF::RelocationSerializationSize32, "");
691   auto RelocationOrErr =
692       getObject<XCOFFRelocation32>(Data, reinterpret_cast<void *>(RelocAddr),
693                                    NumRelocEntries * sizeof(XCOFFRelocation32));
694   if (Error E = RelocationOrErr.takeError())
695     return std::move(E);
696 
697   const XCOFFRelocation32 *StartReloc = RelocationOrErr.get();
698 
699   return ArrayRef<XCOFFRelocation32>(StartReloc, StartReloc + NumRelocEntries);
700 }
701 
702 Expected<XCOFFStringTable>
703 XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
704   // If there is a string table, then the buffer must contain at least 4 bytes
705   // for the string table's size. Not having a string table is not an error.
706   if (Error E = Binary::checkOffset(
707           Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) {
708     consumeError(std::move(E));
709     return XCOFFStringTable{0, nullptr};
710   }
711 
712   // Read the size out of the buffer.
713   uint32_t Size = support::endian::read32be(Obj->base() + Offset);
714 
715   // If the size is less then 4, then the string table is just a size and no
716   // string data.
717   if (Size <= 4)
718     return XCOFFStringTable{4, nullptr};
719 
720   auto StringTableOrErr =
721       getObject<char>(Obj->Data, Obj->base() + Offset, Size);
722   if (Error E = StringTableOrErr.takeError())
723     return std::move(E);
724 
725   const char *StringTablePtr = StringTableOrErr.get();
726   if (StringTablePtr[Size - 1] != '\0')
727     return errorCodeToError(object_error::string_table_non_null_end);
728 
729   return XCOFFStringTable{Size, StringTablePtr};
730 }
731 
732 Expected<std::unique_ptr<XCOFFObjectFile>>
733 XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
734   // Can't use std::make_unique because of the private constructor.
735   std::unique_ptr<XCOFFObjectFile> Obj;
736   Obj.reset(new XCOFFObjectFile(Type, MBR));
737 
738   uint64_t CurOffset = 0;
739   const auto *Base = Obj->base();
740   MemoryBufferRef Data = Obj->Data;
741 
742   // Parse file header.
743   auto FileHeaderOrErr =
744       getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize());
745   if (Error E = FileHeaderOrErr.takeError())
746     return std::move(E);
747   Obj->FileHeader = FileHeaderOrErr.get();
748 
749   CurOffset += Obj->getFileHeaderSize();
750   // TODO FIXME we don't have support for an optional header yet, so just skip
751   // past it.
752   CurOffset += Obj->getOptionalHeaderSize();
753 
754   // Parse the section header table if it is present.
755   if (Obj->getNumberOfSections()) {
756     auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset,
757                                            Obj->getNumberOfSections() *
758                                                Obj->getSectionHeaderSize());
759     if (Error E = SecHeadersOrErr.takeError())
760       return std::move(E);
761     Obj->SectionHeaderTable = SecHeadersOrErr.get();
762   }
763 
764   const uint32_t NumberOfSymbolTableEntries =
765       Obj->getNumberOfSymbolTableEntries();
766 
767   // If there is no symbol table we are done parsing the memory buffer.
768   if (NumberOfSymbolTableEntries == 0)
769     return std::move(Obj);
770 
771   // Parse symbol table.
772   CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64()
773                              : Obj->getSymbolTableOffset32();
774   const uint64_t SymbolTableSize =
775       static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) *
776       NumberOfSymbolTableEntries;
777   auto SymTableOrErr =
778       getObject<void *>(Data, Base + CurOffset, SymbolTableSize);
779   if (Error E = SymTableOrErr.takeError())
780     return std::move(E);
781   Obj->SymbolTblPtr = SymTableOrErr.get();
782   CurOffset += SymbolTableSize;
783 
784   // Parse String table.
785   Expected<XCOFFStringTable> StringTableOrErr =
786       parseStringTable(Obj.get(), CurOffset);
787   if (Error E = StringTableOrErr.takeError())
788     return std::move(E);
789   Obj->StringTable = StringTableOrErr.get();
790 
791   return std::move(Obj);
792 }
793 
794 Expected<std::unique_ptr<ObjectFile>>
795 ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
796                                   unsigned FileType) {
797   return XCOFFObjectFile::create(FileType, MemBufRef);
798 }
799 
800 bool XCOFFSymbolRef::isFunction() const {
801   if (!isCsectSymbol())
802     return false;
803 
804   if (getSymbolType() & FunctionSym)
805     return true;
806 
807   Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef();
808   if (!ExpCsectAuxEnt)
809     return false;
810 
811   const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get();
812 
813   // A function definition should be a label definition.
814   // FIXME: This is not necessarily the case when -ffunction-sections is
815   // enabled.
816   if (!CsectAuxRef.isLabel())
817     return false;
818 
819   if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR)
820     return false;
821 
822   const int16_t SectNum = getSectionNumber();
823   Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum);
824   if (!SI) {
825     // If we could not get the section, then this symbol should not be
826     // a function. So consume the error and return `false` to move on.
827     consumeError(SI.takeError());
828     return false;
829   }
830 
831   return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT);
832 }
833 
834 bool XCOFFSymbolRef::isCsectSymbol() const {
835   XCOFF::StorageClass SC = getStorageClass();
836   return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT ||
837           SC == XCOFF::C_HIDEXT);
838 }
839 
840 Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const {
841   assert(isCsectSymbol() &&
842          "Calling csect symbol interface with a non-csect symbol.");
843 
844   uint8_t NumberOfAuxEntries = getNumberOfAuxEntries();
845 
846   Expected<StringRef> NameOrErr = getName();
847   if (auto Err = NameOrErr.takeError())
848     return std::move(Err);
849 
850   if (!NumberOfAuxEntries) {
851     return createStringError(object_error::parse_failed,
852                              "csect symbol \"" + *NameOrErr +
853                                  "\" contains no auxiliary entry");
854   }
855 
856   if (!OwningObjectPtr->is64Bit()) {
857     // In XCOFF32, the csect auxilliary entry is always the last auxiliary
858     // entry for the symbol.
859     uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
860         getEntryAddress(), NumberOfAuxEntries);
861     return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr));
862   }
863 
864   // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type.
865   // We need to iterate through all the auxiliary entries to find it.
866   for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) {
867     uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
868         getEntryAddress(), Index);
869     if (*OwningObjectPtr->getSymbolAuxType(AuxAddr) ==
870         XCOFF::SymbolAuxType::AUX_CSECT) {
871 #ifndef NDEBUG
872       OwningObjectPtr->checkSymbolEntryPointer(AuxAddr);
873 #endif
874       return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr));
875     }
876   }
877 
878   return createStringError(
879       object_error::parse_failed,
880       "a csect auxiliary entry is not found for symbol \"" + *NameOrErr + "\"");
881 }
882 
883 Expected<StringRef> XCOFFSymbolRef::getName() const {
884   // A storage class value with the high-order bit on indicates that the name is
885   // a symbolic debugger stabstring.
886   if (getStorageClass() & 0x80)
887     return StringRef("Unimplemented Debug Name");
888 
889   if (Entry32) {
890     if (Entry32->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
891       return generateXCOFFFixedNameStringRef(Entry32->SymbolName);
892 
893     return OwningObjectPtr->getStringTableEntry(Entry32->NameInStrTbl.Offset);
894   }
895 
896   return OwningObjectPtr->getStringTableEntry(Entry64->Offset);
897 }
898 
899 // Explictly instantiate template classes.
900 template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
901 template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
902 
903 bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) {
904   if (Bytes.size() < 4)
905     return false;
906 
907   return support::endian::read32be(Bytes.data()) == 0;
908 }
909 
910 #define GETVALUEWITHMASK(X) (Data & (TracebackTable::X))
911 #define GETVALUEWITHMASKSHIFT(X, S)                                            \
912   ((Data & (TracebackTable::X)) >> (TracebackTable::S))
913 
914 Expected<TBVectorExt> TBVectorExt::create(StringRef TBvectorStrRef) {
915   Error Err = Error::success();
916   TBVectorExt TBTVecExt(TBvectorStrRef, Err);
917   if (Err)
918     return std::move(Err);
919   return TBTVecExt;
920 }
921 
922 TBVectorExt::TBVectorExt(StringRef TBvectorStrRef, Error &Err) {
923   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data());
924   Data = support::endian::read16be(Ptr);
925   uint32_t VecParmsTypeValue = support::endian::read32be(Ptr + 2);
926   unsigned ParmsNum =
927       GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift);
928 
929   ErrorAsOutParameter EAO(&Err);
930   Expected<SmallString<32>> VecParmsTypeOrError =
931       parseVectorParmsType(VecParmsTypeValue, ParmsNum);
932   if (!VecParmsTypeOrError)
933     Err = VecParmsTypeOrError.takeError();
934   else
935     VecParmsInfo = VecParmsTypeOrError.get();
936 }
937 
938 uint8_t TBVectorExt::getNumberOfVRSaved() const {
939   return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift);
940 }
941 
942 bool TBVectorExt::isVRSavedOnStack() const {
943   return GETVALUEWITHMASK(IsVRSavedOnStackMask);
944 }
945 
946 bool TBVectorExt::hasVarArgs() const {
947   return GETVALUEWITHMASK(HasVarArgsMask);
948 }
949 
950 uint8_t TBVectorExt::getNumberOfVectorParms() const {
951   return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask,
952                                NumberOfVectorParmsShift);
953 }
954 
955 bool TBVectorExt::hasVMXInstruction() const {
956   return GETVALUEWITHMASK(HasVMXInstructionMask);
957 }
958 #undef GETVALUEWITHMASK
959 #undef GETVALUEWITHMASKSHIFT
960 
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 
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   unsigned FixedParmsNum = getNumberOfFixedParms();
982   unsigned FloatingParmsNum = getNumberOfFPParms();
983   uint32_t ParamsTypeValue = 0;
984 
985   // Begin to parse optional fields.
986   if (Cur && (FixedParmsNum + FloatingParmsNum) > 0)
987     ParamsTypeValue = DE.getU32(Cur);
988 
989   if (Cur && hasTraceBackTableOffset())
990     TraceBackTableOffset = DE.getU32(Cur);
991 
992   if (Cur && isInterruptHandler())
993     HandlerMask = DE.getU32(Cur);
994 
995   if (Cur && hasControlledStorage()) {
996     NumOfCtlAnchors = DE.getU32(Cur);
997     if (Cur && NumOfCtlAnchors) {
998       SmallVector<uint32_t, 8> Disp;
999       Disp.reserve(NumOfCtlAnchors.getValue());
1000       for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I)
1001         Disp.push_back(DE.getU32(Cur));
1002       if (Cur)
1003         ControlledStorageInfoDisp = std::move(Disp);
1004     }
1005   }
1006 
1007   if (Cur && isFuncNamePresent()) {
1008     uint16_t FunctionNameLen = DE.getU16(Cur);
1009     if (Cur)
1010       FunctionName = DE.getBytes(Cur, FunctionNameLen);
1011   }
1012 
1013   if (Cur && isAllocaUsed())
1014     AllocaRegister = DE.getU8(Cur);
1015 
1016   unsigned VectorParmsNum = 0;
1017   if (Cur && hasVectorInfo()) {
1018     StringRef VectorExtRef = DE.getBytes(Cur, 6);
1019     if (Cur) {
1020       Expected<TBVectorExt> TBVecExtOrErr = TBVectorExt::create(VectorExtRef);
1021       if (!TBVecExtOrErr) {
1022         Err = TBVecExtOrErr.takeError();
1023         return;
1024       }
1025       VecExt = TBVecExtOrErr.get();
1026       VectorParmsNum = VecExt.getValue().getNumberOfVectorParms();
1027     }
1028   }
1029 
1030   // As long as there is no fixed-point or floating-point parameter, this
1031   // field remains not present even when hasVectorInfo gives true and
1032   // indicates the presence of vector parameters.
1033   if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) {
1034     Expected<SmallString<32>> ParmsTypeOrError =
1035         hasVectorInfo()
1036             ? parseParmsTypeWithVecInfo(ParamsTypeValue, FixedParmsNum,
1037                                         FloatingParmsNum, VectorParmsNum)
1038             : parseParmsType(ParamsTypeValue, FixedParmsNum, FloatingParmsNum);
1039 
1040     if (!ParmsTypeOrError) {
1041       Err = ParmsTypeOrError.takeError();
1042       return;
1043     }
1044     ParmsType = ParmsTypeOrError.get();
1045   }
1046 
1047   if (Cur && hasExtensionTable())
1048     ExtensionTable = DE.getU8(Cur);
1049 
1050   if (!Cur)
1051     Err = Cur.takeError();
1052 
1053   Size = Cur.tell();
1054 }
1055 
1056 #define GETBITWITHMASK(P, X)                                                   \
1057   (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X))
1058 #define GETBITWITHMASKSHIFT(P, X, S)                                           \
1059   ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >>           \
1060    (TracebackTable::S))
1061 
1062 uint8_t XCOFFTracebackTable::getVersion() const {
1063   return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift);
1064 }
1065 
1066 uint8_t XCOFFTracebackTable::getLanguageID() const {
1067   return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift);
1068 }
1069 
1070 bool XCOFFTracebackTable::isGlobalLinkage() const {
1071   return GETBITWITHMASK(0, IsGlobaLinkageMask);
1072 }
1073 
1074 bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const {
1075   return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask);
1076 }
1077 
1078 bool XCOFFTracebackTable::hasTraceBackTableOffset() const {
1079   return GETBITWITHMASK(0, HasTraceBackTableOffsetMask);
1080 }
1081 
1082 bool XCOFFTracebackTable::isInternalProcedure() const {
1083   return GETBITWITHMASK(0, IsInternalProcedureMask);
1084 }
1085 
1086 bool XCOFFTracebackTable::hasControlledStorage() const {
1087   return GETBITWITHMASK(0, HasControlledStorageMask);
1088 }
1089 
1090 bool XCOFFTracebackTable::isTOCless() const {
1091   return GETBITWITHMASK(0, IsTOClessMask);
1092 }
1093 
1094 bool XCOFFTracebackTable::isFloatingPointPresent() const {
1095   return GETBITWITHMASK(0, IsFloatingPointPresentMask);
1096 }
1097 
1098 bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const {
1099   return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask);
1100 }
1101 
1102 bool XCOFFTracebackTable::isInterruptHandler() const {
1103   return GETBITWITHMASK(0, IsInterruptHandlerMask);
1104 }
1105 
1106 bool XCOFFTracebackTable::isFuncNamePresent() const {
1107   return GETBITWITHMASK(0, IsFunctionNamePresentMask);
1108 }
1109 
1110 bool XCOFFTracebackTable::isAllocaUsed() const {
1111   return GETBITWITHMASK(0, IsAllocaUsedMask);
1112 }
1113 
1114 uint8_t XCOFFTracebackTable::getOnConditionDirective() const {
1115   return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask,
1116                              OnConditionDirectiveShift);
1117 }
1118 
1119 bool XCOFFTracebackTable::isCRSaved() const {
1120   return GETBITWITHMASK(0, IsCRSavedMask);
1121 }
1122 
1123 bool XCOFFTracebackTable::isLRSaved() const {
1124   return GETBITWITHMASK(0, IsLRSavedMask);
1125 }
1126 
1127 bool XCOFFTracebackTable::isBackChainStored() const {
1128   return GETBITWITHMASK(4, IsBackChainStoredMask);
1129 }
1130 
1131 bool XCOFFTracebackTable::isFixup() const {
1132   return GETBITWITHMASK(4, IsFixupMask);
1133 }
1134 
1135 uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const {
1136   return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift);
1137 }
1138 
1139 bool XCOFFTracebackTable::hasExtensionTable() const {
1140   return GETBITWITHMASK(4, HasExtensionTableMask);
1141 }
1142 
1143 bool XCOFFTracebackTable::hasVectorInfo() const {
1144   return GETBITWITHMASK(4, HasVectorInfoMask);
1145 }
1146 
1147 uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const {
1148   return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift);
1149 }
1150 
1151 uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const {
1152   return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask,
1153                              NumberOfFixedParmsShift);
1154 }
1155 
1156 uint8_t XCOFFTracebackTable::getNumberOfFPParms() const {
1157   return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask,
1158                              NumberOfFloatingPointParmsShift);
1159 }
1160 
1161 bool XCOFFTracebackTable::hasParmsOnStack() const {
1162   return GETBITWITHMASK(4, HasParmsOnStackMask);
1163 }
1164 
1165 #undef GETBITWITHMASK
1166 #undef GETBITWITHMASKSHIFT
1167 } // namespace object
1168 } // namespace llvm
1169