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/StringRef.h"
17 #include "llvm/ADT/iterator_range.h"
18 #include "llvm/BinaryFormat/Magic.h"
19 #include "llvm/BinaryFormat/XCOFF.h"
20 #include "llvm/MC/SubtargetFeature.h"
21 #include "llvm/Object/Binary.h"
22 #include "llvm/Object/Error.h"
23 #include "llvm/Object/ObjectFile.h"
24 #include "llvm/Object/SymbolicFile.h"
25 #include "llvm/Support/Casting.h"
26 #include "llvm/Support/Error.h"
27 #include "llvm/Support/FileSystem.h"
28 #include "llvm/Support/MemoryBuffer.h"
29 #include <cassert>
30 #include <cstdint>
31 #include <memory>
32 #include <system_error>
33 
34 namespace llvm {
35 namespace object {
36 
37 struct XCOFFFileHeader32 {
38   support::ubig16_t Magic;
39   support::ubig16_t NumberOfSections;
40 
41   // Unix time value, value of 0 indicates no timestamp.
42   // Negative values are reserved.
43   support::big32_t TimeStamp;
44 
45   support::ubig32_t SymbolTableOffset; // File offset to symbol table.
46   support::big32_t NumberOfSymTableEntries;
47   support::ubig16_t AuxHeaderSize;
48   support::ubig16_t Flags;
49 };
50 
51 struct XCOFFFileHeader64 {
52   support::ubig16_t Magic;
53   support::ubig16_t NumberOfSections;
54 
55   // Unix time value, value of 0 indicates no timestamp.
56   // Negative values are reserved.
57   support::big32_t TimeStamp;
58 
59   support::ubig64_t SymbolTableOffset; // File offset to symbol table.
60   support::ubig16_t AuxHeaderSize;
61   support::ubig16_t Flags;
62   support::ubig32_t NumberOfSymTableEntries;
63 };
64 
65 struct XCOFFSectionHeader32 {
66   char Name[XCOFF::SectionNameSize];
67   support::ubig32_t PhysicalAddress;
68   support::ubig32_t VirtualAddress;
69   support::ubig32_t SectionSize;
70   support::ubig32_t FileOffsetToRawData;
71   support::ubig32_t FileOffsetToRelocationInfo;
72   support::ubig32_t FileOffsetToLineNumberInfo;
73   support::ubig16_t NumberOfRelocations;
74   support::ubig16_t NumberOfLineNumbers;
75   support::big32_t Flags;
76 
77   StringRef getName() const;
78 };
79 
80 struct XCOFFSectionHeader64 {
81   char Name[XCOFF::SectionNameSize];
82   support::ubig64_t PhysicalAddress;
83   support::ubig64_t VirtualAddress;
84   support::ubig64_t SectionSize;
85   support::big64_t FileOffsetToRawData;
86   support::big64_t FileOffsetToRelocationInfo;
87   support::big64_t FileOffsetToLineNumberInfo;
88   support::ubig32_t NumberOfRelocations;
89   support::ubig32_t NumberOfLineNumbers;
90   support::big32_t Flags;
91   char Padding[4];
92 
93   StringRef getName() const;
94 };
95 
96 struct 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::SymbolNameSize];
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 
125 struct XCOFFStringTable {
126   uint32_t Size;
127   const char *Data;
128 };
129 
130 class XCOFFObjectFile : public ObjectFile {
131 private:
132   const void *FileHeader = nullptr;
133   const void *SectionHeaderTable = nullptr;
134 
135   const XCOFFSymbolEntry *SymbolTblPtr = nullptr;
136   XCOFFStringTable StringTable = {0, nullptr};
137 
138   const XCOFFFileHeader32 *fileHeader32() const;
139   const XCOFFFileHeader64 *fileHeader64() const;
140 
141   const XCOFFSectionHeader32 *sectionHeaderTable32() const;
142   const XCOFFSectionHeader64 *sectionHeaderTable64() const;
143 
144   size_t getFileHeaderSize() const;
145   size_t getSectionHeaderSize() const;
146 
147   const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const;
148   const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const;
149   void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const;
150   uintptr_t getSectionHeaderTableAddress() const;
151 
152   // This returns a pointer to the start of the storage for the name field of
153   // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily
154   // null-terminated.
155   const char *getSectionNameInternal(DataRefImpl Sec) const;
156 
157   int32_t getSectionFlags(DataRefImpl Sec) const;
158 
159   static bool isReservedSectionNumber(int16_t SectionNumber);
160   Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
161 
162   // Constructor and "create" factory function. The constructor is only a thin
163   // wrapper around the base constructor. The "create" function fills out the
164   // XCOFF-specific information and performs the error checking along the way.
165   XCOFFObjectFile(unsigned Type, MemoryBufferRef Object);
166   static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type,
167                                                            MemoryBufferRef MBR);
168 
169   // Helper for parsing the StringTable. Returns an 'Error' if parsing failed
170   // and an XCOFFStringTable if parsing succeeded.
171   static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj,
172                                                      uint64_t Offset);
173 
174   // Make a friend so it can call the private 'create' function.
175   friend Expected<std::unique_ptr<ObjectFile>>
176   ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
177 
178 public:
179   // Interface inherited from base classes.
180   void moveSymbolNext(DataRefImpl &Symb) const override;
181   uint32_t getSymbolFlags(DataRefImpl Symb) const override;
182   basic_symbol_iterator symbol_begin() const override;
183   basic_symbol_iterator symbol_end() const override;
184 
185   Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
186   Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
187   uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
188   uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
189   Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
190   Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
191 
192   void moveSectionNext(DataRefImpl &Sec) const override;
193   Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
194   uint64_t getSectionAddress(DataRefImpl Sec) const override;
195   uint64_t getSectionIndex(DataRefImpl Sec) const override;
196   uint64_t getSectionSize(DataRefImpl Sec) const override;
197   Expected<ArrayRef<uint8_t>>
198   getSectionContents(DataRefImpl Sec) const override;
199   uint64_t getSectionAlignment(DataRefImpl Sec) const override;
200   bool isSectionCompressed(DataRefImpl Sec) const override;
201   bool isSectionText(DataRefImpl Sec) const override;
202   bool isSectionData(DataRefImpl Sec) const override;
203   bool isSectionBSS(DataRefImpl Sec) const override;
204 
205   bool isSectionVirtual(DataRefImpl Sec) const override;
206   relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
207   relocation_iterator section_rel_end(DataRefImpl Sec) const override;
208 
209   void moveRelocationNext(DataRefImpl &Rel) const override;
210   uint64_t getRelocationOffset(DataRefImpl Rel) const override;
211   symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
212   uint64_t getRelocationType(DataRefImpl Rel) const override;
213   void getRelocationTypeName(DataRefImpl Rel,
214                              SmallVectorImpl<char> &Result) const override;
215 
216   section_iterator section_begin() const override;
217   section_iterator section_end() const override;
218   uint8_t getBytesInAddress() const override;
219   StringRef getFileFormatName() const override;
220   Triple::ArchType getArch() const override;
221   SubtargetFeatures getFeatures() const override;
222   Expected<uint64_t> getStartAddress() const override;
223   bool isRelocatableObject() const override;
224 
225   // Below here is the non-inherited interface.
226   bool is64Bit() const;
227 
getPointerToSymbolTable()228   const XCOFFSymbolEntry *getPointerToSymbolTable() const {
229     assert(!is64Bit() && "Symbol table handling not supported yet.");
230     return SymbolTblPtr;
231   }
232 
233   Expected<StringRef>
234   getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const;
235 
236   const XCOFFSymbolEntry *toSymbolEntry(DataRefImpl Ref) const;
237 
238   // File header related interfaces.
239   uint16_t getMagic() const;
240   uint16_t getNumberOfSections() const;
241   int32_t getTimeStamp() const;
242 
243   // Symbol table offset and entry count are handled differently between
244   // XCOFF32 and XCOFF64.
245   uint32_t getSymbolTableOffset32() const;
246   uint64_t getSymbolTableOffset64() const;
247 
248   // Note that this value is signed and might return a negative value. Negative
249   // values are reserved for future use.
250   int32_t getRawNumberOfSymbolTableEntries32() const;
251 
252   // The sanitized value appropriate to use as an index into the symbol table.
253   uint32_t getLogicalNumberOfSymbolTableEntries32() const;
254 
255   uint32_t getNumberOfSymbolTableEntries64() const;
256 
257   uint16_t getOptionalHeaderSize() const;
258   uint16_t getFlags() const;
259 
260   // Section header table related interfaces.
261   ArrayRef<XCOFFSectionHeader32> sections32() const;
262   ArrayRef<XCOFFSectionHeader64> sections64() const;
263 }; // XCOFFObjectFile
264 
265 } // namespace object
266 } // namespace llvm
267 
268 #endif // LLVM_OBJECT_XCOFFOBJECTFILE_H
269