Refactor source line resolver, add interface in supplier and resolver.
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@711 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
d35f113d02
commit
5b117cf53a
24 changed files with 1021 additions and 418 deletions
11
Makefile.am
11
Makefile.am
|
@ -90,6 +90,7 @@ src_libbreakpad_a_SOURCES = \
|
|||
src/google_breakpad/processor/minidump_processor.h \
|
||||
src/google-breakpad/processor/network_source_line_resolver.h \
|
||||
src/google_breakpad/processor/process_state.h \
|
||||
src/google_breakpad/processor/source_line_resolver_base.h \
|
||||
src/google_breakpad/processor/source_line_resolver_interface.h \
|
||||
src/google_breakpad/processor/stack_frame.h \
|
||||
src/google_breakpad/processor/stack_frame_cpu.h \
|
||||
|
@ -101,6 +102,7 @@ src_libbreakpad_a_SOURCES = \
|
|||
src/processor/basic_code_module.h \
|
||||
src/processor/basic_code_modules.cc \
|
||||
src/processor/basic_code_modules.h \
|
||||
src/processor/basic_source_line_resolver_types.h \
|
||||
src/processor/basic_source_line_resolver.cc \
|
||||
src/processor/binarystream.h \
|
||||
src/processor/binarystream.cc \
|
||||
|
@ -134,6 +136,8 @@ src_libbreakpad_a_SOURCES = \
|
|||
src/processor/simple_symbol_supplier.cc \
|
||||
src/processor/simple_symbol_supplier.h \
|
||||
src/processor/windows_frame_info.h \
|
||||
src/processor/source_line_resolver_base_types.h \
|
||||
src/processor/source_line_resolver_base.cc \
|
||||
src/processor/stackwalker.cc \
|
||||
src/processor/stackwalker_amd64.cc \
|
||||
src/processor/stackwalker_amd64.h \
|
||||
|
@ -322,6 +326,7 @@ src_processor_basic_source_line_resolver_unittest_LDADD = \
|
|||
src/processor/cfi_frame_info.o \
|
||||
src/processor/pathname_stripper.o \
|
||||
src/processor/logging.o \
|
||||
src/processor/source_line_resolver_base.o \
|
||||
src/processor/tokenize.o
|
||||
|
||||
src_processor_cfi_frame_info_unittest_SOURCES = \
|
||||
|
@ -370,6 +375,7 @@ src_processor_exploitability_unittest_LDADD = \
|
|||
src/processor/logging.o \
|
||||
src/processor/minidump.o \
|
||||
src/processor/pathname_stripper.o \
|
||||
src/processor/source_line_resolver_base.o \
|
||||
src/processor/stackwalker.o \
|
||||
src/processor/stackwalker_amd64.o \
|
||||
src/processor/stackwalker_arm.o \
|
||||
|
@ -417,6 +423,7 @@ src_processor_minidump_processor_unittest_LDADD = \
|
|||
src/processor/minidump.o \
|
||||
src/processor/pathname_stripper.o \
|
||||
src/processor/process_state.o \
|
||||
src/processor/source_line_resolver_base.o \
|
||||
src/processor/stackwalker.o \
|
||||
src/processor/stackwalker_amd64.o \
|
||||
src/processor/stackwalker_arm.o \
|
||||
|
@ -492,6 +499,7 @@ src_processor_network_source_line_resolver_server_unittest_LDADD = \
|
|||
src/processor/pathname_stripper.o \
|
||||
src/processor/process_state.o \
|
||||
src/processor/simple_symbol_supplier.o \
|
||||
src/processor/source_line_resolver_base.o \
|
||||
src/processor/stackwalker.o \
|
||||
src/processor/stackwalker_amd64.o \
|
||||
src/processor/stackwalker_arm.o \
|
||||
|
@ -563,6 +571,7 @@ src_processor_stackwalker_selftest_LDADD = \
|
|||
src/processor/logging.o \
|
||||
src/processor/minidump.o \
|
||||
src/processor/pathname_stripper.o \
|
||||
src/processor/source_line_resolver_base.o \
|
||||
src/processor/stackwalker.o \
|
||||
src/processor/stackwalker_amd64.o \
|
||||
src/processor/stackwalker_arm.o \
|
||||
|
@ -676,6 +685,7 @@ src_processor_minidump_stackwalk_LDADD = \
|
|||
src/processor/process_state.o \
|
||||
src/processor/network_source_line_resolver.o \
|
||||
src/processor/simple_symbol_supplier.o \
|
||||
src/processor/source_line_resolver_base.o \
|
||||
src/processor/stackwalker.o \
|
||||
src/processor/stackwalker_amd64.o \
|
||||
src/processor/stackwalker_arm.o \
|
||||
|
@ -697,6 +707,7 @@ src_processor_source_daemon_LDADD = \
|
|||
src/processor/network_source_line_server.o \
|
||||
src/processor/pathname_stripper.o \
|
||||
src/processor/simple_symbol_supplier.o \
|
||||
src/processor/source_line_resolver_base.o \
|
||||
src/processor/tokenize.o \
|
||||
src/processor/udp_network.o
|
||||
endif !DISABLE_PROCESSOR
|
||||
|
|
28
Makefile.in
28
Makefile.in
|
@ -192,6 +192,7 @@ am__src_libbreakpad_a_SOURCES_DIST = \
|
|||
src/google_breakpad/processor/minidump_processor.h \
|
||||
src/google-breakpad/processor/network_source_line_resolver.h \
|
||||
src/google_breakpad/processor/process_state.h \
|
||||
src/google_breakpad/processor/source_line_resolver_base.h \
|
||||
src/google_breakpad/processor/source_line_resolver_interface.h \
|
||||
src/google_breakpad/processor/stack_frame.h \
|
||||
src/google_breakpad/processor/stack_frame_cpu.h \
|
||||
|
@ -202,6 +203,7 @@ am__src_libbreakpad_a_SOURCES_DIST = \
|
|||
src/processor/basic_code_module.h \
|
||||
src/processor/basic_code_modules.cc \
|
||||
src/processor/basic_code_modules.h \
|
||||
src/processor/basic_source_line_resolver_types.h \
|
||||
src/processor/basic_source_line_resolver.cc \
|
||||
src/processor/binarystream.h src/processor/binarystream.cc \
|
||||
src/processor/call_stack.cc src/processor/cfi_frame_info.cc \
|
||||
|
@ -228,6 +230,8 @@ am__src_libbreakpad_a_SOURCES_DIST = \
|
|||
src/processor/simple_symbol_supplier.cc \
|
||||
src/processor/simple_symbol_supplier.h \
|
||||
src/processor/windows_frame_info.h \
|
||||
src/processor/source_line_resolver_base_types.h \
|
||||
src/processor/source_line_resolver_base.cc \
|
||||
src/processor/stackwalker.cc \
|
||||
src/processor/stackwalker_amd64.cc \
|
||||
src/processor/stackwalker_amd64.h \
|
||||
|
@ -260,6 +264,7 @@ am__src_libbreakpad_a_SOURCES_DIST = \
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.$(OBJEXT) \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.$(OBJEXT) \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.$(OBJEXT) \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.$(OBJEXT) \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.$(OBJEXT) \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.$(OBJEXT) \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.$(OBJEXT) \
|
||||
|
@ -414,6 +419,7 @@ src_processor_basic_source_line_resolver_unittest_OBJECTS = $(am_src_processor_b
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o
|
||||
am__src_processor_binarystream_unittest_SOURCES_DIST = \
|
||||
src/processor/binarystream_unittest.cc \
|
||||
|
@ -487,6 +493,7 @@ src_processor_exploitability_unittest_OBJECTS = \
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||
|
@ -527,6 +534,7 @@ src_processor_minidump_processor_unittest_OBJECTS = \
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||
|
@ -556,6 +564,7 @@ src_processor_minidump_stackwalk_OBJECTS = \
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_resolver.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||
|
@ -610,6 +619,7 @@ src_processor_network_source_line_resolver_server_unittest_OBJECTS = $(am_src_pr
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||
|
@ -688,6 +698,7 @@ src_processor_source_daemon_OBJECTS = \
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_server.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/udp_network.o
|
||||
am__src_processor_stackwalker_amd64_unittest_SOURCES_DIST = \
|
||||
|
@ -735,6 +746,7 @@ src_processor_stackwalker_selftest_OBJECTS = \
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||
|
@ -1021,6 +1033,7 @@ lib_LIBRARIES = $(am__append_1) $(am__append_3)
|
|||
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/minidump_processor.h \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/google-breakpad/processor/network_source_line_resolver.h \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/process_state.h \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/source_line_resolver_base.h \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/source_line_resolver_interface.h \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stack_frame.h \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stack_frame_cpu.h \
|
||||
|
@ -1032,6 +1045,7 @@ lib_LIBRARIES = $(am__append_1) $(am__append_3)
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_module.h \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.cc \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.h \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver_types.h \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.cc \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.h \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.cc \
|
||||
|
@ -1065,6 +1079,8 @@ lib_LIBRARIES = $(am__append_1) $(am__append_3)
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.cc \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.h \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/windows_frame_info.h \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base_types.h \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.cc \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.cc \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.cc \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.h \
|
||||
|
@ -1201,6 +1217,7 @@ TESTS_ENVIRONMENT =
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o
|
||||
|
||||
@DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_SOURCES = \
|
||||
|
@ -1254,6 +1271,7 @@ TESTS_ENVIRONMENT =
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||
|
@ -1305,6 +1323,7 @@ TESTS_ENVIRONMENT =
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||
|
@ -1386,6 +1405,7 @@ TESTS_ENVIRONMENT =
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||
|
@ -1465,6 +1485,7 @@ TESTS_ENVIRONMENT =
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||
|
@ -1585,6 +1606,7 @@ TESTS_ENVIRONMENT =
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_resolver.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
|
||||
|
@ -1607,6 +1629,7 @@ TESTS_ENVIRONMENT =
|
|||
@DISABLE_PROCESSOR_FALSE@ src/processor/network_source_line_server.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
|
||||
@DISABLE_PROCESSOR_FALSE@ src/processor/udp_network.o
|
||||
|
||||
|
@ -1946,6 +1969,9 @@ src/processor/process_state.$(OBJEXT): src/processor/$(am__dirstamp) \
|
|||
src/processor/simple_symbol_supplier.$(OBJEXT): \
|
||||
src/processor/$(am__dirstamp) \
|
||||
src/processor/$(DEPDIR)/$(am__dirstamp)
|
||||
src/processor/source_line_resolver_base.$(OBJEXT): \
|
||||
src/processor/$(am__dirstamp) \
|
||||
src/processor/$(DEPDIR)/$(am__dirstamp)
|
||||
src/processor/stackwalker.$(OBJEXT): src/processor/$(am__dirstamp) \
|
||||
src/processor/$(DEPDIR)/$(am__dirstamp)
|
||||
src/processor/stackwalker_amd64.$(OBJEXT): \
|
||||
|
@ -2475,6 +2501,7 @@ mostlyclean-compile:
|
|||
-rm -f src/processor/range_map_unittest.$(OBJEXT)
|
||||
-rm -f src/processor/simple_symbol_supplier.$(OBJEXT)
|
||||
-rm -f src/processor/source_daemon.$(OBJEXT)
|
||||
-rm -f src/processor/source_line_resolver_base.$(OBJEXT)
|
||||
-rm -f src/processor/src_client_linux_linux_client_unittest-basic_code_modules.$(OBJEXT)
|
||||
-rm -f src/processor/src_client_linux_linux_client_unittest-logging.$(OBJEXT)
|
||||
-rm -f src/processor/src_client_linux_linux_client_unittest-minidump.$(OBJEXT)
|
||||
|
@ -2615,6 +2642,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/range_map_unittest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/simple_symbol_supplier.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/source_daemon.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/source_line_resolver_base.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest-basic_code_modules.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest-logging.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest-minidump.Po@am__quote@
|
||||
|
|
|
@ -27,59 +27,56 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// BasicSourceLineResolver implements SourceLineResolverInterface, using
|
||||
// address map files produced by a compatible writer, e.g. PDBSourceLineWriter.
|
||||
// basic_source_line_resolver.h: BasicSourceLineResolver is derived from
|
||||
// SourceLineResolverBase, and is a concrete implementation of
|
||||
// SourceLineResolverInterface, using address map files produced by a
|
||||
// compatible writer, e.g. PDBSourceLineWriter.
|
||||
//
|
||||
// see "processor/source_line_resolver_base.h"
|
||||
// and "source_line_resolver_interface.h" for more documentation.
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__
|
||||
#define GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "google_breakpad/processor/source_line_resolver_interface.h"
|
||||
#include "google_breakpad/processor/source_line_resolver_base.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
using std::string;
|
||||
using std::map;
|
||||
|
||||
class BasicSourceLineResolver : public SourceLineResolverInterface {
|
||||
class BasicSourceLineResolver : public SourceLineResolverBase {
|
||||
public:
|
||||
BasicSourceLineResolver();
|
||||
virtual ~BasicSourceLineResolver();
|
||||
virtual ~BasicSourceLineResolver() { }
|
||||
|
||||
// SourceLineResolverInterface methods, see source_line_resolver_interface.h
|
||||
// for more details.
|
||||
|
||||
// Adds a module to this resolver, returning true on success.
|
||||
// The given map_file is read into memory, and its symbols will be
|
||||
// retained until the BasicSourceLineResolver is destroyed.
|
||||
virtual bool LoadModule(const CodeModule *module, const string &map_file);
|
||||
|
||||
// Exactly the same as above, except the given map_buffer is used
|
||||
// for symbols.
|
||||
virtual bool LoadModuleUsingMapBuffer(const CodeModule *module,
|
||||
const string &map_buffer);
|
||||
|
||||
void UnloadModule(const CodeModule *module);
|
||||
virtual bool HasModule(const CodeModule *module);
|
||||
virtual void FillSourceLineInfo(StackFrame *frame);
|
||||
virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame);
|
||||
virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame);
|
||||
using SourceLineResolverBase::LoadModule;
|
||||
using SourceLineResolverBase::LoadModuleUsingMapBuffer;
|
||||
using SourceLineResolverBase::LoadModuleUsingMemoryBuffer;
|
||||
using SourceLineResolverBase::UnloadModule;
|
||||
using SourceLineResolverBase::HasModule;
|
||||
using SourceLineResolverBase::FillSourceLineInfo;
|
||||
using SourceLineResolverBase::FindWindowsFrameInfo;
|
||||
using SourceLineResolverBase::FindCFIFrameInfo;
|
||||
|
||||
private:
|
||||
template<class T> class MemAddrMap;
|
||||
struct Line;
|
||||
// friend declarations:
|
||||
friend class BasicModuleFactory;
|
||||
|
||||
// Function derives from SourceLineResolverBase::Function.
|
||||
struct Function;
|
||||
struct PublicSymbol;
|
||||
struct File;
|
||||
struct CompareString {
|
||||
bool operator()(const string &s1, const string &s2) const;
|
||||
};
|
||||
// Module implements SourceLineResolverBase::Module interface.
|
||||
class Module;
|
||||
|
||||
// All of the modules we've loaded
|
||||
typedef map<string, Module*, CompareString> ModuleMap;
|
||||
ModuleMap *modules_;
|
||||
// Helper method.
|
||||
virtual void DeleteDataAfterLoad(char *symbol_data);
|
||||
// No-op helper methods.
|
||||
virtual void DeleteDataUnload(const CodeModule *module) { }
|
||||
virtual void ClearLocalMemory() { }
|
||||
virtual void StoreDataBeforeLoad(const CodeModule *module,
|
||||
char *symbol_data) { }
|
||||
|
||||
// Disallow unwanted copy ctor and assignment operator
|
||||
BasicSourceLineResolver(const BasicSourceLineResolver&);
|
||||
|
|
|
@ -37,8 +37,8 @@
|
|||
// An implementation of the server side of the protocol is provided there
|
||||
// as NetworkSourceLineServer.
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_RESOLVER_H_
|
||||
#define GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_RESOLVER_H_
|
||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_RESOLVER_H__
|
||||
#define GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_RESOLVER_H__
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
|
@ -81,6 +81,8 @@ class NetworkSourceLineResolver : public SourceLineResolverInterface,
|
|||
virtual bool LoadModule(const CodeModule *module, const string &map_file);
|
||||
virtual bool LoadModuleUsingMapBuffer(const CodeModule *module,
|
||||
const string &map_buffer);
|
||||
virtual bool LoadModuleUsingMemoryBuffer(const CodeModule *module,
|
||||
char *memory_buffer);
|
||||
|
||||
void UnloadModule(const CodeModule *module);
|
||||
|
||||
|
@ -104,6 +106,11 @@ class NetworkSourceLineResolver : public SourceLineResolverInterface,
|
|||
const SystemInfo *system_info,
|
||||
string *symbol_file,
|
||||
string *symbol_data);
|
||||
// Similar as the above GetSymbolFile() method, see the comment above.
|
||||
virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
|
||||
const SystemInfo *system_info,
|
||||
string *symbol_file,
|
||||
char **symbol_data);
|
||||
|
||||
private:
|
||||
int wait_milliseconds_;
|
||||
|
@ -165,4 +172,4 @@ class NetworkSourceLineResolver : public SourceLineResolverInterface,
|
|||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_RESOLVER_H_
|
||||
#endif // GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_RESOLVER_H__
|
||||
|
|
117
src/google_breakpad/processor/source_line_resolver_base.h
Normal file
117
src/google_breakpad/processor/source_line_resolver_base.h
Normal file
|
@ -0,0 +1,117 @@
|
|||
// Copyright (c) 2010 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.
|
||||
//
|
||||
// source_line_resolver_base.h: SourceLineResolverBase, an (incomplete)
|
||||
// implementation of SourceLineResolverInterface. It serves as a common base
|
||||
// class for concrete implementations: FastSourceLineResolver and
|
||||
// BasicSourceLineResolver. It is designed for refactoring that removes
|
||||
// code redundancy in the two concrete source line resolver classes.
|
||||
//
|
||||
// See "google_breakpad/processor/source_line_resolver_interface.h" for more
|
||||
// documentation.
|
||||
|
||||
// Author: Siyang Xie (lambxsy@google.com)
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_BASE_H__
|
||||
#define GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_BASE_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "google_breakpad/processor/source_line_resolver_interface.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
using std::map;
|
||||
|
||||
// Forward declaration.
|
||||
// ModuleFactory is a simple factory interface for creating a Module instance
|
||||
// at run-time.
|
||||
class ModuleFactory;
|
||||
|
||||
class SourceLineResolverBase : public SourceLineResolverInterface {
|
||||
public:
|
||||
// Read the symbol_data from a file with given file_name.
|
||||
// The part of code was originally in BasicSourceLineResolver::Module's
|
||||
// LoadMap() method.
|
||||
static bool ReadSymbolFile(char **symbol_data, const string &file_name);
|
||||
|
||||
protected:
|
||||
// Users are not allowed create SourceLineResolverBase instance directly.
|
||||
SourceLineResolverBase(ModuleFactory *module_factory);
|
||||
virtual ~SourceLineResolverBase();
|
||||
|
||||
// Virtual methods inherited from SourceLineResolverInterface.
|
||||
virtual bool LoadModule(const CodeModule *module, const string &map_file);
|
||||
virtual bool LoadModuleUsingMapBuffer(const CodeModule *module,
|
||||
const string &map_buffer);
|
||||
virtual bool LoadModuleUsingMemoryBuffer(const CodeModule *module,
|
||||
char *memory_buffer);
|
||||
virtual void UnloadModule(const CodeModule *module);
|
||||
virtual bool HasModule(const CodeModule *module);
|
||||
virtual void FillSourceLineInfo(StackFrame *frame);
|
||||
virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame);
|
||||
virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame);
|
||||
|
||||
// Helper methods to manage C-String format symbol data.
|
||||
virtual void StoreDataBeforeLoad(const CodeModule *module, char *symbol_data);
|
||||
virtual void DeleteDataAfterLoad(char *symbol_data);
|
||||
virtual void DeleteDataUnload(const CodeModule *module);
|
||||
virtual void ClearLocalMemory();
|
||||
|
||||
// Nested structs and classes.
|
||||
struct Line;
|
||||
struct Function;
|
||||
struct PublicSymbol;
|
||||
struct CompareString {
|
||||
bool operator()(const string &s1, const string &s2) const;
|
||||
};
|
||||
// Module is an interface for an in-memory symbol file.
|
||||
class Module;
|
||||
class AutoFileCloser;
|
||||
|
||||
// All of the modules we've loaded
|
||||
typedef map<string, Module*, CompareString> ModuleMap;
|
||||
ModuleMap *modules_;
|
||||
|
||||
// Creates a concrete module at run-time.
|
||||
ModuleFactory *module_factory_;
|
||||
|
||||
private:
|
||||
// ModuleFactory needs to have access to protected type Module.
|
||||
friend class ModuleFactory;
|
||||
|
||||
// Disallow unwanted copy ctor and assignment operator
|
||||
SourceLineResolverBase(const SourceLineResolverBase&);
|
||||
void operator=(const SourceLineResolverBase&);
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_BASE_H__
|
|
@ -64,6 +64,12 @@ class SourceLineResolverInterface {
|
|||
virtual bool LoadModuleUsingMapBuffer(const CodeModule *module,
|
||||
const string &map_buffer) = 0;
|
||||
|
||||
// Add an interface to load symbol using C-String data insteading string.
|
||||
// This is useful in the optimization design for avoiding unnecessary copying
|
||||
// of symbol data, in order to improve memory efficiency.
|
||||
virtual bool LoadModuleUsingMemoryBuffer(const CodeModule *module,
|
||||
char *memory_buffer) = 0;
|
||||
|
||||
// Request that the specified module be unloaded from this resolver.
|
||||
// A resolver may choose to ignore such a request.
|
||||
virtual void UnloadModule(const CodeModule *module) = 0;
|
||||
|
|
|
@ -75,6 +75,15 @@ class SymbolSupplier {
|
|||
const SystemInfo *system_info,
|
||||
string *symbol_file,
|
||||
string *symbol_data) = 0;
|
||||
|
||||
// Same as above, except places symbol data into symbol_data as C-string in
|
||||
// dynamically allocated memory. Using C-string as type of symbol data enables
|
||||
// passing data by pointer, and thus avoids unncessary copying of data (to
|
||||
// improve memory efficiency).
|
||||
virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
|
||||
const SystemInfo *system_info,
|
||||
string *symbol_file,
|
||||
char **symbol_data) = 0;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
|
|
@ -26,6 +26,12 @@
|
|||
// 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.
|
||||
//
|
||||
// basic_source_line_resolver.cc: BasicSourceLineResolver implementation.
|
||||
//
|
||||
// See basic_source_line_resolver.h and basic_source_line_resolver_types.h
|
||||
// for documentation.
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -37,17 +43,10 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "processor/address_map-inl.h"
|
||||
#include "processor/contained_range_map-inl.h"
|
||||
#include "processor/range_map-inl.h"
|
||||
|
||||
#include "google_breakpad/processor/basic_source_line_resolver.h"
|
||||
#include "google_breakpad/processor/code_module.h"
|
||||
#include "google_breakpad/processor/stack_frame.h"
|
||||
#include "processor/cfi_frame_info.h"
|
||||
#include "processor/linked_ptr.h"
|
||||
#include "processor/scoped_ptr.h"
|
||||
#include "processor/windows_frame_info.h"
|
||||
#include "processor/basic_source_line_resolver_types.h"
|
||||
#include "processor/module_factory.h"
|
||||
|
||||
#include "processor/tokenize.h"
|
||||
|
||||
using std::map;
|
||||
|
@ -58,299 +57,33 @@ namespace google_breakpad {
|
|||
|
||||
static const char *kWhitespace = " \r\n";
|
||||
|
||||
struct BasicSourceLineResolver::Line {
|
||||
Line(MemAddr addr, MemAddr code_size, int file_id, int source_line)
|
||||
: address(addr)
|
||||
, size(code_size)
|
||||
, source_file_id(file_id)
|
||||
, line(source_line) { }
|
||||
BasicSourceLineResolver::BasicSourceLineResolver() :
|
||||
SourceLineResolverBase(new BasicModuleFactory) { }
|
||||
|
||||
MemAddr address;
|
||||
MemAddr size;
|
||||
int source_file_id;
|
||||
int line;
|
||||
};
|
||||
|
||||
struct BasicSourceLineResolver::Function {
|
||||
Function(const string &function_name,
|
||||
MemAddr function_address,
|
||||
MemAddr code_size,
|
||||
int set_parameter_size)
|
||||
: name(function_name), address(function_address), size(code_size),
|
||||
parameter_size(set_parameter_size) { }
|
||||
|
||||
string name;
|
||||
MemAddr address;
|
||||
MemAddr size;
|
||||
|
||||
// The size of parameters passed to this function on the stack.
|
||||
int parameter_size;
|
||||
|
||||
RangeMap< MemAddr, linked_ptr<Line> > lines;
|
||||
};
|
||||
|
||||
struct BasicSourceLineResolver::PublicSymbol {
|
||||
PublicSymbol(const string& set_name,
|
||||
MemAddr set_address,
|
||||
int set_parameter_size)
|
||||
: name(set_name),
|
||||
address(set_address),
|
||||
parameter_size(set_parameter_size) {}
|
||||
|
||||
string name;
|
||||
MemAddr address;
|
||||
|
||||
// If the public symbol is used as a function entry point, parameter_size
|
||||
// is set to the size of the parameters passed to the funciton on the
|
||||
// stack, if known.
|
||||
int parameter_size;
|
||||
};
|
||||
|
||||
class BasicSourceLineResolver::Module {
|
||||
public:
|
||||
Module(const string &name) : name_(name) { }
|
||||
|
||||
// Loads the given map file, returning true on success. Reads the
|
||||
// map file into memory and calls LoadMapFromBuffer
|
||||
bool LoadMap(const string &map_file);
|
||||
|
||||
// Loads a map from the given buffer, returning true on success
|
||||
bool LoadMapFromBuffer(const string &map_buffer);
|
||||
|
||||
// Looks up the given relative address, and fills the StackFrame struct
|
||||
// with the result.
|
||||
void LookupAddress(StackFrame *frame) const;
|
||||
|
||||
// If Windows stack walking information is available covering ADDRESS,
|
||||
// return a WindowsFrameInfo structure describing it. If the information
|
||||
// is not available, returns NULL. A NULL return value does not indicate
|
||||
// an error. The caller takes ownership of any returned WindowsFrameInfo
|
||||
// object.
|
||||
WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame) const;
|
||||
|
||||
// If CFI stack walking information is available covering ADDRESS,
|
||||
// return a CFIFrameInfo structure describing it. If the information
|
||||
// is not available, return NULL. The caller takes ownership of any
|
||||
// returned CFIFrameInfo object.
|
||||
CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame) const;
|
||||
|
||||
private:
|
||||
friend class BasicSourceLineResolver;
|
||||
typedef map<int, string> FileMap;
|
||||
|
||||
// Parses a file declaration
|
||||
bool ParseFile(char *file_line);
|
||||
|
||||
// Parses a function declaration, returning a new Function object.
|
||||
Function* ParseFunction(char *function_line);
|
||||
|
||||
// Parses a line declaration, returning a new Line object.
|
||||
Line* ParseLine(char *line_line);
|
||||
|
||||
// Parses a PUBLIC symbol declaration, storing it in public_symbols_.
|
||||
// Returns false if an error occurs.
|
||||
bool ParsePublicSymbol(char *public_line);
|
||||
|
||||
// Parses a STACK WIN or STACK CFI frame info declaration, storing
|
||||
// it in the appropriate table.
|
||||
bool ParseStackInfo(char *stack_info_line);
|
||||
|
||||
// Parses a STACK CFI record, storing it in cfi_frame_info_.
|
||||
bool ParseCFIFrameInfo(char *stack_info_line);
|
||||
|
||||
// Parse RULE_SET, a series of rules of the sort appearing in STACK
|
||||
// CFI records, and store the given rules in FRAME_INFO.
|
||||
bool ParseCFIRuleSet(const string &rule_set, CFIFrameInfo *frame_info) const;
|
||||
|
||||
string name_;
|
||||
FileMap files_;
|
||||
RangeMap< MemAddr, linked_ptr<Function> > functions_;
|
||||
AddressMap< MemAddr, linked_ptr<PublicSymbol> > public_symbols_;
|
||||
|
||||
// Each element in the array is a ContainedRangeMap for a type
|
||||
// listed in WindowsFrameInfoTypes. These are split by type because
|
||||
// there may be overlaps between maps of different types, but some
|
||||
// information is only available as certain types.
|
||||
ContainedRangeMap< MemAddr, linked_ptr<WindowsFrameInfo> >
|
||||
windows_frame_info_[WindowsFrameInfo::STACK_INFO_LAST];
|
||||
|
||||
// DWARF CFI stack walking data. The Module stores the initial rule sets
|
||||
// and rule deltas as strings, just as they appear in the symbol file:
|
||||
// although the file may contain hundreds of thousands of STACK CFI
|
||||
// records, walking a stack will only ever use a few of them, so it's
|
||||
// best to delay parsing a record until it's actually needed.
|
||||
|
||||
// STACK CFI INIT records: for each range, an initial set of register
|
||||
// recovery rules. The RangeMap's itself gives the starting and ending
|
||||
// addresses.
|
||||
RangeMap<MemAddr, string> cfi_initial_rules_;
|
||||
|
||||
// STACK CFI records: at a given address, the changes to the register
|
||||
// recovery rules that take effect at that address. The map key is the
|
||||
// starting address; the ending address is the key of the next entry in
|
||||
// this map, or the end of the range as given by the cfi_initial_rules_
|
||||
// entry (which FindCFIFrameInfo looks up first).
|
||||
map<MemAddr, string> cfi_delta_rules_;
|
||||
};
|
||||
|
||||
BasicSourceLineResolver::BasicSourceLineResolver() : modules_(new ModuleMap) {
|
||||
void BasicSourceLineResolver::DeleteDataAfterLoad(char *symbol_data) {
|
||||
// Always delete allocated memory after loading symbol.
|
||||
delete symbol_data;
|
||||
}
|
||||
|
||||
BasicSourceLineResolver::~BasicSourceLineResolver() {
|
||||
ModuleMap::iterator it;
|
||||
for (it = modules_->begin(); it != modules_->end(); ++it) {
|
||||
delete it->second;
|
||||
}
|
||||
delete modules_;
|
||||
}
|
||||
|
||||
bool BasicSourceLineResolver::LoadModule(const CodeModule *module,
|
||||
const string &map_file) {
|
||||
if (module == NULL)
|
||||
return false;
|
||||
|
||||
// Make sure we don't already have a module with the given name.
|
||||
if (modules_->find(module->code_file()) != modules_->end()) {
|
||||
BPLOG(INFO) << "Symbols for module " << module->code_file()
|
||||
<< " already loaded";
|
||||
return false;
|
||||
}
|
||||
|
||||
BPLOG(INFO) << "Loading symbols for module " << module->code_file()
|
||||
<< " from " << map_file;
|
||||
|
||||
Module *basic_module = new Module(module->code_file());
|
||||
if (!basic_module->LoadMap(map_file)) {
|
||||
delete basic_module;
|
||||
return false;
|
||||
}
|
||||
|
||||
modules_->insert(make_pair(module->code_file(), basic_module));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BasicSourceLineResolver::LoadModuleUsingMapBuffer(
|
||||
const CodeModule *module,
|
||||
const string &map_buffer) {
|
||||
if (!module)
|
||||
return false;
|
||||
|
||||
// Make sure we don't already have a module with the given name.
|
||||
if (modules_->find(module->code_file()) != modules_->end()) {
|
||||
BPLOG(INFO) << "Symbols for module " << module->code_file()
|
||||
<< " already loaded";
|
||||
return false;
|
||||
}
|
||||
|
||||
BPLOG(INFO) << "Loading symbols for module " << module->code_file()
|
||||
<< " from buffer";
|
||||
|
||||
Module *basic_module = new Module(module->code_file());
|
||||
if (!basic_module->LoadMapFromBuffer(map_buffer)) {
|
||||
delete basic_module;
|
||||
return false;
|
||||
}
|
||||
|
||||
modules_->insert(make_pair(module->code_file(), basic_module));
|
||||
return true;
|
||||
}
|
||||
|
||||
void BasicSourceLineResolver::UnloadModule(const CodeModule *module)
|
||||
{
|
||||
if (!module)
|
||||
return;
|
||||
|
||||
ModuleMap::iterator iter = modules_->find(module->code_file());
|
||||
if (iter != modules_->end()) {
|
||||
Module *basic_module = iter->second;
|
||||
modules_->erase(iter);
|
||||
delete basic_module;
|
||||
}
|
||||
}
|
||||
|
||||
bool BasicSourceLineResolver::HasModule(const CodeModule *module) {
|
||||
if (!module)
|
||||
return false;
|
||||
return modules_->find(module->code_file()) != modules_->end();
|
||||
}
|
||||
|
||||
void BasicSourceLineResolver::FillSourceLineInfo(StackFrame *frame) {
|
||||
if (frame->module) {
|
||||
ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
|
||||
if (it != modules_->end()) {
|
||||
it->second->LookupAddress(frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WindowsFrameInfo *BasicSourceLineResolver::FindWindowsFrameInfo(
|
||||
const StackFrame *frame) {
|
||||
if (frame->module) {
|
||||
ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
|
||||
if (it != modules_->end()) {
|
||||
return it->second->FindWindowsFrameInfo(frame);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CFIFrameInfo *BasicSourceLineResolver::FindCFIFrameInfo(
|
||||
const StackFrame *frame) {
|
||||
if (frame->module) {
|
||||
ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
|
||||
if (it != modules_->end()) {
|
||||
return it->second->FindCFIFrameInfo(frame);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
class AutoFileCloser {
|
||||
public:
|
||||
AutoFileCloser(FILE *file) : file_(file) {}
|
||||
~AutoFileCloser() {
|
||||
if (file_)
|
||||
fclose(file_);
|
||||
}
|
||||
|
||||
private:
|
||||
FILE *file_;
|
||||
};
|
||||
|
||||
bool BasicSourceLineResolver::Module::LoadMapFromBuffer(
|
||||
const string &map_buffer) {
|
||||
bool BasicSourceLineResolver::Module::LoadMapFromMemory(char *memory_buffer) {
|
||||
linked_ptr<Function> cur_func;
|
||||
int line_number = 0;
|
||||
const char *map_buffer_c_str = map_buffer.c_str();
|
||||
char *save_ptr;
|
||||
|
||||
// set up our input buffer as a c-style string so we
|
||||
// can we use strtok()
|
||||
// have to copy because modifying the result of string::c_str is not
|
||||
// permitted
|
||||
size_t map_buffer_length = strlen(map_buffer_c_str);
|
||||
size_t map_buffer_length = strlen(memory_buffer);
|
||||
|
||||
// If the length is 0, we can still pretend we have a symbol file. This is
|
||||
// for scenarios that want to test symbol lookup, but don't necessarily care if
|
||||
// certain modules do not have any information, like system libraries.
|
||||
// for scenarios that want to test symbol lookup, but don't necessarily care
|
||||
// if certain modules do not have any information, like system libraries.
|
||||
if (map_buffer_length == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
scoped_array<char> map_buffer_chars(new char[map_buffer_length]);
|
||||
if (map_buffer_chars == NULL) {
|
||||
BPLOG(ERROR) << "Memory allocation of " << map_buffer_length <<
|
||||
" bytes failed";
|
||||
return false;
|
||||
if (memory_buffer[map_buffer_length - 1] == '\n') {
|
||||
memory_buffer[map_buffer_length - 1] = '\0';
|
||||
}
|
||||
|
||||
strncpy(map_buffer_chars.get(), map_buffer_c_str, map_buffer_length);
|
||||
|
||||
if (map_buffer_chars[map_buffer_length - 1] == '\n') {
|
||||
map_buffer_chars[map_buffer_length - 1] = '\0';
|
||||
}
|
||||
char *buffer;
|
||||
buffer = strtok_r(map_buffer_chars.get(), "\r\n", &save_ptr);
|
||||
buffer = strtok_r(memory_buffer, "\r\n", &save_ptr);
|
||||
|
||||
while (buffer != NULL) {
|
||||
++line_number;
|
||||
|
@ -413,68 +146,11 @@ bool BasicSourceLineResolver::Module::LoadMapFromBuffer(
|
|||
cur_func->lines.StoreRange(line->address, line->size,
|
||||
linked_ptr<Line>(line));
|
||||
}
|
||||
|
||||
buffer = strtok_r(NULL, "\r\n", &save_ptr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BasicSourceLineResolver::Module::LoadMap(const string &map_file) {
|
||||
struct stat buf;
|
||||
int error_code = stat(map_file.c_str(), &buf);
|
||||
if (error_code == -1) {
|
||||
string error_string;
|
||||
int error_code = ErrnoString(&error_string);
|
||||
BPLOG(ERROR) << "Could not open " << map_file <<
|
||||
", error " << error_code << ": " << error_string;
|
||||
return false;
|
||||
}
|
||||
|
||||
off_t file_size = buf.st_size;
|
||||
|
||||
// Allocate memory for file contents, plus a null terminator
|
||||
// since we'll use strtok() on the contents.
|
||||
char *file_buffer = new char[sizeof(char)*file_size + 1];
|
||||
|
||||
if (file_buffer == NULL) {
|
||||
BPLOG(ERROR) << "Could not allocate memory for " << map_file;
|
||||
return false;
|
||||
}
|
||||
|
||||
BPLOG(INFO) << "Opening " << map_file;
|
||||
|
||||
FILE *f = fopen(map_file.c_str(), "rt");
|
||||
if (!f) {
|
||||
string error_string;
|
||||
int error_code = ErrnoString(&error_string);
|
||||
BPLOG(ERROR) << "Could not open " << map_file <<
|
||||
", error " << error_code << ": " << error_string;
|
||||
delete [] file_buffer;
|
||||
return false;
|
||||
}
|
||||
|
||||
AutoFileCloser closer(f);
|
||||
|
||||
int items_read = 0;
|
||||
|
||||
items_read = fread(file_buffer, 1, file_size, f);
|
||||
|
||||
if (items_read != file_size) {
|
||||
string error_string;
|
||||
int error_code = ErrnoString(&error_string);
|
||||
BPLOG(ERROR) << "Could not slurp " << map_file <<
|
||||
", error " << error_code << ": " << error_string;
|
||||
delete [] file_buffer;
|
||||
return false;
|
||||
}
|
||||
file_buffer[file_size] = '\0';
|
||||
string map_buffer(file_buffer);
|
||||
delete [] file_buffer;
|
||||
|
||||
return LoadMapFromBuffer(map_buffer);
|
||||
}
|
||||
|
||||
void BasicSourceLineResolver::Module::LookupAddress(StackFrame *frame) const {
|
||||
MemAddr address = frame->instruction - frame->module->base_address();
|
||||
|
||||
|
@ -543,7 +219,7 @@ WindowsFrameInfo *BasicSourceLineResolver::Module::FindWindowsFrameInfo(
|
|||
linked_ptr<Function> function;
|
||||
MemAddr function_base, function_size;
|
||||
if (functions_.RetrieveNearestRange(address, &function,
|
||||
&function_base, &function_size) &&
|
||||
&function_base, &function_size) &&
|
||||
address >= function_base && address - function_base < function_size) {
|
||||
result->parameter_size = function->parameter_size;
|
||||
result->valid |= WindowsFrameInfo::VALID_PARAMETER_SIZE;
|
||||
|
@ -558,7 +234,7 @@ WindowsFrameInfo *BasicSourceLineResolver::Module::FindWindowsFrameInfo(
|
|||
(!function.get() || public_address > function_base)) {
|
||||
result->parameter_size = public_symbol->parameter_size;
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -596,13 +272,6 @@ CFIFrameInfo *BasicSourceLineResolver::Module::FindCFIFrameInfo(
|
|||
return rules.release();
|
||||
}
|
||||
|
||||
bool BasicSourceLineResolver::Module::ParseCFIRuleSet(
|
||||
const string &rule_set, CFIFrameInfo *frame_info) const {
|
||||
CFIFrameInfoParseHandler handler(frame_info);
|
||||
CFIRuleParser parser(&handler);
|
||||
return parser.Parse(rule_set);
|
||||
}
|
||||
|
||||
bool BasicSourceLineResolver::Module::ParseFile(char *file_line) {
|
||||
// FILE <id> <filename>
|
||||
file_line += 5; // skip prefix
|
||||
|
@ -762,7 +431,7 @@ bool BasicSourceLineResolver::Module::ParseCFIFrameInfo(
|
|||
// This record has the form "STACK INIT <address> <size> <rules...>".
|
||||
char *address_field = strtok_r(NULL, " \r\n", &cursor);
|
||||
if (!address_field) return false;
|
||||
|
||||
|
||||
char *size_field = strtok_r(NULL, " \r\n", &cursor);
|
||||
if (!size_field) return false;
|
||||
|
||||
|
@ -784,9 +453,4 @@ bool BasicSourceLineResolver::Module::ParseCFIFrameInfo(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BasicSourceLineResolver::CompareString::operator()(
|
||||
const string &s1, const string &s2) const {
|
||||
return strcmp(s1.c_str(), s2.c_str()) < 0;
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
|
159
src/processor/basic_source_line_resolver_types.h
Normal file
159
src/processor/basic_source_line_resolver_types.h
Normal file
|
@ -0,0 +1,159 @@
|
|||
// Copyright (c) 2010 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.
|
||||
//
|
||||
// basic_source_line_types.h: definition of nested classes/structs in
|
||||
// BasicSourceLineResolver. It moves the definitions out of
|
||||
// basic_source_line_resolver.cc, so that other classes could have access
|
||||
// to these private nested types without including basic_source_line_resolver.cc
|
||||
//
|
||||
// Author: Siyang Xie (lambxsy@google.com)
|
||||
|
||||
#ifndef PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_TYPES_H__
|
||||
#define PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_TYPES_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "google_breakpad/processor/basic_source_line_resolver.h"
|
||||
#include "processor/source_line_resolver_base_types.h"
|
||||
|
||||
#include "processor/address_map-inl.h"
|
||||
#include "processor/range_map-inl.h"
|
||||
#include "processor/contained_range_map-inl.h"
|
||||
|
||||
#include "processor/linked_ptr.h"
|
||||
#include "processor/scoped_ptr.h"
|
||||
#include "google_breakpad/processor/stack_frame.h"
|
||||
#include "processor/cfi_frame_info.h"
|
||||
#include "processor/windows_frame_info.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
struct
|
||||
BasicSourceLineResolver::Function : public SourceLineResolverBase::Function {
|
||||
Function(const string &function_name,
|
||||
MemAddr function_address,
|
||||
MemAddr code_size,
|
||||
int set_parameter_size) : Base(function_name,
|
||||
function_address,
|
||||
code_size,
|
||||
set_parameter_size),
|
||||
lines() { }
|
||||
RangeMap< MemAddr, linked_ptr<Line> > lines;
|
||||
private:
|
||||
typedef SourceLineResolverBase::Function Base;
|
||||
};
|
||||
|
||||
|
||||
class BasicSourceLineResolver::Module : public SourceLineResolverBase::Module {
|
||||
public:
|
||||
explicit Module(const string &name) : name_(name) { }
|
||||
virtual ~Module() { }
|
||||
|
||||
// Loads a map from the given buffer in char* type.
|
||||
// Does NOT have ownership of memory_buffer.
|
||||
virtual bool LoadMapFromMemory(char *memory_buffer);
|
||||
|
||||
// Looks up the given relative address, and fills the StackFrame struct
|
||||
// with the result.
|
||||
virtual void LookupAddress(StackFrame *frame) const;
|
||||
|
||||
// If Windows stack walking information is available covering ADDRESS,
|
||||
// return a WindowsFrameInfo structure describing it. If the information
|
||||
// is not available, returns NULL. A NULL return value does not indicate
|
||||
// an error. The caller takes ownership of any returned WindowsFrameInfo
|
||||
// object.
|
||||
virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame) const;
|
||||
|
||||
// If CFI stack walking information is available covering ADDRESS,
|
||||
// return a CFIFrameInfo structure describing it. If the information
|
||||
// is not available, return NULL. The caller takes ownership of any
|
||||
// returned CFIFrameInfo object.
|
||||
virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame) const;
|
||||
|
||||
private:
|
||||
// Friend declarations.
|
||||
friend class BasicSourceLineResolver;
|
||||
|
||||
typedef std::map<int, string> FileMap;
|
||||
|
||||
// Parses a file declaration
|
||||
bool ParseFile(char *file_line);
|
||||
|
||||
// Parses a function declaration, returning a new Function object.
|
||||
Function* ParseFunction(char *function_line);
|
||||
|
||||
// Parses a line declaration, returning a new Line object.
|
||||
Line* ParseLine(char *line_line);
|
||||
|
||||
// Parses a PUBLIC symbol declaration, storing it in public_symbols_.
|
||||
// Returns false if an error occurs.
|
||||
bool ParsePublicSymbol(char *public_line);
|
||||
|
||||
// Parses a STACK WIN or STACK CFI frame info declaration, storing
|
||||
// it in the appropriate table.
|
||||
bool ParseStackInfo(char *stack_info_line);
|
||||
|
||||
// Parses a STACK CFI record, storing it in cfi_frame_info_.
|
||||
bool ParseCFIFrameInfo(char *stack_info_line);
|
||||
|
||||
string name_;
|
||||
FileMap files_;
|
||||
RangeMap< MemAddr, linked_ptr<Function> > functions_;
|
||||
AddressMap< MemAddr, linked_ptr<PublicSymbol> > public_symbols_;
|
||||
|
||||
// Each element in the array is a ContainedRangeMap for a type
|
||||
// listed in WindowsFrameInfoTypes. These are split by type because
|
||||
// there may be overlaps between maps of different types, but some
|
||||
// information is only available as certain types.
|
||||
ContainedRangeMap< MemAddr, linked_ptr<WindowsFrameInfo> >
|
||||
windows_frame_info_[WindowsFrameInfo::STACK_INFO_LAST];
|
||||
|
||||
// DWARF CFI stack walking data. The Module stores the initial rule sets
|
||||
// and rule deltas as strings, just as they appear in the symbol file:
|
||||
// although the file may contain hundreds of thousands of STACK CFI
|
||||
// records, walking a stack will only ever use a few of them, so it's
|
||||
// best to delay parsing a record until it's actually needed.
|
||||
|
||||
// STACK CFI INIT records: for each range, an initial set of register
|
||||
// recovery rules. The RangeMap's itself gives the starting and ending
|
||||
// addresses.
|
||||
RangeMap<MemAddr, string> cfi_initial_rules_;
|
||||
|
||||
// STACK CFI records: at a given address, the changes to the register
|
||||
// recovery rules that take effect at that address. The map key is the
|
||||
// starting address; the ending address is the key of the next entry in
|
||||
// this map, or the end of the range as given by the cfi_initial_rules_
|
||||
// entry (which FindCFIFrameInfo looks up first).
|
||||
std::map<MemAddr, string> cfi_delta_rules_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_TYPES_H__
|
|
@ -93,6 +93,11 @@ class TestSymbolSupplier : public SymbolSupplier {
|
|||
string *symbol_file,
|
||||
string *symbol_data);
|
||||
|
||||
virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
|
||||
const SystemInfo *system_info,
|
||||
string *symbol_file,
|
||||
char **symbol_data);
|
||||
|
||||
// When set to true, causes the SymbolSupplier to return INTERRUPT
|
||||
void set_interrupt(bool interrupt) { interrupt_ = interrupt; }
|
||||
|
||||
|
@ -112,6 +117,14 @@ SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile(
|
|||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
SymbolSupplier::SymbolResult TestSymbolSupplier::GetCStringSymbolData(
|
||||
const CodeModule *module,
|
||||
const SystemInfo *system_info,
|
||||
string *symbol_file,
|
||||
char **symbol_data) {
|
||||
return GetSymbolFile(module, system_info, symbol_file);
|
||||
}
|
||||
|
||||
SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile(
|
||||
const CodeModule *module,
|
||||
const SystemInfo *system_info,
|
||||
|
|
|
@ -113,6 +113,11 @@ class TestSymbolSupplier : public SymbolSupplier {
|
|||
string *symbol_file,
|
||||
string *symbol_data);
|
||||
|
||||
virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
|
||||
const SystemInfo *system_info,
|
||||
string *symbol_file,
|
||||
char **symbol_data);
|
||||
|
||||
// When set to true, causes the SymbolSupplier to return INTERRUPT
|
||||
void set_interrupt(bool interrupt) { interrupt_ = interrupt; }
|
||||
|
||||
|
@ -164,6 +169,25 @@ SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile(
|
|||
return s;
|
||||
}
|
||||
|
||||
SymbolSupplier::SymbolResult TestSymbolSupplier::GetCStringSymbolData(
|
||||
const CodeModule *module,
|
||||
const SystemInfo *system_info,
|
||||
string *symbol_file,
|
||||
char **symbol_data) {
|
||||
string symbol_data_string;
|
||||
SymbolSupplier::SymbolResult s = GetSymbolFile(module,
|
||||
system_info,
|
||||
symbol_file,
|
||||
&symbol_data_string);
|
||||
if (s == FOUND) {
|
||||
unsigned int size = symbol_data_string.size() + 1;
|
||||
*symbol_data = reinterpret_cast<char*>(operator new(size));
|
||||
strcpy(*symbol_data, symbol_data_string.c_str());
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
// A mock symbol supplier that always returns NOT_FOUND; one current
|
||||
// use for testing the processor's caching of symbol lookups.
|
||||
class MockSymbolSupplier : public SymbolSupplier {
|
||||
|
@ -176,6 +200,10 @@ class MockSymbolSupplier : public SymbolSupplier {
|
|||
const SystemInfo*,
|
||||
string*,
|
||||
string*));
|
||||
MOCK_METHOD4(GetCStringSymbolData, SymbolResult(const CodeModule*,
|
||||
const SystemInfo*,
|
||||
string*,
|
||||
char**));
|
||||
};
|
||||
|
||||
class MinidumpProcessorTest : public ::testing::Test {
|
||||
|
@ -217,11 +245,11 @@ TEST_F(MinidumpProcessorTest, TestSymbolSupplierLookupCounts) {
|
|||
string minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") +
|
||||
"/src/processor/testdata/minidump2.dmp";
|
||||
ProcessState state;
|
||||
EXPECT_CALL(supplier, GetSymbolFile(
|
||||
EXPECT_CALL(supplier, GetCStringSymbolData(
|
||||
Property(&google_breakpad::CodeModule::code_file,
|
||||
"c:\\test_app.exe"),
|
||||
_, _, _)).WillOnce(Return(SymbolSupplier::NOT_FOUND));
|
||||
EXPECT_CALL(supplier, GetSymbolFile(
|
||||
EXPECT_CALL(supplier, GetCStringSymbolData(
|
||||
Property(&google_breakpad::CodeModule::code_file,
|
||||
Ne("c:\\test_app.exe")),
|
||||
_, _, _)).WillRepeatedly(Return(SymbolSupplier::NOT_FOUND));
|
||||
|
@ -232,11 +260,11 @@ TEST_F(MinidumpProcessorTest, TestSymbolSupplierLookupCounts) {
|
|||
|
||||
// We need to verify that across minidumps, the processor will refetch
|
||||
// symbol files, even with the same symbol supplier.
|
||||
EXPECT_CALL(supplier, GetSymbolFile(
|
||||
EXPECT_CALL(supplier, GetCStringSymbolData(
|
||||
Property(&google_breakpad::CodeModule::code_file,
|
||||
"c:\\test_app.exe"),
|
||||
_, _, _)).WillOnce(Return(SymbolSupplier::NOT_FOUND));
|
||||
EXPECT_CALL(supplier, GetSymbolFile(
|
||||
EXPECT_CALL(supplier, GetCStringSymbolData(
|
||||
Property(&google_breakpad::CodeModule::code_file,
|
||||
Ne("c:\\test_app.exe")),
|
||||
_, _, _)).WillRepeatedly(Return(SymbolSupplier::NOT_FOUND));
|
||||
|
|
62
src/processor/module_factory.h
Normal file
62
src/processor/module_factory.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) 2010 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.
|
||||
//
|
||||
// module_factory.h: ModuleFactory a factory that provides
|
||||
// an interface for creating a Module and deferring instantiation to subclasses
|
||||
// BasicModuleFactory and FastModuleFactory.
|
||||
|
||||
// Author: Siyang Xie (lambxsy@google.com)
|
||||
|
||||
#ifndef PROCESSOR_MODULE_FACTORY_H__
|
||||
#define PROCESSOR_MODULE_FACTORY_H__
|
||||
|
||||
#include "processor/source_line_resolver_base_types.h"
|
||||
#include "processor/basic_source_line_resolver_types.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
class ModuleFactory {
|
||||
public:
|
||||
virtual ~ModuleFactory() { };
|
||||
virtual SourceLineResolverBase::Module*
|
||||
CreateModule(const string &name) const = 0;
|
||||
};
|
||||
|
||||
class BasicModuleFactory : public ModuleFactory {
|
||||
public:
|
||||
virtual ~BasicModuleFactory() { }
|
||||
virtual BasicSourceLineResolver::Module*
|
||||
CreateModule(const string &name) const {
|
||||
return new BasicSourceLineResolver::Module(name);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // PROCESSOR_MODULE_FACTORY_H__
|
|
@ -97,6 +97,13 @@ bool NetworkSourceLineResolver::LoadModuleUsingMapBuffer(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetworkSourceLineResolver::LoadModuleUsingMemoryBuffer(
|
||||
const CodeModule *module,
|
||||
char *memory_buffer) {
|
||||
// see above
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetworkSourceLineResolver::UnloadModule(const CodeModule *module) {
|
||||
// no-op
|
||||
}
|
||||
|
@ -331,6 +338,18 @@ NetworkSourceLineResolver::GetSymbolFile(const CodeModule *module,
|
|||
return GetSymbolFile(module, system_info, symbol_file);
|
||||
}
|
||||
|
||||
SymbolSupplier::SymbolResult
|
||||
NetworkSourceLineResolver::GetCStringSymbolData(
|
||||
const CodeModule *module,
|
||||
const SystemInfo *system_info,
|
||||
string *symbol_file,
|
||||
char **symbol_data) {
|
||||
if (symbol_data)
|
||||
delete *symbol_data;
|
||||
|
||||
return GetSymbolFile(module, system_info, symbol_file);
|
||||
}
|
||||
|
||||
bool NetworkSourceLineResolver::SendMessageGetResponse(
|
||||
const binarystream &message,
|
||||
binarystream &response) {
|
||||
|
|
|
@ -89,6 +89,10 @@ public:
|
|||
const SystemInfo *system_info,
|
||||
string *symbol_file,
|
||||
string *symbol_data));
|
||||
MOCK_METHOD4(GetCStringSymbolData, SymbolResult(const CodeModule *module,
|
||||
const SystemInfo *system_info,
|
||||
string *symbol_file,
|
||||
char **symbol_data));
|
||||
};
|
||||
|
||||
class MockSourceLineResolver : public SourceLineResolverInterface {
|
||||
|
@ -100,6 +104,8 @@ class MockSourceLineResolver : public SourceLineResolverInterface {
|
|||
const string &map_file));
|
||||
MOCK_METHOD2(LoadModuleUsingMapBuffer, bool(const CodeModule *module,
|
||||
const string &map_buffer));
|
||||
MOCK_METHOD2(LoadModuleUsingMemoryBuffer, bool(const CodeModule *module,
|
||||
char *memory_buffer));
|
||||
MOCK_METHOD1(UnloadModule, void(const CodeModule *module));
|
||||
MOCK_METHOD1(HasModule, bool(const CodeModule *module));
|
||||
MOCK_METHOD1(FillSourceLineInfo, void(StackFrame *frame));
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "processor/simple_symbol_supplier.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
@ -93,6 +94,26 @@ SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFile(
|
|||
return s;
|
||||
}
|
||||
|
||||
SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetCStringSymbolData(
|
||||
const CodeModule *module,
|
||||
const SystemInfo *system_info,
|
||||
string *symbol_file,
|
||||
char **symbol_data) {
|
||||
assert(symbol_data);
|
||||
|
||||
string symbol_data_string;
|
||||
SymbolSupplier::SymbolResult s =
|
||||
GetSymbolFile(module, system_info, symbol_file, &symbol_data_string);
|
||||
|
||||
if (s == FOUND) {
|
||||
unsigned int size = symbol_data_string.size() + 1;
|
||||
*symbol_data = reinterpret_cast<char*>(operator new(size));
|
||||
memcpy(*symbol_data, symbol_data_string.c_str(), size - 1);
|
||||
(*symbol_data)[size - 1] = '\0';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFileAtPathFromRoot(
|
||||
const CodeModule *module, const SystemInfo *system_info,
|
||||
const string &root_path, string *symbol_file) {
|
||||
|
|
|
@ -110,6 +110,12 @@ class SimpleSymbolSupplier : public SymbolSupplier {
|
|||
const SystemInfo *system_info,
|
||||
string *symbol_file,
|
||||
string *symbol_data);
|
||||
|
||||
virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
|
||||
const SystemInfo *system_info,
|
||||
string *symbol_file,
|
||||
char **symbol_data);
|
||||
|
||||
protected:
|
||||
SymbolResult GetSymbolFileAtPathFromRoot(const CodeModule *module,
|
||||
const SystemInfo *system_info,
|
||||
|
|
283
src/processor/source_line_resolver_base.cc
Normal file
283
src/processor/source_line_resolver_base.cc
Normal file
|
@ -0,0 +1,283 @@
|
|||
// Copyright (c) 2010 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.
|
||||
//
|
||||
// source_line_resolver_base.cc: Implementation of SourceLineResolverBase.
|
||||
//
|
||||
// See source_line_resolver_base.h and source_line_resolver_base_types.h for
|
||||
// more documentation.
|
||||
//
|
||||
// Author: Siyang Xie (lambxsy@google.com)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
#include "google_breakpad/processor/source_line_resolver_base.h"
|
||||
#include "processor/source_line_resolver_base_types.h"
|
||||
#include "processor/module_factory.h"
|
||||
|
||||
using std::map;
|
||||
using std::make_pair;
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
SourceLineResolverBase::SourceLineResolverBase(
|
||||
ModuleFactory *module_factory)
|
||||
: modules_(new ModuleMap),
|
||||
module_factory_(module_factory) {
|
||||
}
|
||||
|
||||
SourceLineResolverBase::~SourceLineResolverBase() {
|
||||
ModuleMap::iterator it;
|
||||
// Iterate through ModuleMap and delete all loaded modules.
|
||||
for (it = modules_->begin(); it != modules_->end(); ++it) {
|
||||
// Delete individual module.
|
||||
delete it->second;
|
||||
}
|
||||
// Delete the map of modules.
|
||||
delete modules_;
|
||||
delete module_factory_;
|
||||
|
||||
// Helper method to be specified by subclasses.
|
||||
ClearLocalMemory();
|
||||
}
|
||||
|
||||
// Helper methods to be specified by subclasses.
|
||||
void SourceLineResolverBase::StoreDataBeforeLoad(const CodeModule *module,
|
||||
char *symbol_data) { }
|
||||
void SourceLineResolverBase::DeleteDataAfterLoad(char *symbol_data) { }
|
||||
void SourceLineResolverBase::DeleteDataUnload(const CodeModule *module) { }
|
||||
void SourceLineResolverBase::ClearLocalMemory() { }
|
||||
|
||||
|
||||
bool SourceLineResolverBase::ReadSymbolFile(char **symbol_data,
|
||||
const string &map_file) {
|
||||
if (symbol_data == NULL) {
|
||||
BPLOG(ERROR) << "Could not Read file into Null memory pointer";
|
||||
return false;
|
||||
}
|
||||
|
||||
struct stat buf;
|
||||
int error_code = stat(map_file.c_str(), &buf);
|
||||
if (error_code == -1) {
|
||||
string error_string;
|
||||
int error_code = ErrnoString(&error_string);
|
||||
BPLOG(ERROR) << "Could not open " << map_file <<
|
||||
", error " << error_code << ": " << error_string;
|
||||
return false;
|
||||
}
|
||||
|
||||
off_t file_size = buf.st_size;
|
||||
|
||||
// Allocate memory for file contents, plus a null terminator
|
||||
// since we may use strtok() on the contents.
|
||||
*symbol_data = reinterpret_cast<char*>(operator new(file_size + 1));
|
||||
|
||||
if (*symbol_data == NULL) {
|
||||
BPLOG(ERROR) << "Could not allocate memory for " << map_file;
|
||||
return false;
|
||||
}
|
||||
|
||||
BPLOG(INFO) << "Opening " << map_file;
|
||||
|
||||
FILE *f = fopen(map_file.c_str(), "rt");
|
||||
if (!f) {
|
||||
string error_string;
|
||||
int error_code = ErrnoString(&error_string);
|
||||
BPLOG(ERROR) << "Could not open " << map_file <<
|
||||
", error " << error_code << ": " << error_string;
|
||||
delete (*symbol_data);
|
||||
*symbol_data = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
AutoFileCloser closer(f);
|
||||
|
||||
int items_read = 0;
|
||||
|
||||
items_read = fread(*symbol_data, 1, file_size, f);
|
||||
|
||||
if (items_read != file_size) {
|
||||
string error_string;
|
||||
int error_code = ErrnoString(&error_string);
|
||||
BPLOG(ERROR) << "Could not slurp " << map_file <<
|
||||
", error " << error_code << ": " << error_string;
|
||||
delete (*symbol_data);
|
||||
*symbol_data = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
(*symbol_data)[file_size] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SourceLineResolverBase::LoadModule(const CodeModule *module,
|
||||
const string &map_file) {
|
||||
if (module == NULL)
|
||||
return false;
|
||||
|
||||
// Make sure we don't already have a module with the given name.
|
||||
if (modules_->find(module->code_file()) != modules_->end()) {
|
||||
BPLOG(INFO) << "Symbols for module " << module->code_file()
|
||||
<< " already loaded";
|
||||
return false;
|
||||
}
|
||||
|
||||
BPLOG(INFO) << "Loading symbols for module " << module->code_file()
|
||||
<< " from " << map_file;
|
||||
|
||||
char *memory_buffer;
|
||||
if (!ReadSymbolFile(&memory_buffer, map_file))
|
||||
return false;
|
||||
|
||||
BPLOG(INFO) << "Read symbol file " << map_file << " succeeded";
|
||||
|
||||
// Invoke helper method, let the concrete subclass decides its own action.
|
||||
StoreDataBeforeLoad(module, memory_buffer);
|
||||
|
||||
return LoadModuleUsingMemoryBuffer(module, memory_buffer);
|
||||
}
|
||||
|
||||
bool SourceLineResolverBase::LoadModuleUsingMapBuffer(
|
||||
const CodeModule *module, const string &map_buffer) {
|
||||
char *memory_buffer = reinterpret_cast<char*>(
|
||||
operator new(map_buffer.size() + 1));
|
||||
if (memory_buffer == NULL)
|
||||
return false;
|
||||
|
||||
// Can't use strcpy, as the data may contain '\0's before the end.
|
||||
memcpy(memory_buffer, map_buffer.c_str(), map_buffer.size());
|
||||
memory_buffer[map_buffer.size()] = '\0';
|
||||
|
||||
// Invoke helper method, let the concrete subclass decides its own action.
|
||||
StoreDataBeforeLoad(module, memory_buffer);
|
||||
|
||||
return LoadModuleUsingMemoryBuffer(module, memory_buffer);
|
||||
}
|
||||
|
||||
bool SourceLineResolverBase::LoadModuleUsingMemoryBuffer(
|
||||
const CodeModule *module, char *memory_buffer) {
|
||||
if (!module) {
|
||||
// Invoke helper method, let the concrete subclass decides its own action.
|
||||
DeleteDataAfterLoad(memory_buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure we don't already have a module with the given name.
|
||||
if (modules_->find(module->code_file()) != modules_->end()) {
|
||||
BPLOG(INFO) << "Symbols for module " << module->code_file()
|
||||
<< " already loaded";
|
||||
DeleteDataAfterLoad(memory_buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
BPLOG(INFO) << "Loading symbols for module " << module->code_file()
|
||||
<< " from buffer";
|
||||
|
||||
Module *basic_module = module_factory_->CreateModule(module->code_file());
|
||||
|
||||
// Ownership of memory is NOT transfered to Module::LoadMapFromMemory().
|
||||
if (!basic_module->LoadMapFromMemory(memory_buffer)) {
|
||||
delete basic_module;
|
||||
DeleteDataAfterLoad(memory_buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
modules_->insert(make_pair(module->code_file(), basic_module));
|
||||
DeleteDataAfterLoad(memory_buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SourceLineResolverBase::UnloadModule(const CodeModule *code_module) {
|
||||
if (!code_module)
|
||||
return;
|
||||
|
||||
ModuleMap::iterator iter = modules_->find(code_module->code_file());
|
||||
if (iter != modules_->end()) {
|
||||
Module *symbol_module = iter->second;
|
||||
delete symbol_module;
|
||||
modules_->erase(iter);
|
||||
}
|
||||
|
||||
DeleteDataUnload(code_module);
|
||||
}
|
||||
|
||||
bool SourceLineResolverBase::HasModule(const CodeModule *module) {
|
||||
if (!module)
|
||||
return false;
|
||||
return modules_->find(module->code_file()) != modules_->end();
|
||||
}
|
||||
|
||||
void SourceLineResolverBase::FillSourceLineInfo(StackFrame *frame) {
|
||||
if (frame->module) {
|
||||
ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
|
||||
if (it != modules_->end()) {
|
||||
it->second->LookupAddress(frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WindowsFrameInfo *SourceLineResolverBase::FindWindowsFrameInfo(
|
||||
const StackFrame *frame) {
|
||||
if (frame->module) {
|
||||
ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
|
||||
if (it != modules_->end()) {
|
||||
return it->second->FindWindowsFrameInfo(frame);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CFIFrameInfo *SourceLineResolverBase::FindCFIFrameInfo(
|
||||
const StackFrame *frame) {
|
||||
if (frame->module) {
|
||||
ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
|
||||
if (it != modules_->end()) {
|
||||
return it->second->FindCFIFrameInfo(frame);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool SourceLineResolverBase::CompareString::operator()(
|
||||
const string &s1, const string &s2) const {
|
||||
return strcmp(s1.c_str(), s2.c_str()) < 0;
|
||||
}
|
||||
|
||||
bool SourceLineResolverBase::Module::ParseCFIRuleSet(
|
||||
const string &rule_set, CFIFrameInfo *frame_info) const {
|
||||
CFIFrameInfoParseHandler handler(frame_info);
|
||||
CFIRuleParser parser(&handler);
|
||||
return parser.Parse(rule_set);
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
149
src/processor/source_line_resolver_base_types.h
Normal file
149
src/processor/source_line_resolver_base_types.h
Normal file
|
@ -0,0 +1,149 @@
|
|||
// Copyright (c) 2010 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.
|
||||
|
||||
// source_line_resolver_base_types.h: definition of nested classes/structs in
|
||||
// SourceLineResolverBase. It moves the definitions out of
|
||||
// source_line_resolver_base.cc, so that other classes may have access
|
||||
// to these private nested types without including source_line_resolver_base.cc
|
||||
// In addition, Module is defined as a pure abstract class to be implemented by
|
||||
// each concrete source line resolver class.
|
||||
//
|
||||
// See source_line_resolver_base.h for more documentation.
|
||||
//
|
||||
// Author: Siyang Xie (lambxsy@google.com)
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "google_breakpad/processor/source_line_resolver_base.h"
|
||||
#include "google_breakpad/processor/stack_frame.h"
|
||||
#include "processor/cfi_frame_info.h"
|
||||
#include "processor/windows_frame_info.h"
|
||||
|
||||
#ifndef PROCESSOR_SOURCE_LINE_RESOLVER_BASE_TYPES_H__
|
||||
#define PROCESSOR_SOURCE_LINE_RESOLVER_BASE_TYPES_H__
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
class SourceLineResolverBase::AutoFileCloser {
|
||||
public:
|
||||
explicit AutoFileCloser(FILE *file) : file_(file) {}
|
||||
~AutoFileCloser() {
|
||||
if (file_)
|
||||
fclose(file_);
|
||||
}
|
||||
|
||||
private:
|
||||
FILE *file_;
|
||||
};
|
||||
|
||||
struct SourceLineResolverBase::Line {
|
||||
Line() { }
|
||||
Line(MemAddr addr, MemAddr code_size, int file_id, int source_line)
|
||||
: address(addr)
|
||||
, size(code_size)
|
||||
, source_file_id(file_id)
|
||||
, line(source_line) { }
|
||||
|
||||
MemAddr address;
|
||||
MemAddr size;
|
||||
int32_t source_file_id;
|
||||
int32_t line;
|
||||
};
|
||||
|
||||
struct SourceLineResolverBase::Function {
|
||||
Function() { }
|
||||
Function(const string &function_name,
|
||||
MemAddr function_address,
|
||||
MemAddr code_size,
|
||||
int set_parameter_size)
|
||||
: name(function_name), address(function_address), size(code_size),
|
||||
parameter_size(set_parameter_size) { }
|
||||
|
||||
string name;
|
||||
MemAddr address;
|
||||
MemAddr size;
|
||||
|
||||
// The size of parameters passed to this function on the stack.
|
||||
int32_t parameter_size;
|
||||
};
|
||||
|
||||
struct SourceLineResolverBase::PublicSymbol {
|
||||
PublicSymbol() { }
|
||||
PublicSymbol(const string& set_name,
|
||||
MemAddr set_address,
|
||||
int set_parameter_size)
|
||||
: name(set_name),
|
||||
address(set_address),
|
||||
parameter_size(set_parameter_size) {}
|
||||
|
||||
string name;
|
||||
MemAddr address;
|
||||
|
||||
// If the public symbol is used as a function entry point, parameter_size
|
||||
// is set to the size of the parameters passed to the funciton on the
|
||||
// stack, if known.
|
||||
int32_t parameter_size;
|
||||
};
|
||||
|
||||
class SourceLineResolverBase::Module {
|
||||
public:
|
||||
virtual ~Module() { };
|
||||
// Loads a map from the given buffer in char* type.
|
||||
// Does NOT take ownership of memory_buffer (the caller, source line resolver,
|
||||
// is the owner of memory_buffer).
|
||||
virtual bool LoadMapFromMemory(char *memory_buffer) = 0;
|
||||
|
||||
// Looks up the given relative address, and fills the StackFrame struct
|
||||
// with the result.
|
||||
virtual void LookupAddress(StackFrame *frame) const = 0;
|
||||
|
||||
// If Windows stack walking information is available covering ADDRESS,
|
||||
// return a WindowsFrameInfo structure describing it. If the information
|
||||
// is not available, returns NULL. A NULL return value does not indicate
|
||||
// an error. The caller takes ownership of any returned WindowsFrameInfo
|
||||
// object.
|
||||
virtual WindowsFrameInfo *
|
||||
FindWindowsFrameInfo(const StackFrame *frame) const = 0;
|
||||
|
||||
// If CFI stack walking information is available covering ADDRESS,
|
||||
// return a CFIFrameInfo structure describing it. If the information
|
||||
// is not available, return NULL. The caller takes ownership of any
|
||||
// returned CFIFrameInfo object.
|
||||
virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame) const = 0;
|
||||
protected:
|
||||
virtual bool ParseCFIRuleSet(const string &rule_set,
|
||||
CFIFrameInfo *frame_info) const;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // PROCESSOR_SOURCE_LINE_RESOLVER_BASE_TYPES_H__
|
|
@ -97,15 +97,18 @@ bool Stackwalker::Walk(CallStack *stack) {
|
|||
no_symbol_modules_.find(
|
||||
module->code_file()) == no_symbol_modules_.end() &&
|
||||
supplier_) {
|
||||
string symbol_data, symbol_file;
|
||||
string symbol_file;
|
||||
char *symbol_data;
|
||||
SymbolSupplier::SymbolResult symbol_result =
|
||||
supplier_->GetSymbolFile(module, system_info_,
|
||||
&symbol_file, &symbol_data);
|
||||
supplier_->GetCStringSymbolData(module,
|
||||
system_info_,
|
||||
&symbol_file,
|
||||
&symbol_data);
|
||||
|
||||
switch (symbol_result) {
|
||||
case SymbolSupplier::FOUND:
|
||||
resolver_->LoadModuleUsingMapBuffer(frame->module,
|
||||
symbol_data);
|
||||
resolver_->LoadModuleUsingMemoryBuffer(frame->module,
|
||||
symbol_data);
|
||||
break;
|
||||
case SymbolSupplier::NOT_FOUND:
|
||||
no_symbol_modules_.insert(module->code_file());
|
||||
|
@ -207,13 +210,14 @@ bool Stackwalker::InstructionAddressSeemsValid(u_int64_t address) {
|
|||
}
|
||||
|
||||
if (!resolver_->HasModule(module)) {
|
||||
string symbol_data, symbol_file;
|
||||
string symbol_file;
|
||||
char *symbol_data;
|
||||
SymbolSupplier::SymbolResult symbol_result =
|
||||
supplier_->GetSymbolFile(module, system_info_,
|
||||
&symbol_file, &symbol_data);
|
||||
supplier_->GetCStringSymbolData(module, system_info_,
|
||||
&symbol_file, &symbol_data);
|
||||
|
||||
if (symbol_result != SymbolSupplier::FOUND ||
|
||||
!resolver_->LoadModuleUsingMapBuffer(module,
|
||||
!resolver_->LoadModuleUsingMemoryBuffer(module,
|
||||
symbol_data)) {
|
||||
// we don't have symbols, but we're inside a loaded module
|
||||
return true;
|
||||
|
|
|
@ -85,15 +85,18 @@ class StackwalkerAMD64Fixture {
|
|||
|
||||
// By default, none of the modules have symbol info; call
|
||||
// SetModuleSymbols to override this.
|
||||
EXPECT_CALL(supplier, GetSymbolFile(_, _, _, _))
|
||||
EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _))
|
||||
.WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
|
||||
}
|
||||
|
||||
// Set the Breakpad symbol information that supplier should return for
|
||||
// MODULE to INFO.
|
||||
void SetModuleSymbols(MockCodeModule *module, const string &info) {
|
||||
EXPECT_CALL(supplier, GetSymbolFile(module, &system_info, _, _))
|
||||
.WillRepeatedly(DoAll(SetArgumentPointee<3>(info),
|
||||
unsigned int buffer_size = info.size() + 1;
|
||||
char *buffer = reinterpret_cast<char*>(operator new(buffer_size));
|
||||
strcpy(buffer, info.c_str());
|
||||
EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _))
|
||||
.WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
|
||||
Return(MockSymbolSupplier::FOUND)));
|
||||
}
|
||||
|
||||
|
|
|
@ -87,15 +87,18 @@ class StackwalkerARMFixture {
|
|||
|
||||
// By default, none of the modules have symbol info; call
|
||||
// SetModuleSymbols to override this.
|
||||
EXPECT_CALL(supplier, GetSymbolFile(_, _, _, _))
|
||||
EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _))
|
||||
.WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
|
||||
}
|
||||
|
||||
// Set the Breakpad symbol information that supplier should return for
|
||||
// MODULE to INFO.
|
||||
void SetModuleSymbols(MockCodeModule *module, const string &info) {
|
||||
EXPECT_CALL(supplier, GetSymbolFile(module, &system_info, _, _))
|
||||
.WillRepeatedly(DoAll(SetArgumentPointee<3>(info),
|
||||
unsigned int buffer_size = info.size() + 1;
|
||||
char *buffer = reinterpret_cast<char*>(operator new(buffer_size));
|
||||
strcpy(buffer, info.c_str());
|
||||
EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _))
|
||||
.WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
|
||||
Return(MockSymbolSupplier::FOUND)));
|
||||
}
|
||||
|
||||
|
|
|
@ -170,6 +170,10 @@ class MockSymbolSupplier: public google_breakpad::SymbolSupplier {
|
|||
const SystemInfo *system_info,
|
||||
std::string *symbol_file,
|
||||
std::string *symbol_data));
|
||||
MOCK_METHOD4(GetCStringSymbolData, SymbolResult(const CodeModule *module,
|
||||
const SystemInfo *system_info,
|
||||
std::string *symbol_file,
|
||||
char **symbol_data));
|
||||
};
|
||||
|
||||
#endif // PROCESSOR_STACKWALKER_UNITTEST_UTILS_H_
|
||||
|
|
|
@ -86,15 +86,18 @@ class StackwalkerX86Fixture {
|
|||
|
||||
// By default, none of the modules have symbol info; call
|
||||
// SetModuleSymbols to override this.
|
||||
EXPECT_CALL(supplier, GetSymbolFile(_, _, _, _))
|
||||
EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _))
|
||||
.WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
|
||||
}
|
||||
|
||||
// Set the Breakpad symbol information that supplier should return for
|
||||
// MODULE to INFO.
|
||||
void SetModuleSymbols(MockCodeModule *module, const string &info) {
|
||||
EXPECT_CALL(supplier, GetSymbolFile(module, &system_info, _, _))
|
||||
.WillRepeatedly(DoAll(SetArgumentPointee<3>(info),
|
||||
unsigned int buffer_size = info.size() + 1;
|
||||
char *buffer = reinterpret_cast<char*>(operator new(buffer_size));
|
||||
strcpy(buffer, info.c_str());
|
||||
EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _))
|
||||
.WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
|
||||
Return(MockSymbolSupplier::FOUND)));
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#define PROCESSOR_WINDOWS_FRAME_INFO_H__
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
|
Loading…
Reference in a new issue