diff options
Diffstat (limited to 'lib/Object')
-rw-r--r-- | lib/Object/Binary.cpp | 52 | ||||
-rw-r--r-- | lib/Object/COFFObjectFile.cpp | 128 | ||||
-rw-r--r-- | lib/Object/ELFObjectFile.cpp | 42 | ||||
-rw-r--r-- | lib/Object/MachOObjectFile.cpp | 7 | ||||
-rw-r--r-- | lib/Object/ObjectFile.cpp | 14 |
5 files changed, 152 insertions, 91 deletions
diff --git a/lib/Object/Binary.cpp b/lib/Object/Binary.cpp index 4b31c7557d..75f5a58ac0 100644 --- a/lib/Object/Binary.cpp +++ b/lib/Object/Binary.cpp @@ -16,10 +16,6 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" -// Include headers for createBinary. -#include "llvm/Object/ObjectFile.h" -#include "llvm/Object/COFF.h" - using namespace llvm; using namespace object; @@ -41,51 +37,9 @@ StringRef Binary::getFileName() const { error_code object::createBinary(MemoryBuffer *Source, OwningPtr<Binary> &Result) { - OwningPtr<MemoryBuffer> scopedSource(Source); - if (!Source) - return make_error_code(errc::invalid_argument); - if (Source->getBufferSize() < 64) - return object_error::invalid_file_type; - sys::LLVMFileType type = sys::IdentifyFileType(Source->getBufferStart(), - static_cast<unsigned>(Source->getBufferSize())); - error_code ec; - switch (type) { - case sys::ELF_Relocatable_FileType: - case sys::ELF_Executable_FileType: - case sys::ELF_SharedObject_FileType: - case sys::ELF_Core_FileType: { - OwningPtr<Binary> ret( - ObjectFile::createELFObjectFile(scopedSource.take())); - if (!ret) - return object_error::invalid_file_type; - Result.swap(ret); - return object_error::success; - } - case sys::Mach_O_Object_FileType: - case sys::Mach_O_Executable_FileType: - case sys::Mach_O_FixedVirtualMemorySharedLib_FileType: - case sys::Mach_O_Core_FileType: - case sys::Mach_O_PreloadExecutable_FileType: - case sys::Mach_O_DynamicallyLinkedSharedLib_FileType: - case sys::Mach_O_DynamicLinker_FileType: - case sys::Mach_O_Bundle_FileType: - case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType: { - OwningPtr<Binary> ret( - ObjectFile::createMachOObjectFile(scopedSource.take())); - if (!ret) - return object_error::invalid_file_type; - Result.swap(ret); - return object_error::success; - } - case sys::COFF_FileType: { - OwningPtr<Binary> ret(new COFFObjectFile(scopedSource.take(), ec)); - if (ec) return ec; - Result.swap(ret); - return object_error::success; - } - default: // Unrecognized object file format. - return object_error::invalid_file_type; - } + // We don't support any at the moment. + delete Source; + return object_error::invalid_file_type; } error_code object::createBinary(StringRef Path, OwningPtr<Binary> &Result) { diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 60fc880d7c..86bf44baae 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -11,9 +11,11 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Object/COFF.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/COFF.h" +#include "llvm/Support/Endian.h" using namespace llvm; using namespace object; @@ -25,6 +27,107 @@ using support::ulittle32_t; using support::little16_t; } +namespace { +struct coff_file_header { + ulittle16_t Machine; + ulittle16_t NumberOfSections; + ulittle32_t TimeDateStamp; + ulittle32_t PointerToSymbolTable; + ulittle32_t NumberOfSymbols; + ulittle16_t SizeOfOptionalHeader; + ulittle16_t Characteristics; +}; +} + +extern char coff_file_header_layout_static_assert + [sizeof(coff_file_header) == 20 ? 1 : -1]; + +namespace { +struct coff_symbol { + struct StringTableOffset { + ulittle32_t Zeroes; + ulittle32_t Offset; + }; + + union { + char ShortName[8]; + StringTableOffset Offset; + } Name; + + ulittle32_t Value; + little16_t SectionNumber; + + struct { + ulittle8_t BaseType; + ulittle8_t ComplexType; + } Type; + + ulittle8_t StorageClass; + ulittle8_t NumberOfAuxSymbols; +}; +} + +extern char coff_coff_symbol_layout_static_assert + [sizeof(coff_symbol) == 18 ? 1 : -1]; + +namespace { +struct coff_section { + char Name[8]; + ulittle32_t VirtualSize; + ulittle32_t VirtualAddress; + ulittle32_t SizeOfRawData; + ulittle32_t PointerToRawData; + ulittle32_t PointerToRelocations; + ulittle32_t PointerToLinenumbers; + ulittle16_t NumberOfRelocations; + ulittle16_t NumberOfLinenumbers; + ulittle32_t Characteristics; +}; +} + +extern char coff_coff_section_layout_static_assert + [sizeof(coff_section) == 40 ? 1 : -1]; + +namespace { +class COFFObjectFile : public ObjectFile { +private: + uint64_t HeaderOff; + const coff_file_header *Header; + const coff_section *SectionTable; + const coff_symbol *SymbolTable; + const char *StringTable; + + const coff_section *getSection(std::size_t index) const; + const char *getString(std::size_t offset) const; + +protected: + virtual SymbolRef getSymbolNext(DataRefImpl Symb) const; + virtual StringRef getSymbolName(DataRefImpl Symb) const; + virtual uint64_t getSymbolAddress(DataRefImpl Symb) const; + virtual uint64_t getSymbolSize(DataRefImpl Symb) const; + virtual char getSymbolNMTypeChar(DataRefImpl Symb) const; + virtual bool isSymbolInternal(DataRefImpl Symb) const; + + virtual SectionRef getSectionNext(DataRefImpl Sec) const; + virtual StringRef getSectionName(DataRefImpl Sec) const; + virtual uint64_t getSectionAddress(DataRefImpl Sec) const; + virtual uint64_t getSectionSize(DataRefImpl Sec) const; + virtual StringRef getSectionContents(DataRefImpl Sec) const; + virtual bool isSectionText(DataRefImpl Sec) const; + +public: + COFFObjectFile(MemoryBuffer *Object); + virtual symbol_iterator begin_symbols() const; + virtual symbol_iterator end_symbols() const; + virtual section_iterator begin_sections() const; + virtual section_iterator end_sections() const; + + virtual uint8_t getBytesInAddress() const; + virtual StringRef getFileFormatName() const; + virtual unsigned getArch() const; +}; +} // end namespace + SymbolRef COFFObjectFile::getSymbolNext(DataRefImpl Symb) const { const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(Symb.p); symb += 1 + symb->NumberOfAuxSymbols; @@ -171,8 +274,7 @@ uint64_t COFFObjectFile::getSectionSize(DataRefImpl Sec) const { StringRef COFFObjectFile::getSectionContents(DataRefImpl Sec) const { const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p); - return StringRef(reinterpret_cast<const char *>(base() - + sec->PointerToRawData), + return StringRef(reinterpret_cast<const char *>(base + sec->PointerToRawData), sec->SizeOfRawData); } @@ -181,30 +283,29 @@ bool COFFObjectFile::isSectionText(DataRefImpl Sec) const { return sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; } -COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) - : ObjectFile(Binary::isCOFF, Object, ec) { +COFFObjectFile::COFFObjectFile(MemoryBuffer *Object) + : ObjectFile(Object) { HeaderOff = 0; - if (base()[0] == 0x4d && base()[1] == 0x5a) { + if (base[0] == 0x4d && base[1] == 0x5a) { // PE/COFF, seek through MS-DOS compatibility stub and 4-byte // PE signature to find 'normal' COFF header. - HeaderOff += *reinterpret_cast<const ulittle32_t *>(base() + 0x3c); + HeaderOff += *reinterpret_cast<const ulittle32_t *>(base + 0x3c); HeaderOff += 4; } - Header = reinterpret_cast<const coff_file_header *>(base() + HeaderOff); + Header = reinterpret_cast<const coff_file_header *>(base + HeaderOff); SectionTable = - reinterpret_cast<const coff_section *>( base() + reinterpret_cast<const coff_section *>( base + HeaderOff + sizeof(coff_file_header) + Header->SizeOfOptionalHeader); SymbolTable = - reinterpret_cast<const coff_symbol *>(base() - + Header->PointerToSymbolTable); + reinterpret_cast<const coff_symbol *>(base + Header->PointerToSymbolTable); // Find string table. - StringTable = reinterpret_cast<const char *>(base()) + StringTable = reinterpret_cast<const char *>(base) + Header->PointerToSymbolTable + Header->NumberOfSymbols * 18; } @@ -281,8 +382,7 @@ const char *COFFObjectFile::getString(std::size_t offset) const { namespace llvm { ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { - error_code ec; - return new COFFObjectFile(Object, ec); + return new COFFObjectFile(Object); } } // end namespace llvm diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index 1c4dceaa35..d2a2726ce7 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -237,7 +237,7 @@ protected: virtual bool isSectionText(DataRefImpl Sec) const; public: - ELFObjectFile(MemoryBuffer *Object, error_code &ec); + ELFObjectFile(MemoryBuffer *Object); virtual symbol_iterator begin_symbols() const; virtual symbol_iterator end_symbols() const; virtual section_iterator begin_sections() const; @@ -259,9 +259,9 @@ void ELFObjectFile<target_endianness, is64Bits> // an error object around. if (!( symb && SymbolTableSection - && symb >= (const Elf_Sym*)(base() + && symb >= (const Elf_Sym*)(base + SymbolTableSection->sh_offset) - && symb < (const Elf_Sym*)(base() + && symb < (const Elf_Sym*)(base + SymbolTableSection->sh_offset + SymbolTableSection->sh_size))) // FIXME: Proper error handling. @@ -444,7 +444,7 @@ template<support::endianness target_endianness, bool is64Bits> StringRef ELFObjectFile<target_endianness, is64Bits> ::getSectionContents(DataRefImpl Sec) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); - const char *start = (char*)base() + sec->sh_offset; + const char *start = (char*)base + sec->sh_offset; return StringRef(start, sec->sh_size); } @@ -458,22 +458,21 @@ bool ELFObjectFile<target_endianness, is64Bits> } template<support::endianness target_endianness, bool is64Bits> -ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object - , error_code &ec) - : ObjectFile(Binary::isELF, Object, ec) +ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object) + : ObjectFile(Object) , SectionHeaderTable(0) , dot_shstrtab_sec(0) , dot_strtab_sec(0) { - Header = reinterpret_cast<const Elf_Ehdr *>(base()); + Header = reinterpret_cast<const Elf_Ehdr *>(base); if (Header->e_shoff == 0) return; SectionHeaderTable = - reinterpret_cast<const Elf_Shdr *>(base() + Header->e_shoff); + reinterpret_cast<const Elf_Shdr *>(base + Header->e_shoff); uint32_t SectionTableSize = Header->e_shnum * Header->e_shentsize; if (!( (const uint8_t *)SectionHeaderTable + SectionTableSize - <= base() + Data->getBufferSize())) + <= base + MapFile->getBufferSize())) // FIXME: Proper error handling. report_fatal_error("Section table goes past end of file!"); @@ -492,7 +491,7 @@ ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object dot_shstrtab_sec = getSection(Header->e_shstrndx); if (dot_shstrtab_sec) { // Verify that the last byte in the string table in a null. - if (((const char*)base() + dot_shstrtab_sec->sh_offset) + if (((const char*)base + dot_shstrtab_sec->sh_offset) [dot_shstrtab_sec->sh_size - 1] != 0) // FIXME: Proper error handling. report_fatal_error("String table must end with a null terminator!"); @@ -510,7 +509,7 @@ ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object // FIXME: Proper error handling. report_fatal_error("Already found section named .strtab!"); dot_strtab_sec = sh; - const char *dot_strtab = (const char*)base() + sh->sh_offset; + const char *dot_strtab = (const char*)base + sh->sh_offset; if (dot_strtab[sh->sh_size - 1] != 0) // FIXME: Proper error handling. report_fatal_error("String table must end with a null terminator!"); @@ -549,7 +548,7 @@ ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits> ::begin_sections() const { DataRefImpl ret; memset(&ret, 0, sizeof(DataRefImpl)); - ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff); + ret.p = reinterpret_cast<intptr_t>(base + Header->e_shoff); return section_iterator(SectionRef(ret, this)); } @@ -558,7 +557,7 @@ ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits> ::end_sections() const { DataRefImpl ret; memset(&ret, 0, sizeof(DataRefImpl)); - ret.p = reinterpret_cast<intptr_t>(base() + ret.p = reinterpret_cast<intptr_t>(base + Header->e_shoff + (Header->e_shentsize * Header->e_shnum)); return section_iterator(SectionRef(ret, this)); @@ -614,7 +613,7 @@ const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym * ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const { const Elf_Shdr *sec = SymbolTableSections[Symb.d.b]; return reinterpret_cast<const Elf_Sym *>( - base() + base + sec->sh_offset + (Symb.d.a * sec->sh_entsize)); } @@ -657,8 +656,8 @@ const char *ELFObjectFile<target_endianness, is64Bits> assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); if (offset >= section->sh_size) // FIXME: Proper error handling. - report_fatal_error("Symbol name offset outside of string table!"); - return (const char *)base() + section->sh_offset + offset; + report_fatal_error("Sybol name offset outside of string table!"); + return (const char *)base + section->sh_offset + offset; } // EI_CLASS, EI_DATA. @@ -674,15 +673,14 @@ namespace llvm { ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) { std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object); - error_code ec; if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) - return new ELFObjectFile<support::little, false>(Object, ec); + return new ELFObjectFile<support::little, false>(Object); else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) - return new ELFObjectFile<support::big, false>(Object, ec); + return new ELFObjectFile<support::big, false>(Object); else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) - return new ELFObjectFile<support::little, true>(Object, ec); + return new ELFObjectFile<support::little, true>(Object); else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) - return new ELFObjectFile<support::big, true>(Object, ec); + return new ELFObjectFile<support::big, true>(Object); // FIXME: Proper error handling. report_fatal_error("Not an ELF object file!"); } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 3b76c6f7be..877cbfbdb8 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -32,8 +32,8 @@ typedef MachOObject::LoadCommandInfo LoadCommandInfo; class MachOObjectFile : public ObjectFile { public: - MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec) - : ObjectFile(Binary::isMachO, Object, ec), + MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO) + : ObjectFile(Object), MachOObj(MOO), RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {} @@ -73,12 +73,11 @@ private: }; ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { - error_code ec; std::string Err; MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err); if (!MachOObj) return NULL; - return new MachOObjectFile(Buffer, MachOObj, ec); + return new MachOObjectFile(Buffer, MachOObj); } /*===-- Symbols -----------------------------------------------------------===*/ diff --git a/lib/Object/ObjectFile.cpp b/lib/Object/ObjectFile.cpp index a7798df33f..47b63115a9 100644 --- a/lib/Object/ObjectFile.cpp +++ b/lib/Object/ObjectFile.cpp @@ -21,8 +21,18 @@ using namespace llvm; using namespace object; -ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *source, error_code &ec) - : Binary(Type, source) { +ObjectFile::ObjectFile(MemoryBuffer *Object) + : MapFile(Object) { + assert(MapFile && "Must be a valid MemoryBuffer!"); + base = reinterpret_cast<const uint8_t *>(MapFile->getBufferStart()); +} + +ObjectFile::~ObjectFile() { + delete MapFile; +} + +StringRef ObjectFile::getFilename() const { + return MapFile->getBufferIdentifier(); } ObjectFile *ObjectFile::createObjectFile(MemoryBuffer *Object) { |