blob: cdee7129a2abd7f19f5c837d5c50241a4f921cd5 [file] [log] [blame]
Andrew Walbran3d2c1972020-04-07 12:24:26 +01001//===- 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
34namespace llvm {
35namespace object {
36
37struct 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
51struct 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
65struct 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
80struct 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
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::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
125struct XCOFFStringTable {
126 uint32_t Size;
127 const char *Data;
128};
129
130class XCOFFObjectFile : public ObjectFile {
131private:
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
178public:
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
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