libbacktrace icon indicating copy to clipboard operation
libbacktrace copied to clipboard

backtrace returns mix of absolute and relative paths; how to force absolute paths?

Open timotheecour opened this issue 3 years ago • 0 comments

after investigation, this is the root cause for https://github.com/status-im/nim-libbacktrace/issues/11

this library does not preserve absolute paths in backtrace if the input file is rooted under $PWD/anydir/

it does preserve absolute paths if the input file is under $PWD/foo.c or not rooted under $PWD (eg /other/foo.c)

this is a problem for several reasons eg

  • when a script changes directory and then invokes compilation
  • when different files are compiled in different directories
  • when users expect absolute paths

note that in all cases, I'm invoking clang with absolute paths (and dwarfdump correctly shows absolute paths)

to reproduce

git clone https://github.com/ianlancetaylor/libbacktrace cd libbacktrace ./configure apply the patch [1] which simply adds a call to backtrace_print mkdir sub cp mtest.c sub # note that, as noted above, things work if we use $(pwd)/mtest.c, but not $(pwd)/sub/mtest.c DESTDIR=/tmp/d15c make install

  • clang -o /tmp/z01 -L/tmp/d15c/usr/local/lib -g -I. $(pwd)/sub/mtest.c testlib.c -Wl,-lbacktrace
  • /tmp/z01

output

D20210405T202237 0x103c24de8 f3 sub/mtest.c:112 0x103c24d17 f2 sub/mtest.c:94 0x103c24ccd test1 sub/mtest.c:88 0x103c24c8e main sub/mtest.c:404 PASS: backtrace_full noinline PASS: backtrace_simple noinline test5: unexpected syminfo name got _dyld_private expected global FAIL: backtrace_syminfo variable

expected output

$PWD/sub/mtest.c instead of sub/mtest.c, where $PWD is the current dir

maybe related

https://github.com/ianlancetaylor/libbacktrace/issues/26

patch [1]

diff --git a/mtest.c b/mtest.c
index 7e0189a..f3a682b 100644
--- a/mtest.c
+++ b/mtest.c
@@ -108,6 +108,8 @@ f3 (int f1line __attribute__ ((unused)), int f2line __attribute__ ((unused)))
   data.failed = 0;

   i = backtrace_full (state, 0, callback_mtest, error_callback_one, &data);
+  printf("D20210405T202237\n");
+  backtrace_print (state, 0, stdout);

   if (i != 0)
     {

note 1

i'm on osx, if that matters

note 2

after investigating, in dwarf.c:

  hdr->filenames[0] = u->filename;
  printf("D20210405T183857.2 %s\n", u->filename); // would print absolute paths

  i = 1;
  while (*hdr_buf->buf != '\0')
    {
      printf("ok1\n");
      const char *filename;
      uint64_t dir_index;

      if (hdr_buf->reported_underflow)
	return 0;

      filename = read_string (hdr_buf);
      printf("D20210405T183857.3 %s\n", filename); // would not print absolute paths
      if (filename == NULL)
	return 0;
      dir_index = read_uleb128 (hdr_buf);

note 3

DW_AT_comp_dir is probably incorrectly used (see comp_dir) even if internal DWARF representation uses relative paths relative to compilation dir for compression, backtrace API should "decompress" those into absolute paths in a given compilation unit, at very least as an option.

The caller of backtrace API doesn't have access to DW_AT_comp_dir, in particular different compilation units could have their own DW_AT_comp_dir.

ntoe 4

the code in read_v2_paths seems relevant, eg:

	  memcpy (s + dir_len + 1, filename, filename_len + 1);

misc links

timotheecour avatar Apr 06 '21 04:04 timotheecour