From 330ca2f7c71d84a01626b1198ef600540eb320b8 Mon Sep 17 00:00:00 2001 From: jimblandy Date: Tue, 12 Jan 2010 16:53:02 +0000 Subject: [PATCH] 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 --- src/common/dwarf/dwarf2reader.cc | 45 +++++++++++++++++++++++++------- src/common/dwarf/dwarf2reader.h | 10 +++++++ src/common/dwarf/functioninfo.cc | 36 ++++++++++--------------- src/common/dwarf/functioninfo.h | 10 +++++++ 4 files changed, 70 insertions(+), 31 deletions(-) diff --git a/src/common/dwarf/dwarf2reader.cc b/src/common/dwarf/dwarf2reader.cc index 2580606f..77c318fa 100644 --- a/src/common/dwarf/dwarf2reader.cc +++ b/src/common/dwarf/dwarf2reader.cc @@ -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; diff --git a/src/common/dwarf/dwarf2reader.h b/src/common/dwarf/dwarf2reader.h index f7d379e9..57667563 100644 --- a/src/common/dwarf/dwarf2reader.h +++ b/src/common/dwarf/dwarf2reader.h @@ -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 diff --git a/src/common/dwarf/functioninfo.cc b/src/common/dwarf/functioninfo.cc index 1957153e..09aa01fd 100644 --- a/src/common/dwarf/functioninfo.cc +++ b/src/common/dwarf/functioninfo.cc @@ -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* files, vector* 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; } diff --git a/src/common/dwarf/functioninfo.h b/src/common/dwarf/functioninfo.h index 740f1463..3351c67c 100644 --- a/src/common/dwarf/functioninfo.h +++ b/src/common/dwarf/functioninfo.h @@ -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