libbacktrace: Add support for MiniDebugInfo

2020-09-14 Thread Ian Lance Taylor via Gcc-patches
This patch to libbacktrace adds support for MiniDebugInfo, as
requested in PR 93608.

MiniDebugInfo stores compressed symbol tables for an executable, where
the executable is otherwise stripped.  It is documented at
https://fedoraproject.org/wiki/Features/MiniDebugInfo and
https://sourceware.org/gdb/current/onlinedocs/gdb/MiniDebugInfo.html.

Unfortunately, although debug info processors are already required to
handle data compressed using zlib aka gzip in order to handle zdebug
and SHT_COMPRESSED, the MiniDebugInfo implementation choose to instead
compress the debug information with xz which uses LZMA2.  This in
effect forces all debug info processors to add a second decompression
algorithm.  Note to future developers: do not do this.

This libbacktrace implementation includes a new small LZMA
decompressor that just decompresses from one buffer to another.  It is
not heavily optimized, and on my laptop runs at about 78% of the speed
of using liblzma directly.  I think this is a decent tradeoff for
keeping the code reasonably small.

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian

PR libbacktrace/93608
Add support for MiniDebugInfo.
* elf.c (struct elf_view): Define.  Replace most uses of
backtrace_view with elf_view.
(elf_get_view): New static functions.  Replace most calls of
backtrace_get_view with elf_get_view.
(elf_release_view): New static functions.  Replace most calls of
backtrace_release_view with elf_release_view.
(elf_uncompress_failed): Rename from elf_zlib_failed.  Change all
callers.
(LZMA_STATES, LZMA_POS_STATES, LZMA_DIST_STATES): Define.
(LZMA_DIST_SLOTS, LZMA_DIST_MODEL_START): Define.
(LZMA_DIST_MODEL_END, LZMA_FULL_DISTANCES): Define.
(LZMA_ALIGN_SIZE, LZMA_LEN_LOW_SYMBOLS): Define.
(LZMA_LEN_MID_SYMBOLS, LZMA_LEN_HIGH_SYMBOLS): Define.
(LZMA_LITERAL_CODERS_MAX, LZMA_LITERAL_CODER_SIZE): Define.
(LZMA_PROB_IS_MATCH_LEN, LZMA_PROB_IS_REP_LEN): Define.
(LZMA_PROB_IS_REP0_LEN, LZMA_PROB_IS_REP1_LEN): Define.
(LZMA_PROB_IS_REP2_LEN, LZMA_PROB_IS_REP0_LONG_LEN): Define.
(LZMA_PROB_DIST_SLOT_LEN, LZMA_PROB_DIST_SPECIAL_LEN): Define.
(LZMA_PROB_DIST_ALIGN_LEN): Define.
(LZMA_PROB_MATCH_LEN_CHOICE_LEN): Define.
(LZMA_PROB_MATCH_LEN_CHOICE2_LEN): Define.
(LZMA_PROB_MATCH_LEN_LOW_LEN): Define.
(LZMA_PROB_MATCH_LEN_MID_LEN): Define.
(LZMA_PROB_MATCH_LEN_HIGH_LEN): Define.
(LZMA_PROB_REP_LEN_CHOICE_LEN): Define.
(LZMA_PROB_REP_LEN_CHOICE2_LEN): Define.
(LZMA_PROB_REP_LEN_LOW_LEN): Define.
(LZMA_PROB_REP_LEN_MID_LEN): Define.
(LZMA_PROB_REP_LEN_HIGH_LEN): Define.
(LZMA_PROB_LITERAL_LEN): Define.
(LZMA_PROB_IS_MATCH_OFFSET, LZMA_PROB_IS_REP_OFFSET): Define.
(LZMA_PROB_IS_REP0_OFFSET, LZMA_PROB_IS_REP1_OFFSET): Define.
(LZMA_PROB_IS_REP2_OFFSET): Define.
(LZMA_PROB_IS_REP0_LONG_OFFSET): Define.
(LZMA_PROB_DIST_SLOT_OFFSET): Define.
(LZMA_PROB_DIST_SPECIAL_OFFSET): Define.
(LZMA_PROB_DIST_ALIGN_OFFSET): Define.
(LZMA_PROB_MATCH_LEN_CHOICE_OFFSET): Define.
(LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET): Define.
(LZMA_PROB_MATCH_LEN_LOW_OFFSET): Define.
(LZMA_PROB_MATCH_LEN_MID_OFFSET): Define.
(LZMA_PROB_MATCH_LEN_HIGH_OFFSET): Define.
(LZMA_PROB_REP_LEN_CHOICE_OFFSET): Define.
(LZMA_PROB_REP_LEN_CHOICE2_OFFSET): Define.
(LZMA_PROB_REP_LEN_LOW_OFFSET): Define.
(LZMA_PROB_REP_LEN_MID_OFFSET): Define.
(LZMA_PROB_REP_LEN_HIGH_OFFSET): Define.
(LZMA_PROB_LITERAL_OFFSET): Define.
(LZMA_PROB_TOTAL_COUNT): Define.
(LZMA_IS_MATCH, LZMA_IS_REP, LZMA_IS_REP0): Define.
(LZMA_IS_REP1, LZMA_IS_REP2, LZMA_IS_REP0_LONG): Define.
(LZMA_DIST_SLOT, LZMA_DIST_SPECIAL, LZMA_DIST_ALIGN): Define.
(LZMA_MATCH_LEN_CHOICE, LZMA_MATCH_LEN_CHOICE2): Define.
(LZMA_MATCH_LEN_LOW, LZMA_MATCH_LEN_MID): Define.
(LZMA_MATCH_LEN_HIGH, LZMA_REP_LEN_CHOICE): Define.
(LZMA_REP_LEN_CHOICE2, LZMA_REP_LEN_LOW): Define.
(LZMA_REP_LEN_MID, LZMA_REP_LEN_HIGH, LZMA_LITERAL): Define.
(elf_lzma_varint): New static function.
(elf_lzma_range_normalize): New static function.
(elf_lzma_bit, elf_lzma_integer): New static functions.
(elf_lzma_reverse_integer): New static function.
(elf_lzma_len, elf_uncompress_lzma_block): New static functions.
(elf_uncompress_lzma): New static function.
(backtrace_uncompress_lzma): New function.
(elf_add): Add memory and memory_size parameters.  Change all
callers.  Look for .gnu_debugdata section, and, if found,
decompress it and use it for symbols and debug info.  Permit the
descriptor parameter to be -1.
* internal.h (backtrace_uncompress_lzma): Declare.
* mtest.c: New file.
* xztest.c: New file.
* configure.ac: Check for nm, xz, and comm programs.  Check for
liblzma library.
(HAVE_MINIDEBUG): Define.
* Makefile.am (mtest_SOURCES): Define.
(mtest_CFLAGS, mtest_LDADD): Define.
(TESTS): Add mtest_minidebug if HAVE_MINIDEBUG.
(%_minidebug): New pattern rule, if HAVE_MINIDEBUG.
(xztest_SOURCES, xztest_CFLAGS, xztest_LDADD): Define.
(xztest_alloc_SOURCES, xztest_alloc_CFLAGS): Define
(xztest_alloc_LDADD): Define.
(BUILDTESTS): Add mtest, xztest, xztest_alloc.
(CLEANFILES): Add files created b

Re: libbacktrace: Add support for MiniDebugInfo

2020-09-16 Thread Alex Coplan
Hi Ian,

On 14/09/2020 14:12, Ian Lance Taylor via Gcc-patches wrote:
> This patch to libbacktrace adds support for MiniDebugInfo, as
> requested in PR 93608.

This appears to introduce a failure in the libbacktrace testsuite
(observed on both x86 and aarch64):

../gcc/libbacktrace/../test-driver: line 107:  7905 Segmentation fault  
(core dumped) "$@" > $log_file 2>&1
FAIL: mtest_minidebug

> 
> MiniDebugInfo stores compressed symbol tables for an executable, where
> the executable is otherwise stripped.  It is documented at
> https://fedoraproject.org/wiki/Features/MiniDebugInfo and
> https://sourceware.org/gdb/current/onlinedocs/gdb/MiniDebugInfo.html.
> 
> Unfortunately, although debug info processors are already required to
> handle data compressed using zlib aka gzip in order to handle zdebug
> and SHT_COMPRESSED, the MiniDebugInfo implementation choose to instead
> compress the debug information with xz which uses LZMA2.  This in
> effect forces all debug info processors to add a second decompression
> algorithm.  Note to future developers: do not do this.
> 
> This libbacktrace implementation includes a new small LZMA
> decompressor that just decompresses from one buffer to another.  It is
> not heavily optimized, and on my laptop runs at about 78% of the speed
> of using liblzma directly.  I think this is a decent tradeoff for
> keeping the code reasonably small.
> 
> Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
> to mainline.
> 
> Ian

Thanks,
Alex


Re: libbacktrace: Add support for MiniDebugInfo

2020-09-16 Thread Ian Lance Taylor via Gcc-patches
On Wed, Sep 16, 2020, 4:03 AM Alex Coplan  wrote:

> Hi Ian,
>
> On 14/09/2020 14:12, Ian Lance Taylor via Gcc-patches wrote:
> > This patch to libbacktrace adds support for MiniDebugInfo, as
> > requested in PR 93608.
>
> This appears to introduce a failure in the libbacktrace testsuite
> (observed on both x86 and aarch64):
>
> ../gcc/libbacktrace/../test-driver: line 107:  7905 Segmentation fault
>   (core dumped) "$@" > $log_file 2>&1
> FAIL: mtest_minidebug



I tested on x86 without seeing anything like this.  Can you give me any
more details?  Thanks.

Ian




> > MiniDebugInfo stores compressed symbol tables for an executable, where
> > the executable is otherwise stripped.  It is documented at
> > https://fedoraproject.org/wiki/Features/MiniDebugInfo and
> > https://sourceware.org/gdb/current/onlinedocs/gdb/MiniDebugInfo.html.
> >
> > Unfortunately, although debug info processors are already required to
> > handle data compressed using zlib aka gzip in order to handle zdebug
> > and SHT_COMPRESSED, the MiniDebugInfo implementation choose to instead
> > compress the debug information with xz which uses LZMA2.  This in
> > effect forces all debug info processors to add a second decompression
> > algorithm.  Note to future developers: do not do this.
> >
> > This libbacktrace implementation includes a new small LZMA
> > decompressor that just decompresses from one buffer to another.  It is
> > not heavily optimized, and on my laptop runs at about 78% of the speed
> > of using liblzma directly.  I think this is a decent tradeoff for
> > keeping the code reasonably small.
> >
> > Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
> > to mainline.
> >
> > Ian
>
> Thanks,
> Alex
>


Re: libbacktrace: Add support for MiniDebugInfo

2020-09-16 Thread Alex Coplan
On 16/09/2020 07:26, Ian Lance Taylor wrote:
> On Wed, Sep 16, 2020, 4:03 AM Alex Coplan  wrote:
> 
> > Hi Ian,
> >
> > On 14/09/2020 14:12, Ian Lance Taylor via Gcc-patches wrote:
> > > This patch to libbacktrace adds support for MiniDebugInfo, as
> > > requested in PR 93608.
> >
> > This appears to introduce a failure in the libbacktrace testsuite
> > (observed on both x86 and aarch64):
> >
> > ../gcc/libbacktrace/../test-driver: line 107:  7905 Segmentation fault
> >   (core dumped) "$@" > $log_file 2>&1
> > FAIL: mtest_minidebug
> 
> 
> 
> I tested on x86 without seeing anything like this.  Can you give me any
> more details?  Thanks.

Sure. On an Ubuntu 18.04 / x86-64 system with current trunk, configuring
with:

~/toolchain/src/gcc/configure \
  --prefix=`pwd` \
  --enable-languages=c,c++ \
  --disable-multilib \
  --disable-bootstrap

running `make && make check-libbacktrace` gives the failure described
above. Here is the contents of libbacktrace/test-suite.log:

=
package-unused version-unused: ./test-suite.log
=

# TOTAL: 33
# PASS:  32
# SKIP:  0
# XFAIL: 0
# FAIL:  1
# XPASS: 0
# ERROR: 0

.. contents:: :depth: 2

FAIL: mtest_minidebug
=

no debug info in ELF executable
no debug info in ELF executable
no debug info in ELF executable
no debug info in ELF executable
no debug info in ELF executable
no debug info in ELF executable
no debug info in ELF executable
test1: not enough frames; got 0, expected at least 3
test1: [0]: got  expected f3
test1: [1]: got  expected f2
FAIL mtest_minidebug (exit status: 139)

---

Let me know if you need any more info.

Thanks,
Alex


Re: libbacktrace: Add support for MiniDebugInfo

2020-09-16 Thread Ian Lance Taylor via Gcc-patches
On Wed, Sep 16, 2020 at 8:54 AM Alex Coplan  wrote:
>
> On 16/09/2020 07:26, Ian Lance Taylor wrote:
> > On Wed, Sep 16, 2020, 4:03 AM Alex Coplan  wrote:
> >
> > > Hi Ian,
> > >
> > > On 14/09/2020 14:12, Ian Lance Taylor via Gcc-patches wrote:
> > > > This patch to libbacktrace adds support for MiniDebugInfo, as
> > > > requested in PR 93608.
> > >
> > > This appears to introduce a failure in the libbacktrace testsuite
> > > (observed on both x86 and aarch64):
> > >
> > > ../gcc/libbacktrace/../test-driver: line 107:  7905 Segmentation fault
> > >   (core dumped) "$@" > $log_file 2>&1
> > > FAIL: mtest_minidebug
> >
> >
> >
> > I tested on x86 without seeing anything like this.  Can you give me any
> > more details?  Thanks.
>
> Sure. On an Ubuntu 18.04 / x86-64 system with current trunk, configuring
> with:
>
> ~/toolchain/src/gcc/configure \
>   --prefix=`pwd` \
>   --enable-languages=c,c++ \
>   --disable-multilib \
>   --disable-bootstrap
>
> running `make && make check-libbacktrace` gives the failure described
> above. Here is the contents of libbacktrace/test-suite.log:
>
> =
> package-unused version-unused: ./test-suite.log
> =
>
> # TOTAL: 33
> # PASS:  32
> # SKIP:  0
> # XFAIL: 0
> # FAIL:  1
> # XPASS: 0
> # ERROR: 0
>
> .. contents:: :depth: 2
>
> FAIL: mtest_minidebug
> =
>
> no debug info in ELF executable
> no debug info in ELF executable
> no debug info in ELF executable
> no debug info in ELF executable
> no debug info in ELF executable
> no debug info in ELF executable
> no debug info in ELF executable
> test1: not enough frames; got 0, expected at least 3
> test1: [0]: got  expected f3
> test1: [1]: got  expected f2
> FAIL mtest_minidebug (exit status: 139)
>
> ---
>
> Let me know if you need any more info.


Thanks.  I think the problem arises when libbacktrace is unable to
find debug info for any shared library involved in the link.

This patch should fix it.  Bootstrapped and ran libbacktrace tests on
x86_64-pc-linux-gnu and aarch64-linux-gnu.  Committed to mainline.

Ian

PR libbacktrace/97080
* fileline.c (backtrace_syminfo_to_full_callback): New function.
(backtrace_syminfo_to_full_error_callback): New function.
* elf.c (elf_nodebug): Call syminfo_fn if possible.
* internal.h (struct backtrace_call_full): Define.
(backtrace_syminfo_to_full_callback): Declare.
(backtrace_syminfo_to_full_error_callback): Declare.
* mtest.c (f3): Only check all[i] if data.index permits.
diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c
index dd004708246..941f820d944 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -547,18 +547,6 @@ elf_crc32_file (struct backtrace_state *state, int 
descriptor,
   return ret;
 }
 
-/* A dummy callback function used when we can't find any debug info.  */
-
-static int
-elf_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
-uintptr_t pc ATTRIBUTE_UNUSED,
-backtrace_full_callback callback ATTRIBUTE_UNUSED,
-backtrace_error_callback error_callback, void *data)
-{
-  error_callback (data, "no debug info in ELF executable", -1);
-  return 0;
-}
-
 /* A dummy callback function used when we can't find a symbol
table.  */
 
@@ -571,6 +559,33 @@ elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
   error_callback (data, "no symbol table in ELF executable", -1);
 }
 
+/* A callback function used when we can't find any debug info.  */
+
+static int
+elf_nodebug (struct backtrace_state *state, uintptr_t pc,
+backtrace_full_callback callback,
+backtrace_error_callback error_callback, void *data)
+{
+  if (state->syminfo_fn != NULL && state->syminfo_fn != elf_nosyms)
+{
+  struct backtrace_call_full bdata;
+
+  /* Fetch symbol information so that we can least get the
+function name.  */
+
+  bdata.full_callback = callback;
+  bdata.full_error_callback = error_callback;
+  bdata.full_data = data;
+  bdata.ret = 0;
+  state->syminfo_fn (state, pc, backtrace_syminfo_to_full_callback,
+backtrace_syminfo_to_full_error_callback, &bdata);
+  return bdata.ret;
+}
+
+  error_callback (data, "no debug info in ELF executable", -1);
+  return 0;
+}
+
 /* Compare struct elf_symbol for qsort.  */
 
 static int
diff --git a/libbacktrace/fileline.c b/libbacktrace/fileline.c
index be62b9899c5..cd1e10dd58c 100644
--- a/libbacktrace/fileline.c
+++ b/libbacktrace/fileline.c
@@ -317,3 +317,30 @@ backtrace_syminfo (struct backtrace_state *state, 
uintptr_t pc,
   state->syminfo_fn (state, pc, callback, error_callback, data);
   return 1;
 }
+
+/* A backtrace_syminfo_callback that can call into a
+   backtrace_full_callback, used when we have a symbol table but no
+   debug info.  */
+
+void
+backtrace_syminfo_to_full_callback (void *data, uintptr_t pc,
+   const char *symname,
+