- Drop obsoleted `gdb-archer-pie-0315-breakpoint_address_match.patch'.

- Do not consider memory error on reading _r_debug->r_map as fatal (BZ
    576742).
- PIE: Attach binary even after re-prelinked underneath.
- PIE: Attach binary even after ld.so re-prelinked underneath.
- PIE: Fix occasional error attaching i686 binary (BZ 576742).
- testsuite: Fix unstable results of gdb.base/prelink.exp.
This commit is contained in:
Jan Kratochvil 2010-03-29 17:54:39 +00:00
parent 2770a5f431
commit 7b8bd72d9a
8 changed files with 1079 additions and 81 deletions

View File

@ -0,0 +1,68 @@
http://sourceware.org/ml/gdb-patches/2010-03/msg01006.html
Subject: [patch or FYI] testsuite: Fix prelink.exp on system w/unprelinked system libs
Hi,
this is a more conservative variant superseded by:
[patch 4/6] testsuite: Unify to lib/prelink-support.exp
http://sourceware.org/ml/gdb-patches/2010-03/msg01002.html
where gdb.base/prelink.exp is reworked on generic lib/prelink-support.exp.
I prefer the [patch 4/6] over this patch but this mail can serve also as an
illustration of the current problem.
------------------------------------------------------------------------------
If your system for some reason currently does not have all the libraries
prelinked gdb.base/prelink.exp will get UNRESOLVED randomly also affecting
testsuite results diff.
Apparently the testcase already tried to avoid any system libraries
dependencies by "-nodefaultlibs". But currently it does has not worked that
way.
"-lm" is contained already even in dejagnu's default_target_compile (not just
in gdb/testsuite/lib/ada.exp). But I do not know why it is there and which
systems would get broken by some global gdb/testsuite/ "-lm" removal.
Thanks,
Jan
2010-03-29 Jan Kratochvil <jan.kratochvil@redhat.com>
Fix testcase false UNRESOLVED if system libraries are not prelinked.
* gdb.base/prelink.exp: New variables compile, board, err and mathlib.
Set clear board mathlib for ${libfile} compilation.
--- a/gdb/testsuite/gdb.base/prelink.exp
+++ b/gdb/testsuite/gdb.base/prelink.exp
@@ -42,7 +42,25 @@ set testfile "prelink"
set libsrcfile ${testfile}-lib.c
set libfile ${objdir}/${subdir}/${testfile}.so
-if { [gdb_compile "${srcdir}/${subdir}/${libsrcfile}" "${libfile}" executable [list debug "additional_flags=-fpic -shared -nodefaultlibs"]] != ""} {
+
+# default_target_compile would otherwise add "-lm" making the testcase
+# dependent on whether the system libraries are already prelinked.
+# prelink: Could not set /lib64/libm-2.11.1.so owner or mode: Operation not permitted
+set compile {
+ gdb_compile "${srcdir}/${subdir}/${libsrcfile}" "${libfile}" executable [list debug "additional_flags=-fpic -shared -nodefaultlibs"]
+}
+set board [target_info name]
+if [board_info $board exists mathlib] {
+ set mathlib [board_info $dest mathlib]
+ set_board_info mathlib ""
+ set err [eval $compile]
+ set_board_info mathlib $mathlib
+} else {
+ set_board_info mathlib ""
+ set err [eval $compile]
+ unset_board_info mathlib
+}
+if {$err != ""} {
# If creating the shared library fails, maybe we don't have the right tools
return -1
}

View File

@ -1,77 +0,0 @@
[ Forward-ported context. ]
http://sourceware.org/ml/gdb-patches/2009-11/msg00170.html
Subject: [patch 03/15] PIE: breakpoint_address_match gdbarch_addr_bit workaround
Hi,
there are already multiple cases of CORE_ADDR being masked by the width of
gdbarch_addr_bit. This specific new case was required the PIE support.
Please read the C comment in attached patch.
Checked that CORE_ADDR math operations are present on 6000+ lines of code of
GDB sources which makes it impossible to do some general fix by replacing all
a->addr < b->addr
by
addr_less_than (a->addr, b->addr)
etc.
Even with this patch I think there are still many bugs left in the operation
of x86_64 gdb debugging i386 targets. Do you find the C++ way as a viable
one?
Thanks,
Jan
gdb/
* breakpoint.c (breakpoint_address_match): New variables addr_bit and
addr_mask, initialize it. Mask addresses by ADDR_MASK.
* defs.h (CORE_ADDR): Extend the comment.
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -4559,9 +4559,15 @@ static int
breakpoint_address_match (struct address_space *aspace1, CORE_ADDR addr1,
struct address_space *aspace2, CORE_ADDR addr2)
{
+ int addr_bit = gdbarch_addr_bit (target_gdbarch);
+ CORE_ADDR addr_mask = CORE_ADDR_MAX;
+
+ if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
+ addr_mask = ((CORE_ADDR) 1 << addr_bit) - 1;
+
return ((gdbarch_has_global_breakpoints (target_gdbarch)
|| aspace1 == aspace2)
- && addr1 == addr2);
+ && (addr1 & addr_mask) == (addr2 & addr_mask));
}
/* Assuming LOC1 and LOC2's types' have meaningful target addresses
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -98,7 +98,20 @@
/* A byte from the program being debugged. */
typedef bfd_byte gdb_byte;
-/* An address in the program being debugged. Host byte order. */
+/* An address in the program being debugged. Host byte order.
+
+ Its width is the maximum width of all the supported targets. That means
+ 32-bit target will run on such GDB using 64-bit CORE_ADDR cluttering the
+ bits 32...63 with random data from internal GDB calculations. GDB currently
+ in general truncates the address width only when it is being presented/used
+ externally (such as by the paddress function).
+
+ FIXME: This is still not right as any GDB internal comparisons (such as >=)
+ of CORE_ADDR do not use the properly truncated width. As converting all the
+ CORE_ADDR operations to width-aware functions is not feasible the way out
+ could be a width-aware C++ class CORE_ADDR referencing gdbarch as its
+ constructor parameter. */
+
typedef bfd_vma CORE_ADDR;
/* The largest CORE_ADDR value. */

View File

@ -0,0 +1,443 @@
http://sourceware.org/ml/gdb-patches/2010-03/msg01008.html
Subject: [patch 1/6]: PIE: Attach binary even after re-prelinked underneath
Hi,
there is a regression (against previous unreleased commits) by:
Re: RFC: Verify AT_ENTRY before using it
http://sourceware.org/ml/gdb-patches/2010-03/msg00395.html
for loading PIE executables which have changed on the disk since started.
There are in fact 3 different addresses one has to properly deal with.
This patch uses explicit "file" so it is not dependent on pending:
[patch] Attach to running but deleted executable
http://sourceware.org/ml/gdb-patches/2010-03/msg00950.html
The two copy-pasted blocks for elf32 and elf64 are "not nice" but this is the
current style in GDB.
No regressions on {x86_64,x86_64-m32,i686}-fedora12-linux-gnu for the whole
patch series together.
Thanks,
Jan
gdb/
2010-03-29 Jan Kratochvil <jan.kratochvil@redhat.com>
Fix attaching to PIEs prelinked on the disk since their start.
* solib-svr4.c (svr4_exec_displacement): New variable arch_size.
Verify it against bfd_get_arch_size. Try to match arbitrary
displacement for the phdrs comparison.
gdb/testsuite/
2010-03-29 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.base/break-interp.exp: Run $binpie with new value "ATTACH", new
code for it. New variable relink_args.
(prelinkYES): Call prelinkNO.
(test_attach): Accept new parameter relink_args. Re-prelink the binary
in such case. Move the core code to ...
(test_attach_gdb): ... a new function. Send GDB command "file".
Extend expected "Attaching to " string.
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -1750,13 +1750,183 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
really do not match. */
int phdrs_size, phdrs2_size, ok = 1;
gdb_byte *buf, *buf2;
+ int arch_size;
- buf = read_program_header (-1, &phdrs_size, NULL);
+ buf = read_program_header (-1, &phdrs_size, &arch_size);
buf2 = read_program_headers_from_bfd (exec_bfd, &phdrs2_size);
- if (buf != NULL && buf2 != NULL
- && (phdrs_size != phdrs2_size
- || memcmp (buf, buf2, phdrs_size) != 0))
- ok = 0;
+ if (buf != NULL && buf2 != NULL)
+ {
+ enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
+
+ /* We are dealing with three different addresses. EXEC_BFD
+ represents current address in on-disk file. target memory content
+ may be different from EXEC_BFD as the file may have been prelinked
+ to a different address since the executable has been loaded.
+ Moreover the address of placement in target memory can be
+ different from what say the target memory program headers - this
+ is the goal of PIE.
+
+ Detected DISPLACEMENT covers both the offsets of PIE placement and
+ possible new prelink since start of the program. Here relocate
+ BUF and BUF2 just by the EXEC_BFD vs. target memory content offset
+ for the verification purpose. */
+
+ if (phdrs_size != phdrs2_size
+ || bfd_get_arch_size (exec_bfd) != arch_size)
+ ok = 0;
+ else if (arch_size == 32 && phdrs_size >= sizeof (Elf32_External_Phdr)
+ && phdrs_size % sizeof (Elf32_External_Phdr) == 0)
+ {
+ Elf_Internal_Ehdr *ehdr2 = elf_tdata (exec_bfd)->elf_header;
+ Elf_Internal_Phdr *phdr2 = elf_tdata (exec_bfd)->phdr;
+ CORE_ADDR displacement = 0;
+ int i;
+
+ /* DISPLACEMENT could be found easier by the difference of
+ ehdr2->e_entry but already read BUF does not contain ehdr. */
+
+ for (i = 0; i < ehdr2->e_phnum; i++)
+ if (phdr2[i].p_type == PT_LOAD)
+ {
+ Elf32_External_Phdr *phdrp;
+ gdb_byte *buf_vaddr_p, *buf_paddr_p;
+ CORE_ADDR vaddr, paddr;
+ CORE_ADDR displacement_vaddr = 0;
+ CORE_ADDR displacement_paddr = 0;
+
+ phdrp = &((Elf32_External_Phdr *) buf)[i];
+ buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
+ buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
+
+ vaddr = extract_unsigned_integer (buf_vaddr_p, 4,
+ byte_order);
+ displacement_vaddr = vaddr - phdr2[i].p_vaddr;
+
+ paddr = extract_unsigned_integer (buf_paddr_p, 4,
+ byte_order);
+ displacement_paddr = paddr - phdr2[i].p_paddr;
+
+ if (displacement_vaddr == displacement_paddr)
+ displacement = displacement_vaddr;
+
+ break;
+ }
+
+ /* Now compare BUF and BUF2 with optional DISPLACEMENT. */
+
+ for (i = 0; i < phdrs_size / sizeof (Elf32_External_Phdr); i++)
+ {
+ Elf32_External_Phdr *phdrp;
+ Elf32_External_Phdr *phdr2p;
+ gdb_byte *buf_vaddr_p, *buf_paddr_p;
+ CORE_ADDR vaddr, paddr;
+
+ phdrp = &((Elf32_External_Phdr *) buf)[i];
+ buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
+ buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
+ phdr2p = &((Elf32_External_Phdr *) buf2)[i];
+
+ /* PT_GNU_STACK addresses are left as zero not being
+ relocated by prelink, their displacing would create false
+ verification failure. Feel free to test the unrelocated
+ comparison for any segment type. */
+
+ if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0)
+ continue;
+
+ vaddr = extract_unsigned_integer (buf_vaddr_p, 4, byte_order);
+ vaddr -= displacement;
+ store_unsigned_integer (buf_vaddr_p, 4, byte_order, vaddr);
+
+ paddr = extract_unsigned_integer (buf_paddr_p, 4, byte_order);
+ paddr -= displacement;
+ store_unsigned_integer (buf_paddr_p, 4, byte_order, paddr);
+
+ if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0)
+ continue;
+
+ ok = 0;
+ break;
+ }
+ }
+ else if (arch_size == 64 && phdrs_size >= sizeof (Elf64_External_Phdr)
+ && phdrs_size % sizeof (Elf64_External_Phdr) == 0)
+ {
+ Elf_Internal_Ehdr *ehdr2 = elf_tdata (exec_bfd)->elf_header;
+ Elf_Internal_Phdr *phdr2 = elf_tdata (exec_bfd)->phdr;
+ CORE_ADDR displacement = 0;
+ int i;
+
+ /* DISPLACEMENT could be found easier by the difference of
+ ehdr2->e_entry but already read BUF does not contain ehdr. */
+
+ for (i = 0; i < ehdr2->e_phnum; i++)
+ if (phdr2[i].p_type == PT_LOAD)
+ {
+ Elf64_External_Phdr *phdrp;
+ gdb_byte *buf_vaddr_p, *buf_paddr_p;
+ CORE_ADDR vaddr, paddr;
+ CORE_ADDR displacement_vaddr = 0;
+ CORE_ADDR displacement_paddr = 0;
+
+ phdrp = &((Elf64_External_Phdr *) buf)[i];
+ buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
+ buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
+
+ vaddr = extract_unsigned_integer (buf_vaddr_p, 8,
+ byte_order);
+ displacement_vaddr = vaddr - phdr2[i].p_vaddr;
+
+ paddr = extract_unsigned_integer (buf_paddr_p, 8,
+ byte_order);
+ displacement_paddr = paddr - phdr2[i].p_paddr;
+
+ if (displacement_vaddr == displacement_paddr)
+ displacement = displacement_vaddr;
+
+ break;
+ }
+
+ /* Now compare BUF and BUF2 with optional DISPLACEMENT. */
+
+ for (i = 0; i < phdrs_size / sizeof (Elf64_External_Phdr); i++)
+ {
+ Elf64_External_Phdr *phdrp;
+ Elf64_External_Phdr *phdr2p;
+ gdb_byte *buf_vaddr_p, *buf_paddr_p;
+ CORE_ADDR vaddr, paddr;
+
+ phdrp = &((Elf64_External_Phdr *) buf)[i];
+ buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
+ buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
+ phdr2p = &((Elf64_External_Phdr *) buf2)[i];
+
+ /* PT_GNU_STACK addresses are left as zero not being
+ relocated by prelink, their displacing would create false
+ verification failure. Feel free to test the unrelocated
+ comparison for any segment type. */
+
+ if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0)
+ continue;
+
+ vaddr = extract_unsigned_integer (buf_vaddr_p, 8, byte_order);
+ vaddr -= displacement;
+ store_unsigned_integer (buf_vaddr_p, 8, byte_order, vaddr);
+
+ paddr = extract_unsigned_integer (buf_paddr_p, 8, byte_order);
+ paddr -= displacement;
+ store_unsigned_integer (buf_paddr_p, 8, byte_order, paddr);
+
+ if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0)
+ continue;
+
+ ok = 0;
+ break;
+ }
+ }
+ else
+ ok = 0;
+ }
xfree (buf);
xfree (buf2);
--- a/gdb/testsuite/gdb.base/break-interp.exp
+++ b/gdb/testsuite/gdb.base/break-interp.exp
@@ -154,6 +154,12 @@ proc prelinkYES {arg {name ""}} {
if {$name == ""} {
set name [file tail $arg]
}
+
+ # Try to unprelink it first so that if it has been already prelinked before
+ # we get different address now and the result is not affected by the
+ # previous $arg state..
+ prelinkNO $arg "$name pre-unprelink"
+
set test "prelink $name"
set command "exec /usr/sbin/prelink -qNR --no-exec-shield $arg"
verbose -log "command is $command"
@@ -319,38 +325,12 @@ proc test_core {file displacement} {
set pf_prefix $old_ldprefix
}
-proc test_attach {file displacement} {
- global board_info gdb_prompt expect_out
-
- gdb_exit
-
- set test "sleep function started"
-
- set command "${file} sleep"
- set res [remote_spawn host $command];
- if { $res < 0 || $res == "" } {
- perror "Spawning $command failed."
- fail $test
- return
- }
- set pid [exp_pid -i $res]
- gdb_expect {
- -re "sleeping\r\n" {
- pass $test
- }
- eof {
- fail "$test (eof)"
- return
- }
- timeout {
- fail "$test (timeout)"
- return
- }
- }
+proc test_attach_gdb {file pid displacement prefix} {
+ global gdb_prompt expect_out
global pf_prefix
set old_ldprefix $pf_prefix
- lappend pf_prefix "attach:"
+ lappend pf_prefix "$prefix:"
gdb_exit
gdb_start
@@ -358,9 +338,13 @@ proc test_attach {file displacement} {
# Print the "PIE (Position Independent Executable) displacement" message.
gdb_test "set verbose on"
+ if {$file != ""} {
+ gdb_test "file $file" "Reading symbols from .*done\\." "file"
+ }
+
set test "attach"
gdb_test_multiple "attach $pid" $test {
- -re "Attaching to process $pid\r\n" {
+ -re "Attaching to (program: .*, )?process $pid\r\n" {
# Missing "$gdb_prompt $" is intentional.
pass $test
}
@@ -396,11 +380,56 @@ proc test_attach {file displacement} {
gdb_test "bt" "#\[0-9\]+ +\[^\r\n\]*\\mlibfunc\\M\[^\r\n\]*\r\n#\[0-9\]+ +\[^\r\n\]*\\mmain\\M.*" "attach main bt"
gdb_exit
- remote_exec host "kill -9 $pid"
-
set pf_prefix $old_ldprefix
}
+proc test_attach {file displacement {relink_args ""}} {
+ global board_info
+
+ gdb_exit
+
+ set test "sleep function started"
+
+ set command "${file} sleep"
+ set res [remote_spawn host $command];
+ if { $res < 0 || $res == "" } {
+ perror "Spawning $command failed."
+ fail $test
+ return
+ }
+ set pid [exp_pid -i $res]
+ gdb_expect {
+ -re "sleeping\r\n" {
+ pass $test
+ }
+ eof {
+ fail "$test (eof)"
+ return
+ }
+ timeout {
+ fail "$test (timeout)"
+ return
+ }
+ }
+
+ if {$relink_args == ""} {
+ test_attach_gdb "" $pid $displacement "attach"
+ } else {
+ # These could be rather passed as arguments.
+ global exec interp_saved interp
+
+ foreach relink {YES NO} {
+ if {[prelink$relink $relink_args [file tail $exec]]
+ && [copy $interp_saved $interp]} {
+ # /proc/PID/exe cannot be loaded as it is "EXECNAME (deleted)".
+ test_attach_gdb $exec $pid $displacement "attach-relink$relink"
+ }
+ }
+ }
+
+ remote_exec host "kill -9 $pid"
+}
+
proc test_ld {file ifmain trynosym displacement} {
global srcdir subdir gdb_prompt expect_out
@@ -609,7 +638,10 @@ foreach ldprelink {NO YES} {
set old_binprefix $pf_prefix
foreach binprelink {NO YES} {
foreach binsepdebug {NO IN SEP} {
- foreach binpie {NO YES} {
+ # "ATTACH" is like "YES" but it is modified during run.
+ # It cannot be used for problem reproducibility after the
+ # testcase ends.
+ foreach binpie {NO YES ATTACH} {
# This combination is not possible, non-PIE (fixed address)
# binary cannot be prelinked to any (other) address.
if {$binprelink == "YES" && $binpie == "NO"} {
@@ -628,7 +660,7 @@ foreach ldprelink {NO YES} {
if {$binsepdebug != "NO"} {
lappend opts {debug}
}
- if {$binpie == "YES"} {
+ if {$binpie != "NO"} {
lappend opts {additional_flags=-fPIE -pie}
}
if {[build_executable ${test}.exp [file tail $exec] $srcfile $opts] == -1} {
@@ -680,16 +712,45 @@ foreach ldprelink {NO YES} {
lappend dests $dest
}
- if {[prelink$binprelink "--dynamic-linker=$interp --ld-library-path=$dir $exec $interp [concat $dests]" [file tail $exec]]
+ if {$binpie == "NO"} {
+ set displacement "NONE"
+ } elseif {$binprelink == "NO"} {
+ set displacement "NONZERO"
+ } else {
+ set displacement "ZERO"
+ }
+
+ set relink_args "--dynamic-linker=$interp --ld-library-path=$dir $exec $interp [concat $dests]"
+ if {[prelink$binprelink $relink_args [file tail $exec]]
&& [copy $interp_saved $interp]} {
- if {$binpie == "NO"} {
- set displacement "NONE"
- } elseif {$binprelink == "NO"} {
- set displacement "NONZERO"
+ if {$binpie != "ATTACH"} {
+ test_ld $exec 1 [expr {$binsepdebug == "NO"}] $displacement
} else {
- set displacement "ZERO"
+ # If the file has been randomly prelinked it must
+ # be "NONZERO". We could see "ZERO" only if it was
+ # unprelinked na it is now running at the same
+ # address - which is 0 but executable can never run
+ # at address 0.
+
+ set displacement "NONZERO"
+ test_attach $exec $displacement $relink_args
+
+ # ATTACH executables + libraries get modified since
+ # they have been run. They cannot be used for
+ # problem reproducibility after the testcase ends.
+ set exec_debug [system_debug_get $exec]
+ if {$exec_debug != ""} {
+ # `file delete [glob "${exec_debug}*"]' does not work.
+ foreach f [glob "${exec_debug}*"] {
+ file delete $f
+ }
+ }
+ file delete -force $dir
+ # `file delete [glob "${exec}*"]' does not work.
+ foreach f [glob "${exec}*"] {
+ file delete $f
+ }
}
- test_ld $exec 1 [expr {$binsepdebug == "NO"}] $displacement
}
}
}

View File

@ -0,0 +1,87 @@
http://sourceware.org/ml/gdb-patches/2010-03/msg01000.html
Subject: [patch 2/6] PIE: Attach binary even after ld.so re-prelinked underneath
Hi,
when I have seen the PIE-binary-changed-sice-start tested also
ld.so-changed-since-start and it did not work.
There is questionable when to print and when to not to print non-fatal memory
read errors. Similar change I requested in
Re: [RFC/ia64] memory error when reading wrong core file
http://sourceware.org/ml/gdb-patches/2010-02/msg00001.html
so that GDB prints at least as a warning
Cannot access memory at address ...
when some unexpected error happens.
Contrary to it there is not such warning present in the code below as in the
case of non-valgrind PIE with re-prelinked ld.so the memory read error happens
there. Some GDB code rework could probably avoid it.
Just for example all the memory read errors in read_program_header or even
- primarily - scan_dyntag are currently IMO-incorrectly silent and others.
Therefore posted the patch this way, making all these warnings printed and
possibly fixing code attempting incorrect reads along the way could be done by
a different patch.
No regressions on {x86_64,x86_64-m32,i686}-fedora12-linux-gnu for the whole
patch series together.
Thanks,
Jan
gdb/
2010-03-29 Jan Kratochvil <jan.kratochvil@redhat.com>
* auxv.c (ld_so_xfer_auxv): Do not error on failed read of data_address.
gdb/testsuite/
2010-03-29 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.base/break-interp.exp (test_attach): Keep $interp changed. Move
its restore after the <$relink_args != ""> loop. new comment.
--- a/gdb/auxv.c
+++ b/gdb/auxv.c
@@ -96,7 +96,16 @@ ld_so_xfer_auxv (gdb_byte *readbuf,
pointer_address = SYMBOL_VALUE_ADDRESS (msym);
- data_address = read_memory_typed_address (pointer_address, ptr_type);
+ /* While it is an error I am not aware how to solve attaching to PIE under
+ valgrind --db-attach=yes different way when ld.so on-disk file has prelink
+ change in the meantime. Currently GDB will drop back to procfs_xfer_auxv
+ (so that at least non-valgrind PIE attachments with prelink change of
+ ld.so work). To make it working even with valgrind is PR 11440 requiring
+ a valgrind extension. */
+ if (target_read_memory (pointer_address, ptr_buf, ptr_size) != 0)
+ return -1;
+
+ data_address = extract_typed_address (ptr_buf, ptr_type);
/* Possibly still not initialized such as during an inferior startup. */
if (data_address == 0)
--- a/gdb/testsuite/gdb.base/break-interp.exp
+++ b/gdb/testsuite/gdb.base/break-interp.exp
@@ -419,12 +419,16 @@ proc test_attach {file displacement {relink_args ""}} {
global exec interp_saved interp
foreach relink {YES NO} {
- if {[prelink$relink $relink_args [file tail $exec]]
- && [copy $interp_saved $interp]} {
+ # It would be more correct to also [copy $interp_saved $interp]
+ # here to really test just different prelink of $exec.
+ # But we would need a separate test for different prelink of ld.so
+ # where a bug occured. It is now all merged into this single test.
+ if [prelink$relink $relink_args [file tail $exec]] {
# /proc/PID/exe cannot be loaded as it is "EXECNAME (deleted)".
test_attach_gdb $exec $pid $displacement "attach-relink$relink"
}
}
+ copy $interp_saved $interp
}
remote_exec host "kill -9 $pid"

View File

@ -0,0 +1,412 @@
http://sourceware.org/ml/gdb-patches/2010-03/msg01001.html
Subject: [patch 3/6] PIE: Fix occasional error attaching i686 binary
[ Testcase diff backported. ]
Hi,
this is the real bugreport which started this patch series.
gdb "Cannot access memory" on a running process
https://bugzilla.redhat.com/show_bug.cgi?id=576742
Offsets on i686 cause that while attaching to an unprelinked running PIE
scan_dyntag will incorrectly get a successful read in scan_dyntag from DT_DEBUG
it expects is from the mani executable but in fact it is from some ld.so or
libc.so (located low for --exec-shield). Another issue is that scan_dyntag
could verify more that the target memory matches the .dynamic section it is
reading from exec_bfd. It could also complain when the read failed (as always
failed so for for PIE attaches first, succeeded later so nobody has noticed
anything).
The successful read reads a bogus DT_DEBUG value and GDB errors on it later.
This is again a non-fatal error after the patch by Joel Brobecker above but it
was not so before and it is incorrect anyway.
The svr4_relocate_main_executable call in svr4_special_symbol_handling was
there before delayed that way for svr4_static_exec_displacement.
But svr4_static_exec_displacement has been removed in the meantime by:
Re: RFC: Verify AT_ENTRY before using it
http://sourceware.org/ml/gdb-patches/2010-03/msg00030.html
So it can be simplified + corrected now. Moreover GDB will now finally print
exactly "Using PIE (Position Independent Executable) displacement" exactly
once.
The reproducer depends on various offsets which may be distro dependent but it
was made so that it is hopefully reproducible everywhere. Reproduced + fixed
on Fedora 12 x86_64 and i686.
No regressions on {x86_64,x86_64-m32,i686}-fedora12-linux-gnu for the whole
patch series together.
Thanks,
Jan
gdb/
2010-03-29 Jan Kratochvil <jan.kratochvil@redhat.com>
* auxv.c (memory_xfer_auxv): Update attach comment.
* solib-svr4.c (svr4_special_symbol_handling): Remove the call to
svr4_relocate_main_executable.
(svr4_solib_create_inferior_hook): Make the call to
svr4_relocate_main_executable unconditional.
gdb/testsuite/
2010-03-29 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.base/attach-pie-misread.exp, gdb.base/attach-pie-misread.c: New.
--- a/gdb/auxv.c
+++ b/gdb/auxv.c
@@ -198,7 +198,8 @@ memory_xfer_auxv (struct target_ops *ops,
/* ld_so_xfer_auxv is the only function safe for virtual executables being
executed by valgrind's memcheck. As using ld_so_xfer_auxv is problematic
- during inferior startup GDB does call it only for attached processes. */
+ during inferior startup as ld.so symbol tables are not yet relocated GDB
+ calls ld_so_xfer_auxv only for attached processes. */
if (current_inferior ()->attach_flag != 0)
{
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -1628,7 +1628,6 @@ enable_break (struct svr4_info *info, int from_tty)
static void
svr4_special_symbol_handling (void)
{
- svr4_relocate_main_executable ();
}
/* Read the ELF program headers from ABFD. Return the contents and
@@ -2065,8 +2064,7 @@ svr4_solib_create_inferior_hook (int from_tty)
info = get_svr4_info ();
/* Relocate the main executable if necessary. */
- if (current_inferior ()->attach_flag == 0)
- svr4_relocate_main_executable ();
+ svr4_relocate_main_executable ();
if (!svr4_have_link_map_offsets ())
return;
--- /dev/null
+++ b/gdb/testsuite/gdb.base/attach-pie-misread.c
@@ -0,0 +1,47 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2010 Free Software Foundation, Inc.
+
+ This program 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.
+
+ This program 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 <stdio.h>
+#include <unistd.h>
+
+const char stub[] = {
+#ifdef GEN
+# include GEN
+#endif
+};
+
+int
+main (int argc, char **argv)
+{
+ /* Generator of GEN written in Python takes about 15s for x86_64's 4MB. */
+ if (argc == 2)
+ {
+ long count = strtol (argv[1], NULL, 0);
+
+ while (count-- > 0)
+ puts ("0x55,");
+
+ return 0;
+ }
+ if (argc != 1)
+ return 1;
+
+ puts ("sleeping");
+ fflush (stdout);
+
+ return sleep (60);
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.base/attach-pie-misread.exp
@@ -0,0 +1,209 @@
+# Copyright 2010 Free Software Foundation, Inc.
+
+# This program 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.
+#
+# This program 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/>.
+
+# This test only works on GNU/Linux.
+if { ![isnative] || [is_remote host] || ![istarget *-linux*] || [skip_shlib_tests]} {
+ continue
+}
+
+set test "attach-pie-misread"
+set srcfile ${test}.c
+set genfile ${objdir}/${subdir}/${test}-gen.h
+set executable ${test}
+set binfile ${objdir}/${subdir}/${executable}
+
+if {[build_executable ${test}.exp $executable $srcfile [list "additional_flags=-fPIE -pie"]] == -1} {
+ return -1
+}
+
+# Program Headers:
+# Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+# LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x134f5ec 0x134f5ec R E 0x200000
+# LOAD 0x134f5f0 0x000000000194f5f0 0x000000000194f5f0 0x1dbc60 0x214088 RW 0x200000
+# DYNAMIC 0x134f618 0x000000000194f618 0x000000000194f618 0x000200 0x000200 RW 0x8
+#
+proc read_phdr {binfile test} {
+ set readelf_program [transform readelf]
+ set command "exec $readelf_program -Wl $binfile"
+ verbose -log "command is $command"
+ set result [catch $command output]
+ verbose -log "result is $result"
+ verbose -log "output is $output"
+ if {$result != 0} {
+ fail $test
+ return
+ }
+ if ![regexp {\nProgram Headers:\n *Type [^\n]* Align\n(.*?)\n\n} $output trash phdr] {
+ fail "$test (no Program Headers)"
+ return
+ }
+ if ![regexp -line {^ *DYNAMIC +0x[0-9a-f]+ +(0x[0-9a-f]+) } $phdr trash dynamic_vaddr] {
+ fail "$test (no DYNAMIC found)"
+ return
+ }
+ verbose -log "dynamic_vaddr is $dynamic_vaddr"
+ set align_max -1
+ foreach {trash align} [regexp -line -all -inline {^ *LOAD .* (0x[0-9]+)$} $phdr] {
+ if {$align_max < $align} {
+ set align_max $align
+ }
+ }
+ verbose -log "align_max is $align_max"
+ if {$align_max == -1} {
+ fail "$test (no LOAD found)"
+ return
+ }
+ pass $test
+ return [list $dynamic_vaddr $align_max]
+}
+
+set phdr [read_phdr $binfile "readelf initial scan"]
+set dynamic_vaddr [lindex $phdr 0]
+set align_max [lindex $phdr 1]
+
+set stub_size [format 0x%x [expr "2 * $align_max - ($dynamic_vaddr & ($align_max - 1))"]]
+verbose -log "stub_size is $stub_size"
+
+# On x86_64 it is commonly about 4MB.
+if {$stub_size > 25000000} {
+ xfail "stub size $stub_size is too large"
+ return
+}
+
+set test "generate stub"
+set command "exec $binfile $stub_size >$genfile"
+verbose -log "command is $command"
+set result [catch $command output]
+verbose -log "result is $result"
+verbose -log "output is $output"
+if {$result == 0} {
+ pass $test
+} else {
+ fail $test
+}
+
+if {[build_executable ${test}.exp $executable $srcfile [list "additional_flags=-fPIE -pie -DGEN=\"$genfile\""]] == -1} {
+ return -1
+}
+
+# x86_64 file has 25MB, no need to keep it.
+file delete -- $genfile
+
+set phdr [read_phdr $binfile "readelf rebuilt with stub_size"]
+set dynamic_vaddr_prelinkno [lindex $phdr 0]
+
+set command "exec /usr/sbin/prelink -q -N --no-exec-shield -R $binfile"
+verbose -log "command is $command"
+set result [catch $command output]
+verbose -log "result is $result"
+verbose -log "output is $output"
+
+set test "prelink -R"
+if {$result == 0 && $output == ""} {
+ pass $test
+} elseif {$result == 1 && [regexp {^(couldn't execute "/usr/sbin/prelink[^\r\n]*": no such file or directory\n?)*$} $output]} {
+ untested attach-pie-misread.exp
+ return -1
+} else {
+ fail $test
+}
+
+set phdr [read_phdr $binfile "readelf with prelink -R"]
+set dynamic_vaddr_prelinkyes [lindex $phdr 0]
+
+set first_offset [format 0x%x [expr $dynamic_vaddr_prelinkyes - $dynamic_vaddr_prelinkno]]
+verbose -log "first_offset is $first_offset"
+
+set test "first offset is non-zero"
+if {$first_offset == 0} {
+ fail "$test (-fPIE -pie in effect?)"
+} else {
+ pass $test
+}
+
+set test "start inferior"
+gdb_exit
+
+set res [remote_spawn host $binfile];
+if { $res < 0 || $res == "" } {
+ perror "Spawning $binfile failed."
+ fail $test
+ return
+}
+set pid [exp_pid -i $res]
+gdb_expect {
+ -re "sleeping\r\n" {
+ pass $test
+ }
+ eof {
+ fail "$test (eof)"
+ remote_exec host "kill -9 $pid"
+ return
+ }
+ timeout {
+ fail "$test (timeout)"
+ remote_exec host "kill -9 $pid"
+ return
+ }
+}
+
+# Due to alignments it was reproducible with 1 on x86_64 but 2 on i686.
+foreach align_mult {1 2} {
+ set old_ldprefix $pf_prefix
+ lappend pf_prefix "shift-by-$align_mult:"
+
+ # FIXME: We believe there is enough room under FIRST_OFFSET.
+ set shifted_offset [format 0x%x [expr "$first_offset - $align_mult * $align_max"]]
+ verbose -log "shifted_offset is $shifted_offset"
+
+ set command "exec /usr/sbin/prelink -q -N --no-exec-shield -r $shifted_offset $binfile"
+ verbose -log "command is $command"
+ set result [catch $command output]
+ verbose -log "result is $result"
+ verbose -log "output is $output"
+
+ set test "prelink -r"
+ if {$result == 0 && $output == ""} {
+ pass $test
+ } else {
+ fail $test
+ }
+
+ clean_restart $executable
+
+ set test "attach"
+ gdb_test_multiple "attach $pid" $test {
+ -re "Attaching to program: .*, process $pid\r\n" {
+ # Missing "$gdb_prompt $" is intentional.
+ pass $test
+ }
+ }
+
+ set test "error on Cannot access memory at address"
+ gdb_test_multiple "" $test {
+ -re "\r\nCannot access memory at address .*$gdb_prompt $" {
+ fail $test
+ }
+ -re "$gdb_prompt $" {
+ pass $test
+ }
+ }
+
+ gdb_test "detach" "Detaching from program: .*"
+
+ set pf_prefix $old_ldprefix
+}
+
+remote_exec host "kill -9 $pid"
--- a/gdb/testsuite/gdb.base/break-interp.exp
+++ b/gdb/testsuite/gdb.base/break-interp.exp
@@ -248,9 +248,8 @@ proc reach {func command displacement} {
}
if {$displacement == $case} {
pass $test_displacement
- # Permit multiple such messages.
set displacement "FOUND-$displacement"
- } elseif {$displacement != "FOUND-$case"} {
+ } else {
fail $test_displacement
}
exp_continue
@@ -304,9 +303,8 @@ proc test_core {file displacement} {
}
if {$displacement == $case} {
pass $test_displacement
- # Permit multiple such messages.
set displacement "FOUND-$displacement"
- } elseif {$displacement != "FOUND-$case"} {
+ } else {
fail $test_displacement
}
exp_continue
@@ -362,9 +360,8 @@ proc test_attach_gdb {file pid displacement prefix} {
}
if {$displacement == $case} {
pass $test_displacement
- # Permit multiple such messages.
set displacement "FOUND-$displacement"
- } elseif {$displacement != "FOUND-$case"} {
+ } else {
fail $test_displacement
}
exp_continue
@@ -451,9 +448,7 @@
gdb_test "bt" "#0 +\[^\r\n\]*\\mdl_main\\M.*" "dl bt"
if $ifmain {
- # Displacement message will be printed the second time on initializing
- # the linker from svr4_special_symbol_handling.
- reach "main" continue $displacement
+ reach "main" continue "NONE"
reach "libfunc" continue "NONE"
@@ -528,9 +517,8 @@ proc test_ld {file ifmain trynosym displacement} {
}
if {$displacement == $case} {
pass $test_displacement
- # Permit multiple such messages.
set displacement "FOUND-$displacement"
- } elseif {$displacement != "FOUND-$case"} {
+ } else {
fail $test_displacement
}
exp_continue

View File

@ -69,7 +69,7 @@ Index: gdb-7.0.50.20100115/gdb/testsuite/gdb.base/break-interp.exp
}
@@ -480,9 +500,33 @@ foreach ldprelink {NO YES} {
if {$binpie == "YES"} {
if {$binpie != "NO"} {
lappend opts {additional_flags=-fPIE -pie}
}
- if {[build_executable ${test}.exp [file tail $exec] $srcfile $opts] == -1} {

View File

@ -0,0 +1,41 @@
[RFC/ia64] memory error when reading wrong core file
http://sourceware.org/ml/gdb-patches/2010-01/msg00645.html
http://sourceware.org/ml/gdb-patches/2010-02/msg00001.html
http://sourceware.org/ml/gdb-patches/2010-03/msg00298.html
http://sourceware.org/ml/gdb-cvs/2010-03/msg00065.html
c961a8da422283662e09ee498c0598d48fc9d70f
--- src/gdb/solib-svr4.c 2010/02/24 00:29:02 1.125
+++ src/gdb/solib-svr4.c 2010/03/08 07:45:49 1.126
@@ -868,9 +868,16 @@
{
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
+ CORE_ADDR addr = 0;
+ volatile struct gdb_exception ex;
- return read_memory_typed_address (info->debug_base + lmo->r_map_offset,
- ptr_type);
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ addr = read_memory_typed_address (info->debug_base + lmo->r_map_offset,
+ ptr_type);
+ }
+ exception_print (gdb_stderr, ex);
+ return addr;
}
/* Find r_brk from the inferior's debug base. */
### src/gdb/ChangeLog 2010/03/08 01:49:30 1.11441
### src/gdb/ChangeLog 2010/03/08 07:45:49 1.11442
## -1,3 +1,10 @@
+2010-03-08 Joel Brobecker <brobecker@adacore.com>
+
+ Memory error when reading wrong core file.
+ * solib-svr4.c (solib_svr4_r_map): catch and print all exception
+ errors while reading the inferior memory, and return zero if
+ an exception was raised.
+
2010-03-07 Michael Snyder <msnyder@vmware.com>
* record.c (record_restore): Rename tmpu8 to rectype.

View File

@ -36,7 +36,7 @@ Version: 7.1
# The release always contains a leading reserved number, start it at 1.
# `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
Release: 1%{?_with_upstream:.upstream}%{dist}
Release: 2%{?_with_upstream:.upstream}%{dist}
License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and GFDL and BSD and Public Domain
Group: Development/Debuggers
@ -119,7 +119,6 @@ Patch118: gdb-6.3-gstack-20050411.patch
# VSYSCALL and PIE
Patch122: gdb-6.3-test-pie-20050107.patch
Patch124: gdb-archer-pie-0315-breakpoint_address_match.patch
Patch389: gdb-archer-pie-addons.patch
Patch394: gdb-archer-pie-addons-keep-disabled.patch
@ -429,6 +428,19 @@ Patch429: gdb-bz562975-std-terminate-double-free.patch
# PIE: Fix back re-reun.
Patch430: gdb-pie-rerun.patch
# Do not consider memory error on reading _r_debug->r_map as fatal (BZ 576742).
Patch432: gdb-solib-memory-error-nonfatal.patch
# testsuite: Fix unstable results of gdb.base/prelink.exp.
Patch433: gdb-6.7-testsuite-stable-results-prelink.patch
# [patch 1/6] PIE: Attach binary even after re-prelinked underneath
# [patch 2/6] PIE: Attach binary even after ld.so re-prelinked underneath
# [patch 3/6] PIE: Fix occasional error attaching i686 binary
Patch434: gdb-pie-1of6-reprelinked-bin.patch
Patch435: gdb-pie-2of6-reprelinked-ld.patch
Patch436: gdb-pie-3of6-relocate-once.patch
BuildRequires: ncurses-devel%{?_isa} texinfo gettext flex bison expat-devel%{?_isa}
Requires: readline%{?_isa}
BuildRequires: readline-devel%{?_isa}
@ -567,7 +579,6 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c
%patch232 -p1
%patch349 -p1
%patch420 -p1
%patch124 -p1
%patch1 -p1
%patch3 -p1
@ -679,6 +690,11 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c
%patch422 -p1
%patch429 -p1
%patch430 -p1
%patch432 -p1
%patch433 -p1
%patch434 -p1
%patch435 -p1
%patch436 -p1
%patch415 -p1
%patch393 -p1
@ -1011,6 +1027,14 @@ fi
%endif
%changelog
* Mon Mar 29 2010 Jan Kratochvil <jan.kratochvil@redhat.com> - 7.1-2.fc13
- Drop obsoleted `gdb-archer-pie-0315-breakpoint_address_match.patch'.
- Do not consider memory error on reading _r_debug->r_map as fatal (BZ 576742).
- PIE: Attach binary even after re-prelinked underneath.
- PIE: Attach binary even after ld.so re-prelinked underneath.
- PIE: Fix occasional error attaching i686 binary (BZ 576742).
- testsuite: Fix unstable results of gdb.base/prelink.exp.
* Thu Mar 25 2010 Jan Kratochvil <jan.kratochvil@redhat.com> - 7.1-1.fc13
- Update to new FSF GDB release.