diff options
author | Matt Beaumont-Gay <matthewbg@google.com> | 2012-12-14 17:55:15 +0000 |
---|---|---|
committer | Matt Beaumont-Gay <matthewbg@google.com> | 2012-12-14 17:55:15 +0000 |
commit | 6aed25d93d1cfcde5809a73ffa7dc1b0d6396f66 (patch) | |
tree | 57e2fdf1caf960d8d878e0289f32af6759832b49 /lib/DebugInfo | |
parent | 7139cfb19b1cc28dfd5e274c07ec68835bc6d6d6 (diff) | |
parent | 1ad9253c9d34ccbce3e7e4ea5d87c266cbf93410 (diff) |
Updating branches/google/stable to r169803
git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/google/stable@170212 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/DebugInfo')
-rw-r--r-- | lib/DebugInfo/DIContext.cpp | 12 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFContext.cpp | 88 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFContext.h | 34 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugAranges.cpp | 49 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugAranges.h | 8 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFFormValue.cpp | 35 |
6 files changed, 164 insertions, 62 deletions
diff --git a/lib/DebugInfo/DIContext.cpp b/lib/DebugInfo/DIContext.cpp index ead57f9715..49a44097d3 100644 --- a/lib/DebugInfo/DIContext.cpp +++ b/lib/DebugInfo/DIContext.cpp @@ -13,14 +13,6 @@ using namespace llvm; DIContext::~DIContext() {} -DIContext *DIContext::getDWARFContext(bool isLittleEndian, - StringRef infoSection, - StringRef abbrevSection, - StringRef aRangeSection, - StringRef lineSection, - StringRef stringSection, - StringRef rangeSection) { - return new DWARFContextInMemory(isLittleEndian, infoSection, abbrevSection, - aRangeSection, lineSection, stringSection, - rangeSection); +DIContext *DIContext::getDWARFContext(object::ObjectFile *Obj) { + return new DWARFContextInMemory(Obj); } diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp index afd614cc35..91ed2d22ab 100644 --- a/lib/DebugInfo/DWARFContext.cpp +++ b/lib/DebugInfo/DWARFContext.cpp @@ -35,7 +35,7 @@ void DWARFContext::dump(raw_ostream &OS) { set.dump(OS); uint8_t savedAddressByteSize = 0; - OS << "\n.debug_lines contents:\n"; + OS << "\n.debug_line contents:\n"; for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) { DWARFCompileUnit *cu = getCompileUnitAtIndex(i); savedAddressByteSize = cu->getAddressByteSize(); @@ -91,8 +91,10 @@ const DWARFDebugAranges *DWARFContext::getDebugAranges() { Aranges.reset(new DWARFDebugAranges()); Aranges->extract(arangesData); - if (Aranges->isEmpty()) // No aranges in file, generate them from the DIEs. - Aranges->generate(this); + // Generate aranges from DIEs: even if .debug_aranges section is present, + // it may describe only a small subset of compilation units, so we need to + // manually build aranges for the rest of them. + Aranges->generate(this); return Aranges.get(); } @@ -298,4 +300,84 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, return InliningInfo; } +DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : + IsLittleEndian(true /* FIXME */) { + error_code ec; + for (object::section_iterator i = Obj->begin_sections(), + e = Obj->end_sections(); + i != e; i.increment(ec)) { + StringRef name; + i->getName(name); + StringRef data; + i->getContents(data); + + if (name.startswith("__DWARF,")) + name = name.substr(8); // Skip "__DWARF," prefix. + name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes. + if (name == "debug_info") + InfoSection = data; + else if (name == "debug_abbrev") + AbbrevSection = data; + else if (name == "debug_line") + LineSection = data; + else if (name == "debug_aranges") + ARangeSection = data; + else if (name == "debug_str") + StringSection = data; + else if (name == "debug_ranges") + RangeSection = 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 (object::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); + + object::RelocVisitor V(Obj->getFileFormatName()); + // The section address is always 0 for debug sections. + object::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); + } + } + } +} + void DWARFContextInMemory::anchor() { } diff --git a/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h index d10e850870..24613594de 100644 --- a/lib/DebugInfo/DWARFContext.h +++ b/lib/DebugInfo/DWARFContext.h @@ -14,9 +14,9 @@ #include "DWARFDebugAranges.h" #include "DWARFDebugLine.h" #include "DWARFDebugRangeList.h" -#include "llvm/DebugInfo/DIContext.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DIContext.h" namespace llvm { @@ -25,8 +25,6 @@ namespace llvm { /// information parsing. The actual data is supplied through pure virtual /// methods that a concrete implementation provides. class DWARFContext : public DIContext { - bool IsLittleEndian; - SmallVector<DWARFCompileUnit, 1> CUs; OwningPtr<DWARFDebugAbbrev> Abbrev; OwningPtr<DWARFDebugAranges> Aranges; @@ -37,10 +35,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) {} + public: + DWARFContext() {} virtual void dump(raw_ostream &OS); + /// Get the number of compile units in this context. unsigned getNumCompileUnits() { if (CUs.empty()) @@ -69,8 +68,8 @@ public: virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()); - bool isLittleEndian() const { return IsLittleEndian; } - + virtual bool isLittleEndian() const = 0; + virtual const RelocAddrMap &relocMap() const = 0; virtual StringRef getInfoSection() = 0; virtual StringRef getAbbrevSection() = 0; virtual StringRef getARangeSection() = 0; @@ -95,6 +94,8 @@ private: /// pointers to it. class DWARFContextInMemory : public DWARFContext { virtual void anchor(); + bool IsLittleEndian; + RelocAddrMap RelocMap; StringRef InfoSection; StringRef AbbrevSection; StringRef ARangeSection; @@ -102,22 +103,9 @@ class DWARFContextInMemory : public DWARFContext { StringRef StringSection; StringRef RangeSection; public: - DWARFContextInMemory(bool isLittleEndian, - StringRef infoSection, - StringRef abbrevSection, - StringRef aRangeSection, - StringRef lineSection, - StringRef stringSection, - StringRef rangeSection) - : DWARFContext(isLittleEndian), - InfoSection(infoSection), - AbbrevSection(abbrevSection), - ARangeSection(aRangeSection), - LineSection(lineSection), - StringSection(stringSection), - RangeSection(rangeSection) - {} - + DWARFContextInMemory(object::ObjectFile *); + virtual bool isLittleEndian() const { return IsLittleEndian; } + virtual const RelocAddrMap &relocMap() const { return RelocMap; } virtual StringRef getInfoSection() { return InfoSection; } virtual StringRef getAbbrevSection() { return AbbrevSection; } virtual StringRef getARangeSection() { return ARangeSection; } diff --git a/lib/DebugInfo/DWARFDebugAranges.cpp b/lib/DebugInfo/DWARFDebugAranges.cpp index f9a34c908f..b077eb5e38 100644 --- a/lib/DebugInfo/DWARFDebugAranges.cpp +++ b/lib/DebugInfo/DWARFDebugAranges.cpp @@ -26,34 +26,40 @@ namespace { class CountArangeDescriptors { public: CountArangeDescriptors(uint32_t &count_ref) : Count(count_ref) {} - void operator()(const DWARFDebugArangeSet &set) { - Count += set.getNumDescriptors(); + void operator()(const DWARFDebugArangeSet &Set) { + Count += Set.getNumDescriptors(); } uint32_t &Count; }; class AddArangeDescriptors { public: - AddArangeDescriptors(DWARFDebugAranges::RangeColl &ranges) - : RangeCollection(ranges) {} - void operator()(const DWARFDebugArangeSet& set) { - const DWARFDebugArangeSet::Descriptor* arange_desc_ptr; - DWARFDebugAranges::Range range; - range.Offset = set.getCompileUnitDIEOffset(); - - for (uint32_t i=0; (arange_desc_ptr = set.getDescriptor(i)) != NULL; ++i){ - range.LoPC = arange_desc_ptr->Address; - range.Length = arange_desc_ptr->Length; + AddArangeDescriptors(DWARFDebugAranges::RangeColl &Ranges, + DWARFDebugAranges::ParsedCUOffsetColl &CUOffsets) + : RangeCollection(Ranges), + CUOffsetCollection(CUOffsets) {} + void operator()(const DWARFDebugArangeSet &Set) { + DWARFDebugAranges::Range Range; + Range.Offset = Set.getCompileUnitDIEOffset(); + CUOffsetCollection.insert(Range.Offset); + + for (uint32_t i = 0, n = Set.getNumDescriptors(); i < n; ++i) { + const DWARFDebugArangeSet::Descriptor *ArangeDescPtr = + Set.getDescriptor(i); + Range.LoPC = ArangeDescPtr->Address; + Range.Length = ArangeDescPtr->Length; // Insert each item in increasing address order so binary searching // can later be done! - DWARFDebugAranges::RangeColl::iterator insert_pos = + DWARFDebugAranges::RangeColl::iterator InsertPos = std::lower_bound(RangeCollection.begin(), RangeCollection.end(), - range, RangeLessThan); - RangeCollection.insert(insert_pos, range); + Range, RangeLessThan); + RangeCollection.insert(InsertPos, Range); } + } - DWARFDebugAranges::RangeColl& RangeCollection; + DWARFDebugAranges::RangeColl &RangeCollection; + DWARFDebugAranges::ParsedCUOffsetColl &CUOffsetCollection; }; } @@ -75,7 +81,7 @@ bool DWARFDebugAranges::extract(DataExtractor debug_aranges_data) { if (count > 0) { Aranges.reserve(count); - AddArangeDescriptors range_adder(Aranges); + AddArangeDescriptors range_adder(Aranges, ParsedCUOffsets); std::for_each(sets.begin(), sets.end(), range_adder); } } @@ -83,13 +89,14 @@ bool DWARFDebugAranges::extract(DataExtractor debug_aranges_data) { } bool DWARFDebugAranges::generate(DWARFContext *ctx) { - clear(); if (ctx) { const uint32_t num_compile_units = ctx->getNumCompileUnits(); for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) { - DWARFCompileUnit *cu = ctx->getCompileUnitAtIndex(cu_idx); - if (cu) - cu->buildAddressRangeTable(this, true); + if (DWARFCompileUnit *cu = ctx->getCompileUnitAtIndex(cu_idx)) { + uint32_t CUOffset = cu->getOffset(); + if (ParsedCUOffsets.insert(CUOffset).second) + cu->buildAddressRangeTable(this, true); + } } } sort(true, /* overlap size */ 0); diff --git a/lib/DebugInfo/DWARFDebugAranges.h b/lib/DebugInfo/DWARFDebugAranges.h index 12afb60beb..1509ffad41 100644 --- a/lib/DebugInfo/DWARFDebugAranges.h +++ b/lib/DebugInfo/DWARFDebugAranges.h @@ -11,6 +11,7 @@ #define LLVM_DEBUGINFO_DWARFDEBUGARANGES_H #include "DWARFDebugArangeSet.h" +#include "llvm/ADT/DenseSet.h" #include <list> namespace llvm { @@ -60,7 +61,10 @@ public: uint32_t Offset; // Offset of the compile unit or die }; - void clear() { Aranges.clear(); } + void clear() { + Aranges.clear(); + ParsedCUOffsets.clear(); + } bool allRangesAreContiguous(uint64_t& LoPC, uint64_t& HiPC) const; bool getMaxRange(uint64_t& LoPC, uint64_t& HiPC) const; bool extract(DataExtractor debug_aranges_data); @@ -88,9 +92,11 @@ public: typedef std::vector<Range> RangeColl; typedef RangeColl::const_iterator RangeCollIterator; + typedef DenseSet<uint32_t> ParsedCUOffsetColl; private: RangeColl Aranges; + ParsedCUOffsetColl ParsedCUOffsets; }; } diff --git a/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp index c9ecbbbbd4..1d8ea01110 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" @@ -45,6 +46,8 @@ static const uint8_t form_sizes_addr4[] = { 0, // 0x18 DW_FORM_exprloc 0, // 0x19 DW_FORM_flag_present 8, // 0x20 DW_FORM_ref_sig8 + 4, // 0x1f01 DW_FORM_GNU_addr_index + 4, // 0x1f02 DW_FORM_GNU_str_index }; static const uint8_t form_sizes_addr8[] = { @@ -75,6 +78,8 @@ static const uint8_t form_sizes_addr8[] = { 0, // 0x18 DW_FORM_exprloc 0, // 0x19 DW_FORM_flag_present 8, // 0x20 DW_FORM_ref_sig8 + 8, // 0x1f01 DW_FORM_GNU_addr_index + 8, // 0x1f01 DW_FORM_GNU_str_index }; const uint8_t * @@ -98,9 +103,17 @@ 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: Value.uval = data.getULEB128(offset_ptr); @@ -138,9 +151,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); @@ -168,6 +189,12 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, case DW_FORM_ref_sig8: Value.uval = data.getU64(offset_ptr); break; + case DW_FORM_GNU_addr_index: + Value.uval = data.getULEB128(offset_ptr); + break; + case DW_FORM_GNU_str_index: + Value.uval = data.getULEB128(offset_ptr); + break; default: return false; } |