This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: RFA: handle "MiniDebuginfo" section
>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
Pedro> Are we going to call this "MiniDebugInfo" going forward (as the
Pedro> minidebug.c file spells it)? Would it be a good idea to put a
Pedro> "a.k.a. MiniDebugInfo" in the docs?
Yeah, good idea. I did this and I renamed the node to "MiniDebugInfo".
>> +if {[is_remote host]} {
>> + return 0
>> +}
Pedro> This is no longer necessary.
Whoops.
Here's the revised.
Tom
2012-11-12 Alexander Larsson <alexl@redhat.com>
Jan Kratochvil <jan.kratochvil@redhat.com>
Tom Tromey <tromey@redhat.com>
* 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-12 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (MiniDebugInfo): New node.
(GDB Files): Update.
2012-11-12 Jan Kratochvil <jan.kratochvil@redhat.com>
Tom Tromey <tromey@redhat.com>
* gdb.base/gnu-debugdata.exp: New file.
* gdb.base/gnu-debugdata.c: New file.
* lib/gdb.exp (gdb_file_cmd): Handle LZMA warning.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 9e7702d..864572c 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 739a7b3..03ce548 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -91,6 +91,11 @@ show print type typedefs
containing the absolute file name when GDB can determine it and source
has been requested.
+* 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 <http://sites.google.com/site/x32abi/>
diff --git a/gdb/config.in b/gdb/config.in
index 0f795c6..3db2d46 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -195,6 +195,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 68ee707..4cddd2f 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
@@ -12661,6 +12669,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 f0b7df3..c751c2d 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -2056,6 +2056,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/gdb.texinfo b/gdb/doc/gdb.texinfo
index 86cfe8e..224bdbf 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/minidebug.c b/gdb/minidebug.c
new file mode 100644
index 0000000..8e1362f
--- /dev/null
+++ b/gdb/minidebug.c
@@ -0,0 +1,284 @@
+/* Read MiniDebugInfo data from an objfile.
+
+ Copyright (C) 2012 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "gdb_bfd.h"
+#include "gdb_string.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdbcore.h"
+
+#ifdef HAVE_LIBLZMA
+
+#include <lzma.h>
+
+/* Allocator function for LZMA. */
+
+static void *
+alloc_lzma (void *opaque, size_t nmemb, size_t size)
+{
+ return xmalloc (nmemb * size);
+}
+
+/* Free function for LZMA. */
+
+static void
+free_lzma (void *opaque, void *ptr)
+{
+ xfree (ptr);
+}
+
+/* The allocator object for LZMA. Note that 'gdb_lzma_allocator'
+ cannot be const due to the lzma library function prototypes. */
+
+static lzma_allocator gdb_lzma_allocator = { alloc_lzma, free_lzma, NULL };
+
+/* Custom bfd_openr_iovec implementation to read compressed data from
+ a section. This keeps only the last decompressed block in memory
+ to allow larger data without using to much memory. */
+
+struct lzma_stream
+{
+ /* Section of input BFD from which we are decoding data. */
+ asection *section;
+
+ /* lzma library decompression state. */
+ lzma_index *index;
+
+ /* Currently decoded block. */
+ bfd_size_type data_start;
+ bfd_size_type data_end;
+ gdb_byte *data;
+};
+
+/* bfd_openr_iovec OPEN_P implementation for
+ find_separate_debug_file_in_section. OPEN_CLOSURE is 'asection *'
+ of the section to decompress.
+
+ Return 'struct lzma_stream *' must be freed by caller by xfree, together
+ with its INDEX lzma data. */
+
+static void *
+lzma_open (struct bfd *nbfd, void *open_closure)
+{
+ asection *section = open_closure;
+ bfd_size_type size, offset;
+ lzma_stream_flags options;
+ gdb_byte footer[LZMA_STREAM_HEADER_SIZE];
+ gdb_byte *indexdata;
+ lzma_index *index;
+ int ret;
+ uint64_t memlimit = UINT64_MAX;
+ struct lzma_stream *lstream;
+ size_t pos;
+
+ size = bfd_get_section_size (section);
+ offset = section->filepos + size - LZMA_STREAM_HEADER_SIZE;
+ if (size < LZMA_STREAM_HEADER_SIZE
+ || bfd_seek (section->owner, offset, SEEK_SET) != 0
+ || bfd_bread (footer, LZMA_STREAM_HEADER_SIZE, section->owner)
+ != LZMA_STREAM_HEADER_SIZE
+ || lzma_stream_footer_decode (&options, footer) != LZMA_OK
+ || offset < options.backward_size)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ offset -= options.backward_size;
+ indexdata = xmalloc (options.backward_size);
+ index = NULL;
+ pos = 0;
+ if (bfd_seek (section->owner, offset, SEEK_SET) != 0
+ || bfd_bread (indexdata, options.backward_size, section->owner)
+ != options.backward_size
+ || lzma_index_buffer_decode (&index, &memlimit, &gdb_lzma_allocator,
+ indexdata, &pos, options.backward_size)
+ != LZMA_OK
+ || lzma_index_size (index) != options.backward_size)
+ {
+ xfree (indexdata);
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+ xfree (indexdata);
+
+ lstream = xzalloc (sizeof (struct lzma_stream));
+ lstream->section = section;
+ lstream->index = index;
+
+ return lstream;
+}
+
+/* bfd_openr_iovec PREAD_P implementation for
+ find_separate_debug_file_in_section. Passed STREAM
+ is 'struct lzma_stream *'. */
+
+static file_ptr
+lzma_pread (struct bfd *nbfd, void *stream, void *buf, file_ptr nbytes,
+ file_ptr offset)
+{
+ struct lzma_stream *lstream = stream;
+ bfd_size_type chunk_size;
+ lzma_index_iter iter;
+ gdb_byte *compressed, *uncompressed;
+ file_ptr block_offset;
+ lzma_filter filters[LZMA_FILTERS_MAX + 1];
+ lzma_block block;
+ size_t compressed_pos, uncompressed_pos;
+ file_ptr res;
+
+ res = 0;
+ while (nbytes > 0)
+ {
+ if (lstream->data == NULL
+ || lstream->data_start > offset || offset >= lstream->data_end)
+ {
+ asection *section = lstream->section;
+
+ lzma_index_iter_init (&iter, lstream->index);
+ if (lzma_index_iter_locate (&iter, offset))
+ break;
+
+ compressed = xmalloc (iter.block.total_size);
+ block_offset = section->filepos + iter.block.compressed_file_offset;
+ if (bfd_seek (section->owner, block_offset, SEEK_SET) != 0
+ || bfd_bread (compressed, iter.block.total_size, section->owner)
+ != iter.block.total_size)
+ {
+ xfree (compressed);
+ break;
+ }
+
+ uncompressed = xmalloc (iter.block.uncompressed_size);
+
+ memset (&block, 0, sizeof (block));
+ block.filters = filters;
+ block.header_size = lzma_block_header_size_decode (compressed[0]);
+ if (lzma_block_header_decode (&block, &gdb_lzma_allocator, compressed)
+ != LZMA_OK)
+ {
+ xfree (compressed);
+ xfree (uncompressed);
+ break;
+ }
+
+ compressed_pos = block.header_size;
+ uncompressed_pos = 0;
+ if (lzma_block_buffer_decode (&block, &gdb_lzma_allocator,
+ compressed, &compressed_pos,
+ iter.block.total_size,
+ uncompressed, &uncompressed_pos,
+ iter.block.uncompressed_size)
+ != LZMA_OK)
+ {
+ xfree (compressed);
+ xfree (uncompressed);
+ break;
+ }
+
+ xfree (compressed);
+
+ xfree (lstream->data);
+ lstream->data = uncompressed;
+ lstream->data_start = iter.block.uncompressed_file_offset;
+ lstream->data_end = (iter.block.uncompressed_file_offset
+ + iter.block.uncompressed_size);
+ }
+
+ chunk_size = min (nbytes, lstream->data_end - offset);
+ memcpy (buf, lstream->data + offset - lstream->data_start, chunk_size);
+ buf = (gdb_byte *) buf + chunk_size;
+ offset += chunk_size;
+ nbytes -= chunk_size;
+ res += chunk_size;
+ }
+
+ return res;
+}
+
+/* bfd_openr_iovec CLOSE_P implementation for
+ find_separate_debug_file_in_section. Passed STREAM
+ is 'struct lzma_stream *'. */
+
+static int
+lzma_close (struct bfd *nbfd,
+ void *stream)
+{
+ struct lzma_stream *lstream = stream;
+
+ lzma_index_end (lstream->index, &gdb_lzma_allocator);
+ xfree (lstream->data);
+ xfree (lstream);
+ return 0;
+}
+
+/* bfd_openr_iovec STAT_P implementation for
+ find_separate_debug_file_in_section. Passed STREAM
+ is 'struct lzma_stream *'. */
+
+static int
+lzma_stat (struct bfd *abfd,
+ void *stream,
+ struct stat *sb)
+{
+ struct lzma_stream *lstream = stream;
+
+ sb->st_size = lzma_index_uncompressed_size (lstream->index);
+ return 0;
+}
+
+#endif /* HAVE_LIBLZMA */
+
+/* This looks for a xz compressed separate debug info object file embedded
+ in a section called .gnu_debugdata. See
+ http://fedoraproject.org/wiki/Features/MiniDebugInfo
+ or the "Separate Debug Sections" of the manual for details.
+ If we find one we create a iovec based bfd that decompresses the
+ object data on demand. If we don't find one, return NULL. */
+
+bfd *
+find_separate_debug_file_in_section (struct objfile *objfile)
+{
+ asection *section;
+ bfd *abfd;
+
+ section = bfd_get_section_by_name (objfile->obfd, ".gnu_debugdata");
+ if (section == NULL)
+ return NULL;
+
+#ifdef HAVE_LIBLZMA
+ abfd = gdb_bfd_openr_iovec (objfile->name, gnutarget, lzma_open, section,
+ lzma_pread, lzma_close, lzma_stat);
+ if (abfd == NULL)
+ return NULL;
+
+ if (!bfd_check_format (abfd, bfd_object))
+ {
+ gdb_bfd_unref (abfd);
+ return NULL;
+ }
+#else
+ warning (_("Cannot parse .gnu_debugdata section; LZMA support was "
+ "disabled at compile time"));
+ abfd = NULL;
+#endif /* !HAVE_LIBLZMA */
+
+ return abfd;
+}
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 55af541..6a2fc89 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 bb75c18..223f874 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/gdb.base/gnu-debugdata.c b/gdb/testsuite/gdb.base/gnu-debugdata.c
new file mode 100644
index 0000000..b8b7e8a
--- /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 <http://www.gnu.org/licenses/>. */
+
+#include <signal.h>
+
+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 0000000..eaf1ed1
--- /dev/null
+++ b/gdb/testsuite/gdb.base/gnu-debugdata.exp
@@ -0,0 +1,148 @@
+# 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 <http://www.gnu.org/licenses/>.
+
+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 -log "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 -log "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 -log "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_multiple "p debugdata_function" \
+ { = {<text variable, no debug info>} 0x[0-9a-f]+ <debugdata_function>} \
+ "have symtab"
+}
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 16e8b54..00d156d 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -1278,6 +1278,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 +1327,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"