18e90adafSMichael J. Spencer //===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===// 28e90adafSMichael J. Spencer // 38e90adafSMichael J. Spencer // The LLVM Compiler Infrastructure 48e90adafSMichael J. Spencer // 58e90adafSMichael J. Spencer // This file is distributed under the University of Illinois Open Source 68e90adafSMichael J. Spencer // License. See LICENSE.TXT for details. 78e90adafSMichael J. Spencer // 88e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 98e90adafSMichael J. Spencer // 108e90adafSMichael J. Spencer // This file declares the COFFObjectFile class. 118e90adafSMichael J. Spencer // 128e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 138e90adafSMichael J. Spencer 14*ec29b121SMichael J. Spencer #include "llvm/Object/COFF.h" 158e90adafSMichael J. Spencer #include "llvm/ADT/StringSwitch.h" 168e90adafSMichael J. Spencer #include "llvm/ADT/Triple.h" 178e90adafSMichael J. Spencer 188e90adafSMichael J. Spencer using namespace llvm; 198e90adafSMichael J. Spencer using namespace object; 208e90adafSMichael J. Spencer 218e90adafSMichael J. Spencer namespace { 228e90adafSMichael J. Spencer using support::ulittle8_t; 238e90adafSMichael J. Spencer using support::ulittle16_t; 248e90adafSMichael J. Spencer using support::ulittle32_t; 258e90adafSMichael J. Spencer using support::little16_t; 268e90adafSMichael J. Spencer } 278e90adafSMichael J. Spencer 288e90adafSMichael J. Spencer SymbolRef COFFObjectFile::getSymbolNext(DataRefImpl Symb) const { 290324b672SMichael J. Spencer const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p); 308e90adafSMichael J. Spencer symb += 1 + symb->NumberOfAuxSymbols; 310324b672SMichael J. Spencer Symb.p = reinterpret_cast<intptr_t>(symb); 320324b672SMichael J. Spencer return SymbolRef(Symb, this); 338e90adafSMichael J. Spencer } 348e90adafSMichael J. Spencer 358e90adafSMichael J. Spencer StringRef COFFObjectFile::getSymbolName(DataRefImpl Symb) const { 360324b672SMichael J. Spencer const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p); 378e90adafSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 388e90adafSMichael J. Spencer if (symb->Name.Offset.Zeroes == 0) { 398e90adafSMichael J. Spencer uint32_t Offset = symb->Name.Offset.Offset; 408e90adafSMichael J. Spencer return StringRef(getString(Offset)); 418e90adafSMichael J. Spencer } 428e90adafSMichael J. Spencer 438e90adafSMichael J. Spencer if (symb->Name.ShortName[7] == 0) 448e90adafSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 458e90adafSMichael J. Spencer return StringRef(symb->Name.ShortName); 468e90adafSMichael J. Spencer // Not null terminated, use all 8 bytes. 478e90adafSMichael J. Spencer return StringRef(symb->Name.ShortName, 8); 488e90adafSMichael J. Spencer } 498e90adafSMichael J. Spencer 508e90adafSMichael J. Spencer uint64_t COFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { 510324b672SMichael J. Spencer const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p); 528e90adafSMichael J. Spencer const coff_section *Section = getSection(symb->SectionNumber); 538e90adafSMichael J. Spencer char Type = getSymbolNMTypeChar(Symb); 548e90adafSMichael J. Spencer if (Type == 'U' || Type == 'w') 558e90adafSMichael J. Spencer return UnknownAddressOrSize; 568e90adafSMichael J. Spencer if (Section) 578e90adafSMichael J. Spencer return Section->VirtualAddress + symb->Value; 588e90adafSMichael J. Spencer return symb->Value; 598e90adafSMichael J. Spencer } 608e90adafSMichael J. Spencer 618e90adafSMichael J. Spencer uint64_t COFFObjectFile::getSymbolSize(DataRefImpl Symb) const { 628e90adafSMichael J. Spencer // FIXME: Return the correct size. This requires looking at all the symbols 638e90adafSMichael J. Spencer // in the same section as this symbol, and looking for either the next 648e90adafSMichael J. Spencer // symbol, or the end of the section. 650324b672SMichael J. Spencer const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p); 668e90adafSMichael J. Spencer const coff_section *Section = getSection(symb->SectionNumber); 678e90adafSMichael J. Spencer char Type = getSymbolNMTypeChar(Symb); 688e90adafSMichael J. Spencer if (Type == 'U' || Type == 'w') 698e90adafSMichael J. Spencer return UnknownAddressOrSize; 708e90adafSMichael J. Spencer if (Section) 718e90adafSMichael J. Spencer return Section->SizeOfRawData - symb->Value; 728e90adafSMichael J. Spencer return 0; 738e90adafSMichael J. Spencer } 748e90adafSMichael J. Spencer 758e90adafSMichael J. Spencer char COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb) const { 760324b672SMichael J. Spencer const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p); 778e90adafSMichael J. Spencer char ret = StringSwitch<char>(getSymbolName(Symb)) 788e90adafSMichael J. Spencer .StartsWith(".debug", 'N') 798e90adafSMichael J. Spencer .StartsWith(".sxdata", 'N') 808e90adafSMichael J. Spencer .Default('?'); 818e90adafSMichael J. Spencer 828e90adafSMichael J. Spencer if (ret != '?') 838e90adafSMichael J. Spencer return ret; 848e90adafSMichael J. Spencer 858e90adafSMichael J. Spencer uint32_t Characteristics = 0; 865f1eb968SNick Lewycky if (const coff_section *Section = getSection(symb->SectionNumber)) { 878e90adafSMichael J. Spencer Characteristics = Section->Characteristics; 888e90adafSMichael J. Spencer } 898e90adafSMichael J. Spencer 908e90adafSMichael J. Spencer switch (symb->SectionNumber) { 918e90adafSMichael J. Spencer case COFF::IMAGE_SYM_UNDEFINED: 928e90adafSMichael J. Spencer // Check storage classes. 938e90adafSMichael J. Spencer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) 948e90adafSMichael J. Spencer return 'w'; // Don't do ::toupper. 958e90adafSMichael J. Spencer else 968e90adafSMichael J. Spencer ret = 'u'; 978e90adafSMichael J. Spencer break; 988e90adafSMichael J. Spencer case COFF::IMAGE_SYM_ABSOLUTE: 998e90adafSMichael J. Spencer ret = 'a'; 1008e90adafSMichael J. Spencer break; 1018e90adafSMichael J. Spencer case COFF::IMAGE_SYM_DEBUG: 1028e90adafSMichael J. Spencer ret = 'n'; 1038e90adafSMichael J. Spencer break; 1048e90adafSMichael J. Spencer default: 1058e90adafSMichael J. Spencer // Check section type. 1068e90adafSMichael J. Spencer if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) 1078e90adafSMichael J. Spencer ret = 't'; 1088e90adafSMichael J. Spencer else if ( Characteristics & COFF::IMAGE_SCN_MEM_READ 1098e90adafSMichael J. Spencer && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. 1108e90adafSMichael J. Spencer ret = 'r'; 1118e90adafSMichael J. Spencer else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) 1128e90adafSMichael J. Spencer ret = 'd'; 1138e90adafSMichael J. Spencer else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) 1148e90adafSMichael J. Spencer ret = 'b'; 1158e90adafSMichael J. Spencer else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) 1168e90adafSMichael J. Spencer ret = 'i'; 1178e90adafSMichael J. Spencer 1188e90adafSMichael J. Spencer // Check for section symbol. 1198e90adafSMichael J. Spencer else if ( symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC 1208e90adafSMichael J. Spencer && symb->Value == 0) 1218e90adafSMichael J. Spencer ret = 's'; 1228e90adafSMichael J. Spencer } 1238e90adafSMichael J. Spencer 1248e90adafSMichael J. Spencer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) 1258e90adafSMichael J. Spencer ret = ::toupper(ret); 1268e90adafSMichael J. Spencer 1278e90adafSMichael J. Spencer return ret; 1288e90adafSMichael J. Spencer } 1298e90adafSMichael J. Spencer 1308e90adafSMichael J. Spencer bool COFFObjectFile::isSymbolInternal(DataRefImpl Symb) const { 1318e90adafSMichael J. Spencer return false; 1328e90adafSMichael J. Spencer } 1338e90adafSMichael J. Spencer 1348e90adafSMichael J. Spencer SectionRef COFFObjectFile::getSectionNext(DataRefImpl Sec) const { 1350324b672SMichael J. Spencer const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p); 1368e90adafSMichael J. Spencer sec += 1; 1370324b672SMichael J. Spencer Sec.p = reinterpret_cast<intptr_t>(sec); 1380324b672SMichael J. Spencer return SectionRef(Sec, this); 1398e90adafSMichael J. Spencer } 1408e90adafSMichael J. Spencer 1418e90adafSMichael J. Spencer StringRef COFFObjectFile::getSectionName(DataRefImpl Sec) const { 1420324b672SMichael J. Spencer const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p); 1438e90adafSMichael J. Spencer StringRef name; 1448e90adafSMichael J. Spencer if (sec->Name[7] == 0) 1458e90adafSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 1468e90adafSMichael J. Spencer name = sec->Name; 1478e90adafSMichael J. Spencer else 1488e90adafSMichael J. Spencer // Not null terminated, use all 8 bytes. 1498e90adafSMichael J. Spencer name = StringRef(sec->Name, 8); 1508e90adafSMichael J. Spencer 1518e90adafSMichael J. Spencer // Check for string table entry. First byte is '/'. 1528e90adafSMichael J. Spencer if (name[0] == '/') { 1538e90adafSMichael J. Spencer uint32_t Offset; 154ee066fc4SEric Christopher name.substr(1).getAsInteger(10, Offset); 1558e90adafSMichael J. Spencer return StringRef(getString(Offset)); 1568e90adafSMichael J. Spencer } 1578e90adafSMichael J. Spencer 1588e90adafSMichael J. Spencer // It's just a normal name. 1598e90adafSMichael J. Spencer return name; 1608e90adafSMichael J. Spencer } 1618e90adafSMichael J. Spencer 1628e90adafSMichael J. Spencer uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Sec) const { 1630324b672SMichael J. Spencer const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p); 1648e90adafSMichael J. Spencer return sec->VirtualAddress; 1658e90adafSMichael J. Spencer } 1668e90adafSMichael J. Spencer 1678e90adafSMichael J. Spencer uint64_t COFFObjectFile::getSectionSize(DataRefImpl Sec) const { 1680324b672SMichael J. Spencer const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p); 1698e90adafSMichael J. Spencer return sec->SizeOfRawData; 1708e90adafSMichael J. Spencer } 1718e90adafSMichael J. Spencer 1728e90adafSMichael J. Spencer StringRef COFFObjectFile::getSectionContents(DataRefImpl Sec) const { 1730324b672SMichael J. Spencer const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p); 174*ec29b121SMichael J. Spencer return StringRef(reinterpret_cast<const char *>(base() 175*ec29b121SMichael J. Spencer + sec->PointerToRawData), 1768e90adafSMichael J. Spencer sec->SizeOfRawData); 1778e90adafSMichael J. Spencer } 1788e90adafSMichael J. Spencer 1798e90adafSMichael J. Spencer bool COFFObjectFile::isSectionText(DataRefImpl Sec) const { 1800324b672SMichael J. Spencer const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p); 1818e90adafSMichael J. Spencer return sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 1828e90adafSMichael J. Spencer } 1838e90adafSMichael J. Spencer 184*ec29b121SMichael J. Spencer COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) 185*ec29b121SMichael J. Spencer : ObjectFile(Binary::isCOFF, Object, ec) { 186ee066fc4SEric Christopher 187ee066fc4SEric Christopher HeaderOff = 0; 188ee066fc4SEric Christopher 189*ec29b121SMichael J. Spencer if (base()[0] == 0x4d && base()[1] == 0x5a) { 190ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 191ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 192*ec29b121SMichael J. Spencer HeaderOff += *reinterpret_cast<const ulittle32_t *>(base() + 0x3c); 193ee066fc4SEric Christopher HeaderOff += 4; 194ee066fc4SEric Christopher } 195ee066fc4SEric Christopher 196*ec29b121SMichael J. Spencer Header = reinterpret_cast<const coff_file_header *>(base() + HeaderOff); 1978e90adafSMichael J. Spencer SectionTable = 198*ec29b121SMichael J. Spencer reinterpret_cast<const coff_section *>( base() 199ee066fc4SEric Christopher + HeaderOff 2008e90adafSMichael J. Spencer + sizeof(coff_file_header) 2018e90adafSMichael J. Spencer + Header->SizeOfOptionalHeader); 2028e90adafSMichael J. Spencer SymbolTable = 203*ec29b121SMichael J. Spencer reinterpret_cast<const coff_symbol *>(base() 204*ec29b121SMichael J. Spencer + Header->PointerToSymbolTable); 2058e90adafSMichael J. Spencer 2068e90adafSMichael J. Spencer // Find string table. 207*ec29b121SMichael J. Spencer StringTable = reinterpret_cast<const char *>(base()) 2088e90adafSMichael J. Spencer + Header->PointerToSymbolTable 2098e90adafSMichael J. Spencer + Header->NumberOfSymbols * 18; 2108e90adafSMichael J. Spencer } 2118e90adafSMichael J. Spencer 2128e90adafSMichael J. Spencer ObjectFile::symbol_iterator COFFObjectFile::begin_symbols() const { 2130324b672SMichael J. Spencer DataRefImpl ret; 214ee066fc4SEric Christopher memset(&ret, 0, sizeof(DataRefImpl)); 2150324b672SMichael J. Spencer ret.p = reinterpret_cast<intptr_t>(SymbolTable); 2160324b672SMichael J. Spencer return symbol_iterator(SymbolRef(ret, this)); 2178e90adafSMichael J. Spencer } 2188e90adafSMichael J. Spencer 2198e90adafSMichael J. Spencer ObjectFile::symbol_iterator COFFObjectFile::end_symbols() const { 2208e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 2210324b672SMichael J. Spencer DataRefImpl ret; 222ee066fc4SEric Christopher memset(&ret, 0, sizeof(DataRefImpl)); 2230324b672SMichael J. Spencer ret.p = reinterpret_cast<intptr_t>(StringTable); 2240324b672SMichael J. Spencer return symbol_iterator(SymbolRef(ret, this)); 2258e90adafSMichael J. Spencer } 2268e90adafSMichael J. Spencer 2278e90adafSMichael J. Spencer ObjectFile::section_iterator COFFObjectFile::begin_sections() const { 2280324b672SMichael J. Spencer DataRefImpl ret; 229ee066fc4SEric Christopher memset(&ret, 0, sizeof(DataRefImpl)); 2300324b672SMichael J. Spencer ret.p = reinterpret_cast<intptr_t>(SectionTable); 2310324b672SMichael J. Spencer return section_iterator(SectionRef(ret, this)); 2328e90adafSMichael J. Spencer } 2338e90adafSMichael J. Spencer 2348e90adafSMichael J. Spencer ObjectFile::section_iterator COFFObjectFile::end_sections() const { 2350324b672SMichael J. Spencer DataRefImpl ret; 236ee066fc4SEric Christopher memset(&ret, 0, sizeof(DataRefImpl)); 2370324b672SMichael J. Spencer ret.p = reinterpret_cast<intptr_t>(SectionTable + Header->NumberOfSections); 2380324b672SMichael J. Spencer return section_iterator(SectionRef(ret, this)); 2398e90adafSMichael J. Spencer } 2408e90adafSMichael J. Spencer 2418e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 2420324b672SMichael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 2438e90adafSMichael J. Spencer } 2448e90adafSMichael J. Spencer 2458e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 2468e90adafSMichael J. Spencer switch(Header->Machine) { 2478e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 2488e90adafSMichael J. Spencer return "COFF-i386"; 2498e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 2508e90adafSMichael J. Spencer return "COFF-x86-64"; 2518e90adafSMichael J. Spencer default: 2528e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 2538e90adafSMichael J. Spencer } 2548e90adafSMichael J. Spencer } 2558e90adafSMichael J. Spencer 2568e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const { 2578e90adafSMichael J. Spencer switch(Header->Machine) { 2588e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 2598e90adafSMichael J. Spencer return Triple::x86; 2608e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 2618e90adafSMichael J. Spencer return Triple::x86_64; 2628e90adafSMichael J. Spencer default: 2638e90adafSMichael J. Spencer return Triple::UnknownArch; 2648e90adafSMichael J. Spencer } 2658e90adafSMichael J. Spencer } 2668e90adafSMichael J. Spencer 2678e90adafSMichael J. Spencer const coff_section *COFFObjectFile::getSection(std::size_t index) const { 2688e90adafSMichael J. Spencer if (index > 0 && index <= Header->NumberOfSections) 2698e90adafSMichael J. Spencer return SectionTable + (index - 1); 2708e90adafSMichael J. Spencer return 0; 2718e90adafSMichael J. Spencer } 2728e90adafSMichael J. Spencer 2738e90adafSMichael J. Spencer const char *COFFObjectFile::getString(std::size_t offset) const { 2748e90adafSMichael J. Spencer const ulittle32_t *StringTableSize = 2758e90adafSMichael J. Spencer reinterpret_cast<const ulittle32_t *>(StringTable); 2768e90adafSMichael J. Spencer if (offset < *StringTableSize) 2778e90adafSMichael J. Spencer return StringTable + offset; 2788e90adafSMichael J. Spencer return 0; 2798e90adafSMichael J. Spencer } 2808e90adafSMichael J. Spencer 2818e90adafSMichael J. Spencer namespace llvm { 2828e90adafSMichael J. Spencer 2838e90adafSMichael J. Spencer ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { 284*ec29b121SMichael J. Spencer error_code ec; 285*ec29b121SMichael J. Spencer return new COFFObjectFile(Object, ec); 2868e90adafSMichael J. Spencer } 2878e90adafSMichael J. Spencer 2888e90adafSMichael J. Spencer } // end namespace llvm 289