From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10543 invoked by alias); 12 Nov 2012 16:28:03 -0000 Received: (qmail 10524 invoked by uid 22791); 12 Nov 2012 16:28:00 -0000 X-SWARE-Spam-Status: No, hits=-3.8 required=5.0 tests=AWL,BAYES_00,KAM_STOCKTIP,KHOP_RCVD_UNTRUST,RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,SPF_HELO_PASS,TW_BJ,TW_BL,TW_CP,TW_XZ X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 12 Nov 2012 16:27:50 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id qACGRo9Z027231 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 12 Nov 2012 11:27:50 -0500 Received: from barimba (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id qACG04Kq022294 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Mon, 12 Nov 2012 11:00:08 -0500 From: Tom Tromey To: gdb-patches@sourceware.org Subject: Re: RFA: handle "MiniDebuginfo" section References: <87wqxuel5k.fsf@fleche.redhat.com> Date: Mon, 12 Nov 2012 16:28:00 -0000 In-Reply-To: <87wqxuel5k.fsf@fleche.redhat.com> (Tom Tromey's message of "Fri, 09 Nov 2012 10:33:27 -0700") Message-ID: <87zk2mbym3.fsf@fleche.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain 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: 2012-11/txt/msg00289.txt.bz2 >>>>> "Tom" == Tom Tromey writes: Tom> Fedora recently approved and committed the "MiniDebuginfo" feature: Tom> http://fedoraproject.org/wiki/Features/MiniDebugInfo Here is a new version of the patch. I think I've addressed all the review comments. The new LZMA-using code is now in a new file. I made the new code not be ELF-specific; instead it is a general fallback implemented in symfile.c. I added a warning in the case where the new section is available and would be used, but can't be since LZMA wasn't compiled in. I renamed the test file since I think it isn't DWARF-specific. Tom 2012-11-12 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-12 Tom Tromey * gdb.texinfo (Separate Debug Section): New node. (GDB Files): Update. 2012-11-12 Jan Kratochvil * gdb.base/gnu-debugdata.exp: New file. * gdb.base/gnu-debugdata.c: New file. 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 4a1988d..0c84008 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -70,6 +70,11 @@ py [command] 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 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 ce5415d..9d03aad 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -15787,6 +15787,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 +* Separate Debug Section:: Debugging information in a special section * Index Files:: Index files speed up GDB * Symbol Errors:: Errors reading symbol files * Data Files:: GDB data files @@ -16712,6 +16713,44 @@ gnu_debuglink_crc32 (unsigned long crc, @noindent This computation does not apply to the ``build ID'' method. +@node Separate Debug Section +@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 section holds an +LZMA-compressed object and is used to supply extra symbols for +backtraces. @value{GDBN} has support for this extension. + +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 . */ + +#include "defs.h" +#include "gdb_bfd.h" +#include "gdb_string.h" +#include "symfile.h" +#include "objfiles.h" +#include "gdbcore.h" + +#ifdef HAVE_LIBLZMA + +#include + +/* 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 . */ + +#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 0000000..2b304f1 --- /dev/null +++ b/gdb/testsuite/gdb.base/gnu-debugdata.exp @@ -0,0 +1,97 @@ +# 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 {[is_remote host]} { + return 0 +} + +if [build_executable ${testfile}.exp $testfile] { + return -1 +} + +proc run { test cmdline } { + verbose "cmdline is $cmdline" + set result [catch "exec $cmdline" output] + verbose "result is $result" + verbose "output is $output" + if {$result == 0} { + pass $test + return 0 + } else { + fail $test + return -1 + } +} + +set strip_program [transform strip] +set nm_program [transform nm] + +# Extract the dynamic symbols from the main binary, there is no need +# to also have these in the normal symbol table. +file delete -- ${binfile}.dynsyms +if [run "nm -D" "[transform nm] -D ${binfile} --format=posix --defined-only | awk \\{print\\ \\\$1\\} | sort > ${binfile}.dynsyms"] { + return -1 +} + +# Extract all the text (i.e. function) symbols from the debuginfo. +file delete -- ${binfile}.funcsyms +if [run "nm" "[transform nm] ${binfile} --format=posix --defined-only | awk \\{if(\\\$2==\"T\"||\\\$2==\"t\")print\\ \\\$1\\} | sort > ${binfile}.funcsyms"] { + return -1 +} + +# Keep all the function symbols not already in the dynamic symbol +# table. +file 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. +file 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. +file 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. +file delete -- ${binfile}.mini_debuginfo.xz +if [run "xz" "xz ${binfile}.mini_debuginfo"] { + return -1 +} +file 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" + +gdb_test "p debugdata_function" \ + { = {} 0x[0-9a-f]+ } \ + "have symtab"