summaryrefslogtreecommitdiffstats
path: root/lib/Object
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2012-04-14 13:54:10 +0000
committerdim <dim@FreeBSD.org>2012-04-14 13:54:10 +0000
commit1fc08f5e9ef733ef1ce6f363fecedc2260e78974 (patch)
tree19c69a04768629f2d440944b71cbe90adae0b615 /lib/Object
parent07637c87f826cdf411f0673595e9bc92ebd793f2 (diff)
downloadFreeBSD-src-1fc08f5e9ef733ef1ce6f363fecedc2260e78974.zip
FreeBSD-src-1fc08f5e9ef733ef1ce6f363fecedc2260e78974.tar.gz
Vendor import of llvm trunk r154661:
http://llvm.org/svn/llvm-project/llvm/trunk@r154661
Diffstat (limited to 'lib/Object')
-rw-r--r--lib/Object/Archive.cpp142
-rw-r--r--lib/Object/CMakeLists.txt5
-rw-r--r--lib/Object/COFFObjectFile.cpp295
-rw-r--r--lib/Object/ELFObjectFile.cpp1411
-rw-r--r--lib/Object/LLVMBuild.txt22
-rw-r--r--lib/Object/MachOObject.cpp35
-rw-r--r--lib/Object/MachOObjectFile.cpp694
-rw-r--r--lib/Object/Object.cpp150
-rw-r--r--lib/Object/ObjectFile.cpp4
9 files changed, 1195 insertions, 1563 deletions
diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp
index e2eaff5..c5f15ba 100644
--- a/lib/Object/Archive.cpp
+++ b/lib/Object/Archive.cpp
@@ -13,14 +13,15 @@
#include "llvm/Object/Archive.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/MemoryBuffer.h"
using namespace llvm;
using namespace object;
-namespace {
-const StringRef Magic = "!<arch>\n";
+static const char *Magic = "!<arch>\n";
+namespace {
struct ArchiveMemberHeader {
char Name[16];
char LastModified[12];
@@ -32,7 +33,11 @@ struct ArchiveMemberHeader {
///! Get the name without looking up long names.
StringRef getName() const {
- char EndCond = Name[0] == '/' ? ' ' : '/';
+ char EndCond;
+ if (Name[0] == '/' || Name[0] == '#')
+ EndCond = ' ';
+ else
+ EndCond = '/';
StringRef::size_type end = StringRef(Name, sizeof(Name)).find(EndCond);
if (end == StringRef::npos)
end = sizeof(Name);
@@ -47,12 +52,30 @@ struct ArchiveMemberHeader {
return ret.getZExtValue();
}
};
+}
-const ArchiveMemberHeader *ToHeader(const char *base) {
+static const ArchiveMemberHeader *ToHeader(const char *base) {
return reinterpret_cast<const ArchiveMemberHeader *>(base);
}
+
+
+static bool isInternalMember(const ArchiveMemberHeader &amh) {
+ const char *internals[] = {
+ "/",
+ "//",
+ "#_LLVM_SYM_TAB_#"
+ };
+
+ StringRef name = amh.getName();
+ for (std::size_t i = 0; i < sizeof(internals) / sizeof(*internals); ++i) {
+ if (name == internals[i])
+ return true;
+ }
+ return false;
}
+void Archive::anchor() { }
+
Archive::Child Archive::Child::getNext() const {
size_t SpaceToSkip = sizeof(ArchiveMemberHeader) +
ToHeader(Data.data())->getSize();
@@ -101,6 +124,11 @@ error_code Archive::Child::getName(StringRef &Result) const {
return object_error::parse_failed;
Result = addr;
return object_error::success;
+ } else if (name.startswith("#1/")) {
+ APInt name_size;
+ name.substr(3).getAsInteger(10, name_size);
+ Result = Data.substr(0, name_size.getZExtValue());
+ return object_error::success;
}
// It's a simple name.
if (name[name.size() - 1] == '/')
@@ -111,14 +139,27 @@ error_code Archive::Child::getName(StringRef &Result) const {
}
uint64_t Archive::Child::getSize() const {
- return ToHeader(Data.data())->getSize();
+ uint64_t size = ToHeader(Data.data())->getSize();
+ // Don't include attached name.
+ StringRef name = ToHeader(Data.data())->getName();
+ if (name.startswith("#1/")) {
+ APInt name_size;
+ name.substr(3).getAsInteger(10, name_size);
+ size -= name_size.getZExtValue();
+ }
+ return size;
}
MemoryBuffer *Archive::Child::getBuffer() const {
StringRef name;
if (getName(name)) return NULL;
- return MemoryBuffer::getMemBuffer(Data.substr(sizeof(ArchiveMemberHeader),
- getSize()),
+ int size = sizeof(ArchiveMemberHeader);
+ if (name.startswith("#1/")) {
+ APInt name_size;
+ name.substr(3).getAsInteger(10, name_size);
+ size += name_size.getZExtValue();
+ }
+ return MemoryBuffer::getMemBuffer(Data.substr(size, getSize()),
name,
false);
}
@@ -133,8 +174,7 @@ error_code Archive::Child::getAsBinary(OwningPtr<Binary> &Result) const {
}
Archive::Archive(MemoryBuffer *source, error_code &ec)
- : Binary(Binary::isArchive, source)
- , StringTable(Child(this, StringRef(0, 0))) {
+ : Binary(Binary::ID_Archive, source) {
// Check for sufficient magic.
if (!source || source->getBufferSize()
< (8 + sizeof(ArchiveMemberHeader) + 2) // Smallest archive.
@@ -143,30 +183,90 @@ Archive::Archive(MemoryBuffer *source, error_code &ec)
return;
}
- // Get the string table. It's the 3rd member.
- child_iterator StrTable = begin_children();
+ // Get the special members.
+ child_iterator i = begin_children(false);
child_iterator e = end_children();
- for (int i = 0; StrTable != e && i < 2; ++StrTable, ++i) {}
- // Check to see if there were 3 members, or the 3rd member wasn't named "//".
- StringRef name;
- if (StrTable != e && !StrTable->getName(name) && name == "//")
- StringTable = StrTable;
+ if (i != e) ++i; // Nobody cares about the first member.
+ if (i != e) {
+ SymbolTable = i;
+ ++i;
+ }
+ if (i != e) {
+ StringTable = i;
+ }
ec = object_error::success;
}
-Archive::child_iterator Archive::begin_children() const {
- const char *Loc = Data->getBufferStart() + Magic.size();
+Archive::child_iterator Archive::begin_children(bool skip_internal) const {
+ const char *Loc = Data->getBufferStart() + strlen(Magic);
size_t Size = sizeof(ArchiveMemberHeader) +
ToHeader(Loc)->getSize();
- return Child(this, StringRef(Loc, Size));
+ Child c(this, StringRef(Loc, Size));
+ // Skip internals at the beginning of an archive.
+ if (skip_internal && isInternalMember(*ToHeader(Loc)))
+ return c.getNext();
+ return c;
}
Archive::child_iterator Archive::end_children() const {
return Child(this, StringRef(0, 0));
}
-namespace llvm {
+error_code Archive::Symbol::getName(StringRef &Result) const {
+ Result =
+ StringRef(Parent->SymbolTable->getBuffer()->getBufferStart() + StringIndex);
+ return object_error::success;
+}
+
+error_code Archive::Symbol::getMember(child_iterator &Result) const {
+ const char *buf = Parent->SymbolTable->getBuffer()->getBufferStart();
+ uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
+ const char *offsets = buf + 4;
+ buf += 4 + (member_count * 4); // Skip offsets.
+ const char *indicies = buf + 4;
+
+ uint16_t offsetindex =
+ *(reinterpret_cast<const support::ulittle16_t*>(indicies)
+ + SymbolIndex);
+
+ uint32_t offset = *(reinterpret_cast<const support::ulittle32_t*>(offsets)
+ + (offsetindex - 1));
-} // end namespace llvm
+ const char *Loc = Parent->getData().begin() + offset;
+ size_t Size = sizeof(ArchiveMemberHeader) +
+ ToHeader(Loc)->getSize();
+ Result = Child(Parent, StringRef(Loc, Size));
+
+ return object_error::success;
+}
+
+Archive::Symbol Archive::Symbol::getNext() const {
+ Symbol t(*this);
+ // Go to one past next null.
+ t.StringIndex =
+ Parent->SymbolTable->getBuffer()->getBuffer().find('\0', t.StringIndex) + 1;
+ ++t.SymbolIndex;
+ return t;
+}
+
+Archive::symbol_iterator Archive::begin_symbols() const {
+ const char *buf = SymbolTable->getBuffer()->getBufferStart();
+ uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
+ buf += 4 + (member_count * 4); // Skip offsets.
+ uint32_t symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
+ buf += 4 + (symbol_count * 2); // Skip indices.
+ uint32_t string_start_offset =
+ buf - SymbolTable->getBuffer()->getBufferStart();
+ return symbol_iterator(Symbol(this, 0, string_start_offset));
+}
+
+Archive::symbol_iterator Archive::end_symbols() const {
+ const char *buf = SymbolTable->getBuffer()->getBufferStart();
+ uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
+ buf += 4 + (member_count * 4); // Skip offsets.
+ uint32_t symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf);
+ return symbol_iterator(
+ Symbol(this, symbol_count, 0));
+}
diff --git a/lib/Object/CMakeLists.txt b/lib/Object/CMakeLists.txt
index 86eb51a..c20fc0c 100644
--- a/lib/Object/CMakeLists.txt
+++ b/lib/Object/CMakeLists.txt
@@ -9,8 +9,3 @@ add_llvm_library(LLVMObject
Object.cpp
ObjectFile.cpp
)
-
-add_llvm_library_dependencies(LLVMObject
- LLVMCore
- LLVMSupport
- )
diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp
index 750c34d..bd27a56 100644
--- a/lib/Object/COFFObjectFile.cpp
+++ b/lib/Object/COFFObjectFile.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Object/COFF.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
@@ -98,24 +99,10 @@ error_code COFFObjectFile::getSymbolNext(DataRefImpl Symb,
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;
- 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.
- Result = StringRef(symb->Name.ShortName);
- else
- // Not null terminated, use all 8 bytes.
- Result = StringRef(symb->Name.ShortName, 8);
- return object_error::success;
+ return getSymbolName(symb, Result);
}
-error_code COFFObjectFile::getSymbolOffset(DataRefImpl Symb,
+error_code COFFObjectFile::getSymbolFileOffset(DataRefImpl Symb,
uint64_t &Result) const {
const coff_symbol *symb = toSymb(Symb);
const coff_section *Section = NULL;
@@ -127,7 +114,7 @@ error_code COFFObjectFile::getSymbolOffset(DataRefImpl Symb,
if (Type == 'U' || Type == 'w')
Result = UnknownAddressOrSize;
else if (Section)
- Result = Section->VirtualAddress + symb->Value;
+ Result = Section->PointerToRawData + symb->Value;
else
Result = symb->Value;
return object_error::success;
@@ -145,23 +132,21 @@ error_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb,
if (Type == 'U' || Type == 'w')
Result = UnknownAddressOrSize;
else if (Section)
- Result = reinterpret_cast<uintptr_t>(base() +
- Section->PointerToRawData +
- symb->Value);
+ Result = Section->VirtualAddress + symb->Value;
else
- Result = reinterpret_cast<uintptr_t>(base() + symb->Value);
+ Result = symb->Value;
return object_error::success;
}
error_code COFFObjectFile::getSymbolType(DataRefImpl Symb,
- SymbolRef::SymbolType &Result) const {
+ SymbolRef::Type &Result) const {
const coff_symbol *symb = toSymb(Symb);
Result = SymbolRef::ST_Other;
if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) {
- Result = SymbolRef::ST_External;
+ Result = SymbolRef::ST_Unknown;
} else {
- if (symb->Type.ComplexType == COFF::IMAGE_SYM_DTYPE_FUNCTION) {
+ if (symb->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) {
Result = SymbolRef::ST_Function;
} else {
char Type;
@@ -175,10 +160,27 @@ error_code COFFObjectFile::getSymbolType(DataRefImpl Symb,
return object_error::success;
}
-error_code COFFObjectFile::isSymbolGlobal(DataRefImpl Symb,
- bool &Result) const {
+error_code COFFObjectFile::getSymbolFlags(DataRefImpl Symb,
+ uint32_t &Result) const {
const coff_symbol *symb = toSymb(Symb);
- Result = (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL);
+ Result = SymbolRef::SF_None;
+
+ // TODO: Correctly set SF_FormatSpecific, SF_ThreadLocal, SF_Common
+
+ if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
+ symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED)
+ Result |= SymbolRef::SF_Undefined;
+
+ // TODO: This are certainly too restrictive.
+ if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL)
+ Result |= SymbolRef::SF_Global;
+
+ if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL)
+ Result |= SymbolRef::SF_Weak;
+
+ if (symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE)
+ Result |= SymbolRef::SF_Absolute;
+
return object_error::success;
}
@@ -233,7 +235,9 @@ error_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) {
Result = 'w';
return object_error::success; // Don't do ::toupper.
- } else
+ } else if (symb->Value != 0) // Check for common symbols.
+ ret = 'c';
+ else
ret = 'u';
break;
case COFF::IMAGE_SYM_ABSOLUTE:
@@ -269,9 +273,18 @@ error_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
return object_error::success;
}
-error_code COFFObjectFile::isSymbolInternal(DataRefImpl Symb,
- bool &Result) const {
- Result = false;
+error_code COFFObjectFile::getSymbolSection(DataRefImpl Symb,
+ section_iterator &Result) const {
+ const coff_symbol *symb = toSymb(Symb);
+ if (symb->SectionNumber <= COFF::IMAGE_SYM_UNDEFINED)
+ Result = end_sections();
+ else {
+ const coff_section *sec = 0;
+ if (error_code ec = getSection(symb->SectionNumber, sec)) return ec;
+ DataRefImpl Sec;
+ Sec.p = reinterpret_cast<uintptr_t>(sec);
+ Result = section_iterator(SectionRef(Sec, this));
+ }
return object_error::success;
}
@@ -287,24 +300,7 @@ error_code COFFObjectFile::getSectionNext(DataRefImpl Sec,
error_code COFFObjectFile::getSectionName(DataRefImpl Sec,
StringRef &Result) const {
const coff_section *sec = toSec(Sec);
- StringRef name;
- if (sec->Name[7] == 0)
- // Null terminated, let ::strlen figure out the length.
- name = sec->Name;
- else
- // Not null terminated, use all 8 bytes.
- name = StringRef(sec->Name, 8);
-
- // Check for string table entry. First byte is '/'.
- if (name[0] == '/') {
- uint32_t Offset;
- name.substr(1).getAsInteger(10, Offset);
- if (error_code ec = getString(Offset, name))
- return ec;
- }
-
- Result = name;
- return object_error::success;
+ return getSectionName(sec, Result);
}
error_code COFFObjectFile::getSectionAddress(DataRefImpl Sec,
@@ -324,16 +320,10 @@ error_code COFFObjectFile::getSectionSize(DataRefImpl Sec,
error_code COFFObjectFile::getSectionContents(DataRefImpl Sec,
StringRef &Result) const {
const coff_section *sec = toSec(Sec);
- // The only thing that we need to verify is that the contents is contained
- // within the file bounds. We don't need to make sure it doesn't cover other
- // data, as there's nothing that says that is not allowed.
- uintptr_t con_start = uintptr_t(base()) + sec->PointerToRawData;
- uintptr_t con_end = con_start + sec->SizeOfRawData;
- if (con_end >= uintptr_t(Data->getBufferEnd()))
- return object_error::parse_failed;
- Result = StringRef(reinterpret_cast<const char*>(con_start),
- sec->SizeOfRawData);
- return object_error::success;
+ ArrayRef<uint8_t> Res;
+ error_code EC = getSectionContents(sec, Res);
+ Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
+ return EC;
}
error_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec,
@@ -366,12 +356,33 @@ error_code COFFObjectFile::isSectionBSS(DataRefImpl Sec,
return object_error::success;
}
+error_code COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
+ bool &Result) const {
+ // FIXME: Unimplemented
+ Result = true;
+ return object_error::success;
+}
+
+error_code COFFObjectFile::isSectionVirtual(DataRefImpl Sec,
+ bool &Result) const {
+ const coff_section *sec = toSec(Sec);
+ Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
+ return object_error::success;
+}
+
+error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Sec,
+ bool &Result) const {
+ // FIXME: Unimplemented
+ Result = false;
+ return object_error::success;
+}
+
error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec,
DataRefImpl Symb,
bool &Result) const {
const coff_section *sec = toSec(Sec);
const coff_symbol *symb = toSymb(Symb);
- const coff_section *symb_sec;
+ const coff_section *symb_sec = 0;
if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec;
if (symb_sec == sec)
Result = true;
@@ -383,7 +394,6 @@ error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec,
relocation_iterator COFFObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
const coff_section *sec = toSec(Sec);
DataRefImpl ret;
- std::memset(&ret, 0, sizeof(ret));
if (sec->NumberOfRelocations == 0)
ret.p = 0;
else
@@ -395,7 +405,6 @@ relocation_iterator COFFObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
relocation_iterator COFFObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
const coff_section *sec = toSec(Sec);
DataRefImpl ret;
- std::memset(&ret, 0, sizeof(ret));
if (sec->NumberOfRelocations == 0)
ret.p = 0;
else
@@ -408,7 +417,12 @@ relocation_iterator COFFObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
}
COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
- : ObjectFile(Binary::isCOFF, Object, ec) {
+ : ObjectFile(Binary::ID_COFF, Object, ec)
+ , Header(0)
+ , SectionTable(0)
+ , SymbolTable(0)
+ , StringTable(0)
+ , StringTableSize(0) {
// Check that we at least have enough room for a header.
if (!checkSize(Data, ec, sizeof(coff_file_header))) return;
@@ -421,7 +435,7 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
// PE/COFF, seek through MS-DOS compatibility stub and 4-byte
// PE signature to find 'normal' COFF header.
if (!checkSize(Data, ec, 0x3c + 8)) return;
- HeaderStart += *reinterpret_cast<const ulittle32_t *>(base() + 0x3c);
+ HeaderStart = *reinterpret_cast<const ulittle16_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;
@@ -443,28 +457,30 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
Header->NumberOfSections * sizeof(coff_section)))
return;
- SymbolTable =
- reinterpret_cast<const coff_symbol *>(base()
- + Header->PointerToSymbolTable);
- if (!checkAddr(Data, ec, uintptr_t(SymbolTable),
- Header->NumberOfSymbols * sizeof(coff_symbol)))
- return;
+ if (Header->PointerToSymbolTable != 0) {
+ SymbolTable =
+ 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 * sizeof(coff_symbol);
- if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t)))
- return;
+ // Find string table.
+ 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;
+ 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;
@@ -472,7 +488,6 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
symbol_iterator COFFObjectFile::begin_symbols() const {
DataRefImpl ret;
- std::memset(&ret, 0, sizeof(DataRefImpl));
ret.p = reinterpret_cast<intptr_t>(SymbolTable);
return symbol_iterator(SymbolRef(ret, this));
}
@@ -480,21 +495,44 @@ symbol_iterator COFFObjectFile::begin_symbols() const {
symbol_iterator COFFObjectFile::end_symbols() const {
// The symbol table ends where the string table begins.
DataRefImpl ret;
- std::memset(&ret, 0, sizeof(DataRefImpl));
ret.p = reinterpret_cast<intptr_t>(StringTable);
return symbol_iterator(SymbolRef(ret, this));
}
+symbol_iterator COFFObjectFile::begin_dynamic_symbols() const {
+ // TODO: implement
+ report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile");
+}
+
+symbol_iterator COFFObjectFile::end_dynamic_symbols() const {
+ // TODO: implement
+ report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile");
+}
+
+library_iterator COFFObjectFile::begin_libraries_needed() const {
+ // TODO: implement
+ report_fatal_error("Libraries needed unimplemented in COFFObjectFile");
+}
+
+library_iterator COFFObjectFile::end_libraries_needed() const {
+ // TODO: implement
+ report_fatal_error("Libraries needed unimplemented in COFFObjectFile");
+}
+
+StringRef COFFObjectFile::getLoadName() const {
+ // COFF does not have this field.
+ return "";
+}
+
+
section_iterator COFFObjectFile::begin_sections() const {
DataRefImpl ret;
- std::memset(&ret, 0, sizeof(DataRefImpl));
ret.p = reinterpret_cast<intptr_t>(SectionTable);
return section_iterator(SectionRef(ret, this));
}
section_iterator COFFObjectFile::end_sections() const {
DataRefImpl ret;
- std::memset(&ret, 0, sizeof(DataRefImpl));
ret.p = reinterpret_cast<intptr_t>(SectionTable + Header->NumberOfSections);
return section_iterator(SectionRef(ret, this));
}
@@ -525,6 +563,11 @@ unsigned COFFObjectFile::getArch() const {
}
}
+error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const {
+ Res = Header;
+ return object_error::success;
+}
+
error_code COFFObjectFile::getSection(int32_t index,
const coff_section *&Result) const {
// Check for special index values.
@@ -553,13 +596,69 @@ error_code COFFObjectFile::getString(uint32_t offset,
error_code COFFObjectFile::getSymbol(uint32_t index,
const coff_symbol *&Result) const {
- if (index > 0 && index < Header->NumberOfSymbols)
+ if (index < Header->NumberOfSymbols)
Result = SymbolTable + index;
else
return object_error::parse_failed;
return object_error::success;
}
+error_code COFFObjectFile::getSymbolName(const coff_symbol *symbol,
+ StringRef &Res) const {
+ // Check for string table entry. First 4 bytes are 0.
+ if (symbol->Name.Offset.Zeroes == 0) {
+ uint32_t Offset = symbol->Name.Offset.Offset;
+ if (error_code ec = getString(Offset, Res))
+ return ec;
+ return object_error::success;
+ }
+
+ if (symbol->Name.ShortName[7] == 0)
+ // Null terminated, let ::strlen figure out the length.
+ Res = StringRef(symbol->Name.ShortName);
+ else
+ // Not null terminated, use all 8 bytes.
+ Res = StringRef(symbol->Name.ShortName, 8);
+ return object_error::success;
+}
+
+error_code COFFObjectFile::getSectionName(const coff_section *Sec,
+ StringRef &Res) const {
+ StringRef Name;
+ if (Sec->Name[7] == 0)
+ // Null terminated, let ::strlen figure out the length.
+ Name = Sec->Name;
+ else
+ // Not null terminated, use all 8 bytes.
+ Name = StringRef(Sec->Name, 8);
+
+ // Check for string table entry. First byte is '/'.
+ if (Name[0] == '/') {
+ uint32_t Offset;
+ if (Name.substr(1).getAsInteger(10, Offset))
+ return object_error::parse_failed;
+ if (error_code ec = getString(Offset, Name))
+ return ec;
+ }
+
+ Res = Name;
+ return object_error::success;
+}
+
+error_code COFFObjectFile::getSectionContents(const coff_section *Sec,
+ ArrayRef<uint8_t> &Res) const {
+ // The only thing that we need to verify is that the contents is contained
+ // within the file bounds. We don't need to make sure it doesn't cover other
+ // data, as there's nothing that says that is not allowed.
+ uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
+ uintptr_t ConEnd = ConStart + Sec->SizeOfRawData;
+ if (ConEnd > uintptr_t(Data->getBufferEnd()))
+ return object_error::parse_failed;
+ Res = ArrayRef<uint8_t>(reinterpret_cast<const unsigned char*>(ConStart),
+ Sec->SizeOfRawData);
+ return object_error::success;
+}
+
const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
return reinterpret_cast<const coff_relocation*>(Rel.p);
}
@@ -575,6 +674,11 @@ error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel,
Res = toRel(Rel)->VirtualAddress;
return object_error::success;
}
+error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel,
+ uint64_t &Res) const {
+ Res = toRel(Rel)->VirtualAddress;
+ return object_error::success;
+}
error_code COFFObjectFile::getRelocationSymbol(DataRefImpl Rel,
SymbolRef &Res) const {
const coff_relocation* R = toRel(Rel);
@@ -584,7 +688,7 @@ error_code COFFObjectFile::getRelocationSymbol(DataRefImpl Rel,
return object_error::success;
}
error_code COFFObjectFile::getRelocationType(DataRefImpl Rel,
- uint32_t &Res) const {
+ uint64_t &Res) const {
const coff_relocation* R = toRel(Rel);
Res = R->Type;
return object_error::success;
@@ -658,7 +762,6 @@ error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel,
const coff_symbol *symb = 0;
if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec;
DataRefImpl sym;
- ::memset(&sym, 0, sizeof(sym));
sym.p = reinterpret_cast<uintptr_t>(symb);
StringRef symname;
if (error_code ec = getSymbolName(sym, symname)) return ec;
@@ -666,6 +769,16 @@ error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel,
return object_error::success;
}
+error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData,
+ LibraryRef &Result) const {
+ report_fatal_error("getLibraryNext not implemented in COFFObjectFile");
+}
+
+error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData,
+ StringRef &Result) const {
+ report_fatal_error("getLibraryPath not implemented in COFFObjectFile");
+}
+
namespace llvm {
ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {
diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp
index 257d08c..ab5f810 100644
--- a/lib/Object/ELFObjectFile.cpp
+++ b/lib/Object/ELFObjectFile.cpp
@@ -7,1405 +7,44 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the ELFObjectFile class.
+// Part of the ELFObjectFile class implementation.
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/Object/ObjectFile.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <limits>
-#include <utility>
+#include "llvm/Object/ELF.h"
-using namespace llvm;
-using namespace object;
-
-// Templates to choose Elf_Addr and Elf_Off depending on is64Bits.
-namespace {
-template<support::endianness target_endianness>
-struct ELFDataTypeTypedefHelperCommon {
- typedef support::detail::packed_endian_specific_integral
- <uint16_t, target_endianness, support::aligned> Elf_Half;
- typedef support::detail::packed_endian_specific_integral
- <uint32_t, target_endianness, support::aligned> Elf_Word;
- typedef support::detail::packed_endian_specific_integral
- <int32_t, target_endianness, support::aligned> Elf_Sword;
- typedef support::detail::packed_endian_specific_integral
- <uint64_t, target_endianness, support::aligned> Elf_Xword;
- typedef support::detail::packed_endian_specific_integral
- <int64_t, target_endianness, support::aligned> Elf_Sxword;
-};
-}
-
-namespace {
-template<support::endianness target_endianness, bool is64Bits>
-struct ELFDataTypeTypedefHelper;
-
-/// ELF 32bit types.
-template<support::endianness target_endianness>
-struct ELFDataTypeTypedefHelper<target_endianness, false>
- : ELFDataTypeTypedefHelperCommon<target_endianness> {
- typedef support::detail::packed_endian_specific_integral
- <uint32_t, target_endianness, support::aligned> Elf_Addr;
- typedef support::detail::packed_endian_specific_integral
- <uint32_t, target_endianness, support::aligned> Elf_Off;
-};
-
-/// ELF 64bit types.
-template<support::endianness target_endianness>
-struct ELFDataTypeTypedefHelper<target_endianness, true>
- : ELFDataTypeTypedefHelperCommon<target_endianness>{
- typedef support::detail::packed_endian_specific_integral
- <uint64_t, target_endianness, support::aligned> Elf_Addr;
- typedef support::detail::packed_endian_specific_integral
- <uint64_t, target_endianness, support::aligned> Elf_Off;
-};
-}
-
-// I really don't like doing this, but the alternative is copypasta.
-#define LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) \
-typedef typename \
- ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Addr Elf_Addr; \
-typedef typename \
- ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Off Elf_Off; \
-typedef typename \
- ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Half Elf_Half; \
-typedef typename \
- ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Word Elf_Word; \
-typedef typename \
- ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sword Elf_Sword; \
-typedef typename \
- ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Xword Elf_Xword; \
-typedef typename \
- ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sxword Elf_Sxword;
-
- // Section header.
-namespace {
-template<support::endianness target_endianness, bool is64Bits>
-struct Elf_Shdr_Base;
-
-template<support::endianness target_endianness>
-struct Elf_Shdr_Base<target_endianness, false> {
- LLVM_ELF_IMPORT_TYPES(target_endianness, false)
- Elf_Word sh_name; // Section name (index into string table)
- Elf_Word sh_type; // Section type (SHT_*)
- Elf_Word sh_flags; // Section flags (SHF_*)
- Elf_Addr sh_addr; // Address where section is to be loaded
- Elf_Off sh_offset; // File offset of section data, in bytes
- Elf_Word sh_size; // Size of section, in bytes
- Elf_Word sh_link; // Section type-specific header table index link
- Elf_Word sh_info; // Section type-specific extra information
- Elf_Word sh_addralign;// Section address alignment
- Elf_Word sh_entsize; // Size of records contained within the section
-};
-
-template<support::endianness target_endianness>
-struct Elf_Shdr_Base<target_endianness, true> {
- LLVM_ELF_IMPORT_TYPES(target_endianness, true)
- Elf_Word sh_name; // Section name (index into string table)
- Elf_Word sh_type; // Section type (SHT_*)
- Elf_Xword sh_flags; // Section flags (SHF_*)
- Elf_Addr sh_addr; // Address where section is to be loaded
- Elf_Off sh_offset; // File offset of section data, in bytes
- Elf_Xword sh_size; // Size of section, in bytes
- Elf_Word sh_link; // Section type-specific header table index link
- Elf_Word sh_info; // Section type-specific extra information
- Elf_Xword sh_addralign;// Section address alignment
- Elf_Xword sh_entsize; // Size of records contained within the section
-};
-
-template<support::endianness target_endianness, bool is64Bits>
-struct Elf_Shdr_Impl : Elf_Shdr_Base<target_endianness, is64Bits> {
- using Elf_Shdr_Base<target_endianness, is64Bits>::sh_entsize;
- using Elf_Shdr_Base<target_endianness, is64Bits>::sh_size;
-
- /// @brief Get the number of entities this section contains if it has any.
- unsigned getEntityCount() const {
- if (sh_entsize == 0)
- return 0;
- return sh_size / sh_entsize;
- }
-};
-}
-
-namespace {
-template<support::endianness target_endianness, bool is64Bits>
-struct Elf_Sym_Base;
-
-template<support::endianness target_endianness>
-struct Elf_Sym_Base<target_endianness, false> {
- LLVM_ELF_IMPORT_TYPES(target_endianness, false)
- Elf_Word st_name; // Symbol name (index into string table)
- Elf_Addr st_value; // Value or address associated with the symbol
- Elf_Word st_size; // Size of the symbol
- unsigned char st_info; // Symbol's type and binding attributes
- unsigned char st_other; // Must be zero; reserved
- Elf_Half st_shndx; // Which section (header table index) it's defined in
-};
-
-template<support::endianness target_endianness>
-struct Elf_Sym_Base<target_endianness, true> {
- LLVM_ELF_IMPORT_TYPES(target_endianness, true)
- Elf_Word st_name; // Symbol name (index into string table)
- unsigned char st_info; // Symbol's type and binding attributes
- unsigned char st_other; // Must be zero; reserved
- Elf_Half st_shndx; // Which section (header table index) it's defined in
- Elf_Addr st_value; // Value or address associated with the symbol
- Elf_Xword st_size; // Size of the symbol
-};
-
-template<support::endianness target_endianness, bool is64Bits>
-struct Elf_Sym_Impl : Elf_Sym_Base<target_endianness, is64Bits> {
- using Elf_Sym_Base<target_endianness, is64Bits>::st_info;
-
- // These accessors and mutators correspond to the ELF32_ST_BIND,
- // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification:
- unsigned char getBinding() const { return st_info >> 4; }
- unsigned char getType() const { return st_info & 0x0f; }
- void setBinding(unsigned char b) { setBindingAndType(b, getType()); }
- void setType(unsigned char t) { setBindingAndType(getBinding(), t); }
- void setBindingAndType(unsigned char b, unsigned char t) {
- st_info = (b << 4) + (t & 0x0f);
- }
-};
-}
-
-namespace {
-template<support::endianness target_endianness, bool is64Bits, bool isRela>
-struct Elf_Rel_Base;
-
-template<support::endianness target_endianness>
-struct Elf_Rel_Base<target_endianness, false, false> {
- LLVM_ELF_IMPORT_TYPES(target_endianness, false)
- Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
- Elf_Word r_info; // Symbol table index and type of relocation to apply
-};
-
-template<support::endianness target_endianness>
-struct Elf_Rel_Base<target_endianness, true, false> {
- LLVM_ELF_IMPORT_TYPES(target_endianness, true)
- Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
- Elf_Xword r_info; // Symbol table index and type of relocation to apply
-};
-
-template<support::endianness target_endianness>
-struct Elf_Rel_Base<target_endianness, false, true> {
- LLVM_ELF_IMPORT_TYPES(target_endianness, false)
- Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
- Elf_Word r_info; // Symbol table index and type of relocation to apply
- Elf_Sword r_addend; // Compute value for relocatable field by adding this
-};
-
-template<support::endianness target_endianness>
-struct Elf_Rel_Base<target_endianness, true, true> {
- LLVM_ELF_IMPORT_TYPES(target_endianness, true)
- Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
- Elf_Xword r_info; // Symbol table index and type of relocation to apply
- Elf_Sxword r_addend; // Compute value for relocatable field by adding this.
-};
-
-template<support::endianness target_endianness, bool is64Bits, bool isRela>
-struct Elf_Rel_Impl;
-
-template<support::endianness target_endianness, bool isRela>
-struct Elf_Rel_Impl<target_endianness, true, isRela>
- : Elf_Rel_Base<target_endianness, true, isRela> {
- using Elf_Rel_Base<target_endianness, true, isRela>::r_info;
- LLVM_ELF_IMPORT_TYPES(target_endianness, true)
-
- // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE,
- // and ELF64_R_INFO macros defined in the ELF specification:
- uint64_t getSymbol() const { return (r_info >> 32); }
- unsigned char getType() const {
- return (unsigned char) (r_info & 0xffffffffL);
- }
- void setSymbol(uint64_t s) { setSymbolAndType(s, getType()); }
- void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); }
- void setSymbolAndType(uint64_t s, unsigned char t) {
- r_info = (s << 32) + (t&0xffffffffL);
- }
-};
-
-template<support::endianness target_endianness, bool isRela>
-struct Elf_Rel_Impl<target_endianness, false, isRela>
- : Elf_Rel_Base<target_endianness, false, isRela> {
- using Elf_Rel_Base<target_endianness, false, isRela>::r_info;
- LLVM_ELF_IMPORT_TYPES(target_endianness, false)
-
- // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE,
- // and ELF32_R_INFO macros defined in the ELF specification:
- uint32_t getSymbol() const { return (r_info >> 8); }
- unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); }
- void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); }
- void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); }
- void setSymbolAndType(uint32_t s, unsigned char t) {
- r_info = (s << 8) + t;
- }
-};
+namespace llvm {
-}
+using namespace object;
namespace {
-template<support::endianness target_endianness, bool is64Bits>
-class ELFObjectFile : public ObjectFile {
- LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
-
- typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
- typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
- typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel;
- typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela;
-
- struct Elf_Ehdr {
- unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes
- Elf_Half e_type; // Type of file (see ET_*)
- Elf_Half e_machine; // Required architecture for this file (see EM_*)
- Elf_Word e_version; // Must be equal to 1
- Elf_Addr e_entry; // Address to jump to in order to start program
- Elf_Off e_phoff; // Program header table's file offset, in bytes
- Elf_Off e_shoff; // Section header table's file offset, in bytes
- Elf_Word e_flags; // Processor-specific flags
- Elf_Half e_ehsize; // Size of ELF header, in bytes
- Elf_Half e_phentsize;// Size of an entry in the program header table
- Elf_Half e_phnum; // Number of entries in the program header table
- Elf_Half e_shentsize;// Size of an entry in the section header table
- Elf_Half e_shnum; // Number of entries in the section header table
- Elf_Half e_shstrndx; // Section header table index of section name
- // string table
- bool checkMagic() const {
- return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;
- }
- unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; }
- unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; }
- };
-
- typedef SmallVector<const Elf_Shdr*, 1> Sections_t;
- typedef DenseMap<unsigned, unsigned> IndexMap_t;
- typedef DenseMap<const Elf_Shdr*, SmallVector<uint32_t, 1> > RelocMap_t;
-
- const Elf_Ehdr *Header;
- const Elf_Shdr *SectionHeaderTable;
- const Elf_Shdr *dot_shstrtab_sec; // Section header string table.
- const Elf_Shdr *dot_strtab_sec; // Symbol header string table.
- Sections_t SymbolTableSections;
- IndexMap_t SymbolTableSectionsIndexMap;
- DenseMap<const Elf_Sym*, ELF::Elf64_Word> ExtendedSymbolTable;
-
- /// @brief Map sections to an array of relocation sections that reference
- /// them sorted by section index.
- RelocMap_t SectionRelocMap;
-
- /// @brief Get the relocation section that contains \a Rel.
- const Elf_Shdr *getRelSection(DataRefImpl Rel) const {
- return getSection(Rel.w.b);
- }
-
- void validateSymbol(DataRefImpl Symb) const;
- bool isRelocationHasAddend(DataRefImpl Rel) const;
- template<typename T>
- const T *getEntry(uint16_t Section, uint32_t Entry) const;
- template<typename T>
- const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const;
- const Elf_Sym *getSymbol(DataRefImpl Symb) const;
- const Elf_Shdr *getSection(DataRefImpl index) const;
- const Elf_Shdr *getSection(uint32_t index) const;
- const Elf_Rel *getRel(DataRefImpl Rel) const;
- const Elf_Rela *getRela(DataRefImpl Rela) const;
- const char *getString(uint32_t section, uint32_t offset) const;
- const char *getString(const Elf_Shdr *section, uint32_t offset) const;
- error_code getSymbolName(const Elf_Sym *Symb, StringRef &Res) const;
-
-protected:
- virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
- virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const;
- virtual error_code getSymbolOffset(DataRefImpl Symb, uint64_t &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 isSymbolGlobal(DataRefImpl Symb, bool &Res) const;
- virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::SymbolType &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 getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const;
- virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const;
- virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const;
- virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const;
- virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
- bool &Result) const;
- virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const;
- virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const;
-
- virtual error_code getRelocationNext(DataRefImpl Rel,
- RelocationRef &Res) const;
- virtual error_code getRelocationAddress(DataRefImpl Rel,
- uint64_t &Res) const;
- virtual error_code getRelocationSymbol(DataRefImpl Rel,
- SymbolRef &Res) const;
- virtual error_code getRelocationType(DataRefImpl Rel,
- uint32_t &Res) const;
- virtual error_code getRelocationTypeName(DataRefImpl Rel,
- SmallVectorImpl<char> &Result) const;
- virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
- int64_t &Res) const;
- virtual error_code getRelocationValueString(DataRefImpl Rel,
- SmallVectorImpl<char> &Result) const;
-
-public:
- ELFObjectFile(MemoryBuffer *Object, error_code &ec);
- 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;
-
- uint64_t getNumSections() const;
- uint64_t getStringTableIndex() const;
- ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const;
- const Elf_Shdr *getSection(const Elf_Sym *symb) const;
-};
-} // end namespace
-
-template<support::endianness target_endianness, bool is64Bits>
-void ELFObjectFile<target_endianness, is64Bits>
- ::validateSymbol(DataRefImpl Symb) const {
- const Elf_Sym *symb = getSymbol(Symb);
- const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b];
- // FIXME: We really need to do proper error handling in the case of an invalid
- // input file. Because we don't use exceptions, I think we'll just pass
- // an error object around.
- if (!( symb
- && SymbolTableSection
- && symb >= (const Elf_Sym*)(base()
- + SymbolTableSection->sh_offset)
- && symb < (const Elf_Sym*)(base()
- + SymbolTableSection->sh_offset
- + SymbolTableSection->sh_size)))
- // FIXME: Proper error handling.
- report_fatal_error("Symb must point to a valid symbol!");
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getSymbolNext(DataRefImpl Symb,
- SymbolRef &Result) const {
- validateSymbol(Symb);
- const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b];
-
- ++Symb.d.a;
- // Check to see if we are at the end of this symbol table.
- if (Symb.d.a >= SymbolTableSection->getEntityCount()) {
- // We are at the end. If there are other symbol tables, jump to them.
- ++Symb.d.b;
- Symb.d.a = 1; // The 0th symbol in ELF is fake.
- // Otherwise return the terminator.
- if (Symb.d.b >= SymbolTableSections.size()) {
- Symb.d.a = std::numeric_limits<uint32_t>::max();
- Symb.d.b = std::numeric_limits<uint32_t>::max();
- }
- }
-
- Result = SymbolRef(Symb, this);
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getSymbolName(DataRefImpl Symb,
- StringRef &Result) const {
- validateSymbol(Symb);
- const Elf_Sym *symb = getSymbol(Symb);
- return getSymbolName(symb, Result);
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-ELF::Elf64_Word ELFObjectFile<target_endianness, is64Bits>
- ::getSymbolTableIndex(const Elf_Sym *symb) const {
- if (symb->st_shndx == ELF::SHN_XINDEX)
- return ExtendedSymbolTable.lookup(symb);
- return symb->st_shndx;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr *
-ELFObjectFile<target_endianness, is64Bits>
- ::getSection(const Elf_Sym *symb) const {
- if (symb->st_shndx == ELF::SHN_XINDEX)
- return getSection(ExtendedSymbolTable.lookup(symb));
- if (symb->st_shndx >= ELF::SHN_LORESERVE)
- return 0;
- return getSection(symb->st_shndx);
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getSymbolOffset(DataRefImpl Symb,
- uint64_t &Result) const {
- validateSymbol(Symb);
- const Elf_Sym *symb = getSymbol(Symb);
- const Elf_Shdr *Section;
- switch (getSymbolTableIndex(symb)) {
- case ELF::SHN_COMMON:
- // Undefined symbols have no address yet.
- 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);
- }
-
- switch (symb->getType()) {
- 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:
- Result = symb->st_value;
- return object_error::success;
- default:
- Result = UnknownAddressOrSize;
- return object_error::success;
- }
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-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 (getSymbolTableIndex(symb)) {
- case ELF::SHN_COMMON: // Fall through.
- // Undefined symbols have no address yet.
- case ELF::SHN_UNDEF:
- Result = UnknownAddressOrSize;
- return object_error::success;
- case ELF::SHN_ABS:
- Result = reinterpret_cast<uintptr_t>(base()+symb->st_value);
- return object_error::success;
- default: Section = getSection(symb);
+ std::pair<unsigned char, unsigned char>
+ getElfArchType(MemoryBuffer *Object) {
+ if (Object->getBufferSize() < ELF::EI_NIDENT)
+ return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE);
+ return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS]
+ , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]);
}
- const uint8_t* addr = base();
- if (Section)
- addr += Section->sh_offset;
- switch (symb->getType()) {
- case ELF::STT_SECTION:
- Result = reinterpret_cast<uintptr_t>(addr);
- return object_error::success;
- case ELF::STT_FUNC: // Fall through.
- case ELF::STT_OBJECT: // Fall through.
- case ELF::STT_NOTYPE:
- addr += symb->st_value;
- Result = reinterpret_cast<uintptr_t>(addr);
- return object_error::success;
- default:
- Result = UnknownAddressOrSize;
- return object_error::success;
- }
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-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)
- Result = UnknownAddressOrSize;
- Result = symb->st_size;
- return object_error::success;
}
-template<support::endianness target_endianness, bool is64Bits>
-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);
-
- char ret = '?';
+// Creates an in-memory object-file by default: createELFObjectFile(Buffer)
+ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) {
+ std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object);
+ error_code ec;
- if (Section) {
- switch (Section->sh_type) {
- case ELF::SHT_PROGBITS:
- case ELF::SHT_DYNAMIC:
- switch (Section->sh_flags) {
- case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR):
- ret = 't'; break;
- case (ELF::SHF_ALLOC | ELF::SHF_WRITE):
- ret = 'd'; break;
- case ELF::SHF_ALLOC:
- case (ELF::SHF_ALLOC | ELF::SHF_MERGE):
- case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS):
- ret = 'r'; break;
- }
- break;
- case ELF::SHT_NOBITS: ret = 'b';
- }
+ if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB)
+ 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, ec);
+ else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB)
+ return new ELFObjectFile<support::big, true>(Object, ec);
+ else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) {
+ ELFObjectFile<support::little, true> *result =
+ new ELFObjectFile<support::little, true>(Object, ec);
+ return result;
}
- switch (getSymbolTableIndex(symb)) {
- case ELF::SHN_UNDEF:
- if (ret == '?')
- ret = 'U';
- break;
- case ELF::SHN_ABS: ret = 'a'; break;
- case ELF::SHN_COMMON: ret = 'c'; break;
- }
-
- switch (symb->getBinding()) {
- case ELF::STB_GLOBAL: ret = ::toupper(ret); break;
- case ELF::STB_WEAK:
- if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF)
- ret = 'w';
- else
- if (symb->getType() == ELF::STT_OBJECT)
- ret = 'V';
- else
- ret = 'W';
- }
-
- 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')
- .Default('?');
- return object_error::success;
- }
-
- Result = ret;
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getSymbolType(DataRefImpl Symb,
- SymbolRef::SymbolType &Result) const {
- validateSymbol(Symb);
- const Elf_Sym *symb = getSymbol(Symb);
-
- if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) {
- Result = SymbolRef::ST_External;
- return object_error::success;
- }
-
- switch (symb->getType()) {
- case ELF::STT_FUNC:
- Result = SymbolRef::ST_Function;
- break;
- case ELF::STT_OBJECT:
- Result = SymbolRef::ST_Data;
- break;
- default:
- Result = SymbolRef::ST_Other;
- break;
- }
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::isSymbolGlobal(DataRefImpl Symb,
- bool &Result) const {
- validateSymbol(Symb);
- const Elf_Sym *symb = getSymbol(Symb);
-
- Result = symb->getBinding() == ELF::STB_GLOBAL;
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-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)
- Result = true;
- Result = false;
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-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);
- Result = SectionRef(Sec, this);
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getSectionName(DataRefImpl Sec,
- StringRef &Result) const {
- const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
- Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name));
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getSectionAddress(DataRefImpl Sec,
- uint64_t &Result) const {
- const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
- Result = sec->sh_addr;
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getSectionSize(DataRefImpl Sec,
- uint64_t &Result) const {
- const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
- Result = sec->sh_size;
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-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 = (const char*)base() + sec->sh_offset;
- Result = StringRef(start, sec->sh_size);
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getSectionAlignment(DataRefImpl Sec,
- uint64_t &Result) const {
- const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
- Result = sec->sh_addralign;
- return object_error::success;
+ report_fatal_error("Buffer is not an ELF object file!");
}
-template<support::endianness target_endianness, bool is64Bits>
-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)
- Result = true;
- else
- Result = false;
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::isSectionData(DataRefImpl Sec,
- bool &Result) const {
- const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
- if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE)
- && sec->sh_type == ELF::SHT_PROGBITS)
- Result = true;
- else
- Result = false;
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::isSectionBSS(DataRefImpl Sec,
- bool &Result) const {
- const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
- if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE)
- && sec->sh_type == ELF::SHT_NOBITS)
- 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>
-relocation_iterator ELFObjectFile<target_endianness, is64Bits>
- ::getSectionRelBegin(DataRefImpl Sec) const {
- DataRefImpl RelData;
- memset(&RelData, 0, sizeof(RelData));
- const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
- typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec);
- if (sec != 0 && ittr != SectionRelocMap.end()) {
- RelData.w.a = getSection(ittr->second[0])->sh_info;
- RelData.w.b = ittr->second[0];
- RelData.w.c = 0;
- }
- return relocation_iterator(RelocationRef(RelData, this));
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-relocation_iterator ELFObjectFile<target_endianness, is64Bits>
- ::getSectionRelEnd(DataRefImpl Sec) const {
- DataRefImpl RelData;
- memset(&RelData, 0, sizeof(RelData));
- const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
- typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec);
- if (sec != 0 && ittr != SectionRelocMap.end()) {
- // Get the index of the last relocation section for this section.
- std::size_t relocsecindex = ittr->second[ittr->second.size() - 1];
- const Elf_Shdr *relocsec = getSection(relocsecindex);
- RelData.w.a = relocsec->sh_info;
- RelData.w.b = relocsecindex;
- RelData.w.c = relocsec->sh_size / relocsec->sh_entsize;
- }
- return relocation_iterator(RelocationRef(RelData, this));
-}
-
-// Relocations
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getRelocationNext(DataRefImpl Rel,
- RelocationRef &Result) const {
- ++Rel.w.c;
- const Elf_Shdr *relocsec = getSection(Rel.w.b);
- if (Rel.w.c >= (relocsec->sh_size / relocsec->sh_entsize)) {
- // We have reached the end of the relocations for this section. See if there
- // is another relocation section.
- typename RelocMap_t::mapped_type relocseclist =
- SectionRelocMap.lookup(getSection(Rel.w.a));
-
- // Do a binary search for the current reloc section index (which must be
- // present). Then get the next one.
- typename RelocMap_t::mapped_type::const_iterator loc =
- std::lower_bound(relocseclist.begin(), relocseclist.end(), Rel.w.b);
- ++loc;
-
- // If there is no next one, don't do anything. The ++Rel.w.c above sets Rel
- // to the end iterator.
- if (loc != relocseclist.end()) {
- Rel.w.b = *loc;
- Rel.w.a = 0;
- }
- }
- Result = RelocationRef(Rel, this);
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getRelocationSymbol(DataRefImpl Rel,
- SymbolRef &Result) const {
- uint32_t symbolIdx;
- const Elf_Shdr *sec = getSection(Rel.w.b);
- switch (sec->sh_type) {
- default :
- report_fatal_error("Invalid section type in Rel!");
- case ELF::SHT_REL : {
- symbolIdx = getRel(Rel)->getSymbol();
- break;
- }
- case ELF::SHT_RELA : {
- symbolIdx = getRela(Rel)->getSymbol();
- break;
- }
- }
- DataRefImpl SymbolData;
- IndexMap_t::const_iterator it = SymbolTableSectionsIndexMap.find(sec->sh_link);
- if (it == SymbolTableSectionsIndexMap.end())
- report_fatal_error("Relocation symbol table not found!");
- SymbolData.d.a = symbolIdx;
- SymbolData.d.b = it->second;
- Result = SymbolRef(SymbolData, this);
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getRelocationAddress(DataRefImpl Rel,
- uint64_t &Result) const {
- uint64_t offset;
- const Elf_Shdr *sec = getSection(Rel.w.b);
- switch (sec->sh_type) {
- default :
- report_fatal_error("Invalid section type in Rel!");
- case ELF::SHT_REL : {
- offset = getRel(Rel)->r_offset;
- break;
- }
- case ELF::SHT_RELA : {
- offset = getRela(Rel)->r_offset;
- break;
- }
- }
-
- Result = offset;
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getRelocationType(DataRefImpl Rel,
- uint32_t &Result) const {
- const Elf_Shdr *sec = getSection(Rel.w.b);
- switch (sec->sh_type) {
- default :
- report_fatal_error("Invalid section type in Rel!");
- case ELF::SHT_REL : {
- Result = getRel(Rel)->getType();
- break;
- }
- case ELF::SHT_RELA : {
- Result = getRela(Rel)->getType();
- break;
- }
- }
- return object_error::success;
-}
-
-#define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \
- case ELF::enum: res = #enum; break;
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getRelocationTypeName(DataRefImpl Rel,
- SmallVectorImpl<char> &Result) const {
- const Elf_Shdr *sec = getSection(Rel.w.b);
- uint8_t type;
- StringRef res;
- switch (sec->sh_type) {
- default :
- return object_error::parse_failed;
- case ELF::SHT_REL : {
- type = getRel(Rel)->getType();
- break;
- }
- case ELF::SHT_RELA : {
- type = getRela(Rel)->getType();
- break;
- }
- }
- switch (Header->e_machine) {
- case ELF::EM_X86_64:
- switch (type) {
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_NONE);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_64);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLT32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_COPY);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GLOB_DAT);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_JUMP_SLOT);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_RELATIVE);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32S);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_16);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC16);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_8);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC8);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPMOD64);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF64);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF64);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSGD);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSLD);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTTPOFF);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC64);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTOFF64);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE64);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32_TLSDESC);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC_CALL);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC);
- default:
- res = "Unknown";
- }
- break;
- case ELF::EM_386:
- switch (type) {
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_NONE);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOT32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PLT32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_COPY);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GLOB_DAT);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_JUMP_SLOT);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_RELATIVE);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTOFF);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTPC);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32PLT);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTIE);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_16);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC16);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_8);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC8);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_PUSH);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_CALL);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_POP);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_PUSH);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_CALL);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_POP);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDO_32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE_32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE_32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPMOD32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPOFF32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF32);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTDESC);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC_CALL);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC);
- LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_IRELATIVE);
- default:
- res = "Unknown";
- }
- break;
- default:
- res = "Unknown";
- }
- Result.append(res.begin(), res.end());
- return object_error::success;
-}
-
-#undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getRelocationAdditionalInfo(DataRefImpl Rel,
- int64_t &Result) const {
- const Elf_Shdr *sec = getSection(Rel.w.b);
- switch (sec->sh_type) {
- default :
- report_fatal_error("Invalid section type in Rel!");
- case ELF::SHT_REL : {
- Result = 0;
- return object_error::success;
- }
- case ELF::SHT_RELA : {
- Result = getRela(Rel)->r_addend;
- return object_error::success;
- }
- }
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getRelocationValueString(DataRefImpl Rel,
- SmallVectorImpl<char> &Result) const {
- const Elf_Shdr *sec = getSection(Rel.w.b);
- uint8_t type;
- StringRef res;
- int64_t addend = 0;
- uint16_t symbol_index = 0;
- switch (sec->sh_type) {
- default :
- return object_error::parse_failed;
- case ELF::SHT_REL : {
- type = getRel(Rel)->getType();
- symbol_index = getRel(Rel)->getSymbol();
- // TODO: Read implicit addend from section data.
- break;
- }
- case ELF::SHT_RELA : {
- type = getRela(Rel)->getType();
- symbol_index = getRela(Rel)->getSymbol();
- addend = getRela(Rel)->r_addend;
- break;
- }
- }
- const Elf_Sym *symb = getEntry<Elf_Sym>(sec->sh_link, symbol_index);
- StringRef symname;
- if (error_code ec = getSymbolName(symb, symname))
- return ec;
- switch (Header->e_machine) {
- case ELF::EM_X86_64:
- switch (type) {
- case ELF::R_X86_64_32S:
- res = symname;
- break;
- case ELF::R_X86_64_PC32: {
- std::string fmtbuf;
- raw_string_ostream fmt(fmtbuf);
- fmt << symname << (addend < 0 ? "" : "+") << addend << "-P";
- fmt.flush();
- Result.append(fmtbuf.begin(), fmtbuf.end());
- }
- break;
- default:
- res = "Unknown";
- }
- break;
- default:
- res = "Unknown";
- }
- if (Result.empty())
- Result.append(res.begin(), res.end());
- return object_error::success;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-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());
-
- if (Header->e_shoff == 0)
- return;
-
- SectionHeaderTable =
- reinterpret_cast<const Elf_Shdr *>(base() + Header->e_shoff);
- uint64_t SectionTableSize = getNumSections() * Header->e_shentsize;
- if (!( (const uint8_t *)SectionHeaderTable + SectionTableSize
- <= base() + Data->getBufferSize()))
- // FIXME: Proper error handling.
- report_fatal_error("Section table goes past end of file!");
-
-
- // To find the symbol tables we walk the section table to find SHT_SYMTAB.
- const Elf_Shdr* SymbolTableSectionHeaderIndex = 0;
- const Elf_Shdr* sh = reinterpret_cast<const Elf_Shdr*>(SectionHeaderTable);
- for (uint64_t i = 0, e = getNumSections(); i != e; ++i) {
- if (sh->sh_type == ELF::SHT_SYMTAB_SHNDX) {
- if (SymbolTableSectionHeaderIndex)
- // FIXME: Proper error handling.
- report_fatal_error("More than one .symtab_shndx!");
- SymbolTableSectionHeaderIndex = sh;
- }
- if (sh->sh_type == ELF::SHT_SYMTAB) {
- SymbolTableSectionsIndexMap[i] = SymbolTableSections.size();
- SymbolTableSections.push_back(sh);
- }
- if (sh->sh_type == ELF::SHT_REL || sh->sh_type == ELF::SHT_RELA) {
- SectionRelocMap[getSection(sh->sh_info)].push_back(i);
- }
- ++sh;
- }
-
- // Sort section relocation lists by index.
- for (typename RelocMap_t::iterator i = SectionRelocMap.begin(),
- e = SectionRelocMap.end(); i != e; ++i) {
- std::sort(i->second.begin(), i->second.end());
- }
-
- // Get string table sections.
- dot_shstrtab_sec = getSection(getStringTableIndex());
- 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)
- [dot_shstrtab_sec->sh_size - 1] != 0)
- // FIXME: Proper error handling.
- report_fatal_error("String table must end with a null terminator!");
- }
-
- // Merge this into the above loop.
- for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable),
- *e = i + getNumSections() * Header->e_shentsize;
- i != e; i += Header->e_shentsize) {
- const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i);
- if (sh->sh_type == ELF::SHT_STRTAB) {
- StringRef SectionName(getString(dot_shstrtab_sec, sh->sh_name));
- if (SectionName == ".strtab") {
- if (dot_strtab_sec != 0)
- // 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;
- if (dot_strtab[sh->sh_size - 1] != 0)
- // FIXME: Proper error handling.
- report_fatal_error("String table must end with a null terminator!");
- }
- }
- }
-
- // Build symbol name side-mapping if there is one.
- if (SymbolTableSectionHeaderIndex) {
- const Elf_Word *ShndxTable = reinterpret_cast<const Elf_Word*>(base() +
- SymbolTableSectionHeaderIndex->sh_offset);
- error_code ec;
- for (symbol_iterator si = begin_symbols(),
- se = end_symbols(); si != se; si.increment(ec)) {
- if (ec)
- report_fatal_error("Fewer extended symbol table entries than symbols!");
- if (*ShndxTable != ELF::SHN_UNDEF)
- ExtendedSymbolTable[getSymbol(si->getRawDataRefImpl())] = *ShndxTable;
- ++ShndxTable;
- }
- }
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-symbol_iterator ELFObjectFile<target_endianness, is64Bits>
- ::begin_symbols() const {
- DataRefImpl SymbolData;
- memset(&SymbolData, 0, sizeof(SymbolData));
- if (SymbolTableSections.size() == 0) {
- SymbolData.d.a = std::numeric_limits<uint32_t>::max();
- SymbolData.d.b = std::numeric_limits<uint32_t>::max();
- } else {
- SymbolData.d.a = 1; // The 0th symbol in ELF is fake.
- SymbolData.d.b = 0;
- }
- return symbol_iterator(SymbolRef(SymbolData, this));
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-symbol_iterator ELFObjectFile<target_endianness, is64Bits>
- ::end_symbols() const {
- DataRefImpl SymbolData;
- memset(&SymbolData, 0, sizeof(SymbolData));
- SymbolData.d.a = std::numeric_limits<uint32_t>::max();
- SymbolData.d.b = std::numeric_limits<uint32_t>::max();
- return symbol_iterator(SymbolRef(SymbolData, this));
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-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);
- return section_iterator(SectionRef(ret, this));
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-section_iterator ELFObjectFile<target_endianness, is64Bits>
- ::end_sections() const {
- DataRefImpl ret;
- memset(&ret, 0, sizeof(DataRefImpl));
- ret.p = reinterpret_cast<intptr_t>(base()
- + Header->e_shoff
- + (Header->e_shentsize*getNumSections()));
- return section_iterator(SectionRef(ret, this));
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-uint8_t ELFObjectFile<target_endianness, is64Bits>::getBytesInAddress() const {
- return is64Bits ? 8 : 4;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-StringRef ELFObjectFile<target_endianness, is64Bits>
- ::getFileFormatName() const {
- switch(Header->e_ident[ELF::EI_CLASS]) {
- case ELF::ELFCLASS32:
- switch(Header->e_machine) {
- case ELF::EM_386:
- return "ELF32-i386";
- case ELF::EM_X86_64:
- return "ELF32-x86-64";
- case ELF::EM_ARM:
- return "ELF32-arm";
- default:
- return "ELF32-unknown";
- }
- case ELF::ELFCLASS64:
- switch(Header->e_machine) {
- case ELF::EM_386:
- return "ELF64-i386";
- case ELF::EM_X86_64:
- return "ELF64-x86-64";
- default:
- return "ELF64-unknown";
- }
- default:
- // FIXME: Proper error handling.
- report_fatal_error("Invalid ELFCLASS!");
- }
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-unsigned ELFObjectFile<target_endianness, is64Bits>::getArch() const {
- switch(Header->e_machine) {
- case ELF::EM_386:
- return Triple::x86;
- case ELF::EM_X86_64:
- return Triple::x86_64;
- case ELF::EM_ARM:
- return Triple::arm;
- default:
- return Triple::UnknownArch;
- }
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-uint64_t ELFObjectFile<target_endianness, is64Bits>::getNumSections() const {
- if (Header->e_shnum == ELF::SHN_UNDEF)
- return SectionHeaderTable->sh_size;
- return Header->e_shnum;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-uint64_t
-ELFObjectFile<target_endianness, is64Bits>::getStringTableIndex() const {
- if (Header->e_shnum == ELF::SHN_UNDEF) {
- if (Header->e_shstrndx == ELF::SHN_HIRESERVE)
- return SectionHeaderTable->sh_link;
- if (Header->e_shstrndx >= getNumSections())
- return 0;
- }
- return Header->e_shstrndx;
-}
-
-
-template<support::endianness target_endianness, bool is64Bits>
-template<typename T>
-inline const T *
-ELFObjectFile<target_endianness, is64Bits>::getEntry(uint16_t Section,
- uint32_t Entry) const {
- return getEntry<T>(getSection(Section), Entry);
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-template<typename T>
-inline const T *
-ELFObjectFile<target_endianness, is64Bits>::getEntry(const Elf_Shdr * Section,
- uint32_t Entry) const {
- return reinterpret_cast<const T *>(
- base()
- + Section->sh_offset
- + (Entry * Section->sh_entsize));
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym *
-ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const {
- return getEntry<Elf_Sym>(SymbolTableSections[Symb.d.b], Symb.d.a);
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rel *
-ELFObjectFile<target_endianness, is64Bits>::getRel(DataRefImpl Rel) const {
- return getEntry<Elf_Rel>(Rel.w.b, Rel.w.c);
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rela *
-ELFObjectFile<target_endianness, is64Bits>::getRela(DataRefImpl Rela) const {
- return getEntry<Elf_Rela>(Rela.w.b, Rela.w.c);
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr *
-ELFObjectFile<target_endianness, is64Bits>::getSection(DataRefImpl Symb) const {
- const Elf_Shdr *sec = getSection(Symb.d.b);
- if (sec->sh_type != ELF::SHT_SYMTAB || sec->sh_type != ELF::SHT_DYNSYM)
- // FIXME: Proper error handling.
- report_fatal_error("Invalid symbol table section!");
- return sec;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr *
-ELFObjectFile<target_endianness, is64Bits>::getSection(uint32_t index) const {
- if (index == 0)
- return 0;
- if (!SectionHeaderTable || index >= getNumSections())
- // FIXME: Proper error handling.
- report_fatal_error("Invalid section index!");
-
- return reinterpret_cast<const Elf_Shdr *>(
- reinterpret_cast<const char *>(SectionHeaderTable)
- + (index * Header->e_shentsize));
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-const char *ELFObjectFile<target_endianness, is64Bits>
- ::getString(uint32_t section,
- ELF::Elf32_Word offset) const {
- return getString(getSection(section), offset);
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-const char *ELFObjectFile<target_endianness, is64Bits>
- ::getString(const Elf_Shdr *section,
- ELF::Elf32_Word offset) const {
- assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!");
- if (offset >= section->sh_size)
- // FIXME: Proper error handling.
- report_fatal_error("Symbol name offset outside of string table!");
- return (const char *)base() + section->sh_offset + offset;
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-error_code ELFObjectFile<target_endianness, is64Bits>
- ::getSymbolName(const Elf_Sym *symb,
- StringRef &Result) const {
- if (symb->st_name == 0) {
- const Elf_Shdr *section = getSection(symb);
- if (!section)
- Result = "";
- else
- Result = getString(dot_shstrtab_sec, section->sh_name);
- return object_error::success;
- }
-
- // Use the default symbol table name section.
- Result = getString(dot_strtab_sec, symb->st_name);
- return object_error::success;
-}
-
-// EI_CLASS, EI_DATA.
-static std::pair<unsigned char, unsigned char>
-getElfArchType(MemoryBuffer *Object) {
- if (Object->getBufferSize() < ELF::EI_NIDENT)
- return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE);
- return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS]
- , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]);
-}
-
-namespace llvm {
-
- ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) {
- std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object);
- error_code ec;
- if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB)
- return new ELFObjectFile<support::little, false>(Object, ec);
- else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB)
- 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, ec);
- else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB)
- return new ELFObjectFile<support::big, true>(Object, ec);
- // FIXME: Proper error handling.
- report_fatal_error("Not an ELF object file!");
- }
-
} // end namespace llvm
diff --git a/lib/Object/LLVMBuild.txt b/lib/Object/LLVMBuild.txt
new file mode 100644
index 0000000..69610f9
--- /dev/null
+++ b/lib/Object/LLVMBuild.txt
@@ -0,0 +1,22 @@
+;===- ./lib/Object/LLVMBuild.txt -------------------------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = Object
+parent = Libraries
+required_libraries = Support
diff --git a/lib/Object/MachOObject.cpp b/lib/Object/MachOObject.cpp
index 9cdac86..b7e5cdc 100644
--- a/lib/Object/MachOObject.cpp
+++ b/lib/Object/MachOObject.cpp
@@ -10,11 +10,12 @@
#include "llvm/Object/MachOObject.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/Host.h"
-#include "llvm/Support/SwapByteOrder.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/Debug.h"
+#include "llvm/Support/SwapByteOrder.h"
using namespace llvm;
using namespace llvm::object;
@@ -359,25 +360,13 @@ void MachOObject::ReadSymbol64TableEntry(uint64_t SymbolTableOffset,
void MachOObject::ReadULEB128s(uint64_t Index,
SmallVectorImpl<uint64_t> &Out) const {
- const char *ptr = Buffer->getBufferStart() + Index;
+ DataExtractor extractor(Buffer->getBuffer(), true, 0);
+
+ uint32_t offset = Index;
uint64_t data = 0;
- uint64_t delta = 0;
- uint32_t shift = 0;
- while (true) {
- assert(ptr < Buffer->getBufferEnd() && "index out of bounds");
- assert(shift < 64 && "too big for uint64_t");
-
- uint8_t byte = *ptr++;
- delta |= ((byte & 0x7F) << shift);
- shift += 7;
- if (byte < 0x80) {
- if (delta == 0)
- break;
- data += delta;
- Out.push_back(data);
- delta = 0;
- shift = 0;
- }
+ while (uint64_t delta = extractor.getULEB128(&offset)) {
+ data += delta;
+ Out.push_back(data);
}
}
@@ -393,7 +382,7 @@ void MachOObject::printHeader(raw_ostream &O) const {
O << "('num_load_commands', " << Header.NumLoadCommands << ")\n";
O << "('load_commands_size', " << Header.SizeOfLoadCommands << ")\n";
O << "('flag', " << Header.Flags << ")\n";
-
+
// Print extended header if 64-bit.
if (is64Bit())
O << "('reserved', " << Header64Ext.Reserved << ")\n";
@@ -403,6 +392,6 @@ void MachOObject::print(raw_ostream &O) const {
O << "Header:\n";
printHeader(O);
O << "Load Commands:\n";
-
+
O << "Buffer:\n";
}
diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
index 507df58..3bcda17 100644
--- a/lib/Object/MachOObjectFile.cpp
+++ b/lib/Object/MachOObjectFile.cpp
@@ -15,6 +15,7 @@
#include "llvm/ADT/Triple.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/MachOFormat.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cctype>
@@ -29,11 +30,10 @@ namespace object {
MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO,
error_code &ec)
- : ObjectFile(Binary::isMachO, Object, ec),
+ : ObjectFile(Binary::ID_MachO, Object, ec),
MachOObj(MOO),
RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {
DataRefImpl DRI;
- DRI.d.a = DRI.d.b = 0;
moveToNextSection(DRI);
uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
while (DRI.d.a < LoadCommandCount) {
@@ -124,23 +124,27 @@ error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
return object_error::success;
}
-error_code MachOObjectFile::getSymbolOffset(DataRefImpl DRI,
- uint64_t &Result) const {
- uint64_t SectionOffset;
- uint8_t SectionIndex;
+error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI,
+ uint64_t &Result) const {
if (MachOObj->is64Bit()) {
InMemoryStruct<macho::Symbol64TableEntry> Entry;
getSymbol64TableEntry(DRI, Entry);
Result = Entry->Value;
- SectionIndex = Entry->SectionIndex;
+ if (Entry->SectionIndex) {
+ InMemoryStruct<macho::Section64> Section;
+ getSection64(Sections[Entry->SectionIndex-1], Section);
+ Result += Section->Offset - Section->Address;
+ }
} else {
InMemoryStruct<macho::SymbolTableEntry> Entry;
getSymbolTableEntry(DRI, Entry);
Result = Entry->Value;
- SectionIndex = Entry->SectionIndex;
+ if (Entry->SectionIndex) {
+ InMemoryStruct<macho::Section> Section;
+ getSection(Sections[Entry->SectionIndex-1], Section);
+ Result += Section->Offset - Section->Address;
+ }
}
- getSectionAddress(Sections[SectionIndex-1], SectionOffset);
- Result -= SectionOffset;
return object_error::success;
}
@@ -161,7 +165,74 @@ error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
uint64_t &Result) const {
- Result = UnknownAddressOrSize;
+ uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
+ uint64_t BeginOffset;
+ uint64_t EndOffset = 0;
+ uint8_t SectionIndex;
+ if (MachOObj->is64Bit()) {
+ InMemoryStruct<macho::Symbol64TableEntry> Entry;
+ getSymbol64TableEntry(DRI, Entry);
+ BeginOffset = Entry->Value;
+ SectionIndex = Entry->SectionIndex;
+ if (!SectionIndex) {
+ uint32_t flags = SymbolRef::SF_None;
+ getSymbolFlags(DRI, flags);
+ if (flags & SymbolRef::SF_Common)
+ Result = Entry->Value;
+ else
+ Result = UnknownAddressOrSize;
+ return object_error::success;
+ }
+ // Unfortunately symbols are unsorted so we need to touch all
+ // symbols from load command
+ DRI.d.b = 0;
+ uint32_t Command = DRI.d.a;
+ while (Command == DRI.d.a) {
+ moveToNextSymbol(DRI);
+ if (DRI.d.a < LoadCommandCount) {
+ getSymbol64TableEntry(DRI, Entry);
+ if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
+ if (!EndOffset || Entry->Value < EndOffset)
+ EndOffset = Entry->Value;
+ }
+ DRI.d.b++;
+ }
+ } else {
+ InMemoryStruct<macho::SymbolTableEntry> Entry;
+ getSymbolTableEntry(DRI, Entry);
+ BeginOffset = Entry->Value;
+ SectionIndex = Entry->SectionIndex;
+ if (!SectionIndex) {
+ uint32_t flags = SymbolRef::SF_None;
+ getSymbolFlags(DRI, flags);
+ if (flags & SymbolRef::SF_Common)
+ Result = Entry->Value;
+ else
+ Result = UnknownAddressOrSize;
+ return object_error::success;
+ }
+ // Unfortunately symbols are unsorted so we need to touch all
+ // symbols from load command
+ DRI.d.b = 0;
+ uint32_t Command = DRI.d.a;
+ while (Command == DRI.d.a) {
+ moveToNextSymbol(DRI);
+ if (DRI.d.a < LoadCommandCount) {
+ getSymbolTableEntry(DRI, Entry);
+ if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
+ if (!EndOffset || Entry->Value < EndOffset)
+ EndOffset = Entry->Value;
+ }
+ DRI.d.b++;
+ }
+ }
+ if (!EndOffset) {
+ uint64_t Size;
+ getSectionSize(Sections[SectionIndex-1], Size);
+ getSectionAddress(Sections[SectionIndex-1], EndOffset);
+ EndOffset += Size;
+ }
+ Result = EndOffset - BeginOffset;
return object_error::success;
}
@@ -200,36 +271,69 @@ error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
return object_error::success;
}
-error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI,
- bool &Result) const {
+error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
+ uint32_t &Result) const {
+ uint16_t MachOFlags;
+ uint8_t MachOType;
if (MachOObj->is64Bit()) {
InMemoryStruct<macho::Symbol64TableEntry> Entry;
getSymbol64TableEntry(DRI, Entry);
- Result = Entry->Flags & macho::STF_StabsEntryMask;
+ MachOFlags = Entry->Flags;
+ MachOType = Entry->Type;
} else {
InMemoryStruct<macho::SymbolTableEntry> Entry;
getSymbolTableEntry(DRI, Entry);
- Result = Entry->Flags & macho::STF_StabsEntryMask;
+ MachOFlags = Entry->Flags;
+ MachOType = Entry->Type;
}
+
+ // TODO: Correctly set SF_ThreadLocal
+ Result = SymbolRef::SF_None;
+
+ if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
+ Result |= SymbolRef::SF_Undefined;
+
+ if (MachOFlags & macho::STF_StabsEntryMask)
+ Result |= SymbolRef::SF_FormatSpecific;
+
+ if (MachOType & MachO::NlistMaskExternal) {
+ Result |= SymbolRef::SF_Global;
+ if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
+ Result |= SymbolRef::SF_Common;
+ }
+
+ if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
+ Result |= SymbolRef::SF_Weak;
+
+ if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
+ Result |= SymbolRef::SF_Absolute;
+
return object_error::success;
}
-error_code MachOObjectFile::isSymbolGlobal(DataRefImpl Symb, bool &Res) const {
-
+error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
+ section_iterator &Res) const {
+ uint8_t index;
if (MachOObj->is64Bit()) {
InMemoryStruct<macho::Symbol64TableEntry> Entry;
getSymbol64TableEntry(Symb, Entry);
- Res = Entry->Type & MachO::NlistMaskExternal;
+ index = Entry->SectionIndex;
} else {
InMemoryStruct<macho::SymbolTableEntry> Entry;
getSymbolTableEntry(Symb, Entry);
- Res = Entry->Type & MachO::NlistMaskExternal;
+ index = Entry->SectionIndex;
}
+
+ if (index == 0)
+ Res = end_sections();
+ else
+ Res = section_iterator(SectionRef(Sections[index-1], this));
+
return object_error::success;
}
error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
- SymbolRef::SymbolType &Res) const {
+ SymbolRef::Type &Res) const {
uint8_t n_type;
if (MachOObj->is64Bit()) {
InMemoryStruct<macho::Symbol64TableEntry> Entry;
@@ -243,12 +347,14 @@ error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
Res = SymbolRef::ST_Other;
// If this is a STAB debugging symbol, we can do nothing more.
- if (n_type & MachO::NlistMaskStab)
+ if (n_type & MachO::NlistMaskStab) {
+ Res = SymbolRef::ST_Debug;
return object_error::success;
+ }
switch (n_type & MachO::NlistMaskType) {
case MachO::NListTypeUndefined :
- Res = SymbolRef::ST_External;
+ Res = SymbolRef::ST_Unknown;
break;
case MachO::NListTypeSection :
Res = SymbolRef::ST_Function;
@@ -261,7 +367,6 @@ error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
symbol_iterator MachOObjectFile::begin_symbols() const {
// DRI.d.a = segment number; DRI.d.b = symbol index.
DataRefImpl DRI;
- DRI.d.a = DRI.d.b = 0;
moveToNextSymbol(DRI);
return symbol_iterator(SymbolRef(DRI, this));
}
@@ -269,10 +374,33 @@ symbol_iterator MachOObjectFile::begin_symbols() const {
symbol_iterator MachOObjectFile::end_symbols() const {
DataRefImpl DRI;
DRI.d.a = MachOObj->getHeader().NumLoadCommands;
- DRI.d.b = 0;
return symbol_iterator(SymbolRef(DRI, this));
}
+symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
+ // TODO: implement
+ report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
+}
+
+symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
+ // TODO: implement
+ report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
+}
+
+library_iterator MachOObjectFile::begin_libraries_needed() const {
+ // TODO: implement
+ report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
+}
+
+library_iterator MachOObjectFile::end_libraries_needed() const {
+ // TODO: implement
+ report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
+}
+
+StringRef MachOObjectFile::getLoadName() const {
+ // TODO: Implement
+ report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
+}
/*===-- Sections ----------------------------------------------------------===*/
@@ -451,12 +579,43 @@ error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
return object_error::success;
}
+error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
+ bool &Result) const {
+ // FIXME: Unimplemented
+ Result = true;
+ return object_error::success;
+}
+
+error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
+ bool &Result) const {
+ // FIXME: Unimplemented
+ Result = false;
+ return object_error::success;
+}
+
+error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI,
+ bool &Result) const {
+ if (MachOObj->is64Bit()) {
+ InMemoryStruct<macho::Section64> Sect;
+ getSection64(DRI, Sect);
+ Result = (Sect->Flags & MachO::SectionTypeZeroFill ||
+ Sect->Flags & MachO::SectionTypeZeroFillLarge);
+ } else {
+ InMemoryStruct<macho::Section> Sect;
+ getSection(DRI, Sect);
+ Result = (Sect->Flags & MachO::SectionTypeZeroFill ||
+ Sect->Flags & MachO::SectionTypeZeroFillLarge);
+ }
+
+ return object_error::success;
+}
+
error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
DataRefImpl Symb,
bool &Result) const {
- SymbolRef::SymbolType ST;
+ SymbolRef::Type ST;
getSymbolType(Symb, ST);
- if (ST == SymbolRef::ST_External) {
+ if (ST == SymbolRef::ST_Unknown) {
Result = false;
return object_error::success;
}
@@ -483,7 +642,6 @@ error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
DataRefImpl ret;
- ret.d.a = 0;
ret.d.b = getSectionIndex(Sec);
return relocation_iterator(RelocationRef(ret, this));
}
@@ -506,7 +664,6 @@ relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
section_iterator MachOObjectFile::begin_sections() const {
DataRefImpl DRI;
- DRI.d.a = DRI.d.b = 0;
moveToNextSection(DRI);
return section_iterator(SectionRef(DRI, this));
}
@@ -514,7 +671,6 @@ section_iterator MachOObjectFile::begin_sections() const {
section_iterator MachOObjectFile::end_sections() const {
DataRefImpl DRI;
DRI.d.a = MachOObj->getHeader().NumLoadCommands;
- DRI.d.b = 0;
return section_iterator(SectionRef(DRI, this));
}
@@ -543,19 +699,43 @@ error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
}
error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
uint64_t &Res) const {
- const uint8_t* sectAddress = base();
+ const uint8_t* sectAddress = 0;
if (MachOObj->is64Bit()) {
InMemoryStruct<macho::Section64> Sect;
getSection64(Sections[Rel.d.b], Sect);
- sectAddress += Sect->Offset;
+ sectAddress += Sect->Address;
} else {
InMemoryStruct<macho::Section> Sect;
getSection(Sections[Rel.d.b], Sect);
- sectAddress += Sect->Offset;
+ sectAddress += Sect->Address;
}
InMemoryStruct<macho::RelocationEntry> RE;
getRelocation(Rel, RE);
- Res = reinterpret_cast<uintptr_t>(sectAddress + RE->Word0);
+
+ unsigned Arch = getArch();
+ bool isScattered = (Arch != Triple::x86_64) &&
+ (RE->Word0 & macho::RF_Scattered);
+ uint64_t RelAddr = 0;
+ if (isScattered)
+ RelAddr = RE->Word0 & 0xFFFFFF;
+ else
+ RelAddr = RE->Word0;
+
+ Res = reinterpret_cast<uintptr_t>(sectAddress + RelAddr);
+ return object_error::success;
+}
+error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
+ uint64_t &Res) const {
+ InMemoryStruct<macho::RelocationEntry> RE;
+ getRelocation(Rel, RE);
+
+ unsigned Arch = getArch();
+ bool isScattered = (Arch != Triple::x86_64) &&
+ (RE->Word0 & macho::RF_Scattered);
+ if (isScattered)
+ Res = RE->Word0 & 0xFFFFFF;
+ else
+ Res = RE->Word0;
return object_error::success;
}
error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
@@ -566,7 +746,6 @@ error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
bool isExtern = (RE->Word1 >> 27) & 1;
DataRefImpl Sym;
- Sym.d.a = Sym.d.b = 0;
moveToNextSymbol(Sym);
if (isExtern) {
for (unsigned i = 0; i < SymbolIdx; i++) {
@@ -580,14 +759,112 @@ error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
return object_error::success;
}
error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
- uint32_t &Res) const {
+ uint64_t &Res) const {
InMemoryStruct<macho::RelocationEntry> RE;
getRelocation(Rel, RE);
- Res = RE->Word1;
+ Res = RE->Word0;
+ Res <<= 32;
+ Res |= RE->Word1;
return object_error::success;
}
error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const {
+ // TODO: Support scattered relocations.
+ StringRef res;
+ InMemoryStruct<macho::RelocationEntry> RE;
+ getRelocation(Rel, RE);
+
+ unsigned Arch = getArch();
+ bool isScattered = (Arch != Triple::x86_64) &&
+ (RE->Word0 & macho::RF_Scattered);
+
+ unsigned r_type;
+ if (isScattered)
+ r_type = (RE->Word0 >> 24) & 0xF;
+ else
+ r_type = (RE->Word1 >> 28) & 0xF;
+
+ switch (Arch) {
+ case Triple::x86: {
+ const char* Table[] = {
+ "GENERIC_RELOC_VANILLA",
+ "GENERIC_RELOC_PAIR",
+ "GENERIC_RELOC_SECTDIFF",
+ "GENERIC_RELOC_PB_LA_PTR",
+ "GENERIC_RELOC_LOCAL_SECTDIFF",
+ "GENERIC_RELOC_TLV" };
+
+ if (r_type > 6)
+ res = "Unknown";
+ else
+ res = Table[r_type];
+ break;
+ }
+ case Triple::x86_64: {
+ const char* Table[] = {
+ "X86_64_RELOC_UNSIGNED",
+ "X86_64_RELOC_SIGNED",
+ "X86_64_RELOC_BRANCH",
+ "X86_64_RELOC_GOT_LOAD",
+ "X86_64_RELOC_GOT",
+ "X86_64_RELOC_SUBTRACTOR",
+ "X86_64_RELOC_SIGNED_1",
+ "X86_64_RELOC_SIGNED_2",
+ "X86_64_RELOC_SIGNED_4",
+ "X86_64_RELOC_TLV" };
+
+ if (r_type > 9)
+ res = "Unknown";
+ else
+ res = Table[r_type];
+ break;
+ }
+ case Triple::arm: {
+ const char* Table[] = {
+ "ARM_RELOC_VANILLA",
+ "ARM_RELOC_PAIR",
+ "ARM_RELOC_SECTDIFF",
+ "ARM_RELOC_LOCAL_SECTDIFF",
+ "ARM_RELOC_PB_LA_PTR",
+ "ARM_RELOC_BR24",
+ "ARM_THUMB_RELOC_BR22",
+ "ARM_THUMB_32BIT_BRANCH",
+ "ARM_RELOC_HALF",
+ "ARM_RELOC_HALF_SECTDIFF" };
+
+ if (r_type > 9)
+ res = "Unknown";
+ else
+ res = Table[r_type];
+ break;
+ }
+ case Triple::ppc: {
+ const char* Table[] = {
+ "PPC_RELOC_VANILLA",
+ "PPC_RELOC_PAIR",
+ "PPC_RELOC_BR14",
+ "PPC_RELOC_BR24",
+ "PPC_RELOC_HI16",
+ "PPC_RELOC_LO16",
+ "PPC_RELOC_HA16",
+ "PPC_RELOC_LO14",
+ "PPC_RELOC_SECTDIFF",
+ "PPC_RELOC_PB_LA_PTR",
+ "PPC_RELOC_HI16_SECTDIFF",
+ "PPC_RELOC_LO16_SECTDIFF",
+ "PPC_RELOC_HA16_SECTDIFF",
+ "PPC_RELOC_JBSR",
+ "PPC_RELOC_LO14_SECTDIFF",
+ "PPC_RELOC_LOCAL_SECTDIFF" };
+
+ res = Table[r_type];
+ break;
+ }
+ case Triple::UnknownArch:
+ res = "Unknown";
+ break;
+ }
+ Result.append(res.begin(), res.end());
return object_error::success;
}
error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
@@ -611,11 +888,356 @@ error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
}
return object_error::success;
}
+
+// Helper to advance a section or symbol iterator multiple increments at a time.
+template<class T>
+error_code advance(T &it, size_t Val) {
+ error_code ec;
+ while (Val--) {
+ it.increment(ec);
+ }
+ return ec;
+}
+
+template<class T>
+void advanceTo(T &it, size_t Val) {
+ if (error_code ec = advance(it, Val))
+ report_fatal_error(ec.message());
+}
+
+void MachOObjectFile::printRelocationTargetName(
+ InMemoryStruct<macho::RelocationEntry>& RE,
+ raw_string_ostream &fmt) const {
+ unsigned Arch = getArch();
+ bool isScattered = (Arch != Triple::x86_64) &&
+ (RE->Word0 & macho::RF_Scattered);
+
+ // Target of a scattered relocation is an address. In the interest of
+ // generating pretty output, scan through the symbol table looking for a
+ // symbol that aligns with that address. If we find one, print it.
+ // Otherwise, we just print the hex address of the target.
+ if (isScattered) {
+ uint32_t Val = RE->Word1;
+
+ error_code ec;
+ for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
+ SI.increment(ec)) {
+ if (ec) report_fatal_error(ec.message());
+
+ uint64_t Addr;
+ StringRef Name;
+
+ if ((ec = SI->getAddress(Addr)))
+ report_fatal_error(ec.message());
+ if (Addr != Val) continue;
+ if ((ec = SI->getName(Name)))
+ report_fatal_error(ec.message());
+ fmt << Name;
+ return;
+ }
+
+ // If we couldn't find a symbol that this relocation refers to, try
+ // to find a section beginning instead.
+ for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
+ SI.increment(ec)) {
+ if (ec) report_fatal_error(ec.message());
+
+ uint64_t Addr;
+ StringRef Name;
+
+ if ((ec = SI->getAddress(Addr)))
+ report_fatal_error(ec.message());
+ if (Addr != Val) continue;
+ if ((ec = SI->getName(Name)))
+ report_fatal_error(ec.message());
+ fmt << Name;
+ return;
+ }
+
+ fmt << format("0x%x", Val);
+ return;
+ }
+
+ StringRef S;
+ bool isExtern = (RE->Word1 >> 27) & 1;
+ uint32_t Val = RE->Word1 & 0xFFFFFF;
+
+ if (isExtern) {
+ symbol_iterator SI = begin_symbols();
+ advanceTo(SI, Val);
+ SI->getName(S);
+ } else {
+ section_iterator SI = begin_sections();
+ advanceTo(SI, Val);
+ SI->getName(S);
+ }
+
+ fmt << S;
+}
+
error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const {
+ InMemoryStruct<macho::RelocationEntry> RE;
+ getRelocation(Rel, RE);
+
+ unsigned Arch = getArch();
+ bool isScattered = (Arch != Triple::x86_64) &&
+ (RE->Word0 & macho::RF_Scattered);
+
+ std::string fmtbuf;
+ raw_string_ostream fmt(fmtbuf);
+
+ unsigned Type;
+ if (isScattered)
+ Type = (RE->Word0 >> 24) & 0xF;
+ else
+ Type = (RE->Word1 >> 28) & 0xF;
+
+ bool isPCRel;
+ if (isScattered)
+ isPCRel = ((RE->Word0 >> 30) & 1);
+ else
+ isPCRel = ((RE->Word1 >> 24) & 1);
+
+ // Determine any addends that should be displayed with the relocation.
+ // These require decoding the relocation type, which is triple-specific.
+
+ // X86_64 has entirely custom relocation types.
+ if (Arch == Triple::x86_64) {
+ bool isPCRel = ((RE->Word1 >> 24) & 1);
+
+ switch (Type) {
+ case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
+ case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
+ printRelocationTargetName(RE, fmt);
+ fmt << "@GOT";
+ if (isPCRel) fmt << "PCREL";
+ break;
+ }
+ case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
+ InMemoryStruct<macho::RelocationEntry> RENext;
+ DataRefImpl RelNext = Rel;
+ RelNext.d.a++;
+ getRelocation(RelNext, RENext);
+
+ // X86_64_SUBTRACTOR must be followed by a relocation of type
+ // X86_64_RELOC_UNSIGNED.
+ // NOTE: Scattered relocations don't exist on x86_64.
+ unsigned RType = (RENext->Word1 >> 28) & 0xF;
+ if (RType != 0)
+ report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
+ "X86_64_RELOC_SUBTRACTOR.");
+
+ // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
+ // X86_64_SUBTRACTOR contains to the subtrahend.
+ printRelocationTargetName(RENext, fmt);
+ fmt << "-";
+ printRelocationTargetName(RE, fmt);
+ }
+ case macho::RIT_X86_64_TLV:
+ printRelocationTargetName(RE, fmt);
+ fmt << "@TLV";
+ if (isPCRel) fmt << "P";
+ break;
+ case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
+ printRelocationTargetName(RE, fmt);
+ fmt << "-1";
+ break;
+ case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
+ printRelocationTargetName(RE, fmt);
+ fmt << "-2";
+ break;
+ case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
+ printRelocationTargetName(RE, fmt);
+ fmt << "-4";
+ break;
+ default:
+ printRelocationTargetName(RE, fmt);
+ break;
+ }
+ // X86 and ARM share some relocation types in common.
+ } else if (Arch == Triple::x86 || Arch == Triple::arm) {
+ // Generic relocation types...
+ switch (Type) {
+ case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
+ return object_error::success;
+ case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
+ InMemoryStruct<macho::RelocationEntry> RENext;
+ DataRefImpl RelNext = Rel;
+ RelNext.d.a++;
+ getRelocation(RelNext, RENext);
+
+ // X86 sect diff's must be followed by a relocation of type
+ // GENERIC_RELOC_PAIR.
+ bool isNextScattered = (Arch != Triple::x86_64) &&
+ (RENext->Word0 & macho::RF_Scattered);
+ unsigned RType;
+ if (isNextScattered)
+ RType = (RENext->Word0 >> 24) & 0xF;
+ else
+ RType = (RENext->Word1 >> 28) & 0xF;
+ if (RType != 1)
+ report_fatal_error("Expected GENERIC_RELOC_PAIR after "
+ "GENERIC_RELOC_SECTDIFF.");
+
+ printRelocationTargetName(RE, fmt);
+ fmt << "-";
+ printRelocationTargetName(RENext, fmt);
+ break;
+ }
+ }
+
+ if (Arch == Triple::x86) {
+ // All X86 relocations that need special printing were already
+ // handled in the generic code.
+ switch (Type) {
+ case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
+ InMemoryStruct<macho::RelocationEntry> RENext;
+ DataRefImpl RelNext = Rel;
+ RelNext.d.a++;
+ getRelocation(RelNext, RENext);
+
+ // X86 sect diff's must be followed by a relocation of type
+ // GENERIC_RELOC_PAIR.
+ bool isNextScattered = (Arch != Triple::x86_64) &&
+ (RENext->Word0 & macho::RF_Scattered);
+ unsigned RType;
+ if (isNextScattered)
+ RType = (RENext->Word0 >> 24) & 0xF;
+ else
+ RType = (RENext->Word1 >> 28) & 0xF;
+ if (RType != 1)
+ report_fatal_error("Expected GENERIC_RELOC_PAIR after "
+ "GENERIC_RELOC_LOCAL_SECTDIFF.");
+
+ printRelocationTargetName(RE, fmt);
+ fmt << "-";
+ printRelocationTargetName(RENext, fmt);
+ break;
+ }
+ case macho::RIT_Generic_TLV: {
+ printRelocationTargetName(RE, fmt);
+ fmt << "@TLV";
+ if (isPCRel) fmt << "P";
+ break;
+ }
+ default:
+ printRelocationTargetName(RE, fmt);
+ }
+ } else { // ARM-specific relocations
+ switch (Type) {
+ case macho::RIT_ARM_Half: // ARM_RELOC_HALF
+ case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
+ // Half relocations steal a bit from the length field to encode
+ // whether this is an upper16 or a lower16 relocation.
+ bool isUpper;
+ if (isScattered)
+ isUpper = (RE->Word0 >> 28) & 1;
+ else
+ isUpper = (RE->Word1 >> 25) & 1;
+
+ if (isUpper)
+ fmt << ":upper16:(";
+ else
+ fmt << ":lower16:(";
+ printRelocationTargetName(RE, fmt);
+
+ InMemoryStruct<macho::RelocationEntry> RENext;
+ DataRefImpl RelNext = Rel;
+ RelNext.d.a++;
+ getRelocation(RelNext, RENext);
+
+ // ARM half relocs must be followed by a relocation of type
+ // ARM_RELOC_PAIR.
+ bool isNextScattered = (Arch != Triple::x86_64) &&
+ (RENext->Word0 & macho::RF_Scattered);
+ unsigned RType;
+ if (isNextScattered)
+ RType = (RENext->Word0 >> 24) & 0xF;
+ else
+ RType = (RENext->Word1 >> 28) & 0xF;
+
+ if (RType != 1)
+ report_fatal_error("Expected ARM_RELOC_PAIR after "
+ "GENERIC_RELOC_HALF");
+
+ // NOTE: The half of the target virtual address is stashed in the
+ // address field of the secondary relocation, but we can't reverse
+ // engineer the constant offset from it without decoding the movw/movt
+ // instruction to find the other half in its immediate field.
+
+ // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
+ // symbol/section pointer of the follow-on relocation.
+ if (Type == macho::RIT_ARM_HalfDifference) {
+ fmt << "-";
+ printRelocationTargetName(RENext, fmt);
+ }
+
+ fmt << ")";
+ break;
+ }
+ default: {
+ printRelocationTargetName(RE, fmt);
+ }
+ }
+ }
+ } else
+ printRelocationTargetName(RE, fmt);
+
+ fmt.flush();
+ Result.append(fmtbuf.begin(), fmtbuf.end());
+ return object_error::success;
+}
+
+error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
+ bool &Result) const {
+ InMemoryStruct<macho::RelocationEntry> RE;
+ getRelocation(Rel, RE);
+
+ unsigned Arch = getArch();
+ bool isScattered = (Arch != Triple::x86_64) &&
+ (RE->Word0 & macho::RF_Scattered);
+ unsigned Type;
+ if (isScattered)
+ Type = (RE->Word0 >> 24) & 0xF;
+ else
+ Type = (RE->Word1 >> 28) & 0xF;
+
+ Result = false;
+
+ // On arches that use the generic relocations, GENERIC_RELOC_PAIR
+ // is always hidden.
+ if (Arch == Triple::x86 || Arch == Triple::arm) {
+ if (Type == macho::RIT_Pair) Result = true;
+ } else if (Arch == Triple::x86_64) {
+ // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
+ // an X864_64_RELOC_SUBTRACTOR.
+ if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
+ DataRefImpl RelPrev = Rel;
+ RelPrev.d.a--;
+ InMemoryStruct<macho::RelocationEntry> REPrev;
+ getRelocation(RelPrev, REPrev);
+
+ unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
+
+ if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
+ }
+ }
+
return object_error::success;
}
+error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
+ LibraryRef &Res) const {
+ report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
+}
+
+error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
+ StringRef &Res) const {
+ report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
+}
+
+
/*===-- Miscellaneous -----------------------------------------------------===*/
uint8_t MachOObjectFile::getBytesInAddress() const {
diff --git a/lib/Object/Object.cpp b/lib/Object/Object.cpp
index 2ea8db9..f061ea7 100644
--- a/lib/Object/Object.cpp
+++ b/lib/Object/Object.cpp
@@ -18,6 +18,7 @@
using namespace llvm;
using namespace object;
+// ObjectFile creation
LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) {
return wrap(ObjectFile::createObjectFile(unwrap(MemBuf)));
}
@@ -26,6 +27,7 @@ void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) {
delete unwrap(ObjectFile);
}
+// ObjectFile Section iterators
LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile) {
section_iterator SI = unwrap(ObjectFile)->begin_sections();
return wrap(new section_iterator(SI));
@@ -46,6 +48,34 @@ void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) {
if (ec) report_fatal_error("LLVMMoveToNextSection failed: " + ec.message());
}
+void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect,
+ LLVMSymbolIteratorRef Sym) {
+ if (error_code ec = (*unwrap(Sym))->getSection(*unwrap(Sect)))
+ report_fatal_error(ec.message());
+}
+
+// ObjectFile Symbol iterators
+LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef ObjectFile) {
+ symbol_iterator SI = unwrap(ObjectFile)->begin_symbols();
+ return wrap(new symbol_iterator(SI));
+}
+
+void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI) {
+ delete unwrap(SI);
+}
+
+LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef ObjectFile,
+ LLVMSymbolIteratorRef SI) {
+ return (*unwrap(SI) == unwrap(ObjectFile)->end_symbols()) ? 1 : 0;
+}
+
+void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI) {
+ error_code ec;
+ unwrap(SI)->increment(ec);
+ if (ec) report_fatal_error("LLVMMoveToNextSymbol failed: " + ec.message());
+}
+
+// SectionRef accessors
const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) {
StringRef ret;
if (error_code ec = (*unwrap(SI))->getName(ret))
@@ -66,3 +96,123 @@ const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) {
report_fatal_error(ec.message());
return ret.data();
}
+
+uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI) {
+ uint64_t ret;
+ if (error_code ec = (*unwrap(SI))->getAddress(ret))
+ report_fatal_error(ec.message());
+ return ret;
+}
+
+LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI,
+ LLVMSymbolIteratorRef Sym) {
+ bool ret;
+ if (error_code ec = (*unwrap(SI))->containsSymbol(**unwrap(Sym), ret))
+ report_fatal_error(ec.message());
+ return ret;
+}
+
+// Section Relocation iterators
+LLVMRelocationIteratorRef LLVMGetRelocations(LLVMSectionIteratorRef Section) {
+ relocation_iterator SI = (*unwrap(Section))->begin_relocations();
+ return wrap(new relocation_iterator(SI));
+}
+
+void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef SI) {
+ delete unwrap(SI);
+}
+
+LLVMBool LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section,
+ LLVMRelocationIteratorRef SI) {
+ return (*unwrap(SI) == (*unwrap(Section))->end_relocations()) ? 1 : 0;
+}
+
+void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI) {
+ error_code ec;
+ unwrap(SI)->increment(ec);
+ if (ec) report_fatal_error("LLVMMoveToNextRelocation failed: " +
+ ec.message());
+}
+
+
+// SymbolRef accessors
+const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) {
+ StringRef ret;
+ if (error_code ec = (*unwrap(SI))->getName(ret))
+ report_fatal_error(ec.message());
+ return ret.data();
+}
+
+uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) {
+ uint64_t ret;
+ if (error_code ec = (*unwrap(SI))->getAddress(ret))
+ report_fatal_error(ec.message());
+ return ret;
+}
+
+uint64_t LLVMGetSymbolFileOffset(LLVMSymbolIteratorRef SI) {
+ uint64_t ret;
+ if (error_code ec = (*unwrap(SI))->getFileOffset(ret))
+ report_fatal_error(ec.message());
+ return ret;
+}
+
+uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) {
+ uint64_t ret;
+ if (error_code ec = (*unwrap(SI))->getSize(ret))
+ report_fatal_error(ec.message());
+ return ret;
+}
+
+// RelocationRef accessors
+uint64_t LLVMGetRelocationAddress(LLVMRelocationIteratorRef RI) {
+ uint64_t ret;
+ if (error_code ec = (*unwrap(RI))->getAddress(ret))
+ report_fatal_error(ec.message());
+ return ret;
+}
+
+uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI) {
+ uint64_t ret;
+ if (error_code ec = (*unwrap(RI))->getOffset(ret))
+ report_fatal_error(ec.message());
+ return ret;
+}
+
+LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI) {
+ SymbolRef ret;
+ if (error_code ec = (*unwrap(RI))->getSymbol(ret))
+ report_fatal_error(ec.message());
+
+ return wrap(new symbol_iterator(ret));
+}
+
+uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) {
+ uint64_t ret;
+ if (error_code ec = (*unwrap(RI))->getType(ret))
+ report_fatal_error(ec.message());
+ return ret;
+}
+
+// NOTE: Caller takes ownership of returned string.
+const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) {
+ SmallVector<char, 0> ret;
+ if (error_code ec = (*unwrap(RI))->getTypeName(ret))
+ report_fatal_error(ec.message());
+
+ char *str = static_cast<char*>(malloc(ret.size()));
+ std::copy(ret.begin(), ret.end(), str);
+ return str;
+}
+
+// NOTE: Caller takes ownership of returned string.
+const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) {
+ SmallVector<char, 0> ret;
+ if (error_code ec = (*unwrap(RI))->getValueString(ret))
+ report_fatal_error(ec.message());
+
+ char *str = static_cast<char*>(malloc(ret.size()));
+ std::copy(ret.begin(), ret.end(), str);
+ return str;
+}
+
diff --git a/lib/Object/ObjectFile.cpp b/lib/Object/ObjectFile.cpp
index 69d8ed0..b14df9a 100644
--- a/lib/Object/ObjectFile.cpp
+++ b/lib/Object/ObjectFile.cpp
@@ -21,6 +21,8 @@
using namespace llvm;
using namespace object;
+void ObjectFile::anchor() { }
+
ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *source, error_code &ec)
: Binary(Type, source) {
}
@@ -56,7 +58,7 @@ ObjectFile *ObjectFile::createObjectFile(MemoryBuffer *Object) {
ObjectFile *ObjectFile::createObjectFile(StringRef ObjectPath) {
OwningPtr<MemoryBuffer> File;
- if (error_code ec = MemoryBuffer::getFile(ObjectPath, File))
+ if (MemoryBuffer::getFile(ObjectPath, File))
return NULL;
return createObjectFile(File.take());
}
OpenPOWER on IntegriCloud