Patch to handle compressed sections
Craig Silverstein
csilvers@google.com
Tue Mar 25 23:05:00 GMT 2008
This patch adds support for reading compressed debug sections, as are
produced by the new gold linker when it's run with
--compress-debug-sections=zlib.
(I had a bit of trouble creating the patch file from my VCS, so I hope
it applies cleanly. I got it to apply by running 'patch -p0 < <file>'
from the top-level gdb directory.)
craig
2008-03-24 Craig Silverstein <csilvers@google.com>
* configure.ac (AC_SEARCH_LIBS): Add check for zlib.
* config.in, configure: Regenerate.
* dwarf2read.c: Include zlib.h if present.
(uncompressed_section_size): New.
(section_is_p): New.
(dwarf2_locate_sections): Use section_is_p instead of strcmp
to determine whether a given section has a given name.
(dwarf2_read_section): Read the compressed section if present
in the binary.
--- gdb/config.in 2008-03-25 15:53:56.000000000 -0700
+++ gdb/config.in 2008-03-24 15:50:21.000000000 -0700
@@ -472,6 +472,9 @@
/* Define to 1 if you have the `XML_StopParser' function. */
#undef HAVE_XML_STOPPARSER
+/* Define to 1 if you have the <zlib.h> header file. */
+#undef HAVE_ZLIB_H
+
/* Define to 1 if your system has the _etext variable. */
#undef HAVE__ETEXT
--- gdb/configure 2008-03-25 15:53:56.000000000 -0700
+++ gdb/configure 2008-03-24 15:50:23.000000000 -0700
@@ -6003,6 +6003,283 @@
fi
+# Link in zlib if we can. This allows us to read compressed debug sections.
+echo "$as_me:$LINENO: checking for library containing zlibVersion" >&5
+echo $ECHO_N "checking for library containing zlibVersion... $ECHO_C" >&6
+if test "${ac_cv_search_zlibVersion+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+ac_cv_search_zlibVersion=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char zlibVersion ();
+int
+main ()
+{
+zlibVersion ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_zlibVersion="none required"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_zlibVersion" = no; then
+ for ac_lib in z; do
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char zlibVersion ();
+int
+main ()
+{
+zlibVersion ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_zlibVersion="-l$ac_lib"
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_zlibVersion" >&5
+echo "${ECHO_T}$ac_cv_search_zlibVersion" >&6
+if test "$ac_cv_search_zlibVersion" != no; then
+ test "$ac_cv_search_zlibVersion" = "none required" || LIBS="$ac_cv_search_zlibVersion $LIBS"
+
+for ac_header in zlib.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+fi
+
+
# For the TUI, we need enhanced curses functionality.
#
# FIXME: kettenis/20040905: We prefer ncurses over the vendor-supplied
--- gdb/configure.ac 2008-03-25 15:53:56.000000000 -0700
+++ gdb/configure.ac 2008-03-24 15:50:25.000000000 -0700
@@ -394,6 +394,9 @@
# Some systems (e.g. Solaris) have `socketpair' in libsocket.
AC_SEARCH_LIBS(socketpair, socket)
+# Link in zlib if we can. This allows us to read compressed debug sections.
+AC_SEARCH_LIBS(zlibVersion, z, [AC_CHECK_HEADERS(zlib.h)])
+
# For the TUI, we need enhanced curses functionality.
#
# FIXME: kettenis/20040905: We prefer ncurses over the vendor-supplied
--- gdb/dwarf2read.c 2008-03-25 15:53:56.000000000 -0700
+++ gdb/dwarf2read.c 2008-03-24 17:28:44.000000000 -0700
@@ -50,6 +50,9 @@
#include "gdb_string.h"
#include "gdb_assert.h"
#include <sys/types.h>
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
/* A note on memory usage for this file.
@@ -195,6 +198,10 @@
/* names of the debugging sections */
+/* Note that if the debugging section has been compressed, it might
+ have a name like .debug_info.zlib.nnnn (where nnn is the
+ uncompressed size). */
+
#define INFO_SECTION ".debug_info"
#define ABBREV_SECTION ".debug_abbrev"
#define LINE_SECTION ".debug_line"
@@ -1109,6 +1116,40 @@
return (dwarf_info_section != NULL && dwarf_abbrev_section != NULL);
}
+/* Given a section name like .debug_str.zlib.nnnn, where nnnn is the
+ uncompressed section size, returns nnnn as an unsigned int. For
+ other sections, returns the size as per bfd_get_section_size. */
+static unsigned int
+uncompressed_section_size (asection *sectp)
+{
+ unsigned int uncompressed_size = 0;
+ char *compression_type = strchr (sectp->name + 1, '.');
+ if (compression_type != NULL)
+ {
+ char *size_string = strchr (compression_type + 1, '.');
+ char *strtol_error;
+ if (size_string != NULL
+ && size_string[1] != '\0')
+ uncompressed_size = strtoul (size_string + 1, &strtol_error, 10);
+ if (uncompressed_size > 0 && *strtol_error == '\0')
+ return uncompressed_size;
+ }
+ return bfd_get_section_size (sectp);
+}
+
+/* When loading sections, we can either look for the section name,
+ * or for section_name.zlib.nnnn, which indicates a compressed
+ * section. nnnn is the uncompressed section size. */
+
+static int
+section_is_p(asection *sectp, const char *name)
+{
+ int name_size = strlen (name);
+ return (strcmp (sectp->name, name) == 0
+ || (strncmp (sectp->name, name, name_size) == 0
+ && sectp->name[name_size] == '.'));
+}
+
/* This function is mapped across the sections and remembers the
offset and size of each of the debugging sections we are interested
in. */
@@ -1116,63 +1157,63 @@
static void
dwarf2_locate_sections (bfd *abfd, asection *sectp, void *ignore_ptr)
{
- if (strcmp (sectp->name, INFO_SECTION) == 0)
+ if (section_is_p (sectp, INFO_SECTION))
{
- dwarf2_per_objfile->info_size = bfd_get_section_size (sectp);
+ dwarf2_per_objfile->info_size = uncompressed_section_size (sectp);
dwarf_info_section = sectp;
}
- else if (strcmp (sectp->name, ABBREV_SECTION) == 0)
+ else if (section_is_p (sectp, ABBREV_SECTION))
{
- dwarf2_per_objfile->abbrev_size = bfd_get_section_size (sectp);
+ dwarf2_per_objfile->abbrev_size = uncompressed_section_size (sectp);
dwarf_abbrev_section = sectp;
}
- else if (strcmp (sectp->name, LINE_SECTION) == 0)
+ else if (section_is_p (sectp, LINE_SECTION))
{
- dwarf2_per_objfile->line_size = bfd_get_section_size (sectp);
+ dwarf2_per_objfile->line_size = uncompressed_section_size (sectp);
dwarf_line_section = sectp;
}
- else if (strcmp (sectp->name, PUBNAMES_SECTION) == 0)
+ else if (section_is_p (sectp, PUBNAMES_SECTION))
{
- dwarf2_per_objfile->pubnames_size = bfd_get_section_size (sectp);
+ dwarf2_per_objfile->pubnames_size = uncompressed_section_size (sectp);
dwarf_pubnames_section = sectp;
}
- else if (strcmp (sectp->name, ARANGES_SECTION) == 0)
+ else if (section_is_p (sectp, ARANGES_SECTION))
{
- dwarf2_per_objfile->aranges_size = bfd_get_section_size (sectp);
+ dwarf2_per_objfile->aranges_size = uncompressed_section_size (sectp);
dwarf_aranges_section = sectp;
}
- else if (strcmp (sectp->name, LOC_SECTION) == 0)
+ else if (section_is_p (sectp, LOC_SECTION))
{
- dwarf2_per_objfile->loc_size = bfd_get_section_size (sectp);
+ dwarf2_per_objfile->loc_size = uncompressed_section_size (sectp);
dwarf_loc_section = sectp;
}
- else if (strcmp (sectp->name, MACINFO_SECTION) == 0)
+ else if (section_is_p (sectp, MACINFO_SECTION))
{
- dwarf2_per_objfile->macinfo_size = bfd_get_section_size (sectp);
+ dwarf2_per_objfile->macinfo_size = uncompressed_section_size (sectp);
dwarf_macinfo_section = sectp;
}
- else if (strcmp (sectp->name, STR_SECTION) == 0)
+ else if (section_is_p (sectp, STR_SECTION))
{
- dwarf2_per_objfile->str_size = bfd_get_section_size (sectp);
+ dwarf2_per_objfile->str_size = uncompressed_section_size (sectp);
dwarf_str_section = sectp;
}
- else if (strcmp (sectp->name, FRAME_SECTION) == 0)
+ else if (section_is_p (sectp, FRAME_SECTION))
{
- dwarf2_per_objfile->frame_size = bfd_get_section_size (sectp);
+ dwarf2_per_objfile->frame_size = uncompressed_section_size (sectp);
dwarf_frame_section = sectp;
}
- else if (strcmp (sectp->name, EH_FRAME_SECTION) == 0)
+ else if (section_is_p (sectp, EH_FRAME_SECTION))
{
flagword aflag = bfd_get_section_flags (ignore_abfd, sectp);
if (aflag & SEC_HAS_CONTENTS)
{
- dwarf2_per_objfile->eh_frame_size = bfd_get_section_size (sectp);
+ dwarf2_per_objfile->eh_frame_size = uncompressed_section_size (sectp);
dwarf_eh_frame_section = sectp;
}
}
- else if (strcmp (sectp->name, RANGES_SECTION) == 0)
+ else if (section_is_p (sectp, RANGES_SECTION))
{
- dwarf2_per_objfile->ranges_size = bfd_get_section_size (sectp);
+ dwarf2_per_objfile->ranges_size = uncompressed_section_size (sectp);
dwarf_ranges_section = sectp;
}
@@ -5234,29 +5275,113 @@
}
/* Read the contents of the section at OFFSET and of size SIZE from the
- object file specified by OBJFILE into the objfile_obstack and return it. */
+ object file specified by OBJFILE into the objfile_obstack and return it.
+ If the section is compressed, uncompress it before returning. */
gdb_byte *
dwarf2_read_section (struct objfile *objfile, asection *sectp)
{
bfd *abfd = objfile->obfd;
- gdb_byte *buf, *retbuf;
bfd_size_type size = bfd_get_section_size (sectp);
+ char *compression_type = NULL;
+ unsigned long uncompressed_size = 0;
if (size == 0)
return NULL;
- buf = obstack_alloc (&objfile->objfile_obstack, size);
- retbuf = symfile_relocate_debug_section (abfd, sectp, buf);
- if (retbuf != NULL)
- return retbuf;
+ /* If the section is stored compressed, it will have the name
+ .debug_*.zlib.nnnn, where nnnn is the uncompressed size. */
+ compression_type = strchr (sectp->name + 1, '.');
+ if (compression_type != NULL)
+ {
+ char *size_string = strchr (compression_type + 1, '.');
+ char *strtol_error;
+ if (size_string != NULL
+ && size_string[1] != '\0')
+ uncompressed_size = strtoul (size_string + 1, &strtol_error, 10);
+ if (uncompressed_size == 0 || *strtol_error != '\0')
+ error (_("Dwarf Error: Can't parse size at end of section name '%s'"
+ " in '%s'"),
+ sectp->name, bfd_get_filename (abfd));
+ }
+
+ /* Handle the case of a normal, not-compressed section. */
+ if (compression_type == NULL)
+ {
+ gdb_byte *buf = obstack_alloc (&objfile->objfile_obstack, size);
+ /* When debugging .o files, we may need to apply relocations; see
+ http://www.cygwin.com/ml/gdb-patches/2002-04/msg00136.html .
+ We never compress sections in .o files, so we only need to
+ try this when the section is not compressed. */
+ gdb_byte *retbuf = symfile_relocate_debug_section (abfd, sectp, buf);
+ if (retbuf != NULL)
+ return retbuf;
+
+ if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0
+ || bfd_bread (buf, size, abfd) != size)
+ error (_("Dwarf Error: Can't read DWARF data from '%s'"),
+ bfd_get_filename (abfd));
+
+ return buf;
+ }
+
+ /* Handle the case of a section compressed using zlib. */
+ if (strncmp (compression_type, ".zlib.", sizeof(".zlib.")-1) == 0)
+ {
+#ifndef HAVE_ZLIB_H
+ error (_("Dwarf Error: Can't uncompress zlib-compressed DWARF data "
+ "in '%s'"),
+ bfd_get_filename (abfd));
+#else
+ int rc;
+ gdb_byte *compressed_buffer = xmalloc (size);
+ Bytef *uncompressed_buffer = obstack_alloc (&objfile->objfile_obstack,
+ uncompressed_size);
+ z_stream strm;
+
+ if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0
+ || bfd_bread (compressed_buffer, size, abfd) != size)
+ error (_("Dwarf Error: Can't read DWARF data from '%s'"),
+ bfd_get_filename (abfd));
+
+ /* It is possible the section consists of several compressed
+ buffers concatenated together, so we uncompress in a loop. */
+ strm.zalloc = NULL;
+ strm.zfree = NULL;
+ strm.opaque = NULL;
+ strm.next_in = (Bytef*)compressed_buffer;
+ strm.avail_in = size;
+ strm.avail_out = uncompressed_size;
+ rc = inflateInit (&strm);
+ while (strm.avail_in > 0)
+ {
+ if (rc != Z_OK)
+ error (_("Dwarf Error: setting up DWARF uncompression in '%s': %d"),
+ bfd_get_filename (abfd), rc);
+ strm.next_out = (uncompressed_buffer
+ + (uncompressed_size - strm.avail_out));
+ rc = inflate (&strm, Z_FINISH);
+ if (rc != Z_STREAM_END)
+ error (_("Dwarf Error: zlib error uncompressing from '%s': %d"),
+ bfd_get_filename (abfd), rc);
+ rc = inflateReset (&strm);
+ }
+ rc = inflateEnd (&strm);
+ if (rc != Z_OK
+ || strm.avail_out != 0)
+ error (_("Dwarf Error: concluding DWARF uncompression in '%s': %d"),
+ bfd_get_filename (abfd), rc);
- if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0
- || bfd_bread (buf, size, abfd) != size)
- error (_("Dwarf Error: Can't read DWARF data from '%s'"),
- bfd_get_filename (abfd));
+ xfree (compressed_buffer);
+ return uncompressed_buffer;
+#endif
+ }
- return buf;
+ /* If we get here, we have an unknown compression type. */
+ error (_("Dwarf Error: Unknown compression type in section named '%s'"
+ " from '%s'"),
+ sectp->name, bfd_get_filename (abfd));
+ return NULL;
}
/* In DWARF version 2, the description of the debugging information is
--- /dev/null 1969-12-31 16:00:00.000000000 -0800
+++ gdb/testsuite/gdb.dwarf2/dw2-compressed.S 2008-03-24 15:50:39.000000000 -0700
@@ -0,0 +1,213 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2008 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/>. */
+
+/* This tests that gdb can read compressed sections. The contents
+ are the same as dw2-basic.S, but the .debug_abbrev section has been
+ comrpessed using zlib. */
+
+/* Dummy function to provide debug information for. */
+
+ .text
+ .globl _start
+_start:
+ .int 0
+.Lbegin_text1:
+ .globl func_cu1
+ .type func_cu1, %function
+func_cu1:
+.Lbegin_func_cu1:
+ .int 0
+.Lend_func_cu1:
+ .size func_cu1, .-func_cu1
+.Lend_text1:
+
+/* Debug information */
+
+ .section .debug_info
+.Lcu1_begin:
+ /* CU header */
+ .4byte .Lcu1_end - .Lcu1_start /* Length of Compilation Unit */
+.Lcu1_start:
+ .2byte 2 /* DWARF Version */
+ .4byte .Labbrev1_begin /* Offset into abbrev section */
+ .byte 4 /* Pointer size */
+
+ /* CU die */
+ .uleb128 1 /* Abbrev: DW_TAG_compile_unit */
+ .4byte .Lline1_begin /* DW_AT_stmt_list */
+ .4byte .Lend_text1 /* DW_AT_high_pc */
+ .4byte .Lbegin_text1 /* DW_AT_low_pc */
+ .ascii "file1.txt\0" /* DW_AT_name */
+ .ascii "GNU C 3.3.3\0" /* DW_AT_producer */
+ .byte 1 /* DW_AT_language (C) */
+
+ /* func_cu1 */
+ .uleb128 2 /* Abbrev: DW_TAG_subprogram */
+ .byte 1 /* DW_AT_external */
+ .byte 1 /* DW_AT_decl_file */
+ .byte 2 /* DW_AT_decl_line */
+ .ascii "func_cu1\0" /* DW_AT_name */
+ .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */
+ .4byte .Lbegin_func_cu1 /* DW_AT_low_pc */
+ .4byte .Lend_func_cu1 /* DW_AT_high_pc */
+ .byte 1 /* DW_AT_frame_base: length */
+ .byte 0x55 /* DW_AT_frame_base: DW_OP_reg5 */
+
+.Ltype_int:
+ .uleb128 3 /* Abbrev: DW_TAG_base_type */
+ .ascii "int\0" /* DW_AT_name */
+ .byte 4 /* DW_AT_byte_size */
+ .byte 5 /* DW_AT_encoding */
+
+ .byte 0 /* End of children of CU */
+
+.Lcu1_end:
+
+/* Line table */
+ .section .debug_line
+.Lline1_begin:
+ .4byte .Lline1_end - .Lline1_start /* Initial length */
+.Lline1_start:
+ .2byte 2 /* Version */
+ .4byte .Lline1_lines - .Lline1_hdr /* header_length */
+.Lline1_hdr:
+ .byte 1 /* Minimum insn length */
+ .byte 1 /* default_is_stmt */
+ .byte 1 /* line_base */
+ .byte 1 /* line_range */
+ .byte 0x10 /* opcode_base */
+
+ /* Standard lengths */
+ .byte 0
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte 0
+ .byte 0
+ .byte 0
+ .byte 1
+ .byte 0
+ .byte 0
+ .byte 1
+ .byte 0
+ .byte 0
+ .byte 0
+
+ /* Include directories */
+ .byte 0
+
+ /* File names */
+ .ascii "file1.txt\0"
+ .uleb128 0
+ .uleb128 0
+ .uleb128 0
+
+ .byte 0
+
+.Lline1_lines:
+ .byte 0 /* DW_LNE_set_address */
+ .uleb128 5
+ .byte 2
+ .4byte .Lbegin_func_cu1
+
+ .byte 3 /* DW_LNS_advance_line */
+ .sleb128 3 /* ... to 4 */
+
+ .byte 1 /* DW_LNS_copy */
+
+ .byte 1 /* DW_LNS_copy (second time as an end-of-prologue marker) */
+
+ .byte 0 /* DW_LNE_set_address */
+ .uleb128 5
+ .byte 2
+ .4byte .Lend_func_cu1
+
+ .byte 0 /* DW_LNE_end_of_sequence */
+ .uleb128 1
+ .byte 1
+
+.Lline1_end:
+
+/* Abbrev table -- compressed */
+ .section .debug_abbrev.zlib.51
+.Labbrev1_begin:
+ .byte 0x78
+ .byte 0x5e
+ .byte 0x63
+ .byte 0x14
+ .byte 0x64
+ .byte 0x14
+ .byte 0x60
+ .byte 0x13
+ .byte 0x62
+ .byte 0x14
+ .byte 0x64
+ .byte 0x64
+ .byte 0xe6
+ .byte 0x50
+ .byte 0xe5
+ .byte 0x10
+ .byte 0xe6
+ .byte 0x66
+ .byte 0x60
+ .byte 0x60
+ .byte 0xd2
+ .byte 0x63
+ .byte 0xb0
+ .byte 0xe7
+ .byte 0xb1
+ .byte 0xe2
+ .byte 0xb6
+ .byte 0xe6
+ .byte 0x66
+ .byte 0xe6
+ .byte 0xf0
+ .byte 0x14
+ .byte 0x16
+ .byte 0x64
+ .byte 0x14
+ .byte 0x62
+ .byte 0x74
+ .byte 0xe0
+ .byte 0x02
+ .byte 0x00
+ .byte 0x25
+ .byte 0x78
+ .byte 0x02
+ .byte 0x81
+ .byte 0x78
+ .byte 0x9c
+ .byte 0x63
+ .byte 0x60
+ .byte 0x60
+ .byte 0x56
+ .byte 0x61
+ .byte 0x60
+ .byte 0xe6
+ .byte 0xe0
+ .byte 0xe6
+ .byte 0xb6
+ .byte 0xe3
+ .byte 0x66
+ .byte 0x00
+ .byte 0x02
+ .byte 0x00
+ .byte 0x04
+ .byte 0x9c
+ .byte 0x00
+ .byte 0x92
--- /dev/null 1969-12-31 16:00:00.000000000 -0800
+++ gdb/testsuite/gdb.dwarf2/dw2-compressed.exp 2008-03-24 15:50:39.000000000 -0700
@@ -0,0 +1,52 @@
+# Copyright 2008 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/>.
+
+# Minimal DWARF-2 unit test
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+# For now pick a sampling of likely targets.
+if {![istarget *-*-linux*]
+ && ![istarget *-*-gnu*]
+ && ![istarget *-*-elf*]
+ && ![istarget *-*-openbsd*]
+ && ![istarget arm-*-eabi*]
+ && ![istarget powerpc-*-eabi*]} {
+ return 0
+}
+
+set testfile "dw2-compressed"
+set srcfile ${testfile}.S
+set binfile ${objdir}/${subdir}/${testfile}.x
+
+if { [gdb_compile "${srcdir}/${subdir}/main.c" "main-ndebug.o" object -g0] != "" } {
+ return -1
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${testfile}.o" object {nodebug}] != "" } {
+ return -1
+}
+
+if { [gdb_compile "${testfile}.o main-ndebug.o -static -nostdlib" "${binfile}" executable {debug}] != "" } {
+ return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "set listsize 1" ""
+gdb_test "list func_cu1" "4\[ \t\]+File 1 Line 4"
+gdb_test "ptype func_cu1" "type = int \\(\\)"
More information about the Gdb-patches
mailing list