XCOFFObjectFile.cpp 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135
  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. #include "llvm/Object/XCOFFObjectFile.h"
  13. #include "llvm/MC/SubtargetFeature.h"
  14. #include "llvm/Support/DataExtractor.h"
  15. #include <cstddef>
  16. #include <cstring>
  17. namespace llvm {
  18. using namespace XCOFF;
  19. namespace object {
  20. static const uint8_t FunctionSym = 0x20;
  21. static const uint8_t SymTypeMask = 0x07;
  22. static const uint16_t NoRelMask = 0x0001;
  23. // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
  24. // 'M'. Returns a pointer to the underlying object on success.
  25. template <typename T>
  26. static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr,
  27. const uint64_t Size = sizeof(T)) {
  28. uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr);
  29. if (Error E = Binary::checkOffset(M, Addr, Size))
  30. return std::move(E);
  31. return reinterpret_cast<const T *>(Addr);
  32. }
  33. static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) {
  34. return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) +
  35. Offset);
  36. }
  37. template <typename T> static const T *viewAs(uintptr_t in) {
  38. return reinterpret_cast<const T *>(in);
  39. }
  40. static StringRef generateXCOFFFixedNameStringRef(const char *Name) {
  41. auto NulCharPtr =
  42. static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize));
  43. return NulCharPtr ? StringRef(Name, NulCharPtr - Name)
  44. : StringRef(Name, XCOFF::NameSize);
  45. }
  46. template <typename T> StringRef XCOFFSectionHeader<T>::getName() const {
  47. const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
  48. return generateXCOFFFixedNameStringRef(DerivedXCOFFSectionHeader.Name);
  49. }
  50. template <typename T> uint16_t XCOFFSectionHeader<T>::getSectionType() const {
  51. const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
  52. return DerivedXCOFFSectionHeader.Flags & SectionFlagsTypeMask;
  53. }
  54. template <typename T>
  55. bool XCOFFSectionHeader<T>::isReservedSectionType() const {
  56. return getSectionType() & SectionFlagsReservedMask;
  57. }
  58. bool XCOFFRelocation32::isRelocationSigned() const {
  59. return Info & XR_SIGN_INDICATOR_MASK;
  60. }
  61. bool XCOFFRelocation32::isFixupIndicated() const {
  62. return Info & XR_FIXUP_INDICATOR_MASK;
  63. }
  64. uint8_t XCOFFRelocation32::getRelocatedLength() const {
  65. // The relocation encodes the bit length being relocated minus 1. Add back
  66. // the 1 to get the actual length being relocated.
  67. return (Info & XR_BIASED_LENGTH_MASK) + 1;
  68. }
  69. void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
  70. uintptr_t TableAddress) const {
  71. if (Addr < TableAddress)
  72. report_fatal_error("Section header outside of section header table.");
  73. uintptr_t Offset = Addr - TableAddress;
  74. if (Offset >= getSectionHeaderSize() * getNumberOfSections())
  75. report_fatal_error("Section header outside of section header table.");
  76. if (Offset % getSectionHeaderSize() != 0)
  77. report_fatal_error(
  78. "Section header pointer does not point to a valid section header.");
  79. }
  80. const XCOFFSectionHeader32 *
  81. XCOFFObjectFile::toSection32(DataRefImpl Ref) const {
  82. assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
  83. #ifndef NDEBUG
  84. checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
  85. #endif
  86. return viewAs<XCOFFSectionHeader32>(Ref.p);
  87. }
  88. const XCOFFSectionHeader64 *
  89. XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
  90. assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
  91. #ifndef NDEBUG
  92. checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
  93. #endif
  94. return viewAs<XCOFFSectionHeader64>(Ref.p);
  95. }
  96. const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const {
  97. assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
  98. assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!");
  99. #ifndef NDEBUG
  100. checkSymbolEntryPointer(Ref.p);
  101. #endif
  102. auto SymEntPtr = viewAs<XCOFFSymbolEntry>(Ref.p);
  103. return SymEntPtr;
  104. }
  105. const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
  106. assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
  107. return static_cast<const XCOFFFileHeader32 *>(FileHeader);
  108. }
  109. const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
  110. assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
  111. return static_cast<const XCOFFFileHeader64 *>(FileHeader);
  112. }
  113. const XCOFFSectionHeader32 *
  114. XCOFFObjectFile::sectionHeaderTable32() const {
  115. assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
  116. return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
  117. }
  118. const XCOFFSectionHeader64 *
  119. XCOFFObjectFile::sectionHeaderTable64() const {
  120. assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
  121. return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
  122. }
  123. void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
  124. const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
  125. SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1;
  126. #ifndef NDEBUG
  127. // This function is used by basic_symbol_iterator, which allows to
  128. // point to the end-of-symbol-table address.
  129. if (reinterpret_cast<uintptr_t>(SymEntPtr) != getEndOfSymbolTableAddress())
  130. checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(SymEntPtr));
  131. #endif
  132. Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr);
  133. }
  134. Expected<StringRef>
  135. XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const {
  136. // The byte offset is relative to the start of the string table.
  137. // A byte offset value of 0 is a null or zero-length symbol
  138. // name. A byte offset in the range 1 to 3 (inclusive) points into the length
  139. // field; as a soft-error recovery mechanism, we treat such cases as having an
  140. // offset of 0.
  141. if (Offset < 4)
  142. return StringRef(nullptr, 0);
  143. if (StringTable.Data != nullptr && StringTable.Size > Offset)
  144. return (StringTable.Data + Offset);
  145. return make_error<GenericBinaryError>("Bad offset for string table entry",
  146. object_error::parse_failed);
  147. }
  148. Expected<StringRef>
  149. XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const {
  150. if (CFileEntPtr->NameInStrTbl.Magic !=
  151. XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
  152. return generateXCOFFFixedNameStringRef(CFileEntPtr->Name);
  153. return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset);
  154. }
  155. Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
  156. const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
  157. // A storage class value with the high-order bit on indicates that the name is
  158. // a symbolic debugger stabstring.
  159. if (SymEntPtr->StorageClass & 0x80)
  160. return StringRef("Unimplemented Debug Name");
  161. if (SymEntPtr->NameInStrTbl.Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
  162. return generateXCOFFFixedNameStringRef(SymEntPtr->SymbolName);
  163. return getStringTableEntry(SymEntPtr->NameInStrTbl.Offset);
  164. }
  165. Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
  166. assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
  167. return toSymbolEntry(Symb)->Value;
  168. }
  169. uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
  170. assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
  171. return toSymbolEntry(Symb)->Value;
  172. }
  173. uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
  174. uint64_t Result = 0;
  175. llvm_unreachable("Not yet implemented!");
  176. return Result;
  177. }
  178. Expected<SymbolRef::Type>
  179. XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
  180. llvm_unreachable("Not yet implemented!");
  181. return SymbolRef::ST_Other;
  182. }
  183. Expected<section_iterator>
  184. XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
  185. const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
  186. int16_t SectNum = SymEntPtr->SectionNumber;
  187. if (isReservedSectionNumber(SectNum))
  188. return section_end();
  189. Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum);
  190. if (!ExpSec)
  191. return ExpSec.takeError();
  192. return section_iterator(SectionRef(ExpSec.get(), this));
  193. }
  194. void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
  195. const char *Ptr = reinterpret_cast<const char *>(Sec.p);
  196. Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize());
  197. }
  198. Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
  199. return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec));
  200. }
  201. uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
  202. // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
  203. // with MSVC.
  204. if (is64Bit())
  205. return toSection64(Sec)->VirtualAddress;
  206. return toSection32(Sec)->VirtualAddress;
  207. }
  208. uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
  209. // Section numbers in XCOFF are numbered beginning at 1. A section number of
  210. // zero is used to indicate that a symbol is being imported or is undefined.
  211. if (is64Bit())
  212. return toSection64(Sec) - sectionHeaderTable64() + 1;
  213. else
  214. return toSection32(Sec) - sectionHeaderTable32() + 1;
  215. }
  216. uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
  217. // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
  218. // with MSVC.
  219. if (is64Bit())
  220. return toSection64(Sec)->SectionSize;
  221. return toSection32(Sec)->SectionSize;
  222. }
  223. Expected<ArrayRef<uint8_t>>
  224. XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
  225. if (isSectionVirtual(Sec))
  226. return ArrayRef<uint8_t>();
  227. uint64_t OffsetToRaw;
  228. if (is64Bit())
  229. OffsetToRaw = toSection64(Sec)->FileOffsetToRawData;
  230. else
  231. OffsetToRaw = toSection32(Sec)->FileOffsetToRawData;
  232. const uint8_t * ContentStart = base() + OffsetToRaw;
  233. uint64_t SectionSize = getSectionSize(Sec);
  234. if (checkOffset(Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize))
  235. return make_error<BinaryError>();
  236. return makeArrayRef(ContentStart,SectionSize);
  237. }
  238. uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
  239. uint64_t Result = 0;
  240. llvm_unreachable("Not yet implemented!");
  241. return Result;
  242. }
  243. bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
  244. bool Result = false;
  245. llvm_unreachable("Not yet implemented!");
  246. return Result;
  247. }
  248. bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
  249. return getSectionFlags(Sec) & XCOFF::STYP_TEXT;
  250. }
  251. bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
  252. uint32_t Flags = getSectionFlags(Sec);
  253. return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
  254. }
  255. bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
  256. uint32_t Flags = getSectionFlags(Sec);
  257. return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
  258. }
  259. bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
  260. return is64Bit() ? toSection64(Sec)->FileOffsetToRawData == 0
  261. : toSection32(Sec)->FileOffsetToRawData == 0;
  262. }
  263. relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
  264. if (is64Bit())
  265. report_fatal_error("64-bit support not implemented yet");
  266. const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
  267. auto RelocationsOrErr = relocations(*SectionEntPtr);
  268. if (Error E = RelocationsOrErr.takeError())
  269. return relocation_iterator(RelocationRef());
  270. DataRefImpl Ret;
  271. Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
  272. return relocation_iterator(RelocationRef(Ret, this));
  273. }
  274. relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const {
  275. if (is64Bit())
  276. report_fatal_error("64-bit support not implemented yet");
  277. const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
  278. auto RelocationsOrErr = relocations(*SectionEntPtr);
  279. if (Error E = RelocationsOrErr.takeError())
  280. return relocation_iterator(RelocationRef());
  281. DataRefImpl Ret;
  282. Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
  283. return relocation_iterator(RelocationRef(Ret, this));
  284. }
  285. void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
  286. Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1);
  287. }
  288. uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
  289. if (is64Bit())
  290. report_fatal_error("64-bit support not implemented yet");
  291. const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
  292. const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32();
  293. const uint32_t RelocAddress = Reloc->VirtualAddress;
  294. const uint16_t NumberOfSections = getNumberOfSections();
  295. for (uint16_t i = 0; i < NumberOfSections; ++i) {
  296. // Find which section this relocation is belonging to, and get the
  297. // relocation offset relative to the start of the section.
  298. if (Sec32->VirtualAddress <= RelocAddress &&
  299. RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) {
  300. return RelocAddress - Sec32->VirtualAddress;
  301. }
  302. ++Sec32;
  303. }
  304. return InvalidRelocOffset;
  305. }
  306. symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
  307. if (is64Bit())
  308. report_fatal_error("64-bit support not implemented yet");
  309. const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
  310. const uint32_t Index = Reloc->SymbolIndex;
  311. if (Index >= getLogicalNumberOfSymbolTableEntries32())
  312. return symbol_end();
  313. DataRefImpl SymDRI;
  314. SymDRI.p = reinterpret_cast<uintptr_t>(getPointerToSymbolTable() + Index);
  315. return symbol_iterator(SymbolRef(SymDRI, this));
  316. }
  317. uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const {
  318. if (is64Bit())
  319. report_fatal_error("64-bit support not implemented yet");
  320. return viewAs<XCOFFRelocation32>(Rel.p)->Type;
  321. }
  322. void XCOFFObjectFile::getRelocationTypeName(
  323. DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
  324. if (is64Bit())
  325. report_fatal_error("64-bit support not implemented yet");
  326. const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
  327. StringRef Res = XCOFF::getRelocationTypeString(Reloc->Type);
  328. Result.append(Res.begin(), Res.end());
  329. }
  330. Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
  331. uint32_t Result = 0;
  332. llvm_unreachable("Not yet implemented!");
  333. return Result;
  334. }
  335. basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
  336. if (is64Bit())
  337. report_fatal_error("64-bit support not implemented yet");
  338. DataRefImpl SymDRI;
  339. SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
  340. return basic_symbol_iterator(SymbolRef(SymDRI, this));
  341. }
  342. basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
  343. if (is64Bit())
  344. report_fatal_error("64-bit support not implemented yet");
  345. DataRefImpl SymDRI;
  346. SymDRI.p = reinterpret_cast<uintptr_t>(
  347. SymbolTblPtr + getLogicalNumberOfSymbolTableEntries32());
  348. return basic_symbol_iterator(SymbolRef(SymDRI, this));
  349. }
  350. section_iterator XCOFFObjectFile::section_begin() const {
  351. DataRefImpl DRI;
  352. DRI.p = getSectionHeaderTableAddress();
  353. return section_iterator(SectionRef(DRI, this));
  354. }
  355. section_iterator XCOFFObjectFile::section_end() const {
  356. DataRefImpl DRI;
  357. DRI.p = getWithOffset(getSectionHeaderTableAddress(),
  358. getNumberOfSections() * getSectionHeaderSize());
  359. return section_iterator(SectionRef(DRI, this));
  360. }
  361. uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; }
  362. StringRef XCOFFObjectFile::getFileFormatName() const {
  363. return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000";
  364. }
  365. Triple::ArchType XCOFFObjectFile::getArch() const {
  366. return is64Bit() ? Triple::ppc64 : Triple::ppc;
  367. }
  368. SubtargetFeatures XCOFFObjectFile::getFeatures() const {
  369. return SubtargetFeatures();
  370. }
  371. bool XCOFFObjectFile::isRelocatableObject() const {
  372. if (is64Bit())
  373. report_fatal_error("64-bit support not implemented yet");
  374. return !(fileHeader32()->Flags & NoRelMask);
  375. }
  376. Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
  377. // TODO FIXME Should get from auxiliary_header->o_entry when support for the
  378. // auxiliary_header is added.
  379. return 0;
  380. }
  381. size_t XCOFFObjectFile::getFileHeaderSize() const {
  382. return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32);
  383. }
  384. size_t XCOFFObjectFile::getSectionHeaderSize() const {
  385. return is64Bit() ? sizeof(XCOFFSectionHeader64) :
  386. sizeof(XCOFFSectionHeader32);
  387. }
  388. bool XCOFFObjectFile::is64Bit() const {
  389. return Binary::ID_XCOFF64 == getType();
  390. }
  391. uint16_t XCOFFObjectFile::getMagic() const {
  392. return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic;
  393. }
  394. Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
  395. if (Num <= 0 || Num > getNumberOfSections())
  396. return errorCodeToError(object_error::invalid_section_index);
  397. DataRefImpl DRI;
  398. DRI.p = getWithOffset(getSectionHeaderTableAddress(),
  399. getSectionHeaderSize() * (Num - 1));
  400. return DRI;
  401. }
  402. Expected<StringRef>
  403. XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const {
  404. assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
  405. int16_t SectionNum = SymEntPtr->SectionNumber;
  406. switch (SectionNum) {
  407. case XCOFF::N_DEBUG:
  408. return "N_DEBUG";
  409. case XCOFF::N_ABS:
  410. return "N_ABS";
  411. case XCOFF::N_UNDEF:
  412. return "N_UNDEF";
  413. default:
  414. Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
  415. if (SecRef)
  416. return generateXCOFFFixedNameStringRef(
  417. getSectionNameInternal(SecRef.get()));
  418. return SecRef.takeError();
  419. }
  420. }
  421. bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) {
  422. return (SectionNumber <= 0 && SectionNumber >= -2);
  423. }
  424. uint16_t XCOFFObjectFile::getNumberOfSections() const {
  425. return is64Bit() ? fileHeader64()->NumberOfSections
  426. : fileHeader32()->NumberOfSections;
  427. }
  428. int32_t XCOFFObjectFile::getTimeStamp() const {
  429. return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp;
  430. }
  431. uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
  432. return is64Bit() ? fileHeader64()->AuxHeaderSize
  433. : fileHeader32()->AuxHeaderSize;
  434. }
  435. uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
  436. return fileHeader32()->SymbolTableOffset;
  437. }
  438. int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const {
  439. // As far as symbol table size is concerned, if this field is negative it is
  440. // to be treated as a 0. However since this field is also used for printing we
  441. // don't want to truncate any negative values.
  442. return fileHeader32()->NumberOfSymTableEntries;
  443. }
  444. uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
  445. return (fileHeader32()->NumberOfSymTableEntries >= 0
  446. ? fileHeader32()->NumberOfSymTableEntries
  447. : 0);
  448. }
  449. uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
  450. return fileHeader64()->SymbolTableOffset;
  451. }
  452. uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
  453. return fileHeader64()->NumberOfSymTableEntries;
  454. }
  455. uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const {
  456. uint32_t NumberOfSymTableEntries =
  457. is64Bit() ? getNumberOfSymbolTableEntries64()
  458. : getLogicalNumberOfSymbolTableEntries32();
  459. return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr),
  460. XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries);
  461. }
  462. void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const {
  463. if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr))
  464. report_fatal_error("Symbol table entry is outside of symbol table.");
  465. if (SymbolEntPtr >= getEndOfSymbolTableAddress())
  466. report_fatal_error("Symbol table entry is outside of symbol table.");
  467. ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) -
  468. reinterpret_cast<const char *>(SymbolTblPtr);
  469. if (Offset % XCOFF::SymbolTableEntrySize != 0)
  470. report_fatal_error(
  471. "Symbol table entry position is not valid inside of symbol table.");
  472. }
  473. uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const {
  474. return (reinterpret_cast<const char *>(SymbolEntPtr) -
  475. reinterpret_cast<const char *>(SymbolTblPtr)) /
  476. XCOFF::SymbolTableEntrySize;
  477. }
  478. Expected<StringRef>
  479. XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const {
  480. if (is64Bit())
  481. report_fatal_error("64-bit symbol table support not implemented yet.");
  482. if (Index >= getLogicalNumberOfSymbolTableEntries32())
  483. return errorCodeToError(object_error::invalid_symbol_index);
  484. DataRefImpl SymDRI;
  485. SymDRI.p = reinterpret_cast<uintptr_t>(getPointerToSymbolTable() + Index);
  486. return getSymbolName(SymDRI);
  487. }
  488. uint16_t XCOFFObjectFile::getFlags() const {
  489. return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
  490. }
  491. const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const {
  492. return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name;
  493. }
  494. uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
  495. return reinterpret_cast<uintptr_t>(SectionHeaderTable);
  496. }
  497. int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const {
  498. return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags;
  499. }
  500. XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object)
  501. : ObjectFile(Type, Object) {
  502. assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64);
  503. }
  504. ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const {
  505. assert(is64Bit() && "64-bit interface called for non 64-bit file.");
  506. const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64();
  507. return ArrayRef<XCOFFSectionHeader64>(TablePtr,
  508. TablePtr + getNumberOfSections());
  509. }
  510. ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const {
  511. assert(!is64Bit() && "32-bit interface called for non 32-bit file.");
  512. const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32();
  513. return ArrayRef<XCOFFSectionHeader32>(TablePtr,
  514. TablePtr + getNumberOfSections());
  515. }
  516. // In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO
  517. // section header contains the actual count of relocation entries in the s_paddr
  518. // field. STYP_OVRFLO headers contain the section index of their corresponding
  519. // sections as their raw "NumberOfRelocations" field value.
  520. Expected<uint32_t> XCOFFObjectFile::getLogicalNumberOfRelocationEntries(
  521. const XCOFFSectionHeader32 &Sec) const {
  522. uint16_t SectionIndex = &Sec - sectionHeaderTable32() + 1;
  523. if (Sec.NumberOfRelocations < XCOFF::RelocOverflow)
  524. return Sec.NumberOfRelocations;
  525. for (const auto &Sec : sections32()) {
  526. if (Sec.Flags == XCOFF::STYP_OVRFLO &&
  527. Sec.NumberOfRelocations == SectionIndex)
  528. return Sec.PhysicalAddress;
  529. }
  530. return errorCodeToError(object_error::parse_failed);
  531. }
  532. Expected<ArrayRef<XCOFFRelocation32>>
  533. XCOFFObjectFile::relocations(const XCOFFSectionHeader32 &Sec) const {
  534. uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader),
  535. Sec.FileOffsetToRelocationInfo);
  536. auto NumRelocEntriesOrErr = getLogicalNumberOfRelocationEntries(Sec);
  537. if (Error E = NumRelocEntriesOrErr.takeError())
  538. return std::move(E);
  539. uint32_t NumRelocEntries = NumRelocEntriesOrErr.get();
  540. static_assert(
  541. sizeof(XCOFFRelocation32) == XCOFF::RelocationSerializationSize32, "");
  542. auto RelocationOrErr =
  543. getObject<XCOFFRelocation32>(Data, reinterpret_cast<void *>(RelocAddr),
  544. NumRelocEntries * sizeof(XCOFFRelocation32));
  545. if (Error E = RelocationOrErr.takeError())
  546. return std::move(E);
  547. const XCOFFRelocation32 *StartReloc = RelocationOrErr.get();
  548. return ArrayRef<XCOFFRelocation32>(StartReloc, StartReloc + NumRelocEntries);
  549. }
  550. Expected<XCOFFStringTable>
  551. XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
  552. // If there is a string table, then the buffer must contain at least 4 bytes
  553. // for the string table's size. Not having a string table is not an error.
  554. if (Error E = Binary::checkOffset(
  555. Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) {
  556. consumeError(std::move(E));
  557. return XCOFFStringTable{0, nullptr};
  558. }
  559. // Read the size out of the buffer.
  560. uint32_t Size = support::endian::read32be(Obj->base() + Offset);
  561. // If the size is less then 4, then the string table is just a size and no
  562. // string data.
  563. if (Size <= 4)
  564. return XCOFFStringTable{4, nullptr};
  565. auto StringTableOrErr =
  566. getObject<char>(Obj->Data, Obj->base() + Offset, Size);
  567. if (Error E = StringTableOrErr.takeError())
  568. return std::move(E);
  569. const char *StringTablePtr = StringTableOrErr.get();
  570. if (StringTablePtr[Size - 1] != '\0')
  571. return errorCodeToError(object_error::string_table_non_null_end);
  572. return XCOFFStringTable{Size, StringTablePtr};
  573. }
  574. Expected<std::unique_ptr<XCOFFObjectFile>>
  575. XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
  576. // Can't use std::make_unique because of the private constructor.
  577. std::unique_ptr<XCOFFObjectFile> Obj;
  578. Obj.reset(new XCOFFObjectFile(Type, MBR));
  579. uint64_t CurOffset = 0;
  580. const auto *Base = Obj->base();
  581. MemoryBufferRef Data = Obj->Data;
  582. // Parse file header.
  583. auto FileHeaderOrErr =
  584. getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize());
  585. if (Error E = FileHeaderOrErr.takeError())
  586. return std::move(E);
  587. Obj->FileHeader = FileHeaderOrErr.get();
  588. CurOffset += Obj->getFileHeaderSize();
  589. // TODO FIXME we don't have support for an optional header yet, so just skip
  590. // past it.
  591. CurOffset += Obj->getOptionalHeaderSize();
  592. // Parse the section header table if it is present.
  593. if (Obj->getNumberOfSections()) {
  594. auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset,
  595. Obj->getNumberOfSections() *
  596. Obj->getSectionHeaderSize());
  597. if (Error E = SecHeadersOrErr.takeError())
  598. return std::move(E);
  599. Obj->SectionHeaderTable = SecHeadersOrErr.get();
  600. }
  601. // 64-bit object supports only file header and section headers for now.
  602. if (Obj->is64Bit())
  603. return std::move(Obj);
  604. // If there is no symbol table we are done parsing the memory buffer.
  605. if (Obj->getLogicalNumberOfSymbolTableEntries32() == 0)
  606. return std::move(Obj);
  607. // Parse symbol table.
  608. CurOffset = Obj->fileHeader32()->SymbolTableOffset;
  609. uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) *
  610. Obj->getLogicalNumberOfSymbolTableEntries32();
  611. auto SymTableOrErr =
  612. getObject<XCOFFSymbolEntry>(Data, Base + CurOffset, SymbolTableSize);
  613. if (Error E = SymTableOrErr.takeError())
  614. return std::move(E);
  615. Obj->SymbolTblPtr = SymTableOrErr.get();
  616. CurOffset += SymbolTableSize;
  617. // Parse String table.
  618. Expected<XCOFFStringTable> StringTableOrErr =
  619. parseStringTable(Obj.get(), CurOffset);
  620. if (Error E = StringTableOrErr.takeError())
  621. return std::move(E);
  622. Obj->StringTable = StringTableOrErr.get();
  623. return std::move(Obj);
  624. }
  625. Expected<std::unique_ptr<ObjectFile>>
  626. ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
  627. unsigned FileType) {
  628. return XCOFFObjectFile::create(FileType, MemBufRef);
  629. }
  630. XCOFF::StorageClass XCOFFSymbolRef::getStorageClass() const {
  631. return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->StorageClass;
  632. }
  633. uint8_t XCOFFSymbolRef::getNumberOfAuxEntries() const {
  634. return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->NumberOfAuxEntries;
  635. }
  636. // TODO: The function needs to return an error if there is no csect auxiliary
  637. // entry.
  638. const XCOFFCsectAuxEnt32 *XCOFFSymbolRef::getXCOFFCsectAuxEnt32() const {
  639. assert(!OwningObjectPtr->is64Bit() &&
  640. "32-bit interface called on 64-bit object file.");
  641. assert(hasCsectAuxEnt() && "No Csect Auxiliary Entry is found.");
  642. // In XCOFF32, the csect auxilliary entry is always the last auxiliary
  643. // entry for the symbol.
  644. uintptr_t AuxAddr = getWithOffset(
  645. SymEntDataRef.p, XCOFF::SymbolTableEntrySize * getNumberOfAuxEntries());
  646. #ifndef NDEBUG
  647. OwningObjectPtr->checkSymbolEntryPointer(AuxAddr);
  648. #endif
  649. return reinterpret_cast<const XCOFFCsectAuxEnt32 *>(AuxAddr);
  650. }
  651. uint16_t XCOFFSymbolRef::getType() const {
  652. return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SymbolType;
  653. }
  654. int16_t XCOFFSymbolRef::getSectionNumber() const {
  655. return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SectionNumber;
  656. }
  657. // TODO: The function name needs to be changed to express the purpose of the
  658. // function.
  659. bool XCOFFSymbolRef::hasCsectAuxEnt() const {
  660. XCOFF::StorageClass SC = getStorageClass();
  661. return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT ||
  662. SC == XCOFF::C_HIDEXT);
  663. }
  664. bool XCOFFSymbolRef::isFunction() const {
  665. if (OwningObjectPtr->is64Bit())
  666. report_fatal_error("64-bit support is unimplemented yet.");
  667. if (getType() & FunctionSym)
  668. return true;
  669. if (!hasCsectAuxEnt())
  670. return false;
  671. const XCOFFCsectAuxEnt32 *CsectAuxEnt = getXCOFFCsectAuxEnt32();
  672. // A function definition should be a label definition.
  673. if ((CsectAuxEnt->SymbolAlignmentAndType & SymTypeMask) != XCOFF::XTY_LD)
  674. return false;
  675. if (CsectAuxEnt->StorageMappingClass != XCOFF::XMC_PR)
  676. return false;
  677. int16_t SectNum = getSectionNumber();
  678. Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum);
  679. if (!SI)
  680. return false;
  681. return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT);
  682. }
  683. // Explictly instantiate template classes.
  684. template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
  685. template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
  686. bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) {
  687. if (Bytes.size() < 4)
  688. return false;
  689. return support::endian::read32be(Bytes.data()) == 0;
  690. }
  691. TBVectorExt::TBVectorExt(StringRef TBvectorStrRef) {
  692. const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data());
  693. Data = support::endian::read16be(Ptr);
  694. VecParmsInfo = support::endian::read32be(Ptr + 2);
  695. }
  696. #define GETVALUEWITHMASK(X) (Data & (TracebackTable::X))
  697. #define GETVALUEWITHMASKSHIFT(X, S) \
  698. ((Data & (TracebackTable::X)) >> (TracebackTable::S))
  699. uint8_t TBVectorExt::getNumberOfVRSaved() const {
  700. return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift);
  701. }
  702. bool TBVectorExt::isVRSavedOnStack() const {
  703. return GETVALUEWITHMASK(IsVRSavedOnStackMask);
  704. }
  705. bool TBVectorExt::hasVarArgs() const {
  706. return GETVALUEWITHMASK(HasVarArgsMask);
  707. }
  708. uint8_t TBVectorExt::getNumberOfVectorParms() const {
  709. return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask,
  710. NumberOfVectorParmsShift);
  711. }
  712. bool TBVectorExt::hasVMXInstruction() const {
  713. return GETVALUEWITHMASK(HasVMXInstructionMask);
  714. }
  715. #undef GETVALUEWITHMASK
  716. #undef GETVALUEWITHMASKSHIFT
  717. SmallString<32> TBVectorExt::getVectorParmsInfoString() const {
  718. SmallString<32> ParmsType;
  719. uint32_t Value = VecParmsInfo;
  720. for (uint8_t I = 0; I < getNumberOfVectorParms(); ++I) {
  721. if (I != 0)
  722. ParmsType += ", ";
  723. switch (Value & TracebackTable::ParmTypeMask) {
  724. case TracebackTable::ParmTypeIsVectorCharBit:
  725. ParmsType += "vc";
  726. break;
  727. case TracebackTable::ParmTypeIsVectorShortBit:
  728. ParmsType += "vs";
  729. break;
  730. case TracebackTable::ParmTypeIsVectorIntBit:
  731. ParmsType += "vi";
  732. break;
  733. case TracebackTable::ParmTypeIsVectorFloatBit:
  734. ParmsType += "vf";
  735. break;
  736. }
  737. Value <<= 2;
  738. }
  739. return ParmsType;
  740. }
  741. static SmallString<32> parseParmsTypeWithVecInfo(uint32_t Value,
  742. unsigned int ParmsNum) {
  743. SmallString<32> ParmsType;
  744. unsigned I = 0;
  745. bool Begin = false;
  746. while (I < ParmsNum || Value) {
  747. if (Begin)
  748. ParmsType += ", ";
  749. else
  750. Begin = true;
  751. switch (Value & TracebackTable::ParmTypeMask) {
  752. case TracebackTable::ParmTypeIsFixedBits:
  753. ParmsType += "i";
  754. ++I;
  755. break;
  756. case TracebackTable::ParmTypeIsVectorBits:
  757. ParmsType += "v";
  758. break;
  759. case TracebackTable::ParmTypeIsFloatingBits:
  760. ParmsType += "f";
  761. ++I;
  762. break;
  763. case TracebackTable::ParmTypeIsDoubleBits:
  764. ParmsType += "d";
  765. ++I;
  766. break;
  767. default:
  768. assert(false && "Unrecognized bits in ParmsType.");
  769. }
  770. Value <<= 2;
  771. }
  772. assert(I == ParmsNum &&
  773. "The total parameters number of fixed-point or floating-point "
  774. "parameters not equal to the number in the parameter type!");
  775. return ParmsType;
  776. }
  777. Expected<XCOFFTracebackTable> XCOFFTracebackTable::create(const uint8_t *Ptr,
  778. uint64_t &Size) {
  779. Error Err = Error::success();
  780. XCOFFTracebackTable TBT(Ptr, Size, Err);
  781. if (Err)
  782. return std::move(Err);
  783. return TBT;
  784. }
  785. XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
  786. Error &Err)
  787. : TBPtr(Ptr) {
  788. ErrorAsOutParameter EAO(&Err);
  789. DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false,
  790. /*AddressSize=*/0);
  791. DataExtractor::Cursor Cur(/*Offset=*/0);
  792. // Skip 8 bytes of mandatory fields.
  793. DE.getU64(Cur);
  794. // Begin to parse optional fields.
  795. if (Cur) {
  796. unsigned ParmNum = getNumberOfFixedParms() + getNumberOfFPParms();
  797. // As long as there are no "fixed-point" or floating-point parameters, this
  798. // field remains not present even when hasVectorInfo gives true and
  799. // indicates the presence of vector parameters.
  800. if (ParmNum > 0) {
  801. uint32_t ParamsTypeValue = DE.getU32(Cur);
  802. if (Cur)
  803. ParmsType = hasVectorInfo()
  804. ? parseParmsTypeWithVecInfo(ParamsTypeValue, ParmNum)
  805. : parseParmsType(ParamsTypeValue, ParmNum);
  806. }
  807. }
  808. if (Cur && hasTraceBackTableOffset())
  809. TraceBackTableOffset = DE.getU32(Cur);
  810. if (Cur && isInterruptHandler())
  811. HandlerMask = DE.getU32(Cur);
  812. if (Cur && hasControlledStorage()) {
  813. NumOfCtlAnchors = DE.getU32(Cur);
  814. if (Cur && NumOfCtlAnchors) {
  815. SmallVector<uint32_t, 8> Disp;
  816. Disp.reserve(NumOfCtlAnchors.getValue());
  817. for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I)
  818. Disp.push_back(DE.getU32(Cur));
  819. if (Cur)
  820. ControlledStorageInfoDisp = std::move(Disp);
  821. }
  822. }
  823. if (Cur && isFuncNamePresent()) {
  824. uint16_t FunctionNameLen = DE.getU16(Cur);
  825. if (Cur)
  826. FunctionName = DE.getBytes(Cur, FunctionNameLen);
  827. }
  828. if (Cur && isAllocaUsed())
  829. AllocaRegister = DE.getU8(Cur);
  830. if (Cur && hasVectorInfo()) {
  831. StringRef VectorExtRef = DE.getBytes(Cur, 6);
  832. if (Cur)
  833. VecExt = TBVectorExt(VectorExtRef);
  834. }
  835. if (Cur && hasExtensionTable())
  836. ExtensionTable = DE.getU8(Cur);
  837. if (!Cur)
  838. Err = Cur.takeError();
  839. Size = Cur.tell();
  840. }
  841. #define GETBITWITHMASK(P, X) \
  842. (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X))
  843. #define GETBITWITHMASKSHIFT(P, X, S) \
  844. ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >> \
  845. (TracebackTable::S))
  846. uint8_t XCOFFTracebackTable::getVersion() const {
  847. return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift);
  848. }
  849. uint8_t XCOFFTracebackTable::getLanguageID() const {
  850. return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift);
  851. }
  852. bool XCOFFTracebackTable::isGlobalLinkage() const {
  853. return GETBITWITHMASK(0, IsGlobaLinkageMask);
  854. }
  855. bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const {
  856. return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask);
  857. }
  858. bool XCOFFTracebackTable::hasTraceBackTableOffset() const {
  859. return GETBITWITHMASK(0, HasTraceBackTableOffsetMask);
  860. }
  861. bool XCOFFTracebackTable::isInternalProcedure() const {
  862. return GETBITWITHMASK(0, IsInternalProcedureMask);
  863. }
  864. bool XCOFFTracebackTable::hasControlledStorage() const {
  865. return GETBITWITHMASK(0, HasControlledStorageMask);
  866. }
  867. bool XCOFFTracebackTable::isTOCless() const {
  868. return GETBITWITHMASK(0, IsTOClessMask);
  869. }
  870. bool XCOFFTracebackTable::isFloatingPointPresent() const {
  871. return GETBITWITHMASK(0, IsFloatingPointPresentMask);
  872. }
  873. bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const {
  874. return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask);
  875. }
  876. bool XCOFFTracebackTable::isInterruptHandler() const {
  877. return GETBITWITHMASK(0, IsInterruptHandlerMask);
  878. }
  879. bool XCOFFTracebackTable::isFuncNamePresent() const {
  880. return GETBITWITHMASK(0, IsFunctionNamePresentMask);
  881. }
  882. bool XCOFFTracebackTable::isAllocaUsed() const {
  883. return GETBITWITHMASK(0, IsAllocaUsedMask);
  884. }
  885. uint8_t XCOFFTracebackTable::getOnConditionDirective() const {
  886. return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask,
  887. OnConditionDirectiveShift);
  888. }
  889. bool XCOFFTracebackTable::isCRSaved() const {
  890. return GETBITWITHMASK(0, IsCRSavedMask);
  891. }
  892. bool XCOFFTracebackTable::isLRSaved() const {
  893. return GETBITWITHMASK(0, IsLRSavedMask);
  894. }
  895. bool XCOFFTracebackTable::isBackChainStored() const {
  896. return GETBITWITHMASK(4, IsBackChainStoredMask);
  897. }
  898. bool XCOFFTracebackTable::isFixup() const {
  899. return GETBITWITHMASK(4, IsFixupMask);
  900. }
  901. uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const {
  902. return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift);
  903. }
  904. bool XCOFFTracebackTable::hasExtensionTable() const {
  905. return GETBITWITHMASK(4, HasExtensionTableMask);
  906. }
  907. bool XCOFFTracebackTable::hasVectorInfo() const {
  908. return GETBITWITHMASK(4, HasVectorInfoMask);
  909. }
  910. uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const {
  911. return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift);
  912. }
  913. uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const {
  914. return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask,
  915. NumberOfFixedParmsShift);
  916. }
  917. uint8_t XCOFFTracebackTable::getNumberOfFPParms() const {
  918. return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask,
  919. NumberOfFloatingPointParmsShift);
  920. }
  921. bool XCOFFTracebackTable::hasParmsOnStack() const {
  922. return GETBITWITHMASK(4, HasParmsOnStackMask);
  923. }
  924. #undef GETBITWITHMASK
  925. #undef GETBITWITHMASKSHIFT
  926. } // namespace object
  927. } // namespace llvm