1//===- COFF.h - COFF object file implementation -----------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file declares the COFFObjectFile class. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_OBJECT_COFF_H 15#define LLVM_OBJECT_COFF_H 16 17#include "llvm/Object/ObjectFile.h" 18#include "llvm/Support/COFF.h" 19#include "llvm/Support/Endian.h" 20 21namespace llvm { 22 template <typename T> 23 class ArrayRef; 24 25namespace object { 26class ImportDirectoryEntryRef; 27typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator; 28 29/// The DOS compatible header at the front of all PE/COFF executables. 30struct dos_header { 31 support::ulittle16_t Magic; 32 support::ulittle16_t UsedBytesInTheLastPage; 33 support::ulittle16_t FileSizeInPages; 34 support::ulittle16_t NumberOfRelocationItems; 35 support::ulittle16_t HeaderSizeInParagraphs; 36 support::ulittle16_t MinimumExtraParagraphs; 37 support::ulittle16_t MaximumExtraParagraphs; 38 support::ulittle16_t InitialRelativeSS; 39 support::ulittle16_t InitialSP; 40 support::ulittle16_t Checksum; 41 support::ulittle16_t InitialIP; 42 support::ulittle16_t InitialRelativeCS; 43 support::ulittle16_t AddressOfRelocationTable; 44 support::ulittle16_t OverlayNumber; 45 support::ulittle16_t Reserved[4]; 46 support::ulittle16_t OEMid; 47 support::ulittle16_t OEMinfo; 48 support::ulittle16_t Reserved2[10]; 49 support::ulittle32_t AddressOfNewExeHeader; 50}; 51 52struct coff_file_header { 53 support::ulittle16_t Machine; 54 support::ulittle16_t NumberOfSections; 55 support::ulittle32_t TimeDateStamp; 56 support::ulittle32_t PointerToSymbolTable; 57 support::ulittle32_t NumberOfSymbols; 58 support::ulittle16_t SizeOfOptionalHeader; 59 support::ulittle16_t Characteristics; 60 61 bool isImportLibrary() const { return NumberOfSections == 0xffff; } 62}; 63 64/// The 32-bit PE header that follows the COFF header. 65struct pe32_header { 66 support::ulittle16_t Magic; 67 uint8_t MajorLinkerVersion; 68 uint8_t MinorLinkerVersion; 69 support::ulittle32_t SizeOfCode; 70 support::ulittle32_t SizeOfInitializedData; 71 support::ulittle32_t SizeOfUninitializedData; 72 support::ulittle32_t AddressOfEntryPoint; 73 support::ulittle32_t BaseOfCode; 74 support::ulittle32_t BaseOfData; 75 support::ulittle32_t ImageBase; 76 support::ulittle32_t SectionAlignment; 77 support::ulittle32_t FileAlignment; 78 support::ulittle16_t MajorOperatingSystemVersion; 79 support::ulittle16_t MinorOperatingSystemVersion; 80 support::ulittle16_t MajorImageVersion; 81 support::ulittle16_t MinorImageVersion; 82 support::ulittle16_t MajorSubsystemVersion; 83 support::ulittle16_t MinorSubsystemVersion; 84 support::ulittle32_t Win32VersionValue; 85 support::ulittle32_t SizeOfImage; 86 support::ulittle32_t SizeOfHeaders; 87 support::ulittle32_t CheckSum; 88 support::ulittle16_t Subsystem; 89 support::ulittle16_t DLLCharacteristics; 90 support::ulittle32_t SizeOfStackReserve; 91 support::ulittle32_t SizeOfStackCommit; 92 support::ulittle32_t SizeOfHeapReserve; 93 support::ulittle32_t SizeOfHeapCommit; 94 support::ulittle32_t LoaderFlags; 95 support::ulittle32_t NumberOfRvaAndSize; 96}; 97 98/// The 64-bit PE header that follows the COFF header. 99struct pe32plus_header { 100 support::ulittle16_t Magic; 101 uint8_t MajorLinkerVersion; 102 uint8_t MinorLinkerVersion; 103 support::ulittle32_t SizeOfCode; 104 support::ulittle32_t SizeOfInitializedData; 105 support::ulittle32_t SizeOfUninitializedData; 106 support::ulittle32_t AddressOfEntryPoint; 107 support::ulittle32_t BaseOfCode; 108 support::ulittle64_t ImageBase; 109 support::ulittle32_t SectionAlignment; 110 support::ulittle32_t FileAlignment; 111 support::ulittle16_t MajorOperatingSystemVersion; 112 support::ulittle16_t MinorOperatingSystemVersion; 113 support::ulittle16_t MajorImageVersion; 114 support::ulittle16_t MinorImageVersion; 115 support::ulittle16_t MajorSubsystemVersion; 116 support::ulittle16_t MinorSubsystemVersion; 117 support::ulittle32_t Win32VersionValue; 118 support::ulittle32_t SizeOfImage; 119 support::ulittle32_t SizeOfHeaders; 120 support::ulittle32_t CheckSum; 121 support::ulittle16_t Subsystem; 122 support::ulittle16_t DLLCharacteristics; 123 support::ulittle64_t SizeOfStackReserve; 124 support::ulittle64_t SizeOfStackCommit; 125 support::ulittle64_t SizeOfHeapReserve; 126 support::ulittle64_t SizeOfHeapCommit; 127 support::ulittle32_t LoaderFlags; 128 support::ulittle32_t NumberOfRvaAndSize; 129}; 130 131struct data_directory { 132 support::ulittle32_t RelativeVirtualAddress; 133 support::ulittle32_t Size; 134}; 135 136struct import_directory_table_entry { 137 support::ulittle32_t ImportLookupTableRVA; 138 support::ulittle32_t TimeDateStamp; 139 support::ulittle32_t ForwarderChain; 140 support::ulittle32_t NameRVA; 141 support::ulittle32_t ImportAddressTableRVA; 142}; 143 144struct import_lookup_table_entry32 { 145 support::ulittle32_t data; 146 147 bool isOrdinal() const { return data & 0x80000000; } 148 149 uint16_t getOrdinal() const { 150 assert(isOrdinal() && "ILT entry is not an ordinal!"); 151 return data & 0xFFFF; 152 } 153 154 uint32_t getHintNameRVA() const { 155 assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); 156 return data; 157 } 158}; 159 160struct coff_symbol { 161 struct StringTableOffset { 162 support::ulittle32_t Zeroes; 163 support::ulittle32_t Offset; 164 }; 165 166 union { 167 char ShortName[8]; 168 StringTableOffset Offset; 169 } Name; 170 171 support::ulittle32_t Value; 172 support::little16_t SectionNumber; 173 174 support::ulittle16_t Type; 175 176 support::ulittle8_t StorageClass; 177 support::ulittle8_t NumberOfAuxSymbols; 178 179 uint8_t getBaseType() const { 180 return Type & 0x0F; 181 } 182 183 uint8_t getComplexType() const { 184 return (Type & 0xF0) >> 4; 185 } 186}; 187 188struct coff_section { 189 char Name[8]; 190 support::ulittle32_t VirtualSize; 191 support::ulittle32_t VirtualAddress; 192 support::ulittle32_t SizeOfRawData; 193 support::ulittle32_t PointerToRawData; 194 support::ulittle32_t PointerToRelocations; 195 support::ulittle32_t PointerToLinenumbers; 196 support::ulittle16_t NumberOfRelocations; 197 support::ulittle16_t NumberOfLinenumbers; 198 support::ulittle32_t Characteristics; 199}; 200 201struct coff_relocation { 202 support::ulittle32_t VirtualAddress; 203 support::ulittle32_t SymbolTableIndex; 204 support::ulittle16_t Type; 205}; 206 207struct coff_aux_weak_external { 208 support::ulittle32_t TagIndex; 209 support::ulittle32_t Characteristics; 210 char Unused[10]; 211}; 212 213struct coff_aux_section_definition { 214 support::ulittle32_t Length; 215 support::ulittle16_t NumberOfRelocations; 216 support::ulittle16_t NumberOfLinenumbers; 217 support::ulittle32_t CheckSum; 218 support::ulittle16_t Number; 219 support::ulittle8_t Selection; 220 char Unused[3]; 221}; 222 223class COFFObjectFile : public ObjectFile { 224private: 225 friend class ImportDirectoryEntryRef; 226 const coff_file_header *COFFHeader; 227 const pe32_header *PE32Header; 228 const data_directory *DataDirectory; 229 const coff_section *SectionTable; 230 const coff_symbol *SymbolTable; 231 const char *StringTable; 232 uint32_t StringTableSize; 233 const import_directory_table_entry *ImportDirectory; 234 uint32_t NumberOfImportDirectory; 235 236 error_code getString(uint32_t offset, StringRef &Res) const; 237 238 const coff_symbol *toSymb(DataRefImpl Symb) const; 239 const coff_section *toSec(DataRefImpl Sec) const; 240 const coff_relocation *toRel(DataRefImpl Rel) const; 241 242 error_code initSymbolTablePtr(); 243 error_code initImportTablePtr(); 244 245protected: 246 virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; 247 virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; 248 virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; 249 virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; 250 virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; 251 virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; 252 virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; 253 virtual error_code getSymbolSection(DataRefImpl Symb, 254 section_iterator &Res) const; 255 virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; 256 257 virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; 258 virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; 259 virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; 260 virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; 261 virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; 262 virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; 263 virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; 264 virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; 265 virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; 266 virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; 267 virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; 268 virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; 269 virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, 270 bool &Res) const; 271 virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, 272 bool &Result) const; 273 virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; 274 virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; 275 276 virtual error_code getRelocationNext(DataRefImpl Rel, 277 RelocationRef &Res) const; 278 virtual error_code getRelocationAddress(DataRefImpl Rel, 279 uint64_t &Res) const; 280 virtual error_code getRelocationOffset(DataRefImpl Rel, 281 uint64_t &Res) const; 282 virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; 283 virtual error_code getRelocationType(DataRefImpl Rel, 284 uint64_t &Res) const; 285 virtual error_code getRelocationTypeName(DataRefImpl Rel, 286 SmallVectorImpl<char> &Result) const; 287 virtual error_code getRelocationValueString(DataRefImpl Rel, 288 SmallVectorImpl<char> &Result) const; 289 290 virtual error_code getLibraryNext(DataRefImpl LibData, 291 LibraryRef &Result) const; 292 virtual error_code getLibraryPath(DataRefImpl LibData, 293 StringRef &Result) const; 294 295public: 296 COFFObjectFile(MemoryBuffer *Object, error_code &ec); 297 virtual symbol_iterator begin_symbols() const; 298 virtual symbol_iterator end_symbols() const; 299 virtual symbol_iterator begin_dynamic_symbols() const; 300 virtual symbol_iterator end_dynamic_symbols() const; 301 virtual library_iterator begin_libraries_needed() const; 302 virtual library_iterator end_libraries_needed() const; 303 virtual section_iterator begin_sections() const; 304 virtual section_iterator end_sections() const; 305 306 const coff_section *getCOFFSection(section_iterator &It) const; 307 const coff_symbol *getCOFFSymbol(symbol_iterator &It) const; 308 const coff_relocation *getCOFFRelocation(relocation_iterator &It) const; 309 310 virtual uint8_t getBytesInAddress() const; 311 virtual StringRef getFileFormatName() const; 312 virtual unsigned getArch() const; 313 virtual StringRef getLoadName() const; 314 315 import_directory_iterator import_directory_begin() const; 316 import_directory_iterator import_directory_end() const; 317 318 error_code getHeader(const coff_file_header *&Res) const; 319 error_code getCOFFHeader(const coff_file_header *&Res) const; 320 error_code getPE32Header(const pe32_header *&Res) const; 321 error_code getDataDirectory(uint32_t index, const data_directory *&Res) const; 322 error_code getSection(int32_t index, const coff_section *&Res) const; 323 error_code getSymbol(uint32_t index, const coff_symbol *&Res) const; 324 template <typename T> 325 error_code getAuxSymbol(uint32_t index, const T *&Res) const { 326 const coff_symbol *s; 327 error_code ec = getSymbol(index, s); 328 Res = reinterpret_cast<const T*>(s); 329 return ec; 330 } 331 error_code getSymbolName(const coff_symbol *symbol, StringRef &Res) const; 332 ArrayRef<uint8_t> getSymbolAuxData(const coff_symbol *symbol) const; 333 334 error_code getSectionName(const coff_section *Sec, StringRef &Res) const; 335 error_code getSectionContents(const coff_section *Sec, 336 ArrayRef<uint8_t> &Res) const; 337 338 error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; 339 error_code getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const; 340 341 static inline bool classof(const Binary *v) { 342 return v->isCOFF(); 343 } 344}; 345 346// The iterator for the import directory table. 347class ImportDirectoryEntryRef { 348public: 349 ImportDirectoryEntryRef() : OwningObject(0) {} 350 ImportDirectoryEntryRef(DataRefImpl ImportDirectory, 351 const COFFObjectFile *Owner) 352 : ImportDirectoryPimpl(ImportDirectory), OwningObject(Owner) {} 353 354 bool operator==(const ImportDirectoryEntryRef &Other) const; 355 error_code getNext(ImportDirectoryEntryRef &Result) const; 356 error_code getName(StringRef &Result) const; 357 358 error_code 359 getImportTableEntry(const import_directory_table_entry *&Result) const; 360 361 error_code 362 getImportLookupEntry(const import_lookup_table_entry32 *&Result) const; 363 364private: 365 DataRefImpl ImportDirectoryPimpl; 366 const COFFObjectFile *OwningObject; 367}; 368} // end namespace object 369} // end namespace llvm 370 371#endif 372