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