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

source code of llvm/include/llvm/Object/XCOFFObjectFile.h