Bug Summary

File:build/source/llvm/include/llvm/Object/XCOFFObjectFile.h
Warning:line 760, column 50
Dereference of null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name XCOFFObjectFile.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm -resource-dir /usr/lib/llvm-16/lib/clang/16.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I lib/Object -I /build/source/llvm/lib/Object -I include -I /build/source/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-16/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm=build-llvm -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm=build-llvm -fcoverage-prefix-map=/build/source/= -source-date-epoch 1668078801 -O3 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm -fdebug-prefix-map=/build/source/build-llvm=build-llvm -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-11-10-135928-647445-1 -x c++ /build/source/llvm/lib/Object/XCOFFObjectFile.cpp

/build/source/llvm/lib/Object/XCOFFObjectFile.cpp

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
20namespace llvm {
21
22using namespace XCOFF;
23
24namespace object {
25
26static const uint8_t FunctionSym = 0x20;
27static const uint16_t NoRelMask = 0x0001;
28static 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.
32template <typename T>
33static 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
41static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) {
42 return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) +
43 Offset);
44}
45
46template <typename T> static const T *viewAs(uintptr_t in) {
47 return reinterpret_cast<const T *>(in);
48}
49
50static 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
57template <typename T> StringRef XCOFFSectionHeader<T>::getName() const {
58 const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
59 return generateXCOFFFixedNameStringRef(DerivedXCOFFSectionHeader.Name);
60}
61
62template <typename T> uint16_t XCOFFSectionHeader<T>::getSectionType() const {
63 const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
64 return DerivedXCOFFSectionHeader.Flags & SectionFlagsTypeMask;
65}
66
67template <typename T>
68bool XCOFFSectionHeader<T>::isReservedSectionType() const {
69 return getSectionType() & SectionFlagsReservedMask;
70}
71
72template <typename AddressType>
73bool XCOFFRelocation<AddressType>::isRelocationSigned() const {
74 return Info & XR_SIGN_INDICATOR_MASK;
75}
76
77template <typename AddressType>
78bool XCOFFRelocation<AddressType>::isFixupIndicated() const {
79 return Info & XR_FIXUP_INDICATOR_MASK;
80}
81
82template <typename AddressType>
83uint8_t XCOFFRelocation<AddressType>::getRelocatedLength() const {
84 // The relocation encodes the bit length being relocated minus 1. Add back
85 // the 1 to get the actual length being relocated.
86 return (Info & XR_BIASED_LENGTH_MASK) + 1;
87}
88
89template struct ExceptionSectionEntry<support::ubig32_t>;
90template struct ExceptionSectionEntry<support::ubig64_t>;
91
92uintptr_t
93XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
94 uint32_t Distance) {
95 return getWithOffset(CurrentAddress, Distance * XCOFF::SymbolTableEntrySize);
96}
97
98const XCOFF::SymbolAuxType *
99XCOFFObjectFile::getSymbolAuxType(uintptr_t AuxEntryAddress) const {
100 assert(is64Bit() && "64-bit interface called on a 32-bit object file.")(static_cast <bool> (is64Bit() && "64-bit interface called on a 32-bit object file."
) ? void (0) : __assert_fail ("is64Bit() && \"64-bit interface called on a 32-bit object file.\""
, "llvm/lib/Object/XCOFFObjectFile.cpp", 100, __extension__ __PRETTY_FUNCTION__
))
;
101 return viewAs<XCOFF::SymbolAuxType>(
102 getWithOffset(AuxEntryAddress, SymbolAuxTypeOffset));
103}
104
105void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
106 uintptr_t TableAddress) const {
107 if (Addr < TableAddress)
108 report_fatal_error("Section header outside of section header table.");
109
110 uintptr_t Offset = Addr - TableAddress;
111 if (Offset >= getSectionHeaderSize() * getNumberOfSections())
112 report_fatal_error("Section header outside of section header table.");
113
114 if (Offset % getSectionHeaderSize() != 0)
115 report_fatal_error(
116 "Section header pointer does not point to a valid section header.");
117}
118
119const XCOFFSectionHeader32 *
120XCOFFObjectFile::toSection32(DataRefImpl Ref) const {
121 assert(!is64Bit() && "32-bit interface called on 64-bit object file.")(static_cast <bool> (!is64Bit() && "32-bit interface called on 64-bit object file."
) ? void (0) : __assert_fail ("!is64Bit() && \"32-bit interface called on 64-bit object file.\""
, "llvm/lib/Object/XCOFFObjectFile.cpp", 121, __extension__ __PRETTY_FUNCTION__
))
;
122#ifndef NDEBUG
123 checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
124#endif
125 return viewAs<XCOFFSectionHeader32>(Ref.p);
126}
127
128const XCOFFSectionHeader64 *
129XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
130 assert(is64Bit() && "64-bit interface called on a 32-bit object file.")(static_cast <bool> (is64Bit() && "64-bit interface called on a 32-bit object file."
) ? void (0) : __assert_fail ("is64Bit() && \"64-bit interface called on a 32-bit object file.\""
, "llvm/lib/Object/XCOFFObjectFile.cpp", 130, __extension__ __PRETTY_FUNCTION__
))
;
131#ifndef NDEBUG
132 checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
133#endif
134 return viewAs<XCOFFSectionHeader64>(Ref.p);
135}
136
137XCOFFSymbolRef XCOFFObjectFile::toSymbolRef(DataRefImpl Ref) const {
138 assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!")(static_cast <bool> (Ref.p != 0 && "Symbol table pointer can not be nullptr!"
) ? void (0) : __assert_fail ("Ref.p != 0 && \"Symbol table pointer can not be nullptr!\""
, "llvm/lib/Object/XCOFFObjectFile.cpp", 138, __extension__ __PRETTY_FUNCTION__
))
;
139#ifndef NDEBUG
140 checkSymbolEntryPointer(Ref.p);
141#endif
142 return XCOFFSymbolRef(Ref, this);
143}
144
145const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
146 assert(!is64Bit() && "32-bit interface called on 64-bit object file.")(static_cast <bool> (!is64Bit() && "32-bit interface called on 64-bit object file."
) ? void (0) : __assert_fail ("!is64Bit() && \"32-bit interface called on 64-bit object file.\""
, "llvm/lib/Object/XCOFFObjectFile.cpp", 146, __extension__ __PRETTY_FUNCTION__
))
;
147 return static_cast<const XCOFFFileHeader32 *>(FileHeader);
148}
149
150const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
151 assert(is64Bit() && "64-bit interface called on a 32-bit object file.")(static_cast <bool> (is64Bit() && "64-bit interface called on a 32-bit object file."
) ? void (0) : __assert_fail ("is64Bit() && \"64-bit interface called on a 32-bit object file.\""
, "llvm/lib/Object/XCOFFObjectFile.cpp", 151, __extension__ __PRETTY_FUNCTION__
))
;
152 return static_cast<const XCOFFFileHeader64 *>(FileHeader);
153}
154
155const XCOFFAuxiliaryHeader32 *XCOFFObjectFile::auxiliaryHeader32() const {
156 assert(!is64Bit() && "32-bit interface called on 64-bit object file.")(static_cast <bool> (!is64Bit() && "32-bit interface called on 64-bit object file."
) ? void (0) : __assert_fail ("!is64Bit() && \"32-bit interface called on 64-bit object file.\""
, "llvm/lib/Object/XCOFFObjectFile.cpp", 156, __extension__ __PRETTY_FUNCTION__
))
;
157 return static_cast<const XCOFFAuxiliaryHeader32 *>(AuxiliaryHeader);
158}
159
160const XCOFFAuxiliaryHeader64 *XCOFFObjectFile::auxiliaryHeader64() const {
161 assert(is64Bit() && "64-bit interface called on a 32-bit object file.")(static_cast <bool> (is64Bit() && "64-bit interface called on a 32-bit object file."
) ? void (0) : __assert_fail ("is64Bit() && \"64-bit interface called on a 32-bit object file.\""
, "llvm/lib/Object/XCOFFObjectFile.cpp", 161, __extension__ __PRETTY_FUNCTION__
))
;
162 return static_cast<const XCOFFAuxiliaryHeader64 *>(AuxiliaryHeader);
163}
164
165template <typename T> const T *XCOFFObjectFile::sectionHeaderTable() const {
166 return static_cast<const T *>(SectionHeaderTable);
167}
168
169const XCOFFSectionHeader32 *
170XCOFFObjectFile::sectionHeaderTable32() const {
171 assert(!is64Bit() && "32-bit interface called on 64-bit object file.")(static_cast <bool> (!is64Bit() && "32-bit interface called on 64-bit object file."
) ? void (0) : __assert_fail ("!is64Bit() && \"32-bit interface called on 64-bit object file.\""
, "llvm/lib/Object/XCOFFObjectFile.cpp", 171, __extension__ __PRETTY_FUNCTION__
))
;
172 return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
173}
174
175const XCOFFSectionHeader64 *
176XCOFFObjectFile::sectionHeaderTable64() const {
177 assert(is64Bit() && "64-bit interface called on a 32-bit object file.")(static_cast <bool> (is64Bit() && "64-bit interface called on a 32-bit object file."
) ? void (0) : __assert_fail ("is64Bit() && \"64-bit interface called on a 32-bit object file.\""
, "llvm/lib/Object/XCOFFObjectFile.cpp", 177, __extension__ __PRETTY_FUNCTION__
))
;
178 return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
179}
180
181void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
182 uintptr_t NextSymbolAddr = getAdvancedSymbolEntryAddress(
183 Symb.p, toSymbolRef(Symb).getNumberOfAuxEntries() + 1);
1
Calling 'XCOFFSymbolRef::getNumberOfAuxEntries'
184#ifndef NDEBUG
185 // This function is used by basic_symbol_iterator, which allows to
186 // point to the end-of-symbol-table address.
187 if (NextSymbolAddr != getEndOfSymbolTableAddress())
188 checkSymbolEntryPointer(NextSymbolAddr);
189#endif
190 Symb.p = NextSymbolAddr;
191}
192
193Expected<StringRef>
194XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const {
195 // The byte offset is relative to the start of the string table.
196 // A byte offset value of 0 is a null or zero-length symbol
197 // name. A byte offset in the range 1 to 3 (inclusive) points into the length
198 // field; as a soft-error recovery mechanism, we treat such cases as having an
199 // offset of 0.
200 if (Offset < 4)
201 return StringRef(nullptr, 0);
202
203 if (StringTable.Data != nullptr && StringTable.Size > Offset)
204 return (StringTable.Data + Offset);
205
206 return createError("entry with offset 0x" + Twine::utohexstr(Offset) +
207 " in a string table with size 0x" +
208 Twine::utohexstr(StringTable.Size) + " is invalid");
209}
210
211StringRef XCOFFObjectFile::getStringTable() const {
212 // If the size is less than or equal to 4, then the string table contains no
213 // string data.
214 return StringRef(StringTable.Data,
215 StringTable.Size <= 4 ? 0 : StringTable.Size);
216}
217
218Expected<StringRef>
219XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const {
220 if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
221 return generateXCOFFFixedNameStringRef(CFileEntPtr->Name);
222 return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset);
223}
224
225Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
226 return toSymbolRef(Symb).getName();
227}
228
229Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
230 return toSymbolRef(Symb).getValue();
231}
232
233uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
234 return toSymbolRef(Symb).getValue();
235}
236
237uint32_t XCOFFObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
238 uint64_t Result = 0;
239 XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
240 if (XCOFFSym.isCsectSymbol()) {
241 Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
242 XCOFFSym.getXCOFFCsectAuxRef();
243 if (!CsectAuxRefOrError)
244 // TODO: report the error up the stack.
245 consumeError(CsectAuxRefOrError.takeError());
246 else
247 Result = 1ULL << CsectAuxRefOrError.get().getAlignmentLog2();
248 }
249 return Result;
250}
251
252uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
253 uint64_t Result = 0;
254 XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
255 if (XCOFFSym.isCsectSymbol()) {
256 Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
257 XCOFFSym.getXCOFFCsectAuxRef();
258 if (!CsectAuxRefOrError)
259 // TODO: report the error up the stack.
260 consumeError(CsectAuxRefOrError.takeError());
261 else {
262 XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get();
263 assert(CsectAuxRef.getSymbolType() == XCOFF::XTY_CM)(static_cast <bool> (CsectAuxRef.getSymbolType() == XCOFF
::XTY_CM) ? void (0) : __assert_fail ("CsectAuxRef.getSymbolType() == XCOFF::XTY_CM"
, "llvm/lib/Object/XCOFFObjectFile.cpp", 263, __extension__ __PRETTY_FUNCTION__
))
;
264 Result = CsectAuxRef.getSectionOrLength();
265 }
266 }
267 return Result;
268}
269
270Expected<SymbolRef::Type>
271XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
272 XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
273
274 if (XCOFFSym.isFunction())
275 return SymbolRef::ST_Function;
276
277 if (XCOFF::C_FILE == XCOFFSym.getStorageClass())
278 return SymbolRef::ST_File;
279
280 int16_t SecNum = XCOFFSym.getSectionNumber();
281 if (SecNum <= 0)
282 return SymbolRef::ST_Other;
283
284 Expected<DataRefImpl> SecDRIOrErr =
285 getSectionByNum(XCOFFSym.getSectionNumber());
286
287 if (!SecDRIOrErr)
288 return SecDRIOrErr.takeError();
289
290 DataRefImpl SecDRI = SecDRIOrErr.get();
291
292 Expected<StringRef> SymNameOrError = XCOFFSym.getName();
293 if (SymNameOrError) {
294 // The "TOC" symbol is treated as SymbolRef::ST_Other.
295 if (SymNameOrError.get() == "TOC")
296 return SymbolRef::ST_Other;
297
298 // The symbol for a section name is treated as SymbolRef::ST_Other.
299 StringRef SecName;
300 if (is64Bit())
301 SecName = XCOFFObjectFile::toSection64(SecDRIOrErr.get())->getName();
302 else
303 SecName = XCOFFObjectFile::toSection32(SecDRIOrErr.get())->getName();
304
305 if (SecName == SymNameOrError.get())
306 return SymbolRef::ST_Other;
307 } else
308 return SymNameOrError.takeError();
309
310 if (isSectionData(SecDRI) || isSectionBSS(SecDRI))
311 return SymbolRef::ST_Data;
312
313 if (isDebugSection(SecDRI))
314 return SymbolRef::ST_Debug;
315
316 return SymbolRef::ST_Other;
317}
318
319Expected<section_iterator>
320XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
321 const int16_t SectNum = toSymbolRef(Symb).getSectionNumber();
322
323 if (isReservedSectionNumber(SectNum))
324 return section_end();
325
326 Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum);
327 if (!ExpSec)
328 return ExpSec.takeError();
329
330 return section_iterator(SectionRef(ExpSec.get(), this));
331}
332
333void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
334 const char *Ptr = reinterpret_cast<const char *>(Sec.p);
335 Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize());
336}
337
338Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
339 return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec));
340}
341
342uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
343 // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
344 // with MSVC.
345 if (is64Bit())
346 return toSection64(Sec)->VirtualAddress;
347
348 return toSection32(Sec)->VirtualAddress;
349}
350
351uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
352 // Section numbers in XCOFF are numbered beginning at 1. A section number of
353 // zero is used to indicate that a symbol is being imported or is undefined.
354 if (is64Bit())
355 return toSection64(Sec) - sectionHeaderTable64() + 1;
356 else
357 return toSection32(Sec) - sectionHeaderTable32() + 1;
358}
359
360uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
361 // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t
362 // with MSVC.
363 if (is64Bit())
364 return toSection64(Sec)->SectionSize;
365
366 return toSection32(Sec)->SectionSize;
367}
368
369Expected<ArrayRef<uint8_t>>
370XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
371 if (isSectionVirtual(Sec))
372 return ArrayRef<uint8_t>();
373
374 uint64_t OffsetToRaw;
375 if (is64Bit())
376 OffsetToRaw = toSection64(Sec)->FileOffsetToRawData;
377 else
378 OffsetToRaw = toSection32(Sec)->FileOffsetToRawData;
379
380 const uint8_t * ContentStart = base() + OffsetToRaw;
381 uint64_t SectionSize = getSectionSize(Sec);
382 if (Error E = Binary::checkOffset(
383 Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize))
384 return createError(
385 toString(std::move(E)) + ": section data with offset 0x" +
386 Twine::utohexstr(OffsetToRaw) + " and size 0x" +
387 Twine::utohexstr(SectionSize) + " goes past the end of the file");
388
389 return makeArrayRef(ContentStart,SectionSize);
390}
391
392uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
393 uint64_t Result = 0;
394 llvm_unreachable("Not yet implemented!")::llvm::llvm_unreachable_internal("Not yet implemented!", "llvm/lib/Object/XCOFFObjectFile.cpp"
, 394)
;
395 return Result;
396}
397
398uint64_t XCOFFObjectFile::getSectionFileOffsetToRawData(DataRefImpl Sec) const {
399 if (is64Bit())
400 return toSection64(Sec)->FileOffsetToRawData;
401
402 return toSection32(Sec)->FileOffsetToRawData;
403}
404
405Expected<uintptr_t> XCOFFObjectFile::getSectionFileOffsetToRawData(
406 XCOFF::SectionTypeFlags SectType) const {
407 DataRefImpl DRI = getSectionByType(SectType);
408
409 if (DRI.p == 0) // No section is not an error.
410 return 0;
411
412 uint64_t SectionOffset = getSectionFileOffsetToRawData(DRI);
413 uint64_t SizeOfSection = getSectionSize(DRI);
414
415 uintptr_t SectionStart = reinterpret_cast<uintptr_t>(base() + SectionOffset);
416 if (Error E = Binary::checkOffset(Data, SectionStart, SizeOfSection)) {
417 SmallString<32> UnknownType;
418 Twine(("<Unknown:") + Twine::utohexstr(SectType) + ">")
419 .toVector(UnknownType);
420 const char *SectionName = UnknownType.c_str();
421
422 switch (SectType) {
423#define ECASE(Value, String) \
424 case XCOFF::Value: \
425 SectionName = String; \
426 break
427
428 ECASE(STYP_PAD, "pad");
429 ECASE(STYP_DWARF, "dwarf");
430 ECASE(STYP_TEXT, "text");
431 ECASE(STYP_DATA, "data");
432 ECASE(STYP_BSS, "bss");
433 ECASE(STYP_EXCEPT, "expect");
434 ECASE(STYP_INFO, "info");
435 ECASE(STYP_TDATA, "tdata");
436 ECASE(STYP_TBSS, "tbss");
437 ECASE(STYP_LOADER, "loader");
438 ECASE(STYP_DEBUG, "debug");
439 ECASE(STYP_TYPCHK, "typchk");
440 ECASE(STYP_OVRFLO, "ovrflo");
441#undef ECASE
442 }
443 return createError(toString(std::move(E)) + ": " + SectionName +
444 " section with offset 0x" +
445 Twine::utohexstr(SectionOffset) + " and size 0x" +
446 Twine::utohexstr(SizeOfSection) +
447 " goes past the end of the file");
448 }
449 return SectionStart;
450}
451
452bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
453 return false;
454}
455
456bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
457 return getSectionFlags(Sec) & XCOFF::STYP_TEXT;
458}
459
460bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
461 uint32_t Flags = getSectionFlags(Sec);
462 return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
463}
464
465bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
466 uint32_t Flags = getSectionFlags(Sec);
467 return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
468}
469
470bool XCOFFObjectFile::isDebugSection(DataRefImpl Sec) const {
471 uint32_t Flags = getSectionFlags(Sec);
472 return Flags & (XCOFF::STYP_DEBUG | XCOFF::STYP_DWARF);
473}
474
475bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
476 return is64Bit() ? toSection64(Sec)->FileOffsetToRawData == 0
477 : toSection32(Sec)->FileOffsetToRawData == 0;
478}
479
480relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
481 DataRefImpl Ret;
482 if (is64Bit()) {
483 const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec);
484 auto RelocationsOrErr =
485 relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr);
486 if (Error E = RelocationsOrErr.takeError()) {
487 // TODO: report the error up the stack.
488 consumeError(std::move(E));
489 return relocation_iterator(RelocationRef());
490 }
491 Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
492 } else {
493 const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
494 auto RelocationsOrErr =
495 relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr);
496 if (Error E = RelocationsOrErr.takeError()) {
497 // TODO: report the error up the stack.
498 consumeError(std::move(E));
499 return relocation_iterator(RelocationRef());
500 }
501 Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
502 }
503 return relocation_iterator(RelocationRef(Ret, this));
504}
505
506relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const {
507 DataRefImpl Ret;
508 if (is64Bit()) {
509 const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec);
510 auto RelocationsOrErr =
511 relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr);
512 if (Error E = RelocationsOrErr.takeError()) {
513 // TODO: report the error up the stack.
514 consumeError(std::move(E));
515 return relocation_iterator(RelocationRef());
516 }
517 Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
518 } else {
519 const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
520 auto RelocationsOrErr =
521 relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr);
522 if (Error E = RelocationsOrErr.takeError()) {
523 // TODO: report the error up the stack.
524 consumeError(std::move(E));
525 return relocation_iterator(RelocationRef());
526 }
527 Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
528 }
529 return relocation_iterator(RelocationRef(Ret, this));
530}
531
532void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
533 if (is64Bit())
534 Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation64>(Rel.p) + 1);
535 else
536 Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1);
537}
538
539uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
540 if (is64Bit()) {
541 const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
542 const XCOFFSectionHeader64 *Sec64 = sectionHeaderTable64();
543 const uint64_t RelocAddress = Reloc->VirtualAddress;
544 const uint16_t NumberOfSections = getNumberOfSections();
545 for (uint16_t I = 0; I < NumberOfSections; ++I) {
546 // Find which section this relocation belongs to, and get the
547 // relocation offset relative to the start of the section.
548 if (Sec64->VirtualAddress <= RelocAddress &&
549 RelocAddress < Sec64->VirtualAddress + Sec64->SectionSize) {
550 return RelocAddress - Sec64->VirtualAddress;
551 }
552 ++Sec64;
553 }
554 } else {
555 const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
556 const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32();
557 const uint32_t RelocAddress = Reloc->VirtualAddress;
558 const uint16_t NumberOfSections = getNumberOfSections();
559 for (uint16_t I = 0; I < NumberOfSections; ++I) {
560 // Find which section this relocation belongs to, and get the
561 // relocation offset relative to the start of the section.
562 if (Sec32->VirtualAddress <= RelocAddress &&
563 RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) {
564 return RelocAddress - Sec32->VirtualAddress;
565 }
566 ++Sec32;
567 }
568 }
569 return InvalidRelocOffset;
570}
571
572symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
573 uint32_t Index;
574 if (is64Bit()) {
575 const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
576 Index = Reloc->SymbolIndex;
577
578 if (Index >= getNumberOfSymbolTableEntries64())
579 return symbol_end();
580 } else {
581 const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
582 Index = Reloc->SymbolIndex;
583
584 if (Index >= getLogicalNumberOfSymbolTableEntries32())
585 return symbol_end();
586 }
587 DataRefImpl SymDRI;
588 SymDRI.p = getSymbolEntryAddressByIndex(Index);
589 return symbol_iterator(SymbolRef(SymDRI, this));
590}
591
592uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const {
593 if (is64Bit())
594 return viewAs<XCOFFRelocation64>(Rel.p)->Type;
595 return viewAs<XCOFFRelocation32>(Rel.p)->Type;
596}
597
598void XCOFFObjectFile::getRelocationTypeName(
599 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
600 StringRef Res;
601 if (is64Bit()) {
602 const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
603 Res = XCOFF::getRelocationTypeString(Reloc->Type);
604 } else {
605 const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
606 Res = XCOFF::getRelocationTypeString(Reloc->Type);
607 }
608 Result.append(Res.begin(), Res.end());
609}
610
611Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
612 XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
613 uint32_t Result = SymbolRef::SF_None;
614
615 if (XCOFFSym.getSectionNumber() == XCOFF::N_ABS)
616 Result |= SymbolRef::SF_Absolute;
617
618 XCOFF::StorageClass SC = XCOFFSym.getStorageClass();
619 if (XCOFF::C_EXT == SC || XCOFF::C_WEAKEXT == SC)
620 Result |= SymbolRef::SF_Global;
621
622 if (XCOFF::C_WEAKEXT == SC)
623 Result |= SymbolRef::SF_Weak;
624
625 if (XCOFFSym.isCsectSymbol()) {
626 Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr =
627 XCOFFSym.getXCOFFCsectAuxRef();
628 if (CsectAuxEntOrErr) {
629 if (CsectAuxEntOrErr.get().getSymbolType() == XCOFF::XTY_CM)
630 Result |= SymbolRef::SF_Common;
631 } else
632 return CsectAuxEntOrErr.takeError();
633 }
634
635 if (XCOFFSym.getSectionNumber() == XCOFF::N_UNDEF)
636 Result |= SymbolRef::SF_Undefined;
637
638 // There is no visibility in old 32 bit XCOFF object file interpret.
639 if (is64Bit() || (auxiliaryHeader32() && (auxiliaryHeader32()->getVersion() ==
640 NEW_XCOFF_INTERPRET))) {
641 uint16_t SymType = XCOFFSym.getSymbolType();
642 if ((SymType & VISIBILITY_MASK) == SYM_V_HIDDEN)
643 Result |= SymbolRef::SF_Hidden;
644
645 if ((SymType & VISIBILITY_MASK) == SYM_V_EXPORTED)
646 Result |= SymbolRef::SF_Exported;
647 }
648 return Result;
649}
650
651basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
652 DataRefImpl SymDRI;
653 SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
654 return basic_symbol_iterator(SymbolRef(SymDRI, this));
655}
656
657basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
658 DataRefImpl SymDRI;
659 const uint32_t NumberOfSymbolTableEntries = getNumberOfSymbolTableEntries();
660 SymDRI.p = getSymbolEntryAddressByIndex(NumberOfSymbolTableEntries);
661 return basic_symbol_iterator(SymbolRef(SymDRI, this));
662}
663
664section_iterator XCOFFObjectFile::section_begin() const {
665 DataRefImpl DRI;
666 DRI.p = getSectionHeaderTableAddress();
667 return section_iterator(SectionRef(DRI, this));
668}
669
670section_iterator XCOFFObjectFile::section_end() const {
671 DataRefImpl DRI;
672 DRI.p = getWithOffset(getSectionHeaderTableAddress(),
673 getNumberOfSections() * getSectionHeaderSize());
674 return section_iterator(SectionRef(DRI, this));
675}
676
677uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; }
678
679StringRef XCOFFObjectFile::getFileFormatName() const {
680 return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000";
681}
682
683Triple::ArchType XCOFFObjectFile::getArch() const {
684 return is64Bit() ? Triple::ppc64 : Triple::ppc;
685}
686
687SubtargetFeatures XCOFFObjectFile::getFeatures() const {
688 return SubtargetFeatures();
689}
690
691bool XCOFFObjectFile::isRelocatableObject() const {
692 if (is64Bit())
693 return !(fileHeader64()->Flags & NoRelMask);
694 return !(fileHeader32()->Flags & NoRelMask);
695}
696
697Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
698 // TODO FIXME Should get from auxiliary_header->o_entry when support for the
699 // auxiliary_header is added.
700 return 0;
701}
702
703StringRef XCOFFObjectFile::mapDebugSectionName(StringRef Name) const {
704 return StringSwitch<StringRef>(Name)
705 .Case("dwinfo", "debug_info")
706 .Case("dwline", "debug_line")
707 .Case("dwpbnms", "debug_pubnames")
708 .Case("dwpbtyp", "debug_pubtypes")
709 .Case("dwarnge", "debug_aranges")
710 .Case("dwabrev", "debug_abbrev")
711 .Case("dwstr", "debug_str")
712 .Case("dwrnges", "debug_ranges")
713 .Case("dwloc", "debug_loc")
714 .Case("dwframe", "debug_frame")
715 .Case("dwmac", "debug_macinfo")
716 .Default(Name);
717}
718
719size_t XCOFFObjectFile::getFileHeaderSize() const {
720 return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32);
721}
722
723size_t XCOFFObjectFile::getSectionHeaderSize() const {
724 return is64Bit() ? sizeof(XCOFFSectionHeader64) :
725 sizeof(XCOFFSectionHeader32);
726}
727
728bool XCOFFObjectFile::is64Bit() const {
729 return Binary::ID_XCOFF64 == getType();
730}
731
732Expected<StringRef> XCOFFObjectFile::getRawData(const char *Start,
733 uint64_t Size,
734 StringRef Name) const {
735 uintptr_t StartPtr = reinterpret_cast<uintptr_t>(Start);
736 // TODO: this path is untested.
737 if (Error E = Binary::checkOffset(Data, StartPtr, Size))
738 return createError(toString(std::move(E)) + ": " + Name.data() +
739 " data with offset 0x" + Twine::utohexstr(StartPtr) +
740 " and size 0x" + Twine::utohexstr(Size) +
741 " goes past the end of the file");
742 return StringRef(Start, Size);
743}
744
745uint16_t XCOFFObjectFile::getMagic() const {
746 return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic;
747}
748
749Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
750 if (Num <= 0 || Num > getNumberOfSections())
751 return createStringError(object_error::invalid_section_index,
752 "the section index (" + Twine(Num) +
753 ") is invalid");
754
755 DataRefImpl DRI;
756 DRI.p = getWithOffset(getSectionHeaderTableAddress(),
757 getSectionHeaderSize() * (Num - 1));
758 return DRI;
759}
760
761DataRefImpl
762XCOFFObjectFile::getSectionByType(XCOFF::SectionTypeFlags SectType) const {
763 DataRefImpl DRI;
764 auto GetSectionAddr = [&](const auto &Sections) -> uintptr_t {
765 for (const auto &Sec : Sections)
766 if (Sec.getSectionType() == SectType)
767 return reinterpret_cast<uintptr_t>(&Sec);
768 return uintptr_t(0);
769 };
770 if (is64Bit())
771 DRI.p = GetSectionAddr(sections64());
772 else
773 DRI.p = GetSectionAddr(sections32());
774 return DRI;
775}
776
777Expected<StringRef>
778XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const {
779 const int16_t SectionNum = SymEntPtr.getSectionNumber();
780
781 switch (SectionNum) {
782 case XCOFF::N_DEBUG:
783 return "N_DEBUG";
784 case XCOFF::N_ABS:
785 return "N_ABS";
786 case XCOFF::N_UNDEF:
787 return "N_UNDEF";
788 default:
789 Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
790 if (SecRef)
791 return generateXCOFFFixedNameStringRef(
792 getSectionNameInternal(SecRef.get()));
793 return SecRef.takeError();
794 }
795}
796
797unsigned XCOFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
798 XCOFFSymbolRef XCOFFSymRef(Sym.getRawDataRefImpl(), this);
799 return XCOFFSymRef.getSectionNumber();
800}
801
802bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) {
803 return (SectionNumber <= 0 && SectionNumber >= -2);
804}
805
806uint16_t XCOFFObjectFile::getNumberOfSections() const {
807 return is64Bit() ? fileHeader64()->NumberOfSections
808 : fileHeader32()->NumberOfSections;
809}
810
811int32_t XCOFFObjectFile::getTimeStamp() const {
812 return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp;
813}
814
815uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
816 return is64Bit() ? fileHeader64()->AuxHeaderSize
817 : fileHeader32()->AuxHeaderSize;
818}
819
820uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
821 return fileHeader32()->SymbolTableOffset;
822}
823
824int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const {
825 // As far as symbol table size is concerned, if this field is negative it is
826 // to be treated as a 0. However since this field is also used for printing we
827 // don't want to truncate any negative values.
828 return fileHeader32()->NumberOfSymTableEntries;
829}
830
831uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
832 return (fileHeader32()->NumberOfSymTableEntries >= 0
833 ? fileHeader32()->NumberOfSymTableEntries
834 : 0);
835}
836
837uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
838 return fileHeader64()->SymbolTableOffset;
839}
840
841uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
842 return fileHeader64()->NumberOfSymTableEntries;
843}
844
845uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const {
846 return is64Bit() ? getNumberOfSymbolTableEntries64()
847 : getLogicalNumberOfSymbolTableEntries32();
848}
849
850uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const {
851 const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
852 return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr),
853 XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries);
854}
855
856void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const {
857 if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr))
858 report_fatal_error("Symbol table entry is outside of symbol table.");
859
860 if (SymbolEntPtr >= getEndOfSymbolTableAddress())
861 report_fatal_error("Symbol table entry is outside of symbol table.");
862
863 ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) -
864 reinterpret_cast<const char *>(SymbolTblPtr);
865
866 if (Offset % XCOFF::SymbolTableEntrySize != 0)
867 report_fatal_error(
868 "Symbol table entry position is not valid inside of symbol table.");
869}
870
871uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const {
872 return (reinterpret_cast<const char *>(SymbolEntPtr) -
873 reinterpret_cast<const char *>(SymbolTblPtr)) /
874 XCOFF::SymbolTableEntrySize;
875}
876
877uint64_t XCOFFObjectFile::getSymbolSize(DataRefImpl Symb) const {
878 uint64_t Result = 0;
879 XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
880 if (XCOFFSym.isCsectSymbol()) {
881 Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
882 XCOFFSym.getXCOFFCsectAuxRef();
883 if (!CsectAuxRefOrError)
884 // TODO: report the error up the stack.
885 consumeError(CsectAuxRefOrError.takeError());
886 else {
887 XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get();
888 uint8_t SymType = CsectAuxRef.getSymbolType();
889 if (SymType == XCOFF::XTY_SD || SymType == XCOFF::XTY_CM)
890 Result = CsectAuxRef.getSectionOrLength();
891 }
892 }
893 return Result;
894}
895
896uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const {
897 return getAdvancedSymbolEntryAddress(
898 reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index);
899}
900
901Expected<StringRef>
902XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const {
903 const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
904
905 if (Index >= NumberOfSymTableEntries)
906 return createError("symbol index " + Twine(Index) +
907 " exceeds symbol count " +
908 Twine(NumberOfSymTableEntries));
909
910 DataRefImpl SymDRI;
911 SymDRI.p = getSymbolEntryAddressByIndex(Index);
912 return getSymbolName(SymDRI);
913}
914
915uint16_t XCOFFObjectFile::getFlags() const {
916 return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
917}
918
919const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const {
920 return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name;
921}
922
923uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
924 return reinterpret_cast<uintptr_t>(SectionHeaderTable);
925}
926
927int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const {
928 return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags;
929}
930
931XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object)
932 : ObjectFile(Type, Object) {
933 assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64)(static_cast <bool> (Type == Binary::ID_XCOFF32 || Type
== Binary::ID_XCOFF64) ? void (0) : __assert_fail ("Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64"
, "llvm/lib/Object/XCOFFObjectFile.cpp", 933, __extension__ __PRETTY_FUNCTION__
))
;
934}
935
936ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const {
937 assert(is64Bit() && "64-bit interface called for non 64-bit file.")(static_cast <bool> (is64Bit() && "64-bit interface called for non 64-bit file."
) ? void (0) : __assert_fail ("is64Bit() && \"64-bit interface called for non 64-bit file.\""
, "llvm/lib/Object/XCOFFObjectFile.cpp", 937, __extension__ __PRETTY_FUNCTION__
))
;
938 const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64();
939 return ArrayRef<XCOFFSectionHeader64>(TablePtr,
940 TablePtr + getNumberOfSections());
941}
942
943ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const {
944 assert(!is64Bit() && "32-bit interface called for non 32-bit file.")(static_cast <bool> (!is64Bit() && "32-bit interface called for non 32-bit file."
) ? void (0) : __assert_fail ("!is64Bit() && \"32-bit interface called for non 32-bit file.\""
, "llvm/lib/Object/XCOFFObjectFile.cpp", 944, __extension__ __PRETTY_FUNCTION__
))
;
945 const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32();
946 return ArrayRef<XCOFFSectionHeader32>(TablePtr,
947 TablePtr + getNumberOfSections());
948}
949
950// In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO
951// section header contains the actual count of relocation entries in the s_paddr
952// field. STYP_OVRFLO headers contain the section index of their corresponding
953// sections as their raw "NumberOfRelocations" field value.
954template <typename T>
955Expected<uint32_t> XCOFFObjectFile::getNumberOfRelocationEntries(
956 const XCOFFSectionHeader<T> &Sec) const {
957 const T &Section = static_cast<const T &>(Sec);
958 if (is64Bit())
959 return Section.NumberOfRelocations;
960
961 uint16_t SectionIndex = &Section - sectionHeaderTable<T>() + 1;
962 if (Section.NumberOfRelocations < XCOFF::RelocOverflow)
963 return Section.NumberOfRelocations;
964 for (const auto &Sec : sections32()) {
965 if (Sec.Flags == XCOFF::STYP_OVRFLO &&
966 Sec.NumberOfRelocations == SectionIndex)
967 return Sec.PhysicalAddress;
968 }
969 return errorCodeToError(object_error::parse_failed);
970}
971
972template <typename Shdr, typename Reloc>
973Expected<ArrayRef<Reloc>> XCOFFObjectFile::relocations(const Shdr &Sec) const {
974 uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader),
975 Sec.FileOffsetToRelocationInfo);
976 auto NumRelocEntriesOrErr = getNumberOfRelocationEntries(Sec);
977 if (Error E = NumRelocEntriesOrErr.takeError())
978 return std::move(E);
979
980 uint32_t NumRelocEntries = NumRelocEntriesOrErr.get();
981 static_assert((sizeof(Reloc) == XCOFF::RelocationSerializationSize64 ||
982 sizeof(Reloc) == XCOFF::RelocationSerializationSize32),
983 "Relocation structure is incorrect");
984 auto RelocationOrErr =
985 getObject<Reloc>(Data, reinterpret_cast<void *>(RelocAddr),
986 NumRelocEntries * sizeof(Reloc));
987 if (!RelocationOrErr)
988 return createError(
989 toString(RelocationOrErr.takeError()) + ": relocations with offset 0x" +
990 Twine::utohexstr(Sec.FileOffsetToRelocationInfo) + " and size 0x" +
991 Twine::utohexstr(NumRelocEntries * sizeof(Reloc)) +
992 " go past the end of the file");
993
994 const Reloc *StartReloc = RelocationOrErr.get();
995
996 return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries);
997}
998
999template <typename ExceptEnt>
1000Expected<ArrayRef<ExceptEnt>> XCOFFObjectFile::getExceptionEntries() const {
1001 assert((is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry64)) ||(static_cast <bool> ((is64Bit() && sizeof(ExceptEnt
) == sizeof(ExceptionSectionEntry64)) || (!is64Bit() &&
sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32))) ? void
(0) : __assert_fail ("(is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry64)) || (!is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32))"
, "llvm/lib/Object/XCOFFObjectFile.cpp", 1002, __extension__ __PRETTY_FUNCTION__
))
1002 (!is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32)))(static_cast <bool> ((is64Bit() && sizeof(ExceptEnt
) == sizeof(ExceptionSectionEntry64)) || (!is64Bit() &&
sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32))) ? void
(0) : __assert_fail ("(is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry64)) || (!is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32))"
, "llvm/lib/Object/XCOFFObjectFile.cpp", 1002, __extension__ __PRETTY_FUNCTION__
))
;
1003
1004 Expected<uintptr_t> ExceptionSectOrErr =
1005 getSectionFileOffsetToRawData(XCOFF::STYP_EXCEPT);
1006 if (!ExceptionSectOrErr)
1007 return ExceptionSectOrErr.takeError();
1008
1009 DataRefImpl DRI = getSectionByType(XCOFF::STYP_EXCEPT);
1010 if (DRI.p == 0)
1011 return ArrayRef<ExceptEnt>();
1012
1013 ExceptEnt *ExceptEntStart =
1014 reinterpret_cast<ExceptEnt *>(*ExceptionSectOrErr);
1015 return ArrayRef<ExceptEnt>(
1016 ExceptEntStart, ExceptEntStart + getSectionSize(DRI) / sizeof(ExceptEnt));
1017}
1018
1019template Expected<ArrayRef<ExceptionSectionEntry32>>
1020XCOFFObjectFile::getExceptionEntries() const;
1021template Expected<ArrayRef<ExceptionSectionEntry64>>
1022XCOFFObjectFile::getExceptionEntries() const;
1023
1024Expected<XCOFFStringTable>
1025XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
1026 // If there is a string table, then the buffer must contain at least 4 bytes
1027 // for the string table's size. Not having a string table is not an error.
1028 if (Error E = Binary::checkOffset(
1029 Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) {
1030 consumeError(std::move(E));
1031 return XCOFFStringTable{0, nullptr};
1032 }
1033
1034 // Read the size out of the buffer.
1035 uint32_t Size = support::endian::read32be(Obj->base() + Offset);
1036
1037 // If the size is less then 4, then the string table is just a size and no
1038 // string data.
1039 if (Size <= 4)
1040 return XCOFFStringTable{4, nullptr};
1041
1042 auto StringTableOrErr =
1043 getObject<char>(Obj->Data, Obj->base() + Offset, Size);
1044 if (!StringTableOrErr)
1045 return createError(toString(StringTableOrErr.takeError()) +
1046 ": string table with offset 0x" +
1047 Twine::utohexstr(Offset) + " and size 0x" +
1048 Twine::utohexstr(Size) +
1049 " goes past the end of the file");
1050
1051 const char *StringTablePtr = StringTableOrErr.get();
1052 if (StringTablePtr[Size - 1] != '\0')
1053 return errorCodeToError(object_error::string_table_non_null_end);
1054
1055 return XCOFFStringTable{Size, StringTablePtr};
1056}
1057
1058// This function returns the import file table. Each entry in the import file
1059// table consists of: "path_name\0base_name\0archive_member_name\0".
1060Expected<StringRef> XCOFFObjectFile::getImportFileTable() const {
1061 Expected<uintptr_t> LoaderSectionAddrOrError =
1062 getSectionFileOffsetToRawData(XCOFF::STYP_LOADER);
1063 if (!LoaderSectionAddrOrError)
1064 return LoaderSectionAddrOrError.takeError();
1065
1066 uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get();
1067 if (!LoaderSectionAddr)
1068 return StringRef();
1069
1070 uint64_t OffsetToImportFileTable = 0;
1071 uint64_t LengthOfImportFileTable = 0;
1072 if (is64Bit()) {
1073 const LoaderSectionHeader64 *LoaderSec64 =
1074 viewAs<LoaderSectionHeader64>(LoaderSectionAddr);
1075 OffsetToImportFileTable = LoaderSec64->OffsetToImpid;
1076 LengthOfImportFileTable = LoaderSec64->LengthOfImpidStrTbl;
1077 } else {
1078 const LoaderSectionHeader32 *LoaderSec32 =
1079 viewAs<LoaderSectionHeader32>(LoaderSectionAddr);
1080 OffsetToImportFileTable = LoaderSec32->OffsetToImpid;
1081 LengthOfImportFileTable = LoaderSec32->LengthOfImpidStrTbl;
1082 }
1083
1084 auto ImportTableOrErr = getObject<char>(
1085 Data,
1086 reinterpret_cast<void *>(LoaderSectionAddr + OffsetToImportFileTable),
1087 LengthOfImportFileTable);
1088 if (!ImportTableOrErr)
1089 return createError(
1090 toString(ImportTableOrErr.takeError()) +
1091 ": import file table with offset 0x" +
1092 Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) +
1093 " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) +
1094 " goes past the end of the file");
1095
1096 const char *ImportTablePtr = ImportTableOrErr.get();
1097 if (ImportTablePtr[LengthOfImportFileTable - 1] != '\0')
1098 return createError(
1099 ": import file name table with offset 0x" +
1100 Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) +
1101 " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) +
1102 " must end with a null terminator");
1103
1104 return StringRef(ImportTablePtr, LengthOfImportFileTable);
1105}
1106
1107Expected<std::unique_ptr<XCOFFObjectFile>>
1108XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
1109 // Can't use std::make_unique because of the private constructor.
1110 std::unique_ptr<XCOFFObjectFile> Obj;
1111 Obj.reset(new XCOFFObjectFile(Type, MBR));
1112
1113 uint64_t CurOffset = 0;
1114 const auto *Base = Obj->base();
1115 MemoryBufferRef Data = Obj->Data;
1116
1117 // Parse file header.
1118 auto FileHeaderOrErr =
1119 getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize());
1120 if (Error E = FileHeaderOrErr.takeError())
1121 return std::move(E);
1122 Obj->FileHeader = FileHeaderOrErr.get();
1123
1124 CurOffset += Obj->getFileHeaderSize();
1125
1126 if (Obj->getOptionalHeaderSize()) {
1127 auto AuxiliaryHeaderOrErr =
1128 getObject<void>(Data, Base + CurOffset, Obj->getOptionalHeaderSize());
1129 if (Error E = AuxiliaryHeaderOrErr.takeError())
1130 return std::move(E);
1131 Obj->AuxiliaryHeader = AuxiliaryHeaderOrErr.get();
1132 }
1133
1134 CurOffset += Obj->getOptionalHeaderSize();
1135
1136 // Parse the section header table if it is present.
1137 if (Obj->getNumberOfSections()) {
1138 uint64_t SectionHeadersSize =
1139 Obj->getNumberOfSections() * Obj->getSectionHeaderSize();
1140 auto SecHeadersOrErr =
1141 getObject<void>(Data, Base + CurOffset, SectionHeadersSize);
1142 if (!SecHeadersOrErr)
1143 return createError(toString(SecHeadersOrErr.takeError()) +
1144 ": section headers with offset 0x" +
1145 Twine::utohexstr(CurOffset) + " and size 0x" +
1146 Twine::utohexstr(SectionHeadersSize) +
1147 " go past the end of the file");
1148
1149 Obj->SectionHeaderTable = SecHeadersOrErr.get();
1150 }
1151
1152 const uint32_t NumberOfSymbolTableEntries =
1153 Obj->getNumberOfSymbolTableEntries();
1154
1155 // If there is no symbol table we are done parsing the memory buffer.
1156 if (NumberOfSymbolTableEntries == 0)
1157 return std::move(Obj);
1158
1159 // Parse symbol table.
1160 CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64()
1161 : Obj->getSymbolTableOffset32();
1162 const uint64_t SymbolTableSize =
1163 static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) *
1164 NumberOfSymbolTableEntries;
1165 auto SymTableOrErr =
1166 getObject<void *>(Data, Base + CurOffset, SymbolTableSize);
1167 if (!SymTableOrErr)
1168 return createError(
1169 toString(SymTableOrErr.takeError()) + ": symbol table with offset 0x" +
1170 Twine::utohexstr(CurOffset) + " and size 0x" +
1171 Twine::utohexstr(SymbolTableSize) + " goes past the end of the file");
1172
1173 Obj->SymbolTblPtr = SymTableOrErr.get();
1174 CurOffset += SymbolTableSize;
1175
1176 // Parse String table.
1177 Expected<XCOFFStringTable> StringTableOrErr =
1178 parseStringTable(Obj.get(), CurOffset);
1179 if (Error E = StringTableOrErr.takeError())
1180 return std::move(E);
1181 Obj->StringTable = StringTableOrErr.get();
1182
1183 return std::move(Obj);
1184}
1185
1186Expected<std::unique_ptr<ObjectFile>>
1187ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
1188 unsigned FileType) {
1189 return XCOFFObjectFile::create(FileType, MemBufRef);
1190}
1191
1192bool XCOFFSymbolRef::isFunction() const {
1193 if (!isCsectSymbol())
1194 return false;
1195
1196 if (getSymbolType() & FunctionSym)
1197 return true;
1198
1199 Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef();
1200 if (!ExpCsectAuxEnt) {
1201 // If we could not get the CSECT auxiliary entry, then treat this symbol as
1202 // if it isn't a function. Consume the error and return `false` to move on.
1203 consumeError(ExpCsectAuxEnt.takeError());
1204 return false;
1205 }
1206
1207 const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get();
1208
1209 // A function definition should be a label definition.
1210 // FIXME: This is not necessarily the case when -ffunction-sections is
1211 // enabled.
1212 if (!CsectAuxRef.isLabel())
1213 return false;
1214
1215 if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR)
1216 return false;
1217
1218 const int16_t SectNum = getSectionNumber();
1219 Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum);
1220 if (!SI) {
1221 // If we could not get the section, then this symbol should not be
1222 // a function. So consume the error and return `false` to move on.
1223 consumeError(SI.takeError());
1224 return false;
1225 }
1226
1227 return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT);
1228}
1229
1230bool XCOFFSymbolRef::isCsectSymbol() const {
1231 XCOFF::StorageClass SC = getStorageClass();
1232 return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT ||
1233 SC == XCOFF::C_HIDEXT);
1234}
1235
1236Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const {
1237 assert(isCsectSymbol() &&(static_cast <bool> (isCsectSymbol() && "Calling csect symbol interface with a non-csect symbol."
) ? void (0) : __assert_fail ("isCsectSymbol() && \"Calling csect symbol interface with a non-csect symbol.\""
, "llvm/lib/Object/XCOFFObjectFile.cpp", 1238, __extension__ __PRETTY_FUNCTION__
))
1238 "Calling csect symbol interface with a non-csect symbol.")(static_cast <bool> (isCsectSymbol() && "Calling csect symbol interface with a non-csect symbol."
) ? void (0) : __assert_fail ("isCsectSymbol() && \"Calling csect symbol interface with a non-csect symbol.\""
, "llvm/lib/Object/XCOFFObjectFile.cpp", 1238, __extension__ __PRETTY_FUNCTION__
))
;
1239
1240 uint8_t NumberOfAuxEntries = getNumberOfAuxEntries();
1241
1242 Expected<StringRef> NameOrErr = getName();
1243 if (auto Err = NameOrErr.takeError())
1244 return std::move(Err);
1245
1246 uint32_t SymbolIdx = OwningObjectPtr->getSymbolIndex(getEntryAddress());
1247 if (!NumberOfAuxEntries) {
1248 return createError("csect symbol \"" + *NameOrErr + "\" with index " +
1249 Twine(SymbolIdx) + " contains no auxiliary entry");
1250 }
1251
1252 if (!OwningObjectPtr->is64Bit()) {
1253 // In XCOFF32, the csect auxilliary entry is always the last auxiliary
1254 // entry for the symbol.
1255 uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
1256 getEntryAddress(), NumberOfAuxEntries);
1257 return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr));
1258 }
1259
1260 // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type.
1261 // We need to iterate through all the auxiliary entries to find it.
1262 for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) {
1263 uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
1264 getEntryAddress(), Index);
1265 if (*OwningObjectPtr->getSymbolAuxType(AuxAddr) ==
1266 XCOFF::SymbolAuxType::AUX_CSECT) {
1267#ifndef NDEBUG
1268 OwningObjectPtr->checkSymbolEntryPointer(AuxAddr);
1269#endif
1270 return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr));
1271 }
1272 }
1273
1274 return createError(
1275 "a csect auxiliary entry has not been found for symbol \"" + *NameOrErr +
1276 "\" with index " + Twine(SymbolIdx));
1277}
1278
1279Expected<StringRef> XCOFFSymbolRef::getName() const {
1280 // A storage class value with the high-order bit on indicates that the name is
1281 // a symbolic debugger stabstring.
1282 if (getStorageClass() & 0x80)
1283 return StringRef("Unimplemented Debug Name");
1284
1285 if (Entry32) {
1286 if (Entry32->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
1287 return generateXCOFFFixedNameStringRef(Entry32->SymbolName);
1288
1289 return OwningObjectPtr->getStringTableEntry(Entry32->NameInStrTbl.Offset);
1290 }
1291
1292 return OwningObjectPtr->getStringTableEntry(Entry64->Offset);
1293}
1294
1295// Explictly instantiate template classes.
1296template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
1297template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
1298
1299template struct XCOFFRelocation<llvm::support::ubig32_t>;
1300template struct XCOFFRelocation<llvm::support::ubig64_t>;
1301
1302template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation64>>
1303llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader64,
1304 llvm::object::XCOFFRelocation64>(
1305 llvm::object::XCOFFSectionHeader64 const &) const;
1306template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation32>>
1307llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader32,
1308 llvm::object::XCOFFRelocation32>(
1309 llvm::object::XCOFFSectionHeader32 const &) const;
1310
1311bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) {
1312 if (Bytes.size() < 4)
1313 return false;
1314
1315 return support::endian::read32be(Bytes.data()) == 0;
1316}
1317
1318#define GETVALUEWITHMASK(X) (Data & (TracebackTable::X))
1319#define GETVALUEWITHMASKSHIFT(X, S) \
1320 ((Data & (TracebackTable::X)) >> (TracebackTable::S))
1321
1322Expected<TBVectorExt> TBVectorExt::create(StringRef TBvectorStrRef) {
1323 Error Err = Error::success();
1324 TBVectorExt TBTVecExt(TBvectorStrRef, Err);
1325 if (Err)
1326 return std::move(Err);
1327 return TBTVecExt;
1328}
1329
1330TBVectorExt::TBVectorExt(StringRef TBvectorStrRef, Error &Err) {
1331 const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data());
1332 Data = support::endian::read16be(Ptr);
1333 uint32_t VecParmsTypeValue = support::endian::read32be(Ptr + 2);
1334 unsigned ParmsNum =
1335 GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift);
1336
1337 ErrorAsOutParameter EAO(&Err);
1338 Expected<SmallString<32>> VecParmsTypeOrError =
1339 parseVectorParmsType(VecParmsTypeValue, ParmsNum);
1340 if (!VecParmsTypeOrError)
1341 Err = VecParmsTypeOrError.takeError();
1342 else
1343 VecParmsInfo = VecParmsTypeOrError.get();
1344}
1345
1346uint8_t TBVectorExt::getNumberOfVRSaved() const {
1347 return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift);
1348}
1349
1350bool TBVectorExt::isVRSavedOnStack() const {
1351 return GETVALUEWITHMASK(IsVRSavedOnStackMask);
1352}
1353
1354bool TBVectorExt::hasVarArgs() const {
1355 return GETVALUEWITHMASK(HasVarArgsMask);
1356}
1357
1358uint8_t TBVectorExt::getNumberOfVectorParms() const {
1359 return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask,
1360 NumberOfVectorParmsShift);
1361}
1362
1363bool TBVectorExt::hasVMXInstruction() const {
1364 return GETVALUEWITHMASK(HasVMXInstructionMask);
1365}
1366#undef GETVALUEWITHMASK
1367#undef GETVALUEWITHMASKSHIFT
1368
1369Expected<XCOFFTracebackTable> XCOFFTracebackTable::create(const uint8_t *Ptr,
1370 uint64_t &Size) {
1371 Error Err = Error::success();
1372 XCOFFTracebackTable TBT(Ptr, Size, Err);
1373 if (Err)
1374 return std::move(Err);
1375 return TBT;
1376}
1377
1378XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
1379 Error &Err)
1380 : TBPtr(Ptr) {
1381 ErrorAsOutParameter EAO(&Err);
1382 DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false,
1383 /*AddressSize=*/0);
1384 DataExtractor::Cursor Cur(/*Offset=*/0);
1385
1386 // Skip 8 bytes of mandatory fields.
1387 DE.getU64(Cur);
1388
1389 unsigned FixedParmsNum = getNumberOfFixedParms();
1390 unsigned FloatingParmsNum = getNumberOfFPParms();
1391 uint32_t ParamsTypeValue = 0;
1392
1393 // Begin to parse optional fields.
1394 if (Cur && (FixedParmsNum + FloatingParmsNum) > 0)
1395 ParamsTypeValue = DE.getU32(Cur);
1396
1397 if (Cur && hasTraceBackTableOffset())
1398 TraceBackTableOffset = DE.getU32(Cur);
1399
1400 if (Cur && isInterruptHandler())
1401 HandlerMask = DE.getU32(Cur);
1402
1403 if (Cur && hasControlledStorage()) {
1404 NumOfCtlAnchors = DE.getU32(Cur);
1405 if (Cur && NumOfCtlAnchors) {
1406 SmallVector<uint32_t, 8> Disp;
1407 Disp.reserve(*NumOfCtlAnchors);
1408 for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I)
1409 Disp.push_back(DE.getU32(Cur));
1410 if (Cur)
1411 ControlledStorageInfoDisp = std::move(Disp);
1412 }
1413 }
1414
1415 if (Cur && isFuncNamePresent()) {
1416 uint16_t FunctionNameLen = DE.getU16(Cur);
1417 if (Cur)
1418 FunctionName = DE.getBytes(Cur, FunctionNameLen);
1419 }
1420
1421 if (Cur && isAllocaUsed())
1422 AllocaRegister = DE.getU8(Cur);
1423
1424 unsigned VectorParmsNum = 0;
1425 if (Cur && hasVectorInfo()) {
1426 StringRef VectorExtRef = DE.getBytes(Cur, 6);
1427 if (Cur) {
1428 Expected<TBVectorExt> TBVecExtOrErr = TBVectorExt::create(VectorExtRef);
1429 if (!TBVecExtOrErr) {
1430 Err = TBVecExtOrErr.takeError();
1431 return;
1432 }
1433 VecExt = TBVecExtOrErr.get();
1434 VectorParmsNum = VecExt->getNumberOfVectorParms();
1435 }
1436 }
1437
1438 // As long as there is no fixed-point or floating-point parameter, this
1439 // field remains not present even when hasVectorInfo gives true and
1440 // indicates the presence of vector parameters.
1441 if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) {
1442 Expected<SmallString<32>> ParmsTypeOrError =
1443 hasVectorInfo()
1444 ? parseParmsTypeWithVecInfo(ParamsTypeValue, FixedParmsNum,
1445 FloatingParmsNum, VectorParmsNum)
1446 : parseParmsType(ParamsTypeValue, FixedParmsNum, FloatingParmsNum);
1447
1448 if (!ParmsTypeOrError) {
1449 Err = ParmsTypeOrError.takeError();
1450 return;
1451 }
1452 ParmsType = ParmsTypeOrError.get();
1453 }
1454
1455 if (Cur && hasExtensionTable())
1456 ExtensionTable = DE.getU8(Cur);
1457
1458 if (!Cur)
1459 Err = Cur.takeError();
1460
1461 Size = Cur.tell();
1462}
1463
1464#define GETBITWITHMASK(P, X) \
1465 (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X))
1466#define GETBITWITHMASKSHIFT(P, X, S) \
1467 ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >> \
1468 (TracebackTable::S))
1469
1470uint8_t XCOFFTracebackTable::getVersion() const {
1471 return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift);
1472}
1473
1474uint8_t XCOFFTracebackTable::getLanguageID() const {
1475 return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift);
1476}
1477
1478bool XCOFFTracebackTable::isGlobalLinkage() const {
1479 return GETBITWITHMASK(0, IsGlobaLinkageMask);
1480}
1481
1482bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const {
1483 return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask);
1484}
1485
1486bool XCOFFTracebackTable::hasTraceBackTableOffset() const {
1487 return GETBITWITHMASK(0, HasTraceBackTableOffsetMask);
1488}
1489
1490bool XCOFFTracebackTable::isInternalProcedure() const {
1491 return GETBITWITHMASK(0, IsInternalProcedureMask);
1492}
1493
1494bool XCOFFTracebackTable::hasControlledStorage() const {
1495 return GETBITWITHMASK(0, HasControlledStorageMask);
1496}
1497
1498bool XCOFFTracebackTable::isTOCless() const {
1499 return GETBITWITHMASK(0, IsTOClessMask);
1500}
1501
1502bool XCOFFTracebackTable::isFloatingPointPresent() const {
1503 return GETBITWITHMASK(0, IsFloatingPointPresentMask);
1504}
1505
1506bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const {
1507 return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask);
1508}
1509
1510bool XCOFFTracebackTable::isInterruptHandler() const {
1511 return GETBITWITHMASK(0, IsInterruptHandlerMask);
1512}
1513
1514bool XCOFFTracebackTable::isFuncNamePresent() const {
1515 return GETBITWITHMASK(0, IsFunctionNamePresentMask);
1516}
1517
1518bool XCOFFTracebackTable::isAllocaUsed() const {
1519 return GETBITWITHMASK(0, IsAllocaUsedMask);
1520}
1521
1522uint8_t XCOFFTracebackTable::getOnConditionDirective() const {
1523 return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask,
1524 OnConditionDirectiveShift);
1525}
1526
1527bool XCOFFTracebackTable::isCRSaved() const {
1528 return GETBITWITHMASK(0, IsCRSavedMask);
1529}
1530
1531bool XCOFFTracebackTable::isLRSaved() const {
1532 return GETBITWITHMASK(0, IsLRSavedMask);
1533}
1534
1535bool XCOFFTracebackTable::isBackChainStored() const {
1536 return GETBITWITHMASK(4, IsBackChainStoredMask);
1537}
1538
1539bool XCOFFTracebackTable::isFixup() const {
1540 return GETBITWITHMASK(4, IsFixupMask);
1541}
1542
1543uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const {
1544 return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift);
1545}
1546
1547bool XCOFFTracebackTable::hasExtensionTable() const {
1548 return GETBITWITHMASK(4, HasExtensionTableMask);
1549}
1550
1551bool XCOFFTracebackTable::hasVectorInfo() const {
1552 return GETBITWITHMASK(4, HasVectorInfoMask);
1553}
1554
1555uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const {
1556 return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift);
1557}
1558
1559uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const {
1560 return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask,
1561 NumberOfFixedParmsShift);
1562}
1563
1564uint8_t XCOFFTracebackTable::getNumberOfFPParms() const {
1565 return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask,
1566 NumberOfFloatingPointParmsShift);
1567}
1568
1569bool XCOFFTracebackTable::hasParmsOnStack() const {
1570 return GETBITWITHMASK(4, HasParmsOnStackMask);
1571}
1572
1573#undef GETBITWITHMASK
1574#undef GETBITWITHMASKSHIFT
1575} // namespace object
1576} // namespace llvm

/build/source/llvm/include/llvm/Object/XCOFFObjectFile.h

1//===- XCOFFObjectFile.h - XCOFF object file implementation -----*- C++ -*-===//
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 declares the XCOFFObjectFile class.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_OBJECT_XCOFFOBJECTFILE_H
14#define LLVM_OBJECT_XCOFFOBJECTFILE_H
15
16#include "llvm/ADT/SmallString.h"
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/BinaryFormat/XCOFF.h"
19#include "llvm/Object/ObjectFile.h"
20#include "llvm/Support/Endian.h"
21#include <limits>
22
23namespace llvm {
24namespace object {
25
26struct XCOFFFileHeader32 {
27 support::ubig16_t Magic;
28 support::ubig16_t NumberOfSections;
29
30 // Unix time value, value of 0 indicates no timestamp.
31 // Negative values are reserved.
32 support::big32_t TimeStamp;
33
34 support::ubig32_t SymbolTableOffset; // File offset to symbol table.
35 support::big32_t NumberOfSymTableEntries;
36 support::ubig16_t AuxHeaderSize;
37 support::ubig16_t Flags;
38};
39
40struct XCOFFFileHeader64 {
41 support::ubig16_t Magic;
42 support::ubig16_t NumberOfSections;
43
44 // Unix time value, value of 0 indicates no timestamp.
45 // Negative values are reserved.
46 support::big32_t TimeStamp;
47
48 support::ubig64_t SymbolTableOffset; // File offset to symbol table.
49 support::ubig16_t AuxHeaderSize;
50 support::ubig16_t Flags;
51 support::ubig32_t NumberOfSymTableEntries;
52};
53
54template <typename T> struct XCOFFAuxiliaryHeader {
55 static constexpr uint8_t AuxiHeaderFlagMask = 0xF0;
56 static constexpr uint8_t AuxiHeaderTDataAlignmentMask = 0x0F;
57
58public:
59 uint8_t getFlag() const {
60 return static_cast<const T *>(this)->FlagAndTDataAlignment &
61 AuxiHeaderFlagMask;
62 }
63
64 uint8_t getTDataAlignment() const {
65 return static_cast<const T *>(this)->FlagAndTDataAlignment &
66 AuxiHeaderTDataAlignmentMask;
67 }
68
69 uint16_t getVersion() const { return static_cast<const T *>(this)->Version; }
70};
71
72struct XCOFFAuxiliaryHeader32 : XCOFFAuxiliaryHeader<XCOFFAuxiliaryHeader32> {
73 support::ubig16_t
74 AuxMagic; ///< If the value of the o_vstamp field is greater than 1, the
75 ///< o_mflags field is reserved for future use and it should
76 ///< contain 0. Otherwise, this field is not used.
77 support::ubig16_t
78 Version; ///< The valid values are 1 and 2. When the o_vstamp field is 2
79 ///< in an XCOFF32 file, the new interpretation of the n_type
80 ///< field in the symbol table entry is used.
81 support::ubig32_t TextSize;
82 support::ubig32_t InitDataSize;
83 support::ubig32_t BssDataSize;
84 support::ubig32_t EntryPointAddr;
85 support::ubig32_t TextStartAddr;
86 support::ubig32_t DataStartAddr;
87 support::ubig32_t TOCAnchorAddr;
88 support::ubig16_t SecNumOfEntryPoint;
89 support::ubig16_t SecNumOfText;
90 support::ubig16_t SecNumOfData;
91 support::ubig16_t SecNumOfTOC;
92 support::ubig16_t SecNumOfLoader;
93 support::ubig16_t SecNumOfBSS;
94 support::ubig16_t MaxAlignOfText;
95 support::ubig16_t MaxAlignOfData;
96 support::ubig16_t ModuleType;
97 uint8_t CpuFlag;
98 uint8_t CpuType;
99 support::ubig32_t MaxStackSize; ///< If the value is 0, the system default
100 ///< maximum stack size is used.
101 support::ubig32_t MaxDataSize; ///< If the value is 0, the system default
102 ///< maximum data size is used.
103 support::ubig32_t
104 ReservedForDebugger; ///< This field should contain 0. When a loaded
105 ///< program is being debugged, the memory image of
106 ///< this field may be modified by a debugger to
107 ///< insert a trap instruction.
108 uint8_t TextPageSize; ///< Specifies the size of pages for the exec text. The
109 ///< default value is 0 (system-selected page size).
110 uint8_t DataPageSize; ///< Specifies the size of pages for the exec data. The
111 ///< default value is 0 (system-selected page size).
112 uint8_t StackPageSize; ///< Specifies the size of pages for the stack. The
113 ///< default value is 0 (system-selected page size).
114 uint8_t FlagAndTDataAlignment;
115 support::ubig16_t SecNumOfTData;
116 support::ubig16_t SecNumOfTBSS;
117};
118
119struct XCOFFAuxiliaryHeader64 : XCOFFAuxiliaryHeader<XCOFFAuxiliaryHeader64> {
120 support::ubig16_t AuxMagic;
121 support::ubig16_t Version;
122 support::ubig32_t ReservedForDebugger;
123 support::ubig64_t TextStartAddr;
124 support::ubig64_t DataStartAddr;
125 support::ubig64_t TOCAnchorAddr;
126 support::ubig16_t SecNumOfEntryPoint;
127 support::ubig16_t SecNumOfText;
128 support::ubig16_t SecNumOfData;
129 support::ubig16_t SecNumOfTOC;
130 support::ubig16_t SecNumOfLoader;
131 support::ubig16_t SecNumOfBSS;
132 support::ubig16_t MaxAlignOfText;
133 support::ubig16_t MaxAlignOfData;
134 support::ubig16_t ModuleType;
135 uint8_t CpuFlag;
136 uint8_t CpuType;
137 uint8_t TextPageSize;
138 uint8_t DataPageSize;
139 uint8_t StackPageSize;
140 uint8_t FlagAndTDataAlignment;
141 support::ubig64_t TextSize;
142 support::ubig64_t InitDataSize;
143 support::ubig64_t BssDataSize;
144 support::ubig64_t EntryPointAddr;
145 support::ubig64_t MaxStackSize;
146 support::ubig64_t MaxDataSize;
147 support::ubig16_t SecNumOfTData;
148 support::ubig16_t SecNumOfTBSS;
149 support::ubig16_t XCOFF64Flag;
150};
151
152template <typename T> struct XCOFFSectionHeader {
153 // Least significant 3 bits are reserved.
154 static constexpr unsigned SectionFlagsReservedMask = 0x7;
155
156 // The low order 16 bits of section flags denotes the section type.
157 static constexpr unsigned SectionFlagsTypeMask = 0xffffu;
158
159public:
160 StringRef getName() const;
161 uint16_t getSectionType() const;
162 bool isReservedSectionType() const;
163};
164
165// Explicit extern template declarations.
166struct XCOFFSectionHeader32;
167struct XCOFFSectionHeader64;
168extern template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
169extern template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
170
171struct XCOFFSectionHeader32 : XCOFFSectionHeader<XCOFFSectionHeader32> {
172 char Name[XCOFF::NameSize];
173 support::ubig32_t PhysicalAddress;
174 support::ubig32_t VirtualAddress;
175 support::ubig32_t SectionSize;
176 support::ubig32_t FileOffsetToRawData;
177 support::ubig32_t FileOffsetToRelocationInfo;
178 support::ubig32_t FileOffsetToLineNumberInfo;
179 support::ubig16_t NumberOfRelocations;
180 support::ubig16_t NumberOfLineNumbers;
181 support::big32_t Flags;
182};
183
184struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> {
185 char Name[XCOFF::NameSize];
186 support::ubig64_t PhysicalAddress;
187 support::ubig64_t VirtualAddress;
188 support::ubig64_t SectionSize;
189 support::big64_t FileOffsetToRawData;
190 support::big64_t FileOffsetToRelocationInfo;
191 support::big64_t FileOffsetToLineNumberInfo;
192 support::ubig32_t NumberOfRelocations;
193 support::ubig32_t NumberOfLineNumbers;
194 support::big32_t Flags;
195 char Padding[4];
196};
197
198struct LoaderSectionHeader32 {
199 support::ubig32_t Version;
200 support::ubig32_t NumberOfSymTabEnt;
201 support::ubig32_t NumberOfRelTabEnt;
202 support::ubig32_t LengthOfImpidStrTbl;
203 support::ubig32_t NumberOfImpid;
204 support::big32_t OffsetToImpid;
205 support::ubig32_t LengthOfStrTbl;
206 support::big32_t OffsetToStrTbl;
207};
208
209struct LoaderSectionHeader64 {
210 support::ubig32_t Version;
211 support::ubig32_t NumberOfSymTabEnt;
212 support::ubig32_t NumberOfRelTabEnt;
213 support::ubig32_t LengthOfImpidStrTbl;
214 support::ubig32_t NumberOfImpid;
215 support::ubig32_t LengthOfStrTbl;
216 support::big64_t OffsetToImpid;
217 support::big64_t OffsetToStrTbl;
218 support::big64_t OffsetToSymTbl;
219 support::big64_t OffsetToRelEnt;
220};
221
222template <typename AddressType> struct ExceptionSectionEntry {
223 union {
224 support::ubig32_t SymbolIdx;
225 AddressType TrapInstAddr;
226 };
227 uint8_t LangId;
228 uint8_t Reason;
229
230 uint32_t getSymbolIndex() const {
231 assert(Reason == 0 && "Get symbol table index of the function only when "(static_cast <bool> (Reason == 0 && "Get symbol table index of the function only when "
"the e_reason field is 0.") ? void (0) : __assert_fail ("Reason == 0 && \"Get symbol table index of the function only when \" \"the e_reason field is 0.\""
, "llvm/include/llvm/Object/XCOFFObjectFile.h", 232, __extension__
__PRETTY_FUNCTION__))
232 "the e_reason field is 0.")(static_cast <bool> (Reason == 0 && "Get symbol table index of the function only when "
"the e_reason field is 0.") ? void (0) : __assert_fail ("Reason == 0 && \"Get symbol table index of the function only when \" \"the e_reason field is 0.\""
, "llvm/include/llvm/Object/XCOFFObjectFile.h", 232, __extension__
__PRETTY_FUNCTION__))
;
233 return SymbolIdx;
234 }
235
236 uint64_t getTrapInstAddr() const {
237 assert(Reason != 0 && "Zero is not a valid trap exception reason code.")(static_cast <bool> (Reason != 0 && "Zero is not a valid trap exception reason code."
) ? void (0) : __assert_fail ("Reason != 0 && \"Zero is not a valid trap exception reason code.\""
, "llvm/include/llvm/Object/XCOFFObjectFile.h", 237, __extension__
__PRETTY_FUNCTION__))
;
238 return TrapInstAddr;
239 }
240 uint8_t getLangID() const { return LangId; }
241 uint8_t getReason() const { return Reason; }
242};
243
244typedef ExceptionSectionEntry<support::ubig32_t> ExceptionSectionEntry32;
245typedef ExceptionSectionEntry<support::ubig64_t> ExceptionSectionEntry64;
246
247// Explicit extern template declarations.
248extern template struct ExceptionSectionEntry<support::ubig32_t>;
249extern template struct ExceptionSectionEntry<support::ubig64_t>;
250
251struct XCOFFStringTable {
252 uint32_t Size;
253 const char *Data;
254};
255
256struct XCOFFCsectAuxEnt32 {
257 support::ubig32_t SectionOrLength;
258 support::ubig32_t ParameterHashIndex;
259 support::ubig16_t TypeChkSectNum;
260 uint8_t SymbolAlignmentAndType;
261 XCOFF::StorageMappingClass StorageMappingClass;
262 support::ubig32_t StabInfoIndex;
263 support::ubig16_t StabSectNum;
264};
265
266struct XCOFFCsectAuxEnt64 {
267 support::ubig32_t SectionOrLengthLowByte;
268 support::ubig32_t ParameterHashIndex;
269 support::ubig16_t TypeChkSectNum;
270 uint8_t SymbolAlignmentAndType;
271 XCOFF::StorageMappingClass StorageMappingClass;
272 support::ubig32_t SectionOrLengthHighByte;
273 uint8_t Pad;
274 XCOFF::SymbolAuxType AuxType;
275};
276
277class XCOFFCsectAuxRef {
278public:
279 static constexpr uint8_t SymbolTypeMask = 0x07;
280 static constexpr uint8_t SymbolAlignmentMask = 0xF8;
281 static constexpr size_t SymbolAlignmentBitOffset = 3;
282
283 XCOFFCsectAuxRef(const XCOFFCsectAuxEnt32 *Entry32) : Entry32(Entry32) {}
284 XCOFFCsectAuxRef(const XCOFFCsectAuxEnt64 *Entry64) : Entry64(Entry64) {}
285
286 // For getSectionOrLength(),
287 // If the symbol type is XTY_SD or XTY_CM, the csect length.
288 // If the symbol type is XTY_LD, the symbol table
289 // index of the containing csect.
290 // If the symbol type is XTY_ER, 0.
291 uint64_t getSectionOrLength() const {
292 return Entry32 ? getSectionOrLength32() : getSectionOrLength64();
293 }
294
295 uint32_t getSectionOrLength32() const {
296 assert(Entry32 && "32-bit interface called on 64-bit object file.")(static_cast <bool> (Entry32 && "32-bit interface called on 64-bit object file."
) ? void (0) : __assert_fail ("Entry32 && \"32-bit interface called on 64-bit object file.\""
, "llvm/include/llvm/Object/XCOFFObjectFile.h", 296, __extension__
__PRETTY_FUNCTION__))
;
297 return Entry32->SectionOrLength;
298 }
299
300 uint64_t getSectionOrLength64() const {
301 assert(Entry64 && "64-bit interface called on 32-bit object file.")(static_cast <bool> (Entry64 && "64-bit interface called on 32-bit object file."
) ? void (0) : __assert_fail ("Entry64 && \"64-bit interface called on 32-bit object file.\""
, "llvm/include/llvm/Object/XCOFFObjectFile.h", 301, __extension__
__PRETTY_FUNCTION__))
;
302 return (static_cast<uint64_t>(Entry64->SectionOrLengthHighByte) << 32) |
303 Entry64->SectionOrLengthLowByte;
304 }
305
306#define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X
307
308 uint32_t getParameterHashIndex() const {
309 return GETVALUE(ParameterHashIndex);
310 }
311
312 uint16_t getTypeChkSectNum() const { return GETVALUE(TypeChkSectNum); }
313
314 XCOFF::StorageMappingClass getStorageMappingClass() const {
315 return GETVALUE(StorageMappingClass);
316 }
317
318 uintptr_t getEntryAddress() const {
319 return Entry32 ? reinterpret_cast<uintptr_t>(Entry32)
320 : reinterpret_cast<uintptr_t>(Entry64);
321 }
322
323 uint16_t getAlignmentLog2() const {
324 return (getSymbolAlignmentAndType() & SymbolAlignmentMask) >>
325 SymbolAlignmentBitOffset;
326 }
327
328 uint8_t getSymbolType() const {
329 return getSymbolAlignmentAndType() & SymbolTypeMask;
330 }
331
332 bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; }
333
334 uint32_t getStabInfoIndex32() const {
335 assert(Entry32 && "32-bit interface called on 64-bit object file.")(static_cast <bool> (Entry32 && "32-bit interface called on 64-bit object file."
) ? void (0) : __assert_fail ("Entry32 && \"32-bit interface called on 64-bit object file.\""
, "llvm/include/llvm/Object/XCOFFObjectFile.h", 335, __extension__
__PRETTY_FUNCTION__))
;
336 return Entry32->StabInfoIndex;
337 }
338
339 uint16_t getStabSectNum32() const {
340 assert(Entry32 && "32-bit interface called on 64-bit object file.")(static_cast <bool> (Entry32 && "32-bit interface called on 64-bit object file."
) ? void (0) : __assert_fail ("Entry32 && \"32-bit interface called on 64-bit object file.\""
, "llvm/include/llvm/Object/XCOFFObjectFile.h", 340, __extension__
__PRETTY_FUNCTION__))
;
341 return Entry32->StabSectNum;
342 }
343
344 XCOFF::SymbolAuxType getAuxType64() const {
345 assert(Entry64 && "64-bit interface called on 32-bit object file.")(static_cast <bool> (Entry64 && "64-bit interface called on 32-bit object file."
) ? void (0) : __assert_fail ("Entry64 && \"64-bit interface called on 32-bit object file.\""
, "llvm/include/llvm/Object/XCOFFObjectFile.h", 345, __extension__
__PRETTY_FUNCTION__))
;
346 return Entry64->AuxType;
347 }
348
349private:
350 uint8_t getSymbolAlignmentAndType() const {
351 return GETVALUE(SymbolAlignmentAndType);
352 }
353
354#undef GETVALUE
355
356 const XCOFFCsectAuxEnt32 *Entry32 = nullptr;
357 const XCOFFCsectAuxEnt64 *Entry64 = nullptr;
358};
359
360struct XCOFFFileAuxEnt {
361 typedef struct {
362 support::big32_t Magic; // Zero indicates name in string table.
363 support::ubig32_t Offset;
364 char NamePad[XCOFF::FileNamePadSize];
365 } NameInStrTblType;
366 union {
367 char Name[XCOFF::NameSize + XCOFF::FileNamePadSize];
368 NameInStrTblType NameInStrTbl;
369 };
370 XCOFF::CFileStringType Type;
371 uint8_t ReservedZeros[2];
372 XCOFF::SymbolAuxType AuxType; // 64-bit XCOFF file only.
373};
374
375struct XCOFFSectAuxEntForStat {
376 support::ubig32_t SectionLength;
377 support::ubig16_t NumberOfRelocEnt;
378 support::ubig16_t NumberOfLineNum;
379 uint8_t Pad[10];
380}; // 32-bit XCOFF file only.
381
382struct XCOFFFunctionAuxEnt32 {
383 support::ubig32_t OffsetToExceptionTbl;
384 support::ubig32_t SizeOfFunction;
385 support::ubig32_t PtrToLineNum;
386 support::big32_t SymIdxOfNextBeyond;
387 uint8_t Pad[2];
388};
389
390struct XCOFFFunctionAuxEnt64 {
391 support::ubig64_t PtrToLineNum;
392 support::ubig32_t SizeOfFunction;
393 support::big32_t SymIdxOfNextBeyond;
394 uint8_t Pad;
395 XCOFF::SymbolAuxType AuxType; // Contains _AUX_FCN; Type of auxiliary entry
396};
397
398struct XCOFFExceptionAuxEnt {
399 support::ubig64_t OffsetToExceptionTbl;
400 support::ubig32_t SizeOfFunction;
401 support::big32_t SymIdxOfNextBeyond;
402 uint8_t Pad;
403 XCOFF::SymbolAuxType AuxType; // Contains _AUX_EXCEPT; Type of auxiliary entry
404};
405
406struct XCOFFBlockAuxEnt32 {
407 uint8_t ReservedZeros1[2];
408 support::ubig16_t LineNumHi;
409 support::ubig16_t LineNumLo;
410 uint8_t ReservedZeros2[12];
411};
412
413struct XCOFFBlockAuxEnt64 {
414 support::ubig32_t LineNum;
415 uint8_t Pad[13];
416 XCOFF::SymbolAuxType AuxType; // Contains _AUX_SYM; Type of auxiliary entry
417};
418
419struct XCOFFSectAuxEntForDWARF32 {
420 support::ubig32_t LengthOfSectionPortion;
421 uint8_t Pad1[4];
422 support::ubig32_t NumberOfRelocEnt;
423 uint8_t Pad2[6];
424};
425
426struct XCOFFSectAuxEntForDWARF64 {
427 support::ubig64_t LengthOfSectionPortion;
428 support::ubig64_t NumberOfRelocEnt;
429 uint8_t Pad;
430 XCOFF::SymbolAuxType AuxType; // Contains _AUX_SECT; Type of Auxillary entry
431};
432
433template <typename AddressType> struct XCOFFRelocation {
434 // Masks for packing/unpacking the r_rsize field of relocations.
435
436 // The msb is used to indicate if the bits being relocated are signed or
437 // unsigned.
438 static constexpr uint8_t XR_SIGN_INDICATOR_MASK = 0x80;
439
440 // The 2nd msb is used to indicate that the binder has replaced/modified the
441 // original instruction.
442 static constexpr uint8_t XR_FIXUP_INDICATOR_MASK = 0x40;
443
444 // The remaining bits specify the bit length of the relocatable reference
445 // minus one.
446 static constexpr uint8_t XR_BIASED_LENGTH_MASK = 0x3f;
447
448public:
449 AddressType VirtualAddress;
450 support::ubig32_t SymbolIndex;
451
452 // Packed field, see XR_* masks for details of packing.
453 uint8_t Info;
454
455 XCOFF::RelocationType Type;
456
457public:
458 bool isRelocationSigned() const;
459 bool isFixupIndicated() const;
460
461 // Returns the number of bits being relocated.
462 uint8_t getRelocatedLength() const;
463};
464
465extern template struct XCOFFRelocation<llvm::support::ubig32_t>;
466extern template struct XCOFFRelocation<llvm::support::ubig64_t>;
467
468struct XCOFFRelocation32 : XCOFFRelocation<llvm::support::ubig32_t> {};
469struct XCOFFRelocation64 : XCOFFRelocation<llvm::support::ubig64_t> {};
470
471class XCOFFSymbolRef;
472
473class XCOFFObjectFile : public ObjectFile {
474private:
475 const void *FileHeader = nullptr;
476 const void *AuxiliaryHeader = nullptr;
477 const void *SectionHeaderTable = nullptr;
478
479 const void *SymbolTblPtr = nullptr;
480 XCOFFStringTable StringTable = {0, nullptr};
481
482 const XCOFFSectionHeader32 *sectionHeaderTable32() const;
483 const XCOFFSectionHeader64 *sectionHeaderTable64() const;
484 template <typename T> const T *sectionHeaderTable() const;
485
486 size_t getFileHeaderSize() const;
487 size_t getSectionHeaderSize() const;
488
489 const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const;
490 const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const;
491 uintptr_t getSectionHeaderTableAddress() const;
492 uintptr_t getEndOfSymbolTableAddress() const;
493
494 DataRefImpl getSectionByType(XCOFF::SectionTypeFlags SectType) const;
495 uint64_t getSectionFileOffsetToRawData(DataRefImpl Sec) const;
496
497 // This returns a pointer to the start of the storage for the name field of
498 // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily
499 // null-terminated.
500 const char *getSectionNameInternal(DataRefImpl Sec) const;
501
502 static bool isReservedSectionNumber(int16_t SectionNumber);
503
504 // Constructor and "create" factory function. The constructor is only a thin
505 // wrapper around the base constructor. The "create" function fills out the
506 // XCOFF-specific information and performs the error checking along the way.
507 XCOFFObjectFile(unsigned Type, MemoryBufferRef Object);
508 static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type,
509 MemoryBufferRef MBR);
510
511 // Helper for parsing the StringTable. Returns an 'Error' if parsing failed
512 // and an XCOFFStringTable if parsing succeeded.
513 static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj,
514 uint64_t Offset);
515
516 // Make a friend so it can call the private 'create' function.
517 friend Expected<std::unique_ptr<ObjectFile>>
518 ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
519
520 void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const;
521
522public:
523 static constexpr uint64_t InvalidRelocOffset =
524 std::numeric_limits<uint64_t>::max();
525
526 // Interface inherited from base classes.
527 void moveSymbolNext(DataRefImpl &Symb) const override;
528 Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
529 basic_symbol_iterator symbol_begin() const override;
530 basic_symbol_iterator symbol_end() const override;
531
532 Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
533 Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
534 uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
535 uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
536 uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
537 Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
538 Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
539
540 void moveSectionNext(DataRefImpl &Sec) const override;
541 Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
542 uint64_t getSectionAddress(DataRefImpl Sec) const override;
543 uint64_t getSectionIndex(DataRefImpl Sec) const override;
544 uint64_t getSectionSize(DataRefImpl Sec) const override;
545 Expected<ArrayRef<uint8_t>>
546 getSectionContents(DataRefImpl Sec) const override;
547 uint64_t getSectionAlignment(DataRefImpl Sec) const override;
548 bool isSectionCompressed(DataRefImpl Sec) const override;
549 bool isSectionText(DataRefImpl Sec) const override;
550 bool isSectionData(DataRefImpl Sec) const override;
551 bool isSectionBSS(DataRefImpl Sec) const override;
552 bool isDebugSection(DataRefImpl Sec) const override;
553
554 bool isSectionVirtual(DataRefImpl Sec) const override;
555 relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
556 relocation_iterator section_rel_end(DataRefImpl Sec) const override;
557
558 void moveRelocationNext(DataRefImpl &Rel) const override;
559
560 /// \returns the relocation offset with the base address of the containing
561 /// section as zero, or InvalidRelocOffset on errors (such as a relocation
562 /// that does not refer to an address in any section).
563 uint64_t getRelocationOffset(DataRefImpl Rel) const override;
564 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
565 uint64_t getRelocationType(DataRefImpl Rel) const override;
566 void getRelocationTypeName(DataRefImpl Rel,
567 SmallVectorImpl<char> &Result) const override;
568
569 section_iterator section_begin() const override;
570 section_iterator section_end() const override;
571 uint8_t getBytesInAddress() const override;
572 StringRef getFileFormatName() const override;
573 Triple::ArchType getArch() const override;
574 SubtargetFeatures getFeatures() const override;
575 Expected<uint64_t> getStartAddress() const override;
576 StringRef mapDebugSectionName(StringRef Name) const override;
577 bool isRelocatableObject() const override;
578
579 // Below here is the non-inherited interface.
580 bool is64Bit() const;
581 Expected<StringRef> getRawData(const char *Start, uint64_t Size,
582 StringRef Name) const;
583
584 const XCOFFAuxiliaryHeader32 *auxiliaryHeader32() const;
585 const XCOFFAuxiliaryHeader64 *auxiliaryHeader64() const;
586
587 const void *getPointerToSymbolTable() const { return SymbolTblPtr; }
588
589 Expected<StringRef> getSymbolSectionName(XCOFFSymbolRef Ref) const;
590 unsigned getSymbolSectionID(SymbolRef Sym) const;
591 XCOFFSymbolRef toSymbolRef(DataRefImpl Ref) const;
592
593 // File header related interfaces.
594 const XCOFFFileHeader32 *fileHeader32() const;
595 const XCOFFFileHeader64 *fileHeader64() const;
596 uint16_t getMagic() const;
597 uint16_t getNumberOfSections() const;
598 int32_t getTimeStamp() const;
599
600 // Symbol table offset and entry count are handled differently between
601 // XCOFF32 and XCOFF64.
602 uint32_t getSymbolTableOffset32() const;
603 uint64_t getSymbolTableOffset64() const;
604
605 // Note that this value is signed and might return a negative value. Negative
606 // values are reserved for future use.
607 int32_t getRawNumberOfSymbolTableEntries32() const;
608
609 // The sanitized value appropriate to use as an index into the symbol table.
610 uint32_t getLogicalNumberOfSymbolTableEntries32() const;
611
612 uint32_t getNumberOfSymbolTableEntries64() const;
613
614 // Return getLogicalNumberOfSymbolTableEntries32 or
615 // getNumberOfSymbolTableEntries64 depending on the object mode.
616 uint32_t getNumberOfSymbolTableEntries() const;
617
618 uint32_t getSymbolIndex(uintptr_t SymEntPtr) const;
619 uint64_t getSymbolSize(DataRefImpl Symb) const;
620 uintptr_t getSymbolByIndex(uint32_t Idx) const {
621 return reinterpret_cast<uintptr_t>(SymbolTblPtr) +
622 XCOFF::SymbolTableEntrySize * Idx;
623 }
624 uintptr_t getSymbolEntryAddressByIndex(uint32_t SymbolTableIndex) const;
625 Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const;
626
627 Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const;
628 uint16_t getOptionalHeaderSize() const;
629 uint16_t getFlags() const;
630
631 // Section header table related interfaces.
632 ArrayRef<XCOFFSectionHeader32> sections32() const;
633 ArrayRef<XCOFFSectionHeader64> sections64() const;
634
635 int32_t getSectionFlags(DataRefImpl Sec) const;
636 Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
637
638 Expected<uintptr_t>
639 getSectionFileOffsetToRawData(XCOFF::SectionTypeFlags SectType) const;
640
641 void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const;
642
643 // Relocation-related interfaces.
644 template <typename T>
645 Expected<uint32_t>
646 getNumberOfRelocationEntries(const XCOFFSectionHeader<T> &Sec) const;
647
648 template <typename Shdr, typename Reloc>
649 Expected<ArrayRef<Reloc>> relocations(const Shdr &Sec) const;
650
651 // Loader section related interfaces.
652 Expected<StringRef> getImportFileTable() const;
653
654 // Exception-related interface.
655 template <typename ExceptEnt>
656 Expected<ArrayRef<ExceptEnt>> getExceptionEntries() const;
657
658 // This function returns string table entry.
659 Expected<StringRef> getStringTableEntry(uint32_t Offset) const;
660
661 // This function returns the string table.
662 StringRef getStringTable() const;
663
664 const XCOFF::SymbolAuxType *getSymbolAuxType(uintptr_t AuxEntryAddress) const;
665
666 static uintptr_t getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
667 uint32_t Distance);
668
669 static bool classof(const Binary *B) { return B->isXCOFF(); }
670}; // XCOFFObjectFile
671
672typedef struct {
673 uint8_t LanguageId;
674 uint8_t CpuTypeId;
675} CFileLanguageIdAndTypeIdType;
676
677struct XCOFFSymbolEntry32 {
678 typedef struct {
679 support::big32_t Magic; // Zero indicates name in string table.
680 support::ubig32_t Offset;
681 } NameInStrTblType;
682
683 union {
684 char SymbolName[XCOFF::NameSize];
685 NameInStrTblType NameInStrTbl;
686 };
687
688 support::ubig32_t Value; // Symbol value; storage class-dependent.
689 support::big16_t SectionNumber;
690
691 union {
692 support::ubig16_t SymbolType;
693 CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
694 };
695
696 XCOFF::StorageClass StorageClass;
697 uint8_t NumberOfAuxEntries;
698};
699
700struct XCOFFSymbolEntry64 {
701 support::ubig64_t Value; // Symbol value; storage class-dependent.
702 support::ubig32_t Offset;
703 support::big16_t SectionNumber;
704
705 union {
706 support::ubig16_t SymbolType;
707 CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
708 };
709
710 XCOFF::StorageClass StorageClass;
711 uint8_t NumberOfAuxEntries;
712};
713
714class XCOFFSymbolRef {
715public:
716 enum { NAME_IN_STR_TBL_MAGIC = 0x0 };
717
718 XCOFFSymbolRef(DataRefImpl SymEntDataRef,
719 const XCOFFObjectFile *OwningObjectPtr)
720 : OwningObjectPtr(OwningObjectPtr) {
721 assert(OwningObjectPtr && "OwningObjectPtr cannot be nullptr!")(static_cast <bool> (OwningObjectPtr && "OwningObjectPtr cannot be nullptr!"
) ? void (0) : __assert_fail ("OwningObjectPtr && \"OwningObjectPtr cannot be nullptr!\""
, "llvm/include/llvm/Object/XCOFFObjectFile.h", 721, __extension__
__PRETTY_FUNCTION__))
;
722 assert(SymEntDataRef.p != 0 &&(static_cast <bool> (SymEntDataRef.p != 0 && "Symbol table entry pointer cannot be nullptr!"
) ? void (0) : __assert_fail ("SymEntDataRef.p != 0 && \"Symbol table entry pointer cannot be nullptr!\""
, "llvm/include/llvm/Object/XCOFFObjectFile.h", 723, __extension__
__PRETTY_FUNCTION__))
723 "Symbol table entry pointer cannot be nullptr!")(static_cast <bool> (SymEntDataRef.p != 0 && "Symbol table entry pointer cannot be nullptr!"
) ? void (0) : __assert_fail ("SymEntDataRef.p != 0 && \"Symbol table entry pointer cannot be nullptr!\""
, "llvm/include/llvm/Object/XCOFFObjectFile.h", 723, __extension__
__PRETTY_FUNCTION__))
;
724
725 if (OwningObjectPtr->is64Bit())
726 Entry64 = reinterpret_cast<const XCOFFSymbolEntry64 *>(SymEntDataRef.p);
727 else
728 Entry32 = reinterpret_cast<const XCOFFSymbolEntry32 *>(SymEntDataRef.p);
729 }
730
731 const XCOFFSymbolEntry32 *getSymbol32() { return Entry32; }
732 const XCOFFSymbolEntry64 *getSymbol64() { return Entry64; }
733
734 uint64_t getValue() const { return Entry32 ? getValue32() : getValue64(); }
735
736 uint32_t getValue32() const { return Entry32->Value; }
737
738 uint64_t getValue64() const { return Entry64->Value; }
739
740#define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X
741
742 int16_t getSectionNumber() const { return GETVALUE(SectionNumber); }
743
744 uint16_t getSymbolType() const { return GETVALUE(SymbolType); }
745
746 uint8_t getLanguageIdForCFile() const {
747 assert(getStorageClass() == XCOFF::C_FILE &&(static_cast <bool> (getStorageClass() == XCOFF::C_FILE
&& "This interface is for C_FILE only.") ? void (0) :
__assert_fail ("getStorageClass() == XCOFF::C_FILE && \"This interface is for C_FILE only.\""
, "llvm/include/llvm/Object/XCOFFObjectFile.h", 748, __extension__
__PRETTY_FUNCTION__))
748 "This interface is for C_FILE only.")(static_cast <bool> (getStorageClass() == XCOFF::C_FILE
&& "This interface is for C_FILE only.") ? void (0) :
__assert_fail ("getStorageClass() == XCOFF::C_FILE && \"This interface is for C_FILE only.\""
, "llvm/include/llvm/Object/XCOFFObjectFile.h", 748, __extension__
__PRETTY_FUNCTION__))
;
749 return GETVALUE(CFileLanguageIdAndTypeId.LanguageId);
750 }
751
752 uint8_t getCPUTypeIddForCFile() const {
753 assert(getStorageClass() == XCOFF::C_FILE &&(static_cast <bool> (getStorageClass() == XCOFF::C_FILE
&& "This interface is for C_FILE only.") ? void (0) :
__assert_fail ("getStorageClass() == XCOFF::C_FILE && \"This interface is for C_FILE only.\""
, "llvm/include/llvm/Object/XCOFFObjectFile.h", 754, __extension__
__PRETTY_FUNCTION__))
754 "This interface is for C_FILE only.")(static_cast <bool> (getStorageClass() == XCOFF::C_FILE
&& "This interface is for C_FILE only.") ? void (0) :
__assert_fail ("getStorageClass() == XCOFF::C_FILE && \"This interface is for C_FILE only.\""
, "llvm/include/llvm/Object/XCOFFObjectFile.h", 754, __extension__
__PRETTY_FUNCTION__))
;
755 return GETVALUE(CFileLanguageIdAndTypeId.CpuTypeId);
756 }
757
758 XCOFF::StorageClass getStorageClass() const { return GETVALUE(StorageClass); }
759
760 uint8_t getNumberOfAuxEntries() const { return GETVALUE(NumberOfAuxEntries); }
2
Assuming field 'Entry32' is null
3
'?' condition is false
4
Dereference of null pointer
761
762#undef GETVALUE
763
764 uintptr_t getEntryAddress() const {
765 return Entry32 ? reinterpret_cast<uintptr_t>(Entry32)
766 : reinterpret_cast<uintptr_t>(Entry64);
767 }
768
769 Expected<StringRef> getName() const;
770 bool isFunction() const;
771 bool isCsectSymbol() const;
772 Expected<XCOFFCsectAuxRef> getXCOFFCsectAuxRef() const;
773
774private:
775 const XCOFFObjectFile *OwningObjectPtr;
776 const XCOFFSymbolEntry32 *Entry32 = nullptr;
777 const XCOFFSymbolEntry64 *Entry64 = nullptr;
778};
779
780class TBVectorExt {
781 uint16_t Data;
782 SmallString<32> VecParmsInfo;
783
784 TBVectorExt(StringRef TBvectorStrRef, Error &Err);
785
786public:
787 static Expected<TBVectorExt> create(StringRef TBvectorStrRef);
788 uint8_t getNumberOfVRSaved() const;
789 bool isVRSavedOnStack() const;
790 bool hasVarArgs() const;
791 uint8_t getNumberOfVectorParms() const;
792 bool hasVMXInstruction() const;
793 SmallString<32> getVectorParmsInfo() const { return VecParmsInfo; };
794};
795
796/// This class provides methods to extract traceback table data from a buffer.
797/// The various accessors may reference the buffer provided via the constructor.
798
799class XCOFFTracebackTable {
800 const uint8_t *const TBPtr;
801 Optional<SmallString<32>> ParmsType;
802 Optional<uint32_t> TraceBackTableOffset;
803 Optional<uint32_t> HandlerMask;
804 Optional<uint32_t> NumOfCtlAnchors;
805 Optional<SmallVector<uint32_t, 8>> ControlledStorageInfoDisp;
806 Optional<StringRef> FunctionName;
807 Optional<uint8_t> AllocaRegister;
808 Optional<TBVectorExt> VecExt;
809 Optional<uint8_t> ExtensionTable;
810
811 XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err);
812
813public:
814 /// Parse an XCOFF Traceback Table from \a Ptr with \a Size bytes.
815 /// Returns an XCOFFTracebackTable upon successful parsing, otherwise an
816 /// Error is returned.
817 ///
818 /// \param[in] Ptr
819 /// A pointer that points just past the initial 4 bytes of zeros at the
820 /// beginning of an XCOFF Traceback Table.
821 ///
822 /// \param[in, out] Size
823 /// A pointer that points to the length of the XCOFF Traceback Table.
824 /// If the XCOFF Traceback Table is not parsed successfully or there are
825 /// extra bytes that are not recognized, \a Size will be updated to be the
826 /// size up to the end of the last successfully parsed field of the table.
827 static Expected<XCOFFTracebackTable> create(const uint8_t *Ptr,
828 uint64_t &Size);
829 uint8_t getVersion() const;
830 uint8_t getLanguageID() const;
831
832 bool isGlobalLinkage() const;
833 bool isOutOfLineEpilogOrPrologue() const;
834 bool hasTraceBackTableOffset() const;
835 bool isInternalProcedure() const;
836 bool hasControlledStorage() const;
837 bool isTOCless() const;
838 bool isFloatingPointPresent() const;
839 bool isFloatingPointOperationLogOrAbortEnabled() const;
840
841 bool isInterruptHandler() const;
842 bool isFuncNamePresent() const;
843 bool isAllocaUsed() const;
844 uint8_t getOnConditionDirective() const;
845 bool isCRSaved() const;
846 bool isLRSaved() const;
847
848 bool isBackChainStored() const;
849 bool isFixup() const;
850 uint8_t getNumOfFPRsSaved() const;
851
852 bool hasVectorInfo() const;
853 bool hasExtensionTable() const;
854 uint8_t getNumOfGPRsSaved() const;
855
856 uint8_t getNumberOfFixedParms() const;
857
858 uint8_t getNumberOfFPParms() const;
859 bool hasParmsOnStack() const;
860
861 const Optional<SmallString<32>> &getParmsType() const { return ParmsType; }
862 const Optional<uint32_t> &getTraceBackTableOffset() const {
863 return TraceBackTableOffset;
864 }
865 const Optional<uint32_t> &getHandlerMask() const { return HandlerMask; }
866 const Optional<uint32_t> &getNumOfCtlAnchors() { return NumOfCtlAnchors; }
867 const Optional<SmallVector<uint32_t, 8>> &getControlledStorageInfoDisp() {
868 return ControlledStorageInfoDisp;
869 }
870 const Optional<StringRef> &getFunctionName() const { return FunctionName; }
871 const Optional<uint8_t> &getAllocaRegister() const { return AllocaRegister; }
872 const Optional<TBVectorExt> &getVectorExt() const { return VecExt; }
873 const Optional<uint8_t> &getExtensionTable() const { return ExtensionTable; }
874};
875
876bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes);
877} // namespace object
878} // namespace llvm
879
880#endif // LLVM_OBJECT_XCOFFOBJECTFILE_H