From: Owen Anderson Date: Mon, 24 Oct 2011 21:44:00 +0000 (+0000) Subject: Get relocation parsing/dumping to a mostly-working state for MachO files. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=0135fe1854bef035efea1e3113dc6a127ef6e51e;p=oota-llvm.git Get relocation parsing/dumping to a mostly-working state for MachO files. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@142852 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 19396be05d3..5bf03ff72ad 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -16,6 +16,7 @@ #include "llvm/Object/MachO.h" #include "llvm/Object/MachOFormat.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" #include #include @@ -596,15 +597,15 @@ 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 Sect; getSection64(Sections[Rel.d.b], Sect); - sectAddress += Sect->Offset; + sectAddress += Sect->Address; } else { InMemoryStruct Sect; getSection(Sections[Rel.d.b], Sect); - sectAddress += Sect->Offset; + sectAddress += Sect->Address; } InMemoryStruct RE; getRelocation(Rel, RE); @@ -641,7 +642,88 @@ error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, } error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const { - StringRef res = "Unknown"; + // TODO: Support scattered relocations. + StringRef res; + InMemoryStruct RE; + getRelocation(Rel, RE); + unsigned r_type = (RE->Word1 >> 28) & 0xF; + + unsigned Arch = getArch(); + switch (Arch) { + case Triple::x86: { + const char* Table[] = { + "GENERIC_RELOC_VANILLA", + "GENERIC_RELOC_PAIR", + "GENERIC_RELOC_SECTDIFF", + "GENERIC_RELOC_LOCAL_SECTDIFF", + "GENERIC_RELOC_PB_LA_PTR" }; + + if (r_type > 4) + res = "Unknown"; + else + res = Table[r_type]; + break; + } + case Triple::x86_64: { + const char* Table[] = { + "X86_64_RELOC_BRANCH", + "X86_64_RELOC_GOT_LOAD", + "X86_64_RELOC_GOT", + "X86_64_RELOC_SIGNED", + "X86_64_RELOC_UNSIGNED", + "X86_64_RELOC_SUBTRACTOR" }; + + if (r_type > 5) + 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; } @@ -668,8 +750,47 @@ error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, } error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const { - StringRef res = "Unknown"; - Result.append(res.begin(), res.end()); + InMemoryStruct RE; + getRelocation(Rel, RE); + + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + + bool isExtern = (RE->Word1 >> 27) & 1; + if (isExtern) { + uint32_t Val = (RE->Word1 & 0xFFFFFF); + symbol_iterator SI = begin_symbols(); + + error_code ec; + while (Val--) { + SI.increment(ec); + if (ec) report_fatal_error(ec.message()); + } + + StringRef SymName; + if ((ec = SI->getName(SymName))) + report_fatal_error(ec.message()); + + fmt << SymName; + } else { + uint32_t Val = (RE->Word1 & 0xFFFFFF); + section_iterator SI = begin_sections(); + + error_code ec; + while (Val--) { + SI.increment(ec); + if (ec) report_fatal_error(ec.message()); + } + + StringRef SectName; + if ((ec = SI->getName(SectName))) + report_fatal_error(ec.message()); + + fmt << SectName; + } + + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); return object_error::success; }