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