diff options
| author | Fangrui Song <maskray@google.com> | 2019-03-22 02:43:11 +0000 |
|---|---|---|
| committer | Fangrui Song <maskray@google.com> | 2019-03-22 02:43:11 +0000 |
| commit | 4597dce48319437a80db95153f65e289832f979b (patch) | |
| tree | cc2a7741e814700dfa955f0bec7ba271c2c8cdd2 /llvm/lib/DebugInfo | |
| parent | 1955c8f17267dc263aa7dfb2404341de05fdacaf (diff) | |
| download | bcm5719-llvm-4597dce48319437a80db95153f65e289832f979b.tar.gz bcm5719-llvm-4597dce48319437a80db95153f65e289832f979b.zip | |
[DWARF] Refactor RelocVisitor and fix computation of SHT_RELA-typed relocation entries
Summary:
getRelocatedValue may compute incorrect value for SHT_RELA-typed relocation entries.
// DWARFDataExtractor.cpp
uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off,
...
// This formula is correct for REL, but may be incorrect for RELA if the value
// stored in the location (getUnsigned(Off, Size)) is not zero.
return getUnsigned(Off, Size) + Rel->Value;
In this patch, we
* refactor these visit* functions to include a new parameter `uint64_t A`.
Since these visit* functions are no longer used as visitors, rename them to resolve*.
+ REL: A is used as the addend. A is the value stored in the location where the
relocation applies: getUnsigned(Off, Size)
+ RELA: The addend encoded in RelocationRef is used, e.g. getELFAddend(R)
* and add another set of supports* functions to check if a given relocation type is handled.
DWARFObjInMemory uses them to fail early.
Reviewers: echristo, dblaikie
Reviewed By: echristo
Subscribers: mgorny, aprantl, aheejin, fedor.sergeev, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57939
llvm-svn: 356729
Diffstat (limited to 'llvm/lib/DebugInfo')
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 20 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp | 11 |
2 files changed, 19 insertions, 12 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index dc0539f4634..789874f5cbd 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -36,7 +36,7 @@ #include "llvm/Object/Decompressor.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" -#include "llvm/Object/RelocVisitor.h" +#include "llvm/Object/RelocationResolver.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Error.h" @@ -1500,6 +1500,9 @@ public: // Symbol to [address, section index] cache mapping. std::map<SymbolRef, SymInfo> AddrCache; + bool (*Supports)(uint64_t); + RelocationResolver Resolver; + std::tie(Supports, Resolver) = getRelocationResolver(Obj); for (const RelocationRef &Reloc : Section.relocations()) { // FIXME: it's not clear how to correctly handle scattered // relocations. @@ -1514,9 +1517,15 @@ public: continue; } - object::RelocVisitor V(Obj); - uint64_t Val = V.visit(Reloc.getType(), Reloc, SymInfoOrErr->Address); - if (V.error()) { + // Check if Resolver can handle this relocation type early so as not to + // handle invalid cases in DWARFDataExtractor. + // + // TODO Don't store Resolver in every RelocAddrEntry. + if (Supports && Supports(Reloc.getType())) { + Map->try_emplace(Reloc.getOffset(), + RelocAddrEntry{SymInfoOrErr->SectionIndex, Reloc, + Resolver, SymInfoOrErr->Address}); + } else { SmallString<32> Type; Reloc.getTypeName(Type); ErrorPolicy EP = HandleError( @@ -1524,10 +1533,7 @@ public: errorCodeToError(object_error::parse_failed))); if (EP == ErrorPolicy::Halt) return; - continue; } - RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val}; - Map->insert({Reloc.getOffset(), Rel}); } } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp index bd8c23765e4..6f2f992f53e 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp @@ -18,12 +18,13 @@ uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off, *SecNdx = object::SectionedAddress::UndefSection; if (!Section) return getUnsigned(Off, Size); - Optional<RelocAddrEntry> Rel = Obj->find(*Section, *Off); - if (!Rel) - return getUnsigned(Off, Size); + Optional<RelocAddrEntry> E = Obj->find(*Section, *Off); + uint64_t A = getUnsigned(Off, Size); + if (!E) + return A; if (SecNdx) - *SecNdx = Rel->SectionIndex; - return getUnsigned(Off, Size) + Rel->Value; + *SecNdx = E->SectionIndex; + return E->Resolver(E->Reloc, E->SymbolValue, A); } Optional<uint64_t> |

