Compare commits
10 Commits
main
...
linux-dwar
Author | SHA1 | Date | |
---|---|---|---|
|
01ca4892d8 | ||
|
11fbf26119 | ||
|
548c407f4b | ||
|
52af30d80c | ||
|
3d9c2ce401 | ||
|
06a8c78818 | ||
|
0f3b2d75d9 | ||
|
e1e8be4cae | ||
|
8583d8ee76 | ||
|
64892f177d |
@ -133,9 +133,9 @@
|
||||
F9721F380E8B0CFC00D7E813 /* dump_syms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dump_syms.h; path = ../../../common/mac/dump_syms.h; sourceTree = SOURCE_ROOT; };
|
||||
F9721F390E8B0D0D00D7E813 /* dump_syms.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = dump_syms.mm; path = ../../../common/mac/dump_syms.mm; sourceTree = SOURCE_ROOT; };
|
||||
F9721F6B0E8B0D7000D7E813 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
|
||||
F9721F760E8B0DC700D7E813 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/mac/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
|
||||
F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/mac/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
|
||||
F9721F780E8B0DC700D7E813 /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/mac/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
|
||||
F9721F760E8B0DC700D7E813 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
|
||||
F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
|
||||
F9721F780E8B0DC700D7E813 /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
|
||||
F9721FA10E8B0E2300D7E813 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = /System/Library/Frameworks/SenTestingKit.framework; sourceTree = "<absolute>"; };
|
||||
F9721FA80E8B0E4800D7E813 /* md5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = md5.c; path = ../../../common/md5.c; sourceTree = SOURCE_ROOT; };
|
||||
F982089A0DB3280D0017AECA /* breakpad_nlist_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_nlist_test.h; sourceTree = "<group>"; };
|
||||
|
@ -29,7 +29,9 @@
|
||||
#ifndef UTIL_DEBUGINFO_BYTEREADER_INL_H__
|
||||
#define UTIL_DEBUGINFO_BYTEREADER_INL_H__
|
||||
|
||||
#include "common/mac/dwarf/bytereader.h"
|
||||
#include <cassert>
|
||||
|
||||
#include "common/dwarf/bytereader.h"
|
||||
|
||||
namespace dwarf2reader {
|
||||
|
||||
@ -37,9 +39,11 @@ inline uint8 ByteReader::ReadOneByte(const char* buffer) const {
|
||||
return buffer[0];
|
||||
}
|
||||
|
||||
inline uint16 ByteReader::ReadTwoBytes(const char* buffer) const {
|
||||
const uint16 buffer0 = static_cast<uint16>(buffer[0]);
|
||||
const uint16 buffer1 = static_cast<uint16>(buffer[1]);
|
||||
inline uint16 ByteReader::ReadTwoBytes(const char* signed_buffer) const {
|
||||
const unsigned char *buffer
|
||||
= reinterpret_cast<const unsigned char *>(signed_buffer);
|
||||
const uint16 buffer0 = buffer[0];
|
||||
const uint16 buffer1 = buffer[1];
|
||||
if (endian_ == ENDIANNESS_LITTLE) {
|
||||
return buffer0 | buffer1 << 8;
|
||||
} else {
|
||||
@ -47,11 +51,13 @@ inline uint16 ByteReader::ReadTwoBytes(const char* buffer) const {
|
||||
}
|
||||
}
|
||||
|
||||
inline uint64 ByteReader::ReadFourBytes(const char* buffer) const {
|
||||
const uint32 buffer0 = static_cast<uint32>(buffer[0]);
|
||||
const uint32 buffer1 = static_cast<uint32>(buffer[1]);
|
||||
const uint32 buffer2 = static_cast<uint32>(buffer[2]);
|
||||
const uint32 buffer3 = static_cast<uint32>(buffer[3]);
|
||||
inline uint64 ByteReader::ReadFourBytes(const char* signed_buffer) const {
|
||||
const unsigned char *buffer
|
||||
= reinterpret_cast<const unsigned char *>(signed_buffer);
|
||||
const uint32 buffer0 = buffer[0];
|
||||
const uint32 buffer1 = buffer[1];
|
||||
const uint32 buffer2 = buffer[2];
|
||||
const uint32 buffer3 = buffer[3];
|
||||
if (endian_ == ENDIANNESS_LITTLE) {
|
||||
return buffer0 | buffer1 << 8 | buffer2 << 16 | buffer3 << 24;
|
||||
} else {
|
||||
@ -59,15 +65,17 @@ inline uint64 ByteReader::ReadFourBytes(const char* buffer) const {
|
||||
}
|
||||
}
|
||||
|
||||
inline uint64 ByteReader::ReadEightBytes(const char* buffer) const {
|
||||
const uint64 buffer0 = static_cast<uint64>(buffer[0]);
|
||||
const uint64 buffer1 = static_cast<uint64>(buffer[1]);
|
||||
const uint64 buffer2 = static_cast<uint64>(buffer[2]);
|
||||
const uint64 buffer3 = static_cast<uint64>(buffer[3]);
|
||||
const uint64 buffer4 = static_cast<uint64>(buffer[4]);
|
||||
const uint64 buffer5 = static_cast<uint64>(buffer[5]);
|
||||
const uint64 buffer6 = static_cast<uint64>(buffer[6]);
|
||||
const uint64 buffer7 = static_cast<uint64>(buffer[7]);
|
||||
inline uint64 ByteReader::ReadEightBytes(const char* signed_buffer) const {
|
||||
const unsigned char *buffer
|
||||
= reinterpret_cast<const unsigned char *>(signed_buffer);
|
||||
const uint64 buffer0 = buffer[0];
|
||||
const uint64 buffer1 = buffer[1];
|
||||
const uint64 buffer2 = buffer[2];
|
||||
const uint64 buffer3 = buffer[3];
|
||||
const uint64 buffer4 = buffer[4];
|
||||
const uint64 buffer5 = buffer[5];
|
||||
const uint64 buffer6 = buffer[6];
|
||||
const uint64 buffer7 = buffer[7];
|
||||
if (endian_ == ENDIANNESS_LITTLE) {
|
||||
return buffer0 | buffer1 << 8 | buffer2 << 16 | buffer3 << 24 |
|
||||
buffer4 << 32 | buffer5 << 40 | buffer6 << 48 | buffer7 << 56;
|
@ -26,9 +26,9 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "common/mac/dwarf/bytereader-inl.h"
|
||||
#include "common/dwarf/bytereader-inl.h"
|
||||
|
||||
#include "common/mac/dwarf/bytereader.h"
|
||||
#include "common/dwarf/bytereader.h"
|
||||
|
||||
namespace dwarf2reader {
|
||||
|
@ -26,11 +26,11 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef COMMON_MAC_DWARF_BYTEREADER_H__
|
||||
#define COMMON_MAC_DWARF_BYTEREADER_H__
|
||||
#ifndef COMMON_DWARF_BYTEREADER_H__
|
||||
#define COMMON_DWARF_BYTEREADER_H__
|
||||
|
||||
#include <string>
|
||||
#include "common/mac/dwarf/types.h"
|
||||
#include "common/dwarf/types.h"
|
||||
|
||||
namespace dwarf2reader {
|
||||
|
||||
@ -129,4 +129,4 @@ class ByteReader {
|
||||
|
||||
} // namespace dwarf2reader
|
||||
|
||||
#endif // COMMON_MAC_DWARF_BYTEREADER_H__
|
||||
#endif // COMMON_DWARF_BYTEREADER_H__
|
171
src/common/dwarf/dwarf2diehandler.cc
Normal file
171
src/common/dwarf/dwarf2diehandler.cc
Normal file
@ -0,0 +1,171 @@
|
||||
// Copyright 2009 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Implementation of dwarf2reader::DieDispatcher class.
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "common/dwarf/dwarf2diehandler.h"
|
||||
|
||||
namespace dwarf2reader {
|
||||
|
||||
DIEDispatcher::~DIEDispatcher() {
|
||||
while (! die_handlers_.empty()) {
|
||||
HandlerStack &entry = die_handlers_.top();
|
||||
if (entry.handler_ != root_handler_)
|
||||
delete entry.handler_;
|
||||
die_handlers_.pop();
|
||||
}
|
||||
}
|
||||
|
||||
bool DIEDispatcher::StartCompilationUnit(uint64 offset, uint8 address_size,
|
||||
uint8 offset_size, uint64 cu_length,
|
||||
uint8 dwarf_version) {
|
||||
return root_handler_->StartCompilationUnit(offset, address_size,
|
||||
offset_size, cu_length,
|
||||
dwarf_version);
|
||||
}
|
||||
|
||||
bool DIEDispatcher::StartDIE(uint64 offset, enum DwarfTag tag,
|
||||
const AttributeList& attrs) {
|
||||
// The stack entry for the parent of this DIE, if there is one.
|
||||
HandlerStack *parent = die_handlers_.empty() ? NULL : &die_handlers_.top();
|
||||
|
||||
// Does this call indicate that we're done receiving the parent's
|
||||
// attributes' values? If so, call its EndAttributes member function.
|
||||
if (parent && parent->handler_ && ! parent->reported_attributes_end_) {
|
||||
parent->reported_attributes_end_ = true;
|
||||
if (! parent->handler_->EndAttributes()) {
|
||||
// Finish off this handler now. and edit *PARENT to indicate that
|
||||
// we don't want to visit any of the children.
|
||||
parent->handler_->Finish();
|
||||
if (parent->handler_ != root_handler_) delete parent->handler_;
|
||||
parent->handler_ = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Find a handler for this DIE.
|
||||
DIEHandler *handler;
|
||||
if (parent) {
|
||||
if (parent->handler_)
|
||||
// Ask the parent to find a handler.
|
||||
handler = parent->handler_->FindChildHandler(offset, tag, attrs);
|
||||
else
|
||||
// No parent handler means we're not interested in any of our
|
||||
// children.
|
||||
handler = NULL;
|
||||
} else {
|
||||
// This is the root DIE. For a non-root DIE, the parent's handler
|
||||
// decides whether to visit it, but the root DIE has no parent
|
||||
// handler, so we have a special method on the root DIE handler
|
||||
// itself to decide.
|
||||
if (root_handler_->StartRootDIE(offset, tag, attrs))
|
||||
handler = root_handler_;
|
||||
else
|
||||
handler = NULL;
|
||||
}
|
||||
|
||||
// Push a handler stack entry for this new handler. As an
|
||||
// optimization, we don't push NULL-handler entries on top of other
|
||||
// NULL-handler entries; we just let the oldest such entry stand for
|
||||
// the whole subtree.
|
||||
if (handler || (parent && parent->handler_)) {
|
||||
HandlerStack entry;
|
||||
entry.offset_ = offset;
|
||||
entry.handler_ = handler;
|
||||
entry.reported_attributes_end_ = false;
|
||||
die_handlers_.push(entry);
|
||||
}
|
||||
|
||||
return handler != NULL;
|
||||
}
|
||||
|
||||
void DIEDispatcher::EndDIE(uint64 offset) {
|
||||
assert(! die_handlers_.empty());
|
||||
HandlerStack *entry = &die_handlers_.top();
|
||||
if (entry->handler_) {
|
||||
// This entry had better be the handler for this DIE.
|
||||
assert(entry->offset_ == offset);
|
||||
// If a DIE has no children, this EndDIE call indicates that we're
|
||||
// done receiving its attributes' values.
|
||||
if (! entry->reported_attributes_end_)
|
||||
entry->handler_->EndAttributes(); // Ignore return value: no children.
|
||||
entry->handler_->Finish();
|
||||
if (entry->handler_ != root_handler_) delete entry->handler_;
|
||||
} else {
|
||||
// If this DIE is within a tree we're ignoring, then don't pop the
|
||||
// handler stack: that entry stands for the whole tree.
|
||||
if (entry->offset_ != offset)
|
||||
return;
|
||||
}
|
||||
die_handlers_.pop();
|
||||
}
|
||||
|
||||
void DIEDispatcher::ProcessAttributeUnsigned(uint64 offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
uint64 data) {
|
||||
HandlerStack ¤t = die_handlers_.top();
|
||||
// This had better be an attribute of the DIE we were meant to handle.
|
||||
assert(offset == current.offset_);
|
||||
current.handler_->ProcessAttributeUnsigned(attr, form, data);
|
||||
}
|
||||
|
||||
void DIEDispatcher::ProcessAttributeSigned(uint64 offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
int64 data) {
|
||||
HandlerStack ¤t = die_handlers_.top();
|
||||
// This had better be an attribute of the DIE we were meant to handle.
|
||||
assert(offset == current.offset_);
|
||||
current.handler_->ProcessAttributeSigned(attr, form, data);
|
||||
}
|
||||
|
||||
void DIEDispatcher::ProcessAttributeBuffer(uint64 offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
const char* data,
|
||||
uint64 len) {
|
||||
HandlerStack ¤t = die_handlers_.top();
|
||||
// This had better be an attribute of the DIE we were meant to handle.
|
||||
assert(offset == current.offset_);
|
||||
current.handler_->ProcessAttributeBuffer(attr, form, data, len);
|
||||
}
|
||||
|
||||
void DIEDispatcher::ProcessAttributeString(uint64 offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
const string& data) {
|
||||
HandlerStack ¤t = die_handlers_.top();
|
||||
// This had better be an attribute of the DIE we were meant to handle.
|
||||
assert(offset == current.offset_);
|
||||
current.handler_->ProcessAttributeString(attr, form, data);
|
||||
}
|
||||
|
||||
} // namespace dwarf2reader
|
323
src/common/dwarf/dwarf2diehandler.h
Normal file
323
src/common/dwarf/dwarf2diehandler.h
Normal file
@ -0,0 +1,323 @@
|
||||
// Copyright 2009 Google Inc. All Rights Reserved. -*- mode: c++ -*-
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// dwarf2reader::CompilationUnit is a simple and direct parser for
|
||||
// DWARF data, but its handler interface is not convenient to use. In
|
||||
// particular:
|
||||
//
|
||||
// - CompilationUnit calls Dwarf2Handler's member functions to report
|
||||
// every attribute's value, regardless of what sort of DIE it is.
|
||||
// As a result, the ProcessAttributeX functions end up looking like
|
||||
// this:
|
||||
//
|
||||
// switch (parent_die_tag) {
|
||||
// case DW_TAG_x:
|
||||
// switch (attribute_name) {
|
||||
// case DW_AT_y:
|
||||
// handle attribute y of DIE type x
|
||||
// ...
|
||||
// } break;
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// In C++ it's much nicer to use virtual function dispatch to find
|
||||
// the right code for a given case than to switch on the DIE tag
|
||||
// like this.
|
||||
//
|
||||
// - Processing different kinds of DIEs requires different sets of
|
||||
// data. It would be nice to be able to have separate classes for
|
||||
// separate kinds of DIEs, each with the members appropriate to its
|
||||
// role, instead of having one handler class that needs to hold data
|
||||
// for all every DIE type.
|
||||
//
|
||||
// - It would be nice to have separate handler objects for separate
|
||||
// DIEs, instead of a single handler instance required to keep track
|
||||
// of everything.
|
||||
//
|
||||
// - It's not convenient to take some action after all attributes have
|
||||
// been seen, but before visiting any children. The only indication
|
||||
// you have that a DIE's attribute list is complete is that you get
|
||||
// either a StartDIE or an EndDIE call.
|
||||
//
|
||||
// - It's not convenient to make use of the tree structure of the
|
||||
// DIEs. Skipping all the children of a given die requires
|
||||
// maintaining state and returning false from StartDIE until we get
|
||||
// an EndDIE call with the appropriate offset. And it's not
|
||||
// convenient to maintain the stack of contexts for the DIEs we have
|
||||
// decided to enter.
|
||||
//
|
||||
// This interface tries to take care of all that. (How'd you guess?)
|
||||
//
|
||||
// Using the classes here, you provide an initial handler for the root
|
||||
// DIE of the compilation unit. Each handler receives its DIE's
|
||||
// attributes, and provides fresh handler objects for children of
|
||||
// interest, if any.
|
||||
//
|
||||
// You use them as follows:
|
||||
//
|
||||
// - Define handler classes specialized to particular DIE types of
|
||||
// interest. These handler classes must inherit from the DIEHandler
|
||||
// class, defined below. Thus:
|
||||
//
|
||||
// class My_DW_TAG_X_Handler: public DIEHandler { ... };
|
||||
// class My_DW_TAG_Y_Handler: public DIEHandler { ... };
|
||||
//
|
||||
// DIEHandler subclasses needn't correspond exactly to single DIE
|
||||
// types, as shown here; the point is that you can write different
|
||||
// classes for different kinds of DIEs.
|
||||
//
|
||||
// - In particular, define a DIE handler class for the compilation
|
||||
// unit's root DIE, that inherits from the RootDIEHandler class
|
||||
//
|
||||
// class My_DW_TAG_compile_unit_Handler: public RootDIEHandler { ... };
|
||||
//
|
||||
// RootDIEHandler inherits from DIEHandler, adding a few additional
|
||||
// member functions for examining the compilation unit as a whole,
|
||||
// and other quirks of rootness.
|
||||
//
|
||||
// - Then, create a DIEDispatcher instance, passing it an instance of
|
||||
// your root DIE handler, and use that as the
|
||||
// dwarf2reader::CompilationUnit's handler:
|
||||
//
|
||||
// My_DW_TAG_compile_unit_Handler root_die_handler(...);
|
||||
// DIEDispatcher die_dispatcher(&root_die_handler);
|
||||
// CompilationUnit reader(sections, offset, bytereader, &die_dispatcher);
|
||||
//
|
||||
// Here, 'die_dispatcher' acts as a shim between 'reader' and the
|
||||
// various DIE-specific handlers.
|
||||
//
|
||||
// - When you call reader.Start(), die_dispatcher behaves as follows,
|
||||
// starting with your root die handler and the compilation unit's
|
||||
// root DIE:
|
||||
//
|
||||
// - It calls the handler's ProcessAttributeX member functions for
|
||||
// each of the DIE's attributes.
|
||||
//
|
||||
// - It calls the handler's EndAttributes member function. This
|
||||
// should return true if any of the DIE's children should be
|
||||
// visited, in which case:
|
||||
//
|
||||
// - die_dispatcher calls the handler's FindChildHandler member
|
||||
// function. If that returns NULL, die_dispatcher ignores that
|
||||
// child and its descendants. Otherwise, FindChildHandler
|
||||
// returns a pointer to a DIEHandler instance; die_dispatcher
|
||||
// uses that handler to process the child, using this procedure
|
||||
// recursively.
|
||||
//
|
||||
// - When die_dispatcher has finished processing all the DIE's
|
||||
// children, it invokes the handler's Finish() member function,
|
||||
// and destroys the handler. (As a special case, it doesn't
|
||||
// destroy the root DIE handler.)
|
||||
//
|
||||
// This allows the code for handling a particular kind of DIE to be
|
||||
// gathered together in a single class, makes it easy to skip all the
|
||||
// children or individual children of a particular DIE, and provides
|
||||
// appropriate parental context for each die.
|
||||
|
||||
#ifndef COMMON_DWARF_DWARF2DIEHANDLER_H__
|
||||
#define COMMON_DWARF_DWARF2DIEHANDLER_H__
|
||||
|
||||
#include <stack>
|
||||
|
||||
#include "common/dwarf/types.h"
|
||||
#include "common/dwarf/dwarf2enums.h"
|
||||
#include "common/dwarf/dwarf2reader.h"
|
||||
|
||||
namespace dwarf2reader {
|
||||
|
||||
// A parent class for handlers for specific DIE types.
|
||||
// The series of calls made on a DIE handler is as follows:
|
||||
//
|
||||
// - construction, by the parent DIE's handler
|
||||
// - for each attribute of the DIE:
|
||||
// - ProcessAttributeX()
|
||||
// - EndAttributes()
|
||||
// - if that returned true, then for each child:
|
||||
// - FindChildHandler()
|
||||
// - if that returns non-NULL:
|
||||
// - this sequence inserted recursively
|
||||
// - Finish()
|
||||
class DIEHandler {
|
||||
public:
|
||||
DIEHandler() { }
|
||||
virtual ~DIEHandler() { }
|
||||
|
||||
// When we visit a DIE, we first use these member functions to
|
||||
// report the DIE's attributes and their values. These have the
|
||||
// same restrictions as the corresponding member functions of
|
||||
// dwarf2reader::Dwarf2Handler.
|
||||
//
|
||||
// The default definitions ignore the values they are passed.
|
||||
virtual void ProcessAttributeUnsigned(enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
uint64 data) { }
|
||||
virtual void ProcessAttributeSigned(enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
int64 data) { }
|
||||
virtual void ProcessAttributeBuffer(enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
const char* data,
|
||||
uint64 len) { }
|
||||
virtual void ProcessAttributeString(enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
const string& data) { }
|
||||
|
||||
// Once we have reported all the DIE's attributes' values, we call
|
||||
// this member function. If it returns false, we skip all the DIE's
|
||||
// children. If it returns true, we call FindChildHandler on each
|
||||
// child. If that returns a handler object, we use that to visit
|
||||
// the child; otherwise, we skip it.
|
||||
//
|
||||
// The default definition applies FindChildHandler to all children.
|
||||
virtual bool EndAttributes() { return true; }
|
||||
|
||||
// If EndAttributes returns true to indicate that some of the DIE's
|
||||
// children might be of interest, then we apply this function to
|
||||
// each of the DIE's children. If it returns a handler object, then
|
||||
// we use that to visit the child. If it returns NULL, we skip that
|
||||
// child (and its children).
|
||||
//
|
||||
// OFFSET is the offset of the child; TAG indicates what kind of DIE
|
||||
// it is; and ATTRS is the list of attributes the DIE will have, and
|
||||
// their forms (their values are not provided).
|
||||
//
|
||||
// The default definition doesn't handle any children.
|
||||
virtual DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag,
|
||||
const AttributeList &attrs) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// When we are done processing a DIE, we call this member function.
|
||||
// This happens after the EndAttributes call, all FindChildHandler
|
||||
// calls (if any), and all operations on the children themselves (if
|
||||
// any).
|
||||
virtual void Finish() { };
|
||||
};
|
||||
|
||||
// A subclass of DIEHandler, with additional kludges for handling the
|
||||
// compilation unit's root die.
|
||||
class RootDIEHandler: public DIEHandler {
|
||||
public:
|
||||
RootDIEHandler() { }
|
||||
virtual ~RootDIEHandler() { }
|
||||
|
||||
// We pass the values reported via StartCompilationUnit to this
|
||||
// member function, and skip the entire compilation unit if it
|
||||
// returns false. So the root DIE handler is actually also a
|
||||
// compilation unit handler. The default definition always visits
|
||||
// the compilation unit.
|
||||
virtual bool StartCompilationUnit(uint64 offset, uint8 address_size,
|
||||
uint8 offset_size, uint64 cu_length,
|
||||
uint8 dwarf_version) { return true; }
|
||||
|
||||
// For the root DIE handler only, we pass the offset, tag and
|
||||
// attributes of the compilation unit's root DIE. This is the only
|
||||
// way the root DIE handler can find the root DIE's tag. If this
|
||||
// function returns true, we will visit the root DIE using the usual
|
||||
// DIEHandler methods; otherwise, we skip the entire compilation
|
||||
// unit.
|
||||
//
|
||||
// The default definition elects to visit the root DIE.
|
||||
virtual bool StartRootDIE(uint64 offset, enum DwarfTag tag,
|
||||
const AttributeList& attrs) { return true; }
|
||||
};
|
||||
|
||||
class DIEDispatcher: public Dwarf2Handler {
|
||||
public:
|
||||
// Create a Dwarf2Handler which uses ROOT_HANDLER as the handler for
|
||||
// the compilation unit's root die, as described for the DIEHandler
|
||||
// class.
|
||||
DIEDispatcher(RootDIEHandler *root_handler) :
|
||||
root_handler_(root_handler) { }
|
||||
// Destroying a DIEDispatcher destroys all active handler objects
|
||||
// except the root handler.
|
||||
~DIEDispatcher();
|
||||
bool StartCompilationUnit(uint64 offset, uint8 address_size,
|
||||
uint8 offset_size, uint64 cu_length,
|
||||
uint8 dwarf_version);
|
||||
bool StartDIE(uint64 offset, enum DwarfTag tag,
|
||||
const AttributeList &attrs);
|
||||
void ProcessAttributeUnsigned(uint64 offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
uint64 data);
|
||||
void ProcessAttributeSigned(uint64 offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
int64 data);
|
||||
void ProcessAttributeBuffer(uint64 offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
const char* data,
|
||||
uint64 len);
|
||||
void ProcessAttributeString(uint64 offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
const string &data);
|
||||
void EndDIE(uint64 offset);
|
||||
|
||||
private:
|
||||
|
||||
// The type of a handler stack entry. This includes some fields
|
||||
// which don't really need to be on the stack --- they could just be
|
||||
// single data members of DIEDispatcher --- but putting them here
|
||||
// makes it easy to see that the code is correct.
|
||||
struct HandlerStack {
|
||||
// The offset of the DIE for this handler stack entry.
|
||||
uint64 offset_;
|
||||
|
||||
// The object interested in this DIE's attributes and children.
|
||||
// If NULL, we're not interested in either.
|
||||
DIEHandler *handler_;
|
||||
|
||||
// Have we reported the end of this DIE's attributes to the handler?
|
||||
bool reported_attributes_end_;
|
||||
};
|
||||
|
||||
// Stack of DIE attribute handlers. At StartDIE(D), the top of the
|
||||
// stack is the handler of D's parent, whom we may ask for a handler
|
||||
// for D itself. At EndDIE(D), the top of the stack is D's handler.
|
||||
// Special cases:
|
||||
//
|
||||
// - Before we've seen the compilation unit's root DIE, the stack is
|
||||
// empty; we'll call root_handler_'s special member functions, and
|
||||
// perhaps push root_handler_ on the stack to look at the root's
|
||||
// immediate children.
|
||||
//
|
||||
// - When we decide to ignore a subtree, we only push an entry on
|
||||
// the stack for the root of the tree being ignored, rather than
|
||||
// pushing lots of stack entries with ignore_children_ set.
|
||||
stack<HandlerStack> die_handlers_;
|
||||
|
||||
// The root handler. We don't push it on die_handlers_ until we
|
||||
// actually get the StartDIE call for the root.
|
||||
RootDIEHandler *root_handler_;
|
||||
};
|
||||
|
||||
} // namespace dwarf2reader
|
||||
#endif // COMMON_DWARF_DWARF2DIEHANDLER_H__
|
@ -26,8 +26,8 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef COMMON_MAC_DWARF_DWARF2ENUMS_H__
|
||||
#define COMMON_MAC_DWARF_DWARF2ENUMS_H__
|
||||
#ifndef COMMON_DWARF_DWARF2ENUMS_H__
|
||||
#define COMMON_DWARF_DWARF2ENUMS_H__
|
||||
|
||||
namespace dwarf2reader {
|
||||
|
||||
@ -486,5 +486,40 @@ enum DwarfOpcode {
|
||||
DW_OP_GNU_push_tls_address =0xe0
|
||||
};
|
||||
|
||||
// Source languages. These are values for DW_AT_language.
|
||||
enum DwarfLanguage
|
||||
{
|
||||
DW_LANG_none =0x0000,
|
||||
DW_LANG_C89 =0x0001,
|
||||
DW_LANG_C =0x0002,
|
||||
DW_LANG_Ada83 =0x0003,
|
||||
DW_LANG_C_plus_plus =0x0004,
|
||||
DW_LANG_Cobol74 =0x0005,
|
||||
DW_LANG_Cobol85 =0x0006,
|
||||
DW_LANG_Fortran77 =0x0007,
|
||||
DW_LANG_Fortran90 =0x0008,
|
||||
DW_LANG_Pascal83 =0x0009,
|
||||
DW_LANG_Modula2 =0x000a,
|
||||
DW_LANG_Java =0x000b,
|
||||
DW_LANG_C99 =0x000c,
|
||||
DW_LANG_Ada95 =0x000d,
|
||||
DW_LANG_Fortran95 =0x000e,
|
||||
DW_LANG_PLI =0x000f,
|
||||
DW_LANG_ObjC =0x0010,
|
||||
DW_LANG_ObjC_plus_plus =0x0011,
|
||||
DW_LANG_UPC =0x0012,
|
||||
DW_LANG_D =0x0013,
|
||||
// Implementation-defined language code range.
|
||||
DW_LANG_lo_user = 0x8000,
|
||||
DW_LANG_hi_user = 0xffff,
|
||||
|
||||
// Extensions.
|
||||
|
||||
// MIPS assembly language. The GNU toolchain uses this for all
|
||||
// assembly languages, since there's no generic DW_LANG_ value for that.
|
||||
DW_LANG_Mips_Assembler =0x8001,
|
||||
DW_LANG_Upc =0x8765 // Unified Parallel C
|
||||
};
|
||||
|
||||
} // namespace dwarf2reader
|
||||
#endif // COMMON_MAC_DWARF_DWARF2ENUMS_H__
|
||||
#endif // COMMON_DWARF_DWARF2ENUMS_H__
|
@ -28,11 +28,13 @@
|
||||
|
||||
#include <stack>
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
|
||||
#include "common/mac/dwarf/bytereader-inl.h"
|
||||
#include "common/mac/dwarf/dwarf2reader.h"
|
||||
#include "common/mac/dwarf/bytereader.h"
|
||||
#include "common/mac/dwarf/line_state_machine.h"
|
||||
#include "common/dwarf/bytereader-inl.h"
|
||||
#include "common/dwarf/dwarf2reader.h"
|
||||
#include "common/dwarf/bytereader.h"
|
||||
#include "common/dwarf/line_state_machine.h"
|
||||
|
||||
namespace dwarf2reader {
|
||||
|
||||
@ -75,8 +77,12 @@ void CompilationUnit::ReadAbbrevs() {
|
||||
if (abbrevs_)
|
||||
return;
|
||||
|
||||
// First get the debug_abbrev section
|
||||
SectionMap::const_iterator iter = sections_.find("__debug_abbrev");
|
||||
// First get the debug_abbrev section. ".debug_abbrev" is the name
|
||||
// recommended in the DWARF spec, and used on Linux;
|
||||
// "__debug_abbrev" is the name used in Mac OS X Mach-O files.
|
||||
SectionMap::const_iterator iter = sections_.find(".debug_abbrev");
|
||||
if (iter == sections_.end())
|
||||
iter = sections_.find("__debug_abbrev");
|
||||
assert(iter != sections_.end());
|
||||
|
||||
abbrevs_ = new vector<Abbrev>;
|
||||
@ -88,7 +94,9 @@ void CompilationUnit::ReadAbbrevs() {
|
||||
const char* abbrev_start = iter->second.first +
|
||||
header_.abbrev_offset;
|
||||
const char* abbrevptr = abbrev_start;
|
||||
#ifndef NDEBUG
|
||||
const uint64 abbrev_length = iter->second.second - header_.abbrev_offset;
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
CompilationUnit::Abbrev abbrev;
|
||||
@ -261,8 +269,12 @@ void CompilationUnit::ReadHeader() {
|
||||
}
|
||||
|
||||
uint64 CompilationUnit::Start() {
|
||||
// First get the debug_info section
|
||||
SectionMap::const_iterator iter = sections_.find("__debug_info");
|
||||
// First get the debug_info section. ".debug_info" is the name
|
||||
// recommended in the DWARF spec, and used on Linux; "__debug_info"
|
||||
// is the name used in Mac OS X Mach-O files.
|
||||
SectionMap::const_iterator iter = sections_.find(".debug_info");
|
||||
if (iter == sections_.end())
|
||||
iter = sections_.find("__debug_info");
|
||||
assert(iter != sections_.end());
|
||||
|
||||
// Set up our buffer
|
||||
@ -292,8 +304,12 @@ uint64 CompilationUnit::Start() {
|
||||
// Otherwise, continue by reading our abbreviation entries.
|
||||
ReadAbbrevs();
|
||||
|
||||
// Set the string section if we have one.
|
||||
iter = sections_.find("__debug_str");
|
||||
// Set the string section if we have one. ".debug_str" is the name
|
||||
// recommended in the DWARF spec, and used on Linux; "__debug_str"
|
||||
// is the name used in Mac OS X Mach-O files.
|
||||
iter = sections_.find(".debug_str");
|
||||
if (iter == sections_.end())
|
||||
iter = sections_.find("__debug_str");
|
||||
if (iter != sections_.end()) {
|
||||
string_buffer_ = iter->second.first;
|
||||
string_buffer_length_ = iter->second.second;
|
||||
@ -464,7 +480,7 @@ void CompilationUnit::ProcessDIEs() {
|
||||
// we need semantics of boost scoped_ptr here - no intention of trasnferring
|
||||
// ownership of the stack. use const, but then we limit ourselves to not
|
||||
// ever being able to call .reset() on the smart pointer.
|
||||
auto_ptr<stack<uint64> > const die_stack(new stack<uint64>);
|
||||
std::auto_ptr<stack<uint64> > const die_stack(new stack<uint64>);
|
||||
|
||||
while (dieptr < (lengthstart + header_.length)) {
|
||||
// We give the user the absolute offset from the beginning of
|
||||
@ -799,16 +815,18 @@ void LineInfo::ReadLines() {
|
||||
lengthstart += 4;
|
||||
|
||||
const char* lineptr = after_header_;
|
||||
lsm.Reset(header_.default_is_stmt);
|
||||
while (lineptr < lengthstart + header_.total_length) {
|
||||
lsm.Reset(header_.default_is_stmt);
|
||||
while (!lsm.end_sequence) {
|
||||
size_t oplength;
|
||||
bool add_line = ProcessOneOpcode(reader_, handler_, header_,
|
||||
lineptr, &lsm, &oplength, (uintptr_t)-1, NULL);
|
||||
if (add_line)
|
||||
handler_->AddLine(lsm.address, lsm.file_num, lsm.line_num,
|
||||
lsm.column_num);
|
||||
lineptr += oplength;
|
||||
size_t oplength;
|
||||
bool add_line = ProcessOneOpcode(reader_, handler_, header_,
|
||||
lineptr, &lsm, &oplength, (uintptr_t)-1, NULL);
|
||||
lineptr += oplength;
|
||||
if (lsm.end_sequence) {
|
||||
handler_->EndSequence(lsm.address);
|
||||
lsm.Reset(header_.default_is_stmt);
|
||||
} else if (add_line) {
|
||||
handler_->AddLine(lsm.address, lsm.file_num, lsm.line_num,
|
||||
lsm.column_num);
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +33,8 @@
|
||||
// reading if you wish to modify the implementation.
|
||||
// Only a cursory attempt is made to explain terminology that is
|
||||
// used here, as it is much better explained in the standard documents
|
||||
#ifndef COMMON_MAC_DWARF_DWARF2READER_H__
|
||||
#define COMMON_MAC_DWARF_DWARF2READER_H__
|
||||
#ifndef COMMON_DWARF_DWARF2READER_H__
|
||||
#define COMMON_DWARF_DWARF2READER_H__
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
@ -42,8 +42,8 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "common/mac/dwarf/dwarf2enums.h"
|
||||
#include "common/mac/dwarf/types.h"
|
||||
#include "common/dwarf/dwarf2enums.h"
|
||||
#include "common/dwarf/types.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -173,6 +173,16 @@ class LineInfoHandler {
|
||||
// starts at, if we know it (0 otherwise).
|
||||
virtual void AddLine(uint64 address, uint32 file_num, uint32 line_num,
|
||||
uint32 column_num) { }
|
||||
|
||||
// Called at the end of a sequence of lines. ADDRESS is the address
|
||||
// of the first byte after the final machine instruction of the
|
||||
// sequence.
|
||||
//
|
||||
// Note that this is *not* necessarily the end of the line data for
|
||||
// the compilation unit: a single compilation unit's line program
|
||||
// may contain several "end of sequence" markers, to describe (for
|
||||
// example) several discontiguous regions of code.
|
||||
virtual void EndSequence(uint64 address) { }
|
||||
};
|
||||
|
||||
// The base of DWARF2/3 debug info is a DIE (Debugging Information
|
||||
@ -224,8 +234,11 @@ class CompilationUnit {
|
||||
|
||||
// Begin reading a Dwarf2 compilation unit, and calling the
|
||||
// callbacks in the Dwarf2Handler
|
||||
// Return the offset of the end of the compilation unit - the passed
|
||||
// in offset.
|
||||
|
||||
// Return the full length of the compilation unit, including
|
||||
// headers. This plus the starting offset passed to the constructor
|
||||
// is the offset of the end of the compilation unit --- the start of
|
||||
// the next compilation unit, if there is one.
|
||||
uint64 Start();
|
||||
|
||||
private:
|
@ -34,9 +34,9 @@
|
||||
#include <vector>
|
||||
|
||||
|
||||
#include "common/mac/dwarf/functioninfo.h"
|
||||
#include "common/dwarf/functioninfo.h"
|
||||
|
||||
#include "common/mac/dwarf/bytereader.h"
|
||||
#include "common/dwarf/bytereader.h"
|
||||
|
||||
|
||||
namespace dwarf2reader {
|
||||
@ -121,6 +121,17 @@ void CULineInfoHandler::AddLine(uint64 address, uint32 file_num,
|
||||
}
|
||||
}
|
||||
|
||||
void CULineInfoHandler::EndSequence(uint64 address) {
|
||||
// To preserve this code's behavior prior to the addition of the
|
||||
// EndSequence member function, we duplicate the previous line,
|
||||
// changing its address to ADDRESS.
|
||||
LineMap::iterator it = linemap_->lower_bound(address);
|
||||
if (it != linemap_->begin()) {
|
||||
it--;
|
||||
linemap_->insert(make_pair(address, it->second));
|
||||
}
|
||||
}
|
||||
|
||||
bool CUFunctionInfoHandler::StartCompilationUnit(uint64 offset,
|
||||
uint8 address_size,
|
||||
uint8 offset_size,
|
@ -31,15 +31,15 @@
|
||||
// collector that uses the DWARF2/3 reader interface to build a mapping
|
||||
// of addresses to files, lines, and functions.
|
||||
|
||||
#ifndef COMMON_MAC_DWARF_FUNCTIONINFO_H__
|
||||
#define COMMON_MAC_DWARF_FUNCTIONINFO_H__
|
||||
#ifndef COMMON_DWARF_FUNCTIONINFO_H__
|
||||
#define COMMON_DWARF_FUNCTIONINFO_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "common/mac/dwarf/dwarf2reader.h"
|
||||
#include "common/dwarf/dwarf2reader.h"
|
||||
|
||||
|
||||
namespace dwarf2reader {
|
||||
@ -99,6 +99,16 @@ class CULineInfoHandler: public LineInfoHandler {
|
||||
virtual void AddLine(uint64 address, uint32 file_num, uint32 line_num,
|
||||
uint32 column_num);
|
||||
|
||||
// Called at the end of a sequence of lines. ADDRESS is the address
|
||||
// of the first byte after the final machine instruction of the
|
||||
// sequence.
|
||||
//
|
||||
// Note that this is *not* necessarily the end of the line data for
|
||||
// the compilation unit: a single compilation unit's line program
|
||||
// may contain several "end of sequence" markers, to describe (for
|
||||
// example) several discontiguous regions of code.
|
||||
virtual void EndSequence(uint64 address);
|
||||
|
||||
|
||||
private:
|
||||
LineMap* linemap_;
|
||||
@ -175,4 +185,4 @@ class CUFunctionInfoHandler: public Dwarf2Handler {
|
||||
};
|
||||
|
||||
} // namespace dwarf2reader
|
||||
#endif // COMMON_MAC_DWARF_FUNCTIONINFO_H__
|
||||
#endif // COMMON_DWARF_FUNCTIONINFO_H__
|
@ -27,8 +27,8 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#ifndef COMMON_MAC_DWARF_LINE_STATE_MACHINE_H__
|
||||
#define COMMON_MAC_DWARF_LINE_STATE_MACHINE_H__
|
||||
#ifndef COMMON_DWARF_LINE_STATE_MACHINE_H__
|
||||
#define COMMON_DWARF_LINE_STATE_MACHINE_H__
|
||||
|
||||
namespace dwarf2reader {
|
||||
|
||||
@ -58,4 +58,4 @@ struct LineStateMachine {
|
||||
} // namespace dwarf2reader
|
||||
|
||||
|
||||
#endif // COMMON_MAC_DWARF_LINE_STATE_MACHINE_H__
|
||||
#endif // COMMON_DWARF_LINE_STATE_MACHINE_H__
|
@ -30,8 +30,8 @@
|
||||
// This file contains some typedefs for basic types
|
||||
|
||||
|
||||
#ifndef _COMMON_MAC_DWARF_TYPES_H__
|
||||
#define _COMMON_MAC_DWARF_TYPES_H__
|
||||
#ifndef _COMMON_DWARF_TYPES_H__
|
||||
#define _COMMON_DWARF_TYPES_H__
|
||||
|
||||
typedef signed char int8;
|
||||
typedef short int16;
|
||||
@ -43,4 +43,4 @@ typedef unsigned short uint16;
|
||||
typedef unsigned int uint32;
|
||||
typedef unsigned long long uint64;
|
||||
|
||||
#endif // _COMMON_MAC_DWARF_TYPES_H__
|
||||
#endif // _COMMON_DWARF_TYPES_H__
|
@ -146,6 +146,7 @@ class DumpStabsHandler: public google_breakpad::StabsHandler {
|
||||
bool StartFunction(const std::string &name, uint64_t address);
|
||||
bool EndFunction(uint64_t address);
|
||||
bool Line(uint64_t address, const char *name, int number);
|
||||
void Warning(const char *format, ...);
|
||||
|
||||
// Do any final processing necessary to make module_ contain all the
|
||||
// data provided by the STABS reader.
|
||||
@ -267,6 +268,13 @@ bool DumpStabsHandler::Line(uint64_t address, const char *name, int number) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void DumpStabsHandler::Warning(const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void DumpStabsHandler::Finalize() {
|
||||
// Sort our boundary list, so we can search it quickly.
|
||||
sort(boundaries_.begin(), boundaries_.end());
|
||||
|
@ -94,8 +94,13 @@ bool StabsReader::ProcessCompilationUnit() {
|
||||
if (symbol_ >= symbols_end_ || symbol_->n_type != N_SO)
|
||||
return true;
|
||||
const char *name = SymbolString();
|
||||
if (name[0] == '\0')
|
||||
if (name[0] == '\0') {
|
||||
// This seems to be a stray end-of-compilation-unit marker;
|
||||
// consume it, but don't report the end, since we didn't see a
|
||||
// beginning.
|
||||
symbol_++;
|
||||
return true;
|
||||
}
|
||||
current_source_file_ = name;
|
||||
}
|
||||
|
||||
@ -107,9 +112,9 @@ bool StabsReader::ProcessCompilationUnit() {
|
||||
symbol_++;
|
||||
|
||||
// The STABS documentation says that some compilers may emit
|
||||
// additional N_SO units with names immediately following the first,
|
||||
// and that they should be ignored. However, the original Breakpad
|
||||
// STABS reader doesn't ignore them, so we won't either.
|
||||
// additional N_SO entries with names immediately following the
|
||||
// first, and that they should be ignored. However, the original
|
||||
// Breakpad STABS reader doesn't ignore them, so we won't either.
|
||||
|
||||
// Process the body of the compilation unit, up to the next N_SO.
|
||||
while (symbol_ < symbols_end_ && symbol_->n_type != N_SO) {
|
||||
|
@ -54,8 +54,8 @@ class StabsReader {
|
||||
// Create a reader for the STABS debug information whose .stab
|
||||
// section is the STAB_SIZE bytes at STAB, and whose .stabstr
|
||||
// section is the STABSTR_SIZE bytes at STABSTR. The reader will
|
||||
// call the methods of HANDLER to report the information it finds,
|
||||
// when the reader's 'process' method is called.
|
||||
// call the member functions of HANDLER to report the information it
|
||||
// finds, when the reader's 'Process' member function is called.
|
||||
//
|
||||
// Note that, in ELF, the .stabstr section should be found using the
|
||||
// 'sh_link' field of the .stab section header, not by name.
|
||||
@ -63,9 +63,9 @@ class StabsReader {
|
||||
const uint8_t *stabstr, size_t stabstr_size,
|
||||
StabsHandler *handler);
|
||||
|
||||
// Process the STAB data, calling the handler's methods to report
|
||||
// what we find. While the handler functions return true, continue
|
||||
// to process until we reach the end of the section. If we
|
||||
// Process the STABS data, calling the handler's member functions to
|
||||
// report what we find. While the handler functions return true,
|
||||
// continue to process until we reach the end of the section. If we
|
||||
// processed the entire section and all handlers returned true,
|
||||
// return true. If any handler returned false, return false.
|
||||
bool Process();
|
||||
@ -101,12 +101,13 @@ class StabsReader {
|
||||
const char *current_source_file_;
|
||||
};
|
||||
|
||||
// Consumer-provided callback structure for the STABS reader.
|
||||
// Clients of the STABS reader provide an instance of this structure.
|
||||
// The reader then invokes the methods of that instance to report the
|
||||
// information it finds.
|
||||
// Consumer-provided callback structure for the STABS reader. Clients
|
||||
// of the STABS reader provide an instance of this structure. The
|
||||
// reader then invokes the member functions of that instance to report
|
||||
// the information it finds.
|
||||
//
|
||||
// The default definitions of the methods do nothing.
|
||||
// The default definitions of the member functions do nothing, and return
|
||||
// true so processing will continue.
|
||||
class StabsHandler {
|
||||
public:
|
||||
StabsHandler() { }
|
||||
@ -134,9 +135,10 @@ class StabsHandler {
|
||||
// file names.
|
||||
//
|
||||
// Thus, it's safe to use (say) std::map<char *, ...>, which does
|
||||
// address comparisons. Since all the pointers are into the array
|
||||
// holding the .stabstr section's contents, comparing them produces
|
||||
// predictable results.
|
||||
// string address comparisons, not string content comparisons.
|
||||
// Since all the strings are in same array of characters --- the
|
||||
// .stabstr section --- comparing their addresses produces
|
||||
// predictable, if not lexicographically meaningful, results.
|
||||
|
||||
// Begin processing a compilation unit whose main source file is
|
||||
// named FILENAME, and whose base address is ADDRESS. If
|
||||
@ -147,10 +149,10 @@ class StabsHandler {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Finish processing the compilation unit. If END_ADDRESS is
|
||||
// non-zero, it is the ending address of the compilation unit. This
|
||||
// information may not be available, in which case the consumer must
|
||||
// infer it by other means.
|
||||
// Finish processing the compilation unit. If ADDRESS is non-zero,
|
||||
// it is the ending address of the compilation unit. If ADDRESS is
|
||||
// zero, then the compilation unit's ending address is not
|
||||
// available, and the consumer must infer it by other means.
|
||||
virtual bool EndCompilationUnit(uint64_t address) { return true; }
|
||||
|
||||
// Begin processing a function named NAME, whose starting address is
|
||||
@ -161,14 +163,16 @@ class StabsHandler {
|
||||
// .stabstr section; this is because the name as it appears in the
|
||||
// STABS data is followed by type information. The value passed to
|
||||
// StartFunction is the function name alone.
|
||||
//
|
||||
// In languages that use name mangling, like C++, NAME is mangled.
|
||||
virtual bool StartFunction(const std::string &name, uint64_t address) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Finishing processing the function. If END_ADDRESS is non-zero,
|
||||
// it is the ending address for the function. This information may
|
||||
// not be available, in which case the consumer must infer it by
|
||||
// other means.
|
||||
// Finish processing the function. If ADDRESS is non-zero, it is
|
||||
// the ending address for the function. If ADDRESS is zero, then
|
||||
// the function's ending address is not available, and the consumer
|
||||
// must infer it by other means.
|
||||
virtual bool EndFunction(uint64_t address) { return true; }
|
||||
|
||||
// Report that the code at ADDRESS is attributable to line NUMBER of
|
||||
@ -179,8 +183,9 @@ class StabsHandler {
|
||||
}
|
||||
|
||||
// Report a warning. FORMAT is a printf-like format string,
|
||||
// specifying how to format the subsequent arguments.
|
||||
virtual void Warning(const char *format, ...) { }
|
||||
// specifying how to format the subsequent arguments. By default,
|
||||
// print the message to the standard error output.
|
||||
virtual void Warning(const char *format, ...) = 0;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <mach-o/loader.h>
|
||||
#include "common/mac/dwarf/dwarf2reader.h"
|
||||
#include "common/dwarf/dwarf2reader.h"
|
||||
|
||||
// This will map from an architecture string to a SectionMap, which
|
||||
// will contain the offsets for all the sections in the dictionary
|
||||
|
@ -47,9 +47,9 @@
|
||||
#import "dump_syms.h"
|
||||
#import "common/mac/file_id.h"
|
||||
#import "common/mac/macho_utilities.h"
|
||||
#import "common/mac/dwarf/dwarf2reader.h"
|
||||
#import "common/mac/dwarf/functioninfo.h"
|
||||
#import "common/mac/dwarf/bytereader.h"
|
||||
#import "common/dwarf/dwarf2reader.h"
|
||||
#import "common/dwarf/functioninfo.h"
|
||||
#import "common/dwarf/bytereader.h"
|
||||
|
||||
using google_breakpad::FileID;
|
||||
|
||||
|
@ -16,29 +16,40 @@ BIN=dump_syms
|
||||
|
||||
all:$(BIN)
|
||||
|
||||
DUMP_OBJ=dump_symbols.o guid_creator.o dump_syms.o file_id.o md5.o \
|
||||
stabs_reader.o module.o
|
||||
TOP = ../../../..
|
||||
VPATH = $(TOP)/src/common/linux
|
||||
VPATH += $(TOP)/src/common
|
||||
VPATH += $(TOP)/src/common/dwarf
|
||||
|
||||
DUMP_OBJ = \
|
||||
dump_symbols.o \
|
||||
dump_syms.o \
|
||||
dwarf2diehandler.o \
|
||||
file_id.o \
|
||||
guid_creator.o \
|
||||
md5.o \
|
||||
module.o \
|
||||
stabs_reader.o \
|
||||
$(NULL)
|
||||
|
||||
dump_syms:$(DUMP_OBJ)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $^
|
||||
|
||||
dump_symbols.o:../../../common/linux/dump_symbols.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $^
|
||||
# From this directory:
|
||||
dump_syms.o: dump_syms.cc
|
||||
|
||||
stabs_reader.o:../../../common/linux/stabs_reader.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $^
|
||||
# From src/common/linux:
|
||||
dump_symbols.o: dump_symbols.cc
|
||||
stabs_reader.o: stabs_reader.cc
|
||||
module.o: module.cc
|
||||
guid_creator.o: guid_creator.cc
|
||||
file_id.o: file_id.cc
|
||||
|
||||
module.o:../../../common/linux/module.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $^
|
||||
# From src/common:
|
||||
md5.o: md5.c
|
||||
|
||||
guid_creator.o:../../../common/linux/guid_creator.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $^
|
||||
|
||||
file_id.o:../../../common/linux/file_id.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $^
|
||||
|
||||
md5.o:../../../common/md5.c
|
||||
$(CC) $(CPPFLAGS) $(CXXFLAGS) -c $^
|
||||
# From src/common/dwarf:
|
||||
dwarf2diehandler.o: dwarf2diehandler.cc
|
||||
|
||||
clean:
|
||||
rm -f $(BIN) $(DUMP_OBJ)
|
||||
|
@ -130,9 +130,9 @@
|
||||
9BE650AF0B52FE3000611104 /* macho_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_id.h; path = ../../../common/mac/macho_id.h; sourceTree = SOURCE_ROOT; };
|
||||
9BE650B00B52FE3000611104 /* macho_walker.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_walker.cc; path = ../../../common/mac/macho_walker.cc; sourceTree = SOURCE_ROOT; };
|
||||
9BE650B10B52FE3000611104 /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../../common/mac/macho_walker.h; sourceTree = SOURCE_ROOT; };
|
||||
F9C7ECE20E8ABCA600E953AD /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/mac/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
|
||||
F9C7ECE30E8ABCA600E953AD /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/mac/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
|
||||
F9C7ECE40E8ABCA600E953AD /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/mac/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
|
||||
F9C7ECE20E8ABCA600E953AD /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
|
||||
F9C7ECE30E8ABCA600E953AD /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
|
||||
F9C7ECE40E8ABCA600E953AD /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
|
||||
FD6625C40CF4D438004AC844 /* stackwalker_amd64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_amd64.cc; path = ../../../processor/stackwalker_amd64.cc; sourceTree = SOURCE_ROOT; };
|
||||
FD6625C50CF4D438004AC844 /* stackwalker_amd64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stackwalker_amd64.h; path = ../../../processor/stackwalker_amd64.h; sourceTree = SOURCE_ROOT; };
|
||||
FD8EDEAC0CADDAD400A5EDF1 /* stackwalker_sparc.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_sparc.cc; path = ../../../processor/stackwalker_sparc.cc; sourceTree = SOURCE_ROOT; };
|
||||
|
@ -45,15 +45,15 @@
|
||||
9BE650440B52F6D800611104 /* macho_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_id.h; path = ../../../common/mac/macho_id.h; sourceTree = SOURCE_ROOT; };
|
||||
9BE650450B52F6D800611104 /* macho_walker.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_walker.cc; path = ../../../common/mac/macho_walker.cc; sourceTree = SOURCE_ROOT; };
|
||||
9BE650460B52F6D800611104 /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../../common/mac/macho_walker.h; sourceTree = SOURCE_ROOT; };
|
||||
F95B422B0E0E22D100DBDE83 /* bytereader-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "bytereader-inl.h"; path = "../../../common/mac/dwarf/bytereader-inl.h"; sourceTree = SOURCE_ROOT; };
|
||||
F95B422C0E0E22D100DBDE83 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/mac/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
|
||||
F95B422D0E0E22D100DBDE83 /* bytereader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bytereader.h; path = ../../../common/mac/dwarf/bytereader.h; sourceTree = SOURCE_ROOT; };
|
||||
F95B422E0E0E22D100DBDE83 /* dwarf2enums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2enums.h; path = ../../../common/mac/dwarf/dwarf2enums.h; sourceTree = SOURCE_ROOT; };
|
||||
F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/mac/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
|
||||
F95B42300E0E22D100DBDE83 /* dwarf2reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2reader.h; path = ../../../common/mac/dwarf/dwarf2reader.h; sourceTree = SOURCE_ROOT; };
|
||||
F95B42310E0E22D100DBDE83 /* line_state_machine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = line_state_machine.h; path = ../../../common/mac/dwarf/line_state_machine.h; sourceTree = SOURCE_ROOT; };
|
||||
F9C7ED420E8AD93000E953AD /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/mac/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
|
||||
F9F5344D0E7C902C0012363F /* functioninfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = functioninfo.h; path = ../../../common/mac/dwarf/functioninfo.h; sourceTree = SOURCE_ROOT; };
|
||||
F95B422B0E0E22D100DBDE83 /* bytereader-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "bytereader-inl.h"; path = "../../../common/dwarf/bytereader-inl.h"; sourceTree = SOURCE_ROOT; };
|
||||
F95B422C0E0E22D100DBDE83 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
|
||||
F95B422D0E0E22D100DBDE83 /* bytereader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bytereader.h; path = ../../../common/dwarf/bytereader.h; sourceTree = SOURCE_ROOT; };
|
||||
F95B422E0E0E22D100DBDE83 /* dwarf2enums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2enums.h; path = ../../../common/dwarf/dwarf2enums.h; sourceTree = SOURCE_ROOT; };
|
||||
F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
|
||||
F95B42300E0E22D100DBDE83 /* dwarf2reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2reader.h; path = ../../../common/dwarf/dwarf2reader.h; sourceTree = SOURCE_ROOT; };
|
||||
F95B42310E0E22D100DBDE83 /* line_state_machine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = line_state_machine.h; path = ../../../common/dwarf/line_state_machine.h; sourceTree = SOURCE_ROOT; };
|
||||
F9C7ED420E8AD93000E953AD /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
|
||||
F9F5344D0E7C902C0012363F /* functioninfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = functioninfo.h; path = ../../../common/dwarf/functioninfo.h; sourceTree = SOURCE_ROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
Loading…
Reference in New Issue
Block a user