1 //===- COFFObjectFile.cpp - 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 #include "llvm/ADT/StringSwitch.h" 15 #include "llvm/ADT/Triple.h" 16 #include "llvm/Object/ObjectFile.h" 17 #include "llvm/Support/COFF.h" 18 #include "llvm/Support/Endian.h" 19 20 using namespace llvm; 21 using namespace object; 22 23 namespace { 24 using support::ulittle8_t; 25 using support::ulittle16_t; 26 using support::ulittle32_t; 27 using support::little16_t; 28 } 29 30 namespace { 31 struct coff_file_header { 32 ulittle16_t Machine; 33 ulittle16_t NumberOfSections; 34 ulittle32_t TimeDateStamp; 35 ulittle32_t PointerToSymbolTable; 36 ulittle32_t NumberOfSymbols; 37 ulittle16_t SizeOfOptionalHeader; 38 ulittle16_t Characteristics; 39 }; 40 } 41 42 extern char coff_file_header_layout_static_assert 43 [sizeof(coff_file_header) == 20 ? 1 : -1]; 44 45 namespace { 46 struct coff_symbol { 47 struct StringTableOffset { 48 ulittle32_t Zeroes; 49 ulittle32_t Offset; 50 }; 51 52 union { 53 char ShortName[8]; 54 StringTableOffset Offset; 55 } Name; 56 57 ulittle32_t Value; 58 little16_t SectionNumber; 59 60 struct { 61 ulittle8_t BaseType; 62 ulittle8_t ComplexType; 63 } Type; 64 65 ulittle8_t StorageClass; 66 ulittle8_t NumberOfAuxSymbols; 67 }; 68 } 69 70 extern char coff_coff_symbol_layout_static_assert 71 [sizeof(coff_symbol) == 18 ? 1 : -1]; 72 73 namespace { 74 struct coff_section { 75 char Name[8]; 76 ulittle32_t VirtualSize; 77 ulittle32_t VirtualAddress; 78 ulittle32_t SizeOfRawData; 79 ulittle32_t PointerToRawData; 80 ulittle32_t PointerToRelocations; 81 ulittle32_t PointerToLinenumbers; 82 ulittle16_t NumberOfRelocations; 83 ulittle16_t NumberOfLinenumbers; 84 ulittle32_t Characteristics; 85 }; 86 } 87 88 extern char coff_coff_section_layout_static_assert 89 [sizeof(coff_section) == 40 ? 1 : -1]; 90 91 namespace { 92 class COFFObjectFile : public ObjectFile { 93 private: 94 uint64_t HeaderOff; 95 const coff_file_header *Header; 96 const coff_section *SectionTable; 97 const coff_symbol *SymbolTable; 98 const char *StringTable; 99 100 const coff_section *getSection(std::size_t index) const; 101 const char *getString(std::size_t offset) const; 102 103 protected: 104 virtual SymbolRef getSymbolNext(DataRefImpl Symb) const; 105 virtual StringRef getSymbolName(DataRefImpl Symb) const; 106 virtual uint64_t getSymbolAddress(DataRefImpl Symb) const; 107 virtual uint64_t getSymbolSize(DataRefImpl Symb) const; 108 virtual char getSymbolNMTypeChar(DataRefImpl Symb) const; 109 virtual bool isSymbolInternal(DataRefImpl Symb) const; 110 111 virtual SectionRef getSectionNext(DataRefImpl Sec) const; 112 virtual StringRef getSectionName(DataRefImpl Sec) const; 113 virtual uint64_t getSectionAddress(DataRefImpl Sec) const; 114 virtual uint64_t getSectionSize(DataRefImpl Sec) const; 115 virtual StringRef getSectionContents(DataRefImpl Sec) const; 116 virtual bool isSectionText(DataRefImpl Sec) const; 117 118 public: 119 COFFObjectFile(MemoryBuffer *Object); 120 virtual symbol_iterator begin_symbols() const; 121 virtual symbol_iterator end_symbols() const; 122 virtual section_iterator begin_sections() const; 123 virtual section_iterator end_sections() const; 124 125 virtual uint8_t getBytesInAddress() const; 126 virtual StringRef getFileFormatName() const; 127 virtual unsigned getArch() const; 128 }; 129 } // end namespace 130 131 SymbolRef COFFObjectFile::getSymbolNext(DataRefImpl Symb) const { 132 const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p); 133 symb += 1 + symb->NumberOfAuxSymbols; 134 Symb.p = reinterpret_cast<intptr_t>(symb); 135 return SymbolRef(Symb, this); 136 } 137 138 StringRef COFFObjectFile::getSymbolName(DataRefImpl Symb) const { 139 const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p); 140 // Check for string table entry. First 4 bytes are 0. 141 if (symb->Name.Offset.Zeroes == 0) { 142 uint32_t Offset = symb->Name.Offset.Offset; 143 return StringRef(getString(Offset)); 144 } 145 146 if (symb->Name.ShortName[7] == 0) 147 // Null terminated, let ::strlen figure out the length. 148 return StringRef(symb->Name.ShortName); 149 // Not null terminated, use all 8 bytes. 150 return StringRef(symb->Name.ShortName, 8); 151 } 152 153 uint64_t COFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { 154 const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p); 155 const coff_section *Section = getSection(symb->SectionNumber); 156 char Type = getSymbolNMTypeChar(Symb); 157 if (Type == 'U' || Type == 'w') 158 return UnknownAddressOrSize; 159 if (Section) 160 return Section->VirtualAddress + symb->Value; 161 return symb->Value; 162 } 163 164 uint64_t COFFObjectFile::getSymbolSize(DataRefImpl Symb) const { 165 // FIXME: Return the correct size. This requires looking at all the symbols 166 // in the same section as this symbol, and looking for either the next 167 // symbol, or the end of the section. 168 const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p); 169 const coff_section *Section = getSection(symb->SectionNumber); 170 char Type = getSymbolNMTypeChar(Symb); 171 if (Type == 'U' || Type == 'w') 172 return UnknownAddressOrSize; 173 if (Section) 174 return Section->SizeOfRawData - symb->Value; 175 return 0; 176 } 177 178 char COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb) const { 179 const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p); 180 char ret = StringSwitch<char>(getSymbolName(Symb)) 181 .StartsWith(".debug", 'N') 182 .StartsWith(".sxdata", 'N') 183 .Default('?'); 184 185 if (ret != '?') 186 return ret; 187 188 uint32_t Characteristics = 0; 189 uint32_t PointerToRawData = 0; 190 const coff_section *Section = getSection(symb->SectionNumber); 191 if (Section) { 192 Characteristics = Section->Characteristics; 193 PointerToRawData = Section->PointerToRawData; 194 } 195 196 switch (symb->SectionNumber) { 197 case COFF::IMAGE_SYM_UNDEFINED: 198 // Check storage classes. 199 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) 200 return 'w'; // Don't do ::toupper. 201 else 202 ret = 'u'; 203 break; 204 case COFF::IMAGE_SYM_ABSOLUTE: 205 ret = 'a'; 206 break; 207 case COFF::IMAGE_SYM_DEBUG: 208 ret = 'n'; 209 break; 210 default: 211 // Check section type. 212 if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) 213 ret = 't'; 214 else if ( Characteristics & COFF::IMAGE_SCN_MEM_READ 215 && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. 216 ret = 'r'; 217 else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) 218 ret = 'd'; 219 else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) 220 ret = 'b'; 221 else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) 222 ret = 'i'; 223 224 // Check for section symbol. 225 else if ( symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC 226 && symb->Value == 0) 227 ret = 's'; 228 } 229 230 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) 231 ret = ::toupper(ret); 232 233 return ret; 234 } 235 236 bool COFFObjectFile::isSymbolInternal(DataRefImpl Symb) const { 237 return false; 238 } 239 240 SectionRef COFFObjectFile::getSectionNext(DataRefImpl Sec) const { 241 const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p); 242 sec += 1; 243 Sec.p = reinterpret_cast<intptr_t>(sec); 244 return SectionRef(Sec, this); 245 } 246 247 StringRef COFFObjectFile::getSectionName(DataRefImpl Sec) const { 248 const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p); 249 StringRef name; 250 if (sec->Name[7] == 0) 251 // Null terminated, let ::strlen figure out the length. 252 name = sec->Name; 253 else 254 // Not null terminated, use all 8 bytes. 255 name = StringRef(sec->Name, 8); 256 257 // Check for string table entry. First byte is '/'. 258 if (name[0] == '/') { 259 uint32_t Offset; 260 name.substr(1).getAsInteger(10, Offset); 261 return StringRef(getString(Offset)); 262 } 263 264 // It's just a normal name. 265 return name; 266 } 267 268 uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Sec) const { 269 const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p); 270 return sec->VirtualAddress; 271 } 272 273 uint64_t COFFObjectFile::getSectionSize(DataRefImpl Sec) const { 274 const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p); 275 return sec->SizeOfRawData; 276 } 277 278 StringRef COFFObjectFile::getSectionContents(DataRefImpl Sec) const { 279 const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p); 280 return StringRef(reinterpret_cast<const char *>(base + sec->PointerToRawData), 281 sec->SizeOfRawData); 282 } 283 284 bool COFFObjectFile::isSectionText(DataRefImpl Sec) const { 285 const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p); 286 return sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 287 } 288 289 COFFObjectFile::COFFObjectFile(MemoryBuffer *Object) 290 : ObjectFile(Object) { 291 292 HeaderOff = 0; 293 294 if (base[0] == 0x4d && base[1] == 0x5a) { 295 // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 296 // PE signature to find 'normal' COFF header. 297 HeaderOff += *reinterpret_cast<const ulittle32_t *>(base + 0x3c); 298 HeaderOff += 4; 299 } 300 301 Header = reinterpret_cast<const coff_file_header *>(base + HeaderOff); 302 SectionTable = 303 reinterpret_cast<const coff_section *>( base 304 + HeaderOff 305 + sizeof(coff_file_header) 306 + Header->SizeOfOptionalHeader); 307 SymbolTable = 308 reinterpret_cast<const coff_symbol *>(base + Header->PointerToSymbolTable); 309 310 // Find string table. 311 StringTable = reinterpret_cast<const char *>(base) 312 + Header->PointerToSymbolTable 313 + Header->NumberOfSymbols * 18; 314 } 315 316 ObjectFile::symbol_iterator COFFObjectFile::begin_symbols() const { 317 DataRefImpl ret; 318 memset(&ret, 0, sizeof(DataRefImpl)); 319 ret.p = reinterpret_cast<intptr_t>(SymbolTable); 320 return symbol_iterator(SymbolRef(ret, this)); 321 } 322 323 ObjectFile::symbol_iterator COFFObjectFile::end_symbols() const { 324 // The symbol table ends where the string table begins. 325 DataRefImpl ret; 326 memset(&ret, 0, sizeof(DataRefImpl)); 327 ret.p = reinterpret_cast<intptr_t>(StringTable); 328 return symbol_iterator(SymbolRef(ret, this)); 329 } 330 331 ObjectFile::section_iterator COFFObjectFile::begin_sections() const { 332 DataRefImpl ret; 333 memset(&ret, 0, sizeof(DataRefImpl)); 334 ret.p = reinterpret_cast<intptr_t>(SectionTable); 335 return section_iterator(SectionRef(ret, this)); 336 } 337 338 ObjectFile::section_iterator COFFObjectFile::end_sections() const { 339 DataRefImpl ret; 340 memset(&ret, 0, sizeof(DataRefImpl)); 341 ret.p = reinterpret_cast<intptr_t>(SectionTable + Header->NumberOfSections); 342 return section_iterator(SectionRef(ret, this)); 343 } 344 345 uint8_t COFFObjectFile::getBytesInAddress() const { 346 return getArch() == Triple::x86_64 ? 8 : 4; 347 } 348 349 StringRef COFFObjectFile::getFileFormatName() const { 350 switch(Header->Machine) { 351 case COFF::IMAGE_FILE_MACHINE_I386: 352 return "COFF-i386"; 353 case COFF::IMAGE_FILE_MACHINE_AMD64: 354 return "COFF-x86-64"; 355 default: 356 return "COFF-<unknown arch>"; 357 } 358 } 359 360 unsigned COFFObjectFile::getArch() const { 361 switch(Header->Machine) { 362 case COFF::IMAGE_FILE_MACHINE_I386: 363 return Triple::x86; 364 case COFF::IMAGE_FILE_MACHINE_AMD64: 365 return Triple::x86_64; 366 default: 367 return Triple::UnknownArch; 368 } 369 } 370 371 const coff_section *COFFObjectFile::getSection(std::size_t index) const { 372 if (index > 0 && index <= Header->NumberOfSections) 373 return SectionTable + (index - 1); 374 return 0; 375 } 376 377 const char *COFFObjectFile::getString(std::size_t offset) const { 378 const ulittle32_t *StringTableSize = 379 reinterpret_cast<const ulittle32_t *>(StringTable); 380 if (offset < *StringTableSize) 381 return StringTable + offset; 382 return 0; 383 } 384 385 namespace llvm { 386 387 ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { 388 return new COFFObjectFile(Object); 389 } 390 391 } // end namespace llvm 392