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
23namespace llvm {
24namespace object {
25
26struct 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
40struct 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
54template <typename T> struct XCOFFSectionHeader {
55 // Least significant 3 bits are reserved.
56 static constexpr unsigned SectionFlagsReservedMask = 0x7;
57
58 // The low order 16 bits of section flags denotes the section type.
59 static constexpr unsigned SectionFlagsTypeMask = 0xffffu;
60
61public:
62 StringRef getName() const;
63 uint16_t getSectionType() const;
64 bool isReservedSectionType() const;
65};
66
67// Explicit extern template declarations.
68struct XCOFFSectionHeader32;
69struct XCOFFSectionHeader64;
70extern template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
71extern template struct XCOFFSectionHeader<XCOFFSectionHeader64>;
72
73struct XCOFFSectionHeader32 : XCOFFSectionHeader<XCOFFSectionHeader32> {
74 char Name[XCOFF::NameSize];
75 support::ubig32_t PhysicalAddress;
76 support::ubig32_t VirtualAddress;
77 support::ubig32_t SectionSize;
78 support::ubig32_t FileOffsetToRawData;
79 support::ubig32_t FileOffsetToRelocationInfo;
80 support::ubig32_t FileOffsetToLineNumberInfo;
81 support::ubig16_t NumberOfRelocations;
82 support::ubig16_t NumberOfLineNumbers;
83 support::big32_t Flags;
84};
85
86struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> {
87 char Name[XCOFF::NameSize];
88 support::ubig64_t PhysicalAddress;
89 support::ubig64_t VirtualAddress;
90 support::ubig64_t SectionSize;
91 support::big64_t FileOffsetToRawData;
92 support::big64_t FileOffsetToRelocationInfo;
93 support::big64_t FileOffsetToLineNumberInfo;
94 support::ubig32_t NumberOfRelocations;
95 support::ubig32_t NumberOfLineNumbers;
96 support::big32_t Flags;
97 char Padding[4];
98};
99
100struct XCOFFSymbolEntry {
101 enum { NAME_IN_STR_TBL_MAGIC = 0x0 };
102 typedef struct {
103 support::big32_t Magic; // Zero indicates name in string table.
104 support::ubig32_t Offset;
105 } NameInStrTblType;
106
107 typedef struct {
108 uint8_t LanguageId;
109 uint8_t CpuTypeId;
110 } CFileLanguageIdAndTypeIdType;
111
112 union {
113 char SymbolName[XCOFF::NameSize];
114 NameInStrTblType NameInStrTbl;
115 };
116
117 support::ubig32_t Value; // Symbol value; storage class-dependent.
118 support::big16_t SectionNumber;
119
120 union {
121 support::ubig16_t SymbolType;
122 CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
123 };
124
125 XCOFF::StorageClass StorageClass;
126 uint8_t NumberOfAuxEntries;
127};
128
129struct XCOFFStringTable {
130 uint32_t Size;
131 const char *Data;
132};
133
134struct XCOFFCsectAuxEnt32 {
135 static constexpr uint8_t SymbolTypeMask = 0x07;
136 static constexpr uint8_t SymbolAlignmentMask = 0xF8;
137 static constexpr size_t SymbolAlignmentBitOffset = 3;
138
139 support::ubig32_t
140 SectionOrLength; // If the symbol type is XTY_SD or XTY_CM, the csect
141 // length.
142 // If the symbol type is XTY_LD, the symbol table
143 // index of the containing csect.
144 // If the symbol type is XTY_ER, 0.
145 support::ubig32_t ParameterHashIndex;
146 support::ubig16_t TypeChkSectNum;
147 uint8_t SymbolAlignmentAndType;
148 XCOFF::StorageMappingClass StorageMappingClass;
149 support::ubig32_t StabInfoIndex;
150 support::ubig16_t StabSectNum;
151
152 uint16_t getAlignmentLog2() const {
153 return (SymbolAlignmentAndType & SymbolAlignmentMask) >>
154 SymbolAlignmentBitOffset;
155 }
156
157 uint8_t getSymbolType() const {
158 return SymbolAlignmentAndType & SymbolTypeMask;
159 }
160
161 bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; }
162};
163
164struct XCOFFFileAuxEnt {
165 typedef struct {
166 support::big32_t Magic; // Zero indicates name in string table.
167 support::ubig32_t Offset;
168 char NamePad[XCOFF::FileNamePadSize];
169 } NameInStrTblType;
170 union {
171 char Name[XCOFF::NameSize + XCOFF::FileNamePadSize];
172 NameInStrTblType NameInStrTbl;
173 };
174 XCOFF::CFileStringType Type;
175 uint8_t ReservedZeros[2];
176 uint8_t AuxType; // 64-bit XCOFF file only.
177};
178
179struct XCOFFSectAuxEntForStat {
180 support::ubig32_t SectionLength;
181 support::ubig16_t NumberOfRelocEnt;
182 support::ubig16_t NumberOfLineNum;
183 uint8_t Pad[10];
184};
185
186struct XCOFFRelocation32 {
187 // Masks for packing/unpacking the r_rsize field of relocations.
188
189 // The msb is used to indicate if the bits being relocated are signed or
190 // unsigned.
191 static constexpr uint8_t XR_SIGN_INDICATOR_MASK = 0x80;
192
193 // The 2nd msb is used to indicate that the binder has replaced/modified the
194 // original instruction.
195 static constexpr uint8_t XR_FIXUP_INDICATOR_MASK = 0x40;
196
197 // The remaining bits specify the bit length of the relocatable reference
198 // minus one.
199 static constexpr uint8_t XR_BIASED_LENGTH_MASK = 0x3f;
200
201public:
202 support::ubig32_t VirtualAddress;
203 support::ubig32_t SymbolIndex;
204
205 // Packed field, see XR_* masks for details of packing.
206 uint8_t Info;
207
208 XCOFF::RelocationType Type;
209
210public:
211 bool isRelocationSigned() const;
212 bool isFixupIndicated() const;
213
214 // Returns the number of bits being relocated.
215 uint8_t getRelocatedLength() const;
216};
217
218class XCOFFObjectFile : public ObjectFile {
219private:
220 const void *FileHeader = nullptr;
221 const void *SectionHeaderTable = nullptr;
222
223 const XCOFFSymbolEntry *SymbolTblPtr = nullptr;
224 XCOFFStringTable StringTable = {0, nullptr};
225
226 const XCOFFFileHeader32 *fileHeader32() const;
227 const XCOFFFileHeader64 *fileHeader64() const;
228
229 const XCOFFSectionHeader32 *sectionHeaderTable32() const;
230 const XCOFFSectionHeader64 *sectionHeaderTable64() const;
231
232 size_t getFileHeaderSize() const;
233 size_t getSectionHeaderSize() const;
234
235 const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const;
236 const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const;
237 uintptr_t getSectionHeaderTableAddress() const;
238 uintptr_t getEndOfSymbolTableAddress() const;
239
240 // This returns a pointer to the start of the storage for the name field of
241 // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily
242 // null-terminated.
243 const char *getSectionNameInternal(DataRefImpl Sec) const;
244
245 // This function returns string table entry.
246 Expected<StringRef> getStringTableEntry(uint32_t Offset) const;
247
248 static bool isReservedSectionNumber(int16_t SectionNumber);
249
250 // Constructor and "create" factory function. The constructor is only a thin
251 // wrapper around the base constructor. The "create" function fills out the
252 // XCOFF-specific information and performs the error checking along the way.
253 XCOFFObjectFile(unsigned Type, MemoryBufferRef Object);
254 static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type,
255 MemoryBufferRef MBR);
256
257 // Helper for parsing the StringTable. Returns an 'Error' if parsing failed
258 // and an XCOFFStringTable if parsing succeeded.
259 static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj,
260 uint64_t Offset);
261
262 // Make a friend so it can call the private 'create' function.
263 friend Expected<std::unique_ptr<ObjectFile>>
264 ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
265
266 void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const;
267
268public:
269 static constexpr uint64_t InvalidRelocOffset =
270 std::numeric_limits<uint64_t>::max();
271
272 // Interface inherited from base classes.
273 void moveSymbolNext(DataRefImpl &Symb) const override;
274 Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
275 basic_symbol_iterator symbol_begin() const override;
276 basic_symbol_iterator symbol_end() const override;
277
278 Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
279 Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
280 uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
281 uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
282 Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
283 Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
284
285 void moveSectionNext(DataRefImpl &Sec) const override;
286 Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
287 uint64_t getSectionAddress(DataRefImpl Sec) const override;
288 uint64_t getSectionIndex(DataRefImpl Sec) const override;
289 uint64_t getSectionSize(DataRefImpl Sec) const override;
290 Expected<ArrayRef<uint8_t>>
291 getSectionContents(DataRefImpl Sec) const override;
292 uint64_t getSectionAlignment(DataRefImpl Sec) const override;
293 bool isSectionCompressed(DataRefImpl Sec) const override;
294 bool isSectionText(DataRefImpl Sec) const override;
295 bool isSectionData(DataRefImpl Sec) const override;
296 bool isSectionBSS(DataRefImpl Sec) const override;
297
298 bool isSectionVirtual(DataRefImpl Sec) const override;
299 relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
300 relocation_iterator section_rel_end(DataRefImpl Sec) const override;
301
302 void moveRelocationNext(DataRefImpl &Rel) const override;
303
304 /// \returns the relocation offset with the base address of the containing
305 /// section as zero, or InvalidRelocOffset on errors (such as a relocation
306 /// that does not refer to an address in any section).
307 uint64_t getRelocationOffset(DataRefImpl Rel) const override;
308 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
309 uint64_t getRelocationType(DataRefImpl Rel) const override;
310 void getRelocationTypeName(DataRefImpl Rel,
311 SmallVectorImpl<char> &Result) const override;
312
313 section_iterator section_begin() const override;
314 section_iterator section_end() const override;
315 uint8_t getBytesInAddress() const override;
316 StringRef getFileFormatName() const override;
317 Triple::ArchType getArch() const override;
318 SubtargetFeatures getFeatures() const override;
319 Expected<uint64_t> getStartAddress() const override;
320 StringRef mapDebugSectionName(StringRef Name) const override;
321 bool isRelocatableObject() const override;
322
323 // Below here is the non-inherited interface.
324 bool is64Bit() const;
325
326 const XCOFFSymbolEntry *getPointerToSymbolTable() const {
327 assert(!is64Bit() && "Symbol table handling not supported yet.");
328 return SymbolTblPtr;
329 }
330
331 Expected<StringRef>
332 getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const;
333
334 const XCOFFSymbolEntry *toSymbolEntry(DataRefImpl Ref) const;
335
336 // File header related interfaces.
337 uint16_t getMagic() const;
338 uint16_t getNumberOfSections() const;
339 int32_t getTimeStamp() const;
340
341 // Symbol table offset and entry count are handled differently between
342 // XCOFF32 and XCOFF64.
343 uint32_t getSymbolTableOffset32() const;
344 uint64_t getSymbolTableOffset64() const;
345
346 // Note that this value is signed and might return a negative value. Negative
347 // values are reserved for future use.
348 int32_t getRawNumberOfSymbolTableEntries32() const;
349
350 // The sanitized value appropriate to use as an index into the symbol table.
351 uint32_t getLogicalNumberOfSymbolTableEntries32() const;
352
353 uint32_t getNumberOfSymbolTableEntries64() const;
354 uint32_t getSymbolIndex(uintptr_t SymEntPtr) const;
355 Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const;
356
357 Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const;
358 uint16_t getOptionalHeaderSize() const;
359 uint16_t getFlags() const;
360
361 // Section header table related interfaces.
362 ArrayRef<XCOFFSectionHeader32> sections32() const;
363 ArrayRef<XCOFFSectionHeader64> sections64() const;
364
365 int32_t getSectionFlags(DataRefImpl Sec) const;
366 Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
367
368 void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const;
369
370 // Relocation-related interfaces.
371 Expected<uint32_t>
372 getLogicalNumberOfRelocationEntries(const XCOFFSectionHeader32 &Sec) const;
373
374 Expected<ArrayRef<XCOFFRelocation32>>
375 relocations(const XCOFFSectionHeader32 &) const;
376
377 static bool classof(const Binary *B) { return B->isXCOFF(); }
378}; // XCOFFObjectFile
379
380class XCOFFSymbolRef {
381 const DataRefImpl SymEntDataRef;
382 const XCOFFObjectFile *const OwningObjectPtr;
383
384public:
385 XCOFFSymbolRef(DataRefImpl SymEntDataRef,
386 const XCOFFObjectFile *OwningObjectPtr)
387 : SymEntDataRef(SymEntDataRef), OwningObjectPtr(OwningObjectPtr){};
388
389 XCOFF::StorageClass getStorageClass() const;
390 uint8_t getNumberOfAuxEntries() const;
391 const XCOFFCsectAuxEnt32 *getXCOFFCsectAuxEnt32() const;
392 uint16_t getType() const;
393 int16_t getSectionNumber() const;
394
395 bool hasCsectAuxEnt() const;
396 bool isFunction() const;
397};
398
399class TBVectorExt {
400 friend class XCOFFTracebackTable;
401
402 uint16_t Data;
403 uint32_t VecParmsInfo;
404
405 TBVectorExt(StringRef TBvectorStrRef);
406
407public:
408 uint8_t getNumberOfVRSaved() const;
409 bool isVRSavedOnStack() const;
410 bool hasVarArgs() const;
411 uint8_t getNumberOfVectorParms() const;
412 bool hasVMXInstruction() const;
413 SmallString<32> getVectorParmsInfoString() const;
414};
415
416/// This class provides methods to extract traceback table data from a buffer.
417/// The various accessors may reference the buffer provided via the constructor.
418
419class XCOFFTracebackTable {
420 const uint8_t *const TBPtr;
421 Optional<SmallString<32>> ParmsType;
422 Optional<uint32_t> TraceBackTableOffset;
423 Optional<uint32_t> HandlerMask;
424 Optional<uint32_t> NumOfCtlAnchors;
425 Optional<SmallVector<uint32_t, 8>> ControlledStorageInfoDisp;
426 Optional<StringRef> FunctionName;
427 Optional<uint8_t> AllocaRegister;
428 Optional<TBVectorExt> VecExt;
429 Optional<uint8_t> ExtensionTable;
430
431 XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err);
432public:
433 /// Parse an XCOFF Traceback Table from \a Ptr with \a Size bytes.
434 /// Returns an XCOFFTracebackTable upon successful parsing, otherwise an
435 /// Error is returned.
436 ///
437 /// \param[in] Ptr
438 /// A pointer that points just past the initial 4 bytes of zeros at the
439 /// beginning of an XCOFF Traceback Table.
440 ///
441 /// \param[in, out] Size
442 /// A pointer that points to the length of the XCOFF Traceback Table.
443 /// If the XCOFF Traceback Table is not parsed successfully or there are
444 /// extra bytes that are not recognized, \a Size will be updated to be the
445 /// size up to the end of the last successfully parsed field of the table.
446 static Expected<XCOFFTracebackTable> create(const uint8_t *Ptr,
447 uint64_t &Size);
448 uint8_t getVersion() const;
449 uint8_t getLanguageID() const;
450
451 bool isGlobalLinkage() const;
452 bool isOutOfLineEpilogOrPrologue() const;
453 bool hasTraceBackTableOffset() const;
454 bool isInternalProcedure() const;
455 bool hasControlledStorage() const;
456 bool isTOCless() const;
457 bool isFloatingPointPresent() const;
458 bool isFloatingPointOperationLogOrAbortEnabled() const;
459
460 bool isInterruptHandler() const;
461 bool isFuncNamePresent() const;
462 bool isAllocaUsed() const;
463 uint8_t getOnConditionDirective() const;
464 bool isCRSaved() const;
465 bool isLRSaved() const;
466
467 bool isBackChainStored() const;
468 bool isFixup() const;
469 uint8_t getNumOfFPRsSaved() const;
470
471 bool hasVectorInfo() const;
472 bool hasExtensionTable() const;
473 uint8_t getNumOfGPRsSaved() const;
474
475 uint8_t getNumberOfFixedParms() const;
476
477 uint8_t getNumberOfFPParms() const;
478 bool hasParmsOnStack() const;
479
480 const Optional<SmallString<32>> &getParmsType() const { return ParmsType; }
481 const Optional<uint32_t> &getTraceBackTableOffset() const {
482 return TraceBackTableOffset;
483 }
484 const Optional<uint32_t> &getHandlerMask() const { return HandlerMask; }
485 const Optional<uint32_t> &getNumOfCtlAnchors() { return NumOfCtlAnchors; }
486 const Optional<SmallVector<uint32_t, 8>> &getControlledStorageInfoDisp() {
487 return ControlledStorageInfoDisp;
488 }
489 const Optional<StringRef> &getFunctionName() const { return FunctionName; }
490 const Optional<uint8_t> &getAllocaRegister() const { return AllocaRegister; }
491 const Optional<TBVectorExt> &getVectorExt() const { return VecExt; }
492 const Optional<uint8_t> &getExtensionTable() const { return ExtensionTable; }
493};
494
495bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes);
496} // namespace object
497} // namespace llvm
498
499#endif // LLVM_OBJECT_XCOFFOBJECTFILE_H
500