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