Add support for parsing the DW_AT_ranges attributes
This enables the DWARF reader to properly parse DW_AT_ranges attributes in compilation units and functions. Code covered by a function is now represented by a vector of ranges instead of a single contiguous range and DW_AT_ranges entries are used to populate it. All the code and tests that assumed functions to be contiguous entities has been updated to reflect the change. DW_AT_ranges attributes found in compilation units are parsed but no data is generated for them as it is not currently needed. BUG=754 Change-Id: I310391b525aaba0dd329f1e3187486f2e0c6d442 Reviewed-on: https://chromium-review.googlesource.com/1124721 Reviewed-by: Ted Mielczarek <ted.mielczarek@gmail.com>
This commit is contained in:
parent
7b98edabb6
commit
16e08520e6
20 changed files with 653 additions and 122 deletions
|
@ -574,6 +574,7 @@ src_tools_linux_dump_syms_dump_syms_SOURCES = \
|
|||
src/common/dwarf_cfi_to_module.cc \
|
||||
src/common/dwarf_cu_to_module.cc \
|
||||
src/common/dwarf_line_to_module.cc \
|
||||
src/common/dwarf_range_list_handler.cc \
|
||||
src/common/language.cc \
|
||||
src/common/module.cc \
|
||||
src/common/path_helper.cc \
|
||||
|
@ -622,6 +623,7 @@ src_tools_mac_dump_syms_dump_syms_mac_SOURCES = \
|
|||
src/common/dwarf_cfi_to_module.cc \
|
||||
src/common/dwarf_cu_to_module.cc \
|
||||
src/common/dwarf_line_to_module.cc \
|
||||
src/common/dwarf_range_list_handler.cc \
|
||||
src/common/language.cc \
|
||||
src/common/md5.cc \
|
||||
src/common/module.cc \
|
||||
|
@ -661,6 +663,7 @@ src_common_dumper_unittest_SOURCES = \
|
|||
src/common/dwarf_cu_to_module_unittest.cc \
|
||||
src/common/dwarf_line_to_module.cc \
|
||||
src/common/dwarf_line_to_module_unittest.cc \
|
||||
src/common/dwarf_range_list_handler.cc \
|
||||
src/common/language.cc \
|
||||
src/common/memory_range_unittest.cc \
|
||||
src/common/module.cc \
|
||||
|
|
74
Makefile.in
74
Makefile.in
|
@ -694,10 +694,10 @@ am__src_common_dumper_unittest_SOURCES_DIST = \
|
|||
src/common/dwarf_cu_to_module_unittest.cc \
|
||||
src/common/dwarf_line_to_module.cc \
|
||||
src/common/dwarf_line_to_module_unittest.cc \
|
||||
src/common/language.cc src/common/memory_range_unittest.cc \
|
||||
src/common/module.cc src/common/module_unittest.cc \
|
||||
src/common/path_helper.cc src/common/stabs_reader.cc \
|
||||
src/common/stabs_reader_unittest.cc \
|
||||
src/common/dwarf_range_list_handler.cc src/common/language.cc \
|
||||
src/common/memory_range_unittest.cc src/common/module.cc \
|
||||
src/common/module_unittest.cc src/common/path_helper.cc \
|
||||
src/common/stabs_reader.cc src/common/stabs_reader_unittest.cc \
|
||||
src/common/stabs_to_module.cc \
|
||||
src/common/stabs_to_module_unittest.cc \
|
||||
src/common/test_assembler.cc src/common/dwarf/bytereader.cc \
|
||||
|
@ -740,6 +740,7 @@ am__src_common_dumper_unittest_SOURCES_DIST = \
|
|||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-dwarf_cu_to_module_unittest.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-dwarf_line_to_module.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-dwarf_range_list_handler.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-language.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-memory_range_unittest.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-module.$(OBJEXT) \
|
||||
|
@ -1402,7 +1403,8 @@ src_tools_linux_core2md_core2md_OBJECTS = \
|
|||
am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \
|
||||
src/common/dwarf_cfi_to_module.cc \
|
||||
src/common/dwarf_cu_to_module.cc \
|
||||
src/common/dwarf_line_to_module.cc src/common/language.cc \
|
||||
src/common/dwarf_line_to_module.cc \
|
||||
src/common/dwarf_range_list_handler.cc src/common/language.cc \
|
||||
src/common/module.cc src/common/path_helper.cc \
|
||||
src/common/stabs_reader.cc src/common/stabs_to_module.cc \
|
||||
src/common/dwarf/bytereader.cc \
|
||||
|
@ -1421,6 +1423,7 @@ am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \
|
|||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_dump_syms_dump_syms_OBJECTS = src/common/src_tools_linux_dump_syms_dump_syms-dwarf_cfi_to_module.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_linux_dump_syms_dump_syms-dwarf_cu_to_module.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_linux_dump_syms_dump_syms-dwarf_line_to_module.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_linux_dump_syms_dump_syms-language.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_linux_dump_syms_dump_syms-module.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_linux_dump_syms_dump_syms-path_helper.$(OBJEXT) \
|
||||
|
@ -1486,7 +1489,8 @@ src_tools_linux_symupload_sym_upload_DEPENDENCIES =
|
|||
am__src_tools_mac_dump_syms_dump_syms_mac_SOURCES_DIST = \
|
||||
src/common/dwarf_cfi_to_module.cc \
|
||||
src/common/dwarf_cu_to_module.cc \
|
||||
src/common/dwarf_line_to_module.cc src/common/language.cc \
|
||||
src/common/dwarf_line_to_module.cc \
|
||||
src/common/dwarf_range_list_handler.cc src/common/language.cc \
|
||||
src/common/md5.cc src/common/module.cc \
|
||||
src/common/path_helper.cc src/common/stabs_reader.cc \
|
||||
src/common/stabs_to_module.cc src/common/dwarf/bytereader.cc \
|
||||
|
@ -1505,6 +1509,7 @@ am__src_tools_mac_dump_syms_dump_syms_mac_SOURCES_DIST = \
|
|||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_mac_dump_syms_dump_syms_mac_OBJECTS = src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-language.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-md5.$(OBJEXT) \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-module.$(OBJEXT) \
|
||||
|
@ -2413,6 +2418,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
|
|||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cfi_to_module.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cu_to_module.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_range_list_handler.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/language.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/path_helper.cc \
|
||||
|
@ -2463,6 +2469,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
|
|||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cfi_to_module.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cu_to_module.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_range_list_handler.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/language.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/md5.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.cc \
|
||||
|
@ -2504,6 +2511,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
|
|||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cu_to_module_unittest.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module_unittest.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_range_list_handler.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/language.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/memory_range_unittest.cc \
|
||||
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.cc \
|
||||
|
@ -4053,6 +4061,9 @@ src/common/src_common_dumper_unittest-dwarf_line_to_module.$(OBJEXT): \
|
|||
src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.$(OBJEXT): \
|
||||
src/common/$(am__dirstamp) \
|
||||
src/common/$(DEPDIR)/$(am__dirstamp)
|
||||
src/common/src_common_dumper_unittest-dwarf_range_list_handler.$(OBJEXT): \
|
||||
src/common/$(am__dirstamp) \
|
||||
src/common/$(DEPDIR)/$(am__dirstamp)
|
||||
src/common/src_common_dumper_unittest-language.$(OBJEXT): \
|
||||
src/common/$(am__dirstamp) \
|
||||
src/common/$(DEPDIR)/$(am__dirstamp)
|
||||
|
@ -4560,6 +4571,9 @@ src/common/src_tools_linux_dump_syms_dump_syms-dwarf_cu_to_module.$(OBJEXT): \
|
|||
src/common/src_tools_linux_dump_syms_dump_syms-dwarf_line_to_module.$(OBJEXT): \
|
||||
src/common/$(am__dirstamp) \
|
||||
src/common/$(DEPDIR)/$(am__dirstamp)
|
||||
src/common/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.$(OBJEXT): \
|
||||
src/common/$(am__dirstamp) \
|
||||
src/common/$(DEPDIR)/$(am__dirstamp)
|
||||
src/common/src_tools_linux_dump_syms_dump_syms-language.$(OBJEXT): \
|
||||
src/common/$(am__dirstamp) \
|
||||
src/common/$(DEPDIR)/$(am__dirstamp)
|
||||
|
@ -4681,6 +4695,9 @@ src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.$(OBJEXT):
|
|||
src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.$(OBJEXT): \
|
||||
src/common/$(am__dirstamp) \
|
||||
src/common/$(DEPDIR)/$(am__dirstamp)
|
||||
src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.$(OBJEXT): \
|
||||
src/common/$(am__dirstamp) \
|
||||
src/common/$(DEPDIR)/$(am__dirstamp)
|
||||
src/common/src_tools_mac_dump_syms_dump_syms_mac-language.$(OBJEXT): \
|
||||
src/common/$(am__dirstamp) \
|
||||
src/common/$(DEPDIR)/$(am__dirstamp)
|
||||
|
@ -4811,6 +4828,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cu_to_module_unittest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module_unittest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_range_list_handler.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-language.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-module.Po@am__quote@
|
||||
|
@ -4845,6 +4863,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-dwarf_cfi_to_module.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-dwarf_cu_to_module.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-dwarf_line_to_module.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-language.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-module.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-path_helper.Po@am__quote@
|
||||
|
@ -4853,6 +4872,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-language.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-md5.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-module.Po@am__quote@
|
||||
|
@ -5660,6 +5680,20 @@ src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.obj: src/com
|
|||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.obj `if test -f 'src/common/dwarf_line_to_module_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf_line_to_module_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_line_to_module_unittest.cc'; fi`
|
||||
|
||||
src/common/src_common_dumper_unittest-dwarf_range_list_handler.o: src/common/dwarf_range_list_handler.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-dwarf_range_list_handler.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_range_list_handler.Tpo -c -o src/common/src_common_dumper_unittest-dwarf_range_list_handler.o `test -f 'src/common/dwarf_range_list_handler.cc' || echo '$(srcdir)/'`src/common/dwarf_range_list_handler.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_range_list_handler.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_range_list_handler.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_range_list_handler.cc' object='src/common/src_common_dumper_unittest-dwarf_range_list_handler.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-dwarf_range_list_handler.o `test -f 'src/common/dwarf_range_list_handler.cc' || echo '$(srcdir)/'`src/common/dwarf_range_list_handler.cc
|
||||
|
||||
src/common/src_common_dumper_unittest-dwarf_range_list_handler.obj: src/common/dwarf_range_list_handler.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-dwarf_range_list_handler.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_range_list_handler.Tpo -c -o src/common/src_common_dumper_unittest-dwarf_range_list_handler.obj `if test -f 'src/common/dwarf_range_list_handler.cc'; then $(CYGPATH_W) 'src/common/dwarf_range_list_handler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_range_list_handler.cc'; fi`
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_range_list_handler.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_range_list_handler.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_range_list_handler.cc' object='src/common/src_common_dumper_unittest-dwarf_range_list_handler.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-dwarf_range_list_handler.obj `if test -f 'src/common/dwarf_range_list_handler.cc'; then $(CYGPATH_W) 'src/common/dwarf_range_list_handler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_range_list_handler.cc'; fi`
|
||||
|
||||
src/common/src_common_dumper_unittest-language.o: src/common/language.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-language.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-language.Tpo -c -o src/common/src_common_dumper_unittest-language.o `test -f 'src/common/language.cc' || echo '$(srcdir)/'`src/common/language.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-language.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-language.Po
|
||||
|
@ -7116,6 +7150,20 @@ src/common/src_tools_linux_dump_syms_dump_syms-dwarf_line_to_module.obj: src/com
|
|||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_linux_dump_syms_dump_syms_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_linux_dump_syms_dump_syms-dwarf_line_to_module.obj `if test -f 'src/common/dwarf_line_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_line_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_line_to_module.cc'; fi`
|
||||
|
||||
src/common/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.o: src/common/dwarf_range_list_handler.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_linux_dump_syms_dump_syms_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.o -MD -MP -MF src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.Tpo -c -o src/common/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.o `test -f 'src/common/dwarf_range_list_handler.cc' || echo '$(srcdir)/'`src/common/dwarf_range_list_handler.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.Tpo src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_range_list_handler.cc' object='src/common/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_linux_dump_syms_dump_syms_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.o `test -f 'src/common/dwarf_range_list_handler.cc' || echo '$(srcdir)/'`src/common/dwarf_range_list_handler.cc
|
||||
|
||||
src/common/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.obj: src/common/dwarf_range_list_handler.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_linux_dump_syms_dump_syms_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.obj -MD -MP -MF src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.Tpo -c -o src/common/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.obj `if test -f 'src/common/dwarf_range_list_handler.cc'; then $(CYGPATH_W) 'src/common/dwarf_range_list_handler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_range_list_handler.cc'; fi`
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.Tpo src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_range_list_handler.cc' object='src/common/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_linux_dump_syms_dump_syms_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_linux_dump_syms_dump_syms-dwarf_range_list_handler.obj `if test -f 'src/common/dwarf_range_list_handler.cc'; then $(CYGPATH_W) 'src/common/dwarf_range_list_handler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_range_list_handler.cc'; fi`
|
||||
|
||||
src/common/src_tools_linux_dump_syms_dump_syms-language.o: src/common/language.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_linux_dump_syms_dump_syms_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_linux_dump_syms_dump_syms-language.o -MD -MP -MF src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-language.Tpo -c -o src/common/src_tools_linux_dump_syms_dump_syms-language.o `test -f 'src/common/language.cc' || echo '$(srcdir)/'`src/common/language.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-language.Tpo src/common/$(DEPDIR)/src_tools_linux_dump_syms_dump_syms-language.Po
|
||||
|
@ -7424,6 +7472,20 @@ src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.obj: src/c
|
|||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.obj `if test -f 'src/common/dwarf_line_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_line_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_line_to_module.cc'; fi`
|
||||
|
||||
src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.o: src/common/dwarf_range_list_handler.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.o -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.o `test -f 'src/common/dwarf_range_list_handler.cc' || echo '$(srcdir)/'`src/common/dwarf_range_list_handler.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_range_list_handler.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.o `test -f 'src/common/dwarf_range_list_handler.cc' || echo '$(srcdir)/'`src/common/dwarf_range_list_handler.cc
|
||||
|
||||
src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.obj: src/common/dwarf_range_list_handler.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.obj -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.obj `if test -f 'src/common/dwarf_range_list_handler.cc'; then $(CYGPATH_W) 'src/common/dwarf_range_list_handler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_range_list_handler.cc'; fi`
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_range_list_handler.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_range_list_handler.obj `if test -f 'src/common/dwarf_range_list_handler.cc'; then $(CYGPATH_W) 'src/common/dwarf_range_list_handler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_range_list_handler.cc'; fi`
|
||||
|
||||
src/common/src_tools_mac_dump_syms_dump_syms_mac-language.o: src/common/language.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-language.o -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-language.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-language.o `test -f 'src/common/language.cc' || echo '$(srcdir)/'`src/common/language.cc
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-language.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-language.Po
|
||||
|
|
10
configure
vendored
10
configure
vendored
|
@ -6098,7 +6098,7 @@ else
|
|||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
|
@ -6144,7 +6144,7 @@ else
|
|||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
|
@ -6168,7 +6168,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
|
@ -6213,7 +6213,7 @@ else
|
|||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
|
@ -6237,7 +6237,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
|
|
|
@ -1247,6 +1247,41 @@ void LineInfo::ReadLines() {
|
|||
after_header_ = lengthstart + header_.total_length;
|
||||
}
|
||||
|
||||
RangeListReader::RangeListReader(const uint8_t *buffer, uint64 size,
|
||||
ByteReader *reader, RangeListHandler *handler)
|
||||
: buffer_(buffer), size_(size), reader_(reader), handler_(handler) { }
|
||||
|
||||
bool RangeListReader::ReadRangeList(uint64 offset) {
|
||||
const uint64 max_address =
|
||||
(reader_->AddressSize() == 4) ? 0xffffffffUL
|
||||
: 0xffffffffffffffffULL;
|
||||
const uint64 entry_size = reader_->AddressSize() * 2;
|
||||
bool list_end = false;
|
||||
|
||||
do {
|
||||
if (offset > size_ - entry_size) {
|
||||
return false; // Invalid range detected
|
||||
}
|
||||
|
||||
uint64 start_address = reader_->ReadAddress(buffer_ + offset);
|
||||
uint64 end_address =
|
||||
reader_->ReadAddress(buffer_ + offset + reader_->AddressSize());
|
||||
|
||||
if (start_address == max_address) { // Base address selection
|
||||
handler_->SetBaseAddress(end_address);
|
||||
} else if (start_address == 0 && end_address == 0) { // End-of-list
|
||||
handler_->Finish();
|
||||
list_end = true;
|
||||
} else { // Add a range entry
|
||||
handler_->AddRange(start_address, end_address);
|
||||
}
|
||||
|
||||
offset += entry_size;
|
||||
} while (!list_end);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// A DWARF rule for recovering the address or value of a register, or
|
||||
// computing the canonical frame address. There is one subclass of this for
|
||||
// each '*Rule' member function in CallFrameInfo::Handler.
|
||||
|
|
|
@ -187,6 +187,36 @@ class LineInfoHandler {
|
|||
uint32 file_num, uint32 line_num, uint32 column_num) { }
|
||||
};
|
||||
|
||||
class RangeListHandler {
|
||||
public:
|
||||
RangeListHandler() { }
|
||||
|
||||
virtual ~RangeListHandler() { }
|
||||
|
||||
// Add a range.
|
||||
virtual void AddRange(uint64 begin, uint64 end) { };
|
||||
|
||||
// A new base address must be set for computing the ranges' addresses.
|
||||
virtual void SetBaseAddress(uint64 base_address) { };
|
||||
|
||||
// Finish processing the range list.
|
||||
virtual void Finish() { };
|
||||
};
|
||||
|
||||
class RangeListReader {
|
||||
public:
|
||||
RangeListReader(const uint8_t *buffer, uint64 size, ByteReader *reader,
|
||||
RangeListHandler *handler);
|
||||
|
||||
bool ReadRangeList(uint64 offset);
|
||||
|
||||
private:
|
||||
const uint8_t *buffer_;
|
||||
uint64 size_;
|
||||
ByteReader* reader_;
|
||||
RangeListHandler *handler_;
|
||||
};
|
||||
|
||||
// This class is the main interface between the reader and the
|
||||
// client. The virtual functions inside this get called for
|
||||
// interesting events that happen during DWARF2 reading.
|
||||
|
|
|
@ -184,6 +184,9 @@ void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset,
|
|||
case DW_AT_decl_file:
|
||||
current_function_info_->file = files_->at(data).name;
|
||||
break;
|
||||
case DW_AT_ranges:
|
||||
current_function_info->ranges = data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -58,6 +58,8 @@ struct FunctionInfo {
|
|||
uint64 lowpc;
|
||||
// End address for this function.
|
||||
uint64 highpc;
|
||||
// Ranges offset
|
||||
uint64 ranges;
|
||||
};
|
||||
|
||||
struct SourceFileInfo {
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
|
||||
#include "common/dwarf_line_to_module.h"
|
||||
|
@ -51,6 +52,7 @@
|
|||
|
||||
namespace google_breakpad {
|
||||
|
||||
using std::accumulate;
|
||||
using std::map;
|
||||
using std::pair;
|
||||
using std::sort;
|
||||
|
@ -167,10 +169,15 @@ bool DwarfCUToModule::FileContext::IsUnhandledInterCUReference(
|
|||
// parsing. This is for data shared across the CU's entire DIE tree,
|
||||
// and parameters from the code invoking the CU parser.
|
||||
struct DwarfCUToModule::CUContext {
|
||||
CUContext(FileContext *file_context_arg, WarningReporter *reporter_arg)
|
||||
CUContext(FileContext *file_context_arg, WarningReporter *reporter_arg,
|
||||
RangesHandler *ranges_handler_arg)
|
||||
: file_context(file_context_arg),
|
||||
reporter(reporter_arg),
|
||||
language(Language::CPlusPlus) {}
|
||||
ranges_handler(ranges_handler_arg),
|
||||
language(Language::CPlusPlus),
|
||||
low_pc(0),
|
||||
high_pc(0),
|
||||
ranges(0) {}
|
||||
|
||||
~CUContext() {
|
||||
for (vector<Module::Function *>::iterator it = functions.begin();
|
||||
|
@ -185,9 +192,19 @@ struct DwarfCUToModule::CUContext {
|
|||
// For printing error messages.
|
||||
WarningReporter *reporter;
|
||||
|
||||
// For reading ranges from the .debug_ranges section
|
||||
RangesHandler *ranges_handler;
|
||||
|
||||
// The source language of this compilation unit.
|
||||
const Language *language;
|
||||
|
||||
// Addresses covered by this CU. If high_pc_ is non-zero then the CU covers
|
||||
// low_pc to high_pc, otherwise ranges is non-zero and low_pc represents
|
||||
// the base address of the ranges covered by the CU.
|
||||
uint64 low_pc;
|
||||
uint64 high_pc;
|
||||
uint64 ranges;
|
||||
|
||||
// The functions defined in this compilation unit. We accumulate
|
||||
// them here during parsing. Then, in DwarfCUToModule::Finish, we
|
||||
// assign them lines and add them to file_context->module.
|
||||
|
@ -445,7 +462,7 @@ class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
|
|||
uint64 offset)
|
||||
: GenericDIEHandler(cu_context, parent_context, offset),
|
||||
low_pc_(0), high_pc_(0), high_pc_form_(dwarf2reader::DW_FORM_addr),
|
||||
abstract_origin_(NULL), inline_(false) { }
|
||||
ranges_(0), abstract_origin_(NULL), inline_(false) { }
|
||||
void ProcessAttributeUnsigned(enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
uint64 data);
|
||||
|
@ -465,6 +482,7 @@ class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
|
|||
string name_;
|
||||
uint64 low_pc_, high_pc_; // DW_AT_low_pc, DW_AT_high_pc
|
||||
DwarfForm high_pc_form_; // DW_AT_high_pc can be length or address.
|
||||
uint64 ranges_; // DW_AT_ranges
|
||||
const AbstractOrigin* abstract_origin_;
|
||||
bool inline_;
|
||||
};
|
||||
|
@ -484,6 +502,9 @@ void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
|
|||
high_pc_form_ = form;
|
||||
high_pc_ = data;
|
||||
break;
|
||||
case dwarf2reader::DW_AT_ranges:
|
||||
ranges_ = data;
|
||||
break;
|
||||
|
||||
default:
|
||||
GenericDIEHandler::ProcessAttributeUnsigned(attr, form, data);
|
||||
|
@ -537,17 +558,47 @@ bool DwarfCUToModule::FuncHandler::EndAttributes() {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool IsEmptyRange(vector<Module::Range> ranges) {
|
||||
uint64 size = accumulate(ranges.cbegin(), ranges.cend(), 0,
|
||||
[](uint64 total, Module::Range entry) {
|
||||
return total + entry.size;
|
||||
}
|
||||
);
|
||||
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
void DwarfCUToModule::FuncHandler::Finish() {
|
||||
// Make high_pc_ an address, if it isn't already.
|
||||
if (high_pc_form_ != dwarf2reader::DW_FORM_addr) {
|
||||
high_pc_ += low_pc_;
|
||||
vector<Module::Range> ranges;
|
||||
|
||||
if (!ranges_) {
|
||||
// Make high_pc_ an address, if it isn't already.
|
||||
if (high_pc_form_ != dwarf2reader::DW_FORM_addr) {
|
||||
high_pc_ += low_pc_;
|
||||
}
|
||||
|
||||
Module::Range range(low_pc_, high_pc_ - low_pc_);
|
||||
ranges.push_back(range);
|
||||
} else {
|
||||
RangesHandler *ranges_handler = cu_context_->ranges_handler;
|
||||
|
||||
if (ranges_handler) {
|
||||
if (!ranges_handler->ReadRanges(ranges_, cu_context_->low_pc, &ranges)) {
|
||||
ranges.clear();
|
||||
cu_context_->reporter->MalformedRangeList(ranges_);
|
||||
}
|
||||
} else {
|
||||
cu_context_->reporter->MissingRanges();
|
||||
}
|
||||
}
|
||||
|
||||
// Did we collect the information we need? Not all DWARF function
|
||||
// entries have low and high addresses (for example, inlined
|
||||
// functions that were never used), but all the ones we're
|
||||
// interested in cover a non-empty range of bytes.
|
||||
if (low_pc_ < high_pc_) {
|
||||
// entries are non-empty (for example, inlined functions that were never
|
||||
// used), but all the ones we're interested in cover a non-empty range of
|
||||
// bytes.
|
||||
if (!IsEmptyRange(ranges)) {
|
||||
low_pc_ = ranges.front().address;
|
||||
|
||||
// Malformed DWARF may omit the name, but all Module::Functions must
|
||||
// have names.
|
||||
string name;
|
||||
|
@ -561,7 +612,7 @@ void DwarfCUToModule::FuncHandler::Finish() {
|
|||
// Create a Module::Function based on the data we've gathered, and
|
||||
// add it to the functions_ list.
|
||||
scoped_ptr<Module::Function> func(new Module::Function(name, low_pc_));
|
||||
func->size = high_pc_ - low_pc_;
|
||||
func->ranges = ranges;
|
||||
func->parameter_size = 0;
|
||||
if (func->address) {
|
||||
// If the function address is zero this is a sign that this function
|
||||
|
@ -663,7 +714,7 @@ void DwarfCUToModule::WarningReporter::UncoveredFunction(
|
|||
return;
|
||||
UncoveredHeading();
|
||||
fprintf(stderr, " function%s: %s\n",
|
||||
function.size == 0 ? " (zero-length)" : "",
|
||||
IsEmptyRange(function.ranges) ? " (zero-length)" : "",
|
||||
function.name.c_str());
|
||||
}
|
||||
|
||||
|
@ -697,11 +748,25 @@ void DwarfCUToModule::WarningReporter::UnhandledInterCUReference(
|
|||
filename_.c_str(), offset, target);
|
||||
}
|
||||
|
||||
void DwarfCUToModule::WarningReporter::MalformedRangeList(uint64 offset) {
|
||||
CUHeading();
|
||||
fprintf(stderr, "%s: warning: the range list at offset 0x%llx falls out of "
|
||||
"the .debug_ranges section.\n",
|
||||
filename_.c_str(), offset);
|
||||
}
|
||||
|
||||
void DwarfCUToModule::WarningReporter::MissingRanges() {
|
||||
CUHeading();
|
||||
fprintf(stderr, "%s: warning: A DW_AT_ranges attribute was encountered but "
|
||||
"the .debug_ranges section is missing.\n", filename_.c_str());
|
||||
}
|
||||
|
||||
DwarfCUToModule::DwarfCUToModule(FileContext *file_context,
|
||||
LineToModuleHandler *line_reader,
|
||||
RangesHandler *ranges_handler,
|
||||
WarningReporter *reporter)
|
||||
: line_reader_(line_reader),
|
||||
cu_context_(new CUContext(file_context, reporter)),
|
||||
cu_context_(new CUContext(file_context, reporter, ranges_handler)),
|
||||
child_context_(new DIEContext()),
|
||||
has_source_line_info_(false) {
|
||||
}
|
||||
|
@ -732,6 +797,16 @@ void DwarfCUToModule::ProcessAttributeUnsigned(enum DwarfAttribute attr,
|
|||
case dwarf2reader::DW_AT_language: // source language of this CU
|
||||
SetLanguage(static_cast<DwarfLanguage>(data));
|
||||
break;
|
||||
case dwarf2reader::DW_AT_low_pc:
|
||||
cu_context_->low_pc = data;
|
||||
break;
|
||||
case dwarf2reader::DW_AT_high_pc:
|
||||
cu_context_->high_pc = data;
|
||||
break;
|
||||
case dwarf2reader::DW_AT_ranges:
|
||||
cu_context_->ranges = data;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -841,6 +916,46 @@ void DwarfCUToModule::ReadSourceLines(uint64 offset) {
|
|||
}
|
||||
|
||||
namespace {
|
||||
class FunctionRange {
|
||||
public:
|
||||
FunctionRange(const Module::Range &range, Module::Function *function) :
|
||||
address(range.address), size(range.size), function(function) { }
|
||||
|
||||
void AddLine(Module::Line &line) {
|
||||
function->lines.push_back(line);
|
||||
}
|
||||
|
||||
Module::Address address;
|
||||
Module::Address size;
|
||||
Module::Function *function;
|
||||
};
|
||||
|
||||
// Fills an array of ranges with pointers to the functions which owns them.
|
||||
// The array is sorted in ascending order and the ranges are non-overlapping.
|
||||
|
||||
static void FillSortedFunctionRanges(vector<FunctionRange> &dest_ranges,
|
||||
vector<Module::Function *> *functions) {
|
||||
for (vector<Module::Function *>::const_iterator func_it = functions->cbegin();
|
||||
func_it != functions->cend();
|
||||
func_it++)
|
||||
{
|
||||
Module::Function *func = *func_it;
|
||||
vector<Module::Range> &ranges = func->ranges;
|
||||
for (vector<Module::Range>::const_iterator ranges_it = ranges.cbegin();
|
||||
ranges_it != ranges.cend();
|
||||
++ranges_it) {
|
||||
FunctionRange range(*ranges_it, func);
|
||||
dest_ranges.push_back(range);
|
||||
}
|
||||
}
|
||||
|
||||
sort(dest_ranges.begin(), dest_ranges.end(),
|
||||
[](const FunctionRange &fr1, const FunctionRange &fr2) {
|
||||
return fr1.address < fr2.address;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Return true if ADDRESS falls within the range of ITEM.
|
||||
template <class T>
|
||||
inline bool within(const T &item, Module::Address address) {
|
||||
|
@ -880,47 +995,50 @@ void DwarfCUToModule::AssignLinesToFunctions() {
|
|||
const Module::Function *last_function_cited = NULL;
|
||||
const Module::Line *last_line_cited = NULL;
|
||||
|
||||
// Make a single pass through both vectors from lower to higher
|
||||
// addresses, populating each Function's lines vector with lines
|
||||
// from our lines_ vector that fall within the function's address
|
||||
// range.
|
||||
vector<Module::Function *>::iterator func_it = functions->begin();
|
||||
// Prepare a sorted list of ranges with range-to-function mapping
|
||||
vector<FunctionRange> sorted_ranges;
|
||||
FillSortedFunctionRanges(sorted_ranges, functions);
|
||||
|
||||
// Make a single pass through both the range and line vectors from lower to
|
||||
// higher addresses, populating each range's function lines vector with lines
|
||||
// from our lines_ vector that fall within the range.
|
||||
vector<FunctionRange>::iterator range_it = sorted_ranges.begin();
|
||||
vector<Module::Line>::const_iterator line_it = lines_.begin();
|
||||
|
||||
Module::Address current;
|
||||
|
||||
// Pointers to the referents of func_it and line_it, or NULL if the
|
||||
// iterator is at the end of the sequence.
|
||||
Module::Function *func;
|
||||
FunctionRange *range;
|
||||
const Module::Line *line;
|
||||
|
||||
// Start current at the beginning of the first line or function,
|
||||
// whichever is earlier.
|
||||
if (func_it != functions->end() && line_it != lines_.end()) {
|
||||
func = *func_it;
|
||||
if (range_it != sorted_ranges.end() && line_it != lines_.end()) {
|
||||
range = &*range_it;
|
||||
line = &*line_it;
|
||||
current = std::min(func->address, line->address);
|
||||
current = std::min(range->address, line->address);
|
||||
} else if (line_it != lines_.end()) {
|
||||
func = NULL;
|
||||
range = NULL;
|
||||
line = &*line_it;
|
||||
current = line->address;
|
||||
} else if (func_it != functions->end()) {
|
||||
func = *func_it;
|
||||
} else if (range_it != sorted_ranges.end()) {
|
||||
range = &*range_it;
|
||||
line = NULL;
|
||||
current = (*func_it)->address;
|
||||
current = range->address;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
while (func || line) {
|
||||
while (range || line) {
|
||||
// This loop has two invariants that hold at the top.
|
||||
//
|
||||
// First, at least one of the iterators is not at the end of its
|
||||
// sequence, and those that are not refer to the earliest
|
||||
// function or line that contains or starts after CURRENT.
|
||||
// range or line that contains or starts after CURRENT.
|
||||
//
|
||||
// Note that every byte is in one of four states: it is covered
|
||||
// or not covered by a function, and, independently, it is
|
||||
// or not covered by a range, and, independently, it is
|
||||
// covered or not covered by a line.
|
||||
//
|
||||
// The second invariant is that CURRENT refers to a byte whose
|
||||
|
@ -930,7 +1048,7 @@ void DwarfCUToModule::AssignLinesToFunctions() {
|
|||
//
|
||||
// Note that, although each iteration advances CURRENT from one
|
||||
// transition address to the next in each iteration, it might
|
||||
// not advance the iterators. Suppose we have a function that
|
||||
// not advance the iterators. Suppose we have a range that
|
||||
// starts with a line, has a gap, and then a second line, and
|
||||
// suppose that we enter an iteration with CURRENT at the end of
|
||||
// the first line. The next transition address is the start of
|
||||
|
@ -938,11 +1056,11 @@ void DwarfCUToModule::AssignLinesToFunctions() {
|
|||
// advance CURRENT to that point. At the head of that iteration,
|
||||
// the invariants require that the line iterator be pointing at
|
||||
// the second line. But this is also true at the head of the
|
||||
// next. And clearly, the iteration must not change the function
|
||||
// next. And clearly, the iteration must not change the range
|
||||
// iterator. So neither iterator moves.
|
||||
|
||||
// Assert the first invariant (see above).
|
||||
assert(!func || current < func->address || within(*func, current));
|
||||
assert(!range || current < range->address || within(*range, current));
|
||||
assert(!line || current < line->address || within(*line, current));
|
||||
|
||||
// The next transition after CURRENT.
|
||||
|
@ -950,33 +1068,33 @@ void DwarfCUToModule::AssignLinesToFunctions() {
|
|||
|
||||
// Figure out which state we're in, add lines or warn, and compute
|
||||
// the next transition address.
|
||||
if (func && current >= func->address) {
|
||||
if (range && current >= range->address) {
|
||||
if (line && current >= line->address) {
|
||||
// Covered by both a line and a function.
|
||||
Module::Address func_left = func->size - (current - func->address);
|
||||
// Covered by both a line and a range.
|
||||
Module::Address range_left = range->size - (current - range->address);
|
||||
Module::Address line_left = line->size - (current - line->address);
|
||||
// This may overflow, but things work out.
|
||||
next_transition = current + std::min(func_left, line_left);
|
||||
next_transition = current + std::min(range_left, line_left);
|
||||
Module::Line l = *line;
|
||||
l.address = current;
|
||||
l.size = next_transition - current;
|
||||
func->lines.push_back(l);
|
||||
range->AddLine(l);
|
||||
last_line_used = line;
|
||||
} else {
|
||||
// Covered by a function, but no line.
|
||||
if (func != last_function_cited) {
|
||||
reporter->UncoveredFunction(*func);
|
||||
last_function_cited = func;
|
||||
// Covered by a range, but no line.
|
||||
if (range->function != last_function_cited) {
|
||||
reporter->UncoveredFunction(*(range->function));
|
||||
last_function_cited = range->function;
|
||||
}
|
||||
if (line && within(*func, line->address))
|
||||
if (line && within(*range, line->address))
|
||||
next_transition = line->address;
|
||||
else
|
||||
// If this overflows, we'll catch it below.
|
||||
next_transition = func->address + func->size;
|
||||
next_transition = range->address + range->size;
|
||||
}
|
||||
} else {
|
||||
if (line && current >= line->address) {
|
||||
// Covered by a line, but no function.
|
||||
// Covered by a line, but no range.
|
||||
//
|
||||
// If GCC emits padding after one function to align the start
|
||||
// of the next, then it will attribute the padding
|
||||
|
@ -988,27 +1106,27 @@ void DwarfCUToModule::AssignLinesToFunctions() {
|
|||
// start of the next function, then assume this is what
|
||||
// happened, and don't warn.
|
||||
if (line != last_line_cited
|
||||
&& !(func
|
||||
&& !(range
|
||||
&& line == last_line_used
|
||||
&& func->address - line->address == line->size)) {
|
||||
&& range->address - line->address == line->size)) {
|
||||
reporter->UncoveredLine(*line);
|
||||
last_line_cited = line;
|
||||
}
|
||||
if (func && within(*line, func->address))
|
||||
next_transition = func->address;
|
||||
if (range && within(*line, range->address))
|
||||
next_transition = range->address;
|
||||
else
|
||||
// If this overflows, we'll catch it below.
|
||||
next_transition = line->address + line->size;
|
||||
} else {
|
||||
// Covered by neither a function nor a line. By the invariant,
|
||||
// both func and line begin after CURRENT. The next transition
|
||||
// is the start of the next function or next line, whichever
|
||||
// Covered by neither a range nor a line. By the invariant,
|
||||
// both range and line begin after CURRENT. The next transition
|
||||
// is the start of the next range or next line, whichever
|
||||
// is earliest.
|
||||
assert(func || line);
|
||||
if (func && line)
|
||||
next_transition = std::min(func->address, line->address);
|
||||
else if (func)
|
||||
next_transition = func->address;
|
||||
assert(range || line);
|
||||
if (range && line)
|
||||
next_transition = std::min(range->address, line->address);
|
||||
else if (range)
|
||||
next_transition = range->address;
|
||||
else
|
||||
next_transition = line->address;
|
||||
}
|
||||
|
@ -1025,11 +1143,11 @@ void DwarfCUToModule::AssignLinesToFunctions() {
|
|||
// then we could go around more than once. We don't worry too much
|
||||
// about what result we produce in that case, just as long as we don't
|
||||
// hang or crash.
|
||||
while (func_it != functions->end()
|
||||
&& next_transition >= (*func_it)->address
|
||||
&& !within(**func_it, next_transition))
|
||||
func_it++;
|
||||
func = (func_it != functions->end()) ? *func_it : NULL;
|
||||
while (range_it != sorted_ranges.end()
|
||||
&& next_transition >= range_it->address
|
||||
&& !within(*range_it, next_transition))
|
||||
range_it++;
|
||||
range = (range_it != sorted_ranges.end()) ? &(*range_it) : NULL;
|
||||
while (line_it != lines_.end()
|
||||
&& next_transition >= line_it->address
|
||||
&& !within(*line_it, next_transition))
|
||||
|
|
|
@ -123,6 +123,22 @@ class DwarfCUToModule: public dwarf2reader::RootDIEHandler {
|
|||
scoped_ptr<FilePrivate> file_private_;
|
||||
};
|
||||
|
||||
// An abstract base class for handlers that handle DWARF range lists for
|
||||
// DwarfCUToModule.
|
||||
class RangesHandler {
|
||||
public:
|
||||
RangesHandler() { }
|
||||
virtual ~RangesHandler() { }
|
||||
|
||||
// Called when finishing a function to populate the function's ranges.
|
||||
// The ranges' entries are read starting from offset in the .debug_ranges
|
||||
// section, base_address holds the base PC the range list values are
|
||||
// offsets off. Return false if the rangelist falls out of the
|
||||
// .debug_ranges section.
|
||||
virtual bool ReadRanges(uint64 offset, Module::Address base_address,
|
||||
vector<Module::Range>* ranges) = 0;
|
||||
};
|
||||
|
||||
// An abstract base class for handlers that handle DWARF line data
|
||||
// for DwarfCUToModule. DwarfCUToModule could certainly just use
|
||||
// dwarf2reader::LineInfo itself directly, but decoupling things
|
||||
|
@ -208,6 +224,14 @@ class DwarfCUToModule: public dwarf2reader::RootDIEHandler {
|
|||
// FilePrivate did not retain the inter-CU specification data.
|
||||
virtual void UnhandledInterCUReference(uint64 offset, uint64 target);
|
||||
|
||||
// The DW_AT_ranges at offset is malformed (truncated or outside of the
|
||||
// .debug_ranges section's bound).
|
||||
virtual void MalformedRangeList(uint64 offset);
|
||||
|
||||
// A DW_AT_ranges attribute was encountered but the no .debug_ranges
|
||||
// section was found.
|
||||
virtual void MissingRanges();
|
||||
|
||||
uint64 cu_offset() const {
|
||||
return cu_offset_;
|
||||
}
|
||||
|
@ -235,6 +259,7 @@ class DwarfCUToModule: public dwarf2reader::RootDIEHandler {
|
|||
// data we find.
|
||||
DwarfCUToModule(FileContext *file_context,
|
||||
LineToModuleHandler *line_reader,
|
||||
RangesHandler *ranges_handler,
|
||||
WarningReporter *reporter);
|
||||
~DwarfCUToModule();
|
||||
|
||||
|
@ -296,6 +321,9 @@ class DwarfCUToModule: public dwarf2reader::RootDIEHandler {
|
|||
// The handler to use to handle line number data.
|
||||
LineToModuleHandler *line_reader_;
|
||||
|
||||
// The handler to use to handle range lists.
|
||||
RangesHandler *ranges_handler_;
|
||||
|
||||
// This compilation unit's context.
|
||||
scoped_ptr<CUContext> cu_context_;
|
||||
|
||||
|
|
|
@ -128,7 +128,8 @@ class CUFixtureBase {
|
|||
language_signed_(false),
|
||||
appender_(&lines_),
|
||||
reporter_("dwarf-filename", 0xcf8f9bb6443d29b5LL),
|
||||
root_handler_(&file_context_, &line_reader_, &reporter_),
|
||||
root_handler_(&file_context_, &line_reader_,
|
||||
/* ranges_reader */ nullptr, &reporter_),
|
||||
functions_filled_(false) {
|
||||
// By default, expect no warnings to be reported, and expect the
|
||||
// compilation unit's name to be provided. The test can override
|
||||
|
@ -597,7 +598,7 @@ void CUFixtureBase::TestFunction(int i, const string &name,
|
|||
Module::Function *function = functions_[i];
|
||||
EXPECT_EQ(name, function->name);
|
||||
EXPECT_EQ(address, function->address);
|
||||
EXPECT_EQ(size, function->size);
|
||||
EXPECT_EQ(size, function->ranges[0].size);
|
||||
EXPECT_EQ(0U, function->parameter_size);
|
||||
}
|
||||
|
||||
|
@ -1515,7 +1516,7 @@ TEST_F(Specifications, InterCU) {
|
|||
|
||||
// First CU. Declares class_A.
|
||||
{
|
||||
DwarfCUToModule root1_handler(&fc, &lr, &reporter_);
|
||||
DwarfCUToModule root1_handler(&fc, &lr, nullptr, &reporter_);
|
||||
ASSERT_TRUE(root1_handler.StartCompilationUnit(0, 1, 2, 3, 3));
|
||||
ASSERT_TRUE(root1_handler.StartRootDIE(1,
|
||||
dwarf2reader::DW_TAG_compile_unit));
|
||||
|
@ -1528,7 +1529,7 @@ TEST_F(Specifications, InterCU) {
|
|||
|
||||
// Second CU. Defines class_A, declares member_func_B.
|
||||
{
|
||||
DwarfCUToModule root2_handler(&fc, &lr, &reporter_);
|
||||
DwarfCUToModule root2_handler(&fc, &lr, nullptr, &reporter_);
|
||||
ASSERT_TRUE(root2_handler.StartCompilationUnit(0, 1, 2, 3, 3));
|
||||
ASSERT_TRUE(root2_handler.StartRootDIE(1,
|
||||
dwarf2reader::DW_TAG_compile_unit));
|
||||
|
@ -1545,7 +1546,7 @@ TEST_F(Specifications, InterCU) {
|
|||
|
||||
// Third CU. Defines member_func_B.
|
||||
{
|
||||
DwarfCUToModule root3_handler(&fc, &lr, &reporter_);
|
||||
DwarfCUToModule root3_handler(&fc, &lr, nullptr, &reporter_);
|
||||
ASSERT_TRUE(root3_handler.StartCompilationUnit(0, 1, 2, 3, 3));
|
||||
ASSERT_TRUE(root3_handler.StartRootDIE(1,
|
||||
dwarf2reader::DW_TAG_compile_unit));
|
||||
|
@ -1574,7 +1575,7 @@ TEST_F(Specifications, UnhandledInterCU) {
|
|||
|
||||
// First CU. Declares class_A.
|
||||
{
|
||||
DwarfCUToModule root1_handler(&fc, &lr, &reporter_);
|
||||
DwarfCUToModule root1_handler(&fc, &lr, nullptr, &reporter_);
|
||||
ASSERT_TRUE(root1_handler.StartCompilationUnit(0, 1, 2, 3, 3));
|
||||
ASSERT_TRUE(root1_handler.StartRootDIE(1,
|
||||
dwarf2reader::DW_TAG_compile_unit));
|
||||
|
@ -1587,7 +1588,7 @@ TEST_F(Specifications, UnhandledInterCU) {
|
|||
|
||||
// Second CU. Defines class_A, declares member_func_B.
|
||||
{
|
||||
DwarfCUToModule root2_handler(&fc, &lr, &reporter_);
|
||||
DwarfCUToModule root2_handler(&fc, &lr, nullptr, &reporter_);
|
||||
ASSERT_TRUE(root2_handler.StartCompilationUnit(0, 1, 2, 3, 3));
|
||||
ASSERT_TRUE(root2_handler.StartRootDIE(1,
|
||||
dwarf2reader::DW_TAG_compile_unit));
|
||||
|
@ -1605,7 +1606,7 @@ TEST_F(Specifications, UnhandledInterCU) {
|
|||
|
||||
// Third CU. Defines member_func_B.
|
||||
{
|
||||
DwarfCUToModule root3_handler(&fc, &lr, &reporter_);
|
||||
DwarfCUToModule root3_handler(&fc, &lr, nullptr, &reporter_);
|
||||
ASSERT_TRUE(root3_handler.StartCompilationUnit(0, 1, 2, 3, 3));
|
||||
ASSERT_TRUE(root3_handler.StartRootDIE(1,
|
||||
dwarf2reader::DW_TAG_compile_unit));
|
||||
|
@ -1791,7 +1792,8 @@ struct Reporter: public Test {
|
|||
file("source file name") {
|
||||
reporter.SetCUName("compilation-unit-name");
|
||||
|
||||
function.size = 0x89808a5bdfa0a6a3ULL;
|
||||
Module::Range range(0x19c45c30770c1eb0ULL, 0x89808a5bdfa0a6a3ULL);
|
||||
function.ranges.push_back(range);
|
||||
function.parameter_size = 0x6a329f18683dcd51ULL;
|
||||
|
||||
line.address = 0x3606ac6267aebeccULL;
|
||||
|
|
60
src/common/dwarf_range_list_handler.cc
Normal file
60
src/common/dwarf_range_list_handler.cc
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) 2018 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.
|
||||
|
||||
// Original author: Gabriele Svelto <gsvelto@mozilla.com>
|
||||
// <gabriele.svelto@gmail.com>
|
||||
|
||||
// dwarf_range_list_handler.cc: Implementation of DwarfRangeListHandler class.
|
||||
// See dwarf_range_list_handler.h for details.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common/dwarf_range_list_handler.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
void DwarfRangeListHandler::AddRange(uint64 begin, uint64 end) {
|
||||
Module::Range r(begin + base_address_, end - begin);
|
||||
|
||||
ranges_->push_back(r);
|
||||
}
|
||||
|
||||
void DwarfRangeListHandler::SetBaseAddress(uint64 base_address) {
|
||||
base_address_ = base_address;
|
||||
}
|
||||
|
||||
void DwarfRangeListHandler::Finish() {
|
||||
std::sort(ranges_->begin(), ranges_->end(),
|
||||
[](const Module::Range &a, const Module::Range &b) {
|
||||
return a.address < b.address;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
79
src/common/dwarf_range_list_handler.h
Normal file
79
src/common/dwarf_range_list_handler.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
// -*- mode: c++ -*-
|
||||
|
||||
// Copyright (c) 2018 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.
|
||||
|
||||
// Original author: Gabriele Svelto <gsvelto@mozilla.com>
|
||||
// <gabriele.svelto@gmail.com>
|
||||
|
||||
// The DwarfRangeListHandler class accepts rangelist data from a DWARF parser
|
||||
// and adds it to a google_breakpad::Function or other objects supporting
|
||||
// ranges.
|
||||
|
||||
#ifndef COMMON_LINUX_DWARF_RANGE_LIST_HANDLER_H
|
||||
#define COMMON_LINUX_DWARF_RANGE_LIST_HANDLER_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "common/module.h"
|
||||
#include "common/dwarf/dwarf2reader.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// A class for producing a vector of google_breakpad::Module::Range
|
||||
// instances from a parsed DWARF range list.
|
||||
|
||||
class DwarfRangeListHandler: public dwarf2reader::RangeListHandler {
|
||||
public:
|
||||
DwarfRangeListHandler(uint64 base_address, vector<Module::Range> *ranges)
|
||||
: base_address_(base_address), ranges_(ranges) { }
|
||||
|
||||
~DwarfRangeListHandler() { }
|
||||
|
||||
// Add a range to the list
|
||||
void AddRange(uint64 begin, uint64 end);
|
||||
|
||||
// Record the new base address and use it for the following entries
|
||||
void SetBaseAddress(uint64 base_address);
|
||||
|
||||
// Sort the ranges so that they are in ascending order of starting address
|
||||
void Finish();
|
||||
|
||||
private:
|
||||
// The current PC to add to every entry, this can be overridden by a special
|
||||
// list entry
|
||||
uint64 base_address_;
|
||||
|
||||
// The list of ranges to be populated
|
||||
vector<Module::Range> *ranges_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_LINUX_DWARF_RANGE_LIST_HANDLER_H
|
|
@ -58,6 +58,7 @@
|
|||
#include "common/dwarf_cfi_to_module.h"
|
||||
#include "common/dwarf_cu_to_module.h"
|
||||
#include "common/dwarf_line_to_module.h"
|
||||
#include "common/dwarf_range_list_handler.h"
|
||||
#include "common/linux/crc32.h"
|
||||
#include "common/linux/eintr_wrapper.h"
|
||||
#include "common/linux/elfutils.h"
|
||||
|
@ -81,6 +82,7 @@ using google_breakpad::DumpOptions;
|
|||
using google_breakpad::DwarfCFIToModule;
|
||||
using google_breakpad::DwarfCUToModule;
|
||||
using google_breakpad::DwarfLineToModule;
|
||||
using google_breakpad::DwarfRangeListHandler;
|
||||
using google_breakpad::ElfClass;
|
||||
using google_breakpad::ElfClass32;
|
||||
using google_breakpad::ElfClass64;
|
||||
|
@ -207,6 +209,30 @@ bool LoadStabs(const typename ElfClass::Ehdr* elf_header,
|
|||
}
|
||||
#endif // NO_STABS_SUPPORT
|
||||
|
||||
// A range handler that accepts rangelist data parsed by
|
||||
// dwarf2reader::RangeListReader and populates a range vector (typically
|
||||
// owned by a function) with the results.
|
||||
class DumperRangesHandler : public DwarfCUToModule::RangesHandler {
|
||||
public:
|
||||
DumperRangesHandler(const uint8_t *buffer, uint64 size,
|
||||
dwarf2reader::ByteReader* reader)
|
||||
: buffer_(buffer), size_(size), reader_(reader) { }
|
||||
|
||||
bool ReadRanges(uint64 offset, Module::Address base_address,
|
||||
vector<Module::Range>* ranges) {
|
||||
DwarfRangeListHandler handler(base_address, ranges);
|
||||
dwarf2reader::RangeListReader rangelist_reader(buffer_, size_, reader_,
|
||||
&handler);
|
||||
|
||||
return rangelist_reader.ReadRangeList(offset);
|
||||
}
|
||||
|
||||
private:
|
||||
const uint8_t *buffer_;
|
||||
uint64 size_;
|
||||
dwarf2reader::ByteReader* reader_;
|
||||
};
|
||||
|
||||
// A line-to-module loader that accepts line number info parsed by
|
||||
// dwarf2reader::LineInfo and populates a Module and a line vector
|
||||
// with the results.
|
||||
|
@ -261,6 +287,18 @@ bool LoadDwarf(const string& dwarf_filename,
|
|||
file_context.AddSectionToSectionMap(name, contents, section->sh_size);
|
||||
}
|
||||
|
||||
// Optional .debug_ranges reader
|
||||
scoped_ptr<DumperRangesHandler> ranges_handler;
|
||||
dwarf2reader::SectionMap::const_iterator ranges_entry =
|
||||
file_context.section_map().find(".debug_ranges");
|
||||
if (ranges_entry != file_context.section_map().end()) {
|
||||
const std::pair<const uint8_t *, uint64>& ranges_section =
|
||||
ranges_entry->second;
|
||||
ranges_handler.reset(
|
||||
new DumperRangesHandler(ranges_section.first, ranges_section.second,
|
||||
&byte_reader));
|
||||
}
|
||||
|
||||
// Parse all the compilation units in the .debug_info section.
|
||||
DumperLineToModule line_to_module(&byte_reader);
|
||||
dwarf2reader::SectionMap::const_iterator debug_info_entry =
|
||||
|
@ -276,7 +314,8 @@ bool LoadDwarf(const string& dwarf_filename,
|
|||
// Make a handler for the root DIE that populates MODULE with the
|
||||
// data that was found.
|
||||
DwarfCUToModule::WarningReporter reporter(dwarf_filename, offset);
|
||||
DwarfCUToModule root_handler(&file_context, &line_to_module, &reporter);
|
||||
DwarfCUToModule root_handler(&file_context, &line_to_module,
|
||||
ranges_handler.get(), &reporter);
|
||||
// Make a Dwarf2Handler that drives the DIEHandler.
|
||||
dwarf2reader::DIEDispatcher die_dispatcher(&root_handler);
|
||||
// Make a DWARF parser for the compilation unit at OFFSET.
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "common/dwarf_cfi_to_module.h"
|
||||
#include "common/dwarf_cu_to_module.h"
|
||||
#include "common/dwarf_line_to_module.h"
|
||||
#include "common/dwarf_range_list_handler.h"
|
||||
#include "common/mac/file_id.h"
|
||||
#include "common/mac/arch_utilities.h"
|
||||
#include "common/mac/macho_reader.h"
|
||||
|
@ -76,6 +77,7 @@
|
|||
using dwarf2reader::ByteReader;
|
||||
using google_breakpad::DwarfCUToModule;
|
||||
using google_breakpad::DwarfLineToModule;
|
||||
using google_breakpad::DwarfRangeListHandler;
|
||||
using google_breakpad::FileID;
|
||||
using google_breakpad::mach_o::FatReader;
|
||||
using google_breakpad::mach_o::Section;
|
||||
|
@ -303,6 +305,31 @@ string DumpSymbols::Identifier() {
|
|||
return compacted;
|
||||
}
|
||||
|
||||
// A range handler that accepts rangelist data parsed by
|
||||
// dwarf2reader::RangeListReader and populates a range vector (typically
|
||||
// owned by a function) with the results.
|
||||
class DumpSymbols::DumperRangesHandler:
|
||||
public DwarfCUToModule::RangesHandler {
|
||||
public:
|
||||
DumperRangesHandler(const uint8_t *buffer, uint64 size,
|
||||
dwarf2reader::ByteReader* reader)
|
||||
: buffer_(buffer), size_(size), reader_(reader) { }
|
||||
|
||||
bool ReadRanges(uint64 offset, Module::Address base_address,
|
||||
vector<Module::Range>* ranges) {
|
||||
DwarfRangeListHandler handler(base_address, ranges);
|
||||
dwarf2reader::RangeListReader rangelist_reader(buffer_, size_, reader_,
|
||||
&handler);
|
||||
|
||||
return rangelist_reader.ReadRangeList(offset);
|
||||
}
|
||||
|
||||
private:
|
||||
const uint8_t *buffer_;
|
||||
uint64 size_;
|
||||
dwarf2reader::ByteReader* reader_;
|
||||
};
|
||||
|
||||
// A line-to-module loader that accepts line number info parsed by
|
||||
// dwarf2reader::LineInfo and populates a Module and a line vector
|
||||
// with the results.
|
||||
|
@ -425,6 +452,18 @@ bool DumpSymbols::ReadDwarf(google_breakpad::Module *module,
|
|||
// Build a line-to-module loader for the root handler to use.
|
||||
DumperLineToModule line_to_module(&byte_reader);
|
||||
|
||||
// Optional .debug_ranges reader
|
||||
scoped_ptr<DumperRangesHandler> ranges_handler;
|
||||
dwarf2reader::SectionMap::const_iterator ranges_entry =
|
||||
file_context.section_map().find("__debug_ranges");
|
||||
if (ranges_entry != file_context.section_map().end()) {
|
||||
const std::pair<const uint8_t *, uint64>& ranges_section =
|
||||
ranges_entry->second;
|
||||
ranges_handler.reset(
|
||||
new DumperRangesHandler(ranges_section.first, ranges_section.second,
|
||||
&byte_reader));
|
||||
}
|
||||
|
||||
// Walk the __debug_info section, one compilation unit at a time.
|
||||
uint64 debug_info_length = debug_info_section.second;
|
||||
for (uint64 offset = 0; offset < debug_info_length;) {
|
||||
|
@ -432,7 +471,8 @@ bool DumpSymbols::ReadDwarf(google_breakpad::Module *module,
|
|||
// debug info.
|
||||
DwarfCUToModule::WarningReporter reporter(selected_object_name_,
|
||||
offset);
|
||||
DwarfCUToModule root_handler(&file_context, &line_to_module, &reporter);
|
||||
DwarfCUToModule root_handler(&file_context, &line_to_module,
|
||||
ranges_handler.get(), &reporter);
|
||||
// Make a Dwarf2Handler that drives our DIEHandler.
|
||||
dwarf2reader::DIEDispatcher die_dispatcher(&root_handler);
|
||||
// Make a DWARF parser for the compilation unit at OFFSET.
|
||||
|
|
|
@ -125,6 +125,7 @@ class DumpSymbols {
|
|||
private:
|
||||
// Used internally.
|
||||
class DumperLineToModule;
|
||||
class DumperRangesHandler;
|
||||
class LoadCommandDumper;
|
||||
|
||||
// This method behaves similarly to NXFindBestFatArch, but it supports
|
||||
|
|
|
@ -258,24 +258,33 @@ bool Module::Write(std::ostream &stream, SymbolData symbol_data) {
|
|||
for (FunctionSet::const_iterator func_it = functions_.begin();
|
||||
func_it != functions_.end(); ++func_it) {
|
||||
Function *func = *func_it;
|
||||
stream << "FUNC " << hex
|
||||
<< (func->address - load_address_) << " "
|
||||
<< func->size << " "
|
||||
<< func->parameter_size << " "
|
||||
<< func->name << dec << "\n";
|
||||
if (!stream.good())
|
||||
return ReportError();
|
||||
vector<Line>::iterator line_it = func->lines.begin();
|
||||
for (auto range_it = func->ranges.cbegin();
|
||||
range_it != func->ranges.cend(); ++range_it) {
|
||||
stream << "FUNC " << hex
|
||||
<< (range_it->address - load_address_) << " "
|
||||
<< range_it->size << " "
|
||||
<< func->parameter_size << " "
|
||||
<< func->name << dec << "\n";
|
||||
|
||||
for (vector<Line>::iterator line_it = func->lines.begin();
|
||||
line_it != func->lines.end(); ++line_it) {
|
||||
stream << hex
|
||||
<< (line_it->address - load_address_) << " "
|
||||
<< line_it->size << " "
|
||||
<< dec
|
||||
<< line_it->number << " "
|
||||
<< line_it->file->source_id << "\n";
|
||||
if (!stream.good())
|
||||
return ReportError();
|
||||
|
||||
while ((line_it != func->lines.end()) &&
|
||||
(line_it->address >= range_it->address) &&
|
||||
(line_it->address < (range_it->address + range_it->size))) {
|
||||
stream << hex
|
||||
<< (line_it->address - load_address_) << " "
|
||||
<< line_it->size << " "
|
||||
<< dec
|
||||
<< line_it->number << " "
|
||||
<< line_it->file->source_id << "\n";
|
||||
|
||||
if (!stream.good())
|
||||
return ReportError();
|
||||
|
||||
++line_it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -85,10 +85,19 @@ class Module {
|
|||
int source_id;
|
||||
};
|
||||
|
||||
// An address range.
|
||||
struct Range {
|
||||
Range(const Address address_input, const Address size_input) :
|
||||
address(address_input), size(size_input) { }
|
||||
|
||||
Address address;
|
||||
Address size;
|
||||
};
|
||||
|
||||
// A function.
|
||||
struct Function {
|
||||
Function(const string &name_input, const Address &address_input) :
|
||||
name(name_input), address(address_input), size(0), parameter_size(0) {}
|
||||
name(name_input), address(address_input), parameter_size(0) {}
|
||||
|
||||
// For sorting by address. (Not style-guide compliant, but it's
|
||||
// stupid not to put this in the struct.)
|
||||
|
@ -99,9 +108,9 @@ class Module {
|
|||
// The function's name.
|
||||
const string name;
|
||||
|
||||
// The start address and length of the function's code.
|
||||
// The start address and the address ranges covered by the function.
|
||||
const Address address;
|
||||
Address size;
|
||||
vector<Range> ranges;
|
||||
|
||||
// The function's parameter size.
|
||||
Address parameter_size;
|
||||
|
|
|
@ -55,7 +55,8 @@ static Module::Function *generate_duplicate_function(const string &name) {
|
|||
const Module::Address DUP_PARAMETER_SIZE = 0xf14ac4fed48c4a99LL;
|
||||
|
||||
Module::Function *function = new Module::Function(name, DUP_ADDRESS);
|
||||
function->size = DUP_SIZE;
|
||||
Module::Range range(DUP_ADDRESS, DUP_SIZE);
|
||||
function->ranges.push_back(range);
|
||||
function->parameter_size = DUP_PARAMETER_SIZE;
|
||||
return function;
|
||||
}
|
||||
|
@ -92,7 +93,8 @@ TEST(Write, OneLineFunc) {
|
|||
Module::File *file = m.FindFile("file_name.cc");
|
||||
Module::Function *function = new Module::Function(
|
||||
"function_name", 0xe165bf8023b9d9abLL);
|
||||
function->size = 0x1e4bb0eb1cbf5b09LL;
|
||||
Module::Range range(0xe165bf8023b9d9abLL, 0x1e4bb0eb1cbf5b09LL);
|
||||
function->ranges.push_back(range);
|
||||
function->parameter_size = 0x772beee89114358aLL;
|
||||
Module::Line line = { 0xe165bf8023b9d9abLL, 0x1e4bb0eb1cbf5b09LL,
|
||||
file, 67519080 };
|
||||
|
@ -120,7 +122,8 @@ TEST(Write, RelativeLoadAddress) {
|
|||
// A function.
|
||||
Module::Function *function = new Module::Function(
|
||||
"A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)", 0xbec774ea5dd935f3LL);
|
||||
function->size = 0x2922088f98d3f6fcLL;
|
||||
Module::Range range(0xbec774ea5dd935f3LL, 0x2922088f98d3f6fcLL);
|
||||
function->ranges.push_back(range);
|
||||
function->parameter_size = 0xe5e9aa008bd5f0d0LL;
|
||||
|
||||
// Some source lines. The module should not sort these.
|
||||
|
@ -177,13 +180,14 @@ TEST(Write, OmitUnusedFiles) {
|
|||
// Create a function.
|
||||
Module::Function *function = new Module::Function(
|
||||
"function_name", 0x9b926d464f0b9384LL);
|
||||
function->size = 0x4f524a4ba795e6a6LL;
|
||||
Module::Range range(0x9b926d464f0b9384LL, 0x4f524a4ba795e6a6LL);
|
||||
function->ranges.push_back(range);
|
||||
function->parameter_size = 0xbbe8133a6641c9b7LL;
|
||||
|
||||
// Source files that refer to some files, but not others.
|
||||
Module::Line line1 = { 0x595fa44ebacc1086LL, 0x1e1e0191b066c5b3LL,
|
||||
Module::Line line1 = { 0xab415089485e1a20LL, 0x126e3124979291f2LL,
|
||||
file1, 137850127 };
|
||||
Module::Line line2 = { 0x401ce8c8a12d25e3LL, 0x895751c41b8d2ce2LL,
|
||||
Module::Line line2 = { 0xb2675b5c3c2ed33fLL, 0x1df77f5551dbd68cLL,
|
||||
file3, 28113549 };
|
||||
function->lines.push_back(line1);
|
||||
function->lines.push_back(line2);
|
||||
|
@ -210,8 +214,8 @@ TEST(Write, OmitUnusedFiles) {
|
|||
"FILE 1 filename3\n"
|
||||
"FUNC 9b926d464f0b9384 4f524a4ba795e6a6 bbe8133a6641c9b7"
|
||||
" function_name\n"
|
||||
"595fa44ebacc1086 1e1e0191b066c5b3 137850127 0\n"
|
||||
"401ce8c8a12d25e3 895751c41b8d2ce2 28113549 1\n",
|
||||
"ab415089485e1a20 126e3124979291f2 137850127 0\n"
|
||||
"b2675b5c3c2ed33f 1df77f5551dbd68c 28113549 1\n",
|
||||
contents.c_str());
|
||||
}
|
||||
|
||||
|
@ -225,7 +229,8 @@ TEST(Write, NoCFI) {
|
|||
// A function.
|
||||
Module::Function *function = new Module::Function(
|
||||
"A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)", 0xbec774ea5dd935f3LL);
|
||||
function->size = 0x2922088f98d3f6fcLL;
|
||||
Module::Range range(0xbec774ea5dd935f3LL, 0x2922088f98d3f6fcLL);
|
||||
function->ranges.push_back(range);
|
||||
function->parameter_size = 0xe5e9aa008bd5f0d0LL;
|
||||
|
||||
// Some source lines. The module should not sort these.
|
||||
|
@ -267,12 +272,14 @@ TEST(Construct, AddFunctions) {
|
|||
// Two functions.
|
||||
Module::Function *function1 = new Module::Function(
|
||||
"_without_form", 0xd35024aa7ca7da5cLL);
|
||||
function1->size = 0x200b26e605f99071LL;
|
||||
Module::Range r1(0xd35024aa7ca7da5cLL, 0x200b26e605f99071LL);
|
||||
function1->ranges.push_back(r1);
|
||||
function1->parameter_size = 0xf14ac4fed48c4a99LL;
|
||||
|
||||
Module::Function *function2 = new Module::Function(
|
||||
"_and_void", 0x2987743d0b35b13fLL);
|
||||
function2->size = 0xb369db048deb3010LL;
|
||||
Module::Range r2(0x2987743d0b35b13fLL, 0xb369db048deb3010LL);
|
||||
function2->ranges.push_back(r2);
|
||||
function2->parameter_size = 0x938e556cb5a79988LL;
|
||||
|
||||
// Put them in a vector.
|
||||
|
@ -504,7 +511,8 @@ TEST(Construct, FunctionsAndExternsWithSameAddress) {
|
|||
m.AddExtern(extern2);
|
||||
|
||||
Module::Function* function = new Module::Function("_xyz", 0xfff0);
|
||||
function->size = 0x10;
|
||||
Module::Range range(0xfff0, 0x10);
|
||||
function->ranges.push_back(range);
|
||||
function->parameter_size = 0;
|
||||
m.AddFunction(function);
|
||||
|
||||
|
@ -541,7 +549,8 @@ TEST(Construct, FunctionsAndThumbExternsWithSameAddress) {
|
|||
// The corresponding function from the DWARF debug data have the actual
|
||||
// address.
|
||||
Module::Function* function = new Module::Function("_thumb_xyz", 0xfff0);
|
||||
function->size = 0x10;
|
||||
Module::Range range(0xfff0, 0x10);
|
||||
function->ranges.push_back(range);
|
||||
function->parameter_size = 0;
|
||||
m.AddFunction(function);
|
||||
|
||||
|
|
|
@ -91,7 +91,8 @@ bool StabsToModule::StartFunction(const string &name,
|
|||
uint64_t address) {
|
||||
assert(!current_function_);
|
||||
Module::Function *f = new Module::Function(Demangle(name), address);
|
||||
f->size = 0; // We compute this in StabsToModule::Finalize().
|
||||
Module::Range r(address, 0); // We compute this in StabsToModule::Finalize().
|
||||
f->ranges.push_back(r);
|
||||
f->parameter_size = 0; // We don't provide this information.
|
||||
current_function_ = f;
|
||||
boundaries_.push_back(static_cast<Module::Address>(address));
|
||||
|
@ -167,14 +168,14 @@ void StabsToModule::Finalize() {
|
|||
vector<Module::Address>::const_iterator boundary
|
||||
= std::upper_bound(boundaries_.begin(), boundaries_.end(), f->address);
|
||||
if (boundary != boundaries_.end())
|
||||
f->size = *boundary - f->address;
|
||||
f->ranges[0].size = *boundary - f->address;
|
||||
else
|
||||
// If this is the last function in the module, and the STABS
|
||||
// reader was unable to give us its ending address, then assign
|
||||
// it a bogus, very large value. This will happen at most once
|
||||
// per module: since we've added all functions' addresses to the
|
||||
// boundary table, only one can be the last.
|
||||
f->size = kFallbackSize;
|
||||
f->ranges[0].size = kFallbackSize;
|
||||
|
||||
// Compute sizes for each of the function f's lines --- if it has any.
|
||||
if (!f->lines.empty()) {
|
||||
|
@ -185,7 +186,8 @@ void StabsToModule::Finalize() {
|
|||
line_it != last_line; line_it++)
|
||||
line_it[0].size = line_it[1].address - line_it[0].address;
|
||||
// Compute the size of the last line from f's end address.
|
||||
last_line->size = (f->address + f->size) - last_line->address;
|
||||
last_line->size =
|
||||
(f->ranges[0].address + f->ranges[0].size) - last_line->address;
|
||||
}
|
||||
}
|
||||
// Now that everything has a size, add our functions to the module, and
|
||||
|
|
|
@ -64,7 +64,7 @@ TEST(StabsToModule, SimpleCU) {
|
|||
Module::Function *function = functions[0];
|
||||
EXPECT_STREQ("function", function->name.c_str());
|
||||
EXPECT_EQ(0xfde4abbed390c394LL, function->address);
|
||||
EXPECT_EQ(0x10U, function->size);
|
||||
EXPECT_EQ(0x10U, function->ranges[0].size);
|
||||
EXPECT_EQ(0U, function->parameter_size);
|
||||
ASSERT_EQ((size_t) 1, function->lines.size());
|
||||
Module::Line *line = &function->lines[0];
|
||||
|
@ -130,7 +130,7 @@ TEST(StabsToModule, DuplicateFunctionNames) {
|
|||
|
||||
Module::Function *function = functions[0];
|
||||
EXPECT_EQ(0xf2cfda36ecf7f46dLL, function->address);
|
||||
EXPECT_LT(0U, function->size); // should have used dummy size
|
||||
EXPECT_LT(0U, function->ranges[0].size); // should have used dummy size
|
||||
EXPECT_EQ(0U, function->parameter_size);
|
||||
ASSERT_EQ(0U, function->lines.size());
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ TEST(InferSizes, LineSize) {
|
|||
Module::Function *function = functions[0];
|
||||
EXPECT_STREQ("function", function->name.c_str());
|
||||
EXPECT_EQ(0xb4513962eff94e92LL, function->address);
|
||||
EXPECT_EQ(0x1000100000000ULL, function->size); // inferred from CU end
|
||||
EXPECT_EQ(0x1000100000000ULL, function->ranges[0].size); // inferred from CU end
|
||||
EXPECT_EQ(0U, function->parameter_size);
|
||||
ASSERT_EQ((size_t) 2, function->lines.size());
|
||||
|
||||
|
@ -216,7 +216,7 @@ TEST(FunctionNames, Mangled) {
|
|||
"push_back(unsigned long long const&)",
|
||||
function->name.c_str());
|
||||
EXPECT_EQ(0xf2cfda63cef7f46dLL, function->address);
|
||||
EXPECT_LT(0U, function->size); // should have used dummy size
|
||||
EXPECT_LT(0U, function->ranges[0].size); // should have used dummy size
|
||||
EXPECT_EQ(0U, function->parameter_size);
|
||||
ASSERT_EQ(0U, function->lines.size());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue