From 608e2dbbfefcec9aa3efc863ffcc889786ae93d7 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Mon, 26 Nov 2012 19:23:56 +0000 Subject: [PATCH] 2012-11-26 Alexander Larsson Jan Kratochvil Tom Tromey * NEWS: Mention mini debuginfo feature. * minidebug.c: New file. * configure.ac: Check for lzma. * configure, config.in: Rebuild. * Makefile.in (LIBLZMA): New variable. (CLIBS): Include LIBLZMA. (SFILES): Mention minidebug.c. (COMMON_OBS): Mention minidebug.o. * symfile.c (read_symbols): New function. (syms_from_objfile, reread_symbols): Call it. * symfile.h (find_separate_debug_file_in_section): Declare. doc * gdb.texinfo (MiniDebugInfo): New node. (GDB Files): Update. testsuite * gdb.base/gnu-debugdata.exp: New file. * gdb.base/gnu-debugdata.c: New file. * lib/gdb.exp (gdb_file_cmd): Handle LZMA warning. (gdb_unload): Return 0 on success. --- gdb/ChangeLog | 16 + gdb/Makefile.in | 8 +- gdb/NEWS | 5 + gdb/config.in | 3 + gdb/configure | 496 +++++++++++++++++++++++ gdb/configure.ac | 21 + gdb/doc/ChangeLog | 5 + gdb/doc/gdb.texinfo | 50 +++ gdb/symfile.c | 37 +- gdb/symfile.h | 4 + gdb/testsuite/ChangeLog | 8 + gdb/testsuite/gdb.base/gnu-debugdata.c | 30 ++ gdb/testsuite/gdb.base/gnu-debugdata.exp | 157 +++++++ gdb/testsuite/lib/gdb.exp | 9 + 14 files changed, 835 insertions(+), 14 deletions(-) create mode 100644 gdb/testsuite/gdb.base/gnu-debugdata.c create mode 100644 gdb/testsuite/gdb.base/gnu-debugdata.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 98afd334b9c..4741adfc7c7 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,19 @@ +2012-11-26 Alexander Larsson + Jan Kratochvil + Tom Tromey + + * NEWS: Mention mini debuginfo feature. + * minidebug.c: New file. + * configure.ac: Check for lzma. + * configure, config.in: Rebuild. + * Makefile.in (LIBLZMA): New variable. + (CLIBS): Include LIBLZMA. + (SFILES): Mention minidebug.c. + (COMMON_OBS): Mention minidebug.o. + * symfile.c (read_symbols): New function. + (syms_from_objfile, reread_symbols): Call it. + * symfile.h (find_separate_debug_file_in_section): Declare. + 2012-11-26 Keith Seitz * exec.c (exec_file_attach): Move cleanup after verifying that diff --git a/gdb/Makefile.in b/gdb/Makefile.in index e9aeb0caa37..3dd7b85233d 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -151,6 +151,9 @@ READLINE_CFLAGS = @READLINE_CFLAGS@ # Where is expat? This will be empty if expat was not available. LIBEXPAT = @LIBEXPAT@ +# Where is lzma? This will be empty if lzma was not available. +LIBLZMA = @LIBLZMA@ + WARN_CFLAGS = @WARN_CFLAGS@ WERROR_CFLAGS = @WERROR_CFLAGS@ GDB_WARN_CFLAGS = $(WARN_CFLAGS) @@ -469,7 +472,7 @@ INTERNAL_LDFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(MH_LDFLAGS) $(LDFLAGS) $(CONFIG_ # LIBIBERTY appears twice on purpose. CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(INTL) $(LIBIBERTY) $(LIBDECNUMBER) \ $(XM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ @PYTHON_LIBS@ \ - $(LIBEXPAT) \ + $(LIBEXPAT) $(LIBLZMA) \ $(LIBIBERTY) $(WIN32LIBS) $(LIBGNU) CDEPS = $(XM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) \ $(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) $(LIBGNU) @@ -714,7 +717,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ inline-frame.c \ interps.c \ jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \ - language.c linespec.c \ + language.c linespec.c minidebug.c \ m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c \ macrotab.c macroexp.c macrocmd.c macroscope.c main.c maint.c \ mdebugread.c memattr.c mem-break.c minsyms.c mipsread.c memory-map.c \ @@ -877,6 +880,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ filesystem.o \ inf-child.o \ interps.o \ + minidebug.o \ main.o \ macrotab.o macrocmd.o macroexp.o macroscope.o \ mi-common.o \ diff --git a/gdb/NEWS b/gdb/NEWS index 5e3f54dd15a..3b09e5fad0a 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -100,6 +100,11 @@ show print type typedefs ** New optional parameter COUNT added to the "-data-write-memory-bytes" command, to allow pattern filling of memory areas. +* GDB now supports the "mini debuginfo" section, .gnu_debugdata. + You must have the LZMA library available when configuring GDB for this + feature to be enabled. For more information, see: + http://fedoraproject.org/wiki/Features/MiniDebugInfo + *** Changes in GDB 7.5 * GDB now supports x32 ABI. Visit diff --git a/gdb/config.in b/gdb/config.in index 34aa31e8b6e..a3b8f42bac6 100644 --- a/gdb/config.in +++ b/gdb/config.in @@ -192,6 +192,9 @@ /* Define to 1 if you have the `libiconvlist' function. */ #undef HAVE_LIBICONVLIST +/* Define if you have the lzma library. */ +#undef HAVE_LIBLZMA + /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM diff --git a/gdb/configure b/gdb/configure index 0d70d0aa1ec..1ee8c787c27 100755 --- a/gdb/configure +++ b/gdb/configure @@ -641,6 +641,9 @@ TCL_VERSION WIN32LDAPP GUI_CFLAGS_X LIBGUI +LTLIBLZMA +LIBLZMA +HAVE_LIBLZMA WIN32LIBS SER_HARDWIRE WERROR_CFLAGS @@ -808,6 +811,8 @@ with_system_gdbinit enable_werror enable_build_warnings enable_gdb_build_warnings +with_lzma +with_liblzma_prefix with_tcl with_tk with_x @@ -1521,6 +1526,9 @@ Optional Packages: --with-sysroot[=DIR] search for usr/lib et al within DIR --with-system-gdbinit=PATH automatically load a system-wide gdbinit file + --with-lzma support lzma compression (auto/yes/no) + --with-liblzma-prefix[=DIR] search for liblzma in DIR/include and DIR/lib + --without-liblzma-prefix don't search for liblzma in includedir and libdir --with-tcl directory containing tcl configuration (tclConfig.sh) --with-tk directory containing tk configuration (tkConfig.sh) --with-x use the X Window System @@ -12617,6 +12625,494 @@ LIBS=$OLD_LIBS # Add any host-specific objects to GDB. CONFIG_OBS="${CONFIG_OBS} ${gdb_host_obs}" +# If building on ELF, look for lzma support for embedded compressed debug info. +if test $gdb_cv_var_elf = yes; then + +# Check whether --with-lzma was given. +if test "${with_lzma+set}" = set; then : + withval=$with_lzma; +else + with_lzma=auto +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use lzma" >&5 +$as_echo_n "checking whether to use lzma... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_lzma" >&5 +$as_echo "$with_lzma" >&6; } + + if test "${with_lzma}" != no; then + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-liblzma-prefix was given. +if test "${with_liblzma_prefix+set}" = set; then : + withval=$with_liblzma_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/lib" + fi + fi + +fi + + LIBLZMA= + LTLIBLZMA= + INCLZMA= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='lzma ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBLZMA="${LIBLZMA}${LIBLZMA:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBLZMA="${LTLIBLZMA}${LTLIBLZMA:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + if test $use_additional = yes; then + if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then + found_dir="$additional_libdir" + found_so="$additional_libdir/lib$name.$shlibext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + else + if test -f "$additional_libdir/lib$name.$libext"; then + found_dir="$additional_libdir" + found_a="$additional_libdir/lib$name.$libext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBLZMA; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then + found_dir="$dir" + found_so="$dir/lib$name.$shlibext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + else + if test -f "$dir/lib$name.$libext"; then + found_dir="$dir" + found_a="$dir/lib$name.$libext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBLZMA="${LTLIBLZMA}${LTLIBLZMA:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then + LIBLZMA="${LIBLZMA}${LIBLZMA:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$hardcode_direct" = yes; then + LIBLZMA="${LIBLZMA}${LIBLZMA:+ }$found_so" + else + if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then + LIBLZMA="${LIBLZMA}${LIBLZMA:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBLZMA; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBLZMA="${LIBLZMA}${LIBLZMA:+ }-L$found_dir" + fi + if test "$hardcode_minus_L" != no; then + LIBLZMA="${LIBLZMA}${LIBLZMA:+ }$found_so" + else + LIBLZMA="${LIBLZMA}${LIBLZMA:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBLZMA="${LIBLZMA}${LIBLZMA:+ }$found_a" + else + LIBLZMA="${LIBLZMA}${LIBLZMA:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */lib | */lib/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCLZMA; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCLZMA="${INCLZMA}${INCLZMA:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/lib"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/lib"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBLZMA; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBLZMA="${LIBLZMA}${LIBLZMA:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBLZMA; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBLZMA="${LTLIBLZMA}${LTLIBLZMA:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBLZMA="${LIBLZMA}${LIBLZMA:+ }$dep" + LTLIBLZMA="${LTLIBLZMA}${LTLIBLZMA:+ }$dep" + ;; + esac + done + fi + else + LIBLZMA="${LIBLZMA}${LIBLZMA:+ }-l$name" + LTLIBLZMA="${LTLIBLZMA}${LTLIBLZMA:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBLZMA="${LIBLZMA}${LIBLZMA:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBLZMA="${LIBLZMA}${LIBLZMA:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBLZMA="${LTLIBLZMA}${LTLIBLZMA:+ }-R$found_dir" + done + fi + + + ac_save_CPPFLAGS="$CPPFLAGS" + + for element in $INCLZMA; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for liblzma" >&5 +$as_echo_n "checking for liblzma... " >&6; } +if test "${ac_cv_liblzma+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + ac_save_LIBS="$LIBS" + LIBS="$LIBS $LIBLZMA" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include "lzma.h" +int +main () +{ +lzma_index_iter iter; + lzma_index_iter_init (&iter, 0); + lzma_mf_is_supported (LZMA_MF_HC3); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_liblzma=yes +else + ac_cv_liblzma=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$ac_save_LIBS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_liblzma" >&5 +$as_echo "$ac_cv_liblzma" >&6; } + if test "$ac_cv_liblzma" = yes; then + HAVE_LIBLZMA=yes + +$as_echo "#define HAVE_LIBLZMA 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with liblzma" >&5 +$as_echo_n "checking how to link with liblzma... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBLZMA" >&5 +$as_echo "$LIBLZMA" >&6; } + else + HAVE_LIBLZMA=no + CPPFLAGS="$ac_save_CPPFLAGS" + LIBLZMA= + LTLIBLZMA= + fi + + + + + + + if test "$HAVE_LIBLZMA" != yes; then + if test "$with_lzma" = yes; then + as_fn_error "missing liblzma for --with-lzma" "$LINENO" 5 + fi + fi + fi +fi + LIBGUI="../libgui/src/libgui.a" GUI_CFLAGS_X="-I${srcdir}/../libgui/src" diff --git a/gdb/configure.ac b/gdb/configure.ac index 030fb06c420..97911431879 100644 --- a/gdb/configure.ac +++ b/gdb/configure.ac @@ -2053,6 +2053,27 @@ LIBS=$OLD_LIBS # Add any host-specific objects to GDB. CONFIG_OBS="${CONFIG_OBS} ${gdb_host_obs}" +# If building on ELF, look for lzma support for embedded compressed debug info. +if test $gdb_cv_var_elf = yes; then + AC_ARG_WITH(lzma, + AS_HELP_STRING([--with-lzma], [support lzma compression (auto/yes/no)]), + [], [with_lzma=auto]) + AC_MSG_CHECKING([whether to use lzma]) + AC_MSG_RESULT([$with_lzma]) + + if test "${with_lzma}" != no; then + AC_LIB_HAVE_LINKFLAGS([lzma], [], [#include "lzma.h"], + [lzma_index_iter iter; + lzma_index_iter_init (&iter, 0); + lzma_mf_is_supported (LZMA_MF_HC3);]) + if test "$HAVE_LIBLZMA" != yes; then + if test "$with_lzma" = yes; then + AC_MSG_ERROR([missing liblzma for --with-lzma]) + fi + fi + fi +fi + LIBGUI="../libgui/src/libgui.a" GUI_CFLAGS_X="-I${srcdir}/../libgui/src" AC_SUBST(LIBGUI) diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 8fda5d50060..b59476462d9 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2012-11-26 Tom Tromey + + * gdb.texinfo (MiniDebugInfo): New node. + (GDB Files): Update. + 2012-11-16 Doug Evans * gdb.texinfo (System-wide configuration): If the system-wide init diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 80148f7d3f5..afe3845fe15 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -15865,6 +15865,7 @@ program. To debug a core dump of a previous run, you must also tell @menu * Files:: Commands to specify files * Separate Debug Files:: Debugging information in separate files +* MiniDebugInfo:: Debugging information in a special section * Index Files:: Index files speed up GDB * Symbol Errors:: Errors reading symbol files * Data Files:: GDB data files @@ -16790,6 +16791,55 @@ gnu_debuglink_crc32 (unsigned long crc, @noindent This computation does not apply to the ``build ID'' method. +@node MiniDebugInfo +@section Debugging information in a special section +@cindex separate debug sections +@cindex @samp{.gnu_debugdata} section + +Some systems ship pre-built executables and libraries that have a +special @samp{.gnu_debugdata} section. This feature is called +@dfn{MiniDebugInfo}. This section holds an LZMA-compressed object and +is used to supply extra symbols for backtraces. + +The intent of this section is to provide extra minimal debugging +information for use in simple backtraces. It is not intended to be a +replacement for full separate debugging information (@pxref{Separate +Debug Files}). The example below shows the intended use; however, +@value{GDBN} does not currently put restrictions on what sort of +debugging information might be included in the section. + +@value{GDBN} has support for this extension. If the section exists, +then it is used provided that no other source of debugging information +can be found, and that @value{GDBN} was configured with LZMA support. + +This section can be easily created using @command{objcopy} and other +standard utilities: + +@smallexample +# Extract the dynamic symbols from the main binary, there is no need +# to also have these in the normal symbol table +nm -D @var{binary} --format=posix --defined-only \ + | awk '@{ print $1 @}' | sort > dynsyms + +# Extract all the text (i.e. function) symbols from the debuginfo . +nm @var{binary} --format=posix --defined-only \ + | awk '@{ if ($2 == "T" || $2 == "t") print $1 @}' \ + | sort > funcsyms + +# Keep all the function symbols not already in the dynamic symbol +# table. +comm -13 dynsyms funcsyms > keep_symbols + +# Copy the full debuginfo, keeping only a minimal set of symbols and +# removing some unnecessary sections. +objcopy -S --remove-section .gdb_index --remove-section .comment \ + --keep-symbols=keep_symbols @var{binary} mini_debuginfo + +# Inject the compressed data into the .gnu_debugdata section of the +# original binary. +xz mini_debuginfo +objcopy --add-section .gnu_debugdata=mini_debuginfo.xz @var{binary} +@end smallexample @node Index Files @section Index Files Speed Up @value{GDBN} diff --git a/gdb/symfile.c b/gdb/symfile.c index 55af541e93c..6a2fc89e753 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -876,6 +876,27 @@ default_symfile_segments (bfd *abfd) return data; } +/* This is a convenience function to call sym_read for OBJFILE and + possibly force the partial symbols to be read. */ + +static void +read_symbols (struct objfile *objfile, int add_flags) +{ + (*objfile->sf->sym_read) (objfile, add_flags); + if (!objfile_has_partial_symbols (objfile)) + { + bfd *abfd = find_separate_debug_file_in_section (objfile); + struct cleanup *cleanup = make_cleanup_bfd_unref (abfd); + + if (abfd != NULL) + symbol_file_add_separate (abfd, add_flags, objfile); + + do_cleanups (cleanup); + } + if ((add_flags & SYMFILE_NO_READ) == 0) + require_partial_symbols (objfile, 0); +} + /* Process a symbol file, as either the main file or as a dynamically loaded file. @@ -996,10 +1017,7 @@ syms_from_objfile (struct objfile *objfile, init_objfile_sect_indices (objfile); } - (*objfile->sf->sym_read) (objfile, add_flags); - - if ((add_flags & SYMFILE_NO_READ) == 0) - require_partial_symbols (objfile, 0); + read_symbols (objfile, add_flags); /* Discard cleanups as symbol reading was successful. */ @@ -2601,14 +2619,9 @@ reread_symbols (void) (*objfile->sf->sym_init) (objfile); clear_complaints (&symfile_complaints, 1, 1); - /* Do not set flags as this is safe and we don't want to be - verbose. */ - (*objfile->sf->sym_read) (objfile, 0); - if ((objfile->flags & OBJF_PSYMTABS_READ) != 0) - { - objfile->flags &= ~OBJF_PSYMTABS_READ; - require_partial_symbols (objfile, 0); - } + + objfile->flags &= ~OBJF_PSYMTABS_READ; + read_symbols (objfile, 0); if (!objfile_has_symbols (objfile)) { diff --git a/gdb/symfile.h b/gdb/symfile.h index bb75c184586..223f8740512 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -690,4 +690,8 @@ extern void elfmdebug_build_psymtabs (struct objfile *, const struct ecoff_debug_swap *, asection *); +/* From minidebug.c. */ + +extern bfd *find_separate_debug_file_in_section (struct objfile *); + #endif /* !defined(SYMFILE_H) */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index cd7c7049917..b5b125f6699 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2012-11-26 Jan Kratochvil + Tom Tromey + + * gdb.base/gnu-debugdata.exp: New file. + * gdb.base/gnu-debugdata.c: New file. + * lib/gdb.exp (gdb_file_cmd): Handle LZMA warning. + (gdb_unload): Return 0 on success. + 2012-11-26 Jan Kratochvil * gdb.base/enumval.exp (print e, print f, print K): XFAIL on GCC <= 4.6. diff --git a/gdb/testsuite/gdb.base/gnu-debugdata.c b/gdb/testsuite/gdb.base/gnu-debugdata.c new file mode 100644 index 00000000000..b8b7e8af884 --- /dev/null +++ b/gdb/testsuite/gdb.base/gnu-debugdata.c @@ -0,0 +1,30 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2012 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +static int +debugdata_function (void) +{ + return raise (SIGSEGV) + 1; +} + +int +main (void) +{ + return debugdata_function () + 1; +} diff --git a/gdb/testsuite/gdb.base/gnu-debugdata.exp b/gdb/testsuite/gdb.base/gnu-debugdata.exp new file mode 100644 index 00000000000..f876309ba6f --- /dev/null +++ b/gdb/testsuite/gdb.base/gnu-debugdata.exp @@ -0,0 +1,157 @@ +# Copyright 2012 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +standard_testfile + +if [build_executable ${testfile}.exp $testfile] { + return -1 +} + +# A wrapper for 'remote_exec host' that passes or fails a test. +# Returns 0 if all went well, nonzero on failure. +# TEST is the name of the test, other arguments are as for +# remote_exec. +proc run {test program args} { + verbose "cmdline is remote_exec host $program $args" + # remote_exec doesn't work properly if the output is set but the + # input is the empty string -- so replace an empty input with + # /dev/null. + if {[llength $args] > 1 && [lindex $args 1] == ""} { + set args [lreplace $args 1 1 "/dev/null"] + } + set result [eval remote_exec host [list $program] $args] + verbose "result is $result" + lassign $result status output + if {$status == 0} { + pass $test + return 0 + } else { + fail $test + return -1 + } +} + +set pipeline_counter 0 + +# Run a pipeline of processes through 'run'. +# TEST is the base name of the test, it is modified and passed to 'run'. +# Each subsequent argument is a list of the form {PROGRAM [ARG]...}. +# It is passed to 'run'. However, before being passed, if input and output +# files are not specified in the list, then this proc provides them. +# Each program in the pipeline takes its input from the previous +# program's output. +proc pipeline {test args} { + global pipeline_counter + + set input_file {} + foreach arglist $args { + verbose "raw args are $arglist" + lassign $arglist program arguments input output + + if {$input == ""} { + set input $input_file + } + if {$output == ""} { + set output [standard_output_file pipe.[pid].$pipeline_counter] + incr pipeline_counter + } + verbose "cooked args are [list $program $arguments $input $output]" + + if {[run "$test - invoke $program" $program $arguments \ + $input $output]} { + return -1 + } + + set input_file $output + } + return 0 +} + +# Extract the dynamic symbols from the main binary, there is no need +# to also have these in the normal symbol table. +remote_file host delete ${binfile}.dynsyms +if {[pipeline "nm -D" \ + [list [transform nm] "-D ${binfile} --format=posix --defined-only"] \ + [list awk "\\{print\\ \\\$1\\}"] \ + [list sort "" "" "${binfile}.dynsyms"]]} { + return -1 +} + +# Extract all the text (i.e. function) symbols from the debuginfo. +remote_file host delete ${binfile}.funcsyms +if {[pipeline "nm" \ + [list [transform nm] "${binfile} --format=posix --defined-only"] \ + [list awk "\\{if(\\\$2==\"T\"||\\\$2==\"t\")print\\ \\\$1\\}"] \ + [list sort "" "" "${binfile}.funcsyms"]]} { + return -1 +} + +# Keep all the function symbols not already in the dynamic symbol +# table. +remote_file host delete ${binfile}.keep_symbols +if {[run "comm" "comm" "-13 ${binfile}.dynsyms ${binfile}.funcsyms" "" \ + "${binfile}.keep_symbols"]} { + return -1 +} + +# Copy the full debuginfo, keeping only a minimal set of symbols and +# removing some unnecessary sections. +remote_file host delete ${binfile}.mini_debuginfo +if {[run "objcopy 1" [transform objcopy] "-S --remove-section .gdb_index --remove-section .comment --keep-symbols=${binfile}.keep_symbols ${binfile} ${binfile}.mini_debuginfo"]} { + return -1 +} + +# GDB specific - we do not have split executable in advance. +remote_file host delete ${binfile}.strip +if {[run "strip" [transform strip] \ + "--strip-all -o ${binfile}.strip ${binfile}"]} { + return -1 +} + +# Inject the compressed data into the .gnu_debugdata section of the +# original binary. +remote_file host delete ${binfile}.mini_debuginfo.xz +if {[run "xz" "xz" "${binfile}.mini_debuginfo"]} { + return -1 +} +remote_file host delete ${binfile}.test +if {[run "objcopy 2" [transform objcopy] "--add-section .gnu_debugdata=${binfile}.mini_debuginfo.xz ${binfile}.strip ${binfile}.test"]} { + return -1 +} + +clean_restart "$testfile.strip" + +gdb_test "p debugdata_function" \ + {No symbol table is loaded\. Use the "file" command\.} \ + "no symtab" + +clean_restart "$testfile.test" + +if {$gdb_file_cmd_debug_info == "lzma"} { + unsupported "LZMA support not available in this gdb" +} else { + gdb_test "p debugdata_function" \ + { = {} 0x[0-9a-f]+ } \ + "have symtab" +} + +# Be sure to test the 'close' method on the MiniDebugInfo BFD. +if {[gdb_unload]} { + fail "unload MiniDebugInfo" +} else { + pass "unload MiniDebugInfo" +} + +gdb_exit diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index 16e8b54fc4b..781ccc858c0 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -128,6 +128,7 @@ proc gdb_version { } { # # gdb_unload -- unload a file if one is loaded +# Return 0 on success, -1 on error. # proc gdb_unload {} { @@ -152,6 +153,7 @@ proc gdb_unload {} { return -1 } } + return 0 } # Many of the tests depend on setting breakpoints at various places and @@ -1278,6 +1280,8 @@ proc default_gdb_exit {} { # # debug file was loaded successfully and has debug information # nodebug file was loaded successfully and has no debug information +# lzma file was loaded, .gnu_debugdata found, but no LZMA support +# compiled in # fail file was not loaded # # I tried returning this information as part of the return value, @@ -1325,6 +1329,11 @@ proc gdb_file_cmd { arg } { send_gdb "file $arg\n" gdb_expect 120 { + -re "Reading symbols from.*LZMA support was disabled.*done.*$gdb_prompt $" { + verbose "\t\tLoaded $arg into $GDB; .gnu_debugdata found but no LZMA available" + set gdb_file_cmd_debug_info "lzma" + return 0 + } -re "Reading symbols from.*no debugging symbols found.*done.*$gdb_prompt $" { verbose "\t\tLoaded $arg into $GDB with no debugging symbols" set gdb_file_cmd_debug_info "nodebug" -- 2.30.2