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