DwarfFile: Implement handling of .debug_types section.
- Refactor ExpressionEvaluationContext::GetCallTarget() and DwarfFile::_ResolveReference() to use an enum value for the type of reference being passed in, as we now need to support signature references in addition to local/global. Adjust callers. - Factor out an _ParseDebugInfoSection() and add a corresponding _ParseTypesSection() for the top level loops that handle .debug_info and .debug_types respectively. - Refactor _ParseDebugInfoEntry(), _ParseEntryAttributes() and _ResolveReference to take a pointer to the relevant BaseUnit in order to allow sharing between parsing of the types and info sections. - Implement support for DW_FORM_ref_sig8. In order to handle this, we use a hash table that maps from the corresponding 64-bit DW_AT_signature values to their respective type units. - Adjust debug output to more closely match offsets and values used by objdump for ease of troubleshooting parsing issues. Combined, these changes allow us to load DWARF 4 binaries sufficiently to get source information and unwind call frame, though support is still incomplete. In particular, global references aren't yet implemented, and neither are location expression attributes, which are now used quite heavily, and consequently we can't yet resolve variable values and a few other things properly.
This commit is contained in:
@@ -507,4 +507,11 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum dwarf_reference_type {
|
||||||
|
dwarf_reference_type_local = 0,
|
||||||
|
dwarf_reference_type_global,
|
||||||
|
dwarf_reference_type_signature
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // DWARF_H
|
#endif // DWARF_H
|
||||||
|
|||||||
@@ -600,18 +600,21 @@ DwarfExpressionEvaluator::_Evaluate(ValuePieceLocation* _piece)
|
|||||||
|
|
||||||
case DW_OP_call2:
|
case DW_OP_call2:
|
||||||
TRACE_EXPR(" DW_OP_call2\n");
|
TRACE_EXPR(" DW_OP_call2\n");
|
||||||
_Call(fDataReader.Read<uint16>(0), true);
|
_Call(fDataReader.Read<uint16>(0), dwarf_reference_type_local);
|
||||||
break;
|
break;
|
||||||
case DW_OP_call4:
|
case DW_OP_call4:
|
||||||
TRACE_EXPR(" DW_OP_call4\n");
|
TRACE_EXPR(" DW_OP_call4\n");
|
||||||
_Call(fDataReader.Read<uint32>(0), true);
|
_Call(fDataReader.Read<uint32>(0), dwarf_reference_type_local);
|
||||||
break;
|
break;
|
||||||
case DW_OP_call_ref:
|
case DW_OP_call_ref:
|
||||||
TRACE_EXPR(" DW_OP_call_ref\n");
|
TRACE_EXPR(" DW_OP_call_ref\n");
|
||||||
if (fContext->AddressSize() == 4)
|
if (fContext->AddressSize() == 4) {
|
||||||
_Call(fDataReader.Read<uint32>(0), false);
|
_Call(fDataReader.Read<uint32>(0),
|
||||||
else
|
dwarf_reference_type_global);
|
||||||
_Call(fDataReader.Read<uint64>(0), false);
|
} else {
|
||||||
|
_Call(fDataReader.Read<uint64>(0),
|
||||||
|
dwarf_reference_type_global);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_OP_piece:
|
case DW_OP_piece:
|
||||||
@@ -746,7 +749,7 @@ DwarfExpressionEvaluator::_PushRegister(uint32 reg, target_addr_t offset)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DwarfExpressionEvaluator::_Call(uint64 offset, bool local)
|
DwarfExpressionEvaluator::_Call(uint64 offset, uint8 refType)
|
||||||
{
|
{
|
||||||
if (fDataReader.HasOverflow())
|
if (fDataReader.HasOverflow())
|
||||||
throw EvaluationException("unexpected end of expression");
|
throw EvaluationException("unexpected end of expression");
|
||||||
@@ -754,7 +757,7 @@ DwarfExpressionEvaluator::_Call(uint64 offset, bool local)
|
|||||||
// get the expression to "call"
|
// get the expression to "call"
|
||||||
const void* block;
|
const void* block;
|
||||||
off_t size;
|
off_t size;
|
||||||
if (fContext->GetCallTarget(offset, local, block, size) != B_OK)
|
if (fContext->GetCallTarget(offset, refType, block, size) != B_OK)
|
||||||
throw EvaluationException("failed to get call target");
|
throw EvaluationException("failed to get call target");
|
||||||
|
|
||||||
// no expression is OK, then this is just a no-op
|
// no expression is OK, then this is just a no-op
|
||||||
|
|||||||
@@ -37,8 +37,9 @@ public:
|
|||||||
virtual bool GetTLSAddress(target_addr_t localAddress,
|
virtual bool GetTLSAddress(target_addr_t localAddress,
|
||||||
target_addr_t& _address) = 0;
|
target_addr_t& _address) = 0;
|
||||||
|
|
||||||
virtual status_t GetCallTarget(uint64 offset, bool local,
|
virtual status_t GetCallTarget(uint64 offset,
|
||||||
const void*& _block, off_t& _size) = 0;
|
uint8 refType, const void*& _block,
|
||||||
|
off_t& _size) = 0;
|
||||||
// returns error, when an error resolving
|
// returns error, when an error resolving
|
||||||
// the entry occurs; returns B_OK and a NULL
|
// the entry occurs; returns B_OK and a NULL
|
||||||
// block, when the entry doesn't have a
|
// block, when the entry doesn't have a
|
||||||
@@ -81,7 +82,7 @@ private:
|
|||||||
void _DereferenceAddressSpaceAddress(
|
void _DereferenceAddressSpaceAddress(
|
||||||
uint8 addressSize);
|
uint8 addressSize);
|
||||||
void _PushRegister(uint32 reg, target_addr_t offset);
|
void _PushRegister(uint32 reg, target_addr_t offset);
|
||||||
void _Call(uint64 offset, bool local);
|
void _Call(uint64 offset, uint8 refType);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DwarfExpressionEvaluationContext* fContext;
|
DwarfExpressionEvaluationContext* fContext;
|
||||||
|
|||||||
@@ -147,11 +147,11 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual status_t GetCallTarget(uint64 offset, bool local,
|
virtual status_t GetCallTarget(uint64 offset, uint8 refType,
|
||||||
const void*& _block, off_t& _size)
|
const void*& _block, off_t& _size)
|
||||||
{
|
{
|
||||||
// resolve the entry
|
// resolve the entry
|
||||||
DebugInfoEntry* entry = fFile->_ResolveReference(fUnit, offset, local);
|
DebugInfoEntry* entry = fFile->_ResolveReference(fUnit, offset, refType);
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
@@ -459,8 +459,9 @@ DwarfFile::DwarfFile()
|
|||||||
fEHFrameSection(NULL),
|
fEHFrameSection(NULL),
|
||||||
fDebugLocationSection(NULL),
|
fDebugLocationSection(NULL),
|
||||||
fDebugPublicTypesSection(NULL),
|
fDebugPublicTypesSection(NULL),
|
||||||
|
fDebugTypesSection(NULL),
|
||||||
fCompilationUnits(20, true),
|
fCompilationUnits(20, true),
|
||||||
fCurrentCompilationUnit(NULL),
|
fTypesSectionRequired(false),
|
||||||
fFinished(false),
|
fFinished(false),
|
||||||
fFinishError(B_OK)
|
fFinishError(B_OK)
|
||||||
{
|
{
|
||||||
@@ -501,12 +502,16 @@ DwarfFile::Load(const char* fileName)
|
|||||||
if (fName == NULL)
|
if (fName == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
status_t error = fTypeUnits.Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
// load the ELF file
|
// load the ELF file
|
||||||
fElfFile = new(std::nothrow) ElfFile;
|
fElfFile = new(std::nothrow) ElfFile;
|
||||||
if (fElfFile == NULL)
|
if (fElfFile == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
status_t error = fElfFile->Init(fileName);
|
error = fElfFile->Init(fileName);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -535,72 +540,19 @@ DwarfFile::Load(const char* fileName)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate through the debug info section
|
error = _ParseDebugInfoSection();
|
||||||
DataReader dataReader(fDebugInfoSection->Data(),
|
if (error != B_OK)
|
||||||
fDebugInfoSection->Size(), 4);
|
return error;
|
||||||
// address size doesn't matter here
|
|
||||||
while (dataReader.HasData()) {
|
|
||||||
off_t unitHeaderOffset = dataReader.Offset();
|
|
||||||
bool dwarf64;
|
|
||||||
uint64 unitLength = dataReader.ReadInitialLength(dwarf64);
|
|
||||||
|
|
||||||
off_t unitLengthOffset = dataReader.Offset();
|
if (fTypesSectionRequired) {
|
||||||
// the unitLength starts here
|
fDebugTypesSection = debugInfoFile->GetSection(".debug_types");
|
||||||
|
if (fDebugTypesSection == NULL) {
|
||||||
if (unitLengthOffset + unitLength
|
WARNING(".debug_types section required but missing.\n");
|
||||||
> (uint64)fDebugInfoSection->Size()) {
|
return B_BAD_DATA;
|
||||||
WARNING("\"%s\": Invalid compilation unit length.\n", fileName);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
error = _ParseTypesSection();
|
||||||
int version = dataReader.Read<uint16>(0);
|
|
||||||
off_t abbrevOffset = dwarf64
|
|
||||||
? dataReader.Read<uint64>(0)
|
|
||||||
: dataReader.Read<uint32>(0);
|
|
||||||
uint8 addressSize = dataReader.Read<uint8>(0);
|
|
||||||
|
|
||||||
if (dataReader.HasOverflow()) {
|
|
||||||
WARNING("\"%s\": Unexpected end of data in compilation unit "
|
|
||||||
"header.\n", fileName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE_DIE("DWARF%d compilation unit: version %d, length: %" B_PRIu64
|
|
||||||
", abbrevOffset: %" B_PRIdOFF ", address size: %d\n",
|
|
||||||
dwarf64 ? 64 : 32, version, unitLength, abbrevOffset, addressSize);
|
|
||||||
|
|
||||||
if (version != 2 && version != 3) {
|
|
||||||
WARNING("\"%s\": Unsupported compilation unit version: %d\n",
|
|
||||||
fileName, version);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addressSize != 4 && addressSize != 8) {
|
|
||||||
WARNING("\"%s\": Unsupported address size: %d\n", fileName,
|
|
||||||
addressSize);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dataReader.SetAddressSize(addressSize);
|
|
||||||
|
|
||||||
off_t unitContentOffset = dataReader.Offset();
|
|
||||||
|
|
||||||
// create a compilation unit object
|
|
||||||
CompilationUnit* unit = new(std::nothrow) CompilationUnit(
|
|
||||||
unitHeaderOffset, unitContentOffset,
|
|
||||||
unitLength + (unitLengthOffset - unitHeaderOffset),
|
|
||||||
abbrevOffset, addressSize, dwarf64);
|
|
||||||
if (unit == NULL || !fCompilationUnits.AddItem(unit)) {
|
|
||||||
delete unit;
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse the debug info for the unit
|
|
||||||
fCurrentCompilationUnit = unit;
|
|
||||||
error = _ParseCompilationUnit(unit);
|
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
dataReader.SeekAbsolute(unitLengthOffset + unitLength);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -615,10 +567,17 @@ DwarfFile::FinishLoading()
|
|||||||
if (fFinishError != B_OK)
|
if (fFinishError != B_OK)
|
||||||
return fFinishError;
|
return fFinishError;
|
||||||
|
|
||||||
|
status_t error;
|
||||||
for (int32 i = 0; CompilationUnit* unit = fCompilationUnits.ItemAt(i);
|
for (int32 i = 0; CompilationUnit* unit = fCompilationUnits.ItemAt(i);
|
||||||
i++) {
|
i++) {
|
||||||
fCurrentCompilationUnit = unit;
|
error = _FinishUnit(unit);
|
||||||
status_t error = _FinishCompilationUnit(unit);
|
if (error != B_OK)
|
||||||
|
return fFinishError = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TypeUnitTable::Iterator it = fTypeUnits.GetIterator();
|
||||||
|
TypeUnitTableEntry* entry = it.Next();) {
|
||||||
|
error = _FinishUnit(entry->unit);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return fFinishError = error;
|
return fFinishError = error;
|
||||||
}
|
}
|
||||||
@@ -935,6 +894,171 @@ DwarfFile::EvaluateDynamicValue(CompilationUnit* unit, uint8 addressSize,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::_ParseDebugInfoSection()
|
||||||
|
{
|
||||||
|
// iterate through the debug info section
|
||||||
|
DataReader dataReader(fDebugInfoSection->Data(),
|
||||||
|
fDebugInfoSection->Size(), 4);
|
||||||
|
// address size doesn't matter here
|
||||||
|
while (dataReader.HasData()) {
|
||||||
|
off_t unitHeaderOffset = dataReader.Offset();
|
||||||
|
bool dwarf64;
|
||||||
|
uint64 unitLength = dataReader.ReadInitialLength(dwarf64);
|
||||||
|
|
||||||
|
off_t unitLengthOffset = dataReader.Offset();
|
||||||
|
// the unitLength starts here
|
||||||
|
|
||||||
|
if (unitLengthOffset + unitLength
|
||||||
|
> (uint64)fDebugInfoSection->Size()) {
|
||||||
|
WARNING("\"%s\": Invalid compilation unit length.\n", fName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int version = dataReader.Read<uint16>(0);
|
||||||
|
off_t abbrevOffset = dwarf64
|
||||||
|
? dataReader.Read<uint64>(0)
|
||||||
|
: dataReader.Read<uint32>(0);
|
||||||
|
uint8 addressSize = dataReader.Read<uint8>(0);
|
||||||
|
|
||||||
|
if (dataReader.HasOverflow()) {
|
||||||
|
WARNING("\"%s\": Unexpected end of data in compilation unit "
|
||||||
|
"header.\n", fName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE_DIE("DWARF%d compilation unit: version %d, length: %" B_PRIu64
|
||||||
|
", abbrevOffset: %" B_PRIdOFF ", address size: %d\n",
|
||||||
|
dwarf64 ? 64 : 32, version, unitLength, abbrevOffset, addressSize);
|
||||||
|
|
||||||
|
if (version < 2 || version > 4) {
|
||||||
|
WARNING("\"%s\": Unsupported compilation unit version: %d\n",
|
||||||
|
fName, version);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addressSize != 4 && addressSize != 8) {
|
||||||
|
WARNING("\"%s\": Unsupported address size: %d\n", fName,
|
||||||
|
addressSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dataReader.SetAddressSize(addressSize);
|
||||||
|
|
||||||
|
off_t unitContentOffset = dataReader.Offset();
|
||||||
|
|
||||||
|
// create a compilation unit object
|
||||||
|
CompilationUnit* unit = new(std::nothrow) CompilationUnit(
|
||||||
|
unitHeaderOffset, unitContentOffset,
|
||||||
|
unitLength + (unitLengthOffset - unitHeaderOffset),
|
||||||
|
abbrevOffset, addressSize, dwarf64);
|
||||||
|
if (unit == NULL || !fCompilationUnits.AddItem(unit)) {
|
||||||
|
delete unit;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the debug info for the unit
|
||||||
|
status_t error = _ParseCompilationUnit(unit);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
dataReader.SeekAbsolute(unitLengthOffset + unitLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::_ParseTypesSection()
|
||||||
|
{
|
||||||
|
DataReader dataReader(fDebugTypesSection->Data(),
|
||||||
|
fDebugTypesSection->Size(), 4);
|
||||||
|
while (dataReader.HasData()) {
|
||||||
|
off_t unitHeaderOffset = dataReader.Offset();
|
||||||
|
bool dwarf64;
|
||||||
|
uint64 unitLength = dataReader.ReadInitialLength(dwarf64);
|
||||||
|
|
||||||
|
off_t unitLengthOffset = dataReader.Offset();
|
||||||
|
// the unitLength starts here
|
||||||
|
|
||||||
|
if (unitLengthOffset + unitLength
|
||||||
|
> (uint64)fDebugTypesSection->Size()) {
|
||||||
|
WARNING("Invalid type unit length, offset %#" B_PRIx64 ".\n",
|
||||||
|
unitHeaderOffset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int version = dataReader.Read<uint16>(0);
|
||||||
|
off_t abbrevOffset = dwarf64
|
||||||
|
? dataReader.Read<uint64>(0)
|
||||||
|
: dataReader.Read<uint32>(0);
|
||||||
|
uint8 addressSize = dataReader.Read<uint8>(0);
|
||||||
|
|
||||||
|
if (dataReader.HasOverflow()) {
|
||||||
|
WARNING("Unexpected end of data in type unit header at %#"
|
||||||
|
B_PRIx64 ".\n", unitHeaderOffset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE_DIE("DWARF%d type unit: version %d, length: %" B_PRIu64
|
||||||
|
", abbrevOffset: %" B_PRIdOFF ", address size: %d\n",
|
||||||
|
dwarf64 ? 64 : 32, version, unitLength, abbrevOffset, addressSize);
|
||||||
|
|
||||||
|
if (version > 4) {
|
||||||
|
WARNING("\"%s\": Unsupported type unit version: %d\n",
|
||||||
|
fName, version);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addressSize != 4 && addressSize != 8) {
|
||||||
|
WARNING("\"%s\": Unsupported address size: %d\n", fName,
|
||||||
|
addressSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dataReader.SetAddressSize(addressSize);
|
||||||
|
|
||||||
|
uint64 signature = dataReader.Read<uint64>(0);
|
||||||
|
|
||||||
|
off_t typeOffset = dwarf64
|
||||||
|
? dataReader.Read<uint64>(0)
|
||||||
|
: dataReader.Read<uint32>(0);
|
||||||
|
|
||||||
|
off_t unitContentOffset = dataReader.Offset();
|
||||||
|
|
||||||
|
// create a type unit object
|
||||||
|
TypeUnit* unit = new(std::nothrow) TypeUnit(
|
||||||
|
unitHeaderOffset, unitContentOffset,
|
||||||
|
unitLength + (unitLengthOffset - unitHeaderOffset),
|
||||||
|
abbrevOffset, typeOffset, addressSize, signature, dwarf64);
|
||||||
|
if (unit == NULL) {
|
||||||
|
delete unit;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the debug info for the unit
|
||||||
|
status_t error = _ParseTypeUnit(unit);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// TODO: it should theoretically never happen that we get a duplicate,
|
||||||
|
// but it wouldn't hurt to check since that situation would potentially
|
||||||
|
// be problematic.
|
||||||
|
if (fTypeUnits.Lookup(signature) == NULL) {
|
||||||
|
TypeUnitTableEntry* entry = new(std::nothrow)
|
||||||
|
TypeUnitTableEntry(signature, unit);
|
||||||
|
if (entry == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
fTypeUnits.Insert(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
dataReader.SeekAbsolute(unitLengthOffset + unitLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
|
DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
|
||||||
{
|
{
|
||||||
@@ -952,7 +1076,7 @@ DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
|
|||||||
|
|
||||||
DebugInfoEntry* entry;
|
DebugInfoEntry* entry;
|
||||||
bool endOfEntryList;
|
bool endOfEntryList;
|
||||||
error = _ParseDebugInfoEntry(dataReader, abbreviationTable, entry,
|
error = _ParseDebugInfoEntry(dataReader, unit, abbreviationTable, entry,
|
||||||
endOfEntryList);
|
endOfEntryList);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
@@ -979,13 +1103,57 @@ DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::_ParseTypeUnit(TypeUnit* unit)
|
||||||
|
{
|
||||||
|
AbbreviationTable* abbreviationTable;
|
||||||
|
status_t error = _GetAbbreviationTable(unit->AbbreviationOffset(),
|
||||||
|
abbreviationTable);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
unit->SetAbbreviationTable(abbreviationTable);
|
||||||
|
|
||||||
|
DataReader dataReader(
|
||||||
|
(const uint8*)fDebugTypesSection->Data() + unit->ContentOffset(),
|
||||||
|
unit->ContentSize(), unit->AddressSize());
|
||||||
|
|
||||||
|
DebugInfoEntry* entry;
|
||||||
|
bool endOfEntryList;
|
||||||
|
error = _ParseDebugInfoEntry(dataReader, unit, abbreviationTable, entry,
|
||||||
|
endOfEntryList);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
DIETypeUnit* unitEntry = dynamic_cast<DIETypeUnit*>(entry);
|
||||||
|
if (unitEntry == NULL) {
|
||||||
|
WARNING("No type unit entry in .debug_types section.\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
unit->SetUnitEntry(unitEntry);
|
||||||
|
|
||||||
|
TRACE_DIE_ONLY(
|
||||||
|
TRACE_DIE("remaining bytes in unit: %" B_PRIdOFF "\n",
|
||||||
|
dataReader.BytesRemaining());
|
||||||
|
if (dataReader.HasData()) {
|
||||||
|
TRACE_DIE(" ");
|
||||||
|
while (dataReader.HasData())
|
||||||
|
TRACE_DIE("%02x", dataReader.Read<uint8>(0));
|
||||||
|
TRACE_DIE("\n");
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
|
DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
|
||||||
AbbreviationTable* abbreviationTable, DebugInfoEntry*& _entry,
|
BaseUnit* unit, AbbreviationTable* abbreviationTable,
|
||||||
bool& _endOfEntryList, int level)
|
DebugInfoEntry*& _entry, bool& _endOfEntryList, int level)
|
||||||
{
|
{
|
||||||
off_t entryOffset = dataReader.Offset()
|
off_t entryOffset = dataReader.Offset()
|
||||||
+ fCurrentCompilationUnit->RelativeContentOffset();
|
+ unit->RelativeContentOffset();
|
||||||
|
|
||||||
uint32 code = dataReader.ReadUnsignedLEB128(0);
|
uint32 code = dataReader.ReadUnsignedLEB128(0);
|
||||||
if (code == 0) {
|
if (code == 0) {
|
||||||
@@ -1001,7 +1169,7 @@ DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
|
|||||||
// get the corresponding abbreviation entry
|
// get the corresponding abbreviation entry
|
||||||
AbbreviationEntry abbreviationEntry;
|
AbbreviationEntry abbreviationEntry;
|
||||||
if (!abbreviationTable->GetAbbreviationEntry(code, abbreviationEntry)) {
|
if (!abbreviationTable->GetAbbreviationEntry(code, abbreviationEntry)) {
|
||||||
WARNING("No abbreviation entry for code %" B_PRIu32 "\n", code);
|
WARNING("No abbreviation entry for code %" B_PRIx32 "\n", code);
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1021,12 +1189,13 @@ DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
|
|||||||
abbreviationEntry.Code(), get_entry_tag_name(abbreviationEntry.Tag()),
|
abbreviationEntry.Code(), get_entry_tag_name(abbreviationEntry.Tag()),
|
||||||
abbreviationEntry.Tag(), abbreviationEntry.HasChildren());
|
abbreviationEntry.Tag(), abbreviationEntry.HasChildren());
|
||||||
|
|
||||||
error = fCurrentCompilationUnit->AddDebugInfoEntry(entry, entryOffset);
|
error = unit->AddDebugInfoEntry(entry, entryOffset);
|
||||||
|
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
// parse the attributes (supply NULL entry to avoid adding them yet)
|
// parse the attributes (supply NULL entry to avoid adding them yet)
|
||||||
error = _ParseEntryAttributes(dataReader, NULL, abbreviationEntry);
|
error = _ParseEntryAttributes(dataReader, unit, NULL, abbreviationEntry);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -1036,7 +1205,7 @@ DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
|
|||||||
DebugInfoEntry* childEntry;
|
DebugInfoEntry* childEntry;
|
||||||
bool endOfEntryList;
|
bool endOfEntryList;
|
||||||
status_t error = _ParseDebugInfoEntry(dataReader,
|
status_t error = _ParseDebugInfoEntry(dataReader,
|
||||||
abbreviationTable, childEntry, endOfEntryList, level + 1);
|
unit, abbreviationTable, childEntry, endOfEntryList, level + 1);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -1072,14 +1241,20 @@ DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfFile::_FinishCompilationUnit(CompilationUnit* unit)
|
DwarfFile::_FinishUnit(BaseUnit* unit)
|
||||||
{
|
{
|
||||||
TRACE_DIE("\nfinishing compilation unit %p\n", unit);
|
CompilationUnit* compilationUnit = dynamic_cast<CompilationUnit*>(unit);
|
||||||
|
bool isTypeUnit = compilationUnit == NULL;
|
||||||
|
TRACE_DIE("\nfinishing %s unit %p\n",
|
||||||
|
isTypeUnit ? "type" : "compilation", unit);
|
||||||
|
|
||||||
|
|
||||||
AbbreviationTable* abbreviationTable = unit->GetAbbreviationTable();
|
AbbreviationTable* abbreviationTable = unit->GetAbbreviationTable();
|
||||||
|
|
||||||
|
ElfSection* section = isTypeUnit
|
||||||
|
? fDebugTypesSection : fDebugInfoSection;
|
||||||
DataReader dataReader(
|
DataReader dataReader(
|
||||||
(const uint8*)fDebugInfoSection->Data() + unit->HeaderOffset(),
|
(const uint8*)section->Data() + unit->HeaderOffset(),
|
||||||
unit->TotalSize(), unit->AddressSize());
|
unit->TotalSize(), unit->AddressSize());
|
||||||
|
|
||||||
DebugInfoEntryInitInfo entryInitInfo;
|
DebugInfoEntryInitInfo entryInitInfo;
|
||||||
@@ -1112,7 +1287,8 @@ DwarfFile::_FinishCompilationUnit(CompilationUnit* unit)
|
|||||||
|
|
||||||
// parse the attributes -- this time pass the entry, so that the
|
// parse the attributes -- this time pass the entry, so that the
|
||||||
// attribute get set on it
|
// attribute get set on it
|
||||||
error = _ParseEntryAttributes(dataReader, entry, abbreviationEntry);
|
error = _ParseEntryAttributes(dataReader, unit, entry,
|
||||||
|
abbreviationEntry);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -1127,21 +1303,27 @@ DwarfFile::_FinishCompilationUnit(CompilationUnit* unit)
|
|||||||
// set the compilation unit's source language
|
// set the compilation unit's source language
|
||||||
unit->SetSourceLanguage(entryInitInfo.languageInfo);
|
unit->SetSourceLanguage(entryInitInfo.languageInfo);
|
||||||
|
|
||||||
|
if (isTypeUnit)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
// resolve the compilation unit's address range list
|
// resolve the compilation unit's address range list
|
||||||
if (TargetAddressRangeList* ranges = ResolveRangeList(unit,
|
if (TargetAddressRangeList* ranges = ResolveRangeList(compilationUnit,
|
||||||
unit->UnitEntry()->AddressRangesOffset())) {
|
compilationUnit->UnitEntry()->AddressRangesOffset())) {
|
||||||
unit->SetAddressRanges(ranges);
|
compilationUnit->SetAddressRanges(ranges);
|
||||||
ranges->ReleaseReference();
|
ranges->ReleaseReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
// add compilation dir to directory list
|
// add compilation dir to directory list
|
||||||
const char* compilationDir = unit->UnitEntry()->CompilationDir();
|
const char* compilationDir = compilationUnit->UnitEntry()
|
||||||
if (!unit->AddDirectory(compilationDir != NULL ? compilationDir : "."))
|
->CompilationDir();
|
||||||
|
if (!compilationUnit->AddDirectory(compilationDir != NULL
|
||||||
|
? compilationDir : ".")) {
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
// parse line info header
|
// parse line info header
|
||||||
if (fDebugLineSection != NULL)
|
if (fDebugLineSection != NULL)
|
||||||
_ParseLineInfo(unit);
|
_ParseLineInfo(compilationUnit);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -1149,7 +1331,7 @@ DwarfFile::_FinishCompilationUnit(CompilationUnit* unit)
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
||||||
DebugInfoEntry* entry, AbbreviationEntry& abbreviationEntry)
|
BaseUnit* unit, DebugInfoEntry* entry, AbbreviationEntry& abbreviationEntry)
|
||||||
{
|
{
|
||||||
uint32 attributeName;
|
uint32 attributeName;
|
||||||
uint32 attributeForm;
|
uint32 attributeForm;
|
||||||
@@ -1170,7 +1352,8 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||||||
// first.
|
// first.
|
||||||
uint64 value = 0;
|
uint64 value = 0;
|
||||||
off_t blockLength = 0;
|
off_t blockLength = 0;
|
||||||
bool localReference = true;
|
off_t valueOffset = dataReader.Offset() + unit->ContentOffset();
|
||||||
|
uint8 refType = dwarf_reference_type_local;
|
||||||
|
|
||||||
switch (attributeForm) {
|
switch (attributeForm) {
|
||||||
case DW_FORM_addr:
|
case DW_FORM_addr:
|
||||||
@@ -1213,7 +1396,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||||||
case DW_FORM_strp:
|
case DW_FORM_strp:
|
||||||
{
|
{
|
||||||
if (fDebugStringSection != NULL) {
|
if (fDebugStringSection != NULL) {
|
||||||
off_t offset = fCurrentCompilationUnit->IsDwarf64()
|
off_t offset = unit->IsDwarf64()
|
||||||
? (off_t)dataReader.Read<uint64>(0)
|
? (off_t)dataReader.Read<uint64>(0)
|
||||||
: (off_t)dataReader.Read<uint32>(0);
|
: (off_t)dataReader.Read<uint32>(0);
|
||||||
if (offset >= fDebugStringSection->Size()) {
|
if (offset >= fDebugStringSection->Size()) {
|
||||||
@@ -1233,10 +1416,10 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||||||
value = dataReader.ReadUnsignedLEB128(0);
|
value = dataReader.ReadUnsignedLEB128(0);
|
||||||
break;
|
break;
|
||||||
case DW_FORM_ref_addr:
|
case DW_FORM_ref_addr:
|
||||||
value = fCurrentCompilationUnit->IsDwarf64()
|
value = unit->IsDwarf64()
|
||||||
? dataReader.Read<uint64>(0)
|
? dataReader.Read<uint64>(0)
|
||||||
: (uint64)dataReader.Read<uint32>(0);
|
: (uint64)dataReader.Read<uint32>(0);
|
||||||
localReference = false;
|
refType = dwarf_reference_type_global;
|
||||||
break;
|
break;
|
||||||
case DW_FORM_ref1:
|
case DW_FORM_ref1:
|
||||||
value = dataReader.Read<uint8>(0);
|
value = dataReader.Read<uint8>(0);
|
||||||
@@ -1260,10 +1443,12 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||||||
attributeValue.SetToFlag(true);
|
attributeValue.SetToFlag(true);
|
||||||
break;
|
break;
|
||||||
case DW_FORM_ref_sig8:
|
case DW_FORM_ref_sig8:
|
||||||
|
fTypesSectionRequired = true;
|
||||||
value = dataReader.Read<uint64>(0);
|
value = dataReader.Read<uint64>(0);
|
||||||
|
refType = dwarf_reference_type_signature;
|
||||||
break;
|
break;
|
||||||
case DW_FORM_sec_offset:
|
case DW_FORM_sec_offset:
|
||||||
value = fCurrentCompilationUnit->IsDwarf64()
|
value = unit->IsDwarf64()
|
||||||
? dataReader.Read<uint64>(0)
|
? dataReader.Read<uint64>(0)
|
||||||
: (uint64)dataReader.Read<uint32>(0);
|
: (uint64)dataReader.Read<uint32>(0);
|
||||||
break;
|
break;
|
||||||
@@ -1278,14 +1463,13 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||||||
// it
|
// it
|
||||||
uint8 attributeClass = get_attribute_class(attributeName,
|
uint8 attributeClass = get_attribute_class(attributeName,
|
||||||
attributeForm);
|
attributeForm);
|
||||||
|
|
||||||
if (attributeClass == ATTRIBUTE_CLASS_UNKNOWN) {
|
if (attributeClass == ATTRIBUTE_CLASS_UNKNOWN) {
|
||||||
TRACE_DIE("skipping attribute with unrecognized class: %s (%#"
|
TRACE_DIE("skipping attribute with unrecognized class: %s (%#"
|
||||||
B_PRIx32 ") %s (%#" B_PRIx32 ")\n",
|
B_PRIx32 ") %s (%#" B_PRIx32 ")\n",
|
||||||
get_attribute_name_name(attributeName), attributeName,
|
get_attribute_name_name(attributeName), attributeName,
|
||||||
get_attribute_form_name(attributeForm), attributeForm);
|
get_attribute_form_name(attributeForm), attributeForm);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
// attributeValue.attributeClass = attributeClass;
|
|
||||||
|
|
||||||
// set the attribute value according to the attribute's class
|
// set the attribute value according to the attribute's class
|
||||||
switch (attributeClass) {
|
switch (attributeClass) {
|
||||||
@@ -1314,7 +1498,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||||||
case ATTRIBUTE_CLASS_REFERENCE:
|
case ATTRIBUTE_CLASS_REFERENCE:
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
attributeValue.SetToReference(_ResolveReference(
|
attributeValue.SetToReference(_ResolveReference(
|
||||||
fCurrentCompilationUnit, value, localReference));
|
unit, value, refType));
|
||||||
if (attributeValue.reference == NULL) {
|
if (attributeValue.reference == NULL) {
|
||||||
// gcc 2 apparently somtimes produces DW_AT_sibling
|
// gcc 2 apparently somtimes produces DW_AT_sibling
|
||||||
// attributes pointing to the end of the sibling list.
|
// attributes pointing to the end of the sibling list.
|
||||||
@@ -1322,8 +1506,11 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||||||
if (attributeName == DW_AT_sibling)
|
if (attributeName == DW_AT_sibling)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
WARNING("Failed to resolve reference: %s (%#" B_PRIx32
|
WARNING("Failed to resolve reference on entry %p: "
|
||||||
") %s (%#" B_PRIx32 "): value: %" B_PRIu64 "\n",
|
"(%#" B_PRIx64 ") %s (%#" B_PRIx32 ") %s "
|
||||||
|
"(%#" B_PRIx32 "): value: %#" B_PRIx64 "\n",
|
||||||
|
entry,
|
||||||
|
valueOffset,
|
||||||
get_attribute_name_name(attributeName),
|
get_attribute_name_name(attributeName),
|
||||||
attributeName,
|
attributeName,
|
||||||
get_attribute_form_name(attributeForm),
|
get_attribute_form_name(attributeForm),
|
||||||
@@ -1337,6 +1524,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||||||
// already set
|
// already set
|
||||||
break;
|
break;
|
||||||
case ATTRIBUTE_CLASS_EXPRESSION:
|
case ATTRIBUTE_CLASS_EXPRESSION:
|
||||||
|
WARNING("Skipping unhandled attribute class expression.\n");
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
dataReader.Skip(value);
|
dataReader.Skip(value);
|
||||||
break;
|
break;
|
||||||
@@ -1347,16 +1535,17 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRACE_DIE_ONLY(
|
||||||
|
char buffer[1024];
|
||||||
|
TRACE_DIE(" attr (%#" B_PRIx64 ") %s %s (%d): %s\n",
|
||||||
|
valueOffset,
|
||||||
|
get_attribute_name_name(attributeName),
|
||||||
|
get_attribute_form_name(attributeForm), attributeClass,
|
||||||
|
attributeValue.ToString(buffer, sizeof(buffer)));
|
||||||
|
)
|
||||||
|
|
||||||
// add the attribute
|
// add the attribute
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
TRACE_DIE_ONLY(
|
|
||||||
char buffer[1024];
|
|
||||||
TRACE_DIE(" attr %s %s (%d): %s\n",
|
|
||||||
get_attribute_name_name(attributeName),
|
|
||||||
get_attribute_form_name(attributeForm), attributeClass,
|
|
||||||
attributeValue.ToString(buffer, sizeof(buffer)));
|
|
||||||
)
|
|
||||||
|
|
||||||
DebugInfoEntrySetter attributeSetter
|
DebugInfoEntrySetter attributeSetter
|
||||||
= get_attribute_name_setter(attributeName);
|
= get_attribute_name_setter(attributeName);
|
||||||
if (attributeSetter != 0) {
|
if (attributeSetter != 0) {
|
||||||
@@ -2378,13 +2567,27 @@ DwarfFile::_GetAbbreviationTable(off_t offset, AbbreviationTable*& _table)
|
|||||||
|
|
||||||
|
|
||||||
DebugInfoEntry*
|
DebugInfoEntry*
|
||||||
DwarfFile::_ResolveReference(CompilationUnit* unit, uint64 offset,
|
DwarfFile::_ResolveReference(BaseUnit* unit, uint64 offset,
|
||||||
bool localReference) const
|
uint8 refType) const
|
||||||
{
|
{
|
||||||
if (localReference)
|
switch (refType) {
|
||||||
return unit->EntryForOffset(offset);
|
case dwarf_reference_type_local:
|
||||||
|
return unit->EntryForOffset(offset);
|
||||||
|
break;
|
||||||
|
case dwarf_reference_type_global:
|
||||||
|
{
|
||||||
|
WARNING("DwarfFile: Unhandled global reference\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case dwarf_reference_type_signature:
|
||||||
|
{
|
||||||
|
TypeUnitTableEntry* entry = fTypeUnits.Lookup(offset);
|
||||||
|
if (entry != NULL && entry->unit != NULL)
|
||||||
|
return entry->unit->TypeEntry();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Implement program-global references!
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2524,7 +2727,8 @@ DwarfFile::_LocateDebugInfo()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfFile::_GetDebugInfoPath(const char* debugFileName, BString& _infoPath)
|
DwarfFile::_GetDebugInfoPath(const char* debugFileName,
|
||||||
|
BString& _infoPath) const
|
||||||
{
|
{
|
||||||
const directory_which dirLocations[] = { B_USER_CONFIG_DIRECTORY,
|
const directory_which dirLocations[] = { B_USER_CONFIG_DIRECTORY,
|
||||||
B_COMMON_DIRECTORY, B_SYSTEM_DIRECTORY };
|
B_COMMON_DIRECTORY, B_SYSTEM_DIRECTORY };
|
||||||
@@ -2571,3 +2775,10 @@ DwarfFile::_GetDebugInfoPath(const char* debugFileName, BString& _infoPath)
|
|||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TypeUnitTableEntry*
|
||||||
|
DwarfFile::_GetTypeUnit(uint64 signature) const
|
||||||
|
{
|
||||||
|
return fTypeUnits.Lookup(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,10 @@
|
|||||||
#include <ObjectList.h>
|
#include <ObjectList.h>
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
#include "DebugInfoEntries.h"
|
#include "DebugInfoEntries.h"
|
||||||
|
#include "TypeUnit.h"
|
||||||
|
|
||||||
|
|
||||||
class AbbreviationEntry;
|
class AbbreviationEntry;
|
||||||
@@ -107,15 +109,21 @@ private:
|
|||||||
|
|
||||||
typedef DoublyLinkedList<AbbreviationTable> AbbreviationTableList;
|
typedef DoublyLinkedList<AbbreviationTable> AbbreviationTableList;
|
||||||
typedef BObjectList<CompilationUnit> CompilationUnitList;
|
typedef BObjectList<CompilationUnit> CompilationUnitList;
|
||||||
|
typedef BOpenHashTable<TypeUnitTableHashDefinition> TypeUnitTable;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
status_t _ParseDebugInfoSection();
|
||||||
|
status_t _ParseTypesSection();
|
||||||
status_t _ParseCompilationUnit(CompilationUnit* unit);
|
status_t _ParseCompilationUnit(CompilationUnit* unit);
|
||||||
|
status_t _ParseTypeUnit(TypeUnit* unit);
|
||||||
status_t _ParseDebugInfoEntry(DataReader& dataReader,
|
status_t _ParseDebugInfoEntry(DataReader& dataReader,
|
||||||
|
BaseUnit* unit,
|
||||||
AbbreviationTable* abbreviationTable,
|
AbbreviationTable* abbreviationTable,
|
||||||
DebugInfoEntry*& _entry,
|
DebugInfoEntry*& _entry,
|
||||||
bool& _endOfEntryList, int level = 0);
|
bool& _endOfEntryList, int level = 0);
|
||||||
status_t _FinishCompilationUnit(CompilationUnit* unit);
|
status_t _FinishUnit(BaseUnit* unit);
|
||||||
status_t _ParseEntryAttributes(DataReader& dataReader,
|
status_t _ParseEntryAttributes(DataReader& dataReader,
|
||||||
|
BaseUnit* unit,
|
||||||
DebugInfoEntry* entry,
|
DebugInfoEntry* entry,
|
||||||
AbbreviationEntry& abbreviationEntry);
|
AbbreviationEntry& abbreviationEntry);
|
||||||
|
|
||||||
@@ -150,8 +158,9 @@ private:
|
|||||||
status_t _GetAbbreviationTable(off_t offset,
|
status_t _GetAbbreviationTable(off_t offset,
|
||||||
AbbreviationTable*& _table);
|
AbbreviationTable*& _table);
|
||||||
|
|
||||||
DebugInfoEntry* _ResolveReference(CompilationUnit* unit,
|
DebugInfoEntry* _ResolveReference(BaseUnit* unit,
|
||||||
uint64 offset, bool localReference) const;
|
uint64 offset,
|
||||||
|
uint8 refType) const;
|
||||||
|
|
||||||
status_t _GetLocationExpression(CompilationUnit* unit,
|
status_t _GetLocationExpression(CompilationUnit* unit,
|
||||||
const LocationDescription* location,
|
const LocationDescription* location,
|
||||||
@@ -165,7 +174,9 @@ private:
|
|||||||
|
|
||||||
status_t _LocateDebugInfo();
|
status_t _LocateDebugInfo();
|
||||||
status_t _GetDebugInfoPath(const char* fileName,
|
status_t _GetDebugInfoPath(const char* fileName,
|
||||||
BString& _infoPath);
|
BString& _infoPath) const;
|
||||||
|
|
||||||
|
TypeUnitTableEntry* _GetTypeUnit(uint64 signature) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class DwarfFile::ExpressionEvaluationContext;
|
friend class DwarfFile::ExpressionEvaluationContext;
|
||||||
@@ -184,10 +195,12 @@ private:
|
|||||||
ElfSection* fEHFrameSection;
|
ElfSection* fEHFrameSection;
|
||||||
ElfSection* fDebugLocationSection;
|
ElfSection* fDebugLocationSection;
|
||||||
ElfSection* fDebugPublicTypesSection;
|
ElfSection* fDebugPublicTypesSection;
|
||||||
|
ElfSection* fDebugTypesSection;
|
||||||
AbbreviationTableList fAbbreviationTables;
|
AbbreviationTableList fAbbreviationTables;
|
||||||
DebugInfoEntryFactory fDebugInfoFactory;
|
DebugInfoEntryFactory fDebugInfoFactory;
|
||||||
CompilationUnitList fCompilationUnits;
|
CompilationUnitList fCompilationUnits;
|
||||||
CompilationUnit* fCurrentCompilationUnit;
|
TypeUnitTable fTypeUnits;
|
||||||
|
bool fTypesSectionRequired;
|
||||||
bool fFinished;
|
bool fFinished;
|
||||||
status_t fFinishError;
|
status_t fFinishError;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user