]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Fix resolving ELF symbols for live PIDs with deleted files
authorJan Kratochvil <jan.kratochvil@redhat.com>
Sun, 17 Aug 2014 16:49:36 +0000 (18:49 +0200)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Fri, 29 Aug 2014 20:35:52 +0000 (22:35 +0200)
For deleted shared library files the offsets to the symbol table were
calculated wrongly from the phdrs because the main_bias wasn't taken into
account.

Formerly shared libraries did not get resolved properly:
#2  0x00007fc4d86c56d6
#3  0x0000000000400938 main

Fixed elfutils produce:
#2  0x00007f61094876d6 libfunc
#3  0x0000000000400938 main

Signed-off-by: Jan Kratochvil <jan.kratochvil@redhat.com>
libdwfl/ChangeLog
libdwfl/dwfl_module_getdwarf.c
tests/ChangeLog
tests/Makefile.am
tests/deleted-lib.c [new file with mode: 0644]
tests/deleted.c [new file with mode: 0644]
tests/run-deleted.sh [new file with mode: 0755]

index c644ffe87601ffa5141706780b1b98b8f3c01170..3de772e158421d35a186181e83bd755f2edcc1ad 100644 (file)
@@ -1,3 +1,9 @@
+2014-08-28  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       * dwfl_module_getdwarf.c (find_offsets): Add parameter main_bias, use
+       it.
+       (find_dynsym): Pass the new parameter main_bias.
+
 2014-08-14  Mark Wielaard  <mjw@redhat.com>
 
        * linux-kernel-modules.c (check-suffix): Also TRY .ko.xz.
index 7259984104a0b2e28f80ac314f5c2c65084c9975..e705f57e8e68a3d3cbafffaa615e3a0e00f87964 100644 (file)
@@ -621,7 +621,7 @@ load_symtab (struct dwfl_file *file, struct dwfl_file **symfile,
 /* Translate addresses into file offsets.
    OFFS[*] start out zero and remain zero if unresolved.  */
 static void
-find_offsets (Elf *elf, size_t phnum, size_t n,
+find_offsets (Elf *elf, GElf_Addr main_bias, size_t phnum, size_t n,
              GElf_Addr addrs[n], GElf_Off offs[n])
 {
   size_t unsolved = n;
@@ -632,10 +632,10 @@ find_offsets (Elf *elf, size_t phnum, size_t n,
       if (phdr != NULL && phdr->p_type == PT_LOAD && phdr->p_memsz > 0)
        for (size_t j = 0; j < n; ++j)
          if (offs[j] == 0
-             && addrs[j] >= phdr->p_vaddr
-             && addrs[j] - phdr->p_vaddr < phdr->p_filesz)
+             && addrs[j] >= phdr->p_vaddr + main_bias
+             && addrs[j] - (phdr->p_vaddr + main_bias) < phdr->p_filesz)
            {
-             offs[j] = addrs[j] - phdr->p_vaddr + phdr->p_offset;
+             offs[j] = addrs[j] - (phdr->p_vaddr + main_bias) + phdr->p_offset;
              if (--unsolved == 0)
                break;
            }
@@ -720,7 +720,8 @@ find_dynsym (Dwfl_Module *mod)
 
          /* Translate pointers into file offsets.  */
          GElf_Off offs[i_max] = { 0, };
-         find_offsets (mod->main.elf, phnum, i_max, addrs, offs);
+         find_offsets (mod->main.elf, mod->main_bias, phnum, i_max, addrs,
+                       offs);
 
          /* Figure out the size of the symbol table.  */
          if (offs[i_hash] != 0)
index dce6ebe6748ff450277e0c51330188f1623df4ae..3f1272850fb8c1765b7aad28ef52bbfd2bc00c8a 100644 (file)
@@ -1,3 +1,12 @@
+2014-08-28  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       * Makefile.am (check_PROGRAMS): Add deleted and deleted-lib.so.
+       (TESTS, EXTRA_DIST): Add run-deleted.sh.
+       (deleted_LDADD, deleted_lib_so_LDFLAGS, deleted_lib_so_CFLAGS): New.
+       * deleted-lib.c: New file.
+       * deleted.c: New file.
+       * run-deleted.sh: New file.
+
 2014-06-15  Mark Wielaard  <mjw@redhat.com>
 
        * backtrace.c (frame_callback): Error on seeing more than 16 frames.
index 4cc81c9ca2efe2825f216e785ffe591efb61a785..be3494daba97bcb841acf3f840b7d7ac0269a30d 100644 (file)
@@ -50,7 +50,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
                  test-elf_cntl_gelf_getshdr dwflsyms dwfllines \
                  dwfl-report-elf-align varlocs backtrace backtrace-child \
                  backtrace-data backtrace-dwarf debuglink debugaltlink \
-                 buildid
+                 buildid deleted deleted-lib.so
 
 asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
            asm-tst6 asm-tst7 asm-tst8 asm-tst9
@@ -109,7 +109,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
        run-backtrace-core-s390x.sh run-backtrace-core-s390.sh \
        run-backtrace-core-aarch64.sh \
        run-backtrace-demangle.sh run-stack-d-test.sh run-stack-i-test.sh \
-       run-readelf-dwz-multi.sh run-allfcts-multi.sh
+       run-readelf-dwz-multi.sh run-allfcts-multi.sh run-deleted.sh
 
 if !BIARCH
 export ELFUTILS_DISABLE_BIARCH = 1
@@ -271,7 +271,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
             testfile-backtrace-demangle.core.bz2 \
             run-stack-d-test.sh run-stack-i-test.sh \
             testfiledwarfinlines.bz2 testfiledwarfinlines.core.bz2 \
-            run-readelf-zdebug.sh testfile-debug.bz2 testfile-zdebug.bz2
+            run-readelf-zdebug.sh testfile-debug.bz2 testfile-zdebug.bz2 \
+            run-deleted.sh
 
 if USE_VALGRIND
 valgrind_cmd='valgrind -q --error-exitcode=1 --run-libc-freeres=no'
@@ -406,6 +407,9 @@ backtrace_dwarf_LDADD = $(libdw) $(libelf)
 debuglink_LDADD = $(libdw) $(libelf)
 debugaltlink_LDADD = $(libdw) $(libelf)
 buildid_LDADD = $(libdw) $(libelf)
+deleted_LDADD = ./deleted-lib.so
+deleted_lib_so_LDFLAGS = -shared -rdynamic
+deleted_lib_so_CFLAGS = -fPIC
 
 if GCOV
 check: check-am coverage
diff --git a/tests/deleted-lib.c b/tests/deleted-lib.c
new file mode 100644 (file)
index 0000000..1ff411b
--- /dev/null
@@ -0,0 +1,27 @@
+/* Test program for opening already deleted running binaries.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file 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.
+
+   elfutils 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 <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <unistd.h>
+
+void
+libfunc (void)
+{
+  sleep (60000);
+  /* Avoid tail call optimization for the sleep call.  */
+  asm volatile ("");
+}
diff --git a/tests/deleted.c b/tests/deleted.c
new file mode 100644 (file)
index 0000000..32a310b
--- /dev/null
@@ -0,0 +1,50 @@
+/* Test program for opening already deleted running binaries.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file 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.
+
+   elfutils 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 <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdio.h>
+#include <error.h>
+#include <errno.h>
+
+extern void libfunc (void);
+
+int
+main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused)))
+{
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  pid_t pid = fork ();
+  assert (pid != -1);
+  if (pid == 0)
+    {
+      int err = close (0);
+      assert (!err);
+      err = close (1);
+      assert (!err);
+      err = close (2);
+      assert (!err);
+      libfunc ();
+      abort ();
+    }
+  printf ("%d\n", pid);
+  return EXIT_SUCCESS;
+}
diff --git a/tests/run-deleted.sh b/tests/run-deleted.sh
new file mode 100755 (executable)
index 0000000..b3f17ff
--- /dev/null
@@ -0,0 +1,33 @@
+#! /bin/bash
+# Copyright (C) 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file 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.
+#
+# elfutils 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 <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+tempfiles deleted deleted-lib.so
+cp -p ${abs_builddir}/deleted ${abs_builddir}/deleted-lib.so .
+pid=$(testrun ${abs_builddir}/deleted)
+sleep 1
+rm -f deleted deleted-lib.so
+tempfiles bt
+# It may have non-zero exit code with:
+# .../elfutils/src/stack: dwfl_thread_getframes tid 26376 at 0x4006c8 in .../elfutils/tests/deleted: no matching address range
+testrun ${abs_top_builddir}/src/stack -p $pid >bt || true
+cat bt
+kill -9 $pid
+wait
+grep -qw libfunc bt
+grep -qw main bt