forked from OSchip/llvm-project
[DWARF] - Take relocations in account when extracting ranges from .debug_ranges
I found this when investigated "Bug 32319 - .gdb_index is broken/incomplete" for LLD. When we have object file with .debug_ranges section it may be filled with zeroes. Relocations are exist in file to relocate this zeroes into real values later, but until that a pair of zeroes is treated as terminator. And DWARF parser thinks there is no ranges at all when I am trying to collect address ranges for building .gdb_index. Solution implemented in this patch is to take relocations in account when parsing ranges. Differential revision: https://reviews.llvm.org/D32228 llvm-svn: 301170
This commit is contained in:
parent
df0497c4aa
commit
ca53211beb
|
@ -18,9 +18,9 @@ namespace llvm {
|
|||
class DWARFCompileUnit : public DWARFUnit {
|
||||
public:
|
||||
DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section,
|
||||
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
|
||||
StringRef SOS, StringRef AOS, StringRef LS, bool LE,
|
||||
bool IsDWO, const DWARFUnitSectionBase &UnitSection,
|
||||
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
|
||||
StringRef SS, StringRef SOS, StringRef AOS, StringRef LS,
|
||||
bool LE, bool IsDWO, const DWARFUnitSectionBase &UnitSection,
|
||||
const DWARFUnitIndex::Entry *Entry)
|
||||
: DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
|
||||
UnitSection, Entry) {}
|
||||
|
|
|
@ -221,7 +221,7 @@ public:
|
|||
virtual StringRef getEHFrameSection() = 0;
|
||||
virtual const DWARFSection &getLineSection() = 0;
|
||||
virtual StringRef getStringSection() = 0;
|
||||
virtual StringRef getRangeSection() = 0;
|
||||
virtual const DWARFSection& getRangeSection() = 0;
|
||||
virtual StringRef getMacinfoSection() = 0;
|
||||
virtual StringRef getPubNamesSection() = 0;
|
||||
virtual StringRef getPubTypesSection() = 0;
|
||||
|
@ -236,7 +236,7 @@ public:
|
|||
virtual const DWARFSection &getLocDWOSection() = 0;
|
||||
virtual StringRef getStringDWOSection() = 0;
|
||||
virtual StringRef getStringOffsetDWOSection() = 0;
|
||||
virtual StringRef getRangeDWOSection() = 0;
|
||||
virtual const DWARFSection &getRangeDWOSection() = 0;
|
||||
virtual StringRef getAddrSection() = 0;
|
||||
virtual const DWARFSection& getAppleNamesSection() = 0;
|
||||
virtual const DWARFSection& getAppleTypesSection() = 0;
|
||||
|
@ -276,7 +276,7 @@ class DWARFContextInMemory : public DWARFContext {
|
|||
StringRef EHFrameSection;
|
||||
DWARFSection LineSection;
|
||||
StringRef StringSection;
|
||||
StringRef RangeSection;
|
||||
DWARFSection RangeSection;
|
||||
StringRef MacinfoSection;
|
||||
StringRef PubNamesSection;
|
||||
StringRef PubTypesSection;
|
||||
|
@ -291,7 +291,7 @@ class DWARFContextInMemory : public DWARFContext {
|
|||
DWARFSection LocDWOSection;
|
||||
StringRef StringDWOSection;
|
||||
StringRef StringOffsetDWOSection;
|
||||
StringRef RangeDWOSection;
|
||||
DWARFSection RangeDWOSection;
|
||||
StringRef AddrSection;
|
||||
DWARFSection AppleNamesSection;
|
||||
DWARFSection AppleTypesSection;
|
||||
|
@ -324,7 +324,7 @@ public:
|
|||
StringRef getEHFrameSection() override { return EHFrameSection; }
|
||||
const DWARFSection &getLineSection() override { return LineSection; }
|
||||
StringRef getStringSection() override { return StringSection; }
|
||||
StringRef getRangeSection() override { return RangeSection; }
|
||||
const DWARFSection &getRangeSection() override { return RangeSection; }
|
||||
StringRef getMacinfoSection() override { return MacinfoSection; }
|
||||
StringRef getPubNamesSection() override { return PubNamesSection; }
|
||||
StringRef getPubTypesSection() override { return PubTypesSection; }
|
||||
|
@ -351,7 +351,7 @@ public:
|
|||
return StringOffsetDWOSection;
|
||||
}
|
||||
|
||||
StringRef getRangeDWOSection() override { return RangeDWOSection; }
|
||||
const DWARFSection &getRangeDWOSection() override { return RangeDWOSection; }
|
||||
|
||||
StringRef getAddrSection() override {
|
||||
return AddrSection;
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H
|
||||
|
||||
#include "llvm/Support/DataExtractor.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
@ -71,7 +73,7 @@ public:
|
|||
|
||||
void clear();
|
||||
void dump(raw_ostream &OS) const;
|
||||
bool extract(DataExtractor data, uint32_t *offset_ptr);
|
||||
bool extract(DataExtractor data, uint32_t *offset_ptr, const RelocAddrMap& Relocs);
|
||||
const std::vector<RangeListEntry> &getEntries() { return Entries; }
|
||||
|
||||
/// getAbsoluteRanges - Returns absolute address ranges defined by this range
|
||||
|
|
|
@ -30,9 +30,9 @@ private:
|
|||
|
||||
public:
|
||||
DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section,
|
||||
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
|
||||
StringRef SOS, StringRef AOS, StringRef LS, bool LE, bool IsDWO,
|
||||
const DWARFUnitSectionBase &UnitSection,
|
||||
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
|
||||
StringRef SS, StringRef SOS, StringRef AOS, StringRef LS,
|
||||
bool LE, bool IsDWO, const DWARFUnitSectionBase &UnitSection,
|
||||
const DWARFUnitIndex::Entry *Entry)
|
||||
: DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
|
||||
UnitSection, Entry) {}
|
||||
|
|
|
@ -56,9 +56,9 @@ protected:
|
|||
~DWARFUnitSectionBase() = default;
|
||||
|
||||
virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section,
|
||||
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
|
||||
StringRef SOS, StringRef AOS, StringRef LS,
|
||||
bool isLittleEndian, bool isDWO) = 0;
|
||||
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
|
||||
StringRef SS, StringRef SOS, StringRef AOS,
|
||||
StringRef LS, bool isLittleEndian, bool isDWO) = 0;
|
||||
};
|
||||
|
||||
const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
|
||||
|
@ -88,9 +88,9 @@ public:
|
|||
|
||||
private:
|
||||
void parseImpl(DWARFContext &Context, const DWARFSection &Section,
|
||||
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
|
||||
StringRef SOS, StringRef AOS, StringRef LS, bool LE,
|
||||
bool IsDWO) override {
|
||||
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
|
||||
StringRef SS, StringRef SOS, StringRef AOS, StringRef LS,
|
||||
bool LE, bool IsDWO) override {
|
||||
if (Parsed)
|
||||
return;
|
||||
const auto &Index = getDWARFUnitIndex(Context, UnitType::Section);
|
||||
|
@ -115,7 +115,7 @@ class DWARFUnit {
|
|||
const DWARFSection &InfoSection;
|
||||
|
||||
const DWARFDebugAbbrev *Abbrev;
|
||||
StringRef RangeSection;
|
||||
const DWARFSection *RangeSection;
|
||||
uint32_t RangeSectionBase;
|
||||
StringRef LineSection;
|
||||
StringRef StringSection;
|
||||
|
@ -171,7 +171,7 @@ protected:
|
|||
|
||||
public:
|
||||
DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
|
||||
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
|
||||
const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS,
|
||||
StringRef SOS, StringRef AOS, StringRef LS, bool LE, bool IsDWO,
|
||||
const DWARFUnitSectionBase &UnitSection,
|
||||
const DWARFUnitIndex::Entry *IndexEntry = nullptr);
|
||||
|
@ -192,7 +192,7 @@ public:
|
|||
// Recursively update address to Die map.
|
||||
void updateAddressDieMap(DWARFDie Die);
|
||||
|
||||
void setRangesSection(StringRef RS, uint32_t Base) {
|
||||
void setRangesSection(const DWARFSection *RS, uint32_t Base) {
|
||||
RangeSection = RS;
|
||||
RangeSectionBase = Base;
|
||||
}
|
||||
|
|
|
@ -222,11 +222,11 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH,
|
|||
// sizes, but for simplicity we just use the address byte size of the last
|
||||
// compile unit (there is no easy and fast way to associate address range
|
||||
// list and the compile unit it describes).
|
||||
DataExtractor rangesData(getRangeSection(), isLittleEndian(),
|
||||
DataExtractor rangesData(getRangeSection().Data, isLittleEndian(),
|
||||
savedAddressByteSize);
|
||||
offset = 0;
|
||||
DWARFDebugRangeList rangeList;
|
||||
while (rangeList.extract(rangesData, &offset))
|
||||
while (rangeList.extract(rangesData, &offset, getRangeSection().Relocs))
|
||||
rangeList.dump(OS);
|
||||
}
|
||||
|
||||
|
@ -732,7 +732,7 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
|
|||
*SectionData = data;
|
||||
if (name == "debug_ranges") {
|
||||
// FIXME: Use the other dwo range section when we emit it.
|
||||
RangeDWOSection = data;
|
||||
RangeDWOSection.Data = data;
|
||||
}
|
||||
} else if (name == "debug_types") {
|
||||
// Find debug_types data by section rather than name as there are
|
||||
|
@ -773,6 +773,7 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
|
|||
.Case("debug_loc", &LocSection.Relocs)
|
||||
.Case("debug_info.dwo", &InfoDWOSection.Relocs)
|
||||
.Case("debug_line", &LineSection.Relocs)
|
||||
.Case("debug_ranges", &RangeSection.Relocs)
|
||||
.Case("apple_names", &AppleNamesSection.Relocs)
|
||||
.Case("apple_types", &AppleTypesSection.Relocs)
|
||||
.Case("apple_namespaces", &AppleNamespacesSection.Relocs)
|
||||
|
@ -855,7 +856,7 @@ StringRef *DWARFContextInMemory::MapSectionToMember(StringRef Name) {
|
|||
.Case("debug_frame", &DebugFrameSection)
|
||||
.Case("eh_frame", &EHFrameSection)
|
||||
.Case("debug_str", &StringSection)
|
||||
.Case("debug_ranges", &RangeSection)
|
||||
.Case("debug_ranges", &RangeSection.Data)
|
||||
.Case("debug_macinfo", &MacinfoSection)
|
||||
.Case("debug_pubnames", &PubNamesSection)
|
||||
.Case("debug_pubtypes", &PubTypesSection)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
@ -22,7 +23,8 @@ void DWARFDebugRangeList::clear() {
|
|||
Entries.clear();
|
||||
}
|
||||
|
||||
bool DWARFDebugRangeList::extract(DataExtractor data, uint32_t *offset_ptr) {
|
||||
bool DWARFDebugRangeList::extract(DataExtractor data, uint32_t *offset_ptr,
|
||||
const RelocAddrMap &Relocs) {
|
||||
clear();
|
||||
if (!data.isValidOffset(*offset_ptr))
|
||||
return false;
|
||||
|
@ -33,8 +35,11 @@ bool DWARFDebugRangeList::extract(DataExtractor data, uint32_t *offset_ptr) {
|
|||
while (true) {
|
||||
RangeListEntry entry;
|
||||
uint32_t prev_offset = *offset_ptr;
|
||||
entry.StartAddress = data.getAddress(offset_ptr);
|
||||
entry.EndAddress = data.getAddress(offset_ptr);
|
||||
entry.StartAddress =
|
||||
getRelocatedValue(data, AddressSize, offset_ptr, &Relocs);
|
||||
entry.EndAddress =
|
||||
getRelocatedValue(data, AddressSize, offset_ptr, &Relocs);
|
||||
|
||||
// Check that both values were extracted correctly.
|
||||
if (*offset_ptr != prev_offset + 2 * AddressSize) {
|
||||
clear();
|
||||
|
|
|
@ -32,7 +32,7 @@ using namespace llvm;
|
|||
using namespace dwarf;
|
||||
|
||||
void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) {
|
||||
parseImpl(C, Section, C.getDebugAbbrev(), C.getRangeSection(),
|
||||
parseImpl(C, Section, C.getDebugAbbrev(), &C.getRangeSection(),
|
||||
C.getStringSection(), StringRef(), C.getAddrSection(),
|
||||
C.getLineSection().Data, C.isLittleEndian(), false);
|
||||
}
|
||||
|
@ -40,16 +40,17 @@ void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) {
|
|||
void DWARFUnitSectionBase::parseDWO(DWARFContext &C,
|
||||
const DWARFSection &DWOSection,
|
||||
DWARFUnitIndex *Index) {
|
||||
parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), C.getRangeDWOSection(),
|
||||
parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), &C.getRangeDWOSection(),
|
||||
C.getStringDWOSection(), C.getStringOffsetDWOSection(),
|
||||
C.getAddrSection(), C.getLineDWOSection().Data, C.isLittleEndian(),
|
||||
true);
|
||||
}
|
||||
|
||||
DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
|
||||
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
|
||||
StringRef SOS, StringRef AOS, StringRef LS, bool LE,
|
||||
bool IsDWO, const DWARFUnitSectionBase &UnitSection,
|
||||
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
|
||||
StringRef SS, StringRef SOS, StringRef AOS, StringRef LS,
|
||||
bool LE, bool IsDWO,
|
||||
const DWARFUnitSectionBase &UnitSection,
|
||||
const DWARFUnitIndex::Entry *IndexEntry)
|
||||
: Context(DC), InfoSection(Section), Abbrev(DA), RangeSection(RS),
|
||||
LineSection(LS), StringSection(SS), StringOffsetSection([&]() {
|
||||
|
@ -142,9 +143,10 @@ bool DWARFUnit::extractRangeList(uint32_t RangeListOffset,
|
|||
DWARFDebugRangeList &RangeList) const {
|
||||
// Require that compile unit is extracted.
|
||||
assert(!DieArray.empty());
|
||||
DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize);
|
||||
DataExtractor RangesData(RangeSection->Data, isLittleEndian, AddrSize);
|
||||
uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
|
||||
return RangeList.extract(RangesData, &ActualRangeListOffset);
|
||||
return RangeList.extract(RangesData, &ActualRangeListOffset,
|
||||
RangeSection->Relocs);
|
||||
}
|
||||
|
||||
void DWARFUnit::clear() {
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
# RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %s -o %t
|
||||
# RUN: llvm-dwarfdump %t | FileCheck %s
|
||||
|
||||
# CHECK: .debug_ranges contents:
|
||||
# CHECK: 00000000 0000000000000000 0000000000000001
|
||||
# CHECK: 00000000 0000000000000000 0000000000000002
|
||||
# CHECK: 00000000 <End of list>
|
||||
|
||||
## Asm code for testcase is a reduced output from next invocation and source:
|
||||
# clang test.cpp -S -o test.s -gmlt -ffunction-sections
|
||||
# test.cpp:
|
||||
# void foo1() { }
|
||||
# void foo2() { }
|
||||
|
||||
.section .text.foo1,"ax",@progbits
|
||||
.Lfunc_begin0:
|
||||
nop
|
||||
.Lfunc_end0:
|
||||
|
||||
.section .text.foo2,"ax",@progbits
|
||||
.Lfunc_begin1:
|
||||
nop
|
||||
nop
|
||||
.Lfunc_end1:
|
||||
|
||||
.section .debug_abbrev,"",@progbits
|
||||
.byte 1 # Abbreviation Code
|
||||
.byte 17 # DW_TAG_compile_unit
|
||||
.byte 0 # DW_CHILDREN_no
|
||||
.byte 37 # DW_AT_producer
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 19 # DW_AT_language
|
||||
.byte 5 # DW_FORM_data2
|
||||
.byte 3 # DW_AT_name
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 16 # DW_AT_stmt_list
|
||||
.byte 23 # DW_FORM_sec_offset
|
||||
.byte 27 # DW_AT_comp_dir
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 17 # DW_AT_low_pc
|
||||
.byte 1 # DW_FORM_addr
|
||||
.byte 85 # DW_AT_ranges
|
||||
.byte 23 # DW_FORM_sec_offset
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 0 # EOM(3)
|
||||
|
||||
.section .debug_info,"",@progbits
|
||||
.Lcu_begin0:
|
||||
.long 38 # Length of Unit
|
||||
.short 4 # DWARF version number
|
||||
.long .debug_abbrev # Offset Into Abbrev. Section
|
||||
.byte 8 # Address Size (in bytes)
|
||||
.byte 1 # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
|
||||
.long 0 # DW_AT_producer
|
||||
.short 4 # DW_AT_language
|
||||
.long 0 # DW_AT_name
|
||||
.long 0 # DW_AT_stmt_list
|
||||
.long 0 # DW_AT_comp_dir
|
||||
.quad 0 # DW_AT_low_pc
|
||||
.long .Ldebug_ranges0 # DW_AT_ranges
|
||||
|
||||
.section .debug_ranges,"",@progbits
|
||||
.Ldebug_ranges0:
|
||||
.quad .Lfunc_begin0
|
||||
.quad .Lfunc_end0
|
||||
.quad .Lfunc_begin1
|
||||
.quad .Lfunc_end1
|
||||
.quad 0
|
||||
.quad 0
|
|
@ -2869,7 +2869,7 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit,
|
|||
DWARFDebugRangeList RangeList;
|
||||
const auto &FunctionRanges = Unit.getFunctionRanges();
|
||||
unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
|
||||
DataExtractor RangeExtractor(OrigDwarf.getRangeSection(),
|
||||
DataExtractor RangeExtractor(OrigDwarf.getRangeSection().Data,
|
||||
OrigDwarf.isLittleEndian(), AddressSize);
|
||||
auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange;
|
||||
DWARFUnit &OrigUnit = Unit.getOrigUnit();
|
||||
|
@ -2884,7 +2884,7 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit,
|
|||
for (const auto &RangeAttribute : Unit.getRangesAttributes()) {
|
||||
uint32_t Offset = RangeAttribute.get();
|
||||
RangeAttribute.set(Streamer->getRangesSectionSize());
|
||||
RangeList.extract(RangeExtractor, &Offset);
|
||||
RangeList.extract(RangeExtractor, &Offset, OrigDwarf.getRangeSection().Relocs);
|
||||
const auto &Entries = RangeList.getEntries();
|
||||
if (!Entries.empty()) {
|
||||
const DWARFDebugRangeList::RangeListEntry &First = Entries.front();
|
||||
|
|
Loading…
Reference in New Issue