summaryrefslogtreecommitdiffstats
path: root/lib/Object
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2011-07-17 15:36:56 +0000
committerdim <dim@FreeBSD.org>2011-07-17 15:36:56 +0000
commit1176aa52646fe641a4243a246aa7f960c708a274 (patch)
treec8086addb211fa670a9d2b1038d8c2e453229755 /lib/Object
parentece02cd5829cea836e9365b0845a8ef042d17b0a (diff)
downloadFreeBSD-src-1176aa52646fe641a4243a246aa7f960c708a274.zip
FreeBSD-src-1176aa52646fe641a4243a246aa7f960c708a274.tar.gz
Vendor import of llvm trunk r135360:
http://llvm.org/svn/llvm-project/llvm/trunk@135360
Diffstat (limited to 'lib/Object')
-rw-r--r--lib/Object/Binary.cpp96
-rw-r--r--lib/Object/CMakeLists.txt6
-rw-r--r--lib/Object/COFFObjectFile.cpp433
-rw-r--r--lib/Object/ELFObjectFile.cpp214
-rw-r--r--lib/Object/Error.cpp57
-rw-r--r--lib/Object/MachOObjectFile.cpp278
-rw-r--r--lib/Object/Object.cpp21
-rw-r--r--lib/Object/ObjectFile.cpp14
8 files changed, 767 insertions, 352 deletions
diff --git a/lib/Object/Binary.cpp b/lib/Object/Binary.cpp
new file mode 100644
index 0000000..4b31c75
--- /dev/null
+++ b/lib/Object/Binary.cpp
@@ -0,0 +1,96 @@
+//===- Binary.cpp - A generic binary file -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Binary class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/Binary.h"
+#include "llvm/ADT/StringRef.h"
+#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;
+
+Binary::~Binary() {
+ delete Data;
+}
+
+Binary::Binary(unsigned int Type, MemoryBuffer *Source)
+ : TypeID(Type)
+ , Data(Source) {}
+
+StringRef Binary::getData() const {
+ return Data->getBuffer();
+}
+
+StringRef Binary::getFileName() const {
+ return Data->getBufferIdentifier();
+}
+
+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;
+ }
+}
+
+error_code object::createBinary(StringRef Path, OwningPtr<Binary> &Result) {
+ OwningPtr<MemoryBuffer> File;
+ if (error_code ec = MemoryBuffer::getFile(Path, File))
+ return ec;
+ return createBinary(File.take(), Result);
+}
diff --git a/lib/Object/CMakeLists.txt b/lib/Object/CMakeLists.txt
index 642a8ec..68e5e94 100644
--- a/lib/Object/CMakeLists.txt
+++ b/lib/Object/CMakeLists.txt
@@ -1,8 +1,10 @@
add_llvm_library(LLVMObject
+ Binary.cpp
+ COFFObjectFile.cpp
+ ELFObjectFile.cpp
+ Error.cpp
MachOObject.cpp
MachOObjectFile.cpp
Object.cpp
ObjectFile.cpp
- COFFObjectFile.cpp
- ELFObjectFile.cpp
)
diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp
index 86bf44b..07de6bc 100644
--- a/lib/Object/COFFObjectFile.cpp
+++ b/lib/Object/COFFObjectFile.cpp
@@ -11,11 +11,9 @@
//
//===----------------------------------------------------------------------===//
+#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;
@@ -28,174 +26,164 @@ 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;
-};
+// 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;
}
-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;
-};
+// 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;
+}
}
-extern char coff_coff_symbol_layout_static_assert
- [sizeof(coff_symbol) == 18 ? 1 : -1];
+const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const {
+ const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p);
-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;
-};
+# 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;
}
-extern char coff_coff_section_layout_static_assert
- [sizeof(coff_section) == 40 ? 1 : -1];
+const coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const {
+ const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p);
-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);
+# 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<intptr_t>(symb);
- return SymbolRef(Symb, this);
+ Symb.p = reinterpret_cast<uintptr_t>(symb);
+ Result = SymbolRef(Symb, this);
+ return object_error::success;
}
-StringRef COFFObjectFile::getSymbolName(DataRefImpl Symb) const {
- const coff_symbol *symb = reinterpret_cast<const coff_symbol*>(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<const coff_symbol*>(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 = NULL;
+ 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<const coff_symbol*>(Symb.p);
- const coff_section *Section = getSection(symb->SectionNumber);
- char Type = getSymbolNMTypeChar(Symb);
+ const coff_symbol *symb = toSymb(Symb);
+ const coff_section *Section = NULL;
+ 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<const coff_symbol*>(Symb.p);
- char ret = StringSwitch<char>(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<char>(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 = NULL;
+ 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:
@@ -227,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<const coff_section*>(Sec.p);
+error_code COFFObjectFile::getSectionNext(DataRefImpl Sec,
+ SectionRef &Result) const {
+ const coff_section *sec = toSec(Sec);
sec += 1;
- Sec.p = reinterpret_cast<intptr_t>(sec);
- return SectionRef(Sec, this);
+ Sec.p = reinterpret_cast<uintptr_t>(sec);
+ Result = SectionRef(Sec, this);
+ return object_error::success;
}
-StringRef COFFObjectFile::getSectionName(DataRefImpl Sec) const {
- const coff_section *sec = reinterpret_cast<const coff_section*>(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.
@@ -255,64 +249,124 @@ 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;
+}
+
+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::getSectionAddress(DataRefImpl Sec) const {
- const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p);
- return sec->VirtualAddress;
+error_code COFFObjectFile::getSectionSize(DataRefImpl Sec,
+ uint64_t &Result) const {
+ const coff_section *sec = toSec(Sec);
+ Result = sec->SizeOfRawData;
+ return object_error::success;
}
-uint64_t COFFObjectFile::getSectionSize(DataRefImpl Sec) const {
- const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p);
- return 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<const char*>(con_start),
+ sec->SizeOfRawData);
+ return object_error::success;
}
-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),
- sec->SizeOfRawData);
+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;
}
-bool COFFObjectFile::isSectionText(DataRefImpl Sec) const {
- const coff_section *sec = reinterpret_cast<const coff_section*>(Sec.p);
- return sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
+error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec,
+ DataRefImpl Symb,
+ bool &Result) const {
+ // FIXME: Unimplemented.
+ Result = false;
+ return object_error::success;
}
-COFFObjectFile::COFFObjectFile(MemoryBuffer *Object)
- : ObjectFile(Object) {
+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;
- if (base[0] == 0x4d && base[1] == 0x5a) {
+ // 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<const ulittle32_t *>(base + 0x3c);
- HeaderOff += 4;
+ if (!checkSize(Data, ec, 0x3c + 8)) return;
+ HeaderStart += *reinterpret_cast<const ulittle32_t *>(base() + 0x3c);
+ // Check the PE header. ("PE\0\0")
+ if (std::memcmp(base() + HeaderStart, "PE\0\0", 4) != 0) {
+ ec = object_error::parse_failed;
+ return;
+ }
+ HeaderStart += 4; // Skip the PE Header.
}
- Header = reinterpret_cast<const coff_file_header *>(base + HeaderOff);
+ Header = reinterpret_cast<const coff_file_header *>(base() + HeaderStart);
+ if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header)))
+ return;
+
SectionTable =
- reinterpret_cast<const coff_section *>( base
- + HeaderOff
+ reinterpret_cast<const coff_section *>( base()
+ + HeaderStart
+ sizeof(coff_file_header)
+ Header->SizeOfOptionalHeader);
+ if (!checkAddr(Data, ec, uintptr_t(SectionTable),
+ Header->NumberOfSections * sizeof(coff_section)))
+ return;
+
SymbolTable =
- reinterpret_cast<const coff_symbol *>(base + Header->PointerToSymbolTable);
+ reinterpret_cast<const coff_symbol *>(base()
+ + Header->PointerToSymbolTable);
+ if (!checkAddr(Data, ec, uintptr_t(SymbolTable),
+ Header->NumberOfSymbols * sizeof(coff_symbol)))
+ return;
// Find string table.
- StringTable = reinterpret_cast<const char *>(base)
- + Header->PointerToSymbolTable
- + Header->NumberOfSymbols * 18;
+ StringTable = reinterpret_cast<const char *>(base())
+ + Header->PointerToSymbolTable
+ + Header->NumberOfSymbols * sizeof(coff_symbol);
+ if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t)))
+ return;
+
+ StringTableSize = *reinterpret_cast<const ulittle32_t *>(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<intptr_t>(SymbolTable);
return symbol_iterator(SymbolRef(ret, this));
}
@@ -320,21 +374,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<intptr_t>(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<intptr_t>(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<intptr_t>(SectionTable + Header->NumberOfSections);
return section_iterator(SectionRef(ret, this));
}
@@ -365,24 +419,37 @@ 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<const ulittle32_t *>(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 {
ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {
- return new COFFObjectFile(Object);
+ error_code ec;
+ return new COFFObjectFile(Object, ec);
}
} // end namespace llvm
diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp
index d2a2726..e2ff4df 100644
--- a/lib/Object/ELFObjectFile.cpp
+++ b/lib/Object/ELFObjectFile.cpp
@@ -222,22 +222,24 @@ 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;
+ virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
+ bool &Result) const;
public:
- ELFObjectFile(MemoryBuffer *Object);
+ ELFObjectFile(MemoryBuffer *Object, error_code &ec);
virtual symbol_iterator begin_symbols() const;
virtual symbol_iterator end_symbols() const;
virtual section_iterator begin_sections() const;
@@ -259,9 +261,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.
@@ -269,8 +271,9 @@ void ELFObjectFile<target_endianness, is64Bits>
}
template<support::endianness target_endianness, bool is64Bits>
-SymbolRef ELFObjectFile<target_endianness, is64Bits>
- ::getSymbolNext(DataRefImpl Symb) const {
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::getSymbolNext(DataRefImpl Symb,
+ SymbolRef &Result) const {
validateSymbol(Symb);
const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b];
@@ -287,63 +290,80 @@ SymbolRef ELFObjectFile<target_endianness, is64Bits>
}
}
- return SymbolRef(Symb, this);
+ Result = SymbolRef(Symb, this);
+ return object_error::success;
}
template<support::endianness target_endianness, bool is64Bits>
-StringRef ELFObjectFile<target_endianness, is64Bits>
- ::getSymbolName(DataRefImpl Symb) const {
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::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<support::endianness target_endianness, bool is64Bits>
-uint64_t ELFObjectFile<target_endianness, is64Bits>
- ::getSymbolAddress(DataRefImpl Symb) const {
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::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<support::endianness target_endianness, bool is64Bits>
-uint64_t ELFObjectFile<target_endianness, is64Bits>
- ::getSymbolSize(DataRefImpl Symb) const {
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::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<support::endianness target_endianness, bool is64Bits>
-char ELFObjectFile<target_endianness, is64Bits>
- ::getSymbolNMTypeChar(DataRefImpl Symb) const {
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::getSymbolNMTypeChar(DataRefImpl Symb,
+ char &Result) const {
validateSymbol(Symb);
const Elf_Sym *symb = getSymbol(Symb);
const Elf_Shdr *Section = getSection(symb->st_shndx);
@@ -390,89 +410,120 @@ char ELFObjectFile<target_endianness, is64Bits>
ret = 'W';
}
- if (ret == '?' && symb->getType() == ELF::STT_SECTION)
- return StringSwitch<char>(getSymbolName(Symb))
+ if (ret == '?' && symb->getType() == ELF::STT_SECTION) {
+ StringRef name;
+ if (error_code ec = getSymbolName(Symb, name))
+ return ec;
+ Result = StringSwitch<char>(name)
.StartsWith(".debug", 'N')
.StartsWith(".note", 'n');
+ return object_error::success;
+ }
- return ret;
+ Result = ret;
+ return object_error::success;
}
template<support::endianness target_endianness, bool is64Bits>
-bool ELFObjectFile<target_endianness, is64Bits>
- ::isSymbolInternal(DataRefImpl Symb) const {
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::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<support::endianness target_endianness, bool is64Bits>
-SectionRef ELFObjectFile<target_endianness, is64Bits>
- ::getSectionNext(DataRefImpl Sec) const {
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const {
const uint8_t *sec = reinterpret_cast<const uint8_t *>(Sec.p);
sec += Header->e_shentsize;
Sec.p = reinterpret_cast<intptr_t>(sec);
- return SectionRef(Sec, this);
+ Result = SectionRef(Sec, this);
+ return object_error::success;
}
template<support::endianness target_endianness, bool is64Bits>
-StringRef ELFObjectFile<target_endianness, is64Bits>
- ::getSectionName(DataRefImpl Sec) const {
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::getSectionName(DataRefImpl Sec,
+ StringRef &Result) const {
const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(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<support::endianness target_endianness, bool is64Bits>
-uint64_t ELFObjectFile<target_endianness, is64Bits>
- ::getSectionAddress(DataRefImpl Sec) const {
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::getSectionAddress(DataRefImpl Sec,
+ uint64_t &Result) const {
const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
- return sec->sh_addr;
+ Result = sec->sh_addr;
+ return object_error::success;
}
template<support::endianness target_endianness, bool is64Bits>
-uint64_t ELFObjectFile<target_endianness, is64Bits>
- ::getSectionSize(DataRefImpl Sec) const {
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::getSectionSize(DataRefImpl Sec,
+ uint64_t &Result) const {
const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
- return sec->sh_size;
+ Result = sec->sh_size;
+ return object_error::success;
}
template<support::endianness target_endianness, bool is64Bits>
-StringRef ELFObjectFile<target_endianness, is64Bits>
- ::getSectionContents(DataRefImpl Sec) const {
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::getSectionContents(DataRefImpl Sec,
+ StringRef &Result) const {
const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(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<support::endianness target_endianness, bool is64Bits>
-bool ELFObjectFile<target_endianness, is64Bits>
- ::isSectionText(DataRefImpl Sec) const {
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::isSectionText(DataRefImpl Sec,
+ bool &Result) const {
const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
if (sec->sh_flags & ELF::SHF_EXECINSTR)
- return true;
- return false;
+ Result = true;
+ else
+ Result = false;
+ return object_error::success;
+}
+
+template<support::endianness target_endianness, bool is64Bits>
+error_code ELFObjectFile<target_endianness, is64Bits>
+ ::sectionContainsSymbol(DataRefImpl Sec,
+ DataRefImpl Symb,
+ bool &Result) const {
+ // FIXME: Unimplemented.
+ Result = false;
+ return object_error::success;
}
template<support::endianness target_endianness, bool is64Bits>
-ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object)
- : ObjectFile(Object)
+ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object
+ , error_code &ec)
+ : ObjectFile(Binary::isELF, Object, ec)
, 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 + MapFile->getBufferSize()))
+ <= base() + Data->getBufferSize()))
// FIXME: Proper error handling.
report_fatal_error("Section table goes past end of file!");
@@ -491,7 +542,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!");
@@ -509,7 +560,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!");
@@ -548,7 +599,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));
}
@@ -557,7 +608,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));
@@ -613,7 +664,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));
}
@@ -656,8 +707,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("Sybol name offset outside of string table!");
- return (const char *)base + section->sh_offset + offset;
+ report_fatal_error("Symbol name offset outside of string table!");
+ return (const char *)base() + section->sh_offset + offset;
}
// EI_CLASS, EI_DATA.
@@ -673,14 +724,15 @@ 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);
+ return new ELFObjectFile<support::little, false>(Object, ec);
else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB)
- return new ELFObjectFile<support::big, false>(Object);
+ return new ELFObjectFile<support::big, false>(Object, ec);
else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB)
- return new ELFObjectFile<support::little, true>(Object);
+ return new ELFObjectFile<support::little, true>(Object, ec);
else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB)
- return new ELFObjectFile<support::big, true>(Object);
+ return new ELFObjectFile<support::big, true>(Object, ec);
// FIXME: Proper error handling.
report_fatal_error("Not an ELF object file!");
}
diff --git a/lib/Object/Error.cpp b/lib/Object/Error.cpp
new file mode 100644
index 0000000..2594625
--- /dev/null
+++ b/lib/Object/Error.cpp
@@ -0,0 +1,57 @@
+//===- Error.cpp - system_error extensions for Object -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines a new error_category for the Object library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/Error.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+using namespace object;
+
+namespace {
+class _object_error_category : public _do_message {
+public:
+ virtual const char* name() const;
+ virtual std::string message(int ev) const;
+ virtual error_condition default_error_condition(int ev) const;
+};
+}
+
+const char *_object_error_category::name() const {
+ return "llvm.object";
+}
+
+std::string _object_error_category::message(int ev) const {
+ switch (ev) {
+ case object_error::success: return "Success";
+ case object_error::invalid_file_type:
+ 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.");
+ }
+}
+
+error_condition _object_error_category::default_error_condition(int ev) const {
+ if (ev == object_error::success)
+ return errc::success;
+ return errc::invalid_argument;
+}
+
+const error_category &object::object_category() {
+ static _object_error_category o;
+ return o;
+}
diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
index 877cbfb..26a6e13 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)
- : ObjectFile(Object),
+ MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec)
+ : ObjectFile(Binary::isMachO, Object, ec),
MachOObj(MOO),
RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {}
@@ -47,19 +47,21 @@ 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;
+ virtual error_code sectionContainsSymbol(DataRefImpl DRI, DataRefImpl S,
+ bool &Result) const;
private:
MachOObject *MachOObj;
@@ -68,16 +70,21 @@ private:
void moveToNextSection(DataRefImpl &DRI) const;
void getSymbolTableEntry(DataRefImpl DRI,
InMemoryStruct<macho::SymbolTableEntry> &Res) const;
+ void getSymbol64TableEntry(DataRefImpl DRI,
+ InMemoryStruct<macho::Symbol64TableEntry> &Res) const;
void moveToNextSymbol(DataRefImpl &DRI) const;
void getSection(DataRefImpl DRI, InMemoryStruct<macho::Section> &Res) const;
+ void getSection64(DataRefImpl DRI,
+ InMemoryStruct<macho::Section64> &Res) const;
};
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);
+ return new MachOObjectFile(Buffer, MachOObj, ec);
}
/*===-- Symbols -----------------------------------------------------------===*/
@@ -113,35 +120,81 @@ void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
Res);
}
+void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
+ InMemoryStruct<macho::Symbol64TableEntry> &Res) const {
+ InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
+ LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
+ MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
+
+ if (RegisteredStringTable != DRI.d.a) {
+ MachOObj->RegisterStringTable(*SymtabLoadCmd);
+ RegisteredStringTable = DRI.d.a;
+ }
+
+ MachOObj->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
+ Res);
+}
-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 {
- InMemoryStruct<macho::SymbolTableEntry> Entry;
- getSymbolTableEntry(DRI, Entry);
- return MachOObj->getStringAtIndex(Entry->StringIndex);
+error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
+ StringRef &Result) const {
+ if (MachOObj->is64Bit()) {
+ InMemoryStruct<macho::Symbol64TableEntry> Entry;
+ getSymbol64TableEntry(DRI, Entry);
+ Result = MachOObj->getStringAtIndex(Entry->StringIndex);
+ } else {
+ InMemoryStruct<macho::SymbolTableEntry> Entry;
+ getSymbolTableEntry(DRI, Entry);
+ Result = MachOObj->getStringAtIndex(Entry->StringIndex);
+ }
+ return object_error::success;
}
-uint64_t MachOObjectFile::getSymbolAddress(DataRefImpl DRI) const {
- InMemoryStruct<macho::SymbolTableEntry> Entry;
- getSymbolTableEntry(DRI, Entry);
- return Entry->Value;
+error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
+ uint64_t &Result) const {
+ if (MachOObj->is64Bit()) {
+ InMemoryStruct<macho::Symbol64TableEntry> Entry;
+ getSymbol64TableEntry(DRI, Entry);
+ Result = Entry->Value;
+ } else {
+ InMemoryStruct<macho::SymbolTableEntry> Entry;
+ getSymbolTableEntry(DRI, Entry);
+ 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 {
- InMemoryStruct<macho::SymbolTableEntry> Entry;
- getSymbolTableEntry(DRI, Entry);
+error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
+ char &Result) const {
+ uint8_t Type, Flags;
+ if (MachOObj->is64Bit()) {
+ InMemoryStruct<macho::Symbol64TableEntry> Entry;
+ getSymbol64TableEntry(DRI, Entry);
+ Type = Entry->Type;
+ Flags = Entry->Flags;
+ } else {
+ InMemoryStruct<macho::SymbolTableEntry> Entry;
+ getSymbolTableEntry(DRI, Entry);
+ Type = Entry->Type;
+ Flags = Entry->Flags;
+ }
char Char;
- switch (Entry->Type & macho::STF_TypeMask) {
+ switch (Type & macho::STF_TypeMask) {
case macho::STT_Undefined:
Char = 'u';
break;
@@ -154,15 +207,24 @@ char MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI) const {
break;
}
- if (Entry->Flags & (macho::STF_External | macho::STF_PrivateExtern))
+ if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
Char = toupper(Char);
- return Char;
+ Result = Char;
+ return object_error::success;
}
-bool MachOObjectFile::isSymbolInternal(DataRefImpl DRI) const {
- InMemoryStruct<macho::SymbolTableEntry> Entry;
- getSymbolTableEntry(DRI, Entry);
- return Entry->Flags & macho::STF_StabsEntryMask;
+error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI,
+ bool &Result) const {
+ if (MachOObj->is64Bit()) {
+ InMemoryStruct<macho::Symbol64TableEntry> Entry;
+ getSymbol64TableEntry(DRI, Entry);
+ Result = Entry->Flags & macho::STF_StabsEntryMask;
+ } else {
+ InMemoryStruct<macho::SymbolTableEntry> Entry;
+ getSymbolTableEntry(DRI, Entry);
+ Result = Entry->Flags & macho::STF_StabsEntryMask;
+ }
+ return object_error::success;
}
ObjectFile::symbol_iterator MachOObjectFile::begin_symbols() const {
@@ -204,10 +266,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
@@ -219,43 +283,121 @@ MachOObjectFile::getSection(DataRefImpl DRI,
MachOObj->ReadSection(LCI, DRI.d.b, Res);
}
-StringRef MachOObjectFile::getSectionName(DataRefImpl DRI) const {
- InMemoryStruct<macho::SegmentLoadCommand> SLC;
+void
+MachOObjectFile::getSection64(DataRefImpl DRI,
+ InMemoryStruct<macho::Section64> &Res) const {
+ InMemoryStruct<macho::Segment64LoadCommand> SLC;
LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
- MachOObj->ReadSegmentLoadCommand(LCI, SLC);
- InMemoryStruct<macho::Section> 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);
+ MachOObj->ReadSegment64LoadCommand(LCI, SLC);
+ MachOObj->ReadSection64(LCI, DRI.d.b, Res);
}
-uint64_t MachOObjectFile::getSectionAddress(DataRefImpl DRI) const {
- InMemoryStruct<macho::Section> Sect;
- getSection(DRI, Sect);
- return Sect->Address;
+static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
+ LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
+ if (LCI.Command.Type == macho::LCT_Segment64)
+ return true;
+ assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
+ return false;
}
-uint64_t MachOObjectFile::getSectionSize(DataRefImpl DRI) const {
- InMemoryStruct<macho::Section> Sect;
- getSection(DRI, Sect);
- return Sect->Size;
+error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
+ StringRef &Result) const {
+ // FIXME: thread safety.
+ static char result[34];
+ if (is64BitLoadCommand(MachOObj, DRI)) {
+ InMemoryStruct<macho::Segment64LoadCommand> SLC;
+ LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
+ MachOObj->ReadSegment64LoadCommand(LCI, SLC);
+ InMemoryStruct<macho::Section64> Sect;
+ MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
+
+ strcpy(result, Sect->SegmentName);
+ strcat(result, ",");
+ strcat(result, Sect->Name);
+ } else {
+ InMemoryStruct<macho::SegmentLoadCommand> SLC;
+ LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
+ MachOObj->ReadSegmentLoadCommand(LCI, SLC);
+ InMemoryStruct<macho::Section> Sect;
+ MachOObj->ReadSection(LCI, DRI.d.b, Sect);
+
+ strcpy(result, Sect->SegmentName);
+ strcat(result, ",");
+ strcat(result, Sect->Name);
+ }
+ Result = StringRef(result);
+ return object_error::success;
}
-StringRef MachOObjectFile::getSectionContents(DataRefImpl DRI) const {
- InMemoryStruct<macho::Section> Sect;
- getSection(DRI, Sect);
- return MachOObj->getData(Sect->Offset, Sect->Size);
+error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
+ uint64_t &Result) const {
+ if (is64BitLoadCommand(MachOObj, DRI)) {
+ InMemoryStruct<macho::Section64> Sect;
+ getSection64(DRI, Sect);
+ Result = Sect->Address;
+ } else {
+ InMemoryStruct<macho::Section> Sect;
+ getSection(DRI, Sect);
+ Result = Sect->Address;
+ }
+ return object_error::success;
}
-bool MachOObjectFile::isSectionText(DataRefImpl DRI) const {
- InMemoryStruct<macho::SegmentLoadCommand> SLC;
- LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
- MachOObj->ReadSegmentLoadCommand(LCI, SLC);
- return !strcmp(SLC->Name, "__TEXT");
+error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
+ uint64_t &Result) const {
+ if (is64BitLoadCommand(MachOObj, DRI)) {
+ InMemoryStruct<macho::Section64> Sect;
+ getSection64(DRI, Sect);
+ Result = Sect->Size;
+ } else {
+ InMemoryStruct<macho::Section> Sect;
+ getSection(DRI, Sect);
+ Result = Sect->Size;
+ }
+ return object_error::success;
+}
+
+error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
+ StringRef &Result) const {
+ if (is64BitLoadCommand(MachOObj, DRI)) {
+ InMemoryStruct<macho::Section64> Sect;
+ getSection64(DRI, Sect);
+ Result = MachOObj->getData(Sect->Offset, Sect->Size);
+ } else {
+ InMemoryStruct<macho::Section> Sect;
+ getSection(DRI, Sect);
+ Result = MachOObj->getData(Sect->Offset, Sect->Size);
+ }
+ return object_error::success;
+}
+
+error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
+ bool &Result) const {
+ if (is64BitLoadCommand(MachOObj, DRI)) {
+ InMemoryStruct<macho::Section64> Sect;
+ getSection64(DRI, Sect);
+ Result = !strcmp(Sect->Name, "__text");
+ } else {
+ InMemoryStruct<macho::Section> Sect;
+ getSection(DRI, Sect);
+ Result = !strcmp(Sect->Name, "__text");
+ }
+ return object_error::success;
+}
+
+error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
+ DataRefImpl Symb,
+ bool &Result) const {
+ if (MachOObj->is64Bit()) {
+ InMemoryStruct<macho::Symbol64TableEntry> Entry;
+ getSymbol64TableEntry(Symb, Entry);
+ Result = Entry->SectionIndex == 1 + Sec.d.a + Sec.d.b;
+ } else {
+ InMemoryStruct<macho::SymbolTableEntry> Entry;
+ getSymbolTableEntry(Symb, Entry);
+ Result = Entry->SectionIndex == 1 + Sec.d.a + Sec.d.b;
+ }
+ return object_error::success;
}
ObjectFile::section_iterator MachOObjectFile::begin_sections() const {
diff --git a/lib/Object/Object.cpp b/lib/Object/Object.cpp
index 603b23c..9a373ad 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<ObjectFile::section_iterator*>(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/lib/Object/ObjectFile.cpp b/lib/Object/ObjectFile.cpp
index 47b6311..a7798df 100644
--- a/lib/Object/ObjectFile.cpp
+++ b/lib/Object/ObjectFile.cpp
@@ -21,18 +21,8 @@
using namespace llvm;
using namespace object;
-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(unsigned int Type, MemoryBuffer *source, error_code &ec)
+ : Binary(Type, source) {
}
ObjectFile *ObjectFile::createObjectFile(MemoryBuffer *Object) {
OpenPOWER on IntegriCloud