|
From: <sv...@va...> - 2011-06-26 09:31:38
|
Author: sewardj
Date: 2011-06-26 10:26:48 +0100 (Sun, 26 Jun 2011)
New Revision: 11836
Log:
Add support for PIC executables (e.g. firefox on Ubuntu 11) by adding
the "auxv" protocol packet to gdbsrv. (Philippe Waroquiers,
phi...@sk...). Bug 214909 comment 108.
Added:
trunk/gdbserver_tests/main_pic.c
trunk/gdbserver_tests/mcmain_pic.stderr.exp
trunk/gdbserver_tests/mcmain_pic.stderrB.exp
trunk/gdbserver_tests/mcmain_pic.stdinB.gdb
trunk/gdbserver_tests/mcmain_pic.stdout.exp
trunk/gdbserver_tests/mcmain_pic.stdoutB.exp
trunk/gdbserver_tests/mcmain_pic.vgtest
Modified:
trunk/coregrind/m_clientstate.c
trunk/coregrind/m_gdbserver/server.c
trunk/coregrind/m_initimg/initimg-linux.c
trunk/coregrind/pub_core_clientstate.h
trunk/gdbserver_tests/Makefile.am
Modified: trunk/coregrind/m_clientstate.c
===================================================================
--- trunk/coregrind/m_clientstate.c 2011-06-26 09:13:27 UTC (rev 11835)
+++ trunk/coregrind/m_clientstate.c 2011-06-26 09:26:48 UTC (rev 11836)
@@ -51,6 +51,10 @@
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 */
Modified: trunk/coregrind/m_gdbserver/server.c
===================================================================
--- trunk/coregrind/m_gdbserver/server.c 2011-06-26 09:13:27 UTC (rev 11835)
+++ trunk/coregrind/m_gdbserver/server.c 2011-06-26 09:26:48 UTC (rev 11836)
@@ -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 @@
}
}
+ 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 @@
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) {
Modified: trunk/coregrind/m_initimg/initimg-linux.c
===================================================================
--- trunk/coregrind/m_initimg/initimg-linux.c 2011-06-26 09:13:27 UTC (rev 11835)
+++ trunk/coregrind/m_initimg/initimg-linux.c 2011-06-26 09:26:48 UTC (rev 11836)
@@ -611,6 +611,11 @@
/* --- 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 @@
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;
Modified: trunk/coregrind/pub_core_clientstate.h
===================================================================
--- trunk/coregrind/pub_core_clientstate.h 2011-06-26 09:13:27 UTC (rev 11835)
+++ trunk/coregrind/pub_core_clientstate.h 2011-06-26 09:26:48 UTC (rev 11836)
@@ -46,6 +46,10 @@
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
Modified: trunk/gdbserver_tests/Makefile.am
===================================================================
--- trunk/gdbserver_tests/Makefile.am 2011-06-26 09:13:27 UTC (rev 11835)
+++ trunk/gdbserver_tests/Makefile.am 2011-06-26 09:26:48 UTC (rev 11836)
@@ -44,6 +44,7 @@
mcleak.stdinB.gdb \
mcleak.stdoutB.exp \
mcleak.vgtest \
+ mcmain_pic.vgtest \
mcsignopass.stderrB.exp \
mcsignopass.stderr.exp \
mcsignopass.stdinB.gdb \
@@ -82,6 +83,7 @@
clean_after_fork \
fork_chain \
sleepers \
+ main_pic \
t \
watchpoints
@@ -89,3 +91,6 @@
AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
LDADD = -lpthread
+
+main_pic_LDFLAGS = -pie
+main_pic_CFLAGS = $(AM_CFLAGS) -fPIC
Added: trunk/gdbserver_tests/main_pic.c
===================================================================
--- trunk/gdbserver_tests/main_pic.c (rev 0)
+++ trunk/gdbserver_tests/main_pic.c 2011-06-26 09:26:48 UTC (rev 11836)
@@ -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;
+}
Added: trunk/gdbserver_tests/mcmain_pic.stderr.exp
===================================================================
--- trunk/gdbserver_tests/mcmain_pic.stderr.exp (rev 0)
+++ trunk/gdbserver_tests/mcmain_pic.stderr.exp 2011-06-26 09:26:48 UTC (rev 11836)
@@ -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)
Added: trunk/gdbserver_tests/mcmain_pic.stderrB.exp
===================================================================
--- trunk/gdbserver_tests/mcmain_pic.stderrB.exp (rev 0)
+++ trunk/gdbserver_tests/mcmain_pic.stderrB.exp 2011-06-26 09:26:48 UTC (rev 11836)
@@ -0,0 +1,3 @@
+relaying data between gdb and process ....
+vgdb-error value changed from 0 to 999999
+Remote connection closed
Added: trunk/gdbserver_tests/mcmain_pic.stdinB.gdb
===================================================================
--- trunk/gdbserver_tests/mcmain_pic.stdinB.gdb (rev 0)
+++ trunk/gdbserver_tests/mcmain_pic.stdinB.gdb 2011-06-26 09:26:48 UTC (rev 11836)
@@ -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
Added: trunk/gdbserver_tests/mcmain_pic.stdout.exp
===================================================================
--- trunk/gdbserver_tests/mcmain_pic.stdout.exp (rev 0)
+++ trunk/gdbserver_tests/mcmain_pic.stdout.exp 2011-06-26 09:26:48 UTC (rev 11836)
@@ -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
Added: trunk/gdbserver_tests/mcmain_pic.stdoutB.exp
===================================================================
--- trunk/gdbserver_tests/mcmain_pic.stdoutB.exp (rev 0)
+++ trunk/gdbserver_tests/mcmain_pic.stdoutB.exp 2011-06-26 09:26:48 UTC (rev 11836)
@@ -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.
Added: trunk/gdbserver_tests/mcmain_pic.vgtest
===================================================================
--- trunk/gdbserver_tests/mcmain_pic.vgtest (rev 0)
+++ trunk/gdbserver_tests/mcmain_pic.vgtest 2011-06-26 09:26:48 UTC (rev 11836)
@@ -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
+
|