Merge pull request #207611 from jtojnar/libbacktrace

libbacktrace: Add support for NIX_DEBUG_INFO_DIRS
This commit is contained in:
Jan Tojnar 2023-03-23 16:35:09 +01:00 committed by GitHub
commit a6d96cce27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 493 additions and 11 deletions

View file

@ -0,0 +1,201 @@
From 1cf6b108882669f1b20c18fb5f2d6dff0fc83296 Mon Sep 17 00:00:00 2001
From: Jan Tojnar <jtojnar@gmail.com>
Date: Sat, 24 Dec 2022 15:31:51 +0100
Subject: [PATCH 1/4] libbacktrace: avoid libtool wrapping tests
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When `--enable-shared` is used, libtool will produce shell scripts
instead of programs, preventing separate debug info from being generated:
objcopy --only-keep-debug btest btest_gnudebuglink.debug
objcopy: btest: file format not recognized
make[2]: *** [Makefile:2615: btest_gnudebuglink] Error 1
Lets make it properly set rpath with `-no-install` flag,
so that wrappers are not needed, as mentioned on
https://autotools.info/libtool/wrappers.html
---
Makefile.am | 28 +++++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index c53cbae..6eab991 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -107,6 +107,8 @@ check_DATA =
# Flags to use when compiling test programs.
libbacktrace_TEST_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) -g
+libbacktrace_TEST_LDFLAGS = -no-install
+
if USE_DSYMUTIL
%.dSYM: %
@@ -171,48 +173,56 @@ xcoff_%.c: xcoff.c
test_elf_32_SOURCES = test_format.c testlib.c
test_elf_32_CFLAGS = $(libbacktrace_TEST_CFLAGS)
+test_elf_32_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
test_elf_32_LDADD = libbacktrace_noformat.la elf_32.lo
BUILDTESTS += test_elf_32
test_elf_64_SOURCES = test_format.c testlib.c
test_elf_64_CFLAGS = $(libbacktrace_TEST_CFLAGS)
+test_elf_64_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
test_elf_64_LDADD = libbacktrace_noformat.la elf_64.lo
BUILDTESTS += test_elf_64
test_macho_SOURCES = test_format.c testlib.c
test_macho_CFLAGS = $(libbacktrace_TEST_CFLAGS)
+test_macho_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
test_macho_LDADD = libbacktrace_noformat.la macho.lo
BUILDTESTS += test_macho
test_xcoff_32_SOURCES = test_format.c testlib.c
test_xcoff_32_CFLAGS = $(libbacktrace_TEST_CFLAGS)
+test_xcoff_32_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
test_xcoff_32_LDADD = libbacktrace_noformat.la xcoff_32.lo
BUILDTESTS += test_xcoff_32
test_xcoff_64_SOURCES = test_format.c testlib.c
test_xcoff_64_CFLAGS = $(libbacktrace_TEST_CFLAGS)
+test_xcoff_64_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
test_xcoff_64_LDADD = libbacktrace_noformat.la xcoff_64.lo
BUILDTESTS += test_xcoff_64
test_pecoff_SOURCES = test_format.c testlib.c
test_pecoff_CFLAGS = $(libbacktrace_TEST_CFLAGS)
+test_pecoff_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
test_pecoff_LDADD = libbacktrace_noformat.la pecoff.lo
BUILDTESTS += test_pecoff
test_unknown_SOURCES = test_format.c testlib.c
test_unknown_CFLAGS = $(libbacktrace_TEST_CFLAGS)
+test_unknown_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
test_unknown_LDADD = libbacktrace_noformat.la unknown.lo
BUILDTESTS += test_unknown
unittest_SOURCES = unittest.c testlib.c
unittest_CFLAGS = $(libbacktrace_TEST_CFLAGS)
+unittest_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
unittest_LDADD = libbacktrace.la
BUILDTESTS += unittest
@@ -253,7 +263,7 @@ if HAVE_OBJCOPY_DEBUGLINK
b2test_SOURCES = $(btest_SOURCES)
b2test_CFLAGS = $(libbacktrace_TEST_CFLAGS)
-b2test_LDFLAGS = -Wl,--build-id
+b2test_LDFLAGS = -Wl,--build-id $(libbacktrace_TEST_LDFLAGS)
b2test_LDADD = libbacktrace_elf_for_test.la
check_PROGRAMS += b2test
@@ -263,7 +273,7 @@ if HAVE_DWZ
b3test_SOURCES = $(btest_SOURCES)
b3test_CFLAGS = $(libbacktrace_TEST_CFLAGS)
-b3test_LDFLAGS = -Wl,--build-id
+b3test_LDFLAGS = -Wl,--build-id $(libbacktrace_TEST_LDFLAGS)
b3test_LDADD = libbacktrace_elf_for_test.la
check_PROGRAMS += b3test
@@ -276,6 +286,7 @@ endif HAVE_ELF
btest_SOURCES = btest.c testlib.c
btest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -O
+btest_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
btest_LDADD = libbacktrace.la
BUILDTESTS += btest
@@ -330,6 +341,7 @@ endif HAVE_DWZ
stest_SOURCES = stest.c
stest_CFLAGS = $(libbacktrace_TEST_CFLAGS)
+stest_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
stest_LDADD = libbacktrace.la
BUILDTESTS += stest
@@ -352,6 +364,7 @@ if HAVE_ELF
ztest_SOURCES = ztest.c testlib.c
ztest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -DSRCDIR=\"$(srcdir)\"
+ztest_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
ztest_LDADD = libbacktrace.la
ztest_alloc_LDADD = libbacktrace_alloc.la
@@ -371,6 +384,7 @@ BUILDTESTS += ztest_alloc
zstdtest_SOURCES = zstdtest.c testlib.c
zstdtest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -DSRCDIR=\"$(srcdir)\"
+zstdtest_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
zstdtest_LDADD = libbacktrace.la
zstdtest_alloc_LDADD = libbacktrace_alloc.la
@@ -392,6 +406,7 @@ endif HAVE_ELF
edtest_SOURCES = edtest.c edtest2_build.c testlib.c
edtest_CFLAGS = $(libbacktrace_TEST_CFLAGS)
+edtest_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
edtest_LDADD = libbacktrace.la
BUILDTESTS += edtest
@@ -422,6 +437,7 @@ BUILDTESTS += ttest
ttest_SOURCES = ttest.c testlib.c
ttest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -pthread
+ttest_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
ttest_LDADD = libbacktrace.la
if USE_DSYMUTIL
@@ -460,12 +476,12 @@ if HAVE_COMPRESSED_DEBUG
ctestg_SOURCES = btest.c testlib.c
ctestg_CFLAGS = $(libbacktrace_TEST_CFLAGS)
-ctestg_LDFLAGS = -Wl,--compress-debug-sections=zlib-gnu
+ctestg_LDFLAGS = -Wl,--compress-debug-sections=zlib-gnu $(libbacktrace_TEST_LDFLAGS)
ctestg_LDADD = libbacktrace.la
ctesta_SOURCES = btest.c testlib.c
ctesta_CFLAGS = $(libbacktrace_TEST_CFLAGS)
-ctesta_LDFLAGS = -Wl,--compress-debug-sections=zlib-gabi
+ctesta_LDFLAGS = -Wl,--compress-debug-sections=zlib-gabi $(libbacktrace_TEST_LDFLAGS)
ctesta_LDADD = libbacktrace.la
BUILDTESTS += ctestg ctesta
@@ -474,7 +490,7 @@ if HAVE_COMPRESSED_DEBUG_ZSTD
ctestzstd_SOURCES = btest.c testlib.c
ctestzstd_CFLAGS = $(libbacktrace_TEST_CFLAGS)
-ctestzstd_LDFLAGS = -Wl,--compress-debug-sections=zstd
+ctestzstd_LDFLAGS = -Wl,--compress-debug-sections=zstd $(libbacktrace_TEST_LDFLAGS)
ctestzstd_LDADD = libbacktrace.la
BUILDTESTS += ctestzstd
@@ -521,6 +537,7 @@ endif
mtest_SOURCES = mtest.c testlib.c
mtest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -O
+mtest_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
mtest_LDADD = libbacktrace.la
BUILDTESTS += mtest
@@ -553,6 +570,7 @@ if HAVE_ELF
xztest_SOURCES = xztest.c testlib.c
xztest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -DSRCDIR=\"$(srcdir)\"
+xztest_LDFLAGS = $(libbacktrace_TEST_LDFLAGS)
xztest_LDADD = libbacktrace.la
xztest_alloc_SOURCES = $(xztest_SOURCES)
--
2.38.1

View file

@ -0,0 +1,108 @@
From f409ee343fe6cdc059bb411746f27a515aec66a8 Mon Sep 17 00:00:00 2001
From: Jan Tojnar <jtojnar@gmail.com>
Date: Sat, 24 Dec 2022 16:46:18 +0100
Subject: [PATCH 2/4] libbacktrace: Allow configuring debug dir
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
On platforms that do not use FHS like NixOS or GNU Guix,
the build-id directories are not under `/usr/lib/debug`.
Lets add `--with-separate-debug-dir` configure flag so that
the path can be changed. The same flag is supported by gdb:
https://github.com/bminor/binutils-gdb/blob/095f84c7e3cf85cd68c657c46b80be078f336bc9/gdb/configure.ac#L113-L115
---
Makefile.am | 11 ++++++-----
configure.ac | 8 ++++++++
elf.c | 4 ++--
3 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 6eab991..da443c1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -33,7 +33,8 @@ ACLOCAL_AMFLAGS = -I config
AM_CPPFLAGS =
-AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)
+AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG) \
+ -DSYSTEM_DEBUG_DIR=\"$(SEPARATE_DEBUG_DIR)\"
include_HEADERS = backtrace.h backtrace-supported.h
@@ -134,7 +135,7 @@ libbacktrace_noformat_la_DEPENDENCIES = $(libbacktrace_noformat_la_LIBADD)
if HAVE_ELF
if HAVE_OBJCOPY_DEBUGLINK
-TEST_BUILD_ID_DIR=$(abs_builddir)/usr/lib/debug/.build-id/
+TEST_DEBUG_DIR=$(abs_builddir)/usr/lib/debug
check_LTLIBRARIES += libbacktrace_elf_for_test.la
@@ -143,8 +144,8 @@ libbacktrace_elf_for_test_la_LIBADD = $(BACKTRACE_FILE) elf_for_test.lo \
$(VIEW_FILE) $(ALLOC_FILE)
elf_for_test.c: elf.c
- SEARCH='^#define SYSTEM_BUILD_ID_DIR.*$$'; \
- REPLACE="#define SYSTEM_BUILD_ID_DIR \"$(TEST_BUILD_ID_DIR)\""; \
+ SEARCH='^#define BUILD_ID_DIR.*$$'; \
+ REPLACE='\0\n#undef SYSTEM_DEBUG_DIR\n#define SYSTEM_DEBUG_DIR "$(TEST_DEBUG_DIR)"'; \
$(SED) "s%$$SEARCH%$$REPLACE%" \
$< \
> $@.tmp
@@ -468,7 +469,7 @@ endif HAVE_OBJCOPY_DEBUGLINK
%_buildid: %
./install-debuginfo-for-buildid.sh \
- "$(TEST_BUILD_ID_DIR)" \
+ "$(TEST_DEBUG_DIR)/.build-id" \
$<
$(OBJCOPY) --strip-debug $< $@
diff --git a/configure.ac b/configure.ac
index 7f122cb..bb590ab 100644
--- a/configure.ac
+++ b/configure.ac
@@ -67,6 +67,14 @@ AM_MAINTAINER_MODE
AC_ARG_WITH(target-subdir,
[ --with-target-subdir=SUBDIR Configuring in a subdirectory for target])
+AC_ARG_WITH(separate-debug-dir,
+[ --with-separate-debug-dir=DEBUGDIR Look for global separate debug info in this path @<:@LIBDIR/debug@:>@],
+[separate_debug_dir=$withval],
+[separate_debug_dir=$libdir/debug])
+
+SEPARATE_DEBUG_DIR=$separate_debug_dir
+AC_SUBST(SEPARATE_DEBUG_DIR)
+
# We must force CC to /not/ be precious variables; otherwise
# the wrong, non-multilib-adjusted value will be used in multilibs.
# As a side effect, we have to subst CFLAGS ourselves.
diff --git a/elf.c b/elf.c
index e82ecc5..8b1189c 100644
--- a/elf.c
+++ b/elf.c
@@ -856,7 +856,7 @@ elf_readlink (struct backtrace_state *state, const char *filename,
}
}
-#define SYSTEM_BUILD_ID_DIR "/usr/lib/debug/.build-id/"
+#define BUILD_ID_DIR "/.build-id/"
/* Open a separate debug info file, using the build ID to find it.
Returns an open file descriptor, or -1.
@@ -870,7 +870,7 @@ elf_open_debugfile_by_buildid (struct backtrace_state *state,
backtrace_error_callback error_callback,
void *data)
{
- const char * const prefix = SYSTEM_BUILD_ID_DIR;
+ const char * const prefix = SYSTEM_DEBUG_DIR BUILD_ID_DIR;
const size_t prefix_len = strlen (prefix);
const char * const suffix = ".debug";
const size_t suffix_len = strlen (suffix);
--
2.38.1

View file

@ -0,0 +1,101 @@
From de122af5382d8017cae63bdee946206c6c6c23ab Mon Sep 17 00:00:00 2001
From: Jan Tojnar <jtojnar@gmail.com>
Date: Sat, 24 Dec 2022 20:19:27 +0100
Subject: [PATCH 3/4] libbacktrace: Support multiple build id directories
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
gdb supports multiple debug directories separated by colons:
https://github.com/bminor/binutils-gdb/blob/fcbfb25dcca625a7f999ec51d48b6fc3a32123c3/gdb/build-id.c#L136-L142
This is useful for example when using dwarffs in addition
to debug data installed using distributions package manager.
---
elf.c | 57 ++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 36 insertions(+), 21 deletions(-)
diff --git a/elf.c b/elf.c
index 8b1189c..65c647a 100644
--- a/elf.c
+++ b/elf.c
@@ -865,12 +865,12 @@ elf_readlink (struct backtrace_state *state, const char *filename,
when the build ID is known is in /usr/lib/debug/.build-id. */
static int
-elf_open_debugfile_by_buildid (struct backtrace_state *state,
+elf_open_debugfile_by_buildid (const char * const prefix,
+ struct backtrace_state *state,
const char *buildid_data, size_t buildid_size,
backtrace_error_callback error_callback,
void *data)
{
- const char * const prefix = SYSTEM_DEBUG_DIR BUILD_ID_DIR;
const size_t prefix_len = strlen (prefix);
const char * const suffix = ".debug";
const size_t suffix_len = strlen (suffix);
@@ -6936,27 +6936,42 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
if (buildid_data != NULL)
{
int d;
+ char debug_directories[strlen(SYSTEM_DEBUG_DIR) + 1];
+ char *debug_dir;
- d = elf_open_debugfile_by_buildid (state, buildid_data, buildid_size,
- error_callback, data);
- if (d >= 0)
- {
- int ret;
+ strcpy(debug_directories, SYSTEM_DEBUG_DIR);
- elf_release_view (state, &buildid_view, error_callback, data);
- if (debuglink_view_valid)
- elf_release_view (state, &debuglink_view, error_callback, data);
- if (debugaltlink_view_valid)
- elf_release_view (state, &debugaltlink_view, error_callback, data);
- ret = elf_add (state, "", d, NULL, 0, base_address, error_callback,
- data, fileline_fn, found_sym, found_dwarf, NULL, 0,
- 1, NULL, 0);
- if (ret < 0)
- backtrace_close (d, error_callback, data);
- else if (descriptor >= 0)
- backtrace_close (descriptor, error_callback, data);
- return ret;
- }
+ debug_dir = strtok (debug_directories, ":");
+ while (debug_dir != NULL)
+ {
+ char prefix[strlen(debug_dir) + strlen(BUILD_ID_DIR) + 1];
+ strcpy(prefix, debug_dir);
+ strcat(prefix, BUILD_ID_DIR);
+
+ d = elf_open_debugfile_by_buildid (prefix, state, buildid_data, buildid_size,
+ error_callback, data);
+
+ if (d >= 0)
+ {
+ int ret;
+
+ elf_release_view (state, &buildid_view, error_callback, data);
+ if (debuglink_view_valid)
+ elf_release_view (state, &debuglink_view, error_callback, data);
+ if (debugaltlink_view_valid)
+ elf_release_view (state, &debugaltlink_view, error_callback, data);
+ ret = elf_add (state, "", d, NULL, 0, base_address, error_callback,
+ data, fileline_fn, found_sym, found_dwarf, NULL, 0,
+ 1, NULL, 0);
+ if (ret < 0)
+ backtrace_close (d, error_callback, data);
+ else if (descriptor >= 0)
+ backtrace_close (descriptor, error_callback, data);
+ return ret;
+ }
+
+ debug_dir = strtok (NULL, ":");
+ }
}
if (buildid_view_valid)
--
2.38.1

View file

@ -0,0 +1,42 @@
From a3b7510e4c9e7201a4301f2a45d8569b06354607 Mon Sep 17 00:00:00 2001
From: Jan Tojnar <jtojnar@gmail.com>
Date: Sat, 24 Dec 2022 20:30:22 +0100
Subject: [PATCH 4/4] libbacktrace: Support NIX_DEBUG_INFO_DIRS environment
variable
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Lets make debug data lookup work on NixOS just like in gdb.
---
elf.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/elf.c b/elf.c
index 65c647a..5c8abc0 100644
--- a/elf.c
+++ b/elf.c
@@ -6935,11 +6935,18 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
if (buildid_data != NULL)
{
+ const char *debug_directories_immutable;
+ const char *nix_debug = getenv ("NIX_DEBUG_INFO_DIRS");
+ if (nix_debug != NULL)
+ debug_directories_immutable = nix_debug;
+ else
+ debug_directories_immutable = SYSTEM_DEBUG_DIR;
+
int d;
- char debug_directories[strlen(SYSTEM_DEBUG_DIR) + 1];
+ char debug_directories[strlen(debug_directories_immutable) + 1];
char *debug_dir;
- strcpy(debug_directories, SYSTEM_DEBUG_DIR);
+ strcpy(debug_directories, debug_directories_immutable);
debug_dir = strtok (debug_directories, ":");
while (debug_dir != NULL)
--
2.38.1

View file

@ -1,22 +1,52 @@
{ lib, stdenv, callPackage, fetchFromGitHub
{ stdenv
, lib
, fetchFromGitHub
, enableStatic ? stdenv.hostPlatform.isStatic
, enableShared ? !stdenv.hostPlatform.isStatic
, unstableGitUpdater
, autoreconfHook
}:
let
yesno = b: if b then "yes" else "no";
in stdenv.mkDerivation rec {
stdenv.mkDerivation {
pname = "libbacktrace";
version = "2020-05-13";
version = "unstable-2022-12-16";
src = fetchFromGitHub {
owner = "ianlancetaylor";
repo = pname;
rev = "9b7f216e867916594d81e8b6118f092ac3fcf704";
sha256 = "0qr624v954gnfkmpdlfk66sxz3acyfmv805rybsaggw5gz5sd1nh";
repo = "libbacktrace";
rev = "da7eff2f37e38136c5a0c8922957b9dfab5483ef";
sha256 = "ADp8n1kUf8OysFY/Jv1ytxKjqgz1Nu2VRcFGlt1k/HM=";
};
configureFlags = [
"--enable-static=${yesno enableStatic}"
"--enable-shared=${yesno enableShared}"
patches = [
# Fix tests with shared library.
# https://github.com/ianlancetaylor/libbacktrace/pull/99
./0001-libbacktrace-avoid-libtool-wrapping-tests.patch
# Support multiple debug dirs.
# https://github.com/ianlancetaylor/libbacktrace/pull/100
./0002-libbacktrace-Allow-configuring-debug-dir.patch
./0003-libbacktrace-Support-multiple-build-id-directories.patch
# Support NIX_DEBUG_INFO_DIRS environment variable.
./0004-libbacktrace-Support-NIX_DEBUG_INFO_DIRS-environment.patch
];
nativeBuildInputs = [
autoreconfHook
];
configureFlags = [
(lib.enableFeature enableStatic "static")
(lib.enableFeature enableShared "shared")
];
doCheck = stdenv.isLinux;
passthru = {
updateScript = unstableGitUpdater { };
};
meta = with lib; {
description = "A C library that may be linked into a C/C++ program to produce symbolic backtraces";
homepage = "https://github.com/ianlancetaylor/libbacktrace";