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 */
#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;
}
}
+ 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')) {
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) {
/* --- 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;
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;
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
mcleak.stdinB.gdb \
mcleak.stdoutB.exp \
mcleak.vgtest \
+ mcmain_pic.vgtest \
mcsignopass.stderrB.exp \
mcsignopass.stderr.exp \
mcsignopass.stdinB.gdb \
clean_after_fork \
fork_chain \
sleepers \
+ main_pic \
t \
watchpoints
AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
LDADD = -lpthread
+
+main_pic_LDFLAGS = -pie
+main_pic_CFLAGS = $(AM_CFLAGS) -fPIC
--- /dev/null
+#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;
+}
--- /dev/null
+
+(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)
--- /dev/null
+relaying data between gdb and process ....
+vgdb-error value changed from 0 to 999999
+Remote connection closed
--- /dev/null
+# 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
--- /dev/null
+another func called msg called from gdb
+address of main 0x........
+address of another_func 0x........
+another func called msg called from main
--- /dev/null
+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.
--- /dev/null
+# 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
+