Bug Summary

File:llvm/include/llvm/Object/XCOFFObjectFile.h
Warning:line 502, column 45
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-13~++20210613111130+5be314f79ba7/build-llvm/lib/Object -resource-dir /usr/lib/llvm-13/lib/clang/13.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-13~++20210613111130+5be314f79ba7/build-llvm/lib/Object -I /build/llvm-toolchain-snapshot-13~++20210613111130+5be314f79ba7/llvm/lib/Object -I /build/llvm-toolchain-snapshot-13~++20210613111130+5be314f79ba7/build-llvm/include -I /build/llvm-toolchain-snapshot-13~++20210613111130+5be314f79ba7/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-13/lib/clang/13.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-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-13~++20210613111130+5be314f79ba7/build-llvm/lib/Object -fdebug-prefix-map=/build/llvm-toolchain-snapshot-13~++20210613111130+5be314f79ba7=. -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -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-06-13-111025-38230-1 -x c++ /build/llvm-toolchain-snapshot-13~++20210613111130+5be314f79ba7/llvm/lib/Object/XCOFFObjectFile.cpp

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

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