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