fix gdbsrv inferior calls when PT_GNU_STACK declares stack not executable

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
This commit is contained in:
Philippe Waroquiers 2013-05-02 22:06:31 +00:00
parent ee3a906b26
commit bd849e11cf
3 changed files with 26 additions and 5 deletions

View 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;

View 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)"

View 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. */