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