aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorEric Christopher <echristo@gmail.com>2012-11-07 23:22:07 +0000
committerEric Christopher <echristo@gmail.com>2012-11-07 23:22:07 +0000
commit806e03d2381709ddfb5a8012729bbe6eae12caf5 (patch)
treed01da4fb8a09017a564b27968af88dc1fb82084d /include
parentb0319962cfdb18da38ef47da621f148fe144b092 (diff)
Add a relocation visitor to lib object. This works via caching relocated
values in a map that can be passed to consumers. Add a testcase that ensures this works for llvm-dwarfdump. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167558 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r--include/llvm/DebugInfo/DIContext.h11
-rw-r--r--include/llvm/Object/RelocVisitor.h131
-rw-r--r--include/llvm/Support/DataExtractor.h1
3 files changed, 142 insertions, 1 deletions
diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h
index 8d6054aa45..2e34bacdd3 100644
--- a/include/llvm/DebugInfo/DIContext.h
+++ b/include/llvm/DebugInfo/DIContext.h
@@ -15,6 +15,7 @@
#ifndef LLVM_DEBUGINFO_DICONTEXT_H
#define LLVM_DEBUGINFO_DICONTEXT_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
@@ -89,6 +90,13 @@ public:
}
};
+// In place of applying the relocations to the data we've read from disk we use
+// a separate mapping table to the side and checking that at locations in the dwarf
+// we expec relocated values. This adds a bit of complexity to the dwarf
+// parsing/extraction at the benefit of not allocating memory for the entire
+// size of the debug info sections.
+typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t> > RelocAddrMap;
+
class DIContext {
public:
virtual ~DIContext();
@@ -100,7 +108,8 @@ public:
StringRef aRangeSection = StringRef(),
StringRef lineSection = StringRef(),
StringRef stringSection = StringRef(),
- StringRef rangeSection = StringRef());
+ StringRef rangeSection = StringRef(),
+ const RelocAddrMap &Map = RelocAddrMap());
virtual void dump(raw_ostream &OS) = 0;
diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h
new file mode 100644
index 0000000000..7668bdedb7
--- /dev/null
+++ b/include/llvm/Object/RelocVisitor.h
@@ -0,0 +1,131 @@
+//===-- RelocVisitor.h - Visitor for object file relocations -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides a wrapper around all the different types of relocations
+// in different file formats, such that a client can handle them in a unified
+// manner by only implementing a minimal number of functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LLVM_OBJECT_RELOCVISITOR
+#define _LLVM_OBJECT_RELOCVISITOR
+
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+namespace object {
+
+struct RelocToApply {
+ // The computed value after applying the relevant relocations.
+ int64_t Value;
+
+ // The width of the value; how many bytes to touch when applying the
+ // relocation.
+ char Width;
+ RelocToApply(const RelocToApply &In) : Value(In.Value), Width(In.Width) {}
+ RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {}
+ RelocToApply() : Value(0), Width(0) {}
+};
+
+/// @brief Base class for object file relocation visitors.
+class RelocVisitor {
+public:
+ explicit RelocVisitor(llvm::StringRef FileFormat)
+ : FileFormat(FileFormat), HasError(false) {}
+
+ // TODO: Should handle multiple applied relocations via either passing in the
+ // previously computed value or just count paired relocations as a single
+ // visit.
+ RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t SecAddr = 0,
+ uint64_t Value = 0) {
+ if (FileFormat == "ELF64-x86-64") {
+ switch (RelocType) {
+ case llvm::ELF::R_X86_64_NONE:
+ return visitELF_X86_64_NONE(R);
+ case llvm::ELF::R_X86_64_64:
+ return visitELF_X86_64_64(R, Value);
+ case llvm::ELF::R_X86_64_PC32:
+ return visitELF_X86_64_PC32(R, Value, SecAddr);
+ case llvm::ELF::R_X86_64_32:
+ return visitELF_X86_64_32(R, Value);
+ case llvm::ELF::R_X86_64_32S:
+ return visitELF_X86_64_32S(R, Value);
+ default:
+ HasError = true;
+ return RelocToApply();
+ }
+ }
+ return RelocToApply();
+ }
+
+ bool error() { return HasError; }
+
+private:
+ llvm::StringRef FileFormat;
+ bool HasError;
+
+ /// Operations
+
+ // Width is the width in bytes of the extend.
+ RelocToApply zeroExtend(RelocToApply r, char Width) {
+ if (Width == r.Width)
+ return r;
+ r.Value &= (1 << ((Width * 8))) - 1;
+ return r;
+ }
+ RelocToApply signExtend(RelocToApply r, char Width) {
+ if (Width == r.Width)
+ return r;
+ bool SignBit = r.Value & (1 << ((Width * 8) - 1));
+ if (SignBit) {
+ r.Value |= ~((1 << (Width * 8)) - 1);
+ } else {
+ r.Value &= (1 << (Width * 8)) - 1;
+ }
+ return r;
+ }
+
+ /// X86-64 ELF
+ RelocToApply visitELF_X86_64_NONE(RelocationRef R) {
+ return RelocToApply(0, 0);
+ }
+ RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
+ int64_t Addend;
+ R.getAdditionalInfo(Addend);
+ return RelocToApply(Value + Addend, 8);
+ }
+ RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value,
+ uint64_t SecAddr) {
+ int64_t Addend;
+ R.getAdditionalInfo(Addend);
+ uint64_t Address;
+ R.getAddress(Address);
+ return RelocToApply(Value + Addend - Address, 4);
+ }
+ RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
+ int64_t Addend;
+ R.getAdditionalInfo(Addend);
+ uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
+ return RelocToApply(Res, 4);
+ }
+ RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
+ int64_t Addend;
+ R.getAdditionalInfo(Addend);
+ int32_t Res = (Value + Addend) & 0xFFFFFFFF;
+ return RelocToApply(Res, 4);
+ }
+};
+
+}
+}
+#endif
diff --git a/include/llvm/Support/DataExtractor.h b/include/llvm/Support/DataExtractor.h
index 8d880fd5e8..a3ae782040 100644
--- a/include/llvm/Support/DataExtractor.h
+++ b/include/llvm/Support/DataExtractor.h
@@ -10,6 +10,7 @@
#ifndef LLVM_SUPPORT_DATAEXTRACTOR_H
#define LLVM_SUPPORT_DATAEXTRACTOR_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"