From 25b15777df42d5d608810f6881b6c98107481d69 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Sat, 25 Jun 2011 17:55:23 +0000 Subject: [PATCH] Object: Add proper error handling. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133872 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/COFF.h | 36 ++-- include/llvm/Object/Error.h | 3 +- include/llvm/Object/ObjectFile.h | 125 ++++++++------ lib/Object/COFFObjectFile.cpp | 326 +++++++++++++++++++++++++++--------- lib/Object/ELFObjectFile.cpp | 162 +++++++++++------- lib/Object/Error.cpp | 2 + lib/Object/MachOObjectFile.cpp | 106 +++++++----- lib/Object/Object.cpp | 21 ++- tools/llvm-nm/llvm-nm.cpp | 28 +++- tools/llvm-objdump/llvm-objdump.cpp | 29 +++- 10 files changed, 565 insertions(+), 273 deletions(-) diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 5ed8aa01be8..6a5e0d97235 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -69,29 +69,33 @@ struct coff_section { class COFFObjectFile : public ObjectFile { private: - uint64_t HeaderOff; const coff_file_header *Header; const coff_section *SectionTable; const coff_symbol *SymbolTable; const char *StringTable; + uint32_t StringTableSize; - const coff_section *getSection(std::size_t index) const; - const char *getString(std::size_t offset) const; + error_code getSection(int32_t index, + const coff_section *&Res) const; + error_code getString(uint32_t offset, StringRef &Res) const; + + const coff_symbol *toSymb(DataRefImpl Symb) const; + const coff_section *toSec(DataRefImpl Sec) 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; + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; + virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; + + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; public: COFFObjectFile(MemoryBuffer *Object, error_code &ec); diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h index c1a46298527..fbaf71c17b8 100644 --- a/include/llvm/Object/Error.h +++ b/include/llvm/Object/Error.h @@ -25,7 +25,8 @@ struct object_error { enum _ { success = 0, invalid_file_type, - parse_failed + parse_failed, + unexpected_eof }; _ v_; diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index d16e4dda6ce..f083d3c814a 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -17,6 +17,7 @@ #include "llvm/Object/Binary.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include @@ -29,7 +30,7 @@ union DataRefImpl { struct { uint32_t a, b; } d; - intptr_t p; + uintptr_t p; }; static bool operator ==(const DataRefImpl &a, const DataRefImpl &b) { @@ -38,6 +39,19 @@ static bool operator ==(const DataRefImpl &a, const DataRefImpl &b) { return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; } +class RelocationRef { + DataRefImpl RelocationPimpl; + const ObjectFile *OwningObject; + +public: + RelocationRef() : OwningObject(NULL) { std::memset(&RelocationPimpl, 0, sizeof(RelocationPimpl)); } + RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner); + + bool operator==(const RelocationRef &Other) const; + + error_code getNext(RelocationRef &Result); +}; + /// SymbolRef - This is a value type class that represents a single symbol in /// the list of symbols in the object file. class SymbolRef { @@ -45,23 +59,24 @@ class SymbolRef { const ObjectFile *OwningObject; public: + SymbolRef() : OwningObject(NULL) { std::memset(&SymbolPimpl, 0, sizeof(SymbolPimpl)); } SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); bool operator==(const SymbolRef &Other) const; - SymbolRef getNext() const; + error_code getNext(SymbolRef &Result) const; - StringRef getName() const; - uint64_t getAddress() const; - uint64_t getSize() const; + error_code getName(StringRef &Result) const; + error_code getAddress(uint64_t &Result) const; + error_code getSize(uint64_t &Result) const; /// Returns the ascii char that should be displayed in a symbol table dump via /// nm for this symbol. - char getNMTypeChar() const; + error_code getNMTypeChar(char &Result) const; /// Returns true for symbols that are internal to the object file format such /// as section symbols. - bool isInternal() const; + error_code isInternal(bool &Result) const; }; /// SectionRef - This is a value type class that represents a single section in @@ -71,19 +86,20 @@ class SectionRef { const ObjectFile *OwningObject; public: + SectionRef() : OwningObject(NULL) { std::memset(&SectionPimpl, 0, sizeof(SectionPimpl)); } SectionRef(DataRefImpl SectionP, const ObjectFile *Owner); bool operator==(const SectionRef &Other) const; - SectionRef getNext() const; + error_code getNext(SectionRef &Result) const; - StringRef getName() const; - uint64_t getAddress() const; - uint64_t getSize() const; - StringRef getContents() const; + error_code getName(StringRef &Result) const; + error_code getAddress(uint64_t &Result) const; + error_code getSize(uint64_t &Result) const; + error_code getContents(StringRef &Result) const; // FIXME: Move to the normalization layer when it's created. - bool isText() const; + error_code isText(bool &Result) const; }; const uint64_t UnknownAddressOrSize = ~0ULL; @@ -108,22 +124,25 @@ protected: // entry in the memory mapped object file. SymbolPimpl cannot contain any // virtual functions because then it could not point into the memory mapped // file. + // + // Implementations assume that the DataRefImpl is valid and has not been + // modified externally. It's UB otherwise. friend class SymbolRef; - virtual SymbolRef getSymbolNext(DataRefImpl Symb) const = 0; - virtual StringRef getSymbolName(DataRefImpl Symb) const = 0; - virtual uint64_t getSymbolAddress(DataRefImpl Symb) const = 0; - virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; - virtual char getSymbolNMTypeChar(DataRefImpl Symb) const = 0; - virtual bool isSymbolInternal(DataRefImpl Symb) const = 0; + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const = 0; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const = 0; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const =0; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const = 0; + virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const = 0; // Same as above for SectionRef. friend class SectionRef; - virtual SectionRef getSectionNext(DataRefImpl Sec) const = 0; - virtual StringRef getSectionName(DataRefImpl Sec) const = 0; - virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0; - virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0; - virtual StringRef getSectionContents(DataRefImpl Sec) const = 0; - virtual bool isSectionText(DataRefImpl Sec) const = 0; + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const = 0; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const = 0; + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const =0; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const = 0; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res)const=0; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const = 0; public: @@ -146,8 +165,12 @@ public: return !(*this == other); } - content_iterator& operator++() { // Preincrement - Current = Current.getNext(); + content_iterator& increment(error_code &err) { + content_type next; + if (error_code ec = Current.getNext(next)) + err = ec; + else + Current = next; return *this; } }; @@ -196,28 +219,28 @@ inline bool SymbolRef::operator==(const SymbolRef &Other) const { return SymbolPimpl == Other.SymbolPimpl; } -inline SymbolRef SymbolRef::getNext() const { - return OwningObject->getSymbolNext(SymbolPimpl); +inline error_code SymbolRef::getNext(SymbolRef &Result) const { + return OwningObject->getSymbolNext(SymbolPimpl, Result); } -inline StringRef SymbolRef::getName() const { - return OwningObject->getSymbolName(SymbolPimpl); +inline error_code SymbolRef::getName(StringRef &Result) const { + return OwningObject->getSymbolName(SymbolPimpl, Result); } -inline uint64_t SymbolRef::getAddress() const { - return OwningObject->getSymbolAddress(SymbolPimpl); +inline error_code SymbolRef::getAddress(uint64_t &Result) const { + return OwningObject->getSymbolAddress(SymbolPimpl, Result); } -inline uint64_t SymbolRef::getSize() const { - return OwningObject->getSymbolSize(SymbolPimpl); +inline error_code SymbolRef::getSize(uint64_t &Result) const { + return OwningObject->getSymbolSize(SymbolPimpl, Result); } -inline char SymbolRef::getNMTypeChar() const { - return OwningObject->getSymbolNMTypeChar(SymbolPimpl); +inline error_code SymbolRef::getNMTypeChar(char &Result) const { + return OwningObject->getSymbolNMTypeChar(SymbolPimpl, Result); } -inline bool SymbolRef::isInternal() const { - return OwningObject->isSymbolInternal(SymbolPimpl); +inline error_code SymbolRef::isInternal(bool &Result) const { + return OwningObject->isSymbolInternal(SymbolPimpl, Result); } @@ -231,28 +254,28 @@ inline bool SectionRef::operator==(const SectionRef &Other) const { return SectionPimpl == Other.SectionPimpl; } -inline SectionRef SectionRef::getNext() const { - return OwningObject->getSectionNext(SectionPimpl); +inline error_code SectionRef::getNext(SectionRef &Result) const { + return OwningObject->getSectionNext(SectionPimpl, Result); } -inline StringRef SectionRef::getName() const { - return OwningObject->getSectionName(SectionPimpl); +inline error_code SectionRef::getName(StringRef &Result) const { + return OwningObject->getSectionName(SectionPimpl, Result); } -inline uint64_t SectionRef::getAddress() const { - return OwningObject->getSectionAddress(SectionPimpl); +inline error_code SectionRef::getAddress(uint64_t &Result) const { + return OwningObject->getSectionAddress(SectionPimpl, Result); } -inline uint64_t SectionRef::getSize() const { - return OwningObject->getSectionSize(SectionPimpl); +inline error_code SectionRef::getSize(uint64_t &Result) const { + return OwningObject->getSectionSize(SectionPimpl, Result); } -inline StringRef SectionRef::getContents() const { - return OwningObject->getSectionContents(SectionPimpl); +inline error_code SectionRef::getContents(StringRef &Result) const { + return OwningObject->getSectionContents(SectionPimpl, Result); } -inline bool SectionRef::isText() const { - return OwningObject->isSectionText(SectionPimpl); +inline error_code SectionRef::isText(bool &Result) const { + return OwningObject->isSectionText(SectionPimpl, Result); } } // end namespace object diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 60fc880d7c7..18aad9a9517 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -25,74 +25,165 @@ using support::ulittle32_t; using support::little16_t; } -SymbolRef COFFObjectFile::getSymbolNext(DataRefImpl Symb) const { - const coff_symbol *symb = reinterpret_cast(Symb.p); +namespace { +// Returns false if size is greater than the buffer size. And sets ec. +bool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) { + if (m->getBufferSize() < size) { + ec = object_error::unexpected_eof; + return false; + } + return true; +} + +// Returns false if any bytes in [addr, addr + size) fall outsize of m. +bool checkAddr(const MemoryBuffer *m, + error_code &ec, + uintptr_t addr, + uint64_t size) { + if (addr + size < addr || + addr + size < size || + addr + size > uintptr_t(m->getBufferEnd())) { + ec = object_error::unexpected_eof; + return false; + } + return true; +} +} + +const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const { + const coff_symbol *addr = reinterpret_cast(Symb.p); + +# ifndef NDEBUG + // Verify that the symbol points to a valid entry in the symbol table. + uintptr_t offset = uintptr_t(addr) - uintptr_t(base()); + if (offset < Header->PointerToSymbolTable + || offset >= Header->PointerToSymbolTable + + (Header->NumberOfSymbols * sizeof(coff_symbol))) + report_fatal_error("Symbol was outside of symbol table."); + + assert((offset - Header->PointerToSymbolTable) % sizeof(coff_symbol) + == 0 && "Symbol did not point to the beginning of a symbol"); +# endif + + return addr; +} + +const coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const { + const coff_section *addr = reinterpret_cast(Sec.p); + +# ifndef NDEBUG + // Verify that the section points to a valid entry in the section table. + if (addr < SectionTable + || addr >= (SectionTable + Header->NumberOfSections)) + report_fatal_error("Section was outside of section table."); + + uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable); + assert(offset % sizeof(coff_section) == 0 && + "Section did not point to the beginning of a section"); +# endif + + return addr; +} + +error_code COFFObjectFile::getSymbolNext(DataRefImpl Symb, + SymbolRef &Result) const { + const coff_symbol *symb = toSymb(Symb); symb += 1 + symb->NumberOfAuxSymbols; - Symb.p = reinterpret_cast(symb); - return SymbolRef(Symb, this); + Symb.p = reinterpret_cast(symb); + Result = SymbolRef(Symb, this); + return object_error::success; } -StringRef COFFObjectFile::getSymbolName(DataRefImpl Symb) const { - const coff_symbol *symb = reinterpret_cast(Symb.p); + error_code COFFObjectFile::getSymbolName(DataRefImpl Symb, + StringRef &Result) const { + const coff_symbol *symb = toSymb(Symb); // Check for string table entry. First 4 bytes are 0. if (symb->Name.Offset.Zeroes == 0) { uint32_t Offset = symb->Name.Offset.Offset; - return StringRef(getString(Offset)); + if (error_code ec = getString(Offset, Result)) + return ec; + return object_error::success; } if (symb->Name.ShortName[7] == 0) // Null terminated, let ::strlen figure out the length. - return StringRef(symb->Name.ShortName); - // Not null terminated, use all 8 bytes. - return StringRef(symb->Name.ShortName, 8); + Result = StringRef(symb->Name.ShortName); + else + // Not null terminated, use all 8 bytes. + Result = StringRef(symb->Name.ShortName, 8); + return object_error::success; } -uint64_t COFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { - const coff_symbol *symb = reinterpret_cast(Symb.p); - const coff_section *Section = getSection(symb->SectionNumber); - char Type = getSymbolNMTypeChar(Symb); +error_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb, + uint64_t &Result) const { + const coff_symbol *symb = toSymb(Symb); + const coff_section *Section; + if (error_code ec = getSection(symb->SectionNumber, Section)) + return ec; + char Type; + if (error_code ec = getSymbolNMTypeChar(Symb, Type)) + return ec; if (Type == 'U' || Type == 'w') - return UnknownAddressOrSize; - if (Section) - return Section->VirtualAddress + symb->Value; - return symb->Value; + Result = UnknownAddressOrSize; + else if (Section) + Result = Section->VirtualAddress + symb->Value; + else + Result = symb->Value; + return object_error::success; } -uint64_t COFFObjectFile::getSymbolSize(DataRefImpl Symb) const { +error_code COFFObjectFile::getSymbolSize(DataRefImpl Symb, + uint64_t &Result) const { // FIXME: Return the correct size. This requires looking at all the symbols // in the same section as this symbol, and looking for either the next // symbol, or the end of the section. - const coff_symbol *symb = reinterpret_cast(Symb.p); - const coff_section *Section = getSection(symb->SectionNumber); - char Type = getSymbolNMTypeChar(Symb); + const coff_symbol *symb = toSymb(Symb); + const coff_section *Section; + if (error_code ec = getSection(symb->SectionNumber, Section)) + return ec; + char Type; + if (error_code ec = getSymbolNMTypeChar(Symb, Type)) + return ec; if (Type == 'U' || Type == 'w') - return UnknownAddressOrSize; - if (Section) - return Section->SizeOfRawData - symb->Value; - return 0; + Result = UnknownAddressOrSize; + else if (Section) + Result = Section->SizeOfRawData - symb->Value; + else + Result = 0; + return object_error::success; } -char COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb) const { - const coff_symbol *symb = reinterpret_cast(Symb.p); - char ret = StringSwitch(getSymbolName(Symb)) +error_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, + char &Result) const { + const coff_symbol *symb = toSymb(Symb); + StringRef name; + if (error_code ec = getSymbolName(Symb, name)) + return ec; + char ret = StringSwitch(name) .StartsWith(".debug", 'N') .StartsWith(".sxdata", 'N') .Default('?'); - if (ret != '?') - return ret; + if (ret != '?') { + Result = ret; + return object_error::success; + } uint32_t Characteristics = 0; - if (const coff_section *Section = getSection(symb->SectionNumber)) { + if (symb->SectionNumber > 0) { + const coff_section *Section; + if (error_code ec = getSection(symb->SectionNumber, Section)) + return ec; Characteristics = Section->Characteristics; } switch (symb->SectionNumber) { case COFF::IMAGE_SYM_UNDEFINED: // Check storage classes. - if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) - return 'w'; // Don't do ::toupper. - else + if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) { + Result = 'w'; + return object_error::success; // Don't do ::toupper. + } else ret = 'u'; break; case COFF::IMAGE_SYM_ABSOLUTE: @@ -124,22 +215,28 @@ char COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb) const { if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) ret = ::toupper(ret); - return ret; + Result = ret; + return object_error::success; } -bool COFFObjectFile::isSymbolInternal(DataRefImpl Symb) const { - return false; +error_code COFFObjectFile::isSymbolInternal(DataRefImpl Symb, + bool &Result) const { + Result = false; + return object_error::success; } -SectionRef COFFObjectFile::getSectionNext(DataRefImpl Sec) const { - const coff_section *sec = reinterpret_cast(Sec.p); +error_code COFFObjectFile::getSectionNext(DataRefImpl Sec, + SectionRef &Result) const { + const coff_section *sec = toSec(Sec); sec += 1; - Sec.p = reinterpret_cast(sec); - return SectionRef(Sec, this); + Sec.p = reinterpret_cast(sec); + Result = SectionRef(Sec, this); + return object_error::success; } -StringRef COFFObjectFile::getSectionName(DataRefImpl Sec) const { - const coff_section *sec = reinterpret_cast(Sec.p); +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. @@ -152,66 +249,117 @@ StringRef COFFObjectFile::getSectionName(DataRefImpl Sec) const { if (name[0] == '/') { uint32_t Offset; name.substr(1).getAsInteger(10, Offset); - return StringRef(getString(Offset)); + if (error_code ec = getString(Offset, name)) + return ec; } - // It's just a normal name. - return name; + Result = name; + return object_error::success; } -uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Sec) const { - const coff_section *sec = reinterpret_cast(Sec.p); - return sec->VirtualAddress; +error_code COFFObjectFile::getSectionAddress(DataRefImpl Sec, + uint64_t &Result) const { + const coff_section *sec = toSec(Sec); + Result = sec->VirtualAddress; + return object_error::success; } -uint64_t COFFObjectFile::getSectionSize(DataRefImpl Sec) const { - const coff_section *sec = reinterpret_cast(Sec.p); - return sec->SizeOfRawData; +error_code COFFObjectFile::getSectionSize(DataRefImpl Sec, + uint64_t &Result) const { + const coff_section *sec = toSec(Sec); + Result = sec->SizeOfRawData; + return object_error::success; } -StringRef COFFObjectFile::getSectionContents(DataRefImpl Sec) const { - const coff_section *sec = reinterpret_cast(Sec.p); - return StringRef(reinterpret_cast(base() - + sec->PointerToRawData), - sec->SizeOfRawData); +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; } -bool COFFObjectFile::isSectionText(DataRefImpl Sec) const { - const coff_section *sec = reinterpret_cast(Sec.p); - return sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; +error_code COFFObjectFile::isSectionText(DataRefImpl Sec, + bool &Result) const { + const coff_section *sec = toSec(Sec); + Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; + return object_error::success; } COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) : ObjectFile(Binary::isCOFF, Object, ec) { + // Check that we at least have enough room for a header. + if (!checkSize(Data, ec, sizeof(coff_file_header))) return; - HeaderOff = 0; + // The actual starting location of the COFF header in the file. This can be + // non-zero in PE/COFF files. + uint64_t HeaderStart = 0; + // Check if this is a PE/COFF file. 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(base() + 0x3c); - HeaderOff += 4; + if (!checkSize(Data, ec, 0x3c + 8)) return; + HeaderStart += *reinterpret_cast(base() + 0x3c); + // Check the PE header. ("PE\0\0") + if (StringRef(reinterpret_cast(base() + HeaderStart), 4) + != "PE\0\0") { + ec = object_error::parse_failed; + return; + } + HeaderStart += 4; // Skip the PE Header. } - Header = reinterpret_cast(base() + HeaderOff); + Header = reinterpret_cast(base() + HeaderStart); + if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header))) + return; + SectionTable = reinterpret_cast( base() - + HeaderOff + + HeaderStart + sizeof(coff_file_header) + Header->SizeOfOptionalHeader); + if (!checkAddr(Data, ec, uintptr_t(SectionTable), + Header->NumberOfSections * sizeof(coff_section))) + return; + SymbolTable = reinterpret_cast(base() - + Header->PointerToSymbolTable); + + 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 * 18; + + 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; + } + + ec = object_error::success; } ObjectFile::symbol_iterator COFFObjectFile::begin_symbols() const { DataRefImpl ret; - memset(&ret, 0, sizeof(DataRefImpl)); + std::memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(SymbolTable); return symbol_iterator(SymbolRef(ret, this)); } @@ -219,21 +367,21 @@ ObjectFile::symbol_iterator COFFObjectFile::begin_symbols() const { ObjectFile::symbol_iterator COFFObjectFile::end_symbols() const { // The symbol table ends where the string table begins. DataRefImpl ret; - memset(&ret, 0, sizeof(DataRefImpl)); + std::memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(StringTable); return symbol_iterator(SymbolRef(ret, this)); } ObjectFile::section_iterator COFFObjectFile::begin_sections() const { DataRefImpl ret; - memset(&ret, 0, sizeof(DataRefImpl)); + std::memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(SectionTable); return section_iterator(SectionRef(ret, this)); } ObjectFile::section_iterator COFFObjectFile::end_sections() const { DataRefImpl ret; - memset(&ret, 0, sizeof(DataRefImpl)); + std::memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(SectionTable + Header->NumberOfSections); return section_iterator(SectionRef(ret, this)); } @@ -264,18 +412,30 @@ unsigned COFFObjectFile::getArch() const { } } -const coff_section *COFFObjectFile::getSection(std::size_t index) const { - if (index > 0 && index <= Header->NumberOfSections) - return SectionTable + (index - 1); - return 0; +error_code COFFObjectFile::getSection(int32_t index, + const coff_section *&Result) const { + // Check for special index values. + if (index == COFF::IMAGE_SYM_UNDEFINED || + index == COFF::IMAGE_SYM_ABSOLUTE || + index == COFF::IMAGE_SYM_DEBUG) + Result = NULL; + else if (index > 0 && index <= Header->NumberOfSections) + // We already verified the section table data, so no need to check again. + Result = SectionTable + (index - 1); + else + return object_error::parse_failed; + return object_error::success; } -const char *COFFObjectFile::getString(std::size_t offset) const { - const ulittle32_t *StringTableSize = - reinterpret_cast(StringTable); - if (offset < *StringTableSize) - return StringTable + offset; - return 0; +error_code COFFObjectFile::getString(uint32_t offset, + StringRef &Result) const { + if (StringTableSize <= 4) + // Tried to get a string from an empty string table. + return object_error::parse_failed; + if (offset >= StringTableSize) + return object_error::unexpected_eof; + Result = StringRef(StringTable + offset); + return object_error::success; } namespace llvm { diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index 1c4dceaa35f..edf9824d3df 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -222,19 +222,19 @@ class ELFObjectFile : public ObjectFile { const char *getString(const Elf_Shdr *section, uint32_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; + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; + virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; + + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; public: ELFObjectFile(MemoryBuffer *Object, error_code &ec); @@ -269,8 +269,9 @@ void ELFObjectFile } template -SymbolRef ELFObjectFile - ::getSymbolNext(DataRefImpl Symb) const { +error_code ELFObjectFile + ::getSymbolNext(DataRefImpl Symb, + SymbolRef &Result) const { validateSymbol(Symb); const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; @@ -287,63 +288,80 @@ SymbolRef ELFObjectFile } } - return SymbolRef(Symb, this); + Result = SymbolRef(Symb, this); + return object_error::success; } template -StringRef ELFObjectFile - ::getSymbolName(DataRefImpl Symb) const { +error_code ELFObjectFile + ::getSymbolName(DataRefImpl Symb, + StringRef &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); if (symb->st_name == 0) { const Elf_Shdr *section = getSection(symb->st_shndx); if (!section) - return ""; - return getString(dot_shstrtab_sec, section->sh_name); + Result = ""; + else + Result = getString(dot_shstrtab_sec, section->sh_name); + return object_error::success; } // Use the default symbol table name section. - return getString(dot_strtab_sec, symb->st_name); + Result = getString(dot_strtab_sec, symb->st_name); + return object_error::success; } template -uint64_t ELFObjectFile - ::getSymbolAddress(DataRefImpl Symb) const { +error_code ELFObjectFile + ::getSymbolAddress(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section; switch (symb->st_shndx) { case ELF::SHN_COMMON: // Undefined symbols have no address yet. - case ELF::SHN_UNDEF: return UnknownAddressOrSize; - case ELF::SHN_ABS: return symb->st_value; + case ELF::SHN_UNDEF: + Result = UnknownAddressOrSize; + return object_error::success; + case ELF::SHN_ABS: + Result = symb->st_value; + return object_error::success; default: Section = getSection(symb->st_shndx); } switch (symb->getType()) { - case ELF::STT_SECTION: return Section ? Section->sh_addr - : UnknownAddressOrSize; + case ELF::STT_SECTION: + Result = Section ? Section->sh_addr : UnknownAddressOrSize; + return object_error::success; case ELF::STT_FUNC: case ELF::STT_OBJECT: case ELF::STT_NOTYPE: - return symb->st_value; - default: return UnknownAddressOrSize; + Result = symb->st_value; + return object_error::success; + default: + Result = UnknownAddressOrSize; + return object_error::success; } } template -uint64_t ELFObjectFile - ::getSymbolSize(DataRefImpl Symb) const { +error_code ELFObjectFile + ::getSymbolSize(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); if (symb->st_size == 0) - return UnknownAddressOrSize; - return symb->st_size; + Result = UnknownAddressOrSize; + Result = symb->st_size; + return object_error::success; } template -char ELFObjectFile - ::getSymbolNMTypeChar(DataRefImpl Symb) const { +error_code ELFObjectFile + ::getSymbolNMTypeChar(DataRefImpl Symb, + char &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section = getSection(symb->st_shndx); @@ -390,71 +408,91 @@ char ELFObjectFile ret = 'W'; } - if (ret == '?' && symb->getType() == ELF::STT_SECTION) - return StringSwitch(getSymbolName(Symb)) + if (ret == '?' && symb->getType() == ELF::STT_SECTION) { + StringRef name; + if (error_code ec = getSymbolName(Symb, name)) + return ec; + Result = StringSwitch(name) .StartsWith(".debug", 'N') .StartsWith(".note", 'n'); + return object_error::success; + } - return ret; + Result = ret; + return object_error::success; } template -bool ELFObjectFile - ::isSymbolInternal(DataRefImpl Symb) const { +error_code ELFObjectFile + ::isSymbolInternal(DataRefImpl Symb, + bool &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); if ( symb->getType() == ELF::STT_FILE || symb->getType() == ELF::STT_SECTION) - return true; - return false; + Result = true; + Result = false; + return object_error::success; } template -SectionRef ELFObjectFile - ::getSectionNext(DataRefImpl Sec) const { +error_code ELFObjectFile + ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const { const uint8_t *sec = reinterpret_cast(Sec.p); sec += Header->e_shentsize; Sec.p = reinterpret_cast(sec); - return SectionRef(Sec, this); + Result = SectionRef(Sec, this); + return object_error::success; } template -StringRef ELFObjectFile - ::getSectionName(DataRefImpl Sec) const { +error_code ELFObjectFile + ::getSectionName(DataRefImpl Sec, + StringRef &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); - return StringRef(getString(dot_shstrtab_sec, sec->sh_name)); + Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); + return object_error::success; } template -uint64_t ELFObjectFile - ::getSectionAddress(DataRefImpl Sec) const { +error_code ELFObjectFile + ::getSectionAddress(DataRefImpl Sec, + uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); - return sec->sh_addr; + Result = sec->sh_addr; + return object_error::success; } template -uint64_t ELFObjectFile - ::getSectionSize(DataRefImpl Sec) const { +error_code ELFObjectFile + ::getSectionSize(DataRefImpl Sec, + uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); - return sec->sh_size; + Result = sec->sh_size; + return object_error::success; } template -StringRef ELFObjectFile - ::getSectionContents(DataRefImpl Sec) const { +error_code ELFObjectFile + ::getSectionContents(DataRefImpl Sec, + StringRef &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); - const char *start = (char*)base() + sec->sh_offset; - return StringRef(start, sec->sh_size); + const char *start = (const char*)base() + sec->sh_offset; + Result = StringRef(start, sec->sh_size); + return object_error::success; } template -bool ELFObjectFile - ::isSectionText(DataRefImpl Sec) const { +error_code ELFObjectFile + ::isSectionText(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast(Sec.p); if (sec->sh_flags & ELF::SHF_EXECINSTR) - return true; - return false; + Result = true; + else + Result = false; + return object_error::success; } template diff --git a/lib/Object/Error.cpp b/lib/Object/Error.cpp index 40f97d48a1d..25946257ab5 100644 --- a/lib/Object/Error.cpp +++ b/lib/Object/Error.cpp @@ -37,6 +37,8 @@ std::string _object_error_category::message(int ev) const { return "The file was not recognized as a valid object file"; case object_error::parse_failed: return "Invalid data was encountered while parsing the file"; + case object_error::unexpected_eof: + return "The end of the file was unexpectedly encountered"; default: llvm_unreachable("An enumerator of object_error does not have a message " "defined."); diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 3b76c6f7be5..71f1f8cf4b7 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -47,19 +47,19 @@ public: virtual unsigned getArch() 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; + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; + virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; + + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; private: MachOObject *MachOObj; @@ -115,29 +115,38 @@ void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, } -SymbolRef MachOObjectFile::getSymbolNext(DataRefImpl DRI) const { +error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, + SymbolRef &Result) const { DRI.d.b++; moveToNextSymbol(DRI); - return SymbolRef(DRI, this); + Result = SymbolRef(DRI, this); + return object_error::success; } -StringRef MachOObjectFile::getSymbolName(DataRefImpl DRI) const { +error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, + StringRef &Result) const { InMemoryStruct Entry; getSymbolTableEntry(DRI, Entry); - return MachOObj->getStringAtIndex(Entry->StringIndex); + Result = MachOObj->getStringAtIndex(Entry->StringIndex); + return object_error::success; } -uint64_t MachOObjectFile::getSymbolAddress(DataRefImpl DRI) const { +error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, + uint64_t &Result) const { InMemoryStruct Entry; getSymbolTableEntry(DRI, Entry); - return Entry->Value; + Result = Entry->Value; + return object_error::success; } -uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const { - return UnknownAddressOrSize; +error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, + uint64_t &Result) const { + Result = UnknownAddressOrSize; + return object_error::success; } -char MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI) const { +error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, + char &Result) const { InMemoryStruct Entry; getSymbolTableEntry(DRI, Entry); @@ -157,13 +166,16 @@ char MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI) const { if (Entry->Flags & (macho::STF_External | macho::STF_PrivateExtern)) Char = toupper(Char); - return Char; + Result = Char; + return object_error::success; } -bool MachOObjectFile::isSymbolInternal(DataRefImpl DRI) const { +error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI, + bool &Result) const { InMemoryStruct Entry; getSymbolTableEntry(DRI, Entry); - return Entry->Flags & macho::STF_StabsEntryMask; + Result = Entry->Flags & macho::STF_StabsEntryMask; + return object_error::success; } ObjectFile::symbol_iterator MachOObjectFile::begin_symbols() const { @@ -205,10 +217,12 @@ void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { } } -SectionRef MachOObjectFile::getSectionNext(DataRefImpl DRI) const { +error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, + SectionRef &Result) const { DRI.d.b++; moveToNextSection(DRI); - return SectionRef(DRI, this); + Result = SectionRef(DRI, this); + return object_error::success; } void @@ -220,43 +234,53 @@ MachOObjectFile::getSection(DataRefImpl DRI, MachOObj->ReadSection(LCI, DRI.d.b, Res); } -StringRef MachOObjectFile::getSectionName(DataRefImpl DRI) const { +error_code MachOObjectFile::getSectionName(DataRefImpl DRI, + StringRef &Result) const { InMemoryStruct SLC; LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); MachOObj->ReadSegmentLoadCommand(LCI, SLC); InMemoryStruct Sect; MachOObj->ReadSection(LCI, DRI.d.b, Sect); - static char Result[34]; - strcpy(Result, SLC->Name); - strcat(Result, ","); - strcat(Result, Sect->Name); - return StringRef(Result); + static char result[34]; + strcpy(result, SLC->Name); + strcat(result, ","); + strcat(result, Sect->Name); + Result = StringRef(result); + return object_error::success; } -uint64_t MachOObjectFile::getSectionAddress(DataRefImpl DRI) const { +error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, + uint64_t &Result) const { InMemoryStruct Sect; getSection(DRI, Sect); - return Sect->Address; + Result = Sect->Address; + return object_error::success; } -uint64_t MachOObjectFile::getSectionSize(DataRefImpl DRI) const { +error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, + uint64_t &Result) const { InMemoryStruct Sect; getSection(DRI, Sect); - return Sect->Size; + Result = Sect->Size; + return object_error::success; } -StringRef MachOObjectFile::getSectionContents(DataRefImpl DRI) const { +error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, + StringRef &Result) const { InMemoryStruct Sect; getSection(DRI, Sect); - return MachOObj->getData(Sect->Offset, Sect->Size); + Result = MachOObj->getData(Sect->Offset, Sect->Size); + return object_error::success; } -bool MachOObjectFile::isSectionText(DataRefImpl DRI) const { +error_code MachOObjectFile::isSectionText(DataRefImpl DRI, + bool &Result) const { InMemoryStruct SLC; LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); MachOObj->ReadSegmentLoadCommand(LCI, SLC); - return !strcmp(SLC->Name, "__TEXT"); + Result = !strcmp(SLC->Name, "__TEXT"); + return object_error::success; } ObjectFile::section_iterator MachOObjectFile::begin_sections() const { diff --git a/lib/Object/Object.cpp b/lib/Object/Object.cpp index 603b23c74e9..9a373ad21bd 100644 --- a/lib/Object/Object.cpp +++ b/lib/Object/Object.cpp @@ -41,19 +41,28 @@ LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef ObjectFile, } void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { - // We can't use unwrap() here because the argument to ++ must be an lvalue. - ++*reinterpret_cast(SI); + error_code ec; + unwrap(SI)->increment(ec); + if (ec) report_fatal_error("LLVMMoveToNextSection failed: " + ec.message()); } const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) { - return (*unwrap(SI))->getName().data(); + StringRef ret; + if (error_code ec = (*unwrap(SI))->getName(ret)) + report_fatal_error(ec.message()); + return ret.data(); } uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) { - return (*unwrap(SI))->getSize(); + uint64_t ret; + if (error_code ec = (*unwrap(SI))->getSize(ret)) + report_fatal_error(ec.message()); + return ret; } const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) { - return (*unwrap(SI))->getContents().data(); + StringRef ret; + if (error_code ec = (*unwrap(SI))->getContents(ret)) + report_fatal_error(ec.message()); + return ret.data(); } - diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index f6eb33c9e62..014cb296500 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -143,6 +143,14 @@ namespace { StringRef CurrentFilename; typedef std::vector SymbolListT; SymbolListT SymbolList; + + bool error(error_code ec) { + if (!ec) return false; + + outs() << ToolName << ": error reading file: " << ec.message() << ".\n"; + outs().flush(); + return true; + } } static void SortAndPrintSymbolList() { @@ -261,19 +269,25 @@ static void DumpSymbolNamesFromModule(Module *M) { } static void DumpSymbolNamesFromObject(ObjectFile *obj) { + error_code ec; for (ObjectFile::symbol_iterator i = obj->begin_symbols(), - e = obj->end_symbols(); i != e; ++i) { - if (!DebugSyms && i->isInternal()) + e = obj->end_symbols(); + i != e; i.increment(ec)) { + if (error(ec)) break; + bool internal; + if (error(i->isInternal(internal))) break; + if (!DebugSyms && internal) continue; NMSymbol s; s.Size = object::UnknownAddressOrSize; s.Address = object::UnknownAddressOrSize; - if (PrintSize || SizeSort) - s.Size = i->getSize(); + if (PrintSize || SizeSort) { + if (error(i->getSize(s.Size))) break; + } if (PrintAddress) - s.Address = i->getAddress(); - s.TypeChar = i->getNMTypeChar(); - s.Name = i->getName(); + if (error(i->getAddress(s.Address))) break; + if (error(i->getNMTypeChar(s.TypeChar))) break; + if (error(i->getName(s.Name))) break; SymbolList.push_back(s); } diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index a17624aa3dc..c971e49d04c 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -69,6 +69,14 @@ namespace { "see -version for available targets")); StringRef ToolName; + + bool error(error_code ec) { + if (!ec) return false; + + outs() << ToolName << ": error reading file: " << ec.message() << ".\n"; + outs().flush(); + return true; + } } static const Target *GetTarget(const ObjectFile *Obj = NULL) { @@ -161,12 +169,18 @@ static void DisassembleInput(const StringRef &Filename) { outs() << Filename << ":\tfile format " << Obj->getFileFormatName() << "\n\n\n"; + error_code ec; for (ObjectFile::section_iterator i = Obj->begin_sections(), e = Obj->end_sections(); - i != e; ++i) { - if (!i->isText()) - continue; - outs() << "Disassembly of section " << i->getName() << ":\n\n"; + i != e; i.increment(ec)) { + if (error(ec)) break; + bool text; + if (error(i->isText(text))) break; + if (!text) continue; + + StringRef name; + if (error(i->getName(name))) break; + outs() << "Disassembly of section " << name << ":\n\n"; // Set up disassembler. OwningPtr AsmInfo(TheTarget->createAsmInfo(TripleName)); @@ -202,7 +216,8 @@ static void DisassembleInput(const StringRef &Filename) { return; } - StringRef Bytes = i->getContents(); + StringRef Bytes; + if (error(i->getContents(Bytes))) break; StringRefMemoryObject memoryObject(Bytes); uint64_t Size; uint64_t Index; @@ -217,7 +232,9 @@ static void DisassembleInput(const StringRef &Filename) { # endif if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, DebugOut)) { - outs() << format("%8x:\t", i->getAddress() + Index); + uint64_t addr; + if (error(i->getAddress(addr))) break; + outs() << format("%8x:\t", addr + Index); DumpBytes(StringRef(Bytes.data() + Index, Size)); IP->printInst(&Inst, outs()); outs() << "\n"; -- 2.11.0