summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kratochvil <[email protected]>2014-08-17 18:49:36 +0200
committerJan Kratochvil <[email protected]>2014-08-29 22:35:52 +0200
commit0375056af003d7676fb852e09782a985f3a52b1a (patch)
tree6d101dbae653236bc7f9f0e5234f3a8c0e8dd792
parentf1ec744b5747a3bd66297c9f965be6ea10cb7f86 (diff)
Fix resolving ELF symbols for live PIDs with deleted files
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 <[email protected]>
-rw-r--r--libdwfl/ChangeLog6
-rw-r--r--libdwfl/dwfl_module_getdwarf.c11
-rw-r--r--tests/ChangeLog9
-rw-r--r--tests/Makefile.am10
-rw-r--r--tests/deleted-lib.c27
-rw-r--r--tests/deleted.c50
-rwxr-xr-xtests/run-deleted.sh33
7 files changed, 138 insertions, 8 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index c644ffe8..3de772e1 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,9 @@
+2014-08-28 Jan Kratochvil <[email protected]>
+
+ * 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 <[email protected]>
* linux-kernel-modules.c (check-suffix): Also TRY .ko.xz.
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index 72599841..e705f57e 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -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)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index dce6ebe6..3f127285 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,12 @@
+2014-08-28 Jan Kratochvil <[email protected]>
+
+ * 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 <[email protected]>
* backtrace.c (frame_callback): Error on seeing more than 16 frames.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 4cc81c9c..be3494da 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -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
index 00000000..1ff411b7
--- /dev/null
+++ b/tests/deleted-lib.c
@@ -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
index 00000000..32a310b6
--- /dev/null
+++ b/tests/deleted.c
@@ -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
index 00000000..b3f17ff4
--- /dev/null
+++ b/tests/run-deleted.sh
@@ -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