Google Breakpad DWARF reader: Add a handler function for DIE references.
Add a new member function to dwarf2reader::Dwarf2Handler, ProcessAttributeReference, for reporting attribute values that are references to other DIEs. This handler member function always receives an absolute offset (that is, relative to the start of the .debug_info section, not to the start of the compilation unit), regardless of the form the attribute uses. (Some forms are CU-relative, some are absolute.) a=jimblandy, r=nealsid git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@482 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
0441036f9e
commit
330ca2f7c7
4 changed files with 70 additions and 31 deletions
|
@ -331,24 +331,20 @@ const char* CompilationUnit::ProcessAttribute(
|
|||
|
||||
case DW_FORM_data1:
|
||||
case DW_FORM_flag:
|
||||
case DW_FORM_ref1:
|
||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadOneByte(start));
|
||||
return start + 1;
|
||||
break;
|
||||
case DW_FORM_ref2:
|
||||
case DW_FORM_data2:
|
||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadTwoBytes(start));
|
||||
return start + 2;
|
||||
break;
|
||||
case DW_FORM_ref4:
|
||||
case DW_FORM_data4:
|
||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadFourBytes(start));
|
||||
return start + 4;
|
||||
break;
|
||||
case DW_FORM_ref8:
|
||||
case DW_FORM_data8:
|
||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadEightBytes(start));
|
||||
|
@ -362,7 +358,6 @@ const char* CompilationUnit::ProcessAttribute(
|
|||
}
|
||||
break;
|
||||
case DW_FORM_udata:
|
||||
case DW_FORM_ref_udata:
|
||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadUnsignedLEB128(start,
|
||||
&len));
|
||||
|
@ -379,17 +374,49 @@ const char* CompilationUnit::ProcessAttribute(
|
|||
reader_->ReadAddress(start));
|
||||
return start + reader_->AddressSize();
|
||||
break;
|
||||
|
||||
case DW_FORM_ref1:
|
||||
handler_->ProcessAttributeReference(dieoffset, attr, form,
|
||||
reader_->ReadOneByte(start)
|
||||
+ offset_from_section_start_);
|
||||
return start + 1;
|
||||
break;
|
||||
case DW_FORM_ref2:
|
||||
handler_->ProcessAttributeReference(dieoffset, attr, form,
|
||||
reader_->ReadTwoBytes(start)
|
||||
+ offset_from_section_start_);
|
||||
return start + 2;
|
||||
break;
|
||||
case DW_FORM_ref4:
|
||||
handler_->ProcessAttributeReference(dieoffset, attr, form,
|
||||
reader_->ReadFourBytes(start)
|
||||
+ offset_from_section_start_);
|
||||
return start + 4;
|
||||
break;
|
||||
case DW_FORM_ref8:
|
||||
handler_->ProcessAttributeReference(dieoffset, attr, form,
|
||||
reader_->ReadEightBytes(start)
|
||||
+ offset_from_section_start_);
|
||||
return start + 8;
|
||||
break;
|
||||
case DW_FORM_ref_udata:
|
||||
handler_->ProcessAttributeReference(dieoffset, attr, form,
|
||||
reader_->ReadUnsignedLEB128(start,
|
||||
&len)
|
||||
+ offset_from_section_start_);
|
||||
return start + len;
|
||||
break;
|
||||
case DW_FORM_ref_addr:
|
||||
// DWARF2 and 3 differ on whether ref_addr is address size or
|
||||
// offset size.
|
||||
assert(header_.version == 2 || header_.version == 3);
|
||||
if (header_.version == 2) {
|
||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadAddress(start));
|
||||
handler_->ProcessAttributeReference(dieoffset, attr, form,
|
||||
reader_->ReadAddress(start));
|
||||
return start + reader_->AddressSize();
|
||||
} else if (header_.version == 3) {
|
||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadOffset(start));
|
||||
handler_->ProcessAttributeReference(dieoffset, attr, form,
|
||||
reader_->ReadOffset(start));
|
||||
return start + reader_->OffsetSize();
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -358,6 +358,16 @@ class Dwarf2Handler {
|
|||
enum DwarfForm form,
|
||||
int64 data) { }
|
||||
|
||||
// Called when we have an attribute whose value is a reference to
|
||||
// another DIE. The attribute belongs to the DIE at OFFSET from the
|
||||
// beginning of the .debug_info section. Its name is ATTR, its form
|
||||
// is FORM, and the offset of the DIE being referred to from the
|
||||
// beginning of the .debug_info section is DATA.
|
||||
virtual void ProcessAttributeReference(uint64 offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
uint64 data) { }
|
||||
|
||||
// Called when we have an attribute with a buffer of data to give to our
|
||||
// handler. The attribute is for the DIE at OFFSET from the beginning of the
|
||||
// .debug_info section. Its name is ATTR, its form is FORM, DATA points to
|
||||
|
|
|
@ -42,25 +42,6 @@
|
|||
|
||||
namespace dwarf2reader {
|
||||
|
||||
// Given an offset value, its form, and the base offset of the
|
||||
// compilation unit containing this value, return an absolute offset
|
||||
// within the .debug_info section.
|
||||
uint64 GetAbsoluteOffset(uint64 offset,
|
||||
enum DwarfForm form,
|
||||
uint64 compilation_unit_base) {
|
||||
switch (form) {
|
||||
case DW_FORM_ref1:
|
||||
case DW_FORM_ref2:
|
||||
case DW_FORM_ref4:
|
||||
case DW_FORM_ref8:
|
||||
case DW_FORM_ref_udata:
|
||||
return offset + compilation_unit_base;
|
||||
case DW_FORM_ref_addr:
|
||||
default:
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
|
||||
CULineInfoHandler::CULineInfoHandler(vector<SourceFileInfo>* files,
|
||||
vector<string>* dirs,
|
||||
LineMap* linemap):linemap_(linemap),
|
||||
|
@ -198,6 +179,18 @@ void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset,
|
|||
case DW_AT_decl_file:
|
||||
current_function_info_->file = files_->at(data).name;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CUFunctionInfoHandler::ProcessAttributeReference(uint64 offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
uint64 data) {
|
||||
if (current_function_info_) {
|
||||
switch (attr) {
|
||||
case DW_AT_specification: {
|
||||
// Some functions have a "specification" attribute
|
||||
// which means they were defined elsewhere. The name
|
||||
|
@ -205,14 +198,13 @@ void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset,
|
|||
// the specification DIE. Here we'll assume that
|
||||
// any DIE referenced in this manner will already have
|
||||
// been seen, but that's not really required by the spec.
|
||||
uint64 abs_offset = GetAbsoluteOffset(data, form, current_compilation_unit_offset_);
|
||||
FunctionMap::iterator iter = offset_to_funcinfo_->find(abs_offset);
|
||||
FunctionMap::iterator iter = offset_to_funcinfo_->find(data);
|
||||
if (iter != offset_to_funcinfo_->end()) {
|
||||
current_function_info_->name = iter->second->name;
|
||||
current_function_info_->mangled_name = iter->second->mangled_name;
|
||||
} else {
|
||||
// If you hit this, this code probably needs to be rewritten.
|
||||
fprintf(stderr, "Error: DW_AT_specification was seen before the referenced DIE! (Looking for DIE at offset %08llx, in DIE at offset %08llx)\n", abs_offset, offset);
|
||||
fprintf(stderr, "Error: DW_AT_specification was seen before the referenced DIE! (Looking for DIE at offset %08llx, in DIE at offset %08llx)\n", data, offset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -146,6 +146,16 @@ class CUFunctionInfoHandler: public Dwarf2Handler {
|
|||
enum DwarfForm form,
|
||||
uint64 data);
|
||||
|
||||
// Called when we have an attribute with a DIE reference to give to
|
||||
// our handler. The attribute is for the DIE at OFFSET from the
|
||||
// beginning of the .debug_info section, has a name of ATTR, a form of
|
||||
// FORM, and the offset of the referenced DIE from the start of the
|
||||
// .debug_info section is in DATA.
|
||||
virtual void ProcessAttributeReference(uint64 offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
uint64 data);
|
||||
|
||||
// Called when we have an attribute with string data to give to
|
||||
// our handler. The attribute is for the DIE at OFFSET from the
|
||||
// beginning of the .debug_info section, has a name of ATTR, a form of
|
||||
|
|
Loading…
Reference in a new issue