From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15127 invoked by alias); 25 Mar 2008 23:05:31 -0000 Received: (qmail 15112 invoked by uid 22791); 25 Mar 2008 23:05:28 -0000 X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.33.17) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 25 Mar 2008 23:04:54 +0000 Received: from zps38.corp.google.com (zps38.corp.google.com [172.25.146.38]) by smtp-out.google.com with ESMTP id m2PN4jgG022606 for ; Tue, 25 Mar 2008 23:04:46 GMT Received: from localhost (meta.corp.google.com [172.22.108.53]) by zps38.corp.google.com with ESMTP id m2PN4gLq008328; Tue, 25 Mar 2008 16:04:43 -0700 Received: by localhost (Postfix, from userid 500) id BF0623F25D6; Tue, 25 Mar 2008 16:04:40 -0700 (PDT) To: gdb-patches@sourceware.org Subject: Patch to handle compressed sections Message-Id: <20080325230440.BF0623F25D6@localhost> Date: Tue, 25 Mar 2008 23:05:00 -0000 From: csilvers@google.com (Craig Silverstein) Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-03/txt/msg00391.txt.bz2 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 < ' from the top-level gdb directory.) craig 2008-03-24 Craig Silverstein * 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 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 +#ifdef HAVE_ZLIB_H +#include +#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 . */ + +/* 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 . + +# 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 \\(\\)"