Add debug fission support.

This added debug fission support.
It tries to find the dwp file from the debug dir /usr/lib/debug/*/debug
and read symbols from them.

Most of this patch comes from
https://critique.corp.google.com/#review/52048295
and some fixes after that.
The elf_reader.cc comes from TOT google code. I just
removed some google dependency.

Current problems from this patch
1: Some type mismatch: from uint8_t * to char *.
2: Some hack to find the .dwp file. (replace .debug with .dwp)

BUG=chromium:604440
R=dehao@google.com, ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1884283002 .
This commit is contained in:
Yunlian Jiang 2016-05-04 11:09:44 -07:00
parent b5712766f6
commit 764c21f752
12 changed files with 2296 additions and 172 deletions

View File

@ -564,6 +564,7 @@ src_tools_linux_dump_syms_dump_syms_SOURCES = \
src/common/dwarf/bytereader.cc \
src/common/dwarf/dwarf2diehandler.cc \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/elf_reader.cc \
src/common/linux/crc32.cc \
src/common/linux/dump_symbols.cc \
src/common/linux/elf_symbols_to_module.cc \
@ -601,6 +602,7 @@ src_tools_mac_dump_syms_dump_syms_mac_SOURCES = \
src/common/dwarf/bytereader.cc \
src/common/dwarf/dwarf2diehandler.cc \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/elf_reader.cc \
src/common/mac/arch_utilities.cc \
src/common/mac/dump_syms.cc \
src/common/mac/file_id.cc \
@ -636,6 +638,7 @@ src_common_dumper_unittest_SOURCES = \
src/common/dwarf/dwarf2diehandler.cc \
src/common/dwarf/dwarf2diehandler_unittest.cc \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/elf_reader.cc \
src/common/dwarf/dwarf2reader_cfi_unittest.cc \
src/common/dwarf/dwarf2reader_die_unittest.cc \
src/common/linux/crc32.cc \
@ -678,6 +681,7 @@ src_common_mac_macho_reader_unittest_SOURCES = \
src/common/dwarf/cfi_assembler.cc \
src/common/dwarf/dwarf2diehandler.cc \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/elf_reader.cc \
src/common/mac/arch_utilities.cc \
src/common/mac/file_id.cc \
src/common/mac/macho_id.cc \

View File

@ -691,6 +691,7 @@ am__src_common_dumper_unittest_SOURCES_DIST = \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/dwarf2reader_cfi_unittest.cc \
src/common/dwarf/dwarf2reader_die_unittest.cc \
src/common/dwarf/elf_reader.cc \
src/common/linux/crc32.cc src/common/linux/dump_symbols.cc \
src/common/linux/dump_symbols_unittest.cc \
src/common/linux/elf_core_dump.cc \
@ -732,6 +733,7 @@ am__src_common_dumper_unittest_SOURCES_DIST = \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-elf_reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-crc32.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-dump_symbols.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.$(OBJEXT) \
@ -767,6 +769,7 @@ am__src_common_mac_macho_reader_unittest_SOURCES_DIST = \
src/common/dwarf/cfi_assembler.cc \
src/common/dwarf/dwarf2diehandler.cc \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/elf_reader.cc \
src/common/mac/arch_utilities.cc src/common/mac/file_id.cc \
src/common/mac/macho_id.cc src/common/mac/macho_reader.cc \
src/common/mac/macho_reader_unittest.cc \
@ -785,6 +788,7 @@ am__src_common_mac_macho_reader_unittest_SOURCES_DIST = \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-cfi_assembler.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-file_id.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-macho_id.$(OBJEXT) \
@ -1343,7 +1347,8 @@ am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \
src/common/module.cc src/common/stabs_reader.cc \
src/common/stabs_to_module.cc src/common/dwarf/bytereader.cc \
src/common/dwarf/dwarf2diehandler.cc \
src/common/dwarf/dwarf2reader.cc src/common/linux/crc32.cc \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/elf_reader.cc src/common/linux/crc32.cc \
src/common/linux/dump_symbols.cc \
src/common/linux/elf_symbols_to_module.cc \
src/common/linux/elfutils.cc src/common/linux/file_id.cc \
@ -1361,6 +1366,7 @@ am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/crc32.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.$(OBJEXT) \
@ -1415,6 +1421,7 @@ am__src_tools_mac_dump_syms_dump_syms_mac_SOURCES_DIST = \
src/common/dwarf/bytereader.cc \
src/common/dwarf/dwarf2diehandler.cc \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/elf_reader.cc \
src/common/mac/arch_utilities.cc src/common/mac/dump_syms.cc \
src/common/mac/file_id.cc src/common/mac/macho_id.cc \
src/common/mac/macho_reader.cc \
@ -1432,6 +1439,7 @@ am__src_tools_mac_dump_syms_dump_syms_mac_SOURCES_DIST = \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-bytereader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-file_id.$(OBJEXT) \
@ -2306,6 +2314,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/crc32.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.cc \
@ -2343,6 +2352,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/arch_utilities.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/dump_syms.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/file_id.cc \
@ -2381,6 +2391,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_cfi_unittest.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_die_unittest.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/crc32.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols_unittest.cc \
@ -2423,6 +2434,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/cfi_assembler.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/arch_utilities.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/file_id.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_id.cc \
@ -3790,6 +3802,9 @@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.$(OBJEXT):
src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/dwarf/src_common_dumper_unittest-elf_reader.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/linux/src_common_dumper_unittest-crc32.$(OBJEXT): \
src/common/linux/$(am__dirstamp) \
src/common/linux/$(DEPDIR)/$(am__dirstamp)
@ -3890,6 +3905,9 @@ src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.$(OBJEXT)
src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/mac/$(am__dirstamp):
@$(MKDIR_P) src/common/mac
@: > src/common/mac/$(am__dirstamp)
@ -4222,6 +4240,9 @@ src/common/dwarf/dwarf2diehandler.$(OBJEXT): \
src/common/dwarf/dwarf2reader.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/dwarf/elf_reader.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/linux/crc32.$(OBJEXT): src/common/linux/$(am__dirstamp) \
src/common/linux/$(DEPDIR)/$(am__dirstamp)
src/common/linux/dump_symbols.$(OBJEXT): \
@ -4322,6 +4343,9 @@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.$(OBJEXT
src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.$(OBJEXT): \
src/common/mac/$(am__dirstamp) \
src/common/mac/$(DEPDIR)/$(am__dirstamp)
@ -4472,6 +4496,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/bytereader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/dwarf2diehandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/dwarf2reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/elf_reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-cfi_assembler.Po@am__quote@
@ -4480,13 +4505,16 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_die_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-bytereader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-cfi_assembler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2diehandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-bytereader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/crc32.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/dump_symbols.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/elf_core_dump.Po@am__quote@
@ -6707,6 +6735,20 @@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.obj: src/com
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.obj `if test -f 'src/common/dwarf/dwarf2reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader.cc'; fi`
src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o: src/common/dwarf/elf_reader.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/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.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/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj: src/common/dwarf/elf_reader.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/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.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/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.o: src/common/mac/arch_utilities.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/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.o `test -f 'src/common/mac/arch_utilities.cc' || echo '$(srcdir)/'`src/common/mac/arch_utilities.cc
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Po

View File

@ -75,6 +75,8 @@
'dwarf/dwarf2reader.cc',
'dwarf/dwarf2reader.h',
'dwarf/dwarf2reader_test_common.h',
'dwarf/elf_reader.cc',
'dwarf/elf_reader.h',
'dwarf/functioninfo.cc',
'dwarf/functioninfo.h',
'dwarf/line_state_machine.h',

View File

@ -243,4 +243,8 @@ uint64 ByteReader::ReadEncodedPointer(const uint8_t *buffer,
return pointer;
}
Endianness ByteReader::GetEndianness() const {
return endian_;
}
} // namespace dwarf2reader

View File

@ -280,6 +280,7 @@ class ByteReader {
DwarfPointerEncoding encoding,
size_t *len) const;
Endianness GetEndianness() const;
private:
// Function pointer type for our address and offset readers.

View File

@ -149,7 +149,10 @@ enum DwarfForm {
DW_FORM_sec_offset = 0x17,
DW_FORM_exprloc = 0x18,
DW_FORM_flag_present = 0x19,
DW_FORM_ref_sig8 = 0x20
DW_FORM_ref_sig8 = 0x20,
// Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission.
DW_FORM_GNU_addr_index = 0x1f01,
DW_FORM_GNU_str_index = 0x1f02
};
// Attribute names and codes
@ -264,6 +267,13 @@ enum DwarfAttribute {
DW_AT_body_begin = 0x2105,
DW_AT_body_end = 0x2106,
DW_AT_GNU_vector = 0x2107,
// Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission.
DW_AT_GNU_dwo_name = 0x2130,
DW_AT_GNU_dwo_id = 0x2131,
DW_AT_GNU_ranges_base = 0x2132,
DW_AT_GNU_addr_base = 0x2133,
DW_AT_GNU_pubnames = 0x2134,
DW_AT_GNU_pubtypes = 0x2135,
// VMS extensions.
DW_AT_VMS_rtnbeg_pd_address = 0x2201,
// UPC extension.
@ -491,7 +501,22 @@ enum DwarfOpcode {
DW_OP_lo_user =0xe0,
DW_OP_hi_user =0xff,
// GNU extensions
DW_OP_GNU_push_tls_address =0xe0
DW_OP_GNU_push_tls_address =0xe0,
// Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission.
DW_OP_GNU_addr_index =0xfb,
DW_OP_GNU_const_index =0xfc
};
// Section identifiers for DWP files
enum DwarfSectionId {
DW_SECT_INFO = 1,
DW_SECT_TYPES = 2,
DW_SECT_ABBREV = 3,
DW_SECT_LINE = 4,
DW_SECT_LOC = 5,
DW_SECT_STR_OFFSETS = 6,
DW_SECT_MACINFO = 7,
DW_SECT_MACRO = 8
};
// Source languages. These are values for DW_AT_language.

View File

@ -44,6 +44,8 @@
#include <string>
#include <utility>
#include <sys/stat.h>
#include "common/dwarf/bytereader-inl.h"
#include "common/dwarf/bytereader.h"
#include "common/dwarf/line_state_machine.h"
@ -51,11 +53,38 @@
namespace dwarf2reader {
CompilationUnit::CompilationUnit(const SectionMap& sections, uint64 offset,
CompilationUnit::CompilationUnit(const string& path,
const SectionMap& sections, uint64 offset,
ByteReader* reader, Dwarf2Handler* handler)
: offset_from_section_start_(offset), reader_(reader),
sections_(sections), handler_(handler), abbrevs_(NULL),
string_buffer_(NULL), string_buffer_length_(0) {}
: path_(path), offset_from_section_start_(offset), reader_(reader),
sections_(sections), handler_(handler), abbrevs_(),
string_buffer_(NULL), string_buffer_length_(0),
str_offsets_buffer_(NULL), str_offsets_buffer_length_(0),
addr_buffer_(NULL), addr_buffer_length_(0),
is_split_dwarf_(false), dwo_id_(0), dwo_name_(),
skeleton_dwo_id_(0), ranges_base_(0), addr_base_(0),
have_checked_for_dwp_(false), dwp_path_(),
dwp_byte_reader_(), dwp_reader_() {}
// Initialize a compilation unit from a .dwo or .dwp file.
// In this case, we need the .debug_addr section from the
// executable file that contains the corresponding skeleton
// compilation unit. We also inherit the Dwarf2Handler from
// the executable file, and call it as if we were still
// processing the original compilation unit.
void CompilationUnit::SetSplitDwarf(const uint8_t* addr_buffer,
uint64 addr_buffer_length,
uint64 addr_base,
uint64 ranges_base,
uint64 dwo_id) {
is_split_dwarf_ = true;
addr_buffer_ = addr_buffer;
addr_buffer_length_ = addr_buffer_length;
addr_base_ = addr_base;
ranges_base_ = ranges_base;
skeleton_dwo_id_ = dwo_id;
}
// Read a DWARF2/3 abbreviation section.
// Each abbrev consists of a abbreviation number, a tag, a byte
@ -174,6 +203,8 @@ const uint8_t *CompilationUnit::SkipAttribute(const uint8_t *start,
return start + strlen(reinterpret_cast<const char *>(start)) + 1;
case DW_FORM_udata:
case DW_FORM_ref_udata:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_addr_index:
reader_->ReadUnsignedLEB128(start, &len);
return start + len;
@ -296,9 +327,31 @@ uint64 CompilationUnit::Start() {
string_buffer_length_ = iter->second.second;
}
// Set the string offsets section if we have one.
iter = sections_.find(".debug_str_offsets");
if (iter != sections_.end()) {
str_offsets_buffer_ = iter->second.first;
str_offsets_buffer_length_ = iter->second.second;
}
// Set the address section if we have one.
iter = sections_.find(".debug_addr");
if (iter != sections_.end()) {
addr_buffer_ = iter->second.first;
addr_buffer_length_ = iter->second.second;
}
// Now that we have our abbreviations, start processing DIE's.
ProcessDIEs();
// If this is a skeleton compilation unit generated with split DWARF,
// and the client needs the full debug info, we need to find the full
// compilation unit in a .dwo or .dwp file.
if (!is_split_dwarf_
&& dwo_name_ != NULL
&& handler_->NeedSplitDebugInfo())
ProcessSplitDwarf();
return ourlength;
}
@ -320,47 +373,45 @@ const uint8_t *CompilationUnit::ProcessAttribute(
return ProcessAttribute(dieoffset, start, attr, form);
case DW_FORM_flag_present:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form, 1);
ProcessAttributeUnsigned(dieoffset, attr, form, 1);
return start;
case DW_FORM_data1:
case DW_FORM_flag:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadOneByte(start));
return start + 1;
case DW_FORM_data2:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadTwoBytes(start));
return start + 2;
case DW_FORM_data4:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadFourBytes(start));
return start + 4;
case DW_FORM_data8:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadEightBytes(start));
return start + 8;
case DW_FORM_string: {
const char *str = reinterpret_cast<const char *>(start);
handler_->ProcessAttributeString(dieoffset, attr, form,
str);
ProcessAttributeString(dieoffset, attr, form, str);
return start + strlen(str) + 1;
}
case DW_FORM_udata:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadUnsignedLEB128(start,
&len));
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadUnsignedLEB128(start, &len));
return start + len;
case DW_FORM_sdata:
handler_->ProcessAttributeSigned(dieoffset, attr, form,
ProcessAttributeSigned(dieoffset, attr, form,
reader_->ReadSignedLEB128(start, &len));
return start + len;
case DW_FORM_addr:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadAddress(start));
return start + reader_->AddressSize();
case DW_FORM_sec_offset:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadOffset(start));
return start + reader_->OffsetSize();
@ -441,10 +492,32 @@ const uint8_t *CompilationUnit::ProcessAttribute(
assert(string_buffer_ + offset < string_buffer_ + string_buffer_length_);
const char *str = reinterpret_cast<const char *>(string_buffer_ + offset);
handler_->ProcessAttributeString(dieoffset, attr, form,
str);
ProcessAttributeString(dieoffset, attr, form, str);
return start + reader_->OffsetSize();
}
case DW_FORM_GNU_str_index: {
uint64 str_index = reader_->ReadUnsignedLEB128(start, &len);
const uint8_t* offset_ptr =
str_offsets_buffer_ + str_index * reader_->OffsetSize();
const uint64 offset = reader_->ReadOffset(offset_ptr);
if (offset >= string_buffer_length_) {
return NULL;
}
const char* str = reinterpret_cast<const char *>(string_buffer_) + offset;
ProcessAttributeString(dieoffset, attr, form, str);
return start + len;
break;
}
case DW_FORM_GNU_addr_index: {
uint64 addr_index = reader_->ReadUnsignedLEB128(start, &len);
const uint8_t* addr_ptr =
addr_buffer_ + addr_base_ + addr_index * reader_->AddressSize();
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadAddress(addr_ptr));
return start + len;
}
}
fprintf(stderr, "Unhandled form type\n");
return NULL;
@ -458,6 +531,16 @@ const uint8_t *CompilationUnit::ProcessDIE(uint64 dieoffset,
i++) {
start = ProcessAttribute(dieoffset, start, i->first, i->second);
}
// If this is a compilation unit in a split DWARF object, verify that
// the dwo_id matches. If it does not match, we will ignore this
// compilation unit.
if (abbrev.tag == DW_TAG_compile_unit
&& is_split_dwarf_
&& dwo_id_ != skeleton_dwo_id_) {
return NULL;
}
return start;
}
@ -515,6 +598,307 @@ void CompilationUnit::ProcessDIEs() {
}
}
// Check for a valid ELF file and return the Address size.
// Returns 0 if not a valid ELF file.
inline int GetElfWidth(const ElfReader& elf) {
if (elf.IsElf32File())
return 4;
if (elf.IsElf64File())
return 8;
return 0;
}
void CompilationUnit::ProcessSplitDwarf() {
struct stat statbuf;
if (!have_checked_for_dwp_) {
// Look for a .dwp file in the same directory as the executable.
have_checked_for_dwp_ = true;
string dwp_suffix(".dwp");
dwp_path_ = path_ + dwp_suffix;
if (stat(dwp_path_.c_str(), &statbuf) != 0) {
// Fall back to a split .debug file in the same directory.
string debug_suffix(".debug");
dwp_path_ = path_;
size_t found = path_.rfind(debug_suffix);
if (found + debug_suffix.length() == path_.length())
dwp_path_ = dwp_path_.replace(found, debug_suffix.length(), dwp_suffix);
}
if (stat(dwp_path_.c_str(), &statbuf) == 0) {
ElfReader* elf = new ElfReader(dwp_path_);
int width = GetElfWidth(*elf);
if (width != 0) {
dwp_byte_reader_.reset(new ByteReader(reader_->GetEndianness()));
dwp_byte_reader_->SetAddressSize(width);
dwp_reader_.reset(new DwpReader(*dwp_byte_reader_, elf));
dwp_reader_->Initialize();
} else {
delete elf;
}
}
}
bool found_in_dwp = false;
if (dwp_reader_ != NULL) {
// If we have a .dwp file, read the debug sections for the requested CU.
SectionMap sections;
dwp_reader_->ReadDebugSectionsForCU(dwo_id_, &sections);
if (!sections.empty()) {
found_in_dwp = true;
CompilationUnit dwp_comp_unit(dwp_path_, sections, 0,
dwp_byte_reader_.get(), handler_);
dwp_comp_unit.SetSplitDwarf(addr_buffer_, addr_buffer_length_, addr_base_,
ranges_base_, dwo_id_);
dwp_comp_unit.Start();
}
}
if (!found_in_dwp) {
// If no .dwp file, try to open the .dwo file.
if (stat(dwo_name_, &statbuf) == 0) {
ElfReader elf(dwo_name_);
int width = GetElfWidth(elf);
if (width != 0) {
ByteReader reader(ENDIANNESS_LITTLE);
reader.SetAddressSize(width);
SectionMap sections;
ReadDebugSectionsFromDwo(&elf, &sections);
CompilationUnit dwo_comp_unit(dwo_name_, sections, 0, &reader,
handler_);
dwo_comp_unit.SetSplitDwarf(addr_buffer_, addr_buffer_length_,
addr_base_, ranges_base_, dwo_id_);
dwo_comp_unit.Start();
}
}
}
}
void CompilationUnit::ReadDebugSectionsFromDwo(ElfReader* elf_reader,
SectionMap* sections) {
static const char* const section_names[] = {
".debug_abbrev",
".debug_info",
".debug_str_offsets",
".debug_str"
};
for (unsigned int i = 0u;
i < sizeof(section_names)/sizeof(*(section_names)); ++i) {
string base_name = section_names[i];
string dwo_name = base_name + ".dwo";
size_t section_size;
const char* section_data = elf_reader->GetSectionByName(dwo_name,
&section_size);
if (section_data != NULL)
sections->insert(std::make_pair(
base_name, std::make_pair(
reinterpret_cast<const uint8_t *>(section_data),
section_size)));
}
}
DwpReader::DwpReader(const ByteReader& byte_reader, ElfReader* elf_reader)
: elf_reader_(elf_reader), byte_reader_(byte_reader),
cu_index_(NULL), cu_index_size_(0), string_buffer_(NULL),
string_buffer_size_(0), version_(0), ncolumns_(0), nunits_(0),
nslots_(0), phash_(NULL), pindex_(NULL), shndx_pool_(NULL),
offset_table_(NULL), size_table_(NULL), abbrev_data_(NULL),
abbrev_size_(0), info_data_(NULL), info_size_(0),
str_offsets_data_(NULL), str_offsets_size_(0) {}
DwpReader::~DwpReader() {
if (elf_reader_) delete elf_reader_;
}
void DwpReader::Initialize() {
cu_index_ = elf_reader_->GetSectionByName(".debug_cu_index",
&cu_index_size_);
if (cu_index_ == NULL) {
return;
}
// The .debug_str.dwo section is shared by all CUs in the file.
string_buffer_ = elf_reader_->GetSectionByName(".debug_str.dwo",
&string_buffer_size_);
version_ = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(cu_index_));
if (version_ == 1) {
nslots_ = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(cu_index_)
+ 3 * sizeof(uint32));
phash_ = cu_index_ + 4 * sizeof(uint32);
pindex_ = phash_ + nslots_ * sizeof(uint64);
shndx_pool_ = pindex_ + nslots_ * sizeof(uint32);
if (shndx_pool_ >= cu_index_ + cu_index_size_) {
version_ = 0;
}
} else if (version_ == 2) {
ncolumns_ = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(cu_index_) + sizeof(uint32));
nunits_ = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(cu_index_) + 2 * sizeof(uint32));
nslots_ = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(cu_index_) + 3 * sizeof(uint32));
phash_ = cu_index_ + 4 * sizeof(uint32);
pindex_ = phash_ + nslots_ * sizeof(uint64);
offset_table_ = pindex_ + nslots_ * sizeof(uint32);
size_table_ = offset_table_ + ncolumns_ * (nunits_ + 1) * sizeof(uint32);
abbrev_data_ = elf_reader_->GetSectionByName(".debug_abbrev.dwo",
&abbrev_size_);
info_data_ = elf_reader_->GetSectionByName(".debug_info.dwo", &info_size_);
str_offsets_data_ = elf_reader_->GetSectionByName(".debug_str_offsets.dwo",
&str_offsets_size_);
if (size_table_ >= cu_index_ + cu_index_size_) {
version_ = 0;
}
}
}
void DwpReader::ReadDebugSectionsForCU(uint64 dwo_id,
SectionMap* sections) {
if (version_ == 1) {
int slot = LookupCU(dwo_id);
if (slot == -1) {
return;
}
// The index table points to the section index pool, where we
// can read a list of section indexes for the debug sections
// for the CU whose dwo_id we are looking for.
int index = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(pindex_)
+ slot * sizeof(uint32));
const char* shndx_list = shndx_pool_ + index * sizeof(uint32);
for (;;) {
if (shndx_list >= cu_index_ + cu_index_size_) {
version_ = 0;
return;
}
unsigned int shndx = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(shndx_list));
shndx_list += sizeof(uint32);
if (shndx == 0)
break;
const char* section_name = elf_reader_->GetSectionName(shndx);
size_t section_size;
const char* section_data;
// We're only interested in these four debug sections.
// The section names in the .dwo file end with ".dwo", but we
// add them to the sections table with their normal names.
if (!strncmp(section_name, ".debug_abbrev", strlen(".debug_abbrev"))) {
section_data = elf_reader_->GetSectionByIndex(shndx, &section_size);
sections->insert(std::make_pair(
".debug_abbrev",
std::make_pair(reinterpret_cast<const uint8_t *> (section_data),
section_size)));
} else if (!strncmp(section_name, ".debug_info", strlen(".debug_info"))) {
section_data = elf_reader_->GetSectionByIndex(shndx, &section_size);
sections->insert(std::make_pair(
".debug_info",
std::make_pair(reinterpret_cast<const uint8_t *> (section_data),
section_size)));
} else if (!strncmp(section_name, ".debug_str_offsets",
strlen(".debug_str_offsets"))) {
section_data = elf_reader_->GetSectionByIndex(shndx, &section_size);
sections->insert(std::make_pair(
".debug_str_offsets",
std::make_pair(reinterpret_cast<const uint8_t *> (section_data),
section_size)));
}
}
sections->insert(std::make_pair(
".debug_str",
std::make_pair(reinterpret_cast<const uint8_t *> (string_buffer_),
string_buffer_size_)));
} else if (version_ == 2) {
uint32 index = LookupCUv2(dwo_id);
if (index == 0) {
return;
}
// The index points to a row in each of the section offsets table
// and the section size table, where we can read the offsets and sizes
// of the contributions to each debug section from the CU whose dwo_id
// we are looking for. Row 0 of the section offsets table has the
// section ids for each column of the table. The size table begins
// with row 1.
const char* id_row = offset_table_;
const char* offset_row = offset_table_
+ index * ncolumns_ * sizeof(uint32);
const char* size_row =
size_table_ + (index - 1) * ncolumns_ * sizeof(uint32);
if (size_row + ncolumns_ * sizeof(uint32) > cu_index_ + cu_index_size_) {
version_ = 0;
return;
}
for (unsigned int col = 0u; col < ncolumns_; ++col) {
uint32 section_id =
byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(id_row)
+ col * sizeof(uint32));
uint32 offset = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(offset_row)
+ col * sizeof(uint32));
uint32 size = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(size_row) + col * sizeof(uint32));
if (section_id == DW_SECT_ABBREV) {
sections->insert(std::make_pair(
".debug_abbrev",
std::make_pair(reinterpret_cast<const uint8_t *> (abbrev_data_)
+ offset, size)));
} else if (section_id == DW_SECT_INFO) {
sections->insert(std::make_pair(
".debug_info",
std::make_pair(reinterpret_cast<const uint8_t *> (info_data_)
+ offset, size)));
} else if (section_id == DW_SECT_STR_OFFSETS) {
sections->insert(std::make_pair(
".debug_str_offsets",
std::make_pair(reinterpret_cast<const uint8_t *> (str_offsets_data_)
+ offset, size)));
}
}
sections->insert(std::make_pair(
".debug_str",
std::make_pair(reinterpret_cast<const uint8_t *> (string_buffer_),
string_buffer_size_)));
}
}
int DwpReader::LookupCU(uint64 dwo_id) {
uint32 slot = static_cast<uint32>(dwo_id) & (nslots_ - 1);
uint64 probe = byte_reader_.ReadEightBytes(
reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
if (probe != 0 && probe != dwo_id) {
uint32 secondary_hash =
(static_cast<uint32>(dwo_id >> 32) & (nslots_ - 1)) | 1;
do {
slot = (slot + secondary_hash) & (nslots_ - 1);
probe = byte_reader_.ReadEightBytes(
reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
} while (probe != 0 && probe != dwo_id);
}
if (probe == 0)
return -1;
return slot;
}
uint32 DwpReader::LookupCUv2(uint64 dwo_id) {
uint32 slot = static_cast<uint32>(dwo_id) & (nslots_ - 1);
uint64 probe = byte_reader_.ReadEightBytes(
reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
uint32 index = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(pindex_) + slot * sizeof(uint32));
if (index != 0 && probe != dwo_id) {
uint32 secondary_hash =
(static_cast<uint32>(dwo_id >> 32) & (nslots_ - 1)) | 1;
do {
slot = (slot + secondary_hash) & (nslots_ - 1);
probe = byte_reader_.ReadEightBytes(
reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
index = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(pindex_) + slot * sizeof(uint32));
} while (index != 0 && probe != dwo_id);
}
return index;
}
LineInfo::LineInfo(const uint8_t *buffer, uint64 buffer_length,
ByteReader* reader, LineInfoHandler* handler):
handler_(handler), reader_(reader), buffer_(buffer) {

View File

@ -47,16 +47,19 @@
#include <string>
#include <utility>
#include <vector>
#include <memory>
#include "common/dwarf/bytereader.h"
#include "common/dwarf/dwarf2enums.h"
#include "common/dwarf/types.h"
#include "common/using_std_string.h"
#include "common/dwarf/elf_reader.h"
namespace dwarf2reader {
struct LineStateMachine;
class Dwarf2Handler;
class LineInfoHandler;
class DwpReader;
// This maps from a string naming a section to a pair containing a
// the data for the section, and the size of the section.
@ -184,151 +187,10 @@ class LineInfoHandler {
uint32 file_num, uint32 line_num, uint32 column_num) { }
};
// The base of DWARF2/3 debug info is a DIE (Debugging Information
// Entry.
// DWARF groups DIE's into a tree and calls the root of this tree a
// "compilation unit". Most of the time, there is one compilation
// unit in the .debug_info section for each file that had debug info
// generated.
// Each DIE consists of
// 1. a tag specifying a thing that is being described (ie
// DW_TAG_subprogram for functions, DW_TAG_variable for variables, etc
// 2. attributes (such as DW_AT_location for location in memory,
// DW_AT_name for name), and data for each attribute.
// 3. A flag saying whether the DIE has children or not
// In order to gain some amount of compression, the format of
// each DIE (tag name, attributes and data forms for the attributes)
// are stored in a separate table called the "abbreviation table".
// This is done because a large number of DIEs have the exact same tag
// and list of attributes, but different data for those attributes.
// As a result, the .debug_info section is just a stream of data, and
// requires reading of the .debug_abbrev section to say what the data
// means.
// As a warning to the user, it should be noted that the reason for
// using absolute offsets from the beginning of .debug_info is that
// DWARF2/3 supports referencing DIE's from other DIE's by their offset
// from either the current compilation unit start, *or* the beginning
// of the .debug_info section. This means it is possible to reference
// a DIE in one compilation unit from a DIE in another compilation
// unit. This style of reference is usually used to eliminate
// duplicated information that occurs across compilation
// units, such as base types, etc. GCC 3.4+ support this with
// -feliminate-dwarf2-dups. Other toolchains will sometimes do
// duplicate elimination in the linker.
class CompilationUnit {
public:
// Initialize a compilation unit. This requires a map of sections,
// the offset of this compilation unit in the .debug_info section, a
// ByteReader, and a Dwarf2Handler class to call callbacks in.
CompilationUnit(const SectionMap& sections, uint64 offset,
ByteReader* reader, Dwarf2Handler* handler);
virtual ~CompilationUnit() {
if (abbrevs_) delete abbrevs_;
}
// Begin reading a Dwarf2 compilation unit, and calling the
// callbacks in the Dwarf2Handler
// Return the full length of the compilation unit, including
// headers. This plus the starting offset passed to the constructor
// is the offset of the end of the compilation unit --- and the
// start of the next compilation unit, if there is one.
uint64 Start();
private:
// This struct represents a single DWARF2/3 abbreviation
// The abbreviation tells how to read a DWARF2/3 DIE, and consist of a
// tag and a list of attributes, as well as the data form of each attribute.
struct Abbrev {
uint64 number;
enum DwarfTag tag;
bool has_children;
AttributeList attributes;
};
// A DWARF2/3 compilation unit header. This is not the same size as
// in the actual file, as the one in the file may have a 32 bit or
// 64 bit length.
struct CompilationUnitHeader {
uint64 length;
uint16 version;
uint64 abbrev_offset;
uint8 address_size;
} header_;
// Reads the DWARF2/3 header for this compilation unit.
void ReadHeader();
// Reads the DWARF2/3 abbreviations for this compilation unit
void ReadAbbrevs();
// Processes a single DIE for this compilation unit and return a new
// pointer just past the end of it
const uint8_t *ProcessDIE(uint64 dieoffset,
const uint8_t *start,
const Abbrev& abbrev);
// Processes a single attribute and return a new pointer just past the
// end of it
const uint8_t *ProcessAttribute(uint64 dieoffset,
const uint8_t *start,
enum DwarfAttribute attr,
enum DwarfForm form);
// Processes all DIEs for this compilation unit
void ProcessDIEs();
// Skips the die with attributes specified in ABBREV starting at
// START, and return the new place to position the stream to.
const uint8_t *SkipDIE(const uint8_t *start, const Abbrev& abbrev);
// Skips the attribute starting at START, with FORM, and return the
// new place to position the stream to.
const uint8_t *SkipAttribute(const uint8_t *start, enum DwarfForm form);
// Offset from section start is the offset of this compilation unit
// from the beginning of the .debug_info section.
uint64 offset_from_section_start_;
// buffer is the buffer for our CU, starting at .debug_info + offset
// passed in from constructor.
// after_header points to right after the compilation unit header.
const uint8_t *buffer_;
uint64 buffer_length_;
const uint8_t *after_header_;
// The associated ByteReader that handles endianness issues for us
ByteReader* reader_;
// The map of sections in our file to buffers containing their data
const SectionMap& sections_;
// The associated handler to call processing functions in
Dwarf2Handler* handler_;
// Set of DWARF2/3 abbreviations for this compilation unit. Indexed
// by abbreviation number, which means that abbrevs_[0] is not
// valid.
std::vector<Abbrev>* abbrevs_;
// String section buffer and length, if we have a string section.
// This is here to avoid doing a section lookup for strings in
// ProcessAttribute, which is in the hot path for DWARF2 reading.
const uint8_t *string_buffer_;
uint64 string_buffer_length_;
};
// This class is the main interface between the reader and the
// client. The virtual functions inside this get called for
// interesting events that happen during DWARF2 reading.
// The default implementation skips everything.
class Dwarf2Handler {
public:
Dwarf2Handler() { }
@ -342,6 +204,19 @@ class Dwarf2Handler {
uint8 offset_size, uint64 cu_length,
uint8 dwarf_version) { return false; }
// When processing a skeleton compilation unit, resulting from a split
// DWARF compilation, once the skeleton debug info has been read,
// the reader will call this function to ask the client if it needs
// the full debug info from the .dwo or .dwp file. Return true if
// you need it, or false to skip processing the split debug info.
virtual bool NeedSplitDebugInfo() { return true; }
// Start to process a split compilation unit at OFFSET from the beginning of
// the debug_info section in the .dwp/.dwo file. Return false if you would
// like to skip this compilation unit.
virtual bool StartSplitCompilationUnit(uint64 offset,
uint64 cu_length) { return false; }
// Start to process a DIE at OFFSET from the beginning of the .debug_info
// section. Return false if you would like to skip this DIE.
virtual bool StartDIE(uint64 offset, enum DwarfTag tag) { return false; }
@ -412,6 +287,367 @@ class Dwarf2Handler {
};
// The base of DWARF2/3 debug info is a DIE (Debugging Information
// Entry.
// DWARF groups DIE's into a tree and calls the root of this tree a
// "compilation unit". Most of the time, there is one compilation
// unit in the .debug_info section for each file that had debug info
// generated.
// Each DIE consists of
// 1. a tag specifying a thing that is being described (ie
// DW_TAG_subprogram for functions, DW_TAG_variable for variables, etc
// 2. attributes (such as DW_AT_location for location in memory,
// DW_AT_name for name), and data for each attribute.
// 3. A flag saying whether the DIE has children or not
// In order to gain some amount of compression, the format of
// each DIE (tag name, attributes and data forms for the attributes)
// are stored in a separate table called the "abbreviation table".
// This is done because a large number of DIEs have the exact same tag
// and list of attributes, but different data for those attributes.
// As a result, the .debug_info section is just a stream of data, and
// requires reading of the .debug_abbrev section to say what the data
// means.
// As a warning to the user, it should be noted that the reason for
// using absolute offsets from the beginning of .debug_info is that
// DWARF2/3 supports referencing DIE's from other DIE's by their offset
// from either the current compilation unit start, *or* the beginning
// of the .debug_info section. This means it is possible to reference
// a DIE in one compilation unit from a DIE in another compilation
// unit. This style of reference is usually used to eliminate
// duplicated information that occurs across compilation
// units, such as base types, etc. GCC 3.4+ support this with
// -feliminate-dwarf2-dups. Other toolchains will sometimes do
// duplicate elimination in the linker.
class CompilationUnit {
public:
// Initialize a compilation unit. This requires a map of sections,
// the offset of this compilation unit in the .debug_info section, a
// ByteReader, and a Dwarf2Handler class to call callbacks in.
CompilationUnit(const string& path, const SectionMap& sections, uint64 offset,
ByteReader* reader, Dwarf2Handler* handler);
virtual ~CompilationUnit() {
if (abbrevs_) delete abbrevs_;
}
// Initialize a compilation unit from a .dwo or .dwp file.
// In this case, we need the .debug_addr section from the
// executable file that contains the corresponding skeleton
// compilation unit. We also inherit the Dwarf2Handler from
// the executable file, and call it as if we were still
// processing the original compilation unit.
void SetSplitDwarf(const uint8_t* addr_buffer, uint64 addr_buffer_length,
uint64 addr_base, uint64 ranges_base, uint64 dwo_id);
// Begin reading a Dwarf2 compilation unit, and calling the
// callbacks in the Dwarf2Handler
// Return the full length of the compilation unit, including
// headers. This plus the starting offset passed to the constructor
// is the offset of the end of the compilation unit --- and the
// start of the next compilation unit, if there is one.
uint64 Start();
private:
// This struct represents a single DWARF2/3 abbreviation
// The abbreviation tells how to read a DWARF2/3 DIE, and consist of a
// tag and a list of attributes, as well as the data form of each attribute.
struct Abbrev {
uint64 number;
enum DwarfTag tag;
bool has_children;
AttributeList attributes;
};
// A DWARF2/3 compilation unit header. This is not the same size as
// in the actual file, as the one in the file may have a 32 bit or
// 64 bit length.
struct CompilationUnitHeader {
uint64 length;
uint16 version;
uint64 abbrev_offset;
uint8 address_size;
} header_;
// Reads the DWARF2/3 header for this compilation unit.
void ReadHeader();
// Reads the DWARF2/3 abbreviations for this compilation unit
void ReadAbbrevs();
// Processes a single DIE for this compilation unit and return a new
// pointer just past the end of it
const uint8_t *ProcessDIE(uint64 dieoffset,
const uint8_t *start,
const Abbrev& abbrev);
// Processes a single attribute and return a new pointer just past the
// end of it
const uint8_t *ProcessAttribute(uint64 dieoffset,
const uint8_t *start,
enum DwarfAttribute attr,
enum DwarfForm form);
// Called when we have an attribute with unsigned data to give to
// our handler. The attribute is for the DIE at OFFSET from the
// beginning of compilation unit, has a name of ATTR, a form of
// FORM, and the actual data of the attribute is in DATA.
// If we see a DW_AT_GNU_dwo_id attribute, save the value so that
// we can find the debug info in a .dwo or .dwp file.
void ProcessAttributeUnsigned(uint64 offset,
enum DwarfAttribute attr,
enum DwarfForm form,
uint64 data) {
if (attr == DW_AT_GNU_dwo_id) {
dwo_id_ = data;
}
else if (attr == DW_AT_GNU_addr_base) {
addr_base_ = data;
}
else if (attr == DW_AT_GNU_ranges_base) {
ranges_base_ = data;
}
// TODO(yunlian): When we add DW_AT_ranges_base from DWARF-5,
// that base will apply to DW_AT_ranges attributes in the
// skeleton CU as well as in the .dwo/.dwp files.
else if (attr == DW_AT_ranges && is_split_dwarf_) {
data += ranges_base_;
}
handler_->ProcessAttributeUnsigned(offset, attr, form, data);
}
// Called when we have an attribute with signed data to give to
// our handler. The attribute is for the DIE at OFFSET from the
// beginning of compilation unit, has a name of ATTR, a form of
// FORM, and the actual data of the attribute is in DATA.
void ProcessAttributeSigned(uint64 offset,
enum DwarfAttribute attr,
enum DwarfForm form,
int64 data) {
handler_->ProcessAttributeSigned(offset, attr, form, data);
}
// Called when we have an attribute with a buffer of data to give to
// our handler. The attribute is for the DIE at OFFSET from the
// beginning of compilation unit, has a name of ATTR, a form of
// FORM, and the actual data of the attribute is in DATA, and the
// length of the buffer is LENGTH.
void ProcessAttributeBuffer(uint64 offset,
enum DwarfAttribute attr,
enum DwarfForm form,
const uint8_t* data,
uint64 len) {
handler_->ProcessAttributeBuffer(offset, attr, form, data, len);
}
// Called when we have an attribute with string data to give to
// our handler. The attribute is for the DIE at OFFSET from the
// beginning of compilation unit, has a name of ATTR, a form of
// FORM, and the actual data of the attribute is in DATA.
// If we see a DW_AT_GNU_dwo_name attribute, save the value so
// that we can find the debug info in a .dwo or .dwp file.
void ProcessAttributeString(uint64 offset,
enum DwarfAttribute attr,
enum DwarfForm form,
const char* data) {
if (attr == DW_AT_GNU_dwo_name)
dwo_name_ = data;
handler_->ProcessAttributeString(offset, attr, form, data);
}
// Processes all DIEs for this compilation unit
void ProcessDIEs();
// Skips the die with attributes specified in ABBREV starting at
// START, and return the new place to position the stream to.
const uint8_t *SkipDIE(const uint8_t *start, const Abbrev& abbrev);
// Skips the attribute starting at START, with FORM, and return the
// new place to position the stream to.
const uint8_t *SkipAttribute(const uint8_t *start, enum DwarfForm form);
// Process the actual debug information in a split DWARF file.
void ProcessSplitDwarf();
// Read the debug sections from a .dwo file.
void ReadDebugSectionsFromDwo(ElfReader* elf_reader,
SectionMap* sections);
// Path of the file containing the debug information.
const string path_;
// Offset from section start is the offset of this compilation unit
// from the beginning of the .debug_info section.
uint64 offset_from_section_start_;
// buffer is the buffer for our CU, starting at .debug_info + offset
// passed in from constructor.
// after_header points to right after the compilation unit header.
const uint8_t *buffer_;
uint64 buffer_length_;
const uint8_t *after_header_;
// The associated ByteReader that handles endianness issues for us
ByteReader* reader_;
// The map of sections in our file to buffers containing their data
const SectionMap& sections_;
// The associated handler to call processing functions in
Dwarf2Handler* handler_;
// Set of DWARF2/3 abbreviations for this compilation unit. Indexed
// by abbreviation number, which means that abbrevs_[0] is not
// valid.
std::vector<Abbrev>* abbrevs_;
// String section buffer and length, if we have a string section.
// This is here to avoid doing a section lookup for strings in
// ProcessAttribute, which is in the hot path for DWARF2 reading.
const uint8_t *string_buffer_;
uint64 string_buffer_length_;
// String offsets section buffer and length, if we have a string offsets
// section (.debug_str_offsets or .debug_str_offsets.dwo).
const uint8_t* str_offsets_buffer_;
uint64 str_offsets_buffer_length_;
// Address section buffer and length, if we have an address section
// (.debug_addr).
const uint8_t* addr_buffer_;
uint64 addr_buffer_length_;
// Flag indicating whether this compilation unit is part of a .dwo
// or .dwp file. If true, we are reading this unit because a
// skeleton compilation unit in an executable file had a
// DW_AT_GNU_dwo_name or DW_AT_GNU_dwo_id attribute.
// In a .dwo file, we expect the string offsets section to
// have a ".dwo" suffix, and we will use the ".debug_addr" section
// associated with the skeleton compilation unit.
bool is_split_dwarf_;
// The value of the DW_AT_GNU_dwo_id attribute, if any.
uint64 dwo_id_;
// The value of the DW_AT_GNU_dwo_name attribute, if any.
const char* dwo_name_;
// If this is a split DWARF CU, the value of the DW_AT_GNU_dwo_id attribute
// from the skeleton CU.
uint64 skeleton_dwo_id_;
// The value of the DW_AT_GNU_ranges_base attribute, if any.
uint64 ranges_base_;
// The value of the DW_AT_GNU_addr_base attribute, if any.
uint64 addr_base_;
// True if we have already looked for a .dwp file.
bool have_checked_for_dwp_;
// Path to the .dwp file.
string dwp_path_;
// ByteReader for the DWP file.
std::unique_ptr<ByteReader> dwp_byte_reader_;
// DWP reader.
std::unique_ptr<DwpReader> dwp_reader_;
};
// A Reader for a .dwp file. Supports the fetching of DWARF debug
// info for a given dwo_id.
//
// There are two versions of .dwp files. In both versions, the
// .dwp file is an ELF file containing only debug sections.
// In Version 1, the file contains many copies of each debug
// section, one for each .dwo file that is packaged in the .dwp
// file, and the .debug_cu_index section maps from the dwo_id
// to a set of section indexes. In Version 2, the file contains
// one of each debug section, and the .debug_cu_index section
// maps from the dwo_id to a set of offsets and lengths that
// identify each .dwo file's contribution to the larger sections.
class DwpReader {
public:
DwpReader(const ByteReader& byte_reader, ElfReader* elf_reader);
~DwpReader();
// Read the CU index and initialize data members.
void Initialize();
// Read the debug sections for the given dwo_id.
void ReadDebugSectionsForCU(uint64 dwo_id, SectionMap* sections);
private:
// Search a v1 hash table for "dwo_id". Returns the slot index
// where the dwo_id was found, or -1 if it was not found.
int LookupCU(uint64 dwo_id);
// Search a v2 hash table for "dwo_id". Returns the row index
// in the offsets and sizes tables, or 0 if it was not found.
uint32 LookupCUv2(uint64 dwo_id);
// The ELF reader for the .dwp file.
ElfReader* elf_reader_;
// The ByteReader for the .dwp file.
const ByteReader& byte_reader_;
// Pointer to the .debug_cu_index section.
const char* cu_index_;
// Size of the .debug_cu_index section.
size_t cu_index_size_;
// Pointer to the .debug_str.dwo section.
const char* string_buffer_;
// Size of the .debug_str.dwo section.
size_t string_buffer_size_;
// Version of the .dwp file. We support versions 1 and 2 currently.
int version_;
// Number of columns in the section tables (version 2).
unsigned int ncolumns_;
// Number of units in the section tables (version 2).
unsigned int nunits_;
// Number of slots in the hash table.
unsigned int nslots_;
// Pointer to the beginning of the hash table.
const char* phash_;
// Pointer to the beginning of the index table.
const char* pindex_;
// Pointer to the beginning of the section index pool (version 1).
const char* shndx_pool_;
// Pointer to the beginning of the section offset table (version 2).
const char* offset_table_;
// Pointer to the beginning of the section size table (version 2).
const char* size_table_;
// Contents of the sections of interest (version 2).
const char* abbrev_data_;
size_t abbrev_size_;
const char* info_data_;
size_t info_size_;
const char* str_offsets_data_;
size_t str_offsets_size_;
};
// This class is a reader for DWARF's Call Frame Information. CFI
// describes how to unwind stack frames --- even for functions that do
// not follow fixed conventions for saving registers, whose frame size

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,166 @@
// Copyright 2005 Google Inc. All Rights Reserved.
// Author: chatham@google.com (Andrew Chatham)
// Author: satorux@google.com (Satoru Takabayashi)
//
// ElfReader handles reading in ELF. It can extract symbols from the
// current process, which may be used to symbolize stack traces
// without having to make a potentially dangerous call to fork().
//
// ElfReader dynamically allocates memory, so it is not appropriate to
// use once the address space might be corrupted, such as during
// process death.
//
// ElfReader supports both 32-bit and 64-bit ELF binaries.
#ifndef COMMON_DWARF_ELF_READER_H__
#define COMMON_DWARF_ELF_READER_H__
#include <string>
#include <vector>
#include "common/dwarf/types.h"
using std::string;
using std::vector;
using std::pair;
namespace dwarf2reader {
class SymbolMap;
class Elf32;
class Elf64;
template<typename ElfArch>
class ElfReaderImpl;
class ElfReader {
public:
explicit ElfReader(const string &path);
~ElfReader();
// Parse the ELF prologue of this file and return whether it was
// successfully parsed and matches the word size and byte order of
// the current process.
bool IsNativeElfFile() const;
// Similar to IsNativeElfFile but checks if it's a 32-bit ELF file.
bool IsElf32File() const;
// Similar to IsNativeElfFile but checks if it's a 64-bit ELF file.
bool IsElf64File() const;
// Checks if it's an ELF file of type ET_DYN (shared object file).
bool IsDynamicSharedObject();
// Add symbols in the given ELF file into the provided SymbolMap,
// assuming that the file has been loaded into the specified
// offset.
//
// The remaining arguments are typically taken from a
// ProcMapsIterator (base/sysinfo.h) and describe which portions of
// the ELF file are mapped into which parts of memory:
//
// mem_offset - position at which the segment is mapped into memory
// file_offset - offset in the file where the mapping begins
// length - length of the mapped segment
void AddSymbols(SymbolMap *symbols,
uint64 mem_offset, uint64 file_offset,
uint64 length);
class SymbolSink {
public:
virtual ~SymbolSink() {}
virtual void AddSymbol(const char *name, uint64 address, uint64 size) = 0;
};
// Like AddSymbols above, but with no address correction.
// Processes any SHT_SYMTAB section, followed by any SHT_DYNSYM section.
void VisitSymbols(SymbolSink *sink);
// Like VisitSymbols above, but for a specific symbol binding/type.
// A negative value for the binding and type parameters means any
// binding or type.
void VisitSymbols(SymbolSink *sink, int symbol_binding, int symbol_type);
// Like VisitSymbols above but can optionally export raw symbol values instead
// of adjusted ones.
void VisitSymbols(SymbolSink *sink, int symbol_binding, int symbol_type,
bool get_raw_symbol_values);
// p_vaddr of the first PT_LOAD segment (if any), or 0 if no PT_LOAD
// segments are present. This is the address an ELF image was linked
// (by static linker) to be loaded at. Usually (but not always) 0 for
// shared libraries and position-independent executables.
uint64 VaddrOfFirstLoadSegment();
// Return the name of section "shndx". Returns NULL if the section
// is not found.
const char *GetSectionName(int shndx);
// Return the number of sections in the given ELF file.
uint64 GetNumSections();
// Get section "shndx" from the given ELF file. On success, return
// the pointer to the section and store the size in "size".
// On error, return NULL. The returned section data is only valid
// until the ElfReader gets destroyed.
const char *GetSectionByIndex(int shndx, size_t *size);
// Get section with "section_name" (ex. ".text", ".symtab") in the
// given ELF file. On success, return the pointer to the section
// and store the size in "size". On error, return NULL. The
// returned section data is only valid until the ElfReader gets
// destroyed.
const char *GetSectionByName(const string &section_name, size_t *size);
// This is like GetSectionByName() but it returns a lot of extra information
// about the section. The SectionInfo structure is almost identical to
// the typedef struct Elf64_Shdr defined in <elf.h>, but is redefined
// here so that the many short macro names in <elf.h> don't have to be
// added to our already cluttered namespace.
struct SectionInfo {
uint32 type; // Section type (SHT_xxx constant from elf.h).
uint64 flags; // Section flags (SHF_xxx constants from elf.h).
uint64 addr; // Section virtual address at execution.
uint64 offset; // Section file offset.
uint64 size; // Section size in bytes.
uint32 link; // Link to another section.
uint32 info; // Additional section information.
uint64 addralign; // Section alignment.
uint64 entsize; // Entry size if section holds a table.
};
const char *GetSectionInfoByName(const string &section_name,
SectionInfo *info);
// Check if "path" is an ELF binary that has not been stripped of symbol
// tables. This function supports both 32-bit and 64-bit ELF binaries.
static bool IsNonStrippedELFBinary(const string &path);
// Check if "path" is an ELF binary that has not been stripped of debug
// info. Unlike IsNonStrippedELFBinary, this function will return
// false for binaries passed through "strip -S".
static bool IsNonDebugStrippedELFBinary(const string &path);
// Match a requested section name with the section name as it
// appears in the elf-file, adjusting for compressed debug section
// names. For example, returns true if name == ".debug_abbrev" and
// sh_name == ".zdebug_abbrev"
static bool SectionNamesMatch(const string &name, const string &sh_name);
private:
// Lazily initialize impl32_ and return it.
ElfReaderImpl<Elf32> *GetImpl32();
// Ditto for impl64_.
ElfReaderImpl<Elf64> *GetImpl64();
// Path of the file we're reading.
const string path_;
// Read-only file descriptor for the file. May be -1 if there was an
// error during open.
int fd_;
ElfReaderImpl<Elf32> *impl32_;
ElfReaderImpl<Elf64> *impl64_;
};
} // namespace dwarf2reader
#endif // COMMON_DWARF_ELF_READER_H__

View File

@ -288,7 +288,8 @@ bool LoadDwarf(const string& dwarf_filename,
// Make a Dwarf2Handler that drives the DIEHandler.
dwarf2reader::DIEDispatcher die_dispatcher(&root_handler);
// Make a DWARF parser for the compilation unit at OFFSET.
dwarf2reader::CompilationUnit reader(file_context.section_map(),
dwarf2reader::CompilationUnit reader(dwarf_filename,
file_context.section_map(),
offset,
&byte_reader,
&die_dispatcher);

View File

@ -437,7 +437,8 @@ bool DumpSymbols::ReadDwarf(google_breakpad::Module *module,
// Make a Dwarf2Handler that drives our DIEHandler.
dwarf2reader::DIEDispatcher die_dispatcher(&root_handler);
// Make a DWARF parser for the compilation unit at OFFSET.
dwarf2reader::CompilationUnit dwarf_reader(file_context.section_map(),
dwarf2reader::CompilationUnit dwarf_reader(selected_object_name_,
file_context.section_map(),
offset,
&byte_reader,
&die_dispatcher);