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