Implement qXfer:exec-file:read in gdbserver From: Gary Benson This commit implements the "qXfer:exec-file:read" packet in gdbserver. gdb/gdbserver/ChangeLog: * target.h (struct target_ops) : New field. * linux-low.c (linux_target_ops): Initialize pid_to_exec_file. * server.c (handle_qxfer_exec_file): New function. (qxfer_packets): Add exec-file entry. (handle_query): Report qXfer:exec-file:read as supported packet. --- gdb/gdbserver/linux-low.c | 19 +++++++++++++++++++ gdb/gdbserver/server.c | 40 ++++++++++++++++++++++++++++++++++++++++ gdb/gdbserver/target.h | 7 +++++++ 3 files changed, 66 insertions(+) Index: gdb-7.6.1/gdb/gdbserver/linux-low.c =================================================================== --- gdb-7.6.1.orig/gdb/gdbserver/linux-low.c 2016-03-15 19:04:39.260193747 +0100 +++ gdb-7.6.1/gdb/gdbserver/linux-low.c 2016-03-15 19:04:48.841256052 +0100 @@ -5993,6 +5993,24 @@ } #endif /* HAVE_LINUX_BTRACE */ +// gdb/nat/linux-procfs.c +static char * +linux_proc_pid_to_exec_file (int pid) +{ + static char buf[PATH_MAX]; + char name[PATH_MAX]; + ssize_t len; + + xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid); + len = readlink (name, buf, PATH_MAX - 1); + if (len <= 0) + strcpy (buf, name); + else + buf[len] = '\0'; + + return buf; +} + static struct target_ops linux_target_ops = { linux_create_inferior, linux_attach, @@ -6070,6 +6088,7 @@ NULL, NULL, #endif + linux_proc_pid_to_exec_file, }; static void Index: gdb-7.6.1/gdb/gdbserver/server.c =================================================================== --- gdb-7.6.1.orig/gdb/gdbserver/server.c 2016-03-15 19:04:39.262193760 +0100 +++ gdb-7.6.1/gdb/gdbserver/server.c 2016-03-15 19:04:48.842256059 +0100 @@ -1006,6 +1006,42 @@ return (*the_target->read_auxv) (offset, readbuf, len); } +/* Handle qXfer:exec-file:read. */ + +static int +handle_qxfer_exec_file (const char *const_annex, + gdb_byte *readbuf, const gdb_byte *writebuf, + ULONGEST offset, LONGEST len) +{ + char *annex, *file; + ULONGEST pid; + int total_len; + + if (the_target->pid_to_exec_file == NULL || writebuf != NULL) + return -2; + + annex = alloca (strlen (const_annex) + 1); + strcpy (annex, const_annex); + annex = unpack_varlen_hex (annex, &pid); + if (annex[0] != '\0' || pid == 0) + return -1; + + file = (*the_target->pid_to_exec_file) (pid); + if (file == NULL) + return -1; + + total_len = strlen (file); + + if (offset > total_len) + return -1; + + if (offset + len > total_len) + len = total_len - offset; + + memcpy (readbuf, file + offset, len); + return len; +} + /* Handle qXfer:features:read. */ static int @@ -1408,6 +1444,7 @@ { { "auxv", handle_qxfer_auxv }, { "btrace", handle_qxfer_btrace }, + { "exec-file", handle_qxfer_exec_file}, { "fdpic", handle_qxfer_fdpic}, { "features", handle_qxfer_features }, { "libraries", handle_qxfer_libraries }, @@ -1828,6 +1865,9 @@ if (target_supports_stopped_by_hw_breakpoint ()) strcat (own_buf, ";hwbreak+"); + if (the_target->pid_to_exec_file != NULL) + strcat (own_buf, ";qXfer:exec-file:read+"); + return; } Index: gdb-7.6.1/gdb/gdbserver/target.h =================================================================== --- gdb-7.6.1.orig/gdb/gdbserver/target.h 2016-03-15 19:04:39.262193760 +0100 +++ gdb-7.6.1/gdb/gdbserver/target.h 2016-03-15 19:04:48.842256059 +0100 @@ -421,6 +421,13 @@ to break a cyclic dependency. */ void (*read_btrace) (struct btrace_target_info *, struct buffer *, int type); + /* Return the full absolute name of the executable file that was + run to create the process PID. If the executable file cannot + be determined, NULL is returned. Otherwise, a pointer to a + character string containing the pathname is returned. This + string should be copied into a buffer by the client if the string + will not be immediately used, or if it must persist. */ + char *(*pid_to_exec_file) (int pid); }; extern struct target_ops *the_target;