summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Anderson <resistor@mac.com>2011-10-24 23:20:07 +0000
committerOwen Anderson <resistor@mac.com>2011-10-24 23:20:07 +0000
commitd8fa76d4bed067cd8662c3196211bc90cc8d4470 (patch)
treed95842c82a00a7f783db69b6f16ef95c93cc0ddc
parent5c89cb8cd613c5a9d2bb2d6ab68afe8c2b41db70 (diff)
downloadllvm-d8fa76d4bed067cd8662c3196211bc90cc8d4470.tar.gz
llvm-d8fa76d4bed067cd8662c3196211bc90cc8d4470.tar.bz2
llvm-d8fa76d4bed067cd8662c3196211bc90cc8d4470.tar.xz
More fixes and improvements to MachO relocation pretty-printing, particular for x86 and x86_64 relocations with addends.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@142875 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Object/MachO.h2
-rw-r--r--lib/Object/MachOObjectFile.cpp158
2 files changed, 129 insertions, 31 deletions
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index 0962994be2..1ae9372bbd 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -108,6 +108,8 @@ private:
void getRelocation(DataRefImpl Rel,
InMemoryStruct<macho::RelocationEntry> &Res) const;
std::size_t getSectionIndex(DataRefImpl Sec) const;
+
+ error_code getRelocationTargetName(uint32_t Idx, StringRef &S) const;
};
}
diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
index 5bf03ff72a..09500206b5 100644
--- a/lib/Object/MachOObjectFile.cpp
+++ b/lib/Object/MachOObjectFile.cpp
@@ -666,14 +666,18 @@ error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
}
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_SIGNED",
- "X86_64_RELOC_UNSIGNED",
- "X86_64_RELOC_SUBTRACTOR" };
+ "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 > 5)
+ if (r_type > 9)
res = "Unknown";
else
res = Table[r_type];
@@ -748,46 +752,138 @@ 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());
+}
+
+error_code
+MachOObjectFile::getRelocationTargetName(uint32_t Idx, StringRef &S) const {
+ bool isExtern = (Idx >> 27) & 1;
+ uint32_t Val = Idx & 0xFFFFFF;
+ error_code ec;
+
+ if (isExtern) {
+ symbol_iterator SI = begin_symbols();
+ advanceTo(SI, Val);
+ ec = SI->getName(S);
+ } else {
+ section_iterator SI = begin_sections();
+ advanceTo(SI, Val);
+ ec = SI->getName(S);
+ }
+
+ return ec;
+}
+
error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const {
InMemoryStruct<macho::RelocationEntry> RE;
getRelocation(Rel, RE);
- std::string fmtbuf;
- raw_string_ostream fmt(fmtbuf);
+ std::string addend;
+ raw_string_ostream addend_fmt(addend);
- bool isExtern = (RE->Word1 >> 27) & 1;
- if (isExtern) {
- uint32_t Val = (RE->Word1 & 0xFFFFFF);
- symbol_iterator SI = begin_symbols();
+ bool isPCRel = (RE->Word1 >> 25) & 1;
+ unsigned Type = (RE->Word1 >> 28) & 0xF;
+
+ // Determine any addends that should be displayed with the relocation.
+ // These require decoding the relocation type, which is triple-specific.
+ unsigned Arch = getArch();
- error_code ec;
- while (Val--) {
- SI.increment(ec);
- if (ec) report_fatal_error(ec.message());
+ // X86_64 has entirely custom relocation types.
+ if (Arch == Triple::x86_64) {
+ switch (Type) {
+ case 5: { // X86_64_RELOC_SUBTRACTOR
+ RelocationRef NextReloc;
+ if (error_code ec = getRelocationNext(Rel, NextReloc))
+ report_fatal_error(ec.message());
+
+ uint32_t SucessorType;
+ if (error_code ec = NextReloc.getType(SucessorType))
+ report_fatal_error(ec.message());
+
+ // X86_64_SUBTRACTOR must be followed by a relocation of type
+ // X86_64_RELOC_UNSIGNED.
+ unsigned RType = (SucessorType >> 28) & 0xF;
+ if (RType != 0)
+ report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
+ "X86_64_RELOC_SUBTRACTOR.");
+
+ StringRef Name;
+ if (error_code ec = getRelocationTargetName(SucessorType, Name))
+ report_fatal_error(ec.message());
+
+ addend_fmt << "-" << Name;
+ }
+ case 6: // X86_64_RELOC_SIGNED1
+ addend_fmt << "-1";
+ break;
+ case 7: // X86_64_RELOC_SIGNED2
+ addend_fmt << "-2";
+ break;
+ case 8: // X86_64_RELOC_SIGNED4
+ addend_fmt << "-4";
+ break;
}
+ }
- StringRef SymName;
- if ((ec = SI->getName(SymName)))
- report_fatal_error(ec.message());
+ // X86 and ARM share some relocation types in common.
+ if (Arch == Triple::x86 || Arch == Triple::arm) {
+ switch (Type) {
+ case 1: // GENERIC_RELOC_PAIR - prints no info
+ return object_error::success;
+ case 2: // GENERIC_RELOC_SECTDIFF
+ case 4: { // GENERIC_RELOC_LOCAL_SECTDIFF
+ RelocationRef NextReloc;
+ if (error_code ec = getRelocationNext(Rel, NextReloc))
+ report_fatal_error(ec.message());
+
+ uint32_t SucessorType;
+ if (error_code ec = NextReloc.getType(SucessorType))
+ report_fatal_error(ec.message());
+
+ // X86 sect diff's must be followed by a relocation of type
+ // GENERIC_RELOC_PAIR.
+ unsigned RType = (SucessorType >> 28) & 0xF;
+ if (RType != 1)
+ report_fatal_error("Expected GENERIC_RELOC_PAIR after "
+ "GENERIC_RELOC_SECTDIFF or "
+ "GENERIC_RELOC_LOCAL_SECTDIFF.");
+
+ StringRef Name;
+ if (error_code ec = getRelocationTargetName(SucessorType, Name))
+ report_fatal_error(ec.message());
+
+ addend_fmt << "-" << Name;
+
+ }
+ }
+ }
- fmt << SymName;
- } else {
- uint32_t Val = (RE->Word1 & 0xFFFFFF);
- section_iterator SI = begin_sections();
+ addend_fmt.flush();
- error_code ec;
- while (Val--) {
- SI.increment(ec);
- if (ec) report_fatal_error(ec.message());
- }
+ std::string fmtbuf;
+ raw_string_ostream fmt(fmtbuf);
- StringRef SectName;
- if ((ec = SI->getName(SectName)))
- report_fatal_error(ec.message());
+ StringRef Name;
+ if (error_code ec = getRelocationTargetName(RE->Word1, Name))
+ report_fatal_error(ec.message());
- fmt << SectName;
- }
+ fmt << Name << addend;
+ if (isPCRel) fmt << "-P";
fmt.flush();
Result.append(fmtbuf.begin(), fmtbuf.end());