--- Begin Message ---
libdwfl/
2013-12-18 Jan Kratochvil <[email protected]>
Support live PIDs with deleted files.
* linux-proc-maps.c (PROCMAPFILESFMT): New #defined.
(proc_maps_report): New comment for low and high. New variable
high_start, set it everywhere.
(proc_maps_report) (map_files_name): New inlined function.
(proc_maps_report) (report): Call it and set mod->main.NAME.
tests/
2013-12-18 Jan Kratochvil <[email protected]>
Support live PIDs with deleted files.
* 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.
Signed-off-by: Jan Kratochvil <[email protected]>
---
libdwfl/linux-proc-maps.c | 30 +++++++++++++++++++++++++---
tests/Makefile.am | 10 +++++++---
tests/deleted-lib.c | 27 +++++++++++++++++++++++++
tests/deleted.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++
tests/run-deleted.sh | 34 ++++++++++++++++++++++++++++++++
5 files changed, 145 insertions(+), 6 deletions(-)
create mode 100644 tests/deleted-lib.c
create mode 100644 tests/deleted.c
create mode 100755 tests/run-deleted.sh
diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c
index 8863cc8..b9604d0 100644
--- a/libdwfl/linux-proc-maps.c
+++ b/libdwfl/linux-proc-maps.c
@@ -43,6 +43,7 @@
#define PROCMAPSFMT "/proc/%d/maps"
+#define PROCMAPFILESFMT "/proc/%d/map_files/%" PRIx64 "-%" PRIx64
#define PROCMEMFMT "/proc/%d/mem"
#define PROCAUXVFMT "/proc/%d/auxv"
#define PROCEXEFMT "/proc/%d/exe"
@@ -176,7 +177,26 @@ proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr
sysinfo_ehdr, pid_t pid)
unsigned int last_dmajor = -1, last_dminor = -1;
uint64_t last_ino = -1;
char *last_file = NULL;
- Dwarf_Addr low = 0, high = 0;
+ // LOW-HIGH is cumulative range for all lines of the current filename.
+ // HIGH_START-HIGH is range of only the very last PROCMAPSFMT line.
+ Dwarf_Addr low = 0, high_start = 0, high = 0;
+
+ inline char *map_files_name (void)
+ {
+ static int map_files_failed = -1;
+ if (map_files_failed > 0)
+ return NULL;
+ char *map_fname;
+ if (asprintf (&map_fname, PROCMAPFILESFMT, pid, high_start, high) < 0)
+ return NULL;
+ if (map_files_failed == 0)
+ return map_fname;
+ map_files_failed = access (map_fname, R_OK) != 0;
+ if (! map_files_failed)
+ return map_fname;
+ free (map_fname);
+ return NULL;
+ }
inline bool report (void)
{
@@ -188,6 +208,9 @@ proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr
sysinfo_ehdr, pid_t pid)
last_file = NULL;
if (unlikely (mod == NULL))
return true;
+ char *map_fname = map_files_name ();
+ if (map_fname != NULL)
+ mod->main.name = map_fname;
}
return false;
}
@@ -224,7 +247,7 @@ proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr
sysinfo_ehdr, pid_t pid)
return -1;
}
- low = start;
+ low = high_start = start;
high = end;
if (asprintf (&last_file, "[vdso: %d]", (int) pid) < 0
|| report ())
@@ -241,6 +264,7 @@ proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr
sysinfo_ehdr, pid_t pid)
{
/* This is another portion of the same file's mapping. */
assert (!strcmp (last_file, file));
+ high_start = start;
high = end;
}
else
@@ -248,7 +272,7 @@ proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr
sysinfo_ehdr, pid_t pid)
/* This is a different file mapping. Report the last one. */
if (report ())
goto bad_report;
- low = start;
+ low = high_start = start;
high = end;
last_file = strdup (file);
last_ino = ino;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b58e0f5..cb2f861 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -53,7 +53,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames
sectiondump \
alldts md5-sha1-test typeiter typeiter2 low_high_pc \
test-elf_cntl_gelf_getshdr dwflsyms dwfllines \
dwfl-report-elf-align varlocs backtrace backtrace-child \
- backtrace-data backtrace-dwarf
+ backtrace-data backtrace-dwarf deleted deleted-lib.so
asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
asm-tst6 asm-tst7 asm-tst8 asm-tst9
@@ -107,7 +107,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile
test-nlist \
run-backtrace-native-biarch.sh run-backtrace-native-core.sh \
run-backtrace-native-core-biarch.sh run-backtrace-core-x86_64.sh \
run-backtrace-core-i386.sh run-backtrace-core-ppc.sh \
- run-backtrace-core-s390x.sh run-backtrace-core-s390.sh
+ run-backtrace-core-s390x.sh run-backtrace-core-s390.sh run-deleted.sh
if !BIARCH
export ELFUTILS_DISABLE_BIARCH = 1
@@ -251,7 +251,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
run-backtrace-core-ppc.sh \
backtrace.s390x.core.bz2 backtrace.s390x.exec.bz2 \
backtrace.s390.core.bz2 backtrace.s390.exec.bz2 \
- run-backtrace-core-s390x.sh run-backtrace-core-s390.sh
+ run-backtrace-core-s390x.sh run-backtrace-core-s390.sh \
+ run-deleted.sh
if USE_VALGRIND
valgrind_cmd='valgrind -q --error-exitcode=1 --run-libc-freeres=no'
@@ -388,6 +389,9 @@ backtrace_child_biarch_SOURCES = backtrace-child.c
backtrace_data_LDADD = $(libdw) $(libelf) $(libmudflap)
backtrace_dwarf_CFLAGS = -Wno-unused-parameter
backtrace_dwarf_LDADD = $(libdw) $(libelf) $(libmudflap)
+deleted_LDADD = ./deleted-lib.so
+deleted_lib_so_LDFLAGS = -shared
+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 0000000..b4a12bf
--- /dev/null
+++ b/tests/deleted-lib.c
@@ -0,0 +1,27 @@
+/* Test program for opening already deleted running binaries.
+ Copyright (C) 2013 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 (60);
+ /* 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 0000000..feb6ac5
--- /dev/null
+++ b/tests/deleted.c
@@ -0,0 +1,50 @@
+/* Test program for opening already deleted running binaries.
+ Copyright (C) 2013 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 0000000..4f20404
--- /dev/null
+++ b/tests/run-deleted.sh
@@ -0,0 +1,34 @@
+#! /bin/bash
+# Copyright (C) 2013 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
+
+# Linux kernel 3.11.10 permits map_files/ access only for root.
+if head -qc0 /proc/self/map_files/* 2>&1 | grep -w 'Operation not permitted';
then
+ exit 77
+fi
+
+tempfiles deleted deleted-lib.so
+cp -p ${abs_builddir}/deleted ${abs_builddir}/deleted-lib.so .
+pid=$(testrun ${abs_builddir}/deleted)
+sleep 1
+tempfiles bt
+testrun ${abs_top_builddir}/src/stack -p $pid >bt
+kill -9 $pid
+wait
+grep -w libfunc bt
+grep -w main bt
--
1.8.3.1
--- End Message ---