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 struct XCOFFFunctionAuxEnt32 {
352   support::ubig32_t OffsetToExceptionTbl;
353   support::ubig32_t SizeOfFunction;
354   support::ubig32_t PtrToLineNum;
355   support::big32_t SymIdxOfNextBeyond;
356   uint8_t Pad[2];
357 };
358 
359 struct XCOFFFunctionAuxEnt64 {
360   support::ubig64_t PtrToLineNum;
361   support::ubig32_t SizeOfFunction;
362   support::big32_t SymIdxOfNextBeyond;
363   uint8_t Pad;
364   XCOFF::SymbolAuxType AuxType; // Contains _AUX_FCN; Type of auxiliary entry
365 };
366 
367 struct XCOFFExceptionAuxEnt {
368   support::ubig64_t OffsetToExceptionTbl;
369   support::ubig32_t SizeOfFunction;
370   support::big32_t SymIdxOfNextBeyond;
371   uint8_t Pad;
372   XCOFF::SymbolAuxType AuxType; // Contains _AUX_EXCEPT; Type of auxiliary entry
373 };
374 
375 struct XCOFFBlockAuxEnt32 {
376   uint8_t ReservedZeros1[2];
377   support::ubig16_t LineNumHi;
378   support::ubig16_t LineNumLo;
379   uint8_t ReservedZeros2[12];
380 };
381 
382 struct XCOFFBlockAuxEnt64 {
383   support::ubig32_t LineNum;
384   uint8_t Pad[13];
385   XCOFF::SymbolAuxType AuxType; // Contains _AUX_SYM; Type of auxiliary entry
386 };
387 
388 struct XCOFFSectAuxEntForDWARF32 {
389   support::ubig32_t LengthOfSectionPortion;
390   uint8_t Pad1[4];
391   support::ubig32_t NumberOfRelocEnt;
392   uint8_t Pad2[6];
393 };
394 
395 struct XCOFFSectAuxEntForDWARF64 {
396   support::ubig64_t LengthOfSectionPortion;
397   support::ubig64_t NumberOfRelocEnt;
398   uint8_t Pad;
399   XCOFF::SymbolAuxType AuxType; // Contains _AUX_SECT; Type of Auxillary entry
400 };
401 
402 template <typename AddressType> struct XCOFFRelocation {
403   // Masks for packing/unpacking the r_rsize field of relocations.
404 
405   // The msb is used to indicate if the bits being relocated are signed or
406   // unsigned.
407   static constexpr uint8_t XR_SIGN_INDICATOR_MASK = 0x80;
408 
409   // The 2nd msb is used to indicate that the binder has replaced/modified the
410   // original instruction.
411   static constexpr uint8_t XR_FIXUP_INDICATOR_MASK = 0x40;
412 
413   // The remaining bits specify the bit length of the relocatable reference
414   // minus one.
415   static constexpr uint8_t XR_BIASED_LENGTH_MASK = 0x3f;
416 
417 public:
418   AddressType VirtualAddress;
419   support::ubig32_t SymbolIndex;
420 
421   // Packed field, see XR_* masks for details of packing.
422   uint8_t Info;
423 
424   XCOFF::RelocationType Type;
425 
426 public:
427   bool isRelocationSigned() const;
428   bool isFixupIndicated() const;
429 
430   // Returns the number of bits being relocated.
431   uint8_t getRelocatedLength() const;
432 };
433 
434 extern template struct XCOFFRelocation<llvm::support::ubig32_t>;
435 extern template struct XCOFFRelocation<llvm::support::ubig64_t>;
436 
437 struct XCOFFRelocation32 : XCOFFRelocation<llvm::support::ubig32_t> {};
438 struct XCOFFRelocation64 : XCOFFRelocation<llvm::support::ubig64_t> {};
439 
440 class XCOFFSymbolRef;
441 
442 class XCOFFObjectFile : public ObjectFile {
443 private:
444   const void *FileHeader = nullptr;
445   const void *AuxiliaryHeader = nullptr;
446   const void *SectionHeaderTable = nullptr;
447 
448   const void *SymbolTblPtr = nullptr;
449   XCOFFStringTable StringTable = {0, nullptr};
450 
451   const XCOFFFileHeader32 *fileHeader32() const;
452   const XCOFFFileHeader64 *fileHeader64() const;
453 
454   const XCOFFSectionHeader32 *sectionHeaderTable32() const;
455   const XCOFFSectionHeader64 *sectionHeaderTable64() const;
456   template <typename T> const T *sectionHeaderTable() const;
457 
458   size_t getFileHeaderSize() const;
459   size_t getSectionHeaderSize() const;
460 
461   const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const;
462   const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const;
463   uintptr_t getSectionHeaderTableAddress() const;
464   uintptr_t getEndOfSymbolTableAddress() const;
465   Expected<uintptr_t> getLoaderSectionAddress() const;
466 
467   // This returns a pointer to the start of the storage for the name field of
468   // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily
469   // null-terminated.
470   const char *getSectionNameInternal(DataRefImpl Sec) const;
471 
472   static bool isReservedSectionNumber(int16_t SectionNumber);
473 
474   // Constructor and "create" factory function. The constructor is only a thin
475   // wrapper around the base constructor. The "create" function fills out the
476   // XCOFF-specific information and performs the error checking along the way.
477   XCOFFObjectFile(unsigned Type, MemoryBufferRef Object);
478   static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type,
479                                                            MemoryBufferRef MBR);
480 
481   // Helper for parsing the StringTable. Returns an 'Error' if parsing failed
482   // and an XCOFFStringTable if parsing succeeded.
483   static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj,
484                                                      uint64_t Offset);
485 
486   // Make a friend so it can call the private 'create' function.
487   friend Expected<std::unique_ptr<ObjectFile>>
488   ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
489 
490   void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const;
491 
492 public:
493   static constexpr uint64_t InvalidRelocOffset =
494       std::numeric_limits<uint64_t>::max();
495 
496   // Interface inherited from base classes.
497   void moveSymbolNext(DataRefImpl &Symb) const override;
498   Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
499   basic_symbol_iterator symbol_begin() const override;
500   basic_symbol_iterator symbol_end() const override;
501 
502   Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
503   Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
504   uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
505   uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
506   uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
507   Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
508   Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
509 
510   void moveSectionNext(DataRefImpl &Sec) const override;
511   Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
512   uint64_t getSectionAddress(DataRefImpl Sec) const override;
513   uint64_t getSectionIndex(DataRefImpl Sec) const override;
514   uint64_t getSectionSize(DataRefImpl Sec) const override;
515   Expected<ArrayRef<uint8_t>>
516   getSectionContents(DataRefImpl Sec) const override;
517   uint64_t getSectionAlignment(DataRefImpl Sec) const override;
518   bool isSectionCompressed(DataRefImpl Sec) const override;
519   bool isSectionText(DataRefImpl Sec) const override;
520   bool isSectionData(DataRefImpl Sec) const override;
521   bool isSectionBSS(DataRefImpl Sec) const override;
522   bool isDebugSection(DataRefImpl Sec) const override;
523 
524   bool isSectionVirtual(DataRefImpl Sec) const override;
525   relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
526   relocation_iterator section_rel_end(DataRefImpl Sec) const override;
527 
528   void moveRelocationNext(DataRefImpl &Rel) const override;
529 
530   /// \returns the relocation offset with the base address of the containing
531   /// section as zero, or InvalidRelocOffset on errors (such as a relocation
532   /// that does not refer to an address in any section).
533   uint64_t getRelocationOffset(DataRefImpl Rel) const override;
534   symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
535   uint64_t getRelocationType(DataRefImpl Rel) const override;
536   void getRelocationTypeName(DataRefImpl Rel,
537                              SmallVectorImpl<char> &Result) const override;
538 
539   section_iterator section_begin() const override;
540   section_iterator section_end() const override;
541   uint8_t getBytesInAddress() const override;
542   StringRef getFileFormatName() const override;
543   Triple::ArchType getArch() const override;
544   SubtargetFeatures getFeatures() const override;
545   Expected<uint64_t> getStartAddress() const override;
546   StringRef mapDebugSectionName(StringRef Name) const override;
547   bool isRelocatableObject() const override;
548 
549   // Below here is the non-inherited interface.
550   bool is64Bit() const;
551 
552   const XCOFFAuxiliaryHeader32 *auxiliaryHeader32() const;
553   const XCOFFAuxiliaryHeader64 *auxiliaryHeader64() const;
554 
555   const void *getPointerToSymbolTable() const { return SymbolTblPtr; }
556 
557   Expected<StringRef> getSymbolSectionName(XCOFFSymbolRef Ref) const;
558   unsigned getSymbolSectionID(SymbolRef Sym) const;
559   XCOFFSymbolRef toSymbolRef(DataRefImpl Ref) const;
560 
561   // File header related interfaces.
562   uint16_t getMagic() const;
563   uint16_t getNumberOfSections() const;
564   int32_t getTimeStamp() const;
565 
566   // Symbol table offset and entry count are handled differently between
567   // XCOFF32 and XCOFF64.
568   uint32_t getSymbolTableOffset32() const;
569   uint64_t getSymbolTableOffset64() const;
570 
571   // Note that this value is signed and might return a negative value. Negative
572   // values are reserved for future use.
573   int32_t getRawNumberOfSymbolTableEntries32() const;
574 
575   // The sanitized value appropriate to use as an index into the symbol table.
576   uint32_t getLogicalNumberOfSymbolTableEntries32() const;
577 
578   uint32_t getNumberOfSymbolTableEntries64() const;
579 
580   // Return getLogicalNumberOfSymbolTableEntries32 or
581   // getNumberOfSymbolTableEntries64 depending on the object mode.
582   uint32_t getNumberOfSymbolTableEntries() const;
583 
584   uint32_t getSymbolIndex(uintptr_t SymEntPtr) const;
585   uint64_t getSymbolSize(DataRefImpl Symb) const;
586   uintptr_t getSymbolByIndex(uint32_t Idx) const {
587     return reinterpret_cast<uintptr_t>(SymbolTblPtr) +
588            XCOFF::SymbolTableEntrySize * Idx;
589   }
590   uintptr_t getSymbolEntryAddressByIndex(uint32_t SymbolTableIndex) const;
591   Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const;
592 
593   Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const;
594   uint16_t getOptionalHeaderSize() const;
595   uint16_t getFlags() const;
596 
597   // Section header table related interfaces.
598   ArrayRef<XCOFFSectionHeader32> sections32() const;
599   ArrayRef<XCOFFSectionHeader64> sections64() const;
600 
601   int32_t getSectionFlags(DataRefImpl Sec) const;
602   Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
603 
604   void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const;
605 
606   // Relocation-related interfaces.
607   template <typename T>
608   Expected<uint32_t>
609   getNumberOfRelocationEntries(const XCOFFSectionHeader<T> &Sec) const;
610 
611   template <typename Shdr, typename Reloc>
612   Expected<ArrayRef<Reloc>> relocations(const Shdr &Sec) const;
613 
614   // Loader section related interfaces.
615   Expected<StringRef> getImportFileTable() const;
616 
617   // This function returns string table entry.
618   Expected<StringRef> getStringTableEntry(uint32_t Offset) const;
619 
620   // This function returns the string table.
621   StringRef getStringTable() const;
622 
623   const XCOFF::SymbolAuxType *getSymbolAuxType(uintptr_t AuxEntryAddress) const;
624 
625   static uintptr_t getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
626                                                  uint32_t Distance);
627 
628   static bool classof(const Binary *B) { return B->isXCOFF(); }
629 }; // XCOFFObjectFile
630 
631 typedef struct {
632   uint8_t LanguageId;
633   uint8_t CpuTypeId;
634 } CFileLanguageIdAndTypeIdType;
635 
636 struct XCOFFSymbolEntry32 {
637   typedef struct {
638     support::big32_t Magic; // Zero indicates name in string table.
639     support::ubig32_t Offset;
640   } NameInStrTblType;
641 
642   union {
643     char SymbolName[XCOFF::NameSize];
644     NameInStrTblType NameInStrTbl;
645   };
646 
647   support::ubig32_t Value; // Symbol value; storage class-dependent.
648   support::big16_t SectionNumber;
649 
650   union {
651     support::ubig16_t SymbolType;
652     CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
653   };
654 
655   XCOFF::StorageClass StorageClass;
656   uint8_t NumberOfAuxEntries;
657 };
658 
659 struct XCOFFSymbolEntry64 {
660   support::ubig64_t Value; // Symbol value; storage class-dependent.
661   support::ubig32_t Offset;
662   support::big16_t SectionNumber;
663 
664   union {
665     support::ubig16_t SymbolType;
666     CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
667   };
668 
669   XCOFF::StorageClass StorageClass;
670   uint8_t NumberOfAuxEntries;
671 };
672 
673 class XCOFFSymbolRef {
674 public:
675   enum { NAME_IN_STR_TBL_MAGIC = 0x0 };
676 
677   XCOFFSymbolRef(DataRefImpl SymEntDataRef,
678                  const XCOFFObjectFile *OwningObjectPtr)
679       : OwningObjectPtr(OwningObjectPtr) {
680     assert(OwningObjectPtr && "OwningObjectPtr cannot be nullptr!");
681     assert(SymEntDataRef.p != 0 &&
682            "Symbol table entry pointer cannot be nullptr!");
683 
684     if (OwningObjectPtr->is64Bit())
685       Entry64 = reinterpret_cast<const XCOFFSymbolEntry64 *>(SymEntDataRef.p);
686     else
687       Entry32 = reinterpret_cast<const XCOFFSymbolEntry32 *>(SymEntDataRef.p);
688   }
689 
690   uint64_t getValue() const { return Entry32 ? getValue32() : getValue64(); }
691 
692   uint32_t getValue32() const { return Entry32->Value; }
693 
694   uint64_t getValue64() const { return Entry64->Value; }
695 
696 #define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X
697 
698   int16_t getSectionNumber() const { return GETVALUE(SectionNumber); }
699 
700   uint16_t getSymbolType() const { return GETVALUE(SymbolType); }
701 
702   uint8_t getLanguageIdForCFile() const {
703     assert(getStorageClass() == XCOFF::C_FILE &&
704            "This interface is for C_FILE only.");
705     return GETVALUE(CFileLanguageIdAndTypeId.LanguageId);
706   }
707 
708   uint8_t getCPUTypeIddForCFile() const {
709     assert(getStorageClass() == XCOFF::C_FILE &&
710            "This interface is for C_FILE only.");
711     return GETVALUE(CFileLanguageIdAndTypeId.CpuTypeId);
712   }
713 
714   XCOFF::StorageClass getStorageClass() const { return GETVALUE(StorageClass); }
715 
716   uint8_t getNumberOfAuxEntries() const { return GETVALUE(NumberOfAuxEntries); }
717 
718 #undef GETVALUE
719 
720   uintptr_t getEntryAddress() const {
721     return Entry32 ? reinterpret_cast<uintptr_t>(Entry32)
722                    : reinterpret_cast<uintptr_t>(Entry64);
723   }
724 
725   Expected<StringRef> getName() const;
726   bool isFunction() const;
727   bool isCsectSymbol() const;
728   Expected<XCOFFCsectAuxRef> getXCOFFCsectAuxRef() const;
729 
730 private:
731   const XCOFFObjectFile *OwningObjectPtr;
732   const XCOFFSymbolEntry32 *Entry32 = nullptr;
733   const XCOFFSymbolEntry64 *Entry64 = nullptr;
734 };
735 
736 class TBVectorExt {
737   uint16_t Data;
738   SmallString<32> VecParmsInfo;
739 
740   TBVectorExt(StringRef TBvectorStrRef, Error &Err);
741 
742 public:
743   static Expected<TBVectorExt> create(StringRef TBvectorStrRef);
744   uint8_t getNumberOfVRSaved() const;
745   bool isVRSavedOnStack() const;
746   bool hasVarArgs() const;
747   uint8_t getNumberOfVectorParms() const;
748   bool hasVMXInstruction() const;
749   SmallString<32> getVectorParmsInfo() const { return VecParmsInfo; };
750 };
751 
752 /// This class provides methods to extract traceback table data from a buffer.
753 /// The various accessors may reference the buffer provided via the constructor.
754 
755 class XCOFFTracebackTable {
756   const uint8_t *const TBPtr;
757   Optional<SmallString<32>> ParmsType;
758   Optional<uint32_t> TraceBackTableOffset;
759   Optional<uint32_t> HandlerMask;
760   Optional<uint32_t> NumOfCtlAnchors;
761   Optional<SmallVector<uint32_t, 8>> ControlledStorageInfoDisp;
762   Optional<StringRef> FunctionName;
763   Optional<uint8_t> AllocaRegister;
764   Optional<TBVectorExt> VecExt;
765   Optional<uint8_t> ExtensionTable;
766 
767   XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err);
768 
769 public:
770   /// Parse an XCOFF Traceback Table from \a Ptr with \a Size bytes.
771   /// Returns an XCOFFTracebackTable upon successful parsing, otherwise an
772   /// Error is returned.
773   ///
774   /// \param[in] Ptr
775   ///   A pointer that points just past the initial 4 bytes of zeros at the
776   ///   beginning of an XCOFF Traceback Table.
777   ///
778   /// \param[in, out] Size
779   ///    A pointer that points to the length of the XCOFF Traceback Table.
780   ///    If the XCOFF Traceback Table is not parsed successfully or there are
781   ///    extra bytes that are not recognized, \a Size will be updated to be the
782   ///    size up to the end of the last successfully parsed field of the table.
783   static Expected<XCOFFTracebackTable> create(const uint8_t *Ptr,
784                                               uint64_t &Size);
785   uint8_t getVersion() const;
786   uint8_t getLanguageID() const;
787 
788   bool isGlobalLinkage() const;
789   bool isOutOfLineEpilogOrPrologue() const;
790   bool hasTraceBackTableOffset() const;
791   bool isInternalProcedure() const;
792   bool hasControlledStorage() const;
793   bool isTOCless() const;
794   bool isFloatingPointPresent() const;
795   bool isFloatingPointOperationLogOrAbortEnabled() const;
796 
797   bool isInterruptHandler() const;
798   bool isFuncNamePresent() const;
799   bool isAllocaUsed() const;
800   uint8_t getOnConditionDirective() const;
801   bool isCRSaved() const;
802   bool isLRSaved() const;
803 
804   bool isBackChainStored() const;
805   bool isFixup() const;
806   uint8_t getNumOfFPRsSaved() const;
807 
808   bool hasVectorInfo() const;
809   bool hasExtensionTable() const;
810   uint8_t getNumOfGPRsSaved() const;
811 
812   uint8_t getNumberOfFixedParms() const;
813 
814   uint8_t getNumberOfFPParms() const;
815   bool hasParmsOnStack() const;
816 
817   const Optional<SmallString<32>> &getParmsType() const { return ParmsType; }
818   const Optional<uint32_t> &getTraceBackTableOffset() const {
819     return TraceBackTableOffset;
820   }
821   const Optional<uint32_t> &getHandlerMask() const { return HandlerMask; }
822   const Optional<uint32_t> &getNumOfCtlAnchors() { return NumOfCtlAnchors; }
823   const Optional<SmallVector<uint32_t, 8>> &getControlledStorageInfoDisp() {
824     return ControlledStorageInfoDisp;
825   }
826   const Optional<StringRef> &getFunctionName() const { return FunctionName; }
827   const Optional<uint8_t> &getAllocaRegister() const { return AllocaRegister; }
828   const Optional<TBVectorExt> &getVectorExt() const { return VecExt; }
829   const Optional<uint8_t> &getExtensionTable() const { return ExtensionTable; }
830 };
831 
832 bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes);
833 } // namespace object
834 } // namespace llvm
835 
836 #endif // LLVM_OBJECT_XCOFFOBJECTFILE_H
837