]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
fix gdbsrv inferior calls when PT_GNU_STACK declares stack not executable
authorPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Thu, 2 May 2013 22:06:31 +0000 (22:06 +0000)
committerPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Thu, 2 May 2013 22:06:31 +0000 (22:06 +0000)
With rev 13368, Valgrind obeys PT_GNU_STACK making the stack not
executable. This makes inferior function call with GDB >= 7.5 failing,
as GDB places a breakpoint on the stack, which must be decoded
and translated by Valgrind to have the inferior function call properly done.
=> introduce a special case in the conditions to allow translation
when a segment is not executable but is readable and there is a
breakpoint at the address.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13381

coregrind/m_gdbserver/m_gdbserver.c
coregrind/m_translate.c
coregrind/pub_core_gdbserver.h

index 57aeefe8271b98923d2ef69cc2b9c1ba17ddb0a0..44a9990e0bf85643570858a626503a7fa53cb4c6 100644 (file)
@@ -394,6 +394,15 @@ Bool VG_(gdbserver_point) (PointKind kind, Bool insert,
    return True;
 }
 
+Bool VG_(has_gdbserver_breakpoint) (Addr addr)
+{
+   GS_Address *g;
+   if (!gdbserver_called)
+      return False;
+   g = VG_(HT_lookup) (gs_addresses, (UWord)HT_addr(addr));
+   return (g != NULL && g->kind == GS_break);
+}
+
 Bool VG_(is_watched)(PointKind kind, Addr addr, Int szB)
 {
    Word n_elems;
index 5088c3667dbbf068873207c02a70fe8cd310c618..92aa00866a04d1f4e1d1ab92ce227bbf94d724ec 100644 (file)
@@ -745,9 +745,9 @@ void log_bytes ( HChar* bytes, Int nbytes )
 /* --------- Various helper functions for translation --------- */
 
 /* Look for reasons to disallow making translations from the given
-   segment. */
+   segment/addr. */
 
-static Bool translations_allowable_from_seg ( NSegment const* seg )
+static Bool translations_allowable_from_seg ( NSegment const* seg, Addr addr )
 {
 #  if defined(VGA_x86) || defined(VGA_s390x) || defined(VGA_mips32) \
       || defined(VGA_mips64)
@@ -757,7 +757,16 @@ static Bool translations_allowable_from_seg ( NSegment const* seg )
 #  endif
    return seg != NULL
           && (seg->kind == SkAnonC || seg->kind == SkFileC || seg->kind == SkShmC)
-          && (seg->hasX || (seg->hasR && allowR));
+          && (seg->hasX 
+              || (seg->hasR && (allowR
+                                || VG_(has_gdbserver_breakpoint) (addr))));
+   /* If GDB/gdbsrv has inserted a breakpoint at addr, assume this is a valid
+      location to translate if seg is not executable but is readable.
+      This is needed for inferior function calls from GDB: GDB inserts a
+      breakpoint on the stack, and expects to regain control before the
+      breakpoint instruction at the breakpoint address is really
+      executed. For this, the breakpoint instruction must be translated
+      so as to have the call to gdbserver executed. */
 }
 
 
@@ -852,7 +861,7 @@ static Bool chase_into_ok ( void* closureV, Addr64 addr64 )
       allow a chase. */
 
    /* Destination not in a plausible segment? */
-   if (!translations_allowable_from_seg(seg))
+   if (!translations_allowable_from_seg(seg, addr))
       goto dontchase;
 
    /* Destination is redirected? */
@@ -1418,7 +1427,7 @@ Bool VG_(translate) ( ThreadId tid,
    { /* BEGIN new scope specially for 'seg' */
    NSegment const* seg = VG_(am_find_nsegment)(addr);
 
-   if ( (!translations_allowable_from_seg(seg))
+   if ( (!translations_allowable_from_seg(seg, addr))
         || addr == TRANSTAB_BOGUS_GUEST_ADDR ) {
       if (VG_(clo_trace_signals))
          VG_(message)(Vg_DebugMsg, "translations not allowed here (0x%llx)"
index d172a36295919c446aa7c6d91ee7d1d5a84d18b6..f4286c36df98061a8a27007916af56fa617800da 100644 (file)
@@ -76,6 +76,9 @@ void VG_(gdbserver_exit) (ThreadId tid, VgSchedReturnCode tids_schedretcode);
 Bool VG_(gdbserver_point) (PointKind kind, Bool insert, 
                            Addr addr, int len);
 
+/* True if there is a breakpoint at addr. */
+Bool VG_(has_gdbserver_breakpoint) (Addr addr);
+
 /* Entry point invoked by vgdb when it uses ptrace to cause a gdbserver
    invocation. A magic value is passed by vgdb in check as a verification
    that the call has been properly pushed by vgdb. */