2011-07-19 Andrew Stubbs Yao Qi gdb/ * remote.c (PACKET_qXfer_fdpic): New enum value. (remote_protocol_features): Add qXfer:fdpic:read packet. (remote_xfer_partial): Support TARGET_OBJECT_FDPIC. (_initialize_remote): Add set/show remote read-fdpic-loadmap command. * target.h (enum target_object): Add TARGET_OBJECT_FDPIC. gdb/gdbserver: * linux-low.c (struct target_loadseg): New type. (struct target_loadmap): New type. (linux_read_loadmap): New function. (linux_target_ops): Add linux_read_loadmap. * server.c (handle_query): Support qXfer:fdpic:read packet. * target.h (struct target_ops): Add read_loadmap. --- gdb/gdbserver/linux-low.c | 60 +++++++++++++++++++++++++++++++++++++++++++++ gdb/gdbserver/server.c | 19 ++++++++++++++ gdb/gdbserver/target.h | 4 +++ gdb/remote.c | 10 +++++++ gdb/target.h | 2 + 5 files changed, 95 insertions(+), 0 deletions(-) diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index d84fd68..1e9a4fb 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -4964,6 +4964,61 @@ linux_core_of_thread (ptid_t ptid) return core; } +#if defined __DSBT__ +struct target_loadseg +{ + /* Core address to which the segment is mapped. */ + Elf32_Addr addr; + /* VMA recorded in the program header. */ + Elf32_Addr p_vaddr; + /* Size of this segment in memory. */ + Elf32_Word p_memsz; +}; + +struct target_loadmap { + /* Protocol version number, must be zero. */ + Elf32_Word version; + /* Pointer to the DSBT table, its size, and the DSBT index. */ + unsigned *dsbt_table; + unsigned dsbt_size, dsbt_index; + /* Number of segments in this map. */ + Elf32_Word nsegs; + /* The actual memory map. */ + struct target_loadseg segs[/*nsegs*/]; +}; +#endif + +#if defined __DSBT__ +static int +linux_read_loadmap (const char *annex, CORE_ADDR offset, + unsigned char *myaddr, unsigned int len) +{ + int pid = lwpid_of (get_thread_lwp (current_inferior)); + int addr = (strcmp (annex, "exec") == 0 ? (int) PTRACE_GETDSBT_EXEC : + (strcmp (annex, "interp") == 0 ? (int) PTRACE_GETDSBT_INTERP : + -1)); + struct target_loadmap *data = NULL; + unsigned int actual_length, copy_length; + + if (addr == -1) + return -1; + + ptrace (PTRACE_GETDSBT, pid, addr, &data); + + if (data == NULL) + return -1; + + actual_length = sizeof (struct target_loadmap) + + sizeof (struct target_loadseg) * data->nsegs; + + if (offset < 0 || offset > actual_length) + return -1; + + copy_length = actual_length - offset < len ? actual_length - offset : len; + memcpy (myaddr, ((char *)data) + offset, copy_length); + return copy_length; +} +#endif static void linux_process_qsupported (const char *query) { @@ -5112,6 +5167,11 @@ static struct target_ops linux_target_ops = { NULL, #endif linux_core_of_thread, +#if defined __DSBT__ + linux_read_loadmap, +#else + NULL, +#endif linux_process_qsupported, linux_supports_tracepoints, linux_read_pc, diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index fd06c8f..7991307 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -1171,6 +1171,21 @@ handle_qxfer_traceframe_info (const char *annex, return len; } +/* Handle qXfer:fdpic:read. */ + +static int +handle_qxfer_fdpic (const char *annex, gdb_byte *readbuf, + const gdb_byte *writebuf, ULONGEST offset, LONGEST len) +{ + if (the_target->read_fdpic_loadmap == NULL) + return -2; + + if (!target_running ()) + return -1; + + return (*the_target->read_fdpic_loadmap) (annex, offset, readbuf, len); +} + static const struct qxfer qxfer_packets[] = { { "auxv", handle_qxfer_auxv }, @@ -1182,6 +1197,7 @@ static const struct qxfer qxfer_packets[] = { "statictrace", handle_qxfer_statictrace }, { "threads", handle_qxfer_threads }, { "traceframe-info", handle_qxfer_traceframe_info }, + {"fdpic", handle_qxfer_fdpic} }; static int @@ -1509,6 +1525,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) if (the_target->qxfer_siginfo != NULL) strcat (own_buf, ";qXfer:siginfo:read+;qXfer:siginfo:write+"); + if (the_target->read_fdpic_loadmap != NULL) + strcat (own_buf, ";qXfer:fdpic:read+"); + /* We always report qXfer:features:read, as targets may install XML files on a subsequent call to arch_setup. If we reported to GDB on startup that we don't support diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h index 00214db..60f4f34 100644 --- a/gdb/gdbserver/target.h +++ b/gdb/gdbserver/target.h @@ -311,6 +311,10 @@ struct target_ops /* Returns the core given a thread, or -1 if not known. */ int (*core_of_thread) (ptid_t); + /* Read FDPIC loadmaps. Read LEN bytes at OFFSET into a buffer at MYADDR. */ + int (*read_fdpic_loadmap) (const char *annex, CORE_ADDR offset, + unsigned char *myaddr, unsigned int len); + /* Target specific qSupported support. */ void (*process_qsupported) (const char *); diff --git a/gdb/remote.c b/gdb/remote.c index b03ef59..9a1c653 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -1262,6 +1262,7 @@ enum { PACKET_bs, PACKET_TracepointSource, PACKET_QAllow, + PACKET_qXfer_fdpic, PACKET_MAX }; @@ -3769,6 +3770,8 @@ static struct protocol_feature remote_protocol_features[] = { PACKET_QAllow }, { "EnableDisableTracepoints", PACKET_DISABLE, remote_enable_disable_tracepoint_feature, -1 }, + { "qXfer:fdpic:read", PACKET_DISABLE, remote_supported_packet, + PACKET_qXfer_fdpic }, }; static char *remote_support_xml; @@ -8299,6 +8302,10 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, return remote_read_qxfer (ops, "traceframe-info", annex, readbuf, offset, len, &remote_protocol_packets[PACKET_qXfer_traceframe_info]); + + case TARGET_OBJECT_FDPIC: + return remote_read_qxfer (ops, "fdpic", annex, readbuf, offset, len, + &remote_protocol_packets[PACKET_qXfer_fdpic]); default: return -1; } @@ -10903,6 +10910,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_statictrace_read], "qXfer:statictrace:read", "read-sdata-object", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_fdpic], + "qXfer:fdpic:read", "read-fdpic-loadmap", 0); + /* Keep the old ``set remote Z-packet ...'' working. Each individual Z sub-packet has its own set and show commands, but users may have sets to this variable in their .gdbinit files (or in their diff --git a/gdb/target.h b/gdb/target.h index 3b39d6f..f1bb12d 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -274,6 +274,8 @@ enum target_object TARGET_OBJECT_HPUX_SOLIB_GOT, /* Traceframe info, in XML format. */ TARGET_OBJECT_TRACEFRAME_INFO, + /* Load maps for FDPIC systems. */ + TARGET_OBJECT_FDPIC /* Possible future objects: TARGET_OBJECT_FILE, ... */ }; -- 1.7.0.4