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 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 
43 struct 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 
57 template <typename T> struct XCOFFAuxiliaryHeader {
58   static constexpr uint8_t AuxiHeaderFlagMask = 0xF0;
59   static constexpr uint8_t AuxiHeaderTDataAlignmentMask = 0x0F;
60 
61 public:
getFlagXCOFFAuxiliaryHeader62   uint8_t getFlag() const {
63     return static_cast<const T *>(this)->FlagAndTDataAlignment &
64            AuxiHeaderFlagMask;
65   }
66 
getTDataAlignmentXCOFFAuxiliaryHeader67   uint8_t getTDataAlignment() const {
68     return static_cast<const T *>(this)->FlagAndTDataAlignment &
69            AuxiHeaderTDataAlignmentMask;
70   }
71 
getVersionXCOFFAuxiliaryHeader72   uint16_t getVersion() const { return static_cast<const T *>(this)->Version; }
73 };
74 
75 struct 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 
122 struct 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 
155 template <typename T> struct XCOFFSectionHeader {
156   // Least significant 3 bits are reserved.
157   static constexpr unsigned SectionFlagsReservedMask = 0x7;
158 
159   // The low order 16 bits of section flags denotes the section type.
160   static constexpr unsigned SectionFlagsTypeMask = 0xffffu;
161 
162 public:
163   StringRef getName() const;
164   uint16_t getSectionType() const;
165   bool isReservedSectionType() const;
166 };
167 
168 // Explicit extern template declarations.
169 struct XCOFFSectionHeader32;
170 struct XCOFFSectionHeader64;
171 extern template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
172 extern template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
173 
174 struct XCOFFSectionHeader32 : XCOFFSectionHeader<XCOFFSectionHeader32> {
175   char Name[XCOFF::NameSize];
176   support::ubig32_t PhysicalAddress;
177   support::ubig32_t VirtualAddress;
178   support::ubig32_t SectionSize;
179   support::ubig32_t FileOffsetToRawData;
180   support::ubig32_t FileOffsetToRelocationInfo;
181   support::ubig32_t FileOffsetToLineNumberInfo;
182   support::ubig16_t NumberOfRelocations;
183   support::ubig16_t NumberOfLineNumbers;
184   support::big32_t Flags;
185 };
186 
187 struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> {
188   char Name[XCOFF::NameSize];
189   support::ubig64_t PhysicalAddress;
190   support::ubig64_t VirtualAddress;
191   support::ubig64_t SectionSize;
192   support::big64_t FileOffsetToRawData;
193   support::big64_t FileOffsetToRelocationInfo;
194   support::big64_t FileOffsetToLineNumberInfo;
195   support::ubig32_t NumberOfRelocations;
196   support::ubig32_t NumberOfLineNumbers;
197   support::big32_t Flags;
198   char Padding[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   getSymbolName(const LoaderSectionHeader32 *LoaderSecHeader) 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   getSymbolName(const LoaderSectionHeader64 *LoaderSecHeader) 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 LoaderSectionHeader32 {
249   support::ubig32_t Version;
250   support::ubig32_t NumberOfSymTabEnt;
251   support::ubig32_t NumberOfRelTabEnt;
252   support::ubig32_t LengthOfImpidStrTbl;
253   support::ubig32_t NumberOfImpid;
254   support::big32_t OffsetToImpid;
255   support::ubig32_t LengthOfStrTbl;
256   support::big32_t OffsetToStrTbl;
257 
258   uint64_t getOffsetToSymTbl() const {
259     return NumberOfSymTabEnt == 0 ? 0 : sizeof(LoaderSectionHeader32);
260   }
261 
262   uint64_t getOffsetToRelEnt() 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 LoaderSectionHeader64 {
272   support::ubig32_t Version;
273   support::ubig32_t NumberOfSymTabEnt;
274   support::ubig32_t NumberOfRelTabEnt;
275   support::ubig32_t LengthOfImpidStrTbl;
276   support::ubig32_t NumberOfImpid;
277   support::ubig32_t LengthOfStrTbl;
278   support::big64_t OffsetToImpid;
279   support::big64_t OffsetToStrTbl;
280   support::big64_t OffsetToSymTbl;
281   support::big64_t OffsetToRelEnt;
282 
283   uint64_t getOffsetToSymTbl() const { return OffsetToSymTbl; }
284   uint64_t getOffsetToRelEnt() 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 *FileHeader = nullptr;
527   const void *AuxiliaryHeader = nullptr;
528   const void *SectionHeaderTable = nullptr;
529 
530   const void *SymbolTblPtr = nullptr;
531   XCOFFStringTable StringTable = {0, nullptr};
532 
533   const XCOFFSectionHeader32 *sectionHeaderTable32() const;
534   const XCOFFSectionHeader64 *sectionHeaderTable64() const;
535   template <typename T> const T *sectionHeaderTable() const;
536 
537   size_t getFileHeaderSize() const;
538   size_t getSectionHeaderSize() const;
539 
540   const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const;
541   const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const;
542   uintptr_t getSectionHeaderTableAddress() 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 *auxiliaryHeader32() const;
640   const XCOFFAuxiliaryHeader64 *auxiliaryHeader64() 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 *fileHeader32() const;
650   const XCOFFFileHeader64 *fileHeader64() 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 getOptionalHeaderSize() 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   getNumberOfRelocationEntries(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(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>(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 getNumOfFPRsSaved() const;
942 
943   bool hasVectorInfo() const;
944   bool hasExtensionTable() const;
945   uint8_t getNumOfGPRsSaved() 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