aboutsummaryrefslogtreecommitdiff
path: root/lib/DebugInfo
diff options
context:
space:
mode:
authorMatt Beaumont-Gay <matthewbg@google.com>2012-12-14 17:55:15 +0000
committerMatt Beaumont-Gay <matthewbg@google.com>2012-12-14 17:55:15 +0000
commit6aed25d93d1cfcde5809a73ffa7dc1b0d6396f66 (patch)
tree57e2fdf1caf960d8d878e0289f32af6759832b49 /lib/DebugInfo
parent7139cfb19b1cc28dfd5e274c07ec68835bc6d6d6 (diff)
parent1ad9253c9d34ccbce3e7e4ea5d87c266cbf93410 (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.cpp12
-rw-r--r--lib/DebugInfo/DWARFContext.cpp88
-rw-r--r--lib/DebugInfo/DWARFContext.h34
-rw-r--r--lib/DebugInfo/DWARFDebugAranges.cpp49
-rw-r--r--lib/DebugInfo/DWARFDebugAranges.h8
-rw-r--r--lib/DebugInfo/DWARFFormValue.cpp35
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;
}