X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=lib%2FObject%2FCOFFObjectFile.cpp;h=0b7ee34c09af71dd85aeba486fe809e84e323e6e;hb=a41dce3c642e50775352cce49e3a3d0cd004d393;hp=0859bca40addf451335dd79986cd98d72faaedbf;hpb=c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bd;p=oota-llvm.git diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 0859bca40ad..0b7ee34c09a 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/COFF.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" @@ -101,7 +102,7 @@ error_code COFFObjectFile::getSymbolNext(DataRefImpl Symb, return getSymbolName(symb, Result); } -error_code COFFObjectFile::getSymbolOffset(DataRefImpl Symb, +error_code COFFObjectFile::getSymbolFileOffset(DataRefImpl Symb, uint64_t &Result) const { const coff_symbol *symb = toSymb(Symb); const coff_section *Section = NULL; @@ -113,7 +114,7 @@ error_code COFFObjectFile::getSymbolOffset(DataRefImpl Symb, if (Type == 'U' || Type == 'w') Result = UnknownAddressOrSize; else if (Section) - Result = Section->VirtualAddress + symb->Value; + Result = Section->PointerToRawData + symb->Value; else Result = symb->Value; return object_error::success; @@ -131,11 +132,9 @@ error_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb, if (Type == 'U' || Type == 'w') Result = UnknownAddressOrSize; else if (Section) - Result = reinterpret_cast(base() + - Section->PointerToRawData + - symb->Value); + Result = Section->VirtualAddress + symb->Value; else - Result = reinterpret_cast(base() + symb->Value); + Result = symb->Value; return object_error::success; } @@ -145,9 +144,9 @@ error_code COFFObjectFile::getSymbolType(DataRefImpl Symb, Result = SymbolRef::ST_Other; if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { - Result = SymbolRef::ST_External; + Result = SymbolRef::ST_Unknown; } else { - if (symb->Type.ComplexType == COFF::IMAGE_SYM_DTYPE_FUNCTION) { + if (symb->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) { Result = SymbolRef::ST_Function; } else { char Type; @@ -161,17 +160,27 @@ error_code COFFObjectFile::getSymbolType(DataRefImpl Symb, return object_error::success; } -error_code COFFObjectFile::isSymbolGlobal(DataRefImpl Symb, - bool &Result) const { +error_code COFFObjectFile::getSymbolFlags(DataRefImpl Symb, + uint32_t &Result) const { const coff_symbol *symb = toSymb(Symb); - Result = (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL); - return object_error::success; -} + Result = SymbolRef::SF_None; + + // TODO: Correctly set SF_FormatSpecific, SF_ThreadLocal, SF_Common + + if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && + symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) + Result |= SymbolRef::SF_Undefined; + + // TODO: This are certainly too restrictive. + if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) + Result |= SymbolRef::SF_Global; + + if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) + Result |= SymbolRef::SF_Weak; + + if (symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE) + Result |= SymbolRef::SF_Absolute; -error_code COFFObjectFile::isSymbolWeak(DataRefImpl Symb, - bool &Result) const { - const coff_symbol *symb = toSymb(Symb); - Result = (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL); return object_error::success; } @@ -226,7 +235,9 @@ error_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) { Result = 'w'; return object_error::success; // Don't do ::toupper. - } else + } else if (symb->Value != 0) // Check for common symbols. + ret = 'c'; + else ret = 'u'; break; case COFF::IMAGE_SYM_ABSOLUTE: @@ -262,12 +273,26 @@ error_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, return object_error::success; } -error_code COFFObjectFile::isSymbolInternal(DataRefImpl Symb, - bool &Result) const { - Result = false; +error_code COFFObjectFile::getSymbolSection(DataRefImpl Symb, + section_iterator &Result) const { + const coff_symbol *symb = toSymb(Symb); + if (symb->SectionNumber <= COFF::IMAGE_SYM_UNDEFINED) + Result = end_sections(); + else { + const coff_section *sec = 0; + if (error_code ec = getSection(symb->SectionNumber, sec)) return ec; + DataRefImpl Sec; + Sec.p = reinterpret_cast(sec); + Result = section_iterator(SectionRef(Sec, this)); + } return object_error::success; } +error_code COFFObjectFile::getSymbolValue(DataRefImpl Symb, + uint64_t &Val) const { + report_fatal_error("getSymbolValue unimplemented in COFFObjectFile"); +} + error_code COFFObjectFile::getSectionNext(DataRefImpl Sec, SectionRef &Result) const { const coff_section *sec = toSec(Sec); @@ -280,24 +305,7 @@ error_code COFFObjectFile::getSectionNext(DataRefImpl Sec, error_code COFFObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const { const coff_section *sec = toSec(Sec); - StringRef name; - if (sec->Name[7] == 0) - // Null terminated, let ::strlen figure out the length. - name = sec->Name; - else - // Not null terminated, use all 8 bytes. - name = StringRef(sec->Name, 8); - - // Check for string table entry. First byte is '/'. - if (name[0] == '/') { - uint32_t Offset; - name.substr(1).getAsInteger(10, Offset); - if (error_code ec = getString(Offset, name)) - return ec; - } - - Result = name; - return object_error::success; + return getSectionName(sec, Result); } error_code COFFObjectFile::getSectionAddress(DataRefImpl Sec, @@ -317,16 +325,10 @@ error_code COFFObjectFile::getSectionSize(DataRefImpl Sec, error_code COFFObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Result) const { const coff_section *sec = toSec(Sec); - // The only thing that we need to verify is that the contents is contained - // within the file bounds. We don't need to make sure it doesn't cover other - // data, as there's nothing that says that is not allowed. - uintptr_t con_start = uintptr_t(base()) + sec->PointerToRawData; - uintptr_t con_end = con_start + sec->SizeOfRawData; - if (con_end >= uintptr_t(Data->getBufferEnd())) - return object_error::parse_failed; - Result = StringRef(reinterpret_cast(con_start), - sec->SizeOfRawData); - return object_error::success; + ArrayRef Res; + error_code EC = getSectionContents(sec, Res); + Result = StringRef(reinterpret_cast(Res.data()), Res.size()); + return EC; } error_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec, @@ -359,12 +361,40 @@ error_code COFFObjectFile::isSectionBSS(DataRefImpl Sec, return object_error::success; } +error_code COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, + bool &Result) const { + // FIXME: Unimplemented + Result = true; + return object_error::success; +} + +error_code COFFObjectFile::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { + const coff_section *sec = toSec(Sec); + Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; + return object_error::success; +} + +error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Sec, + bool &Result) const { + // FIXME: Unimplemented. + Result = false; + return object_error::success; +} + +error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, + bool &Result) const { + // FIXME: Unimplemented. + Result = false; + return object_error::success; +} + error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const { const coff_section *sec = toSec(Sec); const coff_symbol *symb = toSymb(Symb); - const coff_section *symb_sec; + const coff_section *symb_sec = 0; if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec; if (symb_sec == sec) Result = true; @@ -376,7 +406,6 @@ error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec, relocation_iterator COFFObjectFile::getSectionRelBegin(DataRefImpl Sec) const { const coff_section *sec = toSec(Sec); DataRefImpl ret; - std::memset(&ret, 0, sizeof(ret)); if (sec->NumberOfRelocations == 0) ret.p = 0; else @@ -388,7 +417,6 @@ relocation_iterator COFFObjectFile::getSectionRelBegin(DataRefImpl Sec) const { relocation_iterator COFFObjectFile::getSectionRelEnd(DataRefImpl Sec) const { const coff_section *sec = toSec(Sec); DataRefImpl ret; - std::memset(&ret, 0, sizeof(ret)); if (sec->NumberOfRelocations == 0) ret.p = 0; else @@ -401,7 +429,12 @@ relocation_iterator COFFObjectFile::getSectionRelEnd(DataRefImpl Sec) const { } COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) - : ObjectFile(Binary::isCOFF, Object, ec) { + : ObjectFile(Binary::ID_COFF, Object, ec) + , Header(0) + , SectionTable(0) + , SymbolTable(0) + , StringTable(0) + , StringTableSize(0) { // Check that we at least have enough room for a header. if (!checkSize(Data, ec, sizeof(coff_file_header))) return; @@ -414,7 +447,7 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) // PE/COFF, seek through MS-DOS compatibility stub and 4-byte // PE signature to find 'normal' COFF header. if (!checkSize(Data, ec, 0x3c + 8)) return; - HeaderStart += *reinterpret_cast(base() + 0x3c); + HeaderStart = *reinterpret_cast(base() + 0x3c); // Check the PE header. ("PE\0\0") if (std::memcmp(base() + HeaderStart, "PE\0\0", 4) != 0) { ec = object_error::parse_failed; @@ -436,28 +469,30 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) Header->NumberOfSections * sizeof(coff_section))) return; - SymbolTable = - reinterpret_cast(base() - + Header->PointerToSymbolTable); - if (!checkAddr(Data, ec, uintptr_t(SymbolTable), - Header->NumberOfSymbols * sizeof(coff_symbol))) - return; + if (Header->PointerToSymbolTable != 0) { + SymbolTable = + reinterpret_cast(base() + + Header->PointerToSymbolTable); + if (!checkAddr(Data, ec, uintptr_t(SymbolTable), + Header->NumberOfSymbols * sizeof(coff_symbol))) + return; - // Find string table. - StringTable = reinterpret_cast(base()) - + Header->PointerToSymbolTable - + Header->NumberOfSymbols * sizeof(coff_symbol); - if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t))) - return; + // Find string table. + StringTable = reinterpret_cast(base()) + + Header->PointerToSymbolTable + + Header->NumberOfSymbols * sizeof(coff_symbol); + if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t))) + return; - StringTableSize = *reinterpret_cast(StringTable); - if (!checkAddr(Data, ec, uintptr_t(StringTable), StringTableSize)) - return; - // Check that the string table is null terminated if has any in it. - if (StringTableSize < 4 - || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) { - ec = object_error::parse_failed; - return; + StringTableSize = *reinterpret_cast(StringTable); + if (!checkAddr(Data, ec, uintptr_t(StringTable), StringTableSize)) + return; + // Check that the string table is null terminated if has any in it. + if (StringTableSize < 4 + || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) { + ec = object_error::parse_failed; + return; + } } ec = object_error::success; @@ -465,7 +500,6 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) symbol_iterator COFFObjectFile::begin_symbols() const { DataRefImpl ret; - std::memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(SymbolTable); return symbol_iterator(SymbolRef(ret, this)); } @@ -473,21 +507,44 @@ symbol_iterator COFFObjectFile::begin_symbols() const { symbol_iterator COFFObjectFile::end_symbols() const { // The symbol table ends where the string table begins. DataRefImpl ret; - std::memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(StringTable); return symbol_iterator(SymbolRef(ret, this)); } +symbol_iterator COFFObjectFile::begin_dynamic_symbols() const { + // TODO: implement + report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); +} + +symbol_iterator COFFObjectFile::end_dynamic_symbols() const { + // TODO: implement + report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); +} + +library_iterator COFFObjectFile::begin_libraries_needed() const { + // TODO: implement + report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); +} + +library_iterator COFFObjectFile::end_libraries_needed() const { + // TODO: implement + report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); +} + +StringRef COFFObjectFile::getLoadName() const { + // COFF does not have this field. + return ""; +} + + section_iterator COFFObjectFile::begin_sections() const { DataRefImpl ret; - std::memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(SectionTable); return section_iterator(SectionRef(ret, this)); } section_iterator COFFObjectFile::end_sections() const { DataRefImpl ret; - std::memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(SectionTable + Header->NumberOfSections); return section_iterator(SectionRef(ret, this)); } @@ -551,7 +608,7 @@ error_code COFFObjectFile::getString(uint32_t offset, error_code COFFObjectFile::getSymbol(uint32_t index, const coff_symbol *&Result) const { - if (index >= 0 && index < Header->NumberOfSymbols) + if (index < Header->NumberOfSymbols) Result = SymbolTable + index; else return object_error::parse_failed; @@ -577,6 +634,65 @@ error_code COFFObjectFile::getSymbolName(const coff_symbol *symbol, return object_error::success; } +ArrayRef COFFObjectFile::getSymbolAuxData( + const coff_symbol *symbol) const { + const uint8_t *aux = NULL; + + if ( symbol->NumberOfAuxSymbols > 0 ) { + // AUX data comes immediately after the symbol in COFF + aux = reinterpret_cast(symbol + 1); +# ifndef NDEBUG + // Verify that the aux symbol points to a valid entry in the symbol table. + uintptr_t offset = uintptr_t(aux) - uintptr_t(base()); + if (offset < Header->PointerToSymbolTable + || offset >= Header->PointerToSymbolTable + + (Header->NumberOfSymbols * sizeof(coff_symbol))) + report_fatal_error("Aux Symbol data was outside of symbol table."); + + assert((offset - Header->PointerToSymbolTable) % sizeof(coff_symbol) + == 0 && "Aux Symbol data did not point to the beginning of a symbol"); +# endif + } + return ArrayRef(aux, symbol->NumberOfAuxSymbols * sizeof(coff_symbol)); +} + +error_code COFFObjectFile::getSectionName(const coff_section *Sec, + StringRef &Res) const { + StringRef Name; + if (Sec->Name[7] == 0) + // Null terminated, let ::strlen figure out the length. + Name = Sec->Name; + else + // Not null terminated, use all 8 bytes. + Name = StringRef(Sec->Name, 8); + + // Check for string table entry. First byte is '/'. + if (Name[0] == '/') { + uint32_t Offset; + if (Name.substr(1).getAsInteger(10, Offset)) + return object_error::parse_failed; + if (error_code ec = getString(Offset, Name)) + return ec; + } + + Res = Name; + return object_error::success; +} + +error_code COFFObjectFile::getSectionContents(const coff_section *Sec, + ArrayRef &Res) const { + // The only thing that we need to verify is that the contents is contained + // within the file bounds. We don't need to make sure it doesn't cover other + // data, as there's nothing that says that is not allowed. + uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; + uintptr_t ConEnd = ConStart + Sec->SizeOfRawData; + if (ConEnd > uintptr_t(Data->getBufferEnd())) + return object_error::parse_failed; + Res = ArrayRef(reinterpret_cast(ConStart), + Sec->SizeOfRawData); + return object_error::success; +} + const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { return reinterpret_cast(Rel.p); } @@ -592,6 +708,11 @@ error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, Res = toRel(Rel)->VirtualAddress; return object_error::success; } +error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const { + Res = toRel(Rel)->VirtualAddress; + return object_error::success; +} error_code COFFObjectFile::getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const { const coff_relocation* R = toRel(Rel); @@ -601,12 +722,26 @@ error_code COFFObjectFile::getRelocationSymbol(DataRefImpl Rel, return object_error::success; } error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, - uint32_t &Res) const { + uint64_t &Res) const { const coff_relocation* R = toRel(Rel); Res = R->Type; return object_error::success; } +const coff_section *COFFObjectFile::getCOFFSection(section_iterator &It) const { + return toSec(It->getRawDataRefImpl()); +} + +const coff_symbol *COFFObjectFile::getCOFFSymbol(symbol_iterator &It) const { + return toSymb(It->getRawDataRefImpl()); +} + +const coff_relocation *COFFObjectFile::getCOFFRelocation( + relocation_iterator &It) const { + return toRel(It->getRawDataRefImpl()); +} + + #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \ case COFF::enum: res = #enum; break; @@ -675,7 +810,6 @@ error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel, const coff_symbol *symb = 0; if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec; DataRefImpl sym; - ::memset(&sym, 0, sizeof(sym)); sym.p = reinterpret_cast(symb); StringRef symname; if (error_code ec = getSymbolName(sym, symname)) return ec; @@ -683,6 +817,16 @@ error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel, return object_error::success; } +error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData, + LibraryRef &Result) const { + report_fatal_error("getLibraryNext not implemented in COFFObjectFile"); +} + +error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData, + StringRef &Result) const { + report_fatal_error("getLibraryPath not implemented in COFFObjectFile"); +} + namespace llvm { ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {