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:
Gabriele Svelto 2018-08-04 00:59:34 +02:00 committed by Ted Mielczarek
parent 7b98edabb6
commit 16e08520e6
20 changed files with 653 additions and 122 deletions

View file

@ -574,6 +574,7 @@ src_tools_linux_dump_syms_dump_syms_SOURCES = \
src/common/dwarf_cfi_to_module.cc \ src/common/dwarf_cfi_to_module.cc \
src/common/dwarf_cu_to_module.cc \ src/common/dwarf_cu_to_module.cc \
src/common/dwarf_line_to_module.cc \ src/common/dwarf_line_to_module.cc \
src/common/dwarf_range_list_handler.cc \
src/common/language.cc \ src/common/language.cc \
src/common/module.cc \ src/common/module.cc \
src/common/path_helper.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_cfi_to_module.cc \
src/common/dwarf_cu_to_module.cc \ src/common/dwarf_cu_to_module.cc \
src/common/dwarf_line_to_module.cc \ src/common/dwarf_line_to_module.cc \
src/common/dwarf_range_list_handler.cc \
src/common/language.cc \ src/common/language.cc \
src/common/md5.cc \ src/common/md5.cc \
src/common/module.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_cu_to_module_unittest.cc \
src/common/dwarf_line_to_module.cc \ src/common/dwarf_line_to_module.cc \
src/common/dwarf_line_to_module_unittest.cc \ src/common/dwarf_line_to_module_unittest.cc \
src/common/dwarf_range_list_handler.cc \
src/common/language.cc \ src/common/language.cc \
src/common/memory_range_unittest.cc \ src/common/memory_range_unittest.cc \
src/common/module.cc \ src/common/module.cc \

View file

@ -694,10 +694,10 @@ am__src_common_dumper_unittest_SOURCES_DIST = \
src/common/dwarf_cu_to_module_unittest.cc \ src/common/dwarf_cu_to_module_unittest.cc \
src/common/dwarf_line_to_module.cc \ src/common/dwarf_line_to_module.cc \
src/common/dwarf_line_to_module_unittest.cc \ src/common/dwarf_line_to_module_unittest.cc \
src/common/language.cc src/common/memory_range_unittest.cc \ src/common/dwarf_range_list_handler.cc src/common/language.cc \
src/common/module.cc src/common/module_unittest.cc \ src/common/memory_range_unittest.cc src/common/module.cc \
src/common/path_helper.cc src/common/stabs_reader.cc \ src/common/module_unittest.cc src/common/path_helper.cc \
src/common/stabs_reader_unittest.cc \ src/common/stabs_reader.cc src/common/stabs_reader_unittest.cc \
src/common/stabs_to_module.cc \ src/common/stabs_to_module.cc \
src/common/stabs_to_module_unittest.cc \ src/common/stabs_to_module_unittest.cc \
src/common/test_assembler.cc src/common/dwarf/bytereader.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_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.$(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_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-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-memory_range_unittest.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-module.$(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 = \ am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \
src/common/dwarf_cfi_to_module.cc \ src/common/dwarf_cfi_to_module.cc \
src/common/dwarf_cu_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/module.cc src/common/path_helper.cc \
src/common/stabs_reader.cc src/common/stabs_to_module.cc \ src/common/stabs_reader.cc src/common/stabs_to_module.cc \
src/common/dwarf/bytereader.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@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_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_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-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-module.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_linux_dump_syms_dump_syms-path_helper.$(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 = \ am__src_tools_mac_dump_syms_dump_syms_mac_SOURCES_DIST = \
src/common/dwarf_cfi_to_module.cc \ src/common/dwarf_cfi_to_module.cc \
src/common/dwarf_cu_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/md5.cc src/common/module.cc \
src/common/path_helper.cc src/common/stabs_reader.cc \ src/common/path_helper.cc src/common/stabs_reader.cc \
src/common/stabs_to_module.cc src/common/dwarf/bytereader.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@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_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_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-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-md5.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-module.$(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_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_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_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/language.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/path_helper.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_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_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_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/language.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/md5.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/md5.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.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_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.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module_unittest.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/language.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/memory_range_unittest.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/memory_range_unittest.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.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/src_common_dumper_unittest-dwarf_line_to_module_unittest.$(OBJEXT): \
src/common/$(am__dirstamp) \ src/common/$(am__dirstamp) \
src/common/$(DEPDIR)/$(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/src_common_dumper_unittest-language.$(OBJEXT): \
src/common/$(am__dirstamp) \ src/common/$(am__dirstamp) \
src/common/$(DEPDIR)/$(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/src_tools_linux_dump_syms_dump_syms-dwarf_line_to_module.$(OBJEXT): \
src/common/$(am__dirstamp) \ src/common/$(am__dirstamp) \
src/common/$(DEPDIR)/$(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/src_tools_linux_dump_syms_dump_syms-language.$(OBJEXT): \
src/common/$(am__dirstamp) \ src/common/$(am__dirstamp) \
src/common/$(DEPDIR)/$(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/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.$(OBJEXT): \
src/common/$(am__dirstamp) \ src/common/$(am__dirstamp) \
src/common/$(DEPDIR)/$(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/src_tools_mac_dump_syms_dump_syms_mac-language.$(OBJEXT): \
src/common/$(am__dirstamp) \ src/common/$(am__dirstamp) \
src/common/$(DEPDIR)/$(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_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.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_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-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-memory_range_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-module.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_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_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_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-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-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@ @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_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_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_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-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-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@ @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@ @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` @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 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_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 @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@ @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` @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 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_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 @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@ @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` @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 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_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 @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
View file

@ -6098,7 +6098,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807, We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */ 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 int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1) && LARGE_OFF_T % 2147483647 == 1)
? 1 : -1]; ? 1 : -1];
@ -6144,7 +6144,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807, We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */ 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 int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1) && LARGE_OFF_T % 2147483647 == 1)
? 1 : -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, We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */ 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 int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1) && LARGE_OFF_T % 2147483647 == 1)
? 1 : -1]; ? 1 : -1];
@ -6213,7 +6213,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807, We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */ 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 int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1) && LARGE_OFF_T % 2147483647 == 1)
? 1 : -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, We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */ 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 int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1) && LARGE_OFF_T % 2147483647 == 1)
? 1 : -1]; ? 1 : -1];

View file

@ -1247,6 +1247,41 @@ void LineInfo::ReadLines() {
after_header_ = lengthstart + header_.total_length; 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 // 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 // computing the canonical frame address. There is one subclass of this for
// each '*Rule' member function in CallFrameInfo::Handler. // each '*Rule' member function in CallFrameInfo::Handler.

View file

@ -187,6 +187,36 @@ class LineInfoHandler {
uint32 file_num, uint32 line_num, uint32 column_num) { } 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 // This class is the main interface between the reader and the
// client. The virtual functions inside this get called for // client. The virtual functions inside this get called for
// interesting events that happen during DWARF2 reading. // interesting events that happen during DWARF2 reading.

View file

@ -184,6 +184,9 @@ void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset,
case DW_AT_decl_file: case DW_AT_decl_file:
current_function_info_->file = files_->at(data).name; current_function_info_->file = files_->at(data).name;
break; break;
case DW_AT_ranges:
current_function_info->ranges = data;
break;
default: default:
break; break;
} }

View file

@ -58,6 +58,8 @@ struct FunctionInfo {
uint64 lowpc; uint64 lowpc;
// End address for this function. // End address for this function.
uint64 highpc; uint64 highpc;
// Ranges offset
uint64 ranges;
}; };
struct SourceFileInfo { struct SourceFileInfo {

View file

@ -44,6 +44,7 @@
#include <stdio.h> #include <stdio.h>
#include <algorithm> #include <algorithm>
#include <numeric>
#include <utility> #include <utility>
#include "common/dwarf_line_to_module.h" #include "common/dwarf_line_to_module.h"
@ -51,6 +52,7 @@
namespace google_breakpad { namespace google_breakpad {
using std::accumulate;
using std::map; using std::map;
using std::pair; using std::pair;
using std::sort; using std::sort;
@ -167,10 +169,15 @@ bool DwarfCUToModule::FileContext::IsUnhandledInterCUReference(
// parsing. This is for data shared across the CU's entire DIE tree, // parsing. This is for data shared across the CU's entire DIE tree,
// and parameters from the code invoking the CU parser. // and parameters from the code invoking the CU parser.
struct DwarfCUToModule::CUContext { 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), : file_context(file_context_arg),
reporter(reporter_arg), reporter(reporter_arg),
language(Language::CPlusPlus) {} ranges_handler(ranges_handler_arg),
language(Language::CPlusPlus),
low_pc(0),
high_pc(0),
ranges(0) {}
~CUContext() { ~CUContext() {
for (vector<Module::Function *>::iterator it = functions.begin(); for (vector<Module::Function *>::iterator it = functions.begin();
@ -185,9 +192,19 @@ struct DwarfCUToModule::CUContext {
// For printing error messages. // For printing error messages.
WarningReporter *reporter; WarningReporter *reporter;
// For reading ranges from the .debug_ranges section
RangesHandler *ranges_handler;
// The source language of this compilation unit. // The source language of this compilation unit.
const Language *language; 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 // The functions defined in this compilation unit. We accumulate
// them here during parsing. Then, in DwarfCUToModule::Finish, we // them here during parsing. Then, in DwarfCUToModule::Finish, we
// assign them lines and add them to file_context->module. // assign them lines and add them to file_context->module.
@ -445,7 +462,7 @@ class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
uint64 offset) uint64 offset)
: GenericDIEHandler(cu_context, parent_context, offset), : GenericDIEHandler(cu_context, parent_context, offset),
low_pc_(0), high_pc_(0), high_pc_form_(dwarf2reader::DW_FORM_addr), 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, void ProcessAttributeUnsigned(enum DwarfAttribute attr,
enum DwarfForm form, enum DwarfForm form,
uint64 data); uint64 data);
@ -465,6 +482,7 @@ class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
string name_; string name_;
uint64 low_pc_, high_pc_; // DW_AT_low_pc, DW_AT_high_pc 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. DwarfForm high_pc_form_; // DW_AT_high_pc can be length or address.
uint64 ranges_; // DW_AT_ranges
const AbstractOrigin* abstract_origin_; const AbstractOrigin* abstract_origin_;
bool inline_; bool inline_;
}; };
@ -484,6 +502,9 @@ void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
high_pc_form_ = form; high_pc_form_ = form;
high_pc_ = data; high_pc_ = data;
break; break;
case dwarf2reader::DW_AT_ranges:
ranges_ = data;
break;
default: default:
GenericDIEHandler::ProcessAttributeUnsigned(attr, form, data); GenericDIEHandler::ProcessAttributeUnsigned(attr, form, data);
@ -537,17 +558,47 @@ bool DwarfCUToModule::FuncHandler::EndAttributes() {
return true; 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() { void DwarfCUToModule::FuncHandler::Finish() {
// Make high_pc_ an address, if it isn't already. vector<Module::Range> ranges;
if (high_pc_form_ != dwarf2reader::DW_FORM_addr) {
high_pc_ += low_pc_; 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 // Did we collect the information we need? Not all DWARF function
// entries have low and high addresses (for example, inlined // entries are non-empty (for example, inlined functions that were never
// functions that were never used), but all the ones we're // used), but all the ones we're interested in cover a non-empty range of
// interested in cover a non-empty range of bytes. // bytes.
if (low_pc_ < high_pc_) { if (!IsEmptyRange(ranges)) {
low_pc_ = ranges.front().address;
// Malformed DWARF may omit the name, but all Module::Functions must // Malformed DWARF may omit the name, but all Module::Functions must
// have names. // have names.
string name; string name;
@ -561,7 +612,7 @@ void DwarfCUToModule::FuncHandler::Finish() {
// Create a Module::Function based on the data we've gathered, and // Create a Module::Function based on the data we've gathered, and
// add it to the functions_ list. // add it to the functions_ list.
scoped_ptr<Module::Function> func(new Module::Function(name, low_pc_)); scoped_ptr<Module::Function> func(new Module::Function(name, low_pc_));
func->size = high_pc_ - low_pc_; func->ranges = ranges;
func->parameter_size = 0; func->parameter_size = 0;
if (func->address) { if (func->address) {
// If the function address is zero this is a sign that this function // If the function address is zero this is a sign that this function
@ -663,7 +714,7 @@ void DwarfCUToModule::WarningReporter::UncoveredFunction(
return; return;
UncoveredHeading(); UncoveredHeading();
fprintf(stderr, " function%s: %s\n", fprintf(stderr, " function%s: %s\n",
function.size == 0 ? " (zero-length)" : "", IsEmptyRange(function.ranges) ? " (zero-length)" : "",
function.name.c_str()); function.name.c_str());
} }
@ -697,11 +748,25 @@ void DwarfCUToModule::WarningReporter::UnhandledInterCUReference(
filename_.c_str(), offset, target); 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, DwarfCUToModule::DwarfCUToModule(FileContext *file_context,
LineToModuleHandler *line_reader, LineToModuleHandler *line_reader,
RangesHandler *ranges_handler,
WarningReporter *reporter) WarningReporter *reporter)
: line_reader_(line_reader), : line_reader_(line_reader),
cu_context_(new CUContext(file_context, reporter)), cu_context_(new CUContext(file_context, reporter, ranges_handler)),
child_context_(new DIEContext()), child_context_(new DIEContext()),
has_source_line_info_(false) { 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 case dwarf2reader::DW_AT_language: // source language of this CU
SetLanguage(static_cast<DwarfLanguage>(data)); SetLanguage(static_cast<DwarfLanguage>(data));
break; 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: default:
break; break;
} }
@ -841,6 +916,46 @@ void DwarfCUToModule::ReadSourceLines(uint64 offset) {
} }
namespace { 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. // Return true if ADDRESS falls within the range of ITEM.
template <class T> template <class T>
inline bool within(const T &item, Module::Address address) { 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::Function *last_function_cited = NULL;
const Module::Line *last_line_cited = NULL; const Module::Line *last_line_cited = NULL;
// Make a single pass through both vectors from lower to higher // Prepare a sorted list of ranges with range-to-function mapping
// addresses, populating each Function's lines vector with lines vector<FunctionRange> sorted_ranges;
// from our lines_ vector that fall within the function's address FillSortedFunctionRanges(sorted_ranges, functions);
// range.
vector<Module::Function *>::iterator func_it = functions->begin(); // 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(); vector<Module::Line>::const_iterator line_it = lines_.begin();
Module::Address current; Module::Address current;
// Pointers to the referents of func_it and line_it, or NULL if the // Pointers to the referents of func_it and line_it, or NULL if the
// iterator is at the end of the sequence. // iterator is at the end of the sequence.
Module::Function *func; FunctionRange *range;
const Module::Line *line; const Module::Line *line;
// Start current at the beginning of the first line or function, // Start current at the beginning of the first line or function,
// whichever is earlier. // whichever is earlier.
if (func_it != functions->end() && line_it != lines_.end()) { if (range_it != sorted_ranges.end() && line_it != lines_.end()) {
func = *func_it; range = &*range_it;
line = &*line_it; line = &*line_it;
current = std::min(func->address, line->address); current = std::min(range->address, line->address);
} else if (line_it != lines_.end()) { } else if (line_it != lines_.end()) {
func = NULL; range = NULL;
line = &*line_it; line = &*line_it;
current = line->address; current = line->address;
} else if (func_it != functions->end()) { } else if (range_it != sorted_ranges.end()) {
func = *func_it; range = &*range_it;
line = NULL; line = NULL;
current = (*func_it)->address; current = range->address;
} else { } else {
return; return;
} }
while (func || line) { while (range || line) {
// This loop has two invariants that hold at the top. // This loop has two invariants that hold at the top.
// //
// First, at least one of the iterators is not at the end of its // First, at least one of the iterators is not at the end of its
// sequence, and those that are not refer to the earliest // 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 // 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. // covered or not covered by a line.
// //
// The second invariant is that CURRENT refers to a byte whose // 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 // Note that, although each iteration advances CURRENT from one
// transition address to the next in each iteration, it might // 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 // 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 // suppose that we enter an iteration with CURRENT at the end of
// the first line. The next transition address is the start 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, // advance CURRENT to that point. At the head of that iteration,
// the invariants require that the line iterator be pointing at // the invariants require that the line iterator be pointing at
// the second line. But this is also true at the head of the // 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. // iterator. So neither iterator moves.
// Assert the first invariant (see above). // 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)); assert(!line || current < line->address || within(*line, current));
// The next transition after 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 // Figure out which state we're in, add lines or warn, and compute
// the next transition address. // the next transition address.
if (func && current >= func->address) { if (range && current >= range->address) {
if (line && current >= line->address) { if (line && current >= line->address) {
// Covered by both a line and a function. // Covered by both a line and a range.
Module::Address func_left = func->size - (current - func->address); Module::Address range_left = range->size - (current - range->address);
Module::Address line_left = line->size - (current - line->address); Module::Address line_left = line->size - (current - line->address);
// This may overflow, but things work out. // 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; Module::Line l = *line;
l.address = current; l.address = current;
l.size = next_transition - current; l.size = next_transition - current;
func->lines.push_back(l); range->AddLine(l);
last_line_used = line; last_line_used = line;
} else { } else {
// Covered by a function, but no line. // Covered by a range, but no line.
if (func != last_function_cited) { if (range->function != last_function_cited) {
reporter->UncoveredFunction(*func); reporter->UncoveredFunction(*(range->function));
last_function_cited = func; last_function_cited = range->function;
} }
if (line && within(*func, line->address)) if (line && within(*range, line->address))
next_transition = line->address; next_transition = line->address;
else else
// If this overflows, we'll catch it below. // If this overflows, we'll catch it below.
next_transition = func->address + func->size; next_transition = range->address + range->size;
} }
} else { } else {
if (line && current >= line->address) { 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 // If GCC emits padding after one function to align the start
// of the next, then it will attribute the padding // 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 // start of the next function, then assume this is what
// happened, and don't warn. // happened, and don't warn.
if (line != last_line_cited if (line != last_line_cited
&& !(func && !(range
&& line == last_line_used && line == last_line_used
&& func->address - line->address == line->size)) { && range->address - line->address == line->size)) {
reporter->UncoveredLine(*line); reporter->UncoveredLine(*line);
last_line_cited = line; last_line_cited = line;
} }
if (func && within(*line, func->address)) if (range && within(*line, range->address))
next_transition = func->address; next_transition = range->address;
else else
// If this overflows, we'll catch it below. // If this overflows, we'll catch it below.
next_transition = line->address + line->size; next_transition = line->address + line->size;
} else { } else {
// Covered by neither a function nor a line. By the invariant, // Covered by neither a range nor a line. By the invariant,
// both func and line begin after CURRENT. The next transition // both range and line begin after CURRENT. The next transition
// is the start of the next function or next line, whichever // is the start of the next range or next line, whichever
// is earliest. // is earliest.
assert(func || line); assert(range || line);
if (func && line) if (range && line)
next_transition = std::min(func->address, line->address); next_transition = std::min(range->address, line->address);
else if (func) else if (range)
next_transition = func->address; next_transition = range->address;
else else
next_transition = line->address; 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 // 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 // about what result we produce in that case, just as long as we don't
// hang or crash. // hang or crash.
while (func_it != functions->end() while (range_it != sorted_ranges.end()
&& next_transition >= (*func_it)->address && next_transition >= range_it->address
&& !within(**func_it, next_transition)) && !within(*range_it, next_transition))
func_it++; range_it++;
func = (func_it != functions->end()) ? *func_it : NULL; range = (range_it != sorted_ranges.end()) ? &(*range_it) : NULL;
while (line_it != lines_.end() while (line_it != lines_.end()
&& next_transition >= line_it->address && next_transition >= line_it->address
&& !within(*line_it, next_transition)) && !within(*line_it, next_transition))

View file

@ -123,6 +123,22 @@ class DwarfCUToModule: public dwarf2reader::RootDIEHandler {
scoped_ptr<FilePrivate> file_private_; 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 // An abstract base class for handlers that handle DWARF line data
// for DwarfCUToModule. DwarfCUToModule could certainly just use // for DwarfCUToModule. DwarfCUToModule could certainly just use
// dwarf2reader::LineInfo itself directly, but decoupling things // 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. // FilePrivate did not retain the inter-CU specification data.
virtual void UnhandledInterCUReference(uint64 offset, uint64 target); 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 { uint64 cu_offset() const {
return cu_offset_; return cu_offset_;
} }
@ -235,6 +259,7 @@ class DwarfCUToModule: public dwarf2reader::RootDIEHandler {
// data we find. // data we find.
DwarfCUToModule(FileContext *file_context, DwarfCUToModule(FileContext *file_context,
LineToModuleHandler *line_reader, LineToModuleHandler *line_reader,
RangesHandler *ranges_handler,
WarningReporter *reporter); WarningReporter *reporter);
~DwarfCUToModule(); ~DwarfCUToModule();
@ -296,6 +321,9 @@ class DwarfCUToModule: public dwarf2reader::RootDIEHandler {
// The handler to use to handle line number data. // The handler to use to handle line number data.
LineToModuleHandler *line_reader_; LineToModuleHandler *line_reader_;
// The handler to use to handle range lists.
RangesHandler *ranges_handler_;
// This compilation unit's context. // This compilation unit's context.
scoped_ptr<CUContext> cu_context_; scoped_ptr<CUContext> cu_context_;

View file

@ -128,7 +128,8 @@ class CUFixtureBase {
language_signed_(false), language_signed_(false),
appender_(&lines_), appender_(&lines_),
reporter_("dwarf-filename", 0xcf8f9bb6443d29b5LL), reporter_("dwarf-filename", 0xcf8f9bb6443d29b5LL),
root_handler_(&file_context_, &line_reader_, &reporter_), root_handler_(&file_context_, &line_reader_,
/* ranges_reader */ nullptr, &reporter_),
functions_filled_(false) { functions_filled_(false) {
// By default, expect no warnings to be reported, and expect the // By default, expect no warnings to be reported, and expect the
// compilation unit's name to be provided. The test can override // 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]; Module::Function *function = functions_[i];
EXPECT_EQ(name, function->name); EXPECT_EQ(name, function->name);
EXPECT_EQ(address, function->address); EXPECT_EQ(address, function->address);
EXPECT_EQ(size, function->size); EXPECT_EQ(size, function->ranges[0].size);
EXPECT_EQ(0U, function->parameter_size); EXPECT_EQ(0U, function->parameter_size);
} }
@ -1515,7 +1516,7 @@ TEST_F(Specifications, InterCU) {
// First CU. Declares class_A. // 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.StartCompilationUnit(0, 1, 2, 3, 3));
ASSERT_TRUE(root1_handler.StartRootDIE(1, ASSERT_TRUE(root1_handler.StartRootDIE(1,
dwarf2reader::DW_TAG_compile_unit)); dwarf2reader::DW_TAG_compile_unit));
@ -1528,7 +1529,7 @@ TEST_F(Specifications, InterCU) {
// Second CU. Defines class_A, declares member_func_B. // 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.StartCompilationUnit(0, 1, 2, 3, 3));
ASSERT_TRUE(root2_handler.StartRootDIE(1, ASSERT_TRUE(root2_handler.StartRootDIE(1,
dwarf2reader::DW_TAG_compile_unit)); dwarf2reader::DW_TAG_compile_unit));
@ -1545,7 +1546,7 @@ TEST_F(Specifications, InterCU) {
// Third CU. Defines member_func_B. // 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.StartCompilationUnit(0, 1, 2, 3, 3));
ASSERT_TRUE(root3_handler.StartRootDIE(1, ASSERT_TRUE(root3_handler.StartRootDIE(1,
dwarf2reader::DW_TAG_compile_unit)); dwarf2reader::DW_TAG_compile_unit));
@ -1574,7 +1575,7 @@ TEST_F(Specifications, UnhandledInterCU) {
// First CU. Declares class_A. // 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.StartCompilationUnit(0, 1, 2, 3, 3));
ASSERT_TRUE(root1_handler.StartRootDIE(1, ASSERT_TRUE(root1_handler.StartRootDIE(1,
dwarf2reader::DW_TAG_compile_unit)); dwarf2reader::DW_TAG_compile_unit));
@ -1587,7 +1588,7 @@ TEST_F(Specifications, UnhandledInterCU) {
// Second CU. Defines class_A, declares member_func_B. // 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.StartCompilationUnit(0, 1, 2, 3, 3));
ASSERT_TRUE(root2_handler.StartRootDIE(1, ASSERT_TRUE(root2_handler.StartRootDIE(1,
dwarf2reader::DW_TAG_compile_unit)); dwarf2reader::DW_TAG_compile_unit));
@ -1605,7 +1606,7 @@ TEST_F(Specifications, UnhandledInterCU) {
// Third CU. Defines member_func_B. // 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.StartCompilationUnit(0, 1, 2, 3, 3));
ASSERT_TRUE(root3_handler.StartRootDIE(1, ASSERT_TRUE(root3_handler.StartRootDIE(1,
dwarf2reader::DW_TAG_compile_unit)); dwarf2reader::DW_TAG_compile_unit));
@ -1791,7 +1792,8 @@ struct Reporter: public Test {
file("source file name") { file("source file name") {
reporter.SetCUName("compilation-unit-name"); reporter.SetCUName("compilation-unit-name");
function.size = 0x89808a5bdfa0a6a3ULL; Module::Range range(0x19c45c30770c1eb0ULL, 0x89808a5bdfa0a6a3ULL);
function.ranges.push_back(range);
function.parameter_size = 0x6a329f18683dcd51ULL; function.parameter_size = 0x6a329f18683dcd51ULL;
line.address = 0x3606ac6267aebeccULL; line.address = 0x3606ac6267aebeccULL;

View 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

View 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

View file

@ -58,6 +58,7 @@
#include "common/dwarf_cfi_to_module.h" #include "common/dwarf_cfi_to_module.h"
#include "common/dwarf_cu_to_module.h" #include "common/dwarf_cu_to_module.h"
#include "common/dwarf_line_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/crc32.h"
#include "common/linux/eintr_wrapper.h" #include "common/linux/eintr_wrapper.h"
#include "common/linux/elfutils.h" #include "common/linux/elfutils.h"
@ -81,6 +82,7 @@ using google_breakpad::DumpOptions;
using google_breakpad::DwarfCFIToModule; using google_breakpad::DwarfCFIToModule;
using google_breakpad::DwarfCUToModule; using google_breakpad::DwarfCUToModule;
using google_breakpad::DwarfLineToModule; using google_breakpad::DwarfLineToModule;
using google_breakpad::DwarfRangeListHandler;
using google_breakpad::ElfClass; using google_breakpad::ElfClass;
using google_breakpad::ElfClass32; using google_breakpad::ElfClass32;
using google_breakpad::ElfClass64; using google_breakpad::ElfClass64;
@ -207,6 +209,30 @@ bool LoadStabs(const typename ElfClass::Ehdr* elf_header,
} }
#endif // NO_STABS_SUPPORT #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 // A line-to-module loader that accepts line number info parsed by
// dwarf2reader::LineInfo and populates a Module and a line vector // dwarf2reader::LineInfo and populates a Module and a line vector
// with the results. // with the results.
@ -261,6 +287,18 @@ bool LoadDwarf(const string& dwarf_filename,
file_context.AddSectionToSectionMap(name, contents, section->sh_size); 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. // Parse all the compilation units in the .debug_info section.
DumperLineToModule line_to_module(&byte_reader); DumperLineToModule line_to_module(&byte_reader);
dwarf2reader::SectionMap::const_iterator debug_info_entry = 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 // Make a handler for the root DIE that populates MODULE with the
// data that was found. // data that was found.
DwarfCUToModule::WarningReporter reporter(dwarf_filename, offset); 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. // Make a Dwarf2Handler that drives the DIEHandler.
dwarf2reader::DIEDispatcher die_dispatcher(&root_handler); dwarf2reader::DIEDispatcher die_dispatcher(&root_handler);
// Make a DWARF parser for the compilation unit at OFFSET. // Make a DWARF parser for the compilation unit at OFFSET.

View file

@ -55,6 +55,7 @@
#include "common/dwarf_cfi_to_module.h" #include "common/dwarf_cfi_to_module.h"
#include "common/dwarf_cu_to_module.h" #include "common/dwarf_cu_to_module.h"
#include "common/dwarf_line_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/file_id.h"
#include "common/mac/arch_utilities.h" #include "common/mac/arch_utilities.h"
#include "common/mac/macho_reader.h" #include "common/mac/macho_reader.h"
@ -76,6 +77,7 @@
using dwarf2reader::ByteReader; using dwarf2reader::ByteReader;
using google_breakpad::DwarfCUToModule; using google_breakpad::DwarfCUToModule;
using google_breakpad::DwarfLineToModule; using google_breakpad::DwarfLineToModule;
using google_breakpad::DwarfRangeListHandler;
using google_breakpad::FileID; using google_breakpad::FileID;
using google_breakpad::mach_o::FatReader; using google_breakpad::mach_o::FatReader;
using google_breakpad::mach_o::Section; using google_breakpad::mach_o::Section;
@ -303,6 +305,31 @@ string DumpSymbols::Identifier() {
return compacted; 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 // A line-to-module loader that accepts line number info parsed by
// dwarf2reader::LineInfo and populates a Module and a line vector // dwarf2reader::LineInfo and populates a Module and a line vector
// with the results. // 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. // Build a line-to-module loader for the root handler to use.
DumperLineToModule line_to_module(&byte_reader); 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. // Walk the __debug_info section, one compilation unit at a time.
uint64 debug_info_length = debug_info_section.second; uint64 debug_info_length = debug_info_section.second;
for (uint64 offset = 0; offset < debug_info_length;) { for (uint64 offset = 0; offset < debug_info_length;) {
@ -432,7 +471,8 @@ bool DumpSymbols::ReadDwarf(google_breakpad::Module *module,
// debug info. // debug info.
DwarfCUToModule::WarningReporter reporter(selected_object_name_, DwarfCUToModule::WarningReporter reporter(selected_object_name_,
offset); 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. // Make a Dwarf2Handler that drives our DIEHandler.
dwarf2reader::DIEDispatcher die_dispatcher(&root_handler); dwarf2reader::DIEDispatcher die_dispatcher(&root_handler);
// Make a DWARF parser for the compilation unit at OFFSET. // Make a DWARF parser for the compilation unit at OFFSET.

View file

@ -125,6 +125,7 @@ class DumpSymbols {
private: private:
// Used internally. // Used internally.
class DumperLineToModule; class DumperLineToModule;
class DumperRangesHandler;
class LoadCommandDumper; class LoadCommandDumper;
// This method behaves similarly to NXFindBestFatArch, but it supports // This method behaves similarly to NXFindBestFatArch, but it supports

View file

@ -258,24 +258,33 @@ bool Module::Write(std::ostream &stream, SymbolData symbol_data) {
for (FunctionSet::const_iterator func_it = functions_.begin(); for (FunctionSet::const_iterator func_it = functions_.begin();
func_it != functions_.end(); ++func_it) { func_it != functions_.end(); ++func_it) {
Function *func = *func_it; Function *func = *func_it;
stream << "FUNC " << hex vector<Line>::iterator line_it = func->lines.begin();
<< (func->address - load_address_) << " " for (auto range_it = func->ranges.cbegin();
<< func->size << " " range_it != func->ranges.cend(); ++range_it) {
<< func->parameter_size << " " stream << "FUNC " << hex
<< func->name << dec << "\n"; << (range_it->address - load_address_) << " "
if (!stream.good()) << range_it->size << " "
return ReportError(); << 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()) if (!stream.good())
return ReportError(); 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;
}
} }
} }

View file

@ -85,10 +85,19 @@ class Module {
int source_id; 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. // A function.
struct Function { struct Function {
Function(const string &name_input, const Address &address_input) : 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 // For sorting by address. (Not style-guide compliant, but it's
// stupid not to put this in the struct.) // stupid not to put this in the struct.)
@ -99,9 +108,9 @@ class Module {
// The function's name. // The function's name.
const string 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; const Address address;
Address size; vector<Range> ranges;
// The function's parameter size. // The function's parameter size.
Address parameter_size; Address parameter_size;

View file

@ -55,7 +55,8 @@ static Module::Function *generate_duplicate_function(const string &name) {
const Module::Address DUP_PARAMETER_SIZE = 0xf14ac4fed48c4a99LL; const Module::Address DUP_PARAMETER_SIZE = 0xf14ac4fed48c4a99LL;
Module::Function *function = new Module::Function(name, DUP_ADDRESS); 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; function->parameter_size = DUP_PARAMETER_SIZE;
return function; return function;
} }
@ -92,7 +93,8 @@ TEST(Write, OneLineFunc) {
Module::File *file = m.FindFile("file_name.cc"); Module::File *file = m.FindFile("file_name.cc");
Module::Function *function = new Module::Function( Module::Function *function = new Module::Function(
"function_name", 0xe165bf8023b9d9abLL); "function_name", 0xe165bf8023b9d9abLL);
function->size = 0x1e4bb0eb1cbf5b09LL; Module::Range range(0xe165bf8023b9d9abLL, 0x1e4bb0eb1cbf5b09LL);
function->ranges.push_back(range);
function->parameter_size = 0x772beee89114358aLL; function->parameter_size = 0x772beee89114358aLL;
Module::Line line = { 0xe165bf8023b9d9abLL, 0x1e4bb0eb1cbf5b09LL, Module::Line line = { 0xe165bf8023b9d9abLL, 0x1e4bb0eb1cbf5b09LL,
file, 67519080 }; file, 67519080 };
@ -120,7 +122,8 @@ TEST(Write, RelativeLoadAddress) {
// A function. // A function.
Module::Function *function = new Module::Function( Module::Function *function = new Module::Function(
"A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)", 0xbec774ea5dd935f3LL); "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; function->parameter_size = 0xe5e9aa008bd5f0d0LL;
// Some source lines. The module should not sort these. // Some source lines. The module should not sort these.
@ -177,13 +180,14 @@ TEST(Write, OmitUnusedFiles) {
// Create a function. // Create a function.
Module::Function *function = new Module::Function( Module::Function *function = new Module::Function(
"function_name", 0x9b926d464f0b9384LL); "function_name", 0x9b926d464f0b9384LL);
function->size = 0x4f524a4ba795e6a6LL; Module::Range range(0x9b926d464f0b9384LL, 0x4f524a4ba795e6a6LL);
function->ranges.push_back(range);
function->parameter_size = 0xbbe8133a6641c9b7LL; function->parameter_size = 0xbbe8133a6641c9b7LL;
// Source files that refer to some files, but not others. // Source files that refer to some files, but not others.
Module::Line line1 = { 0x595fa44ebacc1086LL, 0x1e1e0191b066c5b3LL, Module::Line line1 = { 0xab415089485e1a20LL, 0x126e3124979291f2LL,
file1, 137850127 }; file1, 137850127 };
Module::Line line2 = { 0x401ce8c8a12d25e3LL, 0x895751c41b8d2ce2LL, Module::Line line2 = { 0xb2675b5c3c2ed33fLL, 0x1df77f5551dbd68cLL,
file3, 28113549 }; file3, 28113549 };
function->lines.push_back(line1); function->lines.push_back(line1);
function->lines.push_back(line2); function->lines.push_back(line2);
@ -210,8 +214,8 @@ TEST(Write, OmitUnusedFiles) {
"FILE 1 filename3\n" "FILE 1 filename3\n"
"FUNC 9b926d464f0b9384 4f524a4ba795e6a6 bbe8133a6641c9b7" "FUNC 9b926d464f0b9384 4f524a4ba795e6a6 bbe8133a6641c9b7"
" function_name\n" " function_name\n"
"595fa44ebacc1086 1e1e0191b066c5b3 137850127 0\n" "ab415089485e1a20 126e3124979291f2 137850127 0\n"
"401ce8c8a12d25e3 895751c41b8d2ce2 28113549 1\n", "b2675b5c3c2ed33f 1df77f5551dbd68c 28113549 1\n",
contents.c_str()); contents.c_str());
} }
@ -225,7 +229,8 @@ TEST(Write, NoCFI) {
// A function. // A function.
Module::Function *function = new Module::Function( Module::Function *function = new Module::Function(
"A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)", 0xbec774ea5dd935f3LL); "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; function->parameter_size = 0xe5e9aa008bd5f0d0LL;
// Some source lines. The module should not sort these. // Some source lines. The module should not sort these.
@ -267,12 +272,14 @@ TEST(Construct, AddFunctions) {
// Two functions. // Two functions.
Module::Function *function1 = new Module::Function( Module::Function *function1 = new Module::Function(
"_without_form", 0xd35024aa7ca7da5cLL); "_without_form", 0xd35024aa7ca7da5cLL);
function1->size = 0x200b26e605f99071LL; Module::Range r1(0xd35024aa7ca7da5cLL, 0x200b26e605f99071LL);
function1->ranges.push_back(r1);
function1->parameter_size = 0xf14ac4fed48c4a99LL; function1->parameter_size = 0xf14ac4fed48c4a99LL;
Module::Function *function2 = new Module::Function( Module::Function *function2 = new Module::Function(
"_and_void", 0x2987743d0b35b13fLL); "_and_void", 0x2987743d0b35b13fLL);
function2->size = 0xb369db048deb3010LL; Module::Range r2(0x2987743d0b35b13fLL, 0xb369db048deb3010LL);
function2->ranges.push_back(r2);
function2->parameter_size = 0x938e556cb5a79988LL; function2->parameter_size = 0x938e556cb5a79988LL;
// Put them in a vector. // Put them in a vector.
@ -504,7 +511,8 @@ TEST(Construct, FunctionsAndExternsWithSameAddress) {
m.AddExtern(extern2); m.AddExtern(extern2);
Module::Function* function = new Module::Function("_xyz", 0xfff0); 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; function->parameter_size = 0;
m.AddFunction(function); m.AddFunction(function);
@ -541,7 +549,8 @@ TEST(Construct, FunctionsAndThumbExternsWithSameAddress) {
// The corresponding function from the DWARF debug data have the actual // The corresponding function from the DWARF debug data have the actual
// address. // address.
Module::Function* function = new Module::Function("_thumb_xyz", 0xfff0); 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; function->parameter_size = 0;
m.AddFunction(function); m.AddFunction(function);

View file

@ -91,7 +91,8 @@ bool StabsToModule::StartFunction(const string &name,
uint64_t address) { uint64_t address) {
assert(!current_function_); assert(!current_function_);
Module::Function *f = new Module::Function(Demangle(name), address); 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. f->parameter_size = 0; // We don't provide this information.
current_function_ = f; current_function_ = f;
boundaries_.push_back(static_cast<Module::Address>(address)); boundaries_.push_back(static_cast<Module::Address>(address));
@ -167,14 +168,14 @@ void StabsToModule::Finalize() {
vector<Module::Address>::const_iterator boundary vector<Module::Address>::const_iterator boundary
= std::upper_bound(boundaries_.begin(), boundaries_.end(), f->address); = std::upper_bound(boundaries_.begin(), boundaries_.end(), f->address);
if (boundary != boundaries_.end()) if (boundary != boundaries_.end())
f->size = *boundary - f->address; f->ranges[0].size = *boundary - f->address;
else else
// If this is the last function in the module, and the STABS // If this is the last function in the module, and the STABS
// reader was unable to give us its ending address, then assign // reader was unable to give us its ending address, then assign
// it a bogus, very large value. This will happen at most once // it a bogus, very large value. This will happen at most once
// per module: since we've added all functions' addresses to the // per module: since we've added all functions' addresses to the
// boundary table, only one can be the last. // 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. // Compute sizes for each of the function f's lines --- if it has any.
if (!f->lines.empty()) { if (!f->lines.empty()) {
@ -185,7 +186,8 @@ void StabsToModule::Finalize() {
line_it != last_line; line_it++) line_it != last_line; line_it++)
line_it[0].size = line_it[1].address - line_it[0].address; line_it[0].size = line_it[1].address - line_it[0].address;
// Compute the size of the last line from f's end 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 // Now that everything has a size, add our functions to the module, and

View file

@ -64,7 +64,7 @@ TEST(StabsToModule, SimpleCU) {
Module::Function *function = functions[0]; Module::Function *function = functions[0];
EXPECT_STREQ("function", function->name.c_str()); EXPECT_STREQ("function", function->name.c_str());
EXPECT_EQ(0xfde4abbed390c394LL, function->address); EXPECT_EQ(0xfde4abbed390c394LL, function->address);
EXPECT_EQ(0x10U, function->size); EXPECT_EQ(0x10U, function->ranges[0].size);
EXPECT_EQ(0U, function->parameter_size); EXPECT_EQ(0U, function->parameter_size);
ASSERT_EQ((size_t) 1, function->lines.size()); ASSERT_EQ((size_t) 1, function->lines.size());
Module::Line *line = &function->lines[0]; Module::Line *line = &function->lines[0];
@ -130,7 +130,7 @@ TEST(StabsToModule, DuplicateFunctionNames) {
Module::Function *function = functions[0]; Module::Function *function = functions[0];
EXPECT_EQ(0xf2cfda36ecf7f46dLL, function->address); 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); EXPECT_EQ(0U, function->parameter_size);
ASSERT_EQ(0U, function->lines.size()); ASSERT_EQ(0U, function->lines.size());
} }
@ -166,7 +166,7 @@ TEST(InferSizes, LineSize) {
Module::Function *function = functions[0]; Module::Function *function = functions[0];
EXPECT_STREQ("function", function->name.c_str()); EXPECT_STREQ("function", function->name.c_str());
EXPECT_EQ(0xb4513962eff94e92LL, function->address); 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); EXPECT_EQ(0U, function->parameter_size);
ASSERT_EQ((size_t) 2, function->lines.size()); ASSERT_EQ((size_t) 2, function->lines.size());
@ -216,7 +216,7 @@ TEST(FunctionNames, Mangled) {
"push_back(unsigned long long const&)", "push_back(unsigned long long const&)",
function->name.c_str()); function->name.c_str());
EXPECT_EQ(0xf2cfda63cef7f46dLL, function->address); 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); EXPECT_EQ(0U, function->parameter_size);
ASSERT_EQ(0U, function->lines.size()); ASSERT_EQ(0U, function->lines.size());
} }