summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kratochvil <jan.kratochvil@redhat.com>2014-08-17 18:49:36 +0200
committerJan Kratochvil <jan.kratochvil@redhat.com>2014-08-29 22:35:52 +0200
commit0375056af003d7676fb852e09782a985f3a52b1a (patch)
tree6d101dbae653236bc7f9f0e5234f3a8c0e8dd792
parentf1ec744b5747a3bd66297c9f965be6ea10cb7f86 (diff)
downloadelfutils-0375056af003d7676fb852e09782a985f3a52b1a.tar.gz
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 <jan.kratochvil@redhat.com>
-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 <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.
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 <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.
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