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