[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gdb-cvs
Subject:    [binutils-gdb] gdb/linux_nat: Write memory using ptrace if /proc/pid/mem is not writable
From:       Pedro Alves via Gdb-cvs <gdb-cvs () sourceware ! org>
Date:       2022-07-26 18:46:44
Message-ID: 20220726184644.9D3B2385829E () sourceware ! org
[Download RAW message or body]

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=dd09fe0d53242a5f6a86d2822b0cfdeb3f5baa8f

commit dd09fe0d53242a5f6a86d2822b0cfdeb3f5baa8f
Author: Keith Seitz <keiths@redhat.com>
Date:   Tue Jul 26 19:11:04 2022 +0100

    gdb/linux_nat: Write memory using ptrace if /proc/pid/mem is not writable
    
    Commit 05c06f318fd9a112529dfc313e6512b399a645e4 enabled GDB to access
    memory while threads are running.  It did this by accessing
    /proc/PID/task/LWP/mem.
    
    Unfortunately, this interface is not implemented for writing in older
    kernels (such as RHEL6).  This means that GDB is unable to insert
    breakpoints on these hosts:
    
     $ ./gdb -q gdb -ex start
     Reading symbols from gdb...
     Temporary breakpoint 1 at 0x40fdd5: file ../../src/gdb/gdb.c, line 28.
     Starting program: /home/rhel6/fsf/linux/gdb/gdb
     Warning:
     Cannot insert breakpoint 1.
     Cannot access memory at address 0x40fdd5
    
     (gdb)
    
    Before this patch, linux_proc_xfer_memory_partial (previously called
    linux_proc_xfer_partial) would return TARGET_XFER_EOF if the write to
    /proc/PID/mem failed. [More specifically, linux_proc_xfer_partial
    would not "bother for one word," but the effect is the essentially
    same.]
    
    This status was checked by linux_nat_target::xfer_partial, which would
    then fallback to using ptrace to perform the operation.
    
    This is the specific hunk that removed the fallback:
    
    -  xfer = linux_proc_xfer_partial (object, annex, readbuf, writebuf,
    -                                 offset, len, xfered_len);
    -  if (xfer != TARGET_XFER_EOF)
    -    return xfer;
    +      return linux_proc_xfer_memory_partial (readbuf, writebuf,
    +                                            offset, len, xfered_len);
    +    }
    
       return inf_ptrace_target::xfer_partial (object, annex, readbuf, writebuf,
                                              offset, len, xfered_len);
    
    This patch makes linux_nat_target::xfer_partial go straight to writing
    memory via ptrace if writing via /proc/pid/mem is not possible in the
    running kernel, enabling GDB to insert breakpoints on these older
    kernels.  Note that a recent patch changed the return status from
    TARGET_XFER_EOF to TARGET_XFER_E_IO.
    
    Tested on {unix,native-gdbserver,native-extended-gdbserver}/-m{32,64}
    on x86_64, s390x, aarch64, and ppc64le.
    
    Change-Id: If1d884278e8c4ea71d8836bedd56e6a6c242a415

Diff:
---
 gdb/linux-nat.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index b641e88b1ef..e638e8ad04e 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -3711,8 +3711,15 @@ linux_nat_target::xfer_partial (enum target_object object,
       if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT))
 	offset &= ((ULONGEST) 1 << addr_bit) - 1;
 
-      return linux_proc_xfer_memory_partial (readbuf, writebuf,
-					     offset, len, xfered_len);
+      /* If /proc/pid/mem is writable, don't fallback to ptrace.  If
+	 the write via /proc/pid/mem fails because the inferior execed
+	 (and we haven't seen the exec event yet), a subsequent ptrace
+	 poke would incorrectly write memory to the post-exec address
+	 space, while the core was trying to write to the pre-exec
+	 address space.  */
+      if (proc_mem_file_is_writable ())
+	return linux_proc_xfer_memory_partial (readbuf, writebuf,
+					       offset, len, xfered_len);
     }
 
   return inf_ptrace_target::xfer_partial (object, annex, readbuf, writebuf,
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic