diff options
author | Eric Christopher <echristo@gmail.com> | 2012-11-07 23:22:07 +0000 |
---|---|---|
committer | Eric Christopher <echristo@gmail.com> | 2012-11-07 23:22:07 +0000 |
commit | 806e03d2381709ddfb5a8012729bbe6eae12caf5 (patch) | |
tree | d01da4fb8a09017a564b27968af88dc1fb82084d | |
parent | b0319962cfdb18da38ef47da621f148fe144b092 (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
-rw-r--r-- | include/llvm/DebugInfo/DIContext.h | 11 | ||||
-rw-r--r-- | include/llvm/Object/RelocVisitor.h | 131 | ||||
-rw-r--r-- | include/llvm/Support/DataExtractor.h | 1 | ||||
-rw-r--r-- | lib/DebugInfo/DIContext.cpp | 5 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFContext.h | 11 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFFormValue.cpp | 25 | ||||
-rw-r--r-- | test/DebugInfo/X86/elf-names.ll | 109 | ||||
-rw-r--r-- | tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 59 |
8 files changed, 341 insertions, 11 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" diff --git a/lib/DebugInfo/DIContext.cpp b/lib/DebugInfo/DIContext.cpp index ead57f9715..691a92c392 100644 --- a/lib/DebugInfo/DIContext.cpp +++ b/lib/DebugInfo/DIContext.cpp @@ -19,8 +19,9 @@ DIContext *DIContext::getDWARFContext(bool isLittleEndian, StringRef aRangeSection, StringRef lineSection, StringRef stringSection, - StringRef rangeSection) { + StringRef rangeSection, + const RelocAddrMap &Map) { return new DWARFContextInMemory(isLittleEndian, infoSection, abbrevSection, aRangeSection, lineSection, stringSection, - rangeSection); + rangeSection, Map); } diff --git a/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h index d10e850870..4001792b3d 100644 --- a/lib/DebugInfo/DWARFContext.h +++ b/lib/DebugInfo/DWARFContext.h @@ -26,6 +26,7 @@ namespace llvm { /// methods that a concrete implementation provides. class DWARFContext : public DIContext { bool IsLittleEndian; + const RelocAddrMap &RelocMap; SmallVector<DWARFCompileUnit, 1> CUs; OwningPtr<DWARFDebugAbbrev> Abbrev; @@ -38,9 +39,11 @@ class DWARFContext : public DIContext { /// Read compile units from the debug_info section and store them in CUs. void parseCompileUnits(); protected: - DWARFContext(bool isLittleEndian) : IsLittleEndian(isLittleEndian) {} + DWARFContext(bool isLittleEndian, const RelocAddrMap &Map) : + IsLittleEndian(isLittleEndian), RelocMap(Map) {} public: virtual void dump(raw_ostream &OS); + /// Get the number of compile units in this context. unsigned getNumCompileUnits() { if (CUs.empty()) @@ -70,6 +73,7 @@ public: DILineInfoSpecifier Specifier = DILineInfoSpecifier()); bool isLittleEndian() const { return IsLittleEndian; } + const RelocAddrMap &relocMap() const { return RelocMap; } virtual StringRef getInfoSection() = 0; virtual StringRef getAbbrevSection() = 0; @@ -108,8 +112,9 @@ public: StringRef aRangeSection, StringRef lineSection, StringRef stringSection, - StringRef rangeSection) - : DWARFContext(isLittleEndian), + StringRef rangeSection, + const RelocAddrMap &Map = RelocAddrMap()) + : DWARFContext(isLittleEndian, Map), InfoSection(infoSection), AbbrevSection(abbrevSection), ARangeSection(aRangeSection), diff --git a/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp index c9ecbbbbd4..fea9fd7f7d 100644 --- a/lib/DebugInfo/DWARFFormValue.cpp +++ b/lib/DebugInfo/DWARFFormValue.cpp @@ -10,6 +10,7 @@ #include "DWARFFormValue.h" #include "DWARFCompileUnit.h" #include "DWARFContext.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -98,8 +99,16 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, indirect = false; switch (Form) { case DW_FORM_addr: - case DW_FORM_ref_addr: - Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize()); + case DW_FORM_ref_addr: { + RelocAddrMap::const_iterator AI + = cu->getContext().relocMap().find(*offset_ptr); + if (AI != cu->getContext().relocMap().end()) { + const std::pair<uint8_t, int64_t> &R = AI->second; + Value.uval = R.second; + *offset_ptr += R.first; + } else + Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize()); + } break; case DW_FORM_exprloc: case DW_FORM_block: @@ -138,9 +147,17 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, case DW_FORM_sdata: Value.sval = data.getSLEB128(offset_ptr); break; - case DW_FORM_strp: - Value.uval = data.getU32(offset_ptr); + case DW_FORM_strp: { + RelocAddrMap::const_iterator AI + = cu->getContext().relocMap().find(*offset_ptr); + if (AI != cu->getContext().relocMap().end()) { + const std::pair<uint8_t, int64_t> &R = AI->second; + Value.uval = R.second; + *offset_ptr += R.first; + } else + Value.uval = data.getU32(offset_ptr); break; + } case DW_FORM_udata: case DW_FORM_ref_udata: Value.uval = data.getULEB128(offset_ptr); diff --git a/test/DebugInfo/X86/elf-names.ll b/test/DebugInfo/X86/elf-names.ll new file mode 100644 index 0000000000..b908bcefe4 --- /dev/null +++ b/test/DebugInfo/X86/elf-names.ll @@ -0,0 +1,109 @@ +; RUN: llc -mtriple=x86_64-unknown-linux-gnu %s -o %t -filetype=obj +; RUN: llvm-dwarfdump %t | FileCheck %s + +; CHECK: 0x0000000b: DW_TAG_compile_unit +; CHECK: 0x00000012: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000035] = "foo.cpp") +; CHECK: 0x0000003c: DW_TAG_class_type +; CHECK: 0x0000003d: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000006d] = "D") +; CHECK: 0x00000044: DW_TAG_member +; CHECK: 0x00000045: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000005d] = "c1") + +%class.D = type { i32, i32, i32, i32 } + +@_ZN1DC1Ev = alias void (%class.D*)* @_ZN1DC2Ev +@_ZN1DC1ERKS_ = alias void (%class.D*, %class.D*)* @_ZN1DC2ERKS_ + +define void @_ZN1DC2Ev(%class.D* nocapture %this) unnamed_addr nounwind uwtable align 2 { +entry: + tail call void @llvm.dbg.value(metadata !{%class.D* %this}, i64 0, metadata !29), !dbg !36 + %c1 = getelementptr inbounds %class.D* %this, i64 0, i32 0, !dbg !37 + store i32 1, i32* %c1, align 4, !dbg !37, !tbaa !39 + %c2 = getelementptr inbounds %class.D* %this, i64 0, i32 1, !dbg !42 + store i32 2, i32* %c2, align 4, !dbg !42, !tbaa !39 + %c3 = getelementptr inbounds %class.D* %this, i64 0, i32 2, !dbg !43 + store i32 3, i32* %c3, align 4, !dbg !43, !tbaa !39 + %c4 = getelementptr inbounds %class.D* %this, i64 0, i32 3, !dbg !44 + store i32 4, i32* %c4, align 4, !dbg !44, !tbaa !39 + ret void, !dbg !45 +} + +define void @_ZN1DC2ERKS_(%class.D* nocapture %this, %class.D* nocapture %d) unnamed_addr nounwind uwtable align 2 { +entry: + tail call void @llvm.dbg.value(metadata !{%class.D* %this}, i64 0, metadata !34), !dbg !46 + tail call void @llvm.dbg.value(metadata !{%class.D* %d}, i64 0, metadata !35), !dbg !46 + %c1 = getelementptr inbounds %class.D* %d, i64 0, i32 0, !dbg !47 + %0 = load i32* %c1, align 4, !dbg !47, !tbaa !39 + %c12 = getelementptr inbounds %class.D* %this, i64 0, i32 0, !dbg !47 + store i32 %0, i32* %c12, align 4, !dbg !47, !tbaa !39 + %c2 = getelementptr inbounds %class.D* %d, i64 0, i32 1, !dbg !49 + %1 = load i32* %c2, align 4, !dbg !49, !tbaa !39 + %c23 = getelementptr inbounds %class.D* %this, i64 0, i32 1, !dbg !49 + store i32 %1, i32* %c23, align 4, !dbg !49, !tbaa !39 + %c3 = getelementptr inbounds %class.D* %d, i64 0, i32 2, !dbg !50 + %2 = load i32* %c3, align 4, !dbg !50, !tbaa !39 + %c34 = getelementptr inbounds %class.D* %this, i64 0, i32 2, !dbg !50 + store i32 %2, i32* %c34, align 4, !dbg !50, !tbaa !39 + %c4 = getelementptr inbounds %class.D* %d, i64 0, i32 3, !dbg !51 + %3 = load i32* %c4, align 4, !dbg !51, !tbaa !39 + %c45 = getelementptr inbounds %class.D* %this, i64 0, i32 3, !dbg !51 + store i32 %3, i32* %c45, align 4, !dbg !51, !tbaa !39 + ret void, !dbg !52 +} + +declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone + +!llvm.dbg.cu = !{!0} + +!0 = metadata !{i32 786449, i32 0, i32 4, metadata !"foo.cpp", metadata !"/usr/local/google/home/echristo", metadata !"clang version 3.2 (trunk 167506) (llvm/trunk 167505)", i1 true, i1 true, metadata !"", i32 0, metadata !1, metadata !1, metadata !3, metadata !1} ; [ DW_TAG_compile_unit ] [/usr/local/google/home/echristo/foo.cpp] [DW_LANG_C_plus_plus] +!1 = metadata !{metadata !2} +!2 = metadata !{i32 0} +!3 = metadata !{metadata !4} +!4 = metadata !{metadata !5, metadata !31} +!5 = metadata !{i32 786478, i32 0, null, metadata !"D", metadata !"D", metadata !"_ZN1DC2Ev", metadata !6, i32 12, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, void (%class.D*)* @_ZN1DC2Ev, null, metadata !17, metadata !27, i32 12} ; [ DW_TAG_subprogram ] [line 12] [def] [D] +!6 = metadata !{i32 786473, metadata !"foo.cpp", metadata !"/usr/local/google/home/echristo", null} ; [ DW_TAG_file_type ] +!7 = metadata !{i32 786453, i32 0, metadata !"", i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !8, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!8 = metadata !{null, metadata !9} +!9 = metadata !{i32 786447, i32 0, metadata !"", i32 0, i32 0, i64 64, i64 64, i64 0, i32 1088, metadata !10} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from D] +!10 = metadata !{i32 786434, null, metadata !"D", metadata !6, i32 1, i64 128, i64 32, i32 0, i32 0, null, metadata !11, i32 0, null, null} ; [ DW_TAG_class_type ] [D] [line 1, size 128, align 32, offset 0] [from ] +!11 = metadata !{metadata !12, metadata !14, metadata !15, metadata !16, metadata !17, metadata !20} +!12 = metadata !{i32 786445, metadata !10, metadata !"c1", metadata !6, i32 6, i64 32, i64 32, i64 0, i32 1, metadata !13} ; [ DW_TAG_member ] [c1] [line 6, size 32, align 32, offset 0] [private] [from int] +!13 = metadata !{i32 786468, null, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!14 = metadata !{i32 786445, metadata !10, metadata !"c2", metadata !6, i32 7, i64 32, i64 32, i64 32, i32 1, metadata !13} ; [ DW_TAG_member ] [c2] [line 7, size 32, align 32, offset 32] [private] [from int] +!15 = metadata !{i32 786445, metadata !10, metadata !"c3", metadata !6, i32 8, i64 32, i64 32, i64 64, i32 1, metadata !13} ; [ DW_TAG_member ] [c3] [line 8, size 32, align 32, offset 64] [private] [from int] +!16 = metadata !{i32 786445, metadata !10, metadata !"c4", metadata !6, i32 9, i64 32, i64 32, i64 96, i32 1, metadata !13} ; [ DW_TAG_member ] [c4] [line 9, size 32, align 32, offset 96] [private] [from int] +!17 = metadata !{i32 786478, i32 0, metadata !10, metadata !"D", metadata !"D", metadata !"", metadata !6, i32 3, metadata !7, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 true, null, null, i32 0, metadata !18, i32 3} ; [ DW_TAG_subprogram ] [line 3] [D] +!18 = metadata !{metadata !19} +!19 = metadata !{i32 786468} ; [ DW_TAG_base_type ] [line 0, size 0, align 0, offset 0] +!20 = metadata !{i32 786478, i32 0, metadata !10, metadata !"D", metadata !"D", metadata !"", metadata !6, i32 4, metadata !21, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 true, null, null, i32 0, metadata !25, i32 4} ; [ DW_TAG_subprogram ] [line 4] [D] +!21 = metadata !{i32 786453, i32 0, metadata !"", i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !22, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!22 = metadata !{null, metadata !9, metadata !23} +!23 = metadata !{i32 786448, null, null, null, i32 0, i64 0, i64 0, i64 0, i32 0, metadata !24} ; [ DW_TAG_reference_type ] [line 0, size 0, align 0, offset 0] [from ] +!24 = metadata !{i32 786470, null, metadata !"", null, i32 0, i64 0, i64 0, i64 0, i32 0, metadata !10} ; [ DW_TAG_const_type ] [line 0, size 0, align 0, offset 0] [from D] +!25 = metadata !{metadata !26} +!26 = metadata !{i32 786468} ; [ DW_TAG_base_type ] [line 0, size 0, align 0, offset 0] +!27 = metadata !{metadata !28} +!28 = metadata !{metadata !29} +!29 = metadata !{i32 786689, metadata !5, metadata !"this", metadata !6, i32 16777228, metadata !30, i32 1088, i32 0} ; [ DW_TAG_arg_variable ] [this] [line 12] +!30 = metadata !{i32 786447, null, metadata !"", null, i32 0, i64 64, i64 64, i64 0, i32 0, metadata !10} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from D] +!31 = metadata !{i32 786478, i32 0, null, metadata !"D", metadata !"D", metadata !"_ZN1DC2ERKS_", metadata !6, i32 19, metadata !21, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, void (%class.D*, %class.D*)* @_ZN1DC2ERKS_, null, metadata !20, metadata !32, i32 19} ; [ DW_TAG_subprogram ] [line 19] [def] [D] +!32 = metadata !{metadata !33} +!33 = metadata !{metadata !34, metadata !35} +!34 = metadata !{i32 786689, metadata !31, metadata !"this", metadata !6, i32 16777235, metadata !30, i32 1088, i32 0} ; [ DW_TAG_arg_variable ] [this] [line 19] +!35 = metadata !{i32 786689, metadata !31, metadata !"d", metadata !6, i32 33554451, metadata !23, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [d] [line 19] +!36 = metadata !{i32 12, i32 0, metadata !5, null} +!37 = metadata !{i32 13, i32 0, metadata !38, null} +!38 = metadata !{i32 786443, metadata !5, i32 12, i32 0, metadata !6, i32 0} ; [ DW_TAG_lexical_block ] [/usr/local/google/home/echristo/foo.cpp] +!39 = metadata !{metadata !"int", metadata !40} +!40 = metadata !{metadata !"omnipotent char", metadata !41} +!41 = metadata !{metadata !"Simple C/C++ TBAA"} +!42 = metadata !{i32 14, i32 0, metadata !38, null} +!43 = metadata !{i32 15, i32 0, metadata !38, null} +!44 = metadata !{i32 16, i32 0, metadata !38, null} +!45 = metadata !{i32 17, i32 0, metadata !38, null} +!46 = metadata !{i32 19, i32 0, metadata !31, null} +!47 = metadata !{i32 20, i32 0, metadata !48, null} +!48 = metadata !{i32 786443, metadata !31, i32 19, i32 0, metadata !6, i32 1} ; [ DW_TAG_lexical_block ] [/usr/local/google/home/echristo/foo.cpp] +!49 = metadata !{i32 21, i32 0, metadata !48, null} +!50 = metadata !{i32 22, i32 0, metadata !48, null} +!51 = metadata !{i32 23, i32 0, metadata !48, null} +!52 = metadata !{i32 24, i32 0, metadata !48, null} diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index 309bc4ecd4..e73300a0cd 100644 --- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -15,6 +15,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Object/RelocVisitor.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -28,6 +29,9 @@ #include "llvm/Support/system_error.h" #include <algorithm> #include <cstring> +#include <list> +#include <string> + using namespace llvm; using namespace object; @@ -67,6 +71,7 @@ static void DumpInput(const StringRef &Filename) { OwningPtr<ObjectFile> Obj(ObjectFile::createObjectFile(Buff.take())); StringRef DebugInfoSection; + RelocAddrMap RelocMap; StringRef DebugAbbrevSection; StringRef DebugLineSection; StringRef DebugArangesSection; @@ -97,6 +102,57 @@ static void DumpInput(const StringRef &Filename) { DebugStringSection = data; else if (name == "debug_ranges") DebugRangesSection = data; + // Any more debug info sections go here. + else + continue; + + // TODO: For now only handle relocations for the debug_info section. + if (name != "debug_info") + continue; + + if (i->begin_relocations() != i->end_relocations()) { + uint64_t SectionSize; + i->getSize(SectionSize); + for (relocation_iterator reloc_i = i->begin_relocations(), + reloc_e = i->end_relocations(); + reloc_i != reloc_e; reloc_i.increment(ec)) { + uint64_t Address; + reloc_i->getAddress(Address); + uint64_t Type; + reloc_i->getType(Type); + + RelocVisitor V(Obj->getFileFormatName()); + // The section address is always 0 for debug sections. + RelocToApply R(V.visit(Type, *reloc_i)); + if (V.error()) { + SmallString<32> Name; + error_code ec(reloc_i->getTypeName(Name)); + if (ec) { + errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n"; + } + errs() << "error: failed to compute relocation: " + << Name << "\n"; + continue; + } + + if (Address + R.Width > SectionSize) { + errs() << "error: " << R.Width << "-byte relocation starting " + << Address << " bytes into section " << name << " which is " + << SectionSize << " bytes long.\n"; + continue; + } + if (R.Width > 8) { + errs() << "error: can't handle a relocation of more than 8 bytes at " + "a time.\n"; + continue; + } + DEBUG(dbgs() << "Writing " << format("%p", R.Value) + << " at " << format("%p", Address) + << " with width " << format("%d", R.Width) + << "\n"); + RelocMap[Address] = std::make_pair(R.Width, R.Value); + } + } } OwningPtr<DIContext> dictx(DIContext::getDWARFContext(/*FIXME*/true, @@ -105,7 +161,8 @@ static void DumpInput(const StringRef &Filename) { DebugArangesSection, DebugLineSection, DebugStringSection, - DebugRangesSection)); + DebugRangesSection, + RelocMap)); if (Address == -1ULL) { outs() << Filename << ":\tfile format " << Obj->getFileFormatName() << "\n\n"; |