Hi Mark,
[patchv3] Fix dwfl_report_elf BASE alignment https://lists.fedorahosted.org/pipermail/elfutils-devel/2012-November/002759... Message-ID: 20121116161051.GA2042@host2.jankratochvil.net
[patch 4/4] unwinder: The unwinder (x86* only) https://lists.fedorahosted.org/pipermail/elfutils-devel/2012-November/002748... Message-ID: 20121113203131.GD23062@host2.jankratochvil.net + [patch 1/4] unwinder: New base address based dwfl_report_elf_baseaddr [patch 2/4] unwinder: Provide EBLHOOKVAR [patch 3/4] unwinder: Provide dwfl_core_filename_report [patch 5/4] unwinder: non-x86* parts of the unwinder [resent] [patch 6/4] unwinder: New dwfl_fd_find_debuginfo stub
[patch 3/3] ppc64 .opd: Bidirectional provider https://lists.fedorahosted.org/pipermail/elfutils-devel/2012-December/002840... Message-ID: 20121214194144.GC5500@host2.jankratochvil.net + [patch 1/3] ppc64 .opd: Refactor syments/first_global [patch 2/3] ppc64 .opd: Provide elf_scnfindvma
All of the patches may be out of sync (at least due to ChangeLogs). I would like to know which ones / in which order to rebase, I was already rebasing some in the past.
Thanks, Jan
On Thu, 2013-02-28 at 15:30 +0100, Jan Kratochvil wrote:
[patchv3] Fix dwfl_report_elf BASE alignment https://lists.fedorahosted.org/pipermail/elfutils-devel/2012-November/002759... Message-ID: 20121116161051.GA2042@host2.jankratochvil.net
I think we agree the actual change is fine. Roland reviewed your glibc comment change to l_addr in link.h. So I assume he didn't see anything odd either in this change.
The only reason I was hesitant about the patch was the testcase. I assume this mimics what dwfl_linux_proc_report () would do, and it was easier to write it using dwfl_report_elf ()?
If you could add a comment where the constants for base (0x7f3560c92000) and funcaddr (0x7f3560c92585) come from (and/or how to calculate your own in case someone wants to extend the testcase) that would be appreciated.
Thanks,
Mark
On Fri, 15 Mar 2013 14:37:53 +0100, Mark Wielaard wrote:
The only reason I was hesitant about the patch was the testcase. I assume this mimics what dwfl_linux_proc_report () would do, and it was easier to write it using dwfl_report_elf ()?
dwfl_linux_proc_report uses live PID but if you have a dead core file how to pass a PID to dwfl_linux_proc_report?
It is also explained in the patch mail that elfutils uses dwfl_report_segment which does not have such bug but it is elfutils internal function. Applications cannot use it. Maybe the unwinder could have a different API without using dwfl_report_elf but even in such case dwfl_report_elf exists so its bug should be fixed (by this patch).
If you could add a comment where the constants for base (0x7f3560c92000) and funcaddr (0x7f3560c92585) come from (and/or how to calculate your own in case someone wants to extend the testcase) that would be appreciated.
Done.
Therefore I expect it can be checked in.
Thanks, Jan
jankratochvil/basecleanup-basealign
commit f5752a86cb1b191a09a5636dc76addc030440aec Author: Jan Kratochvil jan.kratochvil@redhat.com Date: Sat Oct 27 20:50:21 2012 +0200
libdwfl/ * dwfl_report_elf.c (__libdwfl_report_elf): Remove BASE aligning.
tests/ * Makefile.am (check_PROGRAMS): Add dwfl-report-elf-align. (TESTS): Add run-dwfl-report-elf-align.sh. (EXTRA_DIST): Add run-dwfl-report-elf-align.sh and testfile-dwfl-report-elf-align-shlib.so.bz2 . (dwfl_report_elf_align_LDADD): New. * dwfl-report-elf-align.c: New file. * run-dwfl-report-elf-align.sh: New file. * testfile-dwfl-report-elf-align-shlib.so.bz2: New file.
Signed-off-by: Jan Kratochvil jan.kratochvil@redhat.com
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 78139ba..f55625c 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,7 @@ +2013-03-15 Jan Kratochvil jan.kratochvil@redhat.com + + * dwfl_report_elf.c (__libdwfl_report_elf): Remove BASE aligning. + 2013-02-22 Mark Wielaard mjw@redhat.com
* open.c (__libdw_gunzip,__libdw_bunzip2,__libdw_unlzma): Define diff --git a/libdwfl/dwfl_report_elf.c b/libdwfl/dwfl_report_elf.c index 174ce7c..d706170 100644 --- a/libdwfl/dwfl_report_elf.c +++ b/libdwfl/dwfl_report_elf.c @@ -181,8 +181,6 @@ __libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name, { vaddr = ph->p_vaddr & -ph->p_align; address_sync = ph->p_vaddr + ph->p_memsz; - if ((base & (ph->p_align - 1)) != 0) - base = (base + ph->p_align - 1) & -ph->p_align; start = base + vaddr; break; } diff --git a/tests/ChangeLog b/tests/ChangeLog index d181cd5..4071e6f 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,14 @@ +2013-03-15 Jan Kratochvil jan.kratochvil@redhat.com + + * Makefile.am (check_PROGRAMS): Add dwfl-report-elf-align. + (TESTS): Add run-dwfl-report-elf-align.sh. + (EXTRA_DIST): Add run-dwfl-report-elf-align.sh and + testfile-dwfl-report-elf-align-shlib.so.bz2 . + (dwfl_report_elf_align_LDADD): New. + * dwfl-report-elf-align.c: New file. + * run-dwfl-report-elf-align.sh: New file. + * testfile-dwfl-report-elf-align-shlib.so.bz2: New file. + 2013-02-22 Mark Wielaard mjw@redhat.com
* Makefile.am (TESTS): Remove run-readelf-s.sh and run-dwflsyms.sh. diff --git a/tests/Makefile.am b/tests/Makefile.am index 63184f8..d256733 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -51,7 +51,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ dwfl-bug-getmodules dwarf-getmacros addrcfi \ test-flag-nobits dwarf-getstring rerequest_tag \ alldts md5-sha1-test typeiter low_high_pc \ - test-elf_cntl_gelf_getshdr dwflsyms + test-elf_cntl_gelf_getshdr dwflsyms dwfl-report-elf-align asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \ asm-tst6 asm-tst7 asm-tst8 asm-tst9
@@ -85,7 +85,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-readelf-d.sh run-readelf-gdb_index.sh run-unstrip-n.sh \ run-low_high_pc.sh run-macro-test.sh run-elf_cntl_gelf_getshdr.sh \ run-test-archive64.sh run-readelf-vmcoreinfo.sh \ - run-readelf-mixed-corenote.sh + run-readelf-mixed-corenote.sh run-dwfl-report-elf-align.sh
if !STANDALONE check_PROGRAMS += msg_tst md5-sha1-test @@ -192,7 +192,9 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ run-readelf-mixed-corenote.sh testfile63.bz2 testfile64.bz2 \ testfile65.bz2 testfile67.bz2 testfile68.bz2 \ testfile69.core.bz2 testfile69.so.bz2 \ - testfile70.core.bz2 testfile70.exec.bz2 + testfile70.core.bz2 testfile70.exec.bz2 \ + run-dwfl-report-elf-align.sh \ + testfile-dwfl-report-elf-align-shlib.so.bz2
if USE_VALGRIND valgrind_cmd="valgrind -q --trace-children=yes --error-exitcode=1 --run-libc-freeres=no" @@ -300,6 +302,7 @@ typeiter_LDADD = $(libdw) $(libelf) $(libmudflap) low_high_pc_LDADD = $(libdw) $(libelf) $(libmudflap) test_elf_cntl_gelf_getshdr_LDADD = $(libelf) $(libmudflap) dwflsyms_LDADD = $(libdw) $(libelf) $(libmudflap) +dwfl_report_elf_align_LDADD = $(libdw) $(libmudflap)
if GCOV check: check-am coverage diff --git a/tests/dwfl-report-elf-align.c b/tests/dwfl-report-elf-align.c new file mode 100644 index 0000000..0e8bfe3 --- /dev/null +++ b/tests/dwfl-report-elf-align.c @@ -0,0 +1,72 @@ +/* Test program for dwfl_report_elf incorrect BASE alignment. + 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 <assert.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <error.h> +#include <locale.h> +#include <string.h> +#include <stdlib.h> +#include ELFUTILS_HEADER(dwfl) + + +static const Dwfl_Callbacks offline_callbacks = + { + .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo), + .section_address = INTUSE(dwfl_offline_section_address), + }; + + +int +main (int argc, char **argv) +{ + /* We use no threads here which can interfere with handling a stream. */ + (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER); + + /* Set locale. */ + (void) setlocale (LC_ALL, ""); + + if (argc != 5) + error (1, 0, "dwfl-report-elf-align shlib.so base funcaddr funcname"); + + Dwfl *dwfl = dwfl_begin (&offline_callbacks); + assert (dwfl != NULL); + + char *endptr; + uintptr_t base = strtoull (argv[2], &endptr, 0); + assert (endptr && !*endptr); + + Dwfl_Module *mod = dwfl_report_elf (dwfl, argv[1], argv[1], -1, base); + assert (mod != NULL); + + uintptr_t funcaddr = strtoull (argv[3], &endptr, 0); + assert (endptr && !*endptr); + + Dwfl_Module *mod_found = dwfl_addrmodule (dwfl, funcaddr); + assert (mod_found == mod); + + const char *symname = dwfl_module_addrname (mod, funcaddr); + assert (symname != NULL); + assert (strcmp (symname, argv[4]) == 0); + + dwfl_end (dwfl); + + return 0; +} diff --git a/tests/run-dwfl-report-elf-align.sh b/tests/run-dwfl-report-elf-align.sh new file mode 100755 index 0000000..d032aba --- /dev/null +++ b/tests/run-dwfl-report-elf-align.sh @@ -0,0 +1,44 @@ +#! /bin/sh +# 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 + +testfiles testfile-dwfl-report-elf-align-shlib.so + +# /proc/PID/maps when the process was running: +# 7f3560c92000-7f3560c93000 r-xp 00000000 fd:02 25037063 testfile-dwfl-report-elf-align-shlib.so +# 7f3560c93000-7f3560e92000 ---p 00001000 fd:02 25037063 testfile-dwfl-report-elf-align-shlib.so +# 7f3560e92000-7f3560e93000 rw-p 00000000 fd:02 25037063 testfile-dwfl-report-elf-align-shlib.so +# testfile-dwfl-report-elf-align-shlib.so: +# Program Headers: +# Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align +# LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x00065c 0x00065c R E 0x200000 +# LOAD 0x000660 0x0000000000200660 0x0000000000200660 0x0001f0 0x000200 RW 0x200000 +# Symbol table '.dynsym' contains 12 entries: +# Num: Value Size Type Bind Vis Ndx Name +# 8: 000000000000057c 11 FUNC GLOBAL DEFAULT 11 shlib +# GDB output showing proper relocation: +# #1 0x00007f3560c92585 in shlib () from ./testfile-dwfl-report-elf-align-shlib.so +# +# 0x7f3560c92000 is VMA address of first byte of testfile-dwfl-report-elf-align-shlib.so. +# 0x7f3560c92585 = 0x7f3560c92000 + 0x585 +# where 0x585 is any address inside the shlib function: 0x57c .. 0x57c + 11 -1 + +testrun ./dwfl-report-elf-align ./testfile-dwfl-report-elf-align-shlib.so \ + 0x7f3560c92000 0x7f3560c92585 shlib + +exit 0 diff --git a/tests/testfile-dwfl-report-elf-align-shlib.so.bz2 b/tests/testfile-dwfl-report-elf-align-shlib.so.bz2 new file mode 100755 index 0000000000000000000000000000000000000000..1f35df98ffa1dc5883acce9f3b567891f024e43e GIT binary patch literal 1546 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
literal 0 HcmV?d00001
On Fri, 2013-03-15 at 15:36 +0100, Jan Kratochvil wrote:
On Fri, 15 Mar 2013 14:37:53 +0100, Mark Wielaard wrote:
The only reason I was hesitant about the patch was the testcase. I assume this mimics what dwfl_linux_proc_report () would do, and it was easier to write it using dwfl_report_elf ()?
dwfl_linux_proc_report uses live PID but if you have a dead core file how to pass a PID to dwfl_linux_proc_report?
It is also explained in the patch mail that elfutils uses dwfl_report_segment which does not have such bug but it is elfutils internal function. Applications cannot use it. Maybe the unwinder could have a different API without using dwfl_report_elf but even in such case dwfl_report_elf exists so its bug should be fixed (by this patch).
Yeah, it seems good to fix this. I was just wondering if there was some other way to trigger it. BTW dwfl_report_segment is a public function.
If you could add a comment where the constants for base (0x7f3560c92000) and funcaddr (0x7f3560c92585) come from (and/or how to calculate your own in case someone wants to extend the testcase) that would be appreciated.
Done.
Therefore I expect it can be checked in.
Yes, thanks for adding the explanation to the testcase.
BTW. For the git commit message it is nice if the first line (< 78 chars) is a short summary of the fix. That way a git shortlog looks a little easier to read.
Cheers,
Mark
On Mon, 18 Mar 2013 16:46:03 +0100, Mark Wielaard wrote:
Yeah, it seems good to fix this. I was just wondering if there was some other way to trigger it. BTW dwfl_report_segment is a public function.
Normally one cannot trigger this bug using standard elfutils src/ binaries.
./src/addr2line -p PID -> dwfl_standard_argp -> dwfl_linux_proc_report -> -> /proc/PID/maps -> dwfl_report_module
./src/addr2line --core=CORE -> dwfl_standard_argp -> dwfl_core_file_report -> -> dwfl_report_segment
For core files this happens as build-ids are present there. One needs to disable build-ids from the core file. I tried it the official way of bit 4 in coredump_filter but this does not work, filed kernel Bug: https://bugzilla.redhat.com/show_bug.cgi?id=923827
So I rather patched out the first build-id page of libc.so.6 from the core file and reproduced the elfutils bug:
(echo -e '#include<unistd.h>\nint main(void){return pause();}'|gcc -Wall -x c -;ulimit -c unlimited;./a.out&p=$!;sleep 1;cat /proc/$p/maps >a.out.maps;kill -SEGV $p)
a.out.maps: 7f9c4f6dc000-7f9c4f889000 r-xp 00000000 fd:01 75366917 /usr/lib64/libc-2.16.so + readelf -Wl a.out.core Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x004000 0x00007f9c4f6dc000 0x0000000000000000 0x001000 0x1ad000 R E 0x1000 -> dd if=/dev/zero of=a.out.core conv=notrunc seek=$[0x4000] count=$[0x1000] bs=1
This really finally invoked dwfl_report_elf: #0 __libdwfl_report_elf at dwfl_report_elf.c:46 #1 in dwfl_report_elf at dwfl_report_elf.c:274 #2 in report_r_debug at link_map.c:397 #3 in dwfl_link_map_report at link_map.c:875 #4 in dwfl_core_file_report at core-file.c:454 #5 in parse_opt at argp-std.c:317
$ gdb ./a.out ./a.out.core Program terminated with signal 11, Segmentation fault. #0 0x00007f9c4f7973d0 in __pause_nocancel () at ../sysdeps/unix/syscall-template.S:81
Unpatched elfutils: $ ../src/addr2line -S -e ./a.out --core=./a.out.core.orig 0x00007f9c4f7973d0 pause+0x10 ../sysdeps/unix/syscall-template.S:81 $ ../src/addr2line -S -e ./a.out --core=./a.out.core 0x00007f9c4f7973d0 ?? ??:0
Patched elfutils: $ ../src/addr2line -S -e ./a.out --core=./a.out.core.orig 0x00007f9c4f7973d0 pause+0x10 ../sysdeps/unix/syscall-template.S:81 $ ../src/addr2line -S -e ./a.out --core=./a.out.core 0x00007f9c4f7973d0 pause+0x10 ../sysdeps/unix/syscall-template.S:81
FYI one needs to be on unprelinked system, otherwise libc.so.6 l_addr will be always 0 so no alignment bug can be reproduced with 0.
But I find this reproducer from src/addr2line a bit too complicated, relying on r_debug may make dependencies on system paths etc. so I find the artificial testcase of mine to be a safer/easier way.
BTW. For the git commit message it is nice if the first line (< 78 chars) is a short summary of the fix. That way a git shortlog looks a little easier to read.
done.
Checked in.
Thanks, Jan
commit a1d44825ffc756ed6c0dca3a836c1ff9f0ec151f Author: Jan Kratochvil jan.kratochvil@redhat.com Date: Tue Mar 19 13:40:13 2013 +0100
Fix dwfl_report_elf BASE alignment
libdwfl/ * dwfl_report_elf.c (__libdwfl_report_elf): Remove BASE aligning.
tests/ * Makefile.am (check_PROGRAMS): Add dwfl-report-elf-align. (TESTS): Add run-dwfl-report-elf-align.sh. (EXTRA_DIST): Add run-dwfl-report-elf-align.sh and testfile-dwfl-report-elf-align-shlib.so.bz2 . (dwfl_report_elf_align_LDADD): New. * dwfl-report-elf-align.c: New file. * run-dwfl-report-elf-align.sh: New file. * testfile-dwfl-report-elf-align-shlib.so.bz2: New file.
Signed-off-by: Jan Kratochvil jan.kratochvil@redhat.com
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 15a6c9c..41fc84b 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,7 @@ +2013-03-20 Jan Kratochvil jan.kratochvil@redhat.com + + * dwfl_report_elf.c (__libdwfl_report_elf): Remove BASE aligning. + 2013-03-12 Mark Wielaard mjw@redhat.com
* dwfl_getsrclines.c (dwfl_getsrclines): Return 0 on success. diff --git a/libdwfl/dwfl_report_elf.c b/libdwfl/dwfl_report_elf.c index 174ce7c..d706170 100644 --- a/libdwfl/dwfl_report_elf.c +++ b/libdwfl/dwfl_report_elf.c @@ -181,8 +181,6 @@ __libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name, { vaddr = ph->p_vaddr & -ph->p_align; address_sync = ph->p_vaddr + ph->p_memsz; - if ((base & (ph->p_align - 1)) != 0) - base = (base + ph->p_align - 1) & -ph->p_align; start = base + vaddr; break; } diff --git a/tests/ChangeLog b/tests/ChangeLog index ca06a55..62b589d 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,14 @@ +2013-03-20 Jan Kratochvil jan.kratochvil@redhat.com + + * Makefile.am (check_PROGRAMS): Add dwfl-report-elf-align. + (TESTS): Add run-dwfl-report-elf-align.sh. + (EXTRA_DIST): Add run-dwfl-report-elf-align.sh and + testfile-dwfl-report-elf-align-shlib.so.bz2 . + (dwfl_report_elf_align_LDADD): New. + * dwfl-report-elf-align.c: New file. + * run-dwfl-report-elf-align.sh: New file. + * testfile-dwfl-report-elf-align-shlib.so.bz2: New file. + 2013-03-12 Mark Wielaard mjw@redhat.com
* run-dwfllines.sh: New test. diff --git a/tests/Makefile.am b/tests/Makefile.am index a5f7a8c..9b0bbf1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -51,7 +51,8 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ dwfl-bug-getmodules dwarf-getmacros addrcfi \ test-flag-nobits dwarf-getstring rerequest_tag \ alldts md5-sha1-test typeiter low_high_pc \ - test-elf_cntl_gelf_getshdr dwflsyms dwfllines + test-elf_cntl_gelf_getshdr dwflsyms dwfllines \ + dwfl-report-elf-align asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \ asm-tst6 asm-tst7 asm-tst8 asm-tst9
@@ -85,7 +86,8 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-readelf-d.sh run-readelf-gdb_index.sh run-unstrip-n.sh \ run-low_high_pc.sh run-macro-test.sh run-elf_cntl_gelf_getshdr.sh \ run-test-archive64.sh run-readelf-vmcoreinfo.sh \ - run-readelf-mixed-corenote.sh run-dwfllines.sh + run-readelf-mixed-corenote.sh run-dwfllines.sh \ + run-dwfl-report-elf-align.sh
if !STANDALONE check_PROGRAMS += msg_tst md5-sha1-test @@ -193,7 +195,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ testfile65.bz2 testfile67.bz2 testfile68.bz2 \ testfile69.core.bz2 testfile69.so.bz2 \ testfile70.core.bz2 testfile70.exec.bz2 \ - run-dwfllines.sh + run-dwfllines.sh run-dwfl-report-elf-align.sh \ + testfile-dwfl-report-elf-align-shlib.so.bz2
if USE_VALGRIND valgrind_cmd="valgrind -q --trace-children=yes --error-exitcode=1 --run-libc-freeres=no" @@ -302,6 +305,7 @@ low_high_pc_LDADD = $(libdw) $(libelf) $(libmudflap) test_elf_cntl_gelf_getshdr_LDADD = $(libelf) $(libmudflap) dwflsyms_LDADD = $(libdw) $(libelf) $(libmudflap) dwfllines_LDADD = $(libdw) $(libelf) $(libmudflap) +dwfl_report_elf_align_LDADD = $(libdw) $(libmudflap)
if GCOV check: check-am coverage diff --git a/tests/dwfl-report-elf-align.c b/tests/dwfl-report-elf-align.c new file mode 100644 index 0000000..0e8bfe3 --- /dev/null +++ b/tests/dwfl-report-elf-align.c @@ -0,0 +1,72 @@ +/* Test program for dwfl_report_elf incorrect BASE alignment. + 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 <assert.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <error.h> +#include <locale.h> +#include <string.h> +#include <stdlib.h> +#include ELFUTILS_HEADER(dwfl) + + +static const Dwfl_Callbacks offline_callbacks = + { + .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo), + .section_address = INTUSE(dwfl_offline_section_address), + }; + + +int +main (int argc, char **argv) +{ + /* We use no threads here which can interfere with handling a stream. */ + (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER); + + /* Set locale. */ + (void) setlocale (LC_ALL, ""); + + if (argc != 5) + error (1, 0, "dwfl-report-elf-align shlib.so base funcaddr funcname"); + + Dwfl *dwfl = dwfl_begin (&offline_callbacks); + assert (dwfl != NULL); + + char *endptr; + uintptr_t base = strtoull (argv[2], &endptr, 0); + assert (endptr && !*endptr); + + Dwfl_Module *mod = dwfl_report_elf (dwfl, argv[1], argv[1], -1, base); + assert (mod != NULL); + + uintptr_t funcaddr = strtoull (argv[3], &endptr, 0); + assert (endptr && !*endptr); + + Dwfl_Module *mod_found = dwfl_addrmodule (dwfl, funcaddr); + assert (mod_found == mod); + + const char *symname = dwfl_module_addrname (mod, funcaddr); + assert (symname != NULL); + assert (strcmp (symname, argv[4]) == 0); + + dwfl_end (dwfl); + + return 0; +} diff --git a/tests/run-dwfl-report-elf-align.sh b/tests/run-dwfl-report-elf-align.sh new file mode 100755 index 0000000..d032aba --- /dev/null +++ b/tests/run-dwfl-report-elf-align.sh @@ -0,0 +1,44 @@ +#! /bin/sh +# 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 + +testfiles testfile-dwfl-report-elf-align-shlib.so + +# /proc/PID/maps when the process was running: +# 7f3560c92000-7f3560c93000 r-xp 00000000 fd:02 25037063 testfile-dwfl-report-elf-align-shlib.so +# 7f3560c93000-7f3560e92000 ---p 00001000 fd:02 25037063 testfile-dwfl-report-elf-align-shlib.so +# 7f3560e92000-7f3560e93000 rw-p 00000000 fd:02 25037063 testfile-dwfl-report-elf-align-shlib.so +# testfile-dwfl-report-elf-align-shlib.so: +# Program Headers: +# Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align +# LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x00065c 0x00065c R E 0x200000 +# LOAD 0x000660 0x0000000000200660 0x0000000000200660 0x0001f0 0x000200 RW 0x200000 +# Symbol table '.dynsym' contains 12 entries: +# Num: Value Size Type Bind Vis Ndx Name +# 8: 000000000000057c 11 FUNC GLOBAL DEFAULT 11 shlib +# GDB output showing proper relocation: +# #1 0x00007f3560c92585 in shlib () from ./testfile-dwfl-report-elf-align-shlib.so +# +# 0x7f3560c92000 is VMA address of first byte of testfile-dwfl-report-elf-align-shlib.so. +# 0x7f3560c92585 = 0x7f3560c92000 + 0x585 +# where 0x585 is any address inside the shlib function: 0x57c .. 0x57c + 11 -1 + +testrun ./dwfl-report-elf-align ./testfile-dwfl-report-elf-align-shlib.so \ + 0x7f3560c92000 0x7f3560c92585 shlib + +exit 0 diff --git a/tests/testfile-dwfl-report-elf-align-shlib.so.bz2 b/tests/testfile-dwfl-report-elf-align-shlib.so.bz2 new file mode 100755 index 0000000000000000000000000000000000000000..1f35df98ffa1dc5883acce9f3b567891f024e43e GIT binary patch literal 1546 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
literal 0 HcmV?d00001
On Wed, 20 Mar 2013 16:31:41 +0100, Jan Kratochvil wrote:
One needs to disable build-ids from the core file. I tried it the official way of bit 4 in coredump_filter but this does not work, filed kernel Bug: https://bugzilla.redhat.com/show_bug.cgi?id=923827
This is no bug, I just used (instead of default 0x33) wrong mask, the right one should be apparently 0x23.
But I found I have regressed elfutils by: [commit] [patch] Fix for PIE with both -e and --core in use https://lists.fedorahosted.org/pipermail/elfutils-devel/2012-November/002793... commit d5784afaf49cd59b9286e766cd9b1cf00cb43553
before: $ ./src/addr2line -S -e /bin/sleep --core=/tmp/sleep.core.23 0x00007fefc0c2b430 __gconv_lookup_cache+0xb0 /usr/src/debug/glibc-2.16-75f0d304/iconv/gconv_cache.c:163 - although the symbol is wrong due to this bug
and although still before it required proper args order: ./src/addr2line -S --core=/tmp/sleep.core.23 0x00007fefc0c2b430 -e /bin/sleep ?? ??:0
but now always: ?? ??:0
because: libdwfl/link_map.c /* We could not read the executable's phdrs from the memory image. If we have a presupplied executable, we can still use the AT_PHDR and AT_ENTRY values to verify it, and to adjust its bias if it's a PIE.
There is no executable to check available yet after the patch above.
To be fixed later.
Jan
Please fix that regression soon. We certainly need good test coverage for both the partial-segments and no-text-segments flavors of core files. If it will take you longer than a day or two to get the fix in, please put in the new failing test case anyway. It's better to have a 'make check' failure on the trunk than just an informally known regression.
Thanks, Roland
Hi Roland,
work in progress in: jankratochvil/corewithnobuildid
This mail is just FYI, the patch/branch is not yet suitable for a review.
On Wed, 20 Mar 2013 23:09:22 +0100, Roland McGrath wrote:
Please fix that regression soon. We certainly need good test coverage for both the partial-segments and no-text-segments flavors of core files. If it will take you longer than a day or two to get the fix in, please put in the new failing test case anyway. It's better to have a 'make check' failure on the trunk than just an informally known regression.
I had some difficulties isolating the regression and then I found core files have never worked (reliably) with elfutils - at least as tested with e3e3ee261e0d2f8716b5011ca5fcfc88766146f5 before I started my contributions in 2012.
The new testcase in this branch/patch was created with: echo 'libfunc(){*(int*)0=0;}'|gcc -Wl,--build-id=none -o test-core-lib.so -shared -fPIC -x c -;echo 'const char x[4000]={0};main(){libfunc();}'|gcc -Wl,--build-id=none -o test-core-main ./test-core-lib.so -x c - (ulimit -c unlimited;echo 0x23 >/proc/self/coredump_filter;cat /proc/self/coredump_filter;./test-core-main)
* there is no build-id * first ELF pages is not dumped by kernel
This leads to /proc/PID/maps layout:
7ffff7bda000-7ffff7bdb000 r-xp 00000000 fd:01 25079538 test-core-lib.so 7ffff7bdb000-7ffff7dda000 ---p 00001000 fd:01 25079538 test-core-lib.so 7ffff7dda000-7ffff7ddb000 r--p 00000000 fd:01 25079538 test-core-lib.so 7ffff7ddb000-7ffff7ddc000 rw-p 00001000 fd:01 25079538 test-core-lib.so
which gets dumped as (addresses do not match - it was a different session):
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x014000 0x00007f67f2aaf000 0x0000000000000000 0x000000 0x001000 R E 0x1000 LOAD 0x014000 0x00007f67f2ab0000 0x0000000000000000 0x000000 0x1ff000 0x1000 LOAD 0x014000 0x00007f67f2caf000 0x0000000000000000 0x001000 0x001000 R 0x1000 LOAD 0x015000 0x00007f67f2cb0000 0x0000000000000000 0x001000 0x001000 RW 0x1000
Due to FileSiz == 0 elfutils will find the first ELF page at the 3rd entry during the elfutils pass: /* Now sniff segment contents for modules. */ call dwfl_segment_report_module
Which will place the library incorrectly 2MB higher than it should be, later dwfl_link_map_report pass will not fix that.
I have deleted the whole dwfl_segment_report_module pass as it cannot work. One needs to find libraries from the link map otherwise one may get false positives (finding libraries which were not in the link map) even for example from mmapped (and for some reason dumped) files.
And even if one could ignore additional false positives the current dwfl_link_map_report code tries to match the link map entries back to the entries (incorrectly) found by dwfl_segment_report_module.
But the patch/branch currently has multiple regressions, the elfutils code was relying too much on the dwfl_segment_report_module pass.
Regards, Jan
commit 79098a0798b3e988908a3c735cc8986f15c25fcf Author: Jan Kratochvil jan.kratochvil@redhat.com Date: Mon Apr 1 20:54:36 2013 +0200
../src/addr2line -S -e test-core.exec --core=test-core.core 0x7f67f2aaf619 libfunc+0x9 ??:0
diff --git a/libdwfl/Makefile.am b/libdwfl/Makefile.am index 0ef4928..339b36b 100644 --- a/libdwfl/Makefile.am +++ b/libdwfl/Makefile.am @@ -67,7 +67,6 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c dwfl_version.c \ dwfl_module_addrname.c dwfl_module_addrsym.c \ dwfl_module_return_value_location.c \ dwfl_module_register_names.c \ - dwfl_segment_report_module.c \ link_map.c core-file.c open.c image-header.c
if ZLIB diff --git a/libdwfl/argp-std.c b/libdwfl/argp-std.c index e54f720..d0d49a7 100644 --- a/libdwfl/argp-std.c +++ b/libdwfl/argp-std.c @@ -60,32 +60,6 @@ static const struct argp_option options[] = { NULL, 0, NULL, 0, NULL, 0 } };
-/* Wrapper to provide proper FILE_NAME for -e|--executable. */ -static int -offline_find_elf (Dwfl_Module *mod, void **userdata, const char *modname, - Dwarf_Addr base, char **file_name, Elf **elfp) -{ - if (modname != NULL && (strcmp (modname, "[exe]") == 0 - || strcmp (modname, "[pie]") == 0) - && mod->dwfl->executable_for_core) - { - /* When both --core and --executable are given in whatever order - dwfl_core_file_report is called first and this callback will replace - the Dwfl_Module main.name with the recorded --executable file when the - modname is [exe] or [pie] (which then triggers opening and reporting - of the executable). */ - char *e_dup = strdup (mod->dwfl->executable_for_core); - if (e_dup) - { - free (*file_name); - *file_name = e_dup; - return -1; - } - } - return INTUSE(dwfl_build_id_find_elf) (mod, userdata, modname, base, - file_name, elfp); -} - static char *debuginfo_path;
static const Dwfl_Callbacks offline_callbacks = @@ -96,7 +70,7 @@ static const Dwfl_Callbacks offline_callbacks = .section_address = INTUSE(dwfl_offline_section_address),
/* We use this table for core files too. */ - .find_elf = offline_find_elf, + .find_elf = INTUSE(dwfl_build_id_find_elf), };
static const Dwfl_Callbacks proc_callbacks = @@ -293,6 +267,12 @@ parse_opt (int key, char *arg, struct argp_state *state) opt->dwfl = dwfl; }
+ if (opt->e) + { + if (INTUSE(dwfl_report_offline) (dwfl, "", opt->e, -1) == NULL) + return fail (dwfl, -1, opt->e); + } + if (opt->core) { int fd = open64 (opt->core, O_RDONLY); @@ -330,14 +310,6 @@ parse_opt (int key, char *arg, struct argp_state *state) _("No modules recognized in core file")); return ENOENT; } - - if (opt->e) - dwfl->executable_for_core = strdup (opt->e); - } - else if (opt->e) - { - if (INTUSE(dwfl_report_offline) (dwfl, "", opt->e, -1) == NULL) - return fail (dwfl, -1, opt->e); }
/* One of the three flavors has done dwfl_begin and some reporting diff --git a/libdwfl/core-file.c b/libdwfl/core-file.c index 1545ca8..784b97d 100644 --- a/libdwfl/core-file.c +++ b/libdwfl/core-file.c @@ -39,86 +39,6 @@ #include "system.h"
-/* This is a prototype of what a new libelf interface might be. - This implementation is pessimal for non-mmap cases and should - be replaced by more diddling inside libelf internals. */ -static Elf * -elf_begin_rand (Elf *parent, loff_t offset, loff_t size, loff_t *next) -{ - if (parent == NULL) - return NULL; - - /* On failure return, we update *NEXT to point back at OFFSET. */ - inline Elf *fail (int error) - { - if (next != NULL) - *next = offset; - //__libelf_seterrno (error); - __libdwfl_seterrno (DWFL_E (LIBELF, error)); - return NULL; - } - - loff_t min = (parent->kind == ELF_K_ELF ? - (parent->class == ELFCLASS32 - ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr)) - : parent->kind == ELF_K_AR ? SARMAG - : 0); - - if (unlikely (offset < min) - || unlikely (offset >= (loff_t) parent->maximum_size)) - return fail (ELF_E_RANGE); - - /* For an archive, fetch just the size field - from the archive header to override SIZE. */ - if (parent->kind == ELF_K_AR) - { - struct ar_hdr h = { .ar_size = "" }; - - if (unlikely (parent->maximum_size - offset < sizeof h)) - return fail (ELF_E_RANGE); - - if (parent->map_address != NULL) - memcpy (h.ar_size, parent->map_address + parent->start_offset + offset, - sizeof h.ar_size); - else if (unlikely (pread_retry (parent->fildes, - h.ar_size, sizeof (h.ar_size), - parent->start_offset + offset - + offsetof (struct ar_hdr, ar_size)) - != sizeof (h.ar_size))) - return fail (ELF_E_READ_ERROR); - - offset += sizeof h; - - char *endp; - size = strtoll (h.ar_size, &endp, 10); - if (unlikely (endp == h.ar_size) - || unlikely ((loff_t) parent->maximum_size - offset < size)) - return fail (ELF_E_INVALID_ARCHIVE); - } - - if (unlikely ((loff_t) parent->maximum_size - offset < size)) - return fail (ELF_E_RANGE); - - /* Even if we fail at this point, update *NEXT to point past the file. */ - if (next != NULL) - *next = offset + size; - - if (unlikely (offset == 0) - && unlikely (size == (loff_t) parent->maximum_size)) - return elf_clone (parent, parent->cmd); - - /* Note the image is guaranteed live only as long as PARENT - lives. Using elf_memory is quite suboptimal if the whole - file is not mmap'd. We really should have something like - a generalization of the archive support. */ - Elf_Data *data = elf_getdata_rawchunk (parent, offset, size, ELF_T_BYTE); - if (data == NULL) - return NULL; - assert ((loff_t) data->d_size == size); - return elf_memory (data->d_buf, size); -} - - int dwfl_report_core_segments (Dwfl *dwfl, Elf *elf, size_t phnum, GElf_Phdr *notes) { @@ -158,74 +78,6 @@ dwfl_report_core_segments (Dwfl *dwfl, Elf *elf, size_t phnum, GElf_Phdr *notes) return result; }
-/* Never read more than this much without mmap. */ -#define MAX_EAGER_COST 8192 - -static bool -core_file_read_eagerly (Dwfl_Module *mod, - void **userdata __attribute__ ((unused)), - const char *name __attribute__ ((unused)), - Dwarf_Addr start __attribute__ ((unused)), - void **buffer, size_t *buffer_available, - GElf_Off cost, GElf_Off worthwhile, - GElf_Off whole, - GElf_Off contiguous __attribute__ ((unused)), - void *arg, Elf **elfp) -{ - Elf *core = arg; - - if (whole <= *buffer_available) - { - /* All there ever was, we already have on hand. */ - - if (core->map_address == NULL) - { - /* We already malloc'd the buffer. */ - *elfp = elf_memory (*buffer, whole); - if (unlikely (*elfp == NULL)) - return false; - - (*elfp)->flags |= ELF_F_MALLOCED; - *buffer = NULL; - *buffer_available = 0; - return true; - } - - /* We can use the image inside the core file directly. */ - *elfp = elf_begin_rand (core, *buffer - core->map_address, whole, NULL); - *buffer = NULL; - *buffer_available = 0; - return *elfp != NULL; - } - - /* We don't have the whole file. - Figure out if this is better than nothing. */ - - if (worthwhile == 0) - /* Caller doesn't think so. */ - return false; - - /* - XXX would like to fall back to partial file via memory - when build id find_elf fails - also, link_map name may give file name from disk better than partial here - requires find_elf hook re-doing the magic to fall back if no file found - */ - - if (mod->build_id_len > 0) - /* There is a build ID that could help us find the whole file, - which might be more useful than what we have. - We'll just rely on that. */ - return false; - - if (core->map_address != NULL) - /* It's cheap to get, so get it. */ - return true; - - /* Only use it if there isn't too much to be read. */ - return cost <= MAX_EAGER_COST; -} - bool dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx, void **buffer, size_t *buffer_available, @@ -397,26 +249,6 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf) if (unlikely (ndx <= 0)) return ndx;
- /* Now sniff segment contents for modules. */ - int sniffed = 0; - ndx = 0; - do - { - int seg = dwfl_segment_report_module (dwfl, ndx, NULL, - &dwfl_elf_phdr_memory_callback, elf, - core_file_read_eagerly, elf); - if (unlikely (seg < 0)) - return seg; - if (seg > ndx) - { - ndx = seg; - ++sniffed; - } - else - ++ndx; - } - while (ndx < (int) phnum); - /* Next, we should follow the chain from DT_DEBUG. */
const void *auxv = NULL; @@ -458,6 +290,6 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf) If we found none, we return -1 instead of 0 if there was an error rather than just nothing found. If link_map handling failed, we still have the sniffed modules. */ - return sniffed == 0 || listed > sniffed ? listed : sniffed; + return listed; } INTDEF (dwfl_core_file_report) diff --git a/libdwfl/dwfl_end.c b/libdwfl/dwfl_end.c index 94fcfc6..18dc123 100644 --- a/libdwfl/dwfl_end.c +++ b/libdwfl/dwfl_end.c @@ -46,6 +46,5 @@ dwfl_end (Dwfl *dwfl) __libdwfl_module_free (dead); }
- free (dwfl->executable_for_core); free (dwfl); } diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c deleted file mode 100644 index 7cf7499..0000000 --- a/libdwfl/dwfl_segment_report_module.c +++ /dev/null @@ -1,657 +0,0 @@ -/* Sniff out modules from ELF headers visible in memory segments. - Copyright (C) 2008-2012 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 either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see http://www.gnu.org/licenses/. */ - -#include <config.h> -#include "../libelf/libelfP.h" /* For NOTE_ALIGN. */ -#undef _ -#include "libdwflP.h" - -#include <elf.h> -#include <gelf.h> -#include <inttypes.h> -#include <sys/param.h> -#include <alloca.h> -#include <endian.h> - - -/* A good size for the initial read from memory, if it's not too costly. - This more than covers the phdrs and note segment in the average 64-bit - binary. */ - -#define INITIAL_READ 1024 - -#if __BYTE_ORDER == __LITTLE_ENDIAN -# define MY_ELFDATA ELFDATA2LSB -#else -# define MY_ELFDATA ELFDATA2MSB -#endif - - -/* Return user segment index closest to ADDR but not above it. - If NEXT, return the closest to ADDR but not below it. */ -static int -addr_segndx (Dwfl *dwfl, size_t segment, GElf_Addr addr, bool next) -{ - int ndx = -1; - do - { - if (dwfl->lookup_segndx[segment] >= 0) - ndx = dwfl->lookup_segndx[segment]; - if (++segment >= dwfl->lookup_elts - 1) - return next ? ndx + 1 : ndx; - } - while (dwfl->lookup_addr[segment] < addr); - - if (next) - { - while (dwfl->lookup_segndx[segment] < 0) - if (++segment >= dwfl->lookup_elts - 1) - return ndx + 1; - ndx = dwfl->lookup_segndx[segment]; - } - - return ndx; -} - -int -dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, - Dwfl_Memory_Callback *memory_callback, - void *memory_callback_arg, - Dwfl_Module_Callback *read_eagerly, - void *read_eagerly_arg) -{ - size_t segment = ndx; - - if (segment >= dwfl->lookup_elts) - segment = dwfl->lookup_elts - 1; - - while (segment > 0 - && (dwfl->lookup_segndx[segment] > ndx - || dwfl->lookup_segndx[segment] == -1)) - --segment; - - while (dwfl->lookup_segndx[segment] < ndx) - if (++segment == dwfl->lookup_elts) - return 0; - - GElf_Addr start = dwfl->lookup_addr[segment]; - - inline bool segment_read (int segndx, - void **buffer, size_t *buffer_available, - GElf_Addr addr, size_t minread) - { - return ! (*memory_callback) (dwfl, segndx, buffer, buffer_available, - addr, minread, memory_callback_arg); - } - - inline void release_buffer (void **buffer, size_t *buffer_available) - { - if (*buffer != NULL) - (void) segment_read (-1, buffer, buffer_available, 0, 0); - } - - /* First read in the file header and check its sanity. */ - - void *buffer = NULL; - size_t buffer_available = INITIAL_READ; - - inline int finish (void) - { - release_buffer (&buffer, &buffer_available); - return ndx; - } - - if (segment_read (ndx, &buffer, &buffer_available, - start, sizeof (Elf64_Ehdr)) - || memcmp (buffer, ELFMAG, SELFMAG) != 0) - return finish (); - - inline bool read_portion (void **data, size_t *data_size, - GElf_Addr vaddr, size_t filesz) - { - if (vaddr - start + filesz > buffer_available - /* If we're in string mode, then don't consider the buffer we have - sufficient unless it contains the terminator of the string. */ - || (filesz == 0 && memchr (vaddr - start + buffer, '\0', - buffer_available - (vaddr - start)) == NULL)) - { - *data = NULL; - *data_size = filesz; - return segment_read (addr_segndx (dwfl, segment, vaddr, false), - data, data_size, vaddr, filesz); - } - - /* We already have this whole note segment from our initial read. */ - *data = vaddr - start + buffer; - *data_size = 0; - return false; - } - - inline void finish_portion (void **data, size_t *data_size) - { - if (*data_size != 0) - release_buffer (data, data_size); - } - - /* Extract the information we need from the file header. */ - union - { - Elf32_Ehdr e32; - Elf64_Ehdr e64; - } ehdr; - GElf_Off phoff; - uint_fast16_t phnum; - uint_fast16_t phentsize; - GElf_Off shdrs_end; - Elf_Data xlatefrom = - { - .d_type = ELF_T_EHDR, - .d_buf = (void *) buffer, - .d_version = EV_CURRENT, - }; - Elf_Data xlateto = - { - .d_type = ELF_T_EHDR, - .d_buf = &ehdr, - .d_size = sizeof ehdr, - .d_version = EV_CURRENT, - }; - switch (((const unsigned char *) buffer)[EI_CLASS]) - { - case ELFCLASS32: - xlatefrom.d_size = sizeof (Elf32_Ehdr); - if (elf32_xlatetom (&xlateto, &xlatefrom, - ((const unsigned char *) buffer)[EI_DATA]) == NULL) - return finish (); - phoff = ehdr.e32.e_phoff; - phnum = ehdr.e32.e_phnum; - phentsize = ehdr.e32.e_phentsize; - if (phentsize != sizeof (Elf32_Phdr)) - return finish (); - shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize; - break; - - case ELFCLASS64: - xlatefrom.d_size = sizeof (Elf64_Ehdr); - if (elf64_xlatetom (&xlateto, &xlatefrom, - ((const unsigned char *) buffer)[EI_DATA]) == NULL) - return finish (); - phoff = ehdr.e64.e_phoff; - phnum = ehdr.e64.e_phnum; - phentsize = ehdr.e64.e_phentsize; - if (phentsize != sizeof (Elf64_Phdr)) - return finish (); - shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize; - break; - - default: - return finish (); - } - - /* The file header tells where to find the program headers. - These are what we need to find the boundaries of the module. - Without them, we don't have a module to report. */ - - if (phnum == 0) - return finish (); - - xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR; - xlatefrom.d_size = phnum * phentsize; - - void *ph_buffer = NULL; - size_t ph_buffer_size = 0; - if (read_portion (&ph_buffer, &ph_buffer_size, - start + phoff, xlatefrom.d_size)) - return finish (); - - xlatefrom.d_buf = ph_buffer; - - union - { - Elf32_Phdr p32[phnum]; - Elf64_Phdr p64[phnum]; - } phdrs; - - xlateto.d_buf = &phdrs; - xlateto.d_size = sizeof phdrs; - - /* Track the bounds of the file visible in memory. */ - GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end. */ - GElf_Off file_end = 0; /* Rounded up to effective page size. */ - GElf_Off contiguous = 0; /* Visible as contiguous file from START. */ - GElf_Off total_filesz = 0; /* Total size of data to read. */ - - /* Collect the bias between START and the containing PT_LOAD's p_vaddr. */ - GElf_Addr bias = 0; - bool found_bias = false; - - /* Collect the unbiased bounds of the module here. */ - GElf_Addr module_start = -1l; - GElf_Addr module_end = 0; - GElf_Addr module_address_sync = 0; - - /* If we see PT_DYNAMIC, record it here. */ - GElf_Addr dyn_vaddr = 0; - GElf_Xword dyn_filesz = 0; - - /* Collect the build ID bits here. */ - void *build_id = NULL; - size_t build_id_len = 0; - GElf_Addr build_id_vaddr = 0; - - /* Consider a PT_NOTE we've found in the image. */ - inline void consider_notes (GElf_Addr vaddr, GElf_Xword filesz) - { - /* If we have already seen a build ID, we don't care any more. */ - if (build_id != NULL || filesz == 0) - return; - - void *data; - size_t data_size; - if (read_portion (&data, &data_size, vaddr, filesz)) - return; - - assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr)); - - void *notes; - if (ehdr.e32.e_ident[EI_DATA] == MY_ELFDATA) - notes = data; - else - { - notes = malloc (filesz); - if (unlikely (notes == NULL)) - return; - xlatefrom.d_type = xlateto.d_type = ELF_T_NHDR; - xlatefrom.d_buf = (void *) data; - xlatefrom.d_size = filesz; - xlateto.d_buf = notes; - xlateto.d_size = filesz; - if (elf32_xlatetom (&xlateto, &xlatefrom, - ehdr.e32.e_ident[EI_DATA]) == NULL) - goto done; - } - - const GElf_Nhdr *nh = notes; - while ((const void *) nh < (const void *) notes + filesz) - { - const void *note_name = nh + 1; - const void *note_desc = note_name + NOTE_ALIGN (nh->n_namesz); - if (unlikely ((size_t) ((const void *) notes + filesz - - note_desc) < nh->n_descsz)) - break; - - if (nh->n_type == NT_GNU_BUILD_ID - && nh->n_descsz > 0 - && nh->n_namesz == sizeof "GNU" - && !memcmp (note_name, "GNU", sizeof "GNU")) - { - build_id_vaddr = note_desc - (const void *) notes + vaddr; - build_id_len = nh->n_descsz; - build_id = malloc (nh->n_descsz); - if (likely (build_id != NULL)) - memcpy (build_id, note_desc, build_id_len); - break; - } - - nh = note_desc + NOTE_ALIGN (nh->n_descsz); - } - - done: - if (notes != data) - free (notes); - finish_portion (&data, &data_size); - } - - /* Consider each of the program headers we've read from the image. */ - inline void consider_phdr (GElf_Word type, - GElf_Addr vaddr, GElf_Xword memsz, - GElf_Off offset, GElf_Xword filesz, - GElf_Xword align) - { - switch (type) - { - case PT_DYNAMIC: - dyn_vaddr = vaddr; - dyn_filesz = filesz; - break; - - case PT_NOTE: - /* We calculate from the p_offset of the note segment, - because we don't yet know the bias for its p_vaddr. */ - consider_notes (start + offset, filesz); - break; - - case PT_LOAD: - align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1; - - GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align; - GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end; - GElf_Off filesz_offset = filesz_vaddr - vaddr + offset; - - if (file_trimmed_end < offset + filesz) - { - file_trimmed_end = offset + filesz; - - /* Trim the last segment so we don't bother with zeros - in the last page that are off the end of the file. - However, if the extra bit in that page includes the - section headers, keep them. */ - if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end) - { - filesz += shdrs_end - file_trimmed_end; - file_trimmed_end = shdrs_end; - } - } - - total_filesz += filesz; - - if (file_end < filesz_offset) - { - file_end = filesz_offset; - if (filesz_vaddr - start == filesz_offset) - contiguous = file_end; - } - - if (!found_bias && (offset & -align) == 0 - && likely (filesz_offset >= phoff + phnum * phentsize)) - { - bias = start - vaddr; - found_bias = true; - } - - if ((vaddr & -align) < module_start) - { - module_start = vaddr & -align; - module_address_sync = vaddr + memsz; - } - - if (module_end < vaddr_end) - module_end = vaddr_end; - break; - } - } - if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) - { - if (elf32_xlatetom (&xlateto, &xlatefrom, - ehdr.e32.e_ident[EI_DATA]) == NULL) - found_bias = false; /* Trigger error check. */ - else - for (uint_fast16_t i = 0; i < phnum; ++i) - consider_phdr (phdrs.p32[i].p_type, - phdrs.p32[i].p_vaddr, phdrs.p32[i].p_memsz, - phdrs.p32[i].p_offset, phdrs.p32[i].p_filesz, - phdrs.p32[i].p_align); - } - else - { - if (elf64_xlatetom (&xlateto, &xlatefrom, - ehdr.e32.e_ident[EI_DATA]) == NULL) - found_bias = false; /* Trigger error check. */ - else - for (uint_fast16_t i = 0; i < phnum; ++i) - consider_phdr (phdrs.p64[i].p_type, - phdrs.p64[i].p_vaddr, phdrs.p64[i].p_memsz, - phdrs.p64[i].p_offset, phdrs.p64[i].p_filesz, - phdrs.p64[i].p_align); - } - - finish_portion (&ph_buffer, &ph_buffer_size); - - /* We must have seen the segment covering offset 0, or else the ELF - header we read at START was not produced by these program headers. */ - if (unlikely (!found_bias)) - return finish (); - - /* Now we know enough to report a module for sure: its bounds. */ - module_start += bias; - module_end += bias; - - dyn_vaddr += bias; - - /* Our return value now says to skip the segments contained - within the module. */ - ndx = addr_segndx (dwfl, segment, module_end, true); - - /* Examine its .dynamic section to get more interesting details. - If it has DT_SONAME, we'll use that as the module name. - If it has a DT_DEBUG, then it's actually a PIE rather than a DSO. - We need its DT_STRTAB and DT_STRSZ to decipher DT_SONAME, - and they also tell us the essential portion of the file - for fetching symbols. */ - GElf_Addr soname_stroff = 0; - GElf_Addr dynstr_vaddr = 0; - GElf_Xword dynstrsz = 0; - bool execlike = false; - inline bool consider_dyn (GElf_Sxword tag, GElf_Xword val) - { - switch (tag) - { - default: - return false; - - case DT_DEBUG: - execlike = true; - break; - - case DT_SONAME: - soname_stroff = val; - break; - - case DT_STRTAB: - dynstr_vaddr = val; - break; - - case DT_STRSZ: - dynstrsz = val; - break; - } - - return soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0; - } - - const size_t dyn_entsize = (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32 - ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn)); - void *dyn_data = NULL; - size_t dyn_data_size = 0; - if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0 - && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz)) - { - union - { - Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)]; - Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)]; - } dyn; - - xlatefrom.d_type = xlateto.d_type = ELF_T_DYN; - xlatefrom.d_buf = (void *) dyn_data; - xlatefrom.d_size = dyn_filesz; - xlateto.d_buf = &dyn; - xlateto.d_size = sizeof dyn; - - if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) - { - if (elf32_xlatetom (&xlateto, &xlatefrom, - ehdr.e32.e_ident[EI_DATA]) != NULL) - for (size_t i = 0; i < dyn_filesz / sizeof dyn.d32[0]; ++i) - if (consider_dyn (dyn.d32[i].d_tag, dyn.d32[i].d_un.d_val)) - break; - } - else - { - if (elf64_xlatetom (&xlateto, &xlatefrom, - ehdr.e32.e_ident[EI_DATA]) != NULL) - for (size_t i = 0; i < dyn_filesz / sizeof dyn.d64[0]; ++i) - if (consider_dyn (dyn.d64[i].d_tag, dyn.d64[i].d_un.d_val)) - break; - } - } - finish_portion (&dyn_data, &dyn_data_size); - - /* We'll use the name passed in or a stupid default if not DT_SONAME. */ - if (name == NULL) - name = ehdr.e32.e_type == ET_EXEC ? "[exe]" : execlike ? "[pie]" : "[dso]"; - - void *soname = NULL; - size_t soname_size = 0; - if (dynstrsz != 0 && dynstr_vaddr != 0) - { - /* We know the bounds of the .dynstr section. - - The DYNSTR_VADDR pointer comes from the .dynamic section - (DT_STRTAB, detected above). Ordinarily the dynamic linker - will have adjusted this pointer in place so it's now an - absolute address. But sometimes .dynamic is read-only (in - vDSOs and odd architectures), and sometimes the adjustment - just hasn't happened yet in the memory image we looked at. - So treat DYNSTR_VADDR as an absolute address if it falls - within the module bounds, or try applying the phdr bias - when that adjusts it to fall within the module bounds. */ - - if ((dynstr_vaddr < module_start || dynstr_vaddr >= module_end) - && dynstr_vaddr + bias >= module_start - && dynstr_vaddr + bias < module_end) - dynstr_vaddr += bias; - - if (unlikely (dynstr_vaddr + dynstrsz > module_end)) - dynstrsz = 0; - - /* Try to get the DT_SONAME string. */ - if (soname_stroff != 0 && soname_stroff + 1 < dynstrsz - && ! read_portion (&soname, &soname_size, - dynstr_vaddr + soname_stroff, 0)) - name = soname; - } - - /* Now that we have chosen the module's name and bounds, report it. - If we found a build ID, report that too. */ - - Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, name, - module_start, module_end); - if (likely (mod != NULL) && build_id != NULL - && unlikely (INTUSE(dwfl_module_report_build_id) (mod, - build_id, - build_id_len, - build_id_vaddr))) - { - mod->gc = true; - mod = NULL; - } - - /* At this point we do not need BUILD_ID or NAME any more. - They have been copied. */ - free (build_id); - finish_portion (&soname, &soname_size); - - if (unlikely (mod == NULL)) - { - ndx = -1; - return finish (); - } - - /* We have reported the module. Now let the caller decide whether we - should read the whole thing in right now. */ - - const GElf_Off cost = (contiguous < file_trimmed_end ? total_filesz - : buffer_available >= contiguous ? 0 - : contiguous - buffer_available); - const GElf_Off worthwhile = ((dynstr_vaddr == 0 || dynstrsz == 0) ? 0 - : dynstr_vaddr + dynstrsz - start); - const GElf_Off whole = MAX (file_trimmed_end, shdrs_end); - - Elf *elf = NULL; - if ((*read_eagerly) (MODCB_ARGS (mod), &buffer, &buffer_available, - cost, worthwhile, whole, contiguous, - read_eagerly_arg, &elf) - && elf == NULL) - { - /* The caller wants to read the whole file in right now, but hasn't - done it for us. Fill in a local image of the virtual file. */ - - void *contents = calloc (1, file_trimmed_end); - if (unlikely (contents == NULL)) - return finish (); - - inline void final_read (size_t offset, GElf_Addr vaddr, size_t size) - { - void *into = contents + offset; - size_t read_size = size; - (void) segment_read (addr_segndx (dwfl, segment, vaddr, false), - &into, &read_size, vaddr, size); - } - - if (contiguous < file_trimmed_end) - { - /* We can't use the memory image verbatim as the file image. - So we'll be reading into a local image of the virtual file. */ - - inline void read_phdr (GElf_Word type, GElf_Addr vaddr, - GElf_Off offset, GElf_Xword filesz) - { - if (type == PT_LOAD) - final_read (offset, vaddr + bias, filesz); - } - - if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) - for (uint_fast16_t i = 0; i < phnum; ++i) - read_phdr (phdrs.p32[i].p_type, phdrs.p32[i].p_vaddr, - phdrs.p32[i].p_offset, phdrs.p32[i].p_filesz); - else - for (uint_fast16_t i = 0; i < phnum; ++i) - read_phdr (phdrs.p64[i].p_type, phdrs.p64[i].p_vaddr, - phdrs.p64[i].p_offset, phdrs.p64[i].p_filesz); - } - else - { - /* The whole file sits contiguous in memory, - but the caller didn't want to just do it. */ - - const size_t have = MIN (buffer_available, file_trimmed_end); - memcpy (contents, buffer, have); - - if (have < file_trimmed_end) - final_read (have, start + have, file_trimmed_end - have); - } - - elf = elf_memory (contents, file_trimmed_end); - if (unlikely (elf == NULL)) - free (contents); - else - elf->flags |= ELF_F_MALLOCED; - } - - if (elf != NULL) - { - /* Install the file in the module. */ - mod->main.elf = elf; - mod->main.vaddr = module_start - bias; - mod->main.address_sync = module_address_sync; - mod->main_bias = bias; - } - - return finish (); -} diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index 5aaa778..036f1e4 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -108,8 +108,6 @@ struct Dwfl GElf_Off lookup_tail_vaddr; GElf_Off lookup_tail_offset; int lookup_tail_ndx; - - char *executable_for_core; /* --executable if --core was specified. */ };
#define OFFLINE_REDZONE 0x10000 @@ -442,9 +440,7 @@ typedef bool Dwfl_Module_Callback (Dwfl_Module *mod, void **userdata, */ extern int dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, Dwfl_Memory_Callback *memory_callback, - void *memory_callback_arg, - Dwfl_Module_Callback *read_eagerly, - void *read_eagerly_arg); + void *memory_callback_arg);
/* Report a module for entry in the dynamic linker's struct link_map list. For each link_map entry, if an existing module resides at its address, diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c index 00913fe..489319b 100644 --- a/libdwfl/link_map.c +++ b/libdwfl/link_map.c @@ -388,11 +388,21 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata, if (name != NULL && mod->main.name == NULL) mod->main.name = strdup (name); } - else if (name != NULL) + else { /* We have to find the file's phdrs to compute along with l_addr what its runtime address boundaries are. */
+ if (name == NULL) + switch (iterations) + { + case 1: + name = "[exe]"; + break; + case 2: + name = "[vdso]"; + break; + } // XXX hook for sysroot mod = INTUSE(dwfl_report_elf) (dwfl, basename (name), name, -1, l_addr); diff --git a/tests/Makefile.am b/tests/Makefile.am index 9b0bbf1..a1cd64b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -196,7 +196,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ testfile69.core.bz2 testfile69.so.bz2 \ testfile70.core.bz2 testfile70.exec.bz2 \ run-dwfllines.sh run-dwfl-report-elf-align.sh \ - testfile-dwfl-report-elf-align-shlib.so.bz2 + testfile-dwfl-report-elf-align-shlib.so.bz2 \ + test-core-lib.so.bz2 test-core.core.bz2 test-core.exec.bz2
if USE_VALGRIND valgrind_cmd="valgrind -q --trace-children=yes --error-exitcode=1 --run-libc-freeres=no" diff --git a/tests/run-addrname-test.sh b/tests/run-addrname-test.sh index 99abf9d..dd6a8f0 100755 --- a/tests/run-addrname-test.sh +++ b/tests/run-addrname-test.sh @@ -292,6 +292,12 @@ l0local2 ??:0 EOF
+testfiles test-core-lib.so test-core.core test-core.exec +testrun_compare ../src/addr2line -S -e test-core.exec --core=test-core.core 0x7f67f2aaf619 <<\EOF +libfunc+0x9 +??:0 +EOF + testfiles testfile65 testrun_compare ../src/addr2line -S --core=testfile65 0x7fff94bffa30 <<\EOF __vdso_time diff --git a/tests/test-core-lib.so.bz2 b/tests/test-core-lib.so.bz2 new file mode 100755 index 0000000..bb2da88 Binary files /dev/null and b/tests/test-core-lib.so.bz2 differ diff --git a/tests/test-core.core.bz2 b/tests/test-core.core.bz2 new file mode 100644 index 0000000..4d4346b Binary files /dev/null and b/tests/test-core.core.bz2 differ diff --git a/tests/test-core.exec.bz2 b/tests/test-core.exec.bz2 new file mode 100755 index 0000000..49ce551 Binary files /dev/null and b/tests/test-core.exec.bz2 differ
elfutils-devel@lists.fedorahosted.org