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