Add support for PIC executables (e.g. firefox on Ubuntu 11) by adding

the "auxv" protocol packet to gdbsrv.  (Philippe Waroquiers,
philippe.waroquiers@skynet.be).  Bug 214909 comment 108.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11836
This commit is contained in:
Julian Seward 2011-06-26 09:26:48 +00:00
parent 5689679404
commit 7be9d63ed0
12 changed files with 153 additions and 0 deletions

View File

@ -51,6 +51,10 @@ Addr VG_(clstk_base) = 0;
Addr VG_(clstk_end) = 0;
UWord VG_(clstk_id) = 0;
/* linux only: where is the client auxv ? */
/* This is set up as part of setup_client_stack in initimg-linux.c. */
UWord* VG_(client_auxv) = NULL;
Addr VG_(brk_base) = 0; /* start of brk */
Addr VG_(brk_limit) = 0; /* current brk */

View File

@ -26,6 +26,7 @@
#include "pub_core_options.h"
#include "pub_core_translate.h"
#include "pub_core_mallocfree.h"
#include "pub_core_initimg.h"
unsigned long cont_thread;
unsigned long general_thread;
@ -580,6 +581,59 @@ void handle_query (char *arg_own_buf, int *new_packet_len_p)
}
}
if (strncmp ("qXfer:auxv:read:", arg_own_buf, 16) == 0) {
unsigned char *data;
int n;
CORE_ADDR ofs;
unsigned int len;
char *annex;
/* Reject any annex; grab the offset and length. */
if (decode_xfer_read (arg_own_buf + 16, &annex, &ofs, &len) < 0
|| annex[0] != '\0') {
strcpy (arg_own_buf, "E00");
return;
}
if (len > PBUFSIZ - 2)
len = PBUFSIZ - 2;
data = malloc (len);
{
UWord *client_auxv = VG_(client_auxv);
unsigned int client_auxv_len = 0;
while (*client_auxv != 0) {
dlog(4, "auxv %lld %llx\n",
(ULong)*client_auxv,
(ULong)*(client_auxv+1));
client_auxv++;
client_auxv++;
client_auxv_len += 2 * sizeof(UWord);
}
client_auxv_len += 2 * sizeof(UWord);
dlog(4, "auxv len %d\n", client_auxv_len);
if (ofs >= client_auxv_len)
n = -1;
else {
n = client_auxv_len - ofs;
VG_(memcpy) (data, (unsigned char *) VG_(client_auxv), n);
}
}
if (n < 0)
write_enn (arg_own_buf);
else if (n > len)
*new_packet_len_p = write_qxfer_response (arg_own_buf, data, len, 1);
else
*new_packet_len_p = write_qxfer_response (arg_own_buf, data, n, 0);
free (data);
return;
}
/* Protocol features query. */
if (strncmp ("qSupported", arg_own_buf, 10) == 0
&& (arg_own_buf[10] == ':' || arg_own_buf[10] == '\0')) {
@ -589,6 +643,8 @@ void handle_query (char *arg_own_buf, int *new_packet_len_p)
strcat (arg_own_buf, ";QStartNoAckMode+");
strcat (arg_own_buf, ";QPassSignals+");
if (VG_(client_auxv))
strcat (arg_own_buf, ";qXfer:auxv:read+");
if ((*the_target->target_xml)() != NULL
|| (*the_target->shadow_target_xml)() != NULL) {

View File

@ -611,6 +611,11 @@ Addr setup_client_stack( void* init_sp,
/* --- auxv --- */
auxv = (struct auxv *)ptr;
*client_auxv = (UInt *)auxv;
VG_(client_auxv) = (UWord *)*client_auxv;
// ??? According to 'man proc', auxv is a array of unsigned long
// terminated by two zeros. Why is valgrind working with UInt ?
// We do not take ULong* (as ULong 8 bytes on a 32 bits),
// => we take UWord*
# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
auxv[0].a_type = AT_IGNOREPPC;
@ -658,6 +663,11 @@ Addr setup_client_stack( void* init_sp,
break;
case AT_BASE:
/* When gdbserver sends the auxv to gdb, the AT_BASE has
to be ignored, as otherwise gdb adds this offset
to loaded shared libs, causing wrong address
relocation e.g. when inserting breaks. */
auxv->a_type = AT_IGNORE;
auxv->u.a_val = info->interp_base;
break;

View File

@ -46,6 +46,10 @@ extern Addr VG_(clstk_base); // client stack range
extern Addr VG_(clstk_end);
extern UWord VG_(clstk_id); // client stack id
/* linux only: where is the client auxv ? */
/* This is setup as part of setup_client_stack in initimg-linux.c. */
extern UWord* VG_(client_auxv);
extern Addr VG_(brk_base); // start of brk
extern Addr VG_(brk_limit); // current brk

View File

@ -44,6 +44,7 @@ EXTRA_DIST = \
mcleak.stdinB.gdb \
mcleak.stdoutB.exp \
mcleak.vgtest \
mcmain_pic.vgtest \
mcsignopass.stderrB.exp \
mcsignopass.stderr.exp \
mcsignopass.stdinB.gdb \
@ -82,6 +83,7 @@ check_PROGRAMS = \
clean_after_fork \
fork_chain \
sleepers \
main_pic \
t \
watchpoints
@ -89,3 +91,6 @@ AM_CFLAGS += $(AM_FLAG_M3264_PRI)
AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
LDADD = -lpthread
main_pic_LDFLAGS = -pie
main_pic_CFLAGS = $(AM_CFLAGS) -fPIC

View File

@ -0,0 +1,14 @@
#include <stdio.h>
static void another_func(char *msg)
{
printf ("another func called msg %s\n", msg);
}
int main (int argc, char *argv[])
{
printf("address of main %p\n", &main);
printf("address of another_func %p\n", &another_func);
another_func("called from main");
return 0;
}

View File

@ -0,0 +1,13 @@
(action at startup) vgdb me ...
HEAP SUMMARY:
in use at exit: 16 bytes in 1 blocks
total heap usage: 1 allocs, 0 frees, 16 bytes allocated
For a detailed leak analysis, rerun with: --leak-check=full
For counts of detected and suppressed errors, rerun with: -v
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

View File

@ -0,0 +1,3 @@
relaying data between gdb and process ....
vgdb-error value changed from 0 to 999999
Remote connection closed

View File

@ -0,0 +1,16 @@
# connect gdb to Valgrind gdbserver:
target remote | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-mcmain_pic
echo vgdb launched process attached\n
monitor vg.set vgdb-error 999999
#
# break
break main
#
continue
# first break encountered.
print another_func("called from gdb")
#
print &main
print &another_func
continue
quit

View File

@ -0,0 +1,4 @@
another func called msg called from gdb
address of main 0x........
address of another_func 0x........
another func called msg called from main

View File

@ -0,0 +1,8 @@
Breakpoint 1 at 0x........: file main_pic.c, line 10.
Continuing.
Breakpoint 1, main (argc=1, argv=0x........) at main_pic.c:10
10 printf("address of main %p\n", &main);
$1 = void
$2 = (int (*)(int, char **)) 0x........ <main>
$3 = (void (*)(char *)) 0x........ <another_func>
Continuing.

View File

@ -0,0 +1,16 @@
# test that gdbserver/gdb properly handle a PIC executable
# On linux, this implies a proper transfer of the auxv
# information via the gdbserver protocol packet qXfer:auxv:read:
# The content of the auxv data can be shown by gdb using
# gdb command 'info auxv'
prereq: test -e gdb
prog: main_pic
vgopts: --tool=memcheck --vgdb=yes --vgdb-error=0 --vgdb-prefix=./vgdb-prefix-mcmain_pic
stdout_filter: filter_gdb
stderr_filter: filter_memcheck_monitor
progB: gdb
argsB: --quiet -l 60 --nx ./main_pic
stdinB: mcmain_pic.stdinB.gdb
stdoutB_filter: filter_gdb
stderrB_filter: filter_memcheck_monitor