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