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 
64   uint8_t getTDataAlignment() const {
65     return static_cast<const T *>(this)->FlagAndTDataAlignment &
66            AuxiHeaderTDataAlignmentMask;
67   }
68 
69   uint16_t getVersion() const { return static_cast<const T *>(this)->Version; }
70 };
71 
72 struct XCOFFAuxiliaryHeader32 : XCOFFAuxiliaryHeader<XCOFFAuxiliaryHeader32> {
73   support::ubig16_t
74       AuxMagic; ///< If the value of the o_vstamp field is greater than 1, the
75                 ///< o_mflags field is reserved for future use and it should
76                 ///< contain 0. Otherwise, this field is not used.
77   support::ubig16_t
78       Version; ///< The valid values are 1 and 2. When the o_vstamp field is 2
79                ///< in an XCOFF32 file, the new interpretation of the n_type
80                ///< field in the symbol table entry is used.
81   support::ubig32_t TextSize;
82   support::ubig32_t InitDataSize;
83   support::ubig32_t BssDataSize;
84   support::ubig32_t EntryPointAddr;
85   support::ubig32_t TextStartAddr;
86   support::ubig32_t DataStartAddr;
87   support::ubig32_t TOCAnchorAddr;
88   support::ubig16_t SecNumOfEntryPoint;
89   support::ubig16_t SecNumOfText;
90   support::ubig16_t SecNumOfData;
91   support::ubig16_t SecNumOfTOC;
92   support::ubig16_t SecNumOfLoader;
93   support::ubig16_t SecNumOfBSS;
94   support::ubig16_t MaxAlignOfText;
95   support::ubig16_t MaxAlignOfData;
96   support::ubig16_t ModuleType;
97   uint8_t CpuFlag;
98   uint8_t CpuType;
99   support::ubig32_t MaxStackSize; ///< If the value is 0, the system default
100                                   ///< maximum stack size is used.
101   support::ubig32_t MaxDataSize;  ///< If the value is 0, the system default
102                                   ///< maximum data size is used.
103   support::ubig32_t
104       ReservedForDebugger; ///< This field should contain 0. When a loaded
105                            ///< program is being debugged, the memory image of
106                            ///< this field may be modified by a debugger to
107                            ///< insert a trap instruction.
108   uint8_t TextPageSize;  ///< Specifies the size of pages for the exec text. The
109                          ///< default value is 0 (system-selected page size).
110   uint8_t DataPageSize;  ///< Specifies the size of pages for the exec data. The
111                          ///< default value is 0 (system-selected page size).
112   uint8_t StackPageSize; ///< Specifies the size of pages for the stack. The
113                          ///< default value is 0 (system-selected page size).
114   uint8_t FlagAndTDataAlignment;
115   support::ubig16_t SecNumOfTData;
116   support::ubig16_t SecNumOfTBSS;
117 };
118 
119 struct XCOFFAuxiliaryHeader64 : XCOFFAuxiliaryHeader<XCOFFAuxiliaryHeader64> {
120   support::ubig16_t AuxMagic;
121   support::ubig16_t Version;
122   support::ubig32_t ReservedForDebugger;
123   support::ubig64_t TextStartAddr;
124   support::ubig64_t DataStartAddr;
125   support::ubig64_t TOCAnchorAddr;
126   support::ubig16_t SecNumOfEntryPoint;
127   support::ubig16_t SecNumOfText;
128   support::ubig16_t SecNumOfData;
129   support::ubig16_t SecNumOfTOC;
130   support::ubig16_t SecNumOfLoader;
131   support::ubig16_t SecNumOfBSS;
132   support::ubig16_t MaxAlignOfText;
133   support::ubig16_t MaxAlignOfData;
134   support::ubig16_t ModuleType;
135   uint8_t CpuFlag;
136   uint8_t CpuType;
137   uint8_t TextPageSize;
138   uint8_t DataPageSize;
139   uint8_t StackPageSize;
140   uint8_t FlagAndTDataAlignment;
141   support::ubig64_t TextSize;
142   support::ubig64_t InitDataSize;
143   support::ubig64_t BssDataSize;
144   support::ubig64_t EntryPointAddr;
145   support::ubig64_t MaxStackSize;
146   support::ubig64_t MaxDataSize;
147   support::ubig16_t SecNumOfTData;
148   support::ubig16_t SecNumOfTBSS;
149   support::ubig16_t XCOFF64Flag;
150 };
151 
152 template <typename T> struct XCOFFSectionHeader {
153   // Least significant 3 bits are reserved.
154   static constexpr unsigned SectionFlagsReservedMask = 0x7;
155 
156   // The low order 16 bits of section flags denotes the section type.
157   static constexpr unsigned SectionFlagsTypeMask = 0xffffu;
158 
159 public:
160   StringRef getName() const;
161   uint16_t getSectionType() const;
162   bool isReservedSectionType() const;
163 };
164 
165 // Explicit extern template declarations.
166 struct XCOFFSectionHeader32;
167 struct XCOFFSectionHeader64;
168 extern template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
169 extern template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
170 
171 struct XCOFFSectionHeader32 : XCOFFSectionHeader<XCOFFSectionHeader32> {
172   char Name[XCOFF::NameSize];
173   support::ubig32_t PhysicalAddress;
174   support::ubig32_t VirtualAddress;
175   support::ubig32_t SectionSize;
176   support::ubig32_t FileOffsetToRawData;
177   support::ubig32_t FileOffsetToRelocationInfo;
178   support::ubig32_t FileOffsetToLineNumberInfo;
179   support::ubig16_t NumberOfRelocations;
180   support::ubig16_t NumberOfLineNumbers;
181   support::big32_t Flags;
182 };
183 
184 struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> {
185   char Name[XCOFF::NameSize];
186   support::ubig64_t PhysicalAddress;
187   support::ubig64_t VirtualAddress;
188   support::ubig64_t SectionSize;
189   support::big64_t FileOffsetToRawData;
190   support::big64_t FileOffsetToRelocationInfo;
191   support::big64_t FileOffsetToLineNumberInfo;
192   support::ubig32_t NumberOfRelocations;
193   support::ubig32_t NumberOfLineNumbers;
194   support::big32_t Flags;
195   char Padding[4];
196 };
197 
198 struct LoaderSectionHeader32 {
199   support::ubig32_t Version;
200   support::ubig32_t NumberOfSymTabEnt;
201   support::ubig32_t NumberOfRelTabEnt;
202   support::ubig32_t LengthOfImpidStrTbl;
203   support::ubig32_t NumberOfImpid;
204   support::big32_t OffsetToImpid;
205   support::ubig32_t LengthOfStrTbl;
206   support::big32_t OffsetToStrTbl;
207 };
208 
209 struct LoaderSectionHeader64 {
210   support::ubig32_t Version;
211   support::ubig32_t NumberOfSymTabEnt;
212   support::ubig32_t NumberOfRelTabEnt;
213   support::ubig32_t LengthOfImpidStrTbl;
214   support::ubig32_t NumberOfImpid;
215   support::ubig32_t LengthOfStrTbl;
216   support::big64_t OffsetToImpid;
217   support::big64_t OffsetToStrTbl;
218   support::big64_t OffsetToSymTbl;
219   char Padding[16];
220   support::big32_t OffsetToRelEnt;
221 };
222 
223 struct XCOFFStringTable {
224   uint32_t Size;
225   const char *Data;
226 };
227 
228 struct XCOFFCsectAuxEnt32 {
229   support::ubig32_t SectionOrLength;
230   support::ubig32_t ParameterHashIndex;
231   support::ubig16_t TypeChkSectNum;
232   uint8_t SymbolAlignmentAndType;
233   XCOFF::StorageMappingClass StorageMappingClass;
234   support::ubig32_t StabInfoIndex;
235   support::ubig16_t StabSectNum;
236 };
237 
238 struct XCOFFCsectAuxEnt64 {
239   support::ubig32_t SectionOrLengthLowByte;
240   support::ubig32_t ParameterHashIndex;
241   support::ubig16_t TypeChkSectNum;
242   uint8_t SymbolAlignmentAndType;
243   XCOFF::StorageMappingClass StorageMappingClass;
244   support::ubig32_t SectionOrLengthHighByte;
245   uint8_t Pad;
246   XCOFF::SymbolAuxType AuxType;
247 };
248 
249 class XCOFFCsectAuxRef {
250 public:
251   static constexpr uint8_t SymbolTypeMask = 0x07;
252   static constexpr uint8_t SymbolAlignmentMask = 0xF8;
253   static constexpr size_t SymbolAlignmentBitOffset = 3;
254 
255   XCOFFCsectAuxRef(const XCOFFCsectAuxEnt32 *Entry32) : Entry32(Entry32) {}
256   XCOFFCsectAuxRef(const XCOFFCsectAuxEnt64 *Entry64) : Entry64(Entry64) {}
257 
258   // For getSectionOrLength(),
259   // If the symbol type is XTY_SD or XTY_CM, the csect length.
260   // If the symbol type is XTY_LD, the symbol table
261   // index of the containing csect.
262   // If the symbol type is XTY_ER, 0.
263   uint64_t getSectionOrLength() const {
264     return Entry32 ? getSectionOrLength32() : getSectionOrLength64();
265   }
266 
267   uint32_t getSectionOrLength32() const {
268     assert(Entry32 && "32-bit interface called on 64-bit object file.");
269     return Entry32->SectionOrLength;
270   }
271 
272   uint64_t getSectionOrLength64() const {
273     assert(Entry64 && "64-bit interface called on 32-bit object file.");
274     return (static_cast<uint64_t>(Entry64->SectionOrLengthHighByte) << 32) |
275            Entry64->SectionOrLengthLowByte;
276   }
277 
278 #define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X
279 
280   uint32_t getParameterHashIndex() const {
281     return GETVALUE(ParameterHashIndex);
282   }
283 
284   uint16_t getTypeChkSectNum() const { return GETVALUE(TypeChkSectNum); }
285 
286   XCOFF::StorageMappingClass getStorageMappingClass() const {
287     return GETVALUE(StorageMappingClass);
288   }
289 
290   uintptr_t getEntryAddress() const {
291     return Entry32 ? reinterpret_cast<uintptr_t>(Entry32)
292                    : reinterpret_cast<uintptr_t>(Entry64);
293   }
294 
295   uint16_t getAlignmentLog2() const {
296     return (getSymbolAlignmentAndType() & SymbolAlignmentMask) >>
297            SymbolAlignmentBitOffset;
298   }
299 
300   uint8_t getSymbolType() const {
301     return getSymbolAlignmentAndType() & SymbolTypeMask;
302   }
303 
304   bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; }
305 
306   uint32_t getStabInfoIndex32() const {
307     assert(Entry32 && "32-bit interface called on 64-bit object file.");
308     return Entry32->StabInfoIndex;
309   }
310 
311   uint16_t getStabSectNum32() const {
312     assert(Entry32 && "32-bit interface called on 64-bit object file.");
313     return Entry32->StabSectNum;
314   }
315 
316   XCOFF::SymbolAuxType getAuxType64() const {
317     assert(Entry64 && "64-bit interface called on 32-bit object file.");
318     return Entry64->AuxType;
319   }
320 
321 private:
322   uint8_t getSymbolAlignmentAndType() const {
323     return GETVALUE(SymbolAlignmentAndType);
324   }
325 
326 #undef GETVALUE
327 
328   const XCOFFCsectAuxEnt32 *Entry32 = nullptr;
329   const XCOFFCsectAuxEnt64 *Entry64 = nullptr;
330 };
331 
332 struct XCOFFFileAuxEnt {
333   typedef struct {
334     support::big32_t Magic; // Zero indicates name in string table.
335     support::ubig32_t Offset;
336     char NamePad[XCOFF::FileNamePadSize];
337   } NameInStrTblType;
338   union {
339     char Name[XCOFF::NameSize + XCOFF::FileNamePadSize];
340     NameInStrTblType NameInStrTbl;
341   };
342   XCOFF::CFileStringType Type;
343   uint8_t ReservedZeros[2];
344   XCOFF::SymbolAuxType AuxType; // 64-bit XCOFF file only.
345 };
346 
347 struct XCOFFSectAuxEntForStat {
348   support::ubig32_t SectionLength;
349   support::ubig16_t NumberOfRelocEnt;
350   support::ubig16_t NumberOfLineNum;
351   uint8_t Pad[10];
352 }; // 32-bit XCOFF file only.
353 
354 struct XCOFFFunctionAuxEnt32 {
355   support::ubig32_t OffsetToExceptionTbl;
356   support::ubig32_t SizeOfFunction;
357   support::ubig32_t PtrToLineNum;
358   support::big32_t SymIdxOfNextBeyond;
359   uint8_t Pad[2];
360 };
361 
362 struct XCOFFFunctionAuxEnt64 {
363   support::ubig64_t PtrToLineNum;
364   support::ubig32_t SizeOfFunction;
365   support::big32_t SymIdxOfNextBeyond;
366   uint8_t Pad;
367   XCOFF::SymbolAuxType AuxType; // Contains _AUX_FCN; Type of auxiliary entry
368 };
369 
370 struct XCOFFExceptionAuxEnt {
371   support::ubig64_t OffsetToExceptionTbl;
372   support::ubig32_t SizeOfFunction;
373   support::big32_t SymIdxOfNextBeyond;
374   uint8_t Pad;
375   XCOFF::SymbolAuxType AuxType; // Contains _AUX_EXCEPT; Type of auxiliary entry
376 };
377 
378 struct XCOFFBlockAuxEnt32 {
379   uint8_t ReservedZeros1[2];
380   support::ubig16_t LineNumHi;
381   support::ubig16_t LineNumLo;
382   uint8_t ReservedZeros2[12];
383 };
384 
385 struct XCOFFBlockAuxEnt64 {
386   support::ubig32_t LineNum;
387   uint8_t Pad[13];
388   XCOFF::SymbolAuxType AuxType; // Contains _AUX_SYM; Type of auxiliary entry
389 };
390 
391 struct XCOFFSectAuxEntForDWARF32 {
392   support::ubig32_t LengthOfSectionPortion;
393   uint8_t Pad1[4];
394   support::ubig32_t NumberOfRelocEnt;
395   uint8_t Pad2[6];
396 };
397 
398 struct XCOFFSectAuxEntForDWARF64 {
399   support::ubig64_t LengthOfSectionPortion;
400   support::ubig64_t NumberOfRelocEnt;
401   uint8_t Pad;
402   XCOFF::SymbolAuxType AuxType; // Contains _AUX_SECT; Type of Auxillary entry
403 };
404 
405 template <typename AddressType> struct XCOFFRelocation {
406   // Masks for packing/unpacking the r_rsize field of relocations.
407 
408   // The msb is used to indicate if the bits being relocated are signed or
409   // unsigned.
410   static constexpr uint8_t XR_SIGN_INDICATOR_MASK = 0x80;
411 
412   // The 2nd msb is used to indicate that the binder has replaced/modified the
413   // original instruction.
414   static constexpr uint8_t XR_FIXUP_INDICATOR_MASK = 0x40;
415 
416   // The remaining bits specify the bit length of the relocatable reference
417   // minus one.
418   static constexpr uint8_t XR_BIASED_LENGTH_MASK = 0x3f;
419 
420 public:
421   AddressType VirtualAddress;
422   support::ubig32_t SymbolIndex;
423 
424   // Packed field, see XR_* masks for details of packing.
425   uint8_t Info;
426 
427   XCOFF::RelocationType Type;
428 
429 public:
430   bool isRelocationSigned() const;
431   bool isFixupIndicated() const;
432 
433   // Returns the number of bits being relocated.
434   uint8_t getRelocatedLength() const;
435 };
436 
437 extern template struct XCOFFRelocation<llvm::support::ubig32_t>;
438 extern template struct XCOFFRelocation<llvm::support::ubig64_t>;
439 
440 struct XCOFFRelocation32 : XCOFFRelocation<llvm::support::ubig32_t> {};
441 struct XCOFFRelocation64 : XCOFFRelocation<llvm::support::ubig64_t> {};
442 
443 class XCOFFSymbolRef;
444 
445 class XCOFFObjectFile : public ObjectFile {
446 private:
447   const void *FileHeader = nullptr;
448   const void *AuxiliaryHeader = nullptr;
449   const void *SectionHeaderTable = nullptr;
450 
451   const void *SymbolTblPtr = nullptr;
452   XCOFFStringTable StringTable = {0, nullptr};
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   Expected<StringRef> getRawData(const char *Start, uint64_t Size,
552                                  StringRef Name) const;
553 
554   const XCOFFAuxiliaryHeader32 *auxiliaryHeader32() const;
555   const XCOFFAuxiliaryHeader64 *auxiliaryHeader64() const;
556 
557   const void *getPointerToSymbolTable() const { return SymbolTblPtr; }
558 
559   Expected<StringRef> getSymbolSectionName(XCOFFSymbolRef Ref) const;
560   unsigned getSymbolSectionID(SymbolRef Sym) const;
561   XCOFFSymbolRef toSymbolRef(DataRefImpl Ref) const;
562 
563   // File header related interfaces.
564   const XCOFFFileHeader32 *fileHeader32() const;
565   const XCOFFFileHeader64 *fileHeader64() const;
566   uint16_t getMagic() const;
567   uint16_t getNumberOfSections() const;
568   int32_t getTimeStamp() const;
569 
570   // Symbol table offset and entry count are handled differently between
571   // XCOFF32 and XCOFF64.
572   uint32_t getSymbolTableOffset32() const;
573   uint64_t getSymbolTableOffset64() const;
574 
575   // Note that this value is signed and might return a negative value. Negative
576   // values are reserved for future use.
577   int32_t getRawNumberOfSymbolTableEntries32() const;
578 
579   // The sanitized value appropriate to use as an index into the symbol table.
580   uint32_t getLogicalNumberOfSymbolTableEntries32() const;
581 
582   uint32_t getNumberOfSymbolTableEntries64() const;
583 
584   // Return getLogicalNumberOfSymbolTableEntries32 or
585   // getNumberOfSymbolTableEntries64 depending on the object mode.
586   uint32_t getNumberOfSymbolTableEntries() const;
587 
588   uint32_t getSymbolIndex(uintptr_t SymEntPtr) const;
589   uint64_t getSymbolSize(DataRefImpl Symb) const;
590   uintptr_t getSymbolByIndex(uint32_t Idx) const {
591     return reinterpret_cast<uintptr_t>(SymbolTblPtr) +
592            XCOFF::SymbolTableEntrySize * Idx;
593   }
594   uintptr_t getSymbolEntryAddressByIndex(uint32_t SymbolTableIndex) const;
595   Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const;
596 
597   Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const;
598   uint16_t getOptionalHeaderSize() const;
599   uint16_t getFlags() const;
600 
601   // Section header table related interfaces.
602   ArrayRef<XCOFFSectionHeader32> sections32() const;
603   ArrayRef<XCOFFSectionHeader64> sections64() const;
604 
605   int32_t getSectionFlags(DataRefImpl Sec) const;
606   Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
607 
608   void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const;
609 
610   // Relocation-related interfaces.
611   template <typename T>
612   Expected<uint32_t>
613   getNumberOfRelocationEntries(const XCOFFSectionHeader<T> &Sec) const;
614 
615   template <typename Shdr, typename Reloc>
616   Expected<ArrayRef<Reloc>> relocations(const Shdr &Sec) const;
617 
618   // Loader section related interfaces.
619   Expected<StringRef> getImportFileTable() const;
620 
621   // This function returns string table entry.
622   Expected<StringRef> getStringTableEntry(uint32_t Offset) const;
623 
624   // This function returns the string table.
625   StringRef getStringTable() const;
626 
627   const XCOFF::SymbolAuxType *getSymbolAuxType(uintptr_t AuxEntryAddress) const;
628 
629   static uintptr_t getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
630                                                  uint32_t Distance);
631 
632   static bool classof(const Binary *B) { return B->isXCOFF(); }
633 }; // XCOFFObjectFile
634 
635 typedef struct {
636   uint8_t LanguageId;
637   uint8_t CpuTypeId;
638 } CFileLanguageIdAndTypeIdType;
639 
640 struct XCOFFSymbolEntry32 {
641   typedef struct {
642     support::big32_t Magic; // Zero indicates name in string table.
643     support::ubig32_t Offset;
644   } NameInStrTblType;
645 
646   union {
647     char SymbolName[XCOFF::NameSize];
648     NameInStrTblType NameInStrTbl;
649   };
650 
651   support::ubig32_t Value; // Symbol value; storage class-dependent.
652   support::big16_t SectionNumber;
653 
654   union {
655     support::ubig16_t SymbolType;
656     CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
657   };
658 
659   XCOFF::StorageClass StorageClass;
660   uint8_t NumberOfAuxEntries;
661 };
662 
663 struct XCOFFSymbolEntry64 {
664   support::ubig64_t Value; // Symbol value; storage class-dependent.
665   support::ubig32_t Offset;
666   support::big16_t SectionNumber;
667 
668   union {
669     support::ubig16_t SymbolType;
670     CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
671   };
672 
673   XCOFF::StorageClass StorageClass;
674   uint8_t NumberOfAuxEntries;
675 };
676 
677 class XCOFFSymbolRef {
678 public:
679   enum { NAME_IN_STR_TBL_MAGIC = 0x0 };
680 
681   XCOFFSymbolRef(DataRefImpl SymEntDataRef,
682                  const XCOFFObjectFile *OwningObjectPtr)
683       : OwningObjectPtr(OwningObjectPtr) {
684     assert(OwningObjectPtr && "OwningObjectPtr cannot be nullptr!");
685     assert(SymEntDataRef.p != 0 &&
686            "Symbol table entry pointer cannot be nullptr!");
687 
688     if (OwningObjectPtr->is64Bit())
689       Entry64 = reinterpret_cast<const XCOFFSymbolEntry64 *>(SymEntDataRef.p);
690     else
691       Entry32 = reinterpret_cast<const XCOFFSymbolEntry32 *>(SymEntDataRef.p);
692   }
693 
694   const XCOFFSymbolEntry32 *getSymbol32() { return Entry32; }
695   const XCOFFSymbolEntry64 *getSymbol64() { return Entry64; }
696 
697   uint64_t getValue() const { return Entry32 ? getValue32() : getValue64(); }
698 
699   uint32_t getValue32() const { return Entry32->Value; }
700 
701   uint64_t getValue64() const { return Entry64->Value; }
702 
703 #define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X
704 
705   int16_t getSectionNumber() const { return GETVALUE(SectionNumber); }
706 
707   uint16_t getSymbolType() const { return GETVALUE(SymbolType); }
708 
709   uint8_t getLanguageIdForCFile() const {
710     assert(getStorageClass() == XCOFF::C_FILE &&
711            "This interface is for C_FILE only.");
712     return GETVALUE(CFileLanguageIdAndTypeId.LanguageId);
713   }
714 
715   uint8_t getCPUTypeIddForCFile() const {
716     assert(getStorageClass() == XCOFF::C_FILE &&
717            "This interface is for C_FILE only.");
718     return GETVALUE(CFileLanguageIdAndTypeId.CpuTypeId);
719   }
720 
721   XCOFF::StorageClass getStorageClass() const { return GETVALUE(StorageClass); }
722 
723   uint8_t getNumberOfAuxEntries() const { return GETVALUE(NumberOfAuxEntries); }
724 
725 #undef GETVALUE
726 
727   uintptr_t getEntryAddress() const {
728     return Entry32 ? reinterpret_cast<uintptr_t>(Entry32)
729                    : reinterpret_cast<uintptr_t>(Entry64);
730   }
731 
732   Expected<StringRef> getName() const;
733   bool isFunction() const;
734   bool isCsectSymbol() const;
735   Expected<XCOFFCsectAuxRef> getXCOFFCsectAuxRef() const;
736 
737 private:
738   const XCOFFObjectFile *OwningObjectPtr;
739   const XCOFFSymbolEntry32 *Entry32 = nullptr;
740   const XCOFFSymbolEntry64 *Entry64 = nullptr;
741 };
742 
743 class TBVectorExt {
744   uint16_t Data;
745   SmallString<32> VecParmsInfo;
746 
747   TBVectorExt(StringRef TBvectorStrRef, Error &Err);
748 
749 public:
750   static Expected<TBVectorExt> create(StringRef TBvectorStrRef);
751   uint8_t getNumberOfVRSaved() const;
752   bool isVRSavedOnStack() const;
753   bool hasVarArgs() const;
754   uint8_t getNumberOfVectorParms() const;
755   bool hasVMXInstruction() const;
756   SmallString<32> getVectorParmsInfo() const { return VecParmsInfo; };
757 };
758 
759 /// This class provides methods to extract traceback table data from a buffer.
760 /// The various accessors may reference the buffer provided via the constructor.
761 
762 class XCOFFTracebackTable {
763   const uint8_t *const TBPtr;
764   Optional<SmallString<32>> ParmsType;
765   Optional<uint32_t> TraceBackTableOffset;
766   Optional<uint32_t> HandlerMask;
767   Optional<uint32_t> NumOfCtlAnchors;
768   Optional<SmallVector<uint32_t, 8>> ControlledStorageInfoDisp;
769   Optional<StringRef> FunctionName;
770   Optional<uint8_t> AllocaRegister;
771   Optional<TBVectorExt> VecExt;
772   Optional<uint8_t> ExtensionTable;
773 
774   XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err);
775 
776 public:
777   /// Parse an XCOFF Traceback Table from \a Ptr with \a Size bytes.
778   /// Returns an XCOFFTracebackTable upon successful parsing, otherwise an
779   /// Error is returned.
780   ///
781   /// \param[in] Ptr
782   ///   A pointer that points just past the initial 4 bytes of zeros at the
783   ///   beginning of an XCOFF Traceback Table.
784   ///
785   /// \param[in, out] Size
786   ///    A pointer that points to the length of the XCOFF Traceback Table.
787   ///    If the XCOFF Traceback Table is not parsed successfully or there are
788   ///    extra bytes that are not recognized, \a Size will be updated to be the
789   ///    size up to the end of the last successfully parsed field of the table.
790   static Expected<XCOFFTracebackTable> create(const uint8_t *Ptr,
791                                               uint64_t &Size);
792   uint8_t getVersion() const;
793   uint8_t getLanguageID() const;
794 
795   bool isGlobalLinkage() const;
796   bool isOutOfLineEpilogOrPrologue() const;
797   bool hasTraceBackTableOffset() const;
798   bool isInternalProcedure() const;
799   bool hasControlledStorage() const;
800   bool isTOCless() const;
801   bool isFloatingPointPresent() const;
802   bool isFloatingPointOperationLogOrAbortEnabled() const;
803 
804   bool isInterruptHandler() const;
805   bool isFuncNamePresent() const;
806   bool isAllocaUsed() const;
807   uint8_t getOnConditionDirective() const;
808   bool isCRSaved() const;
809   bool isLRSaved() const;
810 
811   bool isBackChainStored() const;
812   bool isFixup() const;
813   uint8_t getNumOfFPRsSaved() const;
814 
815   bool hasVectorInfo() const;
816   bool hasExtensionTable() const;
817   uint8_t getNumOfGPRsSaved() const;
818 
819   uint8_t getNumberOfFixedParms() const;
820 
821   uint8_t getNumberOfFPParms() const;
822   bool hasParmsOnStack() const;
823 
824   const Optional<SmallString<32>> &getParmsType() const { return ParmsType; }
825   const Optional<uint32_t> &getTraceBackTableOffset() const {
826     return TraceBackTableOffset;
827   }
828   const Optional<uint32_t> &getHandlerMask() const { return HandlerMask; }
829   const Optional<uint32_t> &getNumOfCtlAnchors() { return NumOfCtlAnchors; }
830   const Optional<SmallVector<uint32_t, 8>> &getControlledStorageInfoDisp() {
831     return ControlledStorageInfoDisp;
832   }
833   const Optional<StringRef> &getFunctionName() const { return FunctionName; }
834   const Optional<uint8_t> &getAllocaRegister() const { return AllocaRegister; }
835   const Optional<TBVectorExt> &getVectorExt() const { return VecExt; }
836   const Optional<uint8_t> &getExtensionTable() const { return ExtensionTable; }
837 };
838 
839 bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes);
840 } // namespace object
841 } // namespace llvm
842 
843 #endif // LLVM_OBJECT_XCOFFOBJECTFILE_H
844