Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 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 " |
||
294 | "the e_reason field is 0."); |
||
295 | return SymbolIdx; |
||
296 | } |
||
297 | |||
298 | uint64_t getTrapInstAddr() const { |
||
299 | assert(Reason != 0 && "Zero is not a valid trap exception reason code."); |
||
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."); |
||
359 | return Entry32->SectionOrLength; |
||
360 | } |
||
361 | |||
362 | uint64_t getSectionOrLength64() const { |
||
363 | assert(Entry64 && "64-bit interface called on 32-bit object file."); |
||
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."); |
||
398 | return Entry32->StabInfoIndex; |
||
399 | } |
||
400 | |||
401 | uint16_t getStabSectNum32() const { |
||
402 | assert(Entry32 && "32-bit interface called on 64-bit object file."); |
||
403 | return Entry32->StabSectNum; |
||
404 | } |
||
405 | |||
406 | XCOFF::SymbolAuxType getAuxType64() const { |
||
407 | assert(Entry64 && "64-bit interface called on 32-bit object file."); |
||
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!"); |
||
770 | assert(SymEntDataRef.p != 0 && |
||
771 | "Symbol table entry pointer cannot be nullptr!"); |
||
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 && |
||
796 | "This interface is for C_FILE only."); |
||
797 | return GETVALUE(CFileLanguageIdAndTypeId.LanguageId); |
||
798 | } |
||
799 | |||
800 | uint8_t getCPUTypeIddForCFile() const { |
||
801 | assert(getStorageClass() == XCOFF::C_FILE && |
||
802 | "This interface is for C_FILE only."); |
||
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 |