mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-16 14:31:59 +00:00
Add support for DebugFission to DWARF parser
Summary: 1) Make llvm-symbolizer properly symbolize files with split debug info (by using stanalone .dwo files). 2) Make DWARFCompileUnit parse and store corresponding .dwo file, if necessary. 3) Make bits of DWARF parsing more CompileUnit-oriented. Reviewers: echristo Reviewed By: echristo CC: bkramer, llvm-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1164 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189329 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1567abe74f
commit
63fd2af389
@ -20,7 +20,7 @@ class raw_ostream;
|
|||||||
class DWARFFormValue {
|
class DWARFFormValue {
|
||||||
public:
|
public:
|
||||||
struct ValueType {
|
struct ValueType {
|
||||||
ValueType() : data(NULL) {
|
ValueType() : data(NULL), IsDWOIndex(false) {
|
||||||
uval = 0;
|
uval = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,6 +30,7 @@ public:
|
|||||||
const char* cstr;
|
const char* cstr;
|
||||||
};
|
};
|
||||||
const uint8_t* data;
|
const uint8_t* data;
|
||||||
|
bool IsDWOIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -63,11 +64,8 @@ public:
|
|||||||
bool resolveCompileUnitReferences(const DWARFCompileUnit* cu);
|
bool resolveCompileUnitReferences(const DWARFCompileUnit* cu);
|
||||||
uint64_t getUnsigned() const { return Value.uval; }
|
uint64_t getUnsigned() const { return Value.uval; }
|
||||||
int64_t getSigned() const { return Value.sval; }
|
int64_t getSigned() const { return Value.sval; }
|
||||||
const char *getAsCString(const DataExtractor *debug_str_data_ptr) const;
|
const char *getAsCString(const DWARFCompileUnit *CU) const;
|
||||||
const char *getIndirectCString(const DataExtractor *,
|
uint64_t getAsAddress(const DWARFCompileUnit *CU) const;
|
||||||
const DataExtractor *) const;
|
|
||||||
uint64_t getIndirectAddress(const DataExtractor *,
|
|
||||||
const DWARFCompileUnit *) const;
|
|
||||||
bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr,
|
bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr,
|
||||||
const DWARFCompileUnit *cu) const;
|
const DWARFCompileUnit *cu) const;
|
||||||
static bool skipValue(uint16_t form, DataExtractor debug_info_data,
|
static bool skipValue(uint16_t form, DataExtractor debug_info_data,
|
||||||
|
@ -12,12 +12,31 @@
|
|||||||
#include "llvm/DebugInfo/DWARFFormValue.h"
|
#include "llvm/DebugInfo/DWARFFormValue.h"
|
||||||
#include "llvm/Support/Dwarf.h"
|
#include "llvm/Support/Dwarf.h"
|
||||||
#include "llvm/Support/Format.h"
|
#include "llvm/Support/Format.h"
|
||||||
|
#include "llvm/Support/Path.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace dwarf;
|
using namespace dwarf;
|
||||||
|
|
||||||
DataExtractor DWARFCompileUnit::getDebugInfoExtractor() const {
|
bool DWARFCompileUnit::getAddrOffsetSectionItem(uint32_t Index,
|
||||||
return DataExtractor(InfoSection, isLittleEndian, AddrSize);
|
uint64_t &Result) const {
|
||||||
|
uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize;
|
||||||
|
if (AddrOffsetSection.size() < Offset + AddrSize)
|
||||||
|
return false;
|
||||||
|
DataExtractor DA(AddrOffsetSection, isLittleEndian, AddrSize);
|
||||||
|
Result = DA.getAddress(&Offset);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DWARFCompileUnit::getStringOffsetSectionItem(uint32_t Index,
|
||||||
|
uint32_t &Result) const {
|
||||||
|
// FIXME: string offset section entries are 8-byte for DWARF64.
|
||||||
|
const uint32_t ItemSize = 4;
|
||||||
|
uint32_t Offset = Index * ItemSize;
|
||||||
|
if (StringOffsetSection.size() < Offset + ItemSize)
|
||||||
|
return false;
|
||||||
|
DataExtractor DA(StringOffsetSection, isLittleEndian, 0);
|
||||||
|
Result = DA.getU32(&Offset);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
|
bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
|
||||||
@ -78,7 +97,8 @@ bool DWARFCompileUnit::extractRangeList(uint32_t RangeListOffset,
|
|||||||
// Require that compile unit is extracted.
|
// Require that compile unit is extracted.
|
||||||
assert(DieArray.size() > 0);
|
assert(DieArray.size() > 0);
|
||||||
DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize);
|
DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize);
|
||||||
return RangeList.extract(RangesData, &RangeListOffset);
|
uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
|
||||||
|
return RangeList.extract(RangesData, &ActualRangeListOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DWARFCompileUnit::clear() {
|
void DWARFCompileUnit::clear() {
|
||||||
@ -88,7 +108,10 @@ void DWARFCompileUnit::clear() {
|
|||||||
Abbrevs = 0;
|
Abbrevs = 0;
|
||||||
AddrSize = 0;
|
AddrSize = 0;
|
||||||
BaseAddr = 0;
|
BaseAddr = 0;
|
||||||
|
RangeSectionBase = 0;
|
||||||
|
AddrOffsetSectionBase = 0;
|
||||||
clearDIEs(false);
|
clearDIEs(false);
|
||||||
|
DWO.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DWARFCompileUnit::dump(raw_ostream &OS) {
|
void DWARFCompileUnit::dump(raw_ostream &OS) {
|
||||||
@ -112,6 +135,15 @@ const char *DWARFCompileUnit::getCompilationDir() {
|
|||||||
return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0);
|
return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t DWARFCompileUnit::getDWOId() {
|
||||||
|
extractDIEsIfNeeded(true);
|
||||||
|
const uint64_t FailValue = -1ULL;
|
||||||
|
if (DieArray.empty())
|
||||||
|
return FailValue;
|
||||||
|
return DieArray[0]
|
||||||
|
.getAttributeValueAsUnsigned(this, DW_AT_GNU_dwo_id, FailValue);
|
||||||
|
}
|
||||||
|
|
||||||
void DWARFCompileUnit::setDIERelations() {
|
void DWARFCompileUnit::setDIERelations() {
|
||||||
if (DieArray.empty())
|
if (DieArray.empty())
|
||||||
return;
|
return;
|
||||||
@ -207,21 +239,72 @@ size_t DWARFCompileUnit::extractDIEsIfNeeded(bool CUDieOnly) {
|
|||||||
DieArray.size() > 1)
|
DieArray.size() > 1)
|
||||||
return 0; // Already parsed.
|
return 0; // Already parsed.
|
||||||
|
|
||||||
extractDIEsToVector(DieArray.empty(), !CUDieOnly, DieArray);
|
bool HasCUDie = DieArray.size() > 0;
|
||||||
|
extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
|
||||||
|
|
||||||
// Set the base address of current compile unit.
|
if (DieArray.empty())
|
||||||
if (!DieArray.empty()) {
|
return 0;
|
||||||
|
|
||||||
|
// If CU DIE was just parsed, copy several attribute values from it.
|
||||||
|
if (!HasCUDie) {
|
||||||
uint64_t BaseAddr =
|
uint64_t BaseAddr =
|
||||||
DieArray[0].getAttributeValueAsUnsigned(this, DW_AT_low_pc, -1U);
|
DieArray[0].getAttributeValueAsUnsigned(this, DW_AT_low_pc, -1U);
|
||||||
if (BaseAddr == -1U)
|
if (BaseAddr == -1U)
|
||||||
BaseAddr = DieArray[0].getAttributeValueAsUnsigned(this, DW_AT_entry_pc, 0);
|
BaseAddr = DieArray[0].getAttributeValueAsUnsigned(this, DW_AT_entry_pc, 0);
|
||||||
setBaseAddress(BaseAddr);
|
setBaseAddress(BaseAddr);
|
||||||
|
AddrOffsetSectionBase =
|
||||||
|
DieArray[0].getAttributeValueAsReference(this, DW_AT_GNU_addr_base, 0);
|
||||||
|
RangeSectionBase =
|
||||||
|
DieArray[0].getAttributeValueAsReference(this, DW_AT_GNU_ranges_base, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
setDIERelations();
|
setDIERelations();
|
||||||
return DieArray.size();
|
return DieArray.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWARFCompileUnit::DWOHolder::DWOHolder(object::ObjectFile *DWOFile)
|
||||||
|
: DWOFile(DWOFile),
|
||||||
|
DWOContext(cast<DWARFContext>(DIContext::getDWARFContext(DWOFile))),
|
||||||
|
DWOCU(0) {
|
||||||
|
if (DWOContext->getNumDWOCompileUnits() > 0)
|
||||||
|
DWOCU = DWOContext->getDWOCompileUnitAtIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DWARFCompileUnit::parseDWO() {
|
||||||
|
if (DWO.get() != 0)
|
||||||
|
return false;
|
||||||
|
extractDIEsIfNeeded(true);
|
||||||
|
if (DieArray.empty())
|
||||||
|
return false;
|
||||||
|
const char *DWOFileName =
|
||||||
|
DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, 0);
|
||||||
|
if (DWOFileName == 0)
|
||||||
|
return false;
|
||||||
|
const char *CompilationDir =
|
||||||
|
DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0);
|
||||||
|
SmallString<16> AbsolutePath;
|
||||||
|
if (sys::path::is_relative(DWOFileName) && CompilationDir != 0) {
|
||||||
|
sys::path::append(AbsolutePath, CompilationDir);
|
||||||
|
}
|
||||||
|
sys::path::append(AbsolutePath, DWOFileName);
|
||||||
|
object::ObjectFile *DWOFile =
|
||||||
|
object::ObjectFile::createObjectFile(AbsolutePath);
|
||||||
|
if (!DWOFile)
|
||||||
|
return false;
|
||||||
|
// Reset DWOHolder.
|
||||||
|
DWO.reset(new DWOHolder(DWOFile));
|
||||||
|
DWARFCompileUnit *DWOCU = DWO->getCU();
|
||||||
|
// Verify that compile unit in .dwo file is valid.
|
||||||
|
if (DWOCU == 0 || DWOCU->getDWOId() != getDWOId()) {
|
||||||
|
DWO.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Share .debug_addr and .debug_ranges section with compile unit in .dwo
|
||||||
|
DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);
|
||||||
|
DWOCU->setRangesSection(RangeSection, RangeSectionBase);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void DWARFCompileUnit::clearDIEs(bool KeepCUDie) {
|
void DWARFCompileUnit::clearDIEs(bool KeepCUDie) {
|
||||||
if (DieArray.size() > (unsigned)KeepCUDie) {
|
if (DieArray.size() > (unsigned)KeepCUDie) {
|
||||||
// std::vectors never get any smaller when resized to a smaller size,
|
// std::vectors never get any smaller when resized to a smaller size,
|
||||||
@ -241,7 +324,8 @@ void DWARFCompileUnit::clearDIEs(bool KeepCUDie) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
|
DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
|
||||||
bool clear_dies_if_already_not_parsed){
|
bool clear_dies_if_already_not_parsed,
|
||||||
|
uint32_t CUOffsetInAranges) {
|
||||||
// This function is usually called if there in no .debug_aranges section
|
// This function is usually called if there in no .debug_aranges section
|
||||||
// in order to produce a compile unit level set of address ranges that
|
// in order to produce a compile unit level set of address ranges that
|
||||||
// is accurate. If the DIEs weren't parsed, then we don't want all dies for
|
// is accurate. If the DIEs weren't parsed, then we don't want all dies for
|
||||||
@ -250,7 +334,17 @@ DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
|
|||||||
// down.
|
// down.
|
||||||
const bool clear_dies = extractDIEsIfNeeded(false) > 1 &&
|
const bool clear_dies = extractDIEsIfNeeded(false) > 1 &&
|
||||||
clear_dies_if_already_not_parsed;
|
clear_dies_if_already_not_parsed;
|
||||||
DieArray[0].buildAddressRangeTable(this, debug_aranges);
|
DieArray[0].buildAddressRangeTable(this, debug_aranges, CUOffsetInAranges);
|
||||||
|
bool DWOCreated = parseDWO();
|
||||||
|
if (DWO.get()) {
|
||||||
|
// If there is a .dwo file for this compile unit, then skeleton CU DIE
|
||||||
|
// doesn't have children, and we should instead build address range table
|
||||||
|
// from DIEs in the .debug_info.dwo section of .dwo file.
|
||||||
|
DWO->getCU()->buildAddressRangeTable(
|
||||||
|
debug_aranges, clear_dies_if_already_not_parsed, CUOffsetInAranges);
|
||||||
|
}
|
||||||
|
if (DWOCreated && clear_dies_if_already_not_parsed)
|
||||||
|
DWO.reset();
|
||||||
|
|
||||||
// Keep memory down by clearing DIEs if this generate function
|
// Keep memory down by clearing DIEs if this generate function
|
||||||
// caused them to be parsed.
|
// caused them to be parsed.
|
||||||
@ -258,21 +352,38 @@ DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
|
|||||||
clearDIEs(true);
|
clearDIEs(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DWARFDebugInfoEntryMinimal *
|
||||||
|
DWARFCompileUnit::getSubprogramForAddress(uint64_t Address) {
|
||||||
|
extractDIEsIfNeeded(false);
|
||||||
|
for (size_t i = 0, n = DieArray.size(); i != n; i++)
|
||||||
|
if (DieArray[i].isSubprogramDIE() &&
|
||||||
|
DieArray[i].addressRangeContainsAddress(this, Address)) {
|
||||||
|
return &DieArray[i];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
DWARFDebugInfoEntryInlinedChain
|
DWARFDebugInfoEntryInlinedChain
|
||||||
DWARFCompileUnit::getInlinedChainForAddress(uint64_t Address) {
|
DWARFCompileUnit::getInlinedChainForAddress(uint64_t Address) {
|
||||||
// First, find a subprogram that contains the given address (the root
|
// First, find a subprogram that contains the given address (the root
|
||||||
// of inlined chain).
|
// of inlined chain).
|
||||||
extractDIEsIfNeeded(false);
|
const DWARFCompileUnit *ChainCU = 0;
|
||||||
const DWARFDebugInfoEntryMinimal *SubprogramDIE = 0;
|
const DWARFDebugInfoEntryMinimal *SubprogramDIE =
|
||||||
for (size_t i = 0, n = DieArray.size(); i != n; i++) {
|
getSubprogramForAddress(Address);
|
||||||
if (DieArray[i].isSubprogramDIE() &&
|
if (SubprogramDIE) {
|
||||||
DieArray[i].addressRangeContainsAddress(this, Address)) {
|
ChainCU = this;
|
||||||
SubprogramDIE = &DieArray[i];
|
} else {
|
||||||
break;
|
// Try to look for subprogram DIEs in the DWO file.
|
||||||
|
parseDWO();
|
||||||
|
if (DWO.get()) {
|
||||||
|
SubprogramDIE = DWO->getCU()->getSubprogramForAddress(Address);
|
||||||
|
if (SubprogramDIE)
|
||||||
|
ChainCU = DWO->getCU();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get inlined chain rooted at this subprogram DIE.
|
// Get inlined chain rooted at this subprogram DIE.
|
||||||
if (!SubprogramDIE)
|
if (!SubprogramDIE)
|
||||||
return DWARFDebugInfoEntryInlinedChain();
|
return DWARFDebugInfoEntryInlinedChain();
|
||||||
return SubprogramDIE->getInlinedChainForAddress(this, Address);
|
return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#ifndef LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H
|
#ifndef LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H
|
||||||
#define LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H
|
#define LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/OwningPtr.h"
|
||||||
#include "DWARFDebugAbbrev.h"
|
#include "DWARFDebugAbbrev.h"
|
||||||
#include "DWARFDebugInfoEntry.h"
|
#include "DWARFDebugInfoEntry.h"
|
||||||
#include "DWARFDebugRangeList.h"
|
#include "DWARFDebugRangeList.h"
|
||||||
@ -18,6 +19,10 @@
|
|||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
namespace object {
|
||||||
|
class ObjectFile;
|
||||||
|
}
|
||||||
|
|
||||||
class DWARFDebugAbbrev;
|
class DWARFDebugAbbrev;
|
||||||
class StringRef;
|
class StringRef;
|
||||||
class raw_ostream;
|
class raw_ostream;
|
||||||
@ -30,9 +35,11 @@ class DWARFCompileUnit {
|
|||||||
StringRef InfoSection;
|
StringRef InfoSection;
|
||||||
StringRef AbbrevSection;
|
StringRef AbbrevSection;
|
||||||
StringRef RangeSection;
|
StringRef RangeSection;
|
||||||
|
uint32_t RangeSectionBase;
|
||||||
StringRef StringSection;
|
StringRef StringSection;
|
||||||
StringRef StringOffsetSection;
|
StringRef StringOffsetSection;
|
||||||
StringRef AddrOffsetSection;
|
StringRef AddrOffsetSection;
|
||||||
|
uint32_t AddrOffsetSectionBase;
|
||||||
const RelocAddrMap *RelocMap;
|
const RelocAddrMap *RelocMap;
|
||||||
bool isLittleEndian;
|
bool isLittleEndian;
|
||||||
|
|
||||||
@ -44,6 +51,17 @@ class DWARFCompileUnit {
|
|||||||
uint64_t BaseAddr;
|
uint64_t BaseAddr;
|
||||||
// The compile unit debug information entry items.
|
// The compile unit debug information entry items.
|
||||||
std::vector<DWARFDebugInfoEntryMinimal> DieArray;
|
std::vector<DWARFDebugInfoEntryMinimal> DieArray;
|
||||||
|
|
||||||
|
class DWOHolder {
|
||||||
|
OwningPtr<object::ObjectFile> DWOFile;
|
||||||
|
OwningPtr<DWARFContext> DWOContext;
|
||||||
|
DWARFCompileUnit *DWOCU;
|
||||||
|
public:
|
||||||
|
DWOHolder(object::ObjectFile *DWOFile);
|
||||||
|
DWARFCompileUnit *getCU() const { return DWOCU; }
|
||||||
|
};
|
||||||
|
OwningPtr<DWOHolder> DWO;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS,
|
DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS,
|
||||||
@ -57,9 +75,27 @@ public:
|
|||||||
|
|
||||||
StringRef getStringSection() const { return StringSection; }
|
StringRef getStringSection() const { return StringSection; }
|
||||||
StringRef getStringOffsetSection() const { return StringOffsetSection; }
|
StringRef getStringOffsetSection() const { return StringOffsetSection; }
|
||||||
StringRef getAddrOffsetSection() const { return AddrOffsetSection; }
|
void setAddrOffsetSection(StringRef AOS, uint32_t Base) {
|
||||||
|
AddrOffsetSection = AOS;
|
||||||
|
AddrOffsetSectionBase = Base;
|
||||||
|
}
|
||||||
|
void setRangesSection(StringRef RS, uint32_t Base) {
|
||||||
|
RangeSection = RS;
|
||||||
|
RangeSectionBase = Base;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
|
||||||
|
// FIXME: Result should be uint64_t in DWARF64.
|
||||||
|
bool getStringOffsetSectionItem(uint32_t Index, uint32_t &Result) const;
|
||||||
|
|
||||||
|
DataExtractor getDebugInfoExtractor() const {
|
||||||
|
return DataExtractor(InfoSection, isLittleEndian, AddrSize);
|
||||||
|
}
|
||||||
|
DataExtractor getStringExtractor() const {
|
||||||
|
return DataExtractor(StringSection, false, 0);
|
||||||
|
}
|
||||||
|
|
||||||
const RelocAddrMap *getRelocMap() const { return RelocMap; }
|
const RelocAddrMap *getRelocMap() const { return RelocMap; }
|
||||||
DataExtractor getDebugInfoExtractor() const;
|
|
||||||
|
|
||||||
bool extract(DataExtractor debug_info, uint32_t* offset_ptr);
|
bool extract(DataExtractor debug_info, uint32_t* offset_ptr);
|
||||||
uint32_t extract(uint32_t offset, DataExtractor debug_info_data,
|
uint32_t extract(uint32_t offset, DataExtractor debug_info_data,
|
||||||
@ -105,6 +141,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *getCompilationDir();
|
const char *getCompilationDir();
|
||||||
|
uint64_t getDWOId();
|
||||||
|
|
||||||
/// setDIERelations - We read in all of the DIE entries into our flat list
|
/// setDIERelations - We read in all of the DIE entries into our flat list
|
||||||
/// of DIE entries and now we need to go back through all of them and set the
|
/// of DIE entries and now we need to go back through all of them and set the
|
||||||
@ -112,7 +149,8 @@ public:
|
|||||||
void setDIERelations();
|
void setDIERelations();
|
||||||
|
|
||||||
void buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
|
void buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
|
||||||
bool clear_dies_if_already_not_parsed);
|
bool clear_dies_if_already_not_parsed,
|
||||||
|
uint32_t CUOffsetInAranges);
|
||||||
|
|
||||||
/// getInlinedChainForAddress - fetches inlined chain for a given address.
|
/// getInlinedChainForAddress - fetches inlined chain for a given address.
|
||||||
/// Returns empty chain if there is no subprogram containing address. The
|
/// Returns empty chain if there is no subprogram containing address. The
|
||||||
@ -125,6 +163,15 @@ private:
|
|||||||
std::vector<DWARFDebugInfoEntryMinimal> &DIEs) const;
|
std::vector<DWARFDebugInfoEntryMinimal> &DIEs) const;
|
||||||
/// clearDIEs - Clear parsed DIEs to keep memory usage low.
|
/// clearDIEs - Clear parsed DIEs to keep memory usage low.
|
||||||
void clearDIEs(bool KeepCUDie);
|
void clearDIEs(bool KeepCUDie);
|
||||||
|
|
||||||
|
/// parseDWO - Parses .dwo file for current compile unit. Returns true if
|
||||||
|
/// it was actually constructed.
|
||||||
|
bool parseDWO();
|
||||||
|
|
||||||
|
/// getSubprogramForAddress - Returns subprogram DIE with address range
|
||||||
|
/// encompassing the provided address. The pointer is alive as long as parsed
|
||||||
|
/// compile unit DIEs are not cleared.
|
||||||
|
const DWARFDebugInfoEntryMinimal *getSubprogramForAddress(uint64_t Address);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ bool DWARFDebugAranges::generate(DWARFContext *ctx) {
|
|||||||
if (DWARFCompileUnit *cu = ctx->getCompileUnitAtIndex(cu_idx)) {
|
if (DWARFCompileUnit *cu = ctx->getCompileUnitAtIndex(cu_idx)) {
|
||||||
uint32_t CUOffset = cu->getOffset();
|
uint32_t CUOffset = cu->getOffset();
|
||||||
if (ParsedCUOffsets.insert(CUOffset).second)
|
if (ParsedCUOffsets.insert(CUOffset).second)
|
||||||
cu->buildAddressRangeTable(this, true);
|
cu->buildAddressRangeTable(this, true, CUOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,29 +222,30 @@ DWARFDebugInfoEntryMinimal::getAttributeValue(const DWARFCompileUnit *cu,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
|
||||||
DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
|
const DWARFCompileUnit *CU, const uint16_t Attr,
|
||||||
const DWARFCompileUnit* cu,
|
const char *FailValue) const {
|
||||||
const uint16_t attr,
|
DWARFFormValue FormValue;
|
||||||
const char* fail_value)
|
if (getAttributeValue(CU, Attr, FormValue))
|
||||||
const {
|
return FormValue.getAsCString(CU);
|
||||||
DWARFFormValue form_value;
|
return FailValue;
|
||||||
if (getAttributeValue(cu, attr, form_value)) {
|
|
||||||
DataExtractor stringExtractor(cu->getStringSection(), false, 0);
|
|
||||||
return form_value.getAsCString(&stringExtractor);
|
|
||||||
}
|
|
||||||
return fail_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress(
|
||||||
DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsigned(
|
const DWARFCompileUnit *CU, const uint16_t Attr, uint64_t FailValue) const {
|
||||||
const DWARFCompileUnit* cu,
|
DWARFFormValue FormValue;
|
||||||
const uint16_t attr,
|
if (getAttributeValue(CU, Attr, FormValue))
|
||||||
uint64_t fail_value) const {
|
return FormValue.getAsAddress(CU);
|
||||||
DWARFFormValue form_value;
|
return FailValue;
|
||||||
if (getAttributeValue(cu, attr, form_value))
|
}
|
||||||
return form_value.getUnsigned();
|
|
||||||
return fail_value;
|
uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsigned(
|
||||||
|
const DWARFCompileUnit *CU, const uint16_t Attr, uint64_t FailValue) const {
|
||||||
|
DWARFFormValue FormValue;
|
||||||
|
if (getAttributeValue(CU, Attr, FormValue)) {
|
||||||
|
return FormValue.getUnsigned();
|
||||||
|
}
|
||||||
|
return FailValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
@ -274,29 +275,29 @@ bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFCompileUnit *CU,
|
|||||||
uint64_t &LowPC,
|
uint64_t &LowPC,
|
||||||
uint64_t &HighPC) const {
|
uint64_t &HighPC) const {
|
||||||
HighPC = -1ULL;
|
HighPC = -1ULL;
|
||||||
LowPC = getAttributeValueAsUnsigned(CU, DW_AT_low_pc, -1ULL);
|
LowPC = getAttributeValueAsAddress(CU, DW_AT_low_pc, -1ULL);
|
||||||
if (LowPC != -1ULL)
|
if (LowPC != -1ULL)
|
||||||
HighPC = getAttributeValueAsUnsigned(CU, DW_AT_high_pc, -1ULL);
|
HighPC = getAttributeValueAsAddress(CU, DW_AT_high_pc, -1ULL);
|
||||||
return (HighPC != -1ULL);
|
return (HighPC != -1ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *CU,
|
DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *CU,
|
||||||
DWARFDebugAranges *DebugAranges)
|
DWARFDebugAranges *DebugAranges,
|
||||||
|
uint32_t CUOffsetInAranges)
|
||||||
const {
|
const {
|
||||||
if (AbbrevDecl) {
|
if (AbbrevDecl) {
|
||||||
if (isSubprogramDIE()) {
|
if (isSubprogramDIE()) {
|
||||||
uint64_t LowPC, HighPC;
|
uint64_t LowPC, HighPC;
|
||||||
if (getLowAndHighPC(CU, LowPC, HighPC)) {
|
if (getLowAndHighPC(CU, LowPC, HighPC))
|
||||||
DebugAranges->appendRange(CU->getOffset(), LowPC, HighPC);
|
DebugAranges->appendRange(CUOffsetInAranges, LowPC, HighPC);
|
||||||
}
|
|
||||||
// FIXME: try to append ranges from .debug_ranges section.
|
// FIXME: try to append ranges from .debug_ranges section.
|
||||||
}
|
}
|
||||||
|
|
||||||
const DWARFDebugInfoEntryMinimal *child = getFirstChild();
|
const DWARFDebugInfoEntryMinimal *Child = getFirstChild();
|
||||||
while (child) {
|
while (Child) {
|
||||||
child->buildAddressRangeTable(CU, DebugAranges);
|
Child->buildAddressRangeTable(CU, DebugAranges, CUOffsetInAranges);
|
||||||
child = child->getSibling();
|
Child = Child->getSibling();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,6 +128,10 @@ public:
|
|||||||
const uint16_t attr,
|
const uint16_t attr,
|
||||||
const char *fail_value) const;
|
const char *fail_value) const;
|
||||||
|
|
||||||
|
uint64_t getAttributeValueAsAddress(const DWARFCompileUnit *CU,
|
||||||
|
const uint16_t Attr,
|
||||||
|
uint64_t FailValue) const;
|
||||||
|
|
||||||
uint64_t getAttributeValueAsUnsigned(const DWARFCompileUnit *cu,
|
uint64_t getAttributeValueAsUnsigned(const DWARFCompileUnit *cu,
|
||||||
const uint16_t attr,
|
const uint16_t attr,
|
||||||
uint64_t fail_value) const;
|
uint64_t fail_value) const;
|
||||||
@ -146,7 +150,8 @@ public:
|
|||||||
uint64_t &LowPC, uint64_t &HighPC) const;
|
uint64_t &LowPC, uint64_t &HighPC) const;
|
||||||
|
|
||||||
void buildAddressRangeTable(const DWARFCompileUnit *CU,
|
void buildAddressRangeTable(const DWARFCompileUnit *CU,
|
||||||
DWARFDebugAranges *DebugAranges) const;
|
DWARFDebugAranges *DebugAranges,
|
||||||
|
uint32_t CUOffsetInAranges) const;
|
||||||
|
|
||||||
bool addressRangeContainsAddress(const DWARFCompileUnit *CU,
|
bool addressRangeContainsAddress(const DWARFCompileUnit *CU,
|
||||||
const uint64_t Address) const;
|
const uint64_t Address) const;
|
||||||
|
@ -183,10 +183,9 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
|
|||||||
Value.uval = data.getU64(offset_ptr);
|
Value.uval = data.getU64(offset_ptr);
|
||||||
break;
|
break;
|
||||||
case DW_FORM_GNU_addr_index:
|
case DW_FORM_GNU_addr_index:
|
||||||
Value.uval = data.getULEB128(offset_ptr);
|
|
||||||
break;
|
|
||||||
case DW_FORM_GNU_str_index:
|
case DW_FORM_GNU_str_index:
|
||||||
Value.uval = data.getULEB128(offset_ptr);
|
Value.uval = data.getULEB128(offset_ptr);
|
||||||
|
Value.IsDWOIndex = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@ -322,12 +321,11 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
|
|||||||
switch (Form) {
|
switch (Form) {
|
||||||
case DW_FORM_addr: OS << format("0x%016" PRIx64, uvalue); break;
|
case DW_FORM_addr: OS << format("0x%016" PRIx64, uvalue); break;
|
||||||
case DW_FORM_GNU_addr_index: {
|
case DW_FORM_GNU_addr_index: {
|
||||||
StringRef AddrOffsetSec = cu->getAddrOffsetSection();
|
|
||||||
OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue);
|
OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue);
|
||||||
if (AddrOffsetSec.size() != 0) {
|
uint64_t Address;
|
||||||
DataExtractor DA(AddrOffsetSec, true, cu->getAddressByteSize());
|
if (cu->getAddrOffsetSectionItem(uvalue, Address))
|
||||||
OS << format("0x%016" PRIx64, getIndirectAddress(&DA, cu));
|
OS << format("0x%016" PRIx64, Address);
|
||||||
} else
|
else
|
||||||
OS << "<no .debug_addr section>";
|
OS << "<no .debug_addr section>";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -376,7 +374,7 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
|
|||||||
case DW_FORM_udata: OS << getUnsigned(); break;
|
case DW_FORM_udata: OS << getUnsigned(); break;
|
||||||
case DW_FORM_strp: {
|
case DW_FORM_strp: {
|
||||||
OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
|
OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
|
||||||
const char* dbg_str = getAsCString(&debug_str_data);
|
const char* dbg_str = getAsCString(cu);
|
||||||
if (dbg_str) {
|
if (dbg_str) {
|
||||||
OS << '"';
|
OS << '"';
|
||||||
OS.write_escaped(dbg_str);
|
OS.write_escaped(dbg_str);
|
||||||
@ -386,8 +384,7 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
|
|||||||
}
|
}
|
||||||
case DW_FORM_GNU_str_index: {
|
case DW_FORM_GNU_str_index: {
|
||||||
OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
|
OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
|
||||||
const char *dbg_str = getIndirectCString(&debug_str_data,
|
const char *dbg_str = getAsCString(cu);
|
||||||
&debug_str_offset_data);
|
|
||||||
if (dbg_str) {
|
if (dbg_str) {
|
||||||
OS << '"';
|
OS << '"';
|
||||||
OS.write_escaped(dbg_str);
|
OS.write_escaped(dbg_str);
|
||||||
@ -440,33 +437,33 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
DWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const {
|
DWARFFormValue::getAsCString(const DWARFCompileUnit *CU) const {
|
||||||
if (isInlinedCStr()) {
|
if (isInlinedCStr())
|
||||||
return Value.cstr;
|
return Value.cstr;
|
||||||
} else if (debug_str_data_ptr) {
|
if (!CU)
|
||||||
uint32_t offset = Value.uval;
|
|
||||||
return debug_str_data_ptr->getCStr(&offset);
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
uint32_t Offset = Value.uval;
|
||||||
|
if (Value.IsDWOIndex) {
|
||||||
const char*
|
uint32_t StrOffset;
|
||||||
DWARFFormValue::getIndirectCString(const DataExtractor *DS,
|
if (!CU->getStringOffsetSectionItem(Offset, StrOffset))
|
||||||
const DataExtractor *DSO) const {
|
return NULL;
|
||||||
if (!DS || !DSO) return NULL;
|
Offset = StrOffset;
|
||||||
|
}
|
||||||
uint32_t offset = Value.uval * 4;
|
return CU->getStringExtractor().getCStr(&Offset);
|
||||||
uint32_t soffset = DSO->getU32(&offset);
|
|
||||||
return DS->getCStr(&soffset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
DWARFFormValue::getIndirectAddress(const DataExtractor *DA,
|
DWARFFormValue::getAsAddress(const DWARFCompileUnit *CU) const {
|
||||||
const DWARFCompileUnit *cu) const {
|
if (!CU)
|
||||||
if (!DA) return 0;
|
return 0;
|
||||||
|
if (Value.IsDWOIndex) {
|
||||||
uint32_t offset = Value.uval * cu->getAddressByteSize();
|
uint32_t Index = Value.uval;
|
||||||
return DA->getAddress(&offset);
|
uint64_t Address;
|
||||||
|
if (!CU->getAddrOffsetSectionItem(Index, Address))
|
||||||
|
return 0;
|
||||||
|
return Address;
|
||||||
|
}
|
||||||
|
return Value.uval;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const {
|
uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user