Bug Summary

File:llvm/include/llvm/Object/XCOFFObjectFile.h
Warning:line 538, column 40
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name XCOFFObjectFile.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/build-llvm -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I lib/Object -I /build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Object -I include -I /build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/include -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-14/lib/clang/14.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 -O2 -Wno-unused-command-line-argument -Wno-unknown-warning-option -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 -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/build-llvm -ferror-limit 19 -fvisibility-inlines-hidden -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-2021-09-26-234817-15343-1 -x c++ /build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Object/XCOFFObjectFile.cpp

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

/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/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 XCOFFSectionHeader {
55 // Least significant 3 bits are reserved.
56 static constexpr unsigned SectionFlagsReservedMask = 0x7;
57
58 // The low order 16 bits of section flags denotes the section type.
59 static constexpr unsigned SectionFlagsTypeMask = 0xffffu;
60
61public:
62 StringRef getName() const;
63 uint16_t getSectionType() const;
64 bool isReservedSectionType() const;
65};
66
67// Explicit extern template declarations.
68struct XCOFFSectionHeader32;
69struct XCOFFSectionHeader64;
70extern template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
71extern template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
72
73struct XCOFFSectionHeader32 : XCOFFSectionHeader<XCOFFSectionHeader32> {
74 char Name[XCOFF::NameSize];
75 support::ubig32_t PhysicalAddress;
76 support::ubig32_t VirtualAddress;
77 support::ubig32_t SectionSize;
78 support::ubig32_t FileOffsetToRawData;
79 support::ubig32_t FileOffsetToRelocationInfo;
80 support::ubig32_t FileOffsetToLineNumberInfo;
81 support::ubig16_t NumberOfRelocations;
82 support::ubig16_t NumberOfLineNumbers;
83 support::big32_t Flags;
84};
85
86struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> {
87 char Name[XCOFF::NameSize];
88 support::ubig64_t PhysicalAddress;
89 support::ubig64_t VirtualAddress;
90 support::ubig64_t SectionSize;
91 support::big64_t FileOffsetToRawData;
92 support::big64_t FileOffsetToRelocationInfo;
93 support::big64_t FileOffsetToLineNumberInfo;
94 support::ubig32_t NumberOfRelocations;
95 support::ubig32_t NumberOfLineNumbers;
96 support::big32_t Flags;
97 char Padding[4];
98};
99
100struct LoaderSectionHeader32 {
101 support::ubig32_t Version;
102 support::ubig32_t NumberOfSymTabEnt;
103 support::ubig32_t NumberOfRelTabEnt;
104 support::ubig32_t LengthOfImpidStrTbl;
105 support::ubig32_t NumberOfImpid;
106 support::big32_t OffsetToImpid;
107 support::ubig32_t LengthOfStrTbl;
108 support::big32_t OffsetToStrTbl;
109};
110
111struct LoaderSectionHeader64 {
112 support::ubig32_t Version;
113 support::ubig32_t NumberOfSymTabEnt;
114 support::ubig32_t NumberOfRelTabEnt;
115 support::ubig32_t LengthOfImpidStrTbl;
116 support::ubig32_t NumberOfImpid;
117 support::ubig32_t LengthOfStrTbl;
118 support::big64_t OffsetToImpid;
119 support::big64_t OffsetToStrTbl;
120 support::big64_t OffsetToSymTbl;
121 char Padding[16];
122 support::big32_t OffsetToRelEnt;
123};
124
125struct XCOFFStringTable {
126 uint32_t Size;
127 const char *Data;
128};
129
130struct XCOFFCsectAuxEnt32 {
131 support::ubig32_t SectionOrLength;
132 support::ubig32_t ParameterHashIndex;
133 support::ubig16_t TypeChkSectNum;
134 uint8_t SymbolAlignmentAndType;
135 XCOFF::StorageMappingClass StorageMappingClass;
136 support::ubig32_t StabInfoIndex;
137 support::ubig16_t StabSectNum;
138};
139
140struct XCOFFCsectAuxEnt64 {
141 support::ubig32_t SectionOrLengthLowByte;
142 support::ubig32_t ParameterHashIndex;
143 support::ubig16_t TypeChkSectNum;
144 uint8_t SymbolAlignmentAndType;
145 XCOFF::StorageMappingClass StorageMappingClass;
146 support::ubig32_t SectionOrLengthHighByte;
147 uint8_t Pad;
148 XCOFF::SymbolAuxType AuxType;
149};
150
151class XCOFFCsectAuxRef {
152public:
153 static constexpr uint8_t SymbolTypeMask = 0x07;
154 static constexpr uint8_t SymbolAlignmentMask = 0xF8;
155 static constexpr size_t SymbolAlignmentBitOffset = 3;
156
157 XCOFFCsectAuxRef(const XCOFFCsectAuxEnt32 *Entry32) : Entry32(Entry32) {}
158 XCOFFCsectAuxRef(const XCOFFCsectAuxEnt64 *Entry64) : Entry64(Entry64) {}
159
160 // For getSectionOrLength(),
161 // If the symbol type is XTY_SD or XTY_CM, the csect length.
162 // If the symbol type is XTY_LD, the symbol table
163 // index of the containing csect.
164 // If the symbol type is XTY_ER, 0.
165 uint64_t getSectionOrLength() const {
166 return Entry32 ? getSectionOrLength32() : getSectionOrLength64();
167 }
168
169 uint32_t getSectionOrLength32() const {
170 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.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/include/llvm/Object/XCOFFObjectFile.h"
, 170, __extension__ __PRETTY_FUNCTION__))
;
171 return Entry32->SectionOrLength;
172 }
173
174 uint64_t getSectionOrLength64() const {
175 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.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/include/llvm/Object/XCOFFObjectFile.h"
, 175, __extension__ __PRETTY_FUNCTION__))
;
176 return (static_cast<uint64_t>(Entry64->SectionOrLengthHighByte) << 32) |
177 Entry64->SectionOrLengthLowByte;
178 }
179
180#define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X
181
182 uint32_t getParameterHashIndex() const {
183 return GETVALUE(ParameterHashIndex);
184 }
185
186 uint16_t getTypeChkSectNum() const { return GETVALUE(TypeChkSectNum); }
187
188 XCOFF::StorageMappingClass getStorageMappingClass() const {
189 return GETVALUE(StorageMappingClass);
190 }
191
192 uintptr_t getEntryAddress() const {
193 return Entry32 ? reinterpret_cast<uintptr_t>(Entry32)
194 : reinterpret_cast<uintptr_t>(Entry64);
195 }
196
197 uint16_t getAlignmentLog2() const {
198 return (getSymbolAlignmentAndType() & SymbolAlignmentMask) >>
199 SymbolAlignmentBitOffset;
200 }
201
202 uint8_t getSymbolType() const {
203 return getSymbolAlignmentAndType() & SymbolTypeMask;
204 }
205
206 bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; }
207
208 uint32_t getStabInfoIndex32() const {
209 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.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/include/llvm/Object/XCOFFObjectFile.h"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return Entry32->StabInfoIndex;
211 }
212
213 uint16_t getStabSectNum32() const {
214 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.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/include/llvm/Object/XCOFFObjectFile.h"
, 214, __extension__ __PRETTY_FUNCTION__))
;
215 return Entry32->StabSectNum;
216 }
217
218 XCOFF::SymbolAuxType getAuxType64() const {
219 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.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/include/llvm/Object/XCOFFObjectFile.h"
, 219, __extension__ __PRETTY_FUNCTION__))
;
220 return Entry64->AuxType;
221 }
222
223private:
224 uint8_t getSymbolAlignmentAndType() const {
225 return GETVALUE(SymbolAlignmentAndType);
226 }
227
228#undef GETVALUE
229
230 const XCOFFCsectAuxEnt32 *Entry32 = nullptr;
231 const XCOFFCsectAuxEnt64 *Entry64 = nullptr;
232};
233
234struct XCOFFFileAuxEnt {
235 typedef struct {
236 support::big32_t Magic; // Zero indicates name in string table.
237 support::ubig32_t Offset;
238 char NamePad[XCOFF::FileNamePadSize];
239 } NameInStrTblType;
240 union {
241 char Name[XCOFF::NameSize + XCOFF::FileNamePadSize];
242 NameInStrTblType NameInStrTbl;
243 };
244 XCOFF::CFileStringType Type;
245 uint8_t ReservedZeros[2];
246 XCOFF::SymbolAuxType AuxType; // 64-bit XCOFF file only.
247};
248
249struct XCOFFSectAuxEntForStat {
250 support::ubig32_t SectionLength;
251 support::ubig16_t NumberOfRelocEnt;
252 support::ubig16_t NumberOfLineNum;
253 uint8_t Pad[10];
254}; // 32-bit XCOFF file only.
255
256template <typename AddressType> struct XCOFFRelocation {
257 // Masks for packing/unpacking the r_rsize field of relocations.
258
259 // The msb is used to indicate if the bits being relocated are signed or
260 // unsigned.
261 static constexpr uint8_t XR_SIGN_INDICATOR_MASK = 0x80;
262
263 // The 2nd msb is used to indicate that the binder has replaced/modified the
264 // original instruction.
265 static constexpr uint8_t XR_FIXUP_INDICATOR_MASK = 0x40;
266
267 // The remaining bits specify the bit length of the relocatable reference
268 // minus one.
269 static constexpr uint8_t XR_BIASED_LENGTH_MASK = 0x3f;
270
271public:
272 AddressType VirtualAddress;
273 support::ubig32_t SymbolIndex;
274
275 // Packed field, see XR_* masks for details of packing.
276 uint8_t Info;
277
278 XCOFF::RelocationType Type;
279
280public:
281 bool isRelocationSigned() const;
282 bool isFixupIndicated() const;
283
284 // Returns the number of bits being relocated.
285 uint8_t getRelocatedLength() const;
286};
287
288extern template struct XCOFFRelocation<llvm::support::ubig32_t>;
289extern template struct XCOFFRelocation<llvm::support::ubig64_t>;
290
291struct XCOFFRelocation32 : XCOFFRelocation<llvm::support::ubig32_t> {};
292struct XCOFFRelocation64 : XCOFFRelocation<llvm::support::ubig64_t> {};
293
294class XCOFFSymbolRef;
295
296class XCOFFObjectFile : public ObjectFile {
297private:
298 const void *FileHeader = nullptr;
299 const void *SectionHeaderTable = nullptr;
300
301 const void *SymbolTblPtr = nullptr;
302 XCOFFStringTable StringTable = {0, nullptr};
303
304 const XCOFFFileHeader32 *fileHeader32() const;
305 const XCOFFFileHeader64 *fileHeader64() const;
306
307 const XCOFFSectionHeader32 *sectionHeaderTable32() const;
308 const XCOFFSectionHeader64 *sectionHeaderTable64() const;
309 template <typename T> const T *sectionHeaderTable() const;
310
311 size_t getFileHeaderSize() const;
312 size_t getSectionHeaderSize() const;
313
314 const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const;
315 const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const;
316 uintptr_t getSectionHeaderTableAddress() const;
317 uintptr_t getEndOfSymbolTableAddress() const;
318 Expected<uintptr_t> getLoaderSectionAddress() const;
319
320 // This returns a pointer to the start of the storage for the name field of
321 // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily
322 // null-terminated.
323 const char *getSectionNameInternal(DataRefImpl Sec) const;
324
325 static bool isReservedSectionNumber(int16_t SectionNumber);
326
327 // Constructor and "create" factory function. The constructor is only a thin
328 // wrapper around the base constructor. The "create" function fills out the
329 // XCOFF-specific information and performs the error checking along the way.
330 XCOFFObjectFile(unsigned Type, MemoryBufferRef Object);
331 static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type,
332 MemoryBufferRef MBR);
333
334 // Helper for parsing the StringTable. Returns an 'Error' if parsing failed
335 // and an XCOFFStringTable if parsing succeeded.
336 static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj,
337 uint64_t Offset);
338
339 // Make a friend so it can call the private 'create' function.
340 friend Expected<std::unique_ptr<ObjectFile>>
341 ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
342
343 void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const;
344
345public:
346 static constexpr uint64_t InvalidRelocOffset =
347 std::numeric_limits<uint64_t>::max();
348
349 // Interface inherited from base classes.
350 void moveSymbolNext(DataRefImpl &Symb) const override;
351 Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
352 basic_symbol_iterator symbol_begin() const override;
353 basic_symbol_iterator symbol_end() const override;
354
355 Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
356 Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
357 uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
358 uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
359 Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
360 Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
361
362 void moveSectionNext(DataRefImpl &Sec) const override;
363 Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
364 uint64_t getSectionAddress(DataRefImpl Sec) const override;
365 uint64_t getSectionIndex(DataRefImpl Sec) const override;
366 uint64_t getSectionSize(DataRefImpl Sec) const override;
367 Expected<ArrayRef<uint8_t>>
368 getSectionContents(DataRefImpl Sec) const override;
369 uint64_t getSectionAlignment(DataRefImpl Sec) const override;
370 bool isSectionCompressed(DataRefImpl Sec) const override;
371 bool isSectionText(DataRefImpl Sec) const override;
372 bool isSectionData(DataRefImpl Sec) const override;
373 bool isSectionBSS(DataRefImpl Sec) const override;
374 bool isDebugSection(DataRefImpl Sec) const override;
375
376 bool isSectionVirtual(DataRefImpl Sec) const override;
377 relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
378 relocation_iterator section_rel_end(DataRefImpl Sec) const override;
379
380 void moveRelocationNext(DataRefImpl &Rel) const override;
381
382 /// \returns the relocation offset with the base address of the containing
383 /// section as zero, or InvalidRelocOffset on errors (such as a relocation
384 /// that does not refer to an address in any section).
385 uint64_t getRelocationOffset(DataRefImpl Rel) const override;
386 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
387 uint64_t getRelocationType(DataRefImpl Rel) const override;
388 void getRelocationTypeName(DataRefImpl Rel,
389 SmallVectorImpl<char> &Result) const override;
390
391 section_iterator section_begin() const override;
392 section_iterator section_end() const override;
393 uint8_t getBytesInAddress() const override;
394 StringRef getFileFormatName() const override;
395 Triple::ArchType getArch() const override;
396 SubtargetFeatures getFeatures() const override;
397 Expected<uint64_t> getStartAddress() const override;
398 StringRef mapDebugSectionName(StringRef Name) const override;
399 bool isRelocatableObject() const override;
400
401 // Below here is the non-inherited interface.
402 bool is64Bit() const;
403
404 const void *getPointerToSymbolTable() const { return SymbolTblPtr; }
405
406 Expected<StringRef> getSymbolSectionName(XCOFFSymbolRef Ref) const;
407 unsigned getSymbolSectionID(SymbolRef Sym) const;
408 XCOFFSymbolRef toSymbolRef(DataRefImpl Ref) const;
409
410 // File header related interfaces.
411 uint16_t getMagic() const;
412 uint16_t getNumberOfSections() const;
413 int32_t getTimeStamp() const;
414
415 // Symbol table offset and entry count are handled differently between
416 // XCOFF32 and XCOFF64.
417 uint32_t getSymbolTableOffset32() const;
418 uint64_t getSymbolTableOffset64() const;
419
420 // Note that this value is signed and might return a negative value. Negative
421 // values are reserved for future use.
422 int32_t getRawNumberOfSymbolTableEntries32() const;
423
424 // The sanitized value appropriate to use as an index into the symbol table.
425 uint32_t getLogicalNumberOfSymbolTableEntries32() const;
426
427 uint32_t getNumberOfSymbolTableEntries64() const;
428
429 // Return getLogicalNumberOfSymbolTableEntries32 or
430 // getNumberOfSymbolTableEntries64 depending on the object mode.
431 uint32_t getNumberOfSymbolTableEntries() const;
432
433 uint32_t getSymbolIndex(uintptr_t SymEntPtr) const;
434 uintptr_t getSymbolEntryAddressByIndex(uint32_t SymbolTableIndex) const;
435 Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const;
436
437 Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const;
438 uint16_t getOptionalHeaderSize() const;
439 uint16_t getFlags() const;
440
441 // Section header table related interfaces.
442 ArrayRef<XCOFFSectionHeader32> sections32() const;
443 ArrayRef<XCOFFSectionHeader64> sections64() const;
444
445 int32_t getSectionFlags(DataRefImpl Sec) const;
446 Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
447
448 void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const;
449
450 // Relocation-related interfaces.
451 template <typename T>
452 Expected<uint32_t>
453 getNumberOfRelocationEntries(const XCOFFSectionHeader<T> &Sec) const;
454
455 template <typename Shdr, typename Reloc>
456 Expected<ArrayRef<Reloc>> relocations(const Shdr &Sec) const;
457
458 // Loader section related interfaces.
459 Expected<StringRef> getImportFileTable() const;
460
461 // This function returns string table entry.
462 Expected<StringRef> getStringTableEntry(uint32_t Offset) const;
463
464 // This function returns the string table.
465 StringRef getStringTable() const;
466
467 const XCOFF::SymbolAuxType *getSymbolAuxType(uintptr_t AuxEntryAddress) const;
468
469 static uintptr_t getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
470 uint32_t Distance);
471
472 static bool classof(const Binary *B) { return B->isXCOFF(); }
473}; // XCOFFObjectFile
474
475typedef struct {
476 uint8_t LanguageId;
477 uint8_t CpuTypeId;
478} CFileLanguageIdAndTypeIdType;
479
480struct XCOFFSymbolEntry32 {
481 typedef struct {
482 support::big32_t Magic; // Zero indicates name in string table.
483 support::ubig32_t Offset;
484 } NameInStrTblType;
485
486 union {
487 char SymbolName[XCOFF::NameSize];
488 NameInStrTblType NameInStrTbl;
489 };
490
491 support::ubig32_t Value; // Symbol value; storage class-dependent.
492 support::big16_t SectionNumber;
493
494 union {
495 support::ubig16_t SymbolType;
496 CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
497 };
498
499 XCOFF::StorageClass StorageClass;
500 uint8_t NumberOfAuxEntries;
501};
502
503struct XCOFFSymbolEntry64 {
504 support::ubig64_t Value; // Symbol value; storage class-dependent.
505 support::ubig32_t Offset;
506 support::big16_t SectionNumber;
507
508 union {
509 support::ubig16_t SymbolType;
510 CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
511 };
512
513 XCOFF::StorageClass StorageClass;
514 uint8_t NumberOfAuxEntries;
515};
516
517class XCOFFSymbolRef {
518public:
519 enum { NAME_IN_STR_TBL_MAGIC = 0x0 };
520
521 XCOFFSymbolRef(DataRefImpl SymEntDataRef,
522 const XCOFFObjectFile *OwningObjectPtr)
523 : OwningObjectPtr(OwningObjectPtr) {
524 assert(OwningObjectPtr && "OwningObjectPtr cannot be nullptr!")(static_cast <bool> (OwningObjectPtr && "OwningObjectPtr cannot be nullptr!"
) ? void (0) : __assert_fail ("OwningObjectPtr && \"OwningObjectPtr cannot be nullptr!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/include/llvm/Object/XCOFFObjectFile.h"
, 524, __extension__ __PRETTY_FUNCTION__))
;
6
'?' condition is true
525 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!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/include/llvm/Object/XCOFFObjectFile.h"
, 526, __extension__ __PRETTY_FUNCTION__))
7
'?' condition is true
526 "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!\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/include/llvm/Object/XCOFFObjectFile.h"
, 526, __extension__ __PRETTY_FUNCTION__))
;
527
528 if (OwningObjectPtr->is64Bit())
8
Taking false branch
529 Entry64 = reinterpret_cast<const XCOFFSymbolEntry64 *>(SymEntDataRef.p);
530 else
531 Entry32 = reinterpret_cast<const XCOFFSymbolEntry32 *>(SymEntDataRef.p);
532 }
533
534 uint64_t getValue() const { return Entry32 ? getValue32() : getValue64(); }
12
Assuming field 'Entry32' is null
13
'?' condition is false
14
Calling 'XCOFFSymbolRef::getValue64'
535
536 uint32_t getValue32() const { return Entry32->Value; }
537
538 uint64_t getValue64() const { return Entry64->Value; }
15
Called C++ object pointer is null
539
540#define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X
541
542 int16_t getSectionNumber() const { return GETVALUE(SectionNumber); }
543
544 uint16_t getSymbolType() const { return GETVALUE(SymbolType); }
545
546 uint8_t getLanguageIdForCFile() const {
547 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.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/include/llvm/Object/XCOFFObjectFile.h"
, 548, __extension__ __PRETTY_FUNCTION__))
548 "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.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/include/llvm/Object/XCOFFObjectFile.h"
, 548, __extension__ __PRETTY_FUNCTION__))
;
549 return GETVALUE(CFileLanguageIdAndTypeId.LanguageId);
550 }
551
552 uint8_t getCPUTypeIddForCFile() const {
553 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.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/include/llvm/Object/XCOFFObjectFile.h"
, 554, __extension__ __PRETTY_FUNCTION__))
554 "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.\""
, "/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/include/llvm/Object/XCOFFObjectFile.h"
, 554, __extension__ __PRETTY_FUNCTION__))
;
555 return GETVALUE(CFileLanguageIdAndTypeId.CpuTypeId);
556 }
557
558 XCOFF::StorageClass getStorageClass() const { return GETVALUE(StorageClass); }
559
560 uint8_t getNumberOfAuxEntries() const { return GETVALUE(NumberOfAuxEntries); }
561
562#undef GETVALUE
563
564 uintptr_t getEntryAddress() const {
565 return Entry32 ? reinterpret_cast<uintptr_t>(Entry32)
566 : reinterpret_cast<uintptr_t>(Entry64);
567 }
568
569 Expected<StringRef> getName() const;
570 bool isFunction() const;
571 bool isCsectSymbol() const;
572 Expected<XCOFFCsectAuxRef> getXCOFFCsectAuxRef() const;
573
574private:
575 const XCOFFObjectFile *OwningObjectPtr;
576 const XCOFFSymbolEntry32 *Entry32 = nullptr;
577 const XCOFFSymbolEntry64 *Entry64 = nullptr;
5
Null pointer value stored to field 'Entry64'
578};
579
580class TBVectorExt {
581 uint16_t Data;
582 SmallString<32> VecParmsInfo;
583
584 TBVectorExt(StringRef TBvectorStrRef, Error &Err);
585
586public:
587 static Expected<TBVectorExt> create(StringRef TBvectorStrRef);
588 uint8_t getNumberOfVRSaved() const;
589 bool isVRSavedOnStack() const;
590 bool hasVarArgs() const;
591 uint8_t getNumberOfVectorParms() const;
592 bool hasVMXInstruction() const;
593 SmallString<32> getVectorParmsInfo() const { return VecParmsInfo; };
594};
595
596/// This class provides methods to extract traceback table data from a buffer.
597/// The various accessors may reference the buffer provided via the constructor.
598
599class XCOFFTracebackTable {
600 const uint8_t *const TBPtr;
601 Optional<SmallString<32>> ParmsType;
602 Optional<uint32_t> TraceBackTableOffset;
603 Optional<uint32_t> HandlerMask;
604 Optional<uint32_t> NumOfCtlAnchors;
605 Optional<SmallVector<uint32_t, 8>> ControlledStorageInfoDisp;
606 Optional<StringRef> FunctionName;
607 Optional<uint8_t> AllocaRegister;
608 Optional<TBVectorExt> VecExt;
609 Optional<uint8_t> ExtensionTable;
610
611 XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err);
612
613public:
614 /// Parse an XCOFF Traceback Table from \a Ptr with \a Size bytes.
615 /// Returns an XCOFFTracebackTable upon successful parsing, otherwise an
616 /// Error is returned.
617 ///
618 /// \param[in] Ptr
619 /// A pointer that points just past the initial 4 bytes of zeros at the
620 /// beginning of an XCOFF Traceback Table.
621 ///
622 /// \param[in, out] Size
623 /// A pointer that points to the length of the XCOFF Traceback Table.
624 /// If the XCOFF Traceback Table is not parsed successfully or there are
625 /// extra bytes that are not recognized, \a Size will be updated to be the
626 /// size up to the end of the last successfully parsed field of the table.
627 static Expected<XCOFFTracebackTable> create(const uint8_t *Ptr,
628 uint64_t &Size);
629 uint8_t getVersion() const;
630 uint8_t getLanguageID() const;
631
632 bool isGlobalLinkage() const;
633 bool isOutOfLineEpilogOrPrologue() const;
634 bool hasTraceBackTableOffset() const;
635 bool isInternalProcedure() const;
636 bool hasControlledStorage() const;
637 bool isTOCless() const;
638 bool isFloatingPointPresent() const;
639 bool isFloatingPointOperationLogOrAbortEnabled() const;
640
641 bool isInterruptHandler() const;
642 bool isFuncNamePresent() const;
643 bool isAllocaUsed() const;
644 uint8_t getOnConditionDirective() const;
645 bool isCRSaved() const;
646 bool isLRSaved() const;
647
648 bool isBackChainStored() const;
649 bool isFixup() const;
650 uint8_t getNumOfFPRsSaved() const;
651
652 bool hasVectorInfo() const;
653 bool hasExtensionTable() const;
654 uint8_t getNumOfGPRsSaved() const;
655
656 uint8_t getNumberOfFixedParms() const;
657
658 uint8_t getNumberOfFPParms() const;
659 bool hasParmsOnStack() const;
660
661 const Optional<SmallString<32>> &getParmsType() const { return ParmsType; }
662 const Optional<uint32_t> &getTraceBackTableOffset() const {
663 return TraceBackTableOffset;
664 }
665 const Optional<uint32_t> &getHandlerMask() const { return HandlerMask; }
666 const Optional<uint32_t> &getNumOfCtlAnchors() { return NumOfCtlAnchors; }
667 const Optional<SmallVector<uint32_t, 8>> &getControlledStorageInfoDisp() {
668 return ControlledStorageInfoDisp;
669 }
670 const Optional<StringRef> &getFunctionName() const { return FunctionName; }
671 const Optional<uint8_t> &getAllocaRegister() const { return AllocaRegister; }
672 const Optional<TBVectorExt> &getVectorExt() const { return VecExt; }
673 const Optional<uint8_t> &getExtensionTable() const { return ExtensionTable; }
674};
675
676bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes);
677} // namespace object
678} // namespace llvm
679
680#endif // LLVM_OBJECT_XCOFFOBJECTFILE_H