Compare commits

...

10 Commits

Author SHA1 Message Date
nealsid
01ca4892d8 Forgot to add modified files for the last commit!
http://breakpad.appspot.com/33002

A=jim.blandy
R=nealsid


git-svn-id: http://google-breakpad.googlecode.com/svn/branches/linux-dwarf@415 4c0a9323-5329-0410-9bdc-e9ce6186880e
2009-10-08 19:20:06 +00:00
nealsid
11fbf26119 Handle DW_LNE_end_sequence, plus a better infrastructure for
creating DIE handlers using dynamic dispatch & virtual methods.

http://breakpad.appspot.com/33002 (although the version of upload.py I'm using doesn't appear to upload new files to the code review for git)

A=jim.blandy
R=nealsid


git-svn-id: http://google-breakpad.googlecode.com/svn/branches/linux-dwarf@414 4c0a9323-5329-0410-9bdc-e9ce6186880e
2009-10-08 19:19:56 +00:00
nealsid
548c407f4b Issue 32002: update char declarations to be unsigned
http://breakpad.appspot.com/32002

A=jim.blandy
R=nealsid


git-svn-id: http://google-breakpad.googlecode.com/svn/branches/linux-dwarf@413 4c0a9323-5329-0410-9bdc-e9ce6186880e
2009-10-08 19:19:49 +00:00
nealsid
52af30d80c Issue 33001: Add missing includes and update comments to DWARF code
http://breakpad.appspot.com/33001

A=jim.blandy
R=nealsid


git-svn-id: http://google-breakpad.googlecode.com/svn/branches/linux-dwarf@412 4c0a9323-5329-0410-9bdc-e9ce6186880e
2009-10-08 19:19:42 +00:00
nealsid
3d9c2ce401 Makefile refactoring/cleanup
A=jim.blandy
R=nealsid


git-svn-id: http://google-breakpad.googlecode.com/svn/branches/linux-dwarf@411 4c0a9323-5329-0410-9bdc-e9ce6186880e
2009-10-08 19:19:33 +00:00
nealsid
06a8c78818 Updated STABS comments and moved DWARF code to a common location. This should have been done already but I think I'm messing something up with my git-svn fiddling :-)
A=jim blandy
R=nealsid


git-svn-id: http://google-breakpad.googlecode.com/svn/branches/linux-dwarf@399 4c0a9323-5329-0410-9bdc-e9ce6186880e
2009-09-17 22:16:13 +00:00
nealsid
0f3b2d75d9 Updated STABS comments and moved DWARF code to a common location.
A=jim blandy
R=nealsid


git-svn-id: http://google-breakpad.googlecode.com/svn/branches/linux-dwarf@398 4c0a9323-5329-0410-9bdc-e9ce6186880e
2009-09-17 22:15:57 +00:00
nealsid
e1e8be4cae Continue past stray end of compilation unit marker rather than returning true early
A=jim blandy
R=nealsid


git-svn-id: http://google-breakpad.googlecode.com/svn/branches/linux-dwarf@397 4c0a9323-5329-0410-9bdc-e9ce6186880e
2009-09-17 22:11:45 +00:00
nealsid
8583d8ee76 Add a warning function to print a formatted string to stderr
A=jim.blandy
R=nealsid


git-svn-id: http://google-breakpad.googlecode.com/svn/branches/linux-dwarf@396 4c0a9323-5329-0410-9bdc-e9ce6186880e
2009-09-17 22:09:30 +00:00
nealsid
64892f177d Branch for Linux dwarf work
git-svn-id: http://google-breakpad.googlecode.com/svn/branches/linux-dwarf@395 4c0a9323-5329-0410-9bdc-e9ce6186880e
2009-09-17 19:19:22 +00:00
21 changed files with 745 additions and 127 deletions

View File

@ -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>"; };

View File

@ -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;

View File

@ -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 {

View File

@ -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__

View 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 &current = 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 &current = 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 &current = 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 &current = 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

View 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__

View File

@ -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__

View File

@ -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);
}
}

View File

@ -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:

View File

@ -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,

View File

@ -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__

View File

@ -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__

View File

@ -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__

View File

@ -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());

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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; };

View File

@ -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 */