llvm-dwarfdump: Add support for dumping the .debug_loc section

This is a basic implementation - we still don't have any support (that I
know of) for dumping DWARF expressions in a meaningful way, so the
location information itself is just printed as a sequence of bytes as we
do elsewhere.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184361 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Blaikie 2013-06-19 21:37:13 +00:00
parent ba54bca472
commit 3df7d2f70b
11 changed files with 211 additions and 1 deletions

View File

@ -105,6 +105,7 @@ enum DIDumpType {
DIDT_Info,
DIDT_InfoDwo,
DIDT_Line,
DIDT_Loc,
DIDT_Ranges,
DIDT_Pubnames,
DIDT_Str,

View File

@ -9,6 +9,7 @@ add_llvm_library(LLVMDebugInfo
DWARFDebugFrame.cpp
DWARFDebugInfoEntry.cpp
DWARFDebugLine.cpp
DWARFDebugLoc.cpp
DWARFDebugRangeList.cpp
DWARFFormValue.cpp
)

View File

@ -35,6 +35,11 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
getCompileUnitAtIndex(i)->dump(OS);
}
if (DumpType == DIDT_All || DumpType == DIDT_Loc) {
OS << ".debug_loc contents:\n";
getDebugLoc()->dump(OS);
}
if (DumpType == DIDT_All || DumpType == DIDT_Frames) {
OS << "\n.debug_frame contents:\n";
getDebugFrame()->dump(OS);
@ -171,6 +176,18 @@ const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() {
return AbbrevDWO.get();
}
const DWARFDebugLoc *DWARFContext::getDebugLoc() {
if (Loc)
return Loc.get();
DataExtractor LocData(getLocSection(), isLittleEndian(), 0);
Loc.reset(new DWARFDebugLoc(locRelocMap()));
// assume all compile units have the same address byte size
if (getNumCompileUnits())
Loc->parse(LocData, getCompileUnitAtIndex(0)->getAddressByteSize());
return Loc.get();
}
const DWARFDebugAranges *DWARFContext::getDebugAranges() {
if (Aranges)
return Aranges.get();
@ -542,6 +559,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
StringRef *Section = StringSwitch<StringRef*>(name)
.Case("debug_info", &InfoSection)
.Case("debug_abbrev", &AbbrevSection)
.Case("debug_loc", &LocSection)
.Case("debug_line", &LineSection)
.Case("debug_aranges", &ARangeSection)
.Case("debug_frame", &DebugFrameSection)
@ -576,6 +594,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
// Record relocations for the debug_info and debug_line sections.
RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(RelSecName)
.Case("debug_info", &InfoRelocMap)
.Case("debug_loc", &LocRelocMap)
.Case("debug_info.dwo", &InfoDWORelocMap)
.Case("debug_line", &LineRelocMap)
.Default(0);

View File

@ -14,6 +14,7 @@
#include "DWARFDebugAranges.h"
#include "DWARFDebugFrame.h"
#include "DWARFDebugLine.h"
#include "DWARFDebugLoc.h"
#include "DWARFDebugRangeList.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
@ -28,6 +29,7 @@ namespace llvm {
class DWARFContext : public DIContext {
SmallVector<DWARFCompileUnit, 1> CUs;
OwningPtr<DWARFDebugAbbrev> Abbrev;
OwningPtr<DWARFDebugLoc> Loc;
OwningPtr<DWARFDebugAranges> Aranges;
OwningPtr<DWARFDebugLine> Line;
OwningPtr<DWARFDebugFrame> DebugFrame;
@ -80,6 +82,9 @@ public:
/// Get a pointer to the parsed DebugAbbrev object.
const DWARFDebugAbbrev *getDebugAbbrev();
/// Get a pointer to the parsed DebugLoc object.
const DWARFDebugLoc *getDebugLoc();
/// Get a pointer to the parsed dwo abbreviations object.
const DWARFDebugAbbrev *getDebugAbbrevDWO();
@ -104,8 +109,10 @@ public:
virtual uint8_t getAddressSize() const = 0;
virtual const RelocAddrMap &infoRelocMap() const = 0;
virtual const RelocAddrMap &lineRelocMap() const = 0;
virtual const RelocAddrMap &locRelocMap() const = 0;
virtual StringRef getInfoSection() = 0;
virtual StringRef getAbbrevSection() = 0;
virtual StringRef getLocSection() = 0;
virtual StringRef getARangeSection() = 0;
virtual StringRef getDebugFrameSection() = 0;
virtual StringRef getLineSection() = 0;
@ -142,9 +149,11 @@ class DWARFContextInMemory : public DWARFContext {
bool IsLittleEndian;
uint8_t AddressSize;
RelocAddrMap InfoRelocMap;
RelocAddrMap LocRelocMap;
RelocAddrMap LineRelocMap;
StringRef InfoSection;
StringRef AbbrevSection;
StringRef LocSection;
StringRef ARangeSection;
StringRef DebugFrameSection;
StringRef LineSection;
@ -169,9 +178,11 @@ public:
virtual bool isLittleEndian() const { return IsLittleEndian; }
virtual uint8_t getAddressSize() const { return AddressSize; }
virtual const RelocAddrMap &infoRelocMap() const { return InfoRelocMap; }
virtual const RelocAddrMap &locRelocMap() const { return LocRelocMap; }
virtual const RelocAddrMap &lineRelocMap() const { return LineRelocMap; }
virtual StringRef getInfoSection() { return InfoSection; }
virtual StringRef getAbbrevSection() { return AbbrevSection; }
virtual StringRef getLocSection() { return LocSection; }
virtual StringRef getARangeSection() { return ARangeSection; }
virtual StringRef getDebugFrameSection() { return DebugFrameSection; }
virtual StringRef getLineSection() { return LineSection; }

View File

@ -0,0 +1,74 @@
//===-- DWARFDebugLoc.cpp -------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "DWARFDebugLoc.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
void DWARFDebugLoc::dump(raw_ostream &OS) const {
for (LocationLists::const_iterator I = Locations.begin(), E = Locations.end(); I != E; ++I) {
OS << format("0x%8.8x: ", I->Offset);
const unsigned Indent = 12;
for (SmallVectorImpl<Entry>::const_iterator I2 = I->Entries.begin(), E2 = I->Entries.end(); I2 != E2; ++I2) {
if (I2 != I->Entries.begin())
OS.indent(Indent);
OS << "Begining address offset: " << format("0x%016" PRIx64, I2->Begin)
<< '\n';
OS.indent(Indent) << " Ending address offset: "
<< format("0x%016" PRIx64, I2->End) << '\n';
OS.indent(Indent) << " Location description: ";
for (SmallVectorImpl<unsigned char>::const_iterator I3 = I2->Loc.begin(), E3 = I2->Loc.end(); I3 != E3; ++I3) {
OS << format("%2.2x ", *I3);
}
OS << "\n\n";
}
}
}
void DWARFDebugLoc::parse(DataExtractor data, unsigned AddressSize) {
uint32_t Offset = 0;
while (data.isValidOffset(Offset)) {
Locations.resize(Locations.size() + 1);
LocationList &Loc = Locations.back();
Loc.Offset = Offset;
// 2.6.2 Location Lists
// A location list entry consists of:
while (true) {
Entry E;
RelocAddrMap::const_iterator AI = RelocMap.find(Offset);
// 1. A beginning address offset. ...
E.Begin = data.getUnsigned(&Offset, AddressSize);
if (AI != RelocMap.end())
E.Begin += AI->second.second;
AI = RelocMap.find(Offset);
// 2. An ending address offset. ...
E.End = data.getUnsigned(&Offset, AddressSize);
if (AI != RelocMap.end())
E.End += AI->second.second;
// The end of any given location list is marked by an end of list entry,
// which consists of a 0 for the beginning address offset and a 0 for the
// ending address offset.
if (E.Begin == 0 && E.End == 0)
break;
unsigned Bytes = data.getU16(&Offset);
// A single location description describing the location of the object...
StringRef str = data.getData().substr(Offset, Bytes);
Offset += Bytes;
E.Loc.reserve(str.size());
std::copy(str.begin(), str.end(), std::back_inserter(E.Loc));
Loc.Entries.push_back(llvm_move(E));
}
}
}

View File

@ -0,0 +1,60 @@
//===-- DWARFDebugLoc.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_DWARFDEBUGLOC_H
#define LLVM_DEBUGINFO_DWARFDEBUGLOC_H
#include "DWARFRelocMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DataExtractor.h"
namespace llvm {
class raw_ostream;
class DWARFDebugLoc {
/// A single location within a location list.
struct Entry {
/// The beginning address of the instruction range.
uint64_t Begin;
/// The ending address of the instruction range.
uint64_t End;
/// The location of the variable within the specified range.
SmallVector<unsigned char, 4> Loc;
};
/// A list of locations that contain one variable.
struct LocationList {
/// The beginning offset where this location list is stored in the debug_loc
/// section.
unsigned Offset;
/// All the locations in which the variable is stored.
SmallVector<Entry, 2> Entries;
};
typedef SmallVector<LocationList, 4> LocationLists;
/// A list of all the variables in the debug_loc section, each one describing
/// the locations in which the variable is stored.
LocationLists Locations;
/// A map used to resolve binary relocations.
const RelocAddrMap &RelocMap;
public:
DWARFDebugLoc(const RelocAddrMap &LocRelocMap) : RelocMap(LocRelocMap) {}
/// Print the location lists found within the debug_loc section.
void dump(raw_ostream &OS) const;
/// Parse the debug_loc section accessible via the 'data' parameter using the
/// specified address size to interpret the address ranges.
void parse(DataExtractor data, unsigned AddressSize);
};
}
#endif

View File

@ -126,9 +126,13 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
Value.uval = data.getU16(offset_ptr);
break;
case DW_FORM_data4:
case DW_FORM_ref4:
case DW_FORM_ref4: {
RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
Value.uval = data.getU32(offset_ptr);
if (AI != cu->getRelocMap()->end())
Value.uval += AI->second.second;
break;
}
case DW_FORM_data8:
case DW_FORM_ref8:
Value.uval = data.getU64(offset_ptr);

View File

@ -0,0 +1,13 @@
// clang -c -g -o dwarfdump-test-loc-list-32bit.elf.o -m32 dwarfdump-test-loc-list-32bit.elf.cpp
namespace pr14763 {
struct foo {
foo(const foo&);
};
foo func(bool b, foo f, foo g) {
if (b)
return f;
return g;
}
}

View File

@ -0,0 +1,26 @@
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test-loc-list-32bit.elf.o | FileCheck %s
Note: the input file was generated from Inputs/dwarfdump-test-loc-list-32bit.elf.cpp
CHECK: .debug_info
CHECK: DW_AT_name{{.*}}"f"
CHECK: DW_AT_location{{.*}}([[F_LOC:0x[0-9a-f]*]])
CHECK: DW_AT_name{{.*}}"g"
CHECK: DW_AT_location{{.*}}([[G_LOC:0x[0-9a-f]*]])
CHECK: .debug_loc contents:
CHECK-NEXT: [[F_LOC]]: Begining address offset: 0x0000000000000000
CHECK-NEXT: Ending address offset: 0x0000000000000023
this is actually the wrong location due to PR14763, but that doesn't matter for
the purposes of testing dwarfdump
CHECK-NEXT: Location description: 51
CHECK-NEXT: {{^$}}
CHECK-NEXT: Begining address offset: 0x0000000000000023
CHECK-NEXT: Ending address offset: 0x000000000000005d
CHECK-NEXT: Location description: 75 70
CHECK-NEXT: {{^$}}
CHECK-NEXT: [[G_LOC]]: Begining address offset: 0x0000000000000000
CHECK-NEXT: Ending address offset: 0x0000000000000020
CHECK-NEXT: Location description: 50
CHECK-NEXT: {{^$}}
CHECK-NEXT: Begining address offset: 0x0000000000000020
CHECK-NEXT: Ending address offset: 0x000000000000005d
CHECK-NEXT: Location description: 75 74

View File

@ -63,6 +63,7 @@ DumpType("debug-dump", cl::init(DIDT_All),
clEnumValN(DIDT_Info, "info", ".debug_info"),
clEnumValN(DIDT_InfoDwo, "info.dwo", ".debug_info.dwo"),
clEnumValN(DIDT_Line, "line", ".debug_line"),
clEnumValN(DIDT_Loc, "loc", ".debug_loc"),
clEnumValN(DIDT_Frames, "frames", ".debug_frame"),
clEnumValN(DIDT_Ranges, "ranges", ".debug_ranges"),
clEnumValN(DIDT_Pubnames, "pubnames", ".debug_pubnames"),