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/BinaryFormat/XCOFF.h"
17 #include "llvm/Object/ObjectFile.h"
18 #include "llvm/Support/Endian.h"
19 #include <limits>
20 
21 namespace llvm {
22 namespace object {
23 
24 struct XCOFFFileHeader32 {
25   support::ubig16_t Magic;
26   support::ubig16_t NumberOfSections;
27 
28   // Unix time value, value of 0 indicates no timestamp.
29   // Negative values are reserved.
30   support::big32_t TimeStamp;
31 
32   support::ubig32_t SymbolTableOffset; // File offset to symbol table.
33   support::big32_t NumberOfSymTableEntries;
34   support::ubig16_t AuxHeaderSize;
35   support::ubig16_t Flags;
36 };
37 
38 struct XCOFFFileHeader64 {
39   support::ubig16_t Magic;
40   support::ubig16_t NumberOfSections;
41 
42   // Unix time value, value of 0 indicates no timestamp.
43   // Negative values are reserved.
44   support::big32_t TimeStamp;
45 
46   support::ubig64_t SymbolTableOffset; // File offset to symbol table.
47   support::ubig16_t AuxHeaderSize;
48   support::ubig16_t Flags;
49   support::ubig32_t NumberOfSymTableEntries;
50 };
51 
52 template <typename T> struct XCOFFSectionHeader {
53   // Least significant 3 bits are reserved.
54   static constexpr unsigned SectionFlagsReservedMask = 0x7;
55 
56   // The low order 16 bits of section flags denotes the section type.
57   static constexpr unsigned SectionFlagsTypeMask = 0xffffu;
58 
59 public:
60   StringRef getName() const;
61   uint16_t getSectionType() const;
62   bool isReservedSectionType() const;
63 };
64 
65 // Explicit extern template declarations.
66 struct XCOFFSectionHeader32;
67 struct XCOFFSectionHeader64;
68 extern template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
69 extern template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
70 
71 struct XCOFFSectionHeader32 : XCOFFSectionHeader<XCOFFSectionHeader32> {
72   char Name[XCOFF::NameSize];
73   support::ubig32_t PhysicalAddress;
74   support::ubig32_t VirtualAddress;
75   support::ubig32_t SectionSize;
76   support::ubig32_t FileOffsetToRawData;
77   support::ubig32_t FileOffsetToRelocationInfo;
78   support::ubig32_t FileOffsetToLineNumberInfo;
79   support::ubig16_t NumberOfRelocations;
80   support::ubig16_t NumberOfLineNumbers;
81   support::big32_t Flags;
82 };
83 
84 struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> {
85   char Name[XCOFF::NameSize];
86   support::ubig64_t PhysicalAddress;
87   support::ubig64_t VirtualAddress;
88   support::ubig64_t SectionSize;
89   support::big64_t FileOffsetToRawData;
90   support::big64_t FileOffsetToRelocationInfo;
91   support::big64_t FileOffsetToLineNumberInfo;
92   support::ubig32_t NumberOfRelocations;
93   support::ubig32_t NumberOfLineNumbers;
94   support::big32_t Flags;
95   char Padding[4];
96 };
97 
98 struct XCOFFSymbolEntry {
99   enum { NAME_IN_STR_TBL_MAGIC = 0x0 };
100   typedef struct {
101     support::big32_t Magic; // Zero indicates name in string table.
102     support::ubig32_t Offset;
103   } NameInStrTblType;
104 
105   typedef struct {
106     uint8_t LanguageId;
107     uint8_t CpuTypeId;
108   } CFileLanguageIdAndTypeIdType;
109 
110   union {
111     char SymbolName[XCOFF::NameSize];
112     NameInStrTblType NameInStrTbl;
113   };
114 
115   support::ubig32_t Value; // Symbol value; storage class-dependent.
116   support::big16_t SectionNumber;
117 
118   union {
119     support::ubig16_t SymbolType;
120     CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
121   };
122 
123   XCOFF::StorageClass StorageClass;
124   uint8_t NumberOfAuxEntries;
125 };
126 
127 struct XCOFFStringTable {
128   uint32_t Size;
129   const char *Data;
130 };
131 
132 struct XCOFFCsectAuxEnt32 {
133   static constexpr uint8_t SymbolTypeMask = 0x07;
134   static constexpr uint8_t SymbolAlignmentMask = 0xF8;
135   static constexpr size_t SymbolAlignmentBitOffset = 3;
136 
137   support::ubig32_t
138       SectionOrLength; // If the symbol type is XTY_SD or XTY_CM, the csect
139                        // length.
140                        // If the symbol type is XTY_LD, the symbol table
141                        // index of the containing csect.
142                        // If the symbol type is XTY_ER, 0.
143   support::ubig32_t ParameterHashIndex;
144   support::ubig16_t TypeChkSectNum;
145   uint8_t SymbolAlignmentAndType;
146   XCOFF::StorageMappingClass StorageMappingClass;
147   support::ubig32_t StabInfoIndex;
148   support::ubig16_t StabSectNum;
149 
150   uint16_t getAlignmentLog2() const {
151     return (SymbolAlignmentAndType & SymbolAlignmentMask) >>
152            SymbolAlignmentBitOffset;
153   }
154 
155   uint8_t getSymbolType() const {
156     return SymbolAlignmentAndType & SymbolTypeMask;
157   }
158 
159   bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; }
160 };
161 
162 struct XCOFFFileAuxEnt {
163   typedef struct {
164     support::big32_t Magic; // Zero indicates name in string table.
165     support::ubig32_t Offset;
166     char NamePad[XCOFF::FileNamePadSize];
167   } NameInStrTblType;
168   union {
169     char Name[XCOFF::NameSize + XCOFF::FileNamePadSize];
170     NameInStrTblType NameInStrTbl;
171   };
172   XCOFF::CFileStringType Type;
173   uint8_t ReservedZeros[2];
174   uint8_t AuxType; // 64-bit XCOFF file only.
175 };
176 
177 struct XCOFFSectAuxEntForStat {
178   support::ubig32_t SectionLength;
179   support::ubig16_t NumberOfRelocEnt;
180   support::ubig16_t NumberOfLineNum;
181   uint8_t Pad[10];
182 };
183 
184 struct XCOFFRelocation32 {
185   // Masks for packing/unpacking the r_rsize field of relocations.
186 
187   // The msb is used to indicate if the bits being relocated are signed or
188   // unsigned.
189   static constexpr uint8_t XR_SIGN_INDICATOR_MASK = 0x80;
190 
191   // The 2nd msb is used to indicate that the binder has replaced/modified the
192   // original instruction.
193   static constexpr uint8_t XR_FIXUP_INDICATOR_MASK = 0x40;
194 
195   // The remaining bits specify the bit length of the relocatable reference
196   // minus one.
197   static constexpr uint8_t XR_BIASED_LENGTH_MASK = 0x3f;
198 
199 public:
200   support::ubig32_t VirtualAddress;
201   support::ubig32_t SymbolIndex;
202 
203   // Packed field, see XR_* masks for details of packing.
204   uint8_t Info;
205 
206   XCOFF::RelocationType Type;
207 
208 public:
209   bool isRelocationSigned() const;
210   bool isFixupIndicated() const;
211 
212   // Returns the number of bits being relocated.
213   uint8_t getRelocatedLength() const;
214 };
215 
216 class XCOFFObjectFile : public ObjectFile {
217 private:
218   const void *FileHeader = nullptr;
219   const void *SectionHeaderTable = nullptr;
220 
221   const XCOFFSymbolEntry *SymbolTblPtr = nullptr;
222   XCOFFStringTable StringTable = {0, nullptr};
223 
224   const XCOFFFileHeader32 *fileHeader32() const;
225   const XCOFFFileHeader64 *fileHeader64() const;
226 
227   const XCOFFSectionHeader32 *sectionHeaderTable32() const;
228   const XCOFFSectionHeader64 *sectionHeaderTable64() const;
229 
230   size_t getFileHeaderSize() const;
231   size_t getSectionHeaderSize() const;
232 
233   const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const;
234   const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const;
235   uintptr_t getSectionHeaderTableAddress() const;
236   uintptr_t getEndOfSymbolTableAddress() const;
237 
238   // This returns a pointer to the start of the storage for the name field of
239   // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily
240   // null-terminated.
241   const char *getSectionNameInternal(DataRefImpl Sec) const;
242 
243   // This function returns string table entry.
244   Expected<StringRef> getStringTableEntry(uint32_t Offset) const;
245 
246   static bool isReservedSectionNumber(int16_t SectionNumber);
247 
248   // Constructor and "create" factory function. The constructor is only a thin
249   // wrapper around the base constructor. The "create" function fills out the
250   // XCOFF-specific information and performs the error checking along the way.
251   XCOFFObjectFile(unsigned Type, MemoryBufferRef Object);
252   static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type,
253                                                            MemoryBufferRef MBR);
254 
255   // Helper for parsing the StringTable. Returns an 'Error' if parsing failed
256   // and an XCOFFStringTable if parsing succeeded.
257   static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj,
258                                                      uint64_t Offset);
259 
260   // Make a friend so it can call the private 'create' function.
261   friend Expected<std::unique_ptr<ObjectFile>>
262   ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
263 
264   void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const;
265 
266 public:
267   static constexpr uint64_t InvalidRelocOffset =
268       std::numeric_limits<uint64_t>::max();
269 
270   // Interface inherited from base classes.
271   void moveSymbolNext(DataRefImpl &Symb) const override;
272   Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
273   basic_symbol_iterator symbol_begin() const override;
274   basic_symbol_iterator symbol_end() const override;
275 
276   Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
277   Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
278   uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
279   uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
280   Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
281   Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
282 
283   void moveSectionNext(DataRefImpl &Sec) const override;
284   Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
285   uint64_t getSectionAddress(DataRefImpl Sec) const override;
286   uint64_t getSectionIndex(DataRefImpl Sec) const override;
287   uint64_t getSectionSize(DataRefImpl Sec) const override;
288   Expected<ArrayRef<uint8_t>>
289   getSectionContents(DataRefImpl Sec) const override;
290   uint64_t getSectionAlignment(DataRefImpl Sec) const override;
291   bool isSectionCompressed(DataRefImpl Sec) const override;
292   bool isSectionText(DataRefImpl Sec) const override;
293   bool isSectionData(DataRefImpl Sec) const override;
294   bool isSectionBSS(DataRefImpl Sec) const override;
295 
296   bool isSectionVirtual(DataRefImpl Sec) const override;
297   relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
298   relocation_iterator section_rel_end(DataRefImpl Sec) const override;
299 
300   void moveRelocationNext(DataRefImpl &Rel) const override;
301 
302   /// \returns the relocation offset with the base address of the containing
303   /// section as zero, or InvalidRelocOffset on errors (such as a relocation
304   /// that does not refer to an address in any section).
305   uint64_t getRelocationOffset(DataRefImpl Rel) const override;
306   symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
307   uint64_t getRelocationType(DataRefImpl Rel) const override;
308   void getRelocationTypeName(DataRefImpl Rel,
309                              SmallVectorImpl<char> &Result) const override;
310 
311   section_iterator section_begin() const override;
312   section_iterator section_end() const override;
313   uint8_t getBytesInAddress() const override;
314   StringRef getFileFormatName() const override;
315   Triple::ArchType getArch() const override;
316   SubtargetFeatures getFeatures() const override;
317   Expected<uint64_t> getStartAddress() const override;
318   bool isRelocatableObject() const override;
319 
320   // Below here is the non-inherited interface.
321   bool is64Bit() const;
322 
323   const XCOFFSymbolEntry *getPointerToSymbolTable() const {
324     assert(!is64Bit() && "Symbol table handling not supported yet.");
325     return SymbolTblPtr;
326   }
327 
328   Expected<StringRef>
329   getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const;
330 
331   const XCOFFSymbolEntry *toSymbolEntry(DataRefImpl Ref) const;
332 
333   // File header related interfaces.
334   uint16_t getMagic() const;
335   uint16_t getNumberOfSections() const;
336   int32_t getTimeStamp() const;
337 
338   // Symbol table offset and entry count are handled differently between
339   // XCOFF32 and XCOFF64.
340   uint32_t getSymbolTableOffset32() const;
341   uint64_t getSymbolTableOffset64() const;
342 
343   // Note that this value is signed and might return a negative value. Negative
344   // values are reserved for future use.
345   int32_t getRawNumberOfSymbolTableEntries32() const;
346 
347   // The sanitized value appropriate to use as an index into the symbol table.
348   uint32_t getLogicalNumberOfSymbolTableEntries32() const;
349 
350   uint32_t getNumberOfSymbolTableEntries64() const;
351   uint32_t getSymbolIndex(uintptr_t SymEntPtr) const;
352   Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const;
353 
354   Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const;
355   uint16_t getOptionalHeaderSize() const;
356   uint16_t getFlags() const;
357 
358   // Section header table related interfaces.
359   ArrayRef<XCOFFSectionHeader32> sections32() const;
360   ArrayRef<XCOFFSectionHeader64> sections64() const;
361 
362   int32_t getSectionFlags(DataRefImpl Sec) const;
363   Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
364 
365   void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const;
366 
367   // Relocation-related interfaces.
368   Expected<uint32_t>
369   getLogicalNumberOfRelocationEntries(const XCOFFSectionHeader32 &Sec) const;
370 
371   Expected<ArrayRef<XCOFFRelocation32>>
372   relocations(const XCOFFSectionHeader32 &) const;
373 }; // XCOFFObjectFile
374 
375 class XCOFFSymbolRef {
376   const DataRefImpl SymEntDataRef;
377   const XCOFFObjectFile *const OwningObjectPtr;
378 
379 public:
380   XCOFFSymbolRef(DataRefImpl SymEntDataRef,
381                  const XCOFFObjectFile *OwningObjectPtr)
382       : SymEntDataRef(SymEntDataRef), OwningObjectPtr(OwningObjectPtr){};
383 
384   XCOFF::StorageClass getStorageClass() const;
385   uint8_t getNumberOfAuxEntries() const;
386   const XCOFFCsectAuxEnt32 *getXCOFFCsectAuxEnt32() const;
387   uint16_t getType() const;
388   int16_t getSectionNumber() const;
389 
390   bool hasCsectAuxEnt() const;
391   bool isFunction() const;
392 };
393 
394 } // namespace object
395 } // namespace llvm
396 
397 #endif // LLVM_OBJECT_XCOFFOBJECTFILE_H
398