diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e4ce649113..00217dbe14 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,26 @@ +2003-10-17 Andrew Cagney + + * target.h (struct target_ops): Add "to_read_partial" and + "to_write_partial", delete "to_query". + (target_read_partial, target_write_partial): Declare. + (target_read, target_write): Declare. + (target_query): Delete macro. + * target.c (target_read_partial): New function. + (target_write_partial, target_read, target_write): New function. + (update_current_target): Delete inheritance of "to_query". Add + comments about "to_read_partial" and "to_write_partial". + (debug_to_partial_read, debug_to_partial_write): New functions. + (debug_to_query): Delete function. + (setup_target_debug): Set "to_read_partial" and "to_write_partial" + instead of "to_query". + * remote.c (remote_read_partial): Replace "remote_query". + (init_remote_ops): Set "to_read_partial" instead of "to_query". + (init_remote_async_ops): Ditto. + * kod.c (gdb_kod_query): Make "bufsize" a LONGEST. Use + "target_read_partial" instead of "target_query". + * avr-tdep.c (avr_io_reg_read_command): Make "bufsize" a LONGEST. + Use "target_read_partial" instead of "target_query". + 2003-10-17 Jeff Johnston * frame.h (struct frame_id): Add new field: special_addr. diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c index 90bf9102eb..e9c5d428d3 100644 --- a/gdb/avr-tdep.c +++ b/gdb/avr-tdep.c @@ -1359,7 +1359,7 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) static void avr_io_reg_read_command (char *args, int from_tty) { - int bufsiz = 0; + LONGEST bufsiz = 0; char buf[400]; char query[400]; char *p; @@ -1367,22 +1367,23 @@ avr_io_reg_read_command (char *args, int from_tty) unsigned int val; int i, j, k, step; - if (!current_target.to_query) + /* Just get the maximum buffer size. */ + bufsiz = target_read_partial (¤t_target, TARGET_OBJECT_AVR, + NULL, NULL, 0, 0); + if (bufsiz < 0) { fprintf_unfiltered (gdb_stderr, "ERR: info io_registers NOT supported by current " "target\n"); return; } - - /* Just get the maximum buffer size. */ - target_query ((int) 'R', 0, 0, &bufsiz); if (bufsiz > sizeof (buf)) bufsiz = sizeof (buf); /* Find out how many io registers the target has. */ strcpy (query, "avr.io_reg"); - target_query ((int) 'R', query, buf, &bufsiz); + target_read_partial (¤t_target, TARGET_OBJECT_AVR, query, buf, 0, + bufsiz); if (strncmp (buf, "", bufsiz) == 0) { @@ -1413,7 +1414,8 @@ avr_io_reg_read_command (char *args, int from_tty) j = nreg - i; /* last block is less than 8 registers */ snprintf (query, sizeof (query) - 1, "avr.io_reg:%x,%x", i, j); - target_query ((int) 'R', query, buf, &bufsiz); + target_read_partial (¤t_target, TARGET_OBJECT_AVR, query, buf, + 0, bufsiz); p = buf; for (k = i; k < (i + j); k++) diff --git a/gdb/kod.c b/gdb/kod.c index 8f565bb8c3..e2bae91338 100644 --- a/gdb/kod.c +++ b/gdb/kod.c @@ -87,11 +87,13 @@ gdb_kod_display (char *arg) static void gdb_kod_query (char *arg, char *result, int *maxsiz) { - int bufsiz = 0; + LONGEST bufsiz = 0; - /* Check if current target has remote_query capabilities. - If not, it does not have kod either. */ - if (! current_target.to_query) + /* Check if current target has remote_query capabilities. If not, + it does not have kod either. */ + bufsiz = target_read_partial (¤t_target, TARGET_OBJECT_KOD, + NULL, NULL, 0, 0); + if (bufsiz < 0) { strcpy (result, "ERR: Kernel Object Display not supported by current target\n"); @@ -99,7 +101,6 @@ gdb_kod_query (char *arg, char *result, int *maxsiz) } /* Just get the maximum buffer size. */ - target_query ((int) 'K', 0, 0, &bufsiz); /* Check if *we* were called just for getting the buffer size. */ if (*maxsiz == 0) @@ -119,7 +120,8 @@ gdb_kod_query (char *arg, char *result, int *maxsiz) error ("kod: query argument too long"); /* Send actual request. */ - if (target_query ((int) 'K', arg, result, &bufsiz)) + if (target_read_partial (¤t_target, TARGET_OBJECT_KOD, + arg, result, 0, bufsiz) < 0) strcpy (result, "ERR: remote query failed"); } diff --git a/gdb/remote.c b/gdb/remote.c index e5bd792dd5..fc25c61453 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -161,8 +161,6 @@ static int ishex (int ch, int *val); static int stubhex (int ch); -static int remote_query (int /*char */ , char *, char *, int *); - static int hexnumstr (char *, ULONGEST); static int hexnumnstr (char *, ULONGEST, int); @@ -5103,41 +5101,47 @@ the loaded file\n"); printf_filtered ("No loaded section named '%s'.\n", args); } -static int -remote_query (int query_type, char *buf, char *outbuf, int *bufsiz) +static LONGEST +remote_read_partial (struct target_ops *ops, enum target_object object, + const char *annex, void *buf, + ULONGEST offset, LONGEST len) { struct remote_state *rs = get_remote_state (); int i; char *buf2 = alloca (rs->remote_packet_size); char *p2 = &buf2[0]; + char query_type; - if (!bufsiz) - error ("null pointer to remote bufer size specified"); - - /* minimum outbuf size is (rs->remote_packet_size) - if bufsiz is not large enough let - the caller know and return what the minimum size is */ - /* Note: a zero bufsiz can be used to query the minimum buffer size */ - if (*bufsiz < (rs->remote_packet_size)) + /* Map pre-existing objects onto letters. DO NOT do this for new + objects!!! Instead specify new query packets. */ + switch (object) { - *bufsiz = (rs->remote_packet_size); + case TARGET_OBJECT_KOD: + query_type = 'K'; + break; + case TARGET_OBJECT_AVR: + query_type = 'R'; + break; + default: return -1; } + /* Note: a zero BUF, OFFSET and LEN can be used to query the minimum + buffer size. */ + if (buf == NULL && offset == 0 && len == 0) + return (rs->remote_packet_size); + /* Minimum outbuf size is (rs->remote_packet_size) - if bufsiz is + not large enough let the caller. */ + if (len < (rs->remote_packet_size)) + return -1; + len = rs->remote_packet_size; + /* except for querying the minimum buffer size, target must be open */ if (!remote_desc) error ("remote query is only available after target open"); - /* we only take uppercase letters as query types, at least for now */ - if ((query_type < 'A') || (query_type > 'Z')) - error ("invalid remote query type"); - - if (!buf) - error ("null remote query specified"); - - if (!outbuf) - error ("remote query requires a buffer to receive data"); - - outbuf[0] = '\0'; + gdb_assert (annex != NULL); + gdb_assert (buf != NULL); *p2++ = 'q'; *p2++ = query_type; @@ -5147,27 +5151,23 @@ remote_query (int query_type, char *buf, char *outbuf, int *bufsiz) plus one extra in case we are debugging (remote_debug), we have PBUFZIZ - 7 left to pack the query string */ i = 0; - while (buf[i] && (i < ((rs->remote_packet_size) - 8))) + while (annex[i] && (i < ((rs->remote_packet_size) - 8))) { - /* bad caller may have sent forbidden characters */ - if ((!isprint (buf[i])) || (buf[i] == '$') || (buf[i] == '#')) - error ("illegal characters in query string"); - - *p2++ = buf[i]; + /* Bad caller may have sent forbidden characters. */ + gdb_assert (isprint (annex[i]) && annex[i] != '$' && annex[i] != '#'); + *p2++ = annex[i]; i++; } - *p2 = buf[i]; - - if (buf[i]) - error ("query larger than available buffer"); + *p2 = '\0'; + gdb_assert (annex[i] == '\0'); i = putpkt (buf2); if (i < 0) return i; - getpkt (outbuf, *bufsiz, 0); + getpkt (buf, len, 0); - return 0; + return strlen (buf); } static void @@ -5445,7 +5445,7 @@ Specify the serial device it is connected to\n\ remote_ops.to_pid_to_str = remote_pid_to_str; remote_ops.to_extra_thread_info = remote_threads_extra_info; remote_ops.to_stop = remote_stop; - remote_ops.to_query = remote_query; + remote_ops.to_read_partial = remote_read_partial; remote_ops.to_rcmd = remote_rcmd; remote_ops.to_stratum = process_stratum; remote_ops.to_has_all_memory = 1; @@ -5965,7 +5965,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya)."; remote_async_ops.to_pid_to_str = remote_pid_to_str; remote_async_ops.to_extra_thread_info = remote_threads_extra_info; remote_async_ops.to_stop = remote_stop; - remote_async_ops.to_query = remote_query; + remote_async_ops.to_read_partial = remote_read_partial; remote_async_ops.to_rcmd = remote_rcmd; remote_async_ops.to_stratum = process_stratum; remote_async_ops.to_has_all_memory = 1; diff --git a/gdb/target.c b/gdb/target.c index 9559914b77..252cb1473c 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -159,8 +159,6 @@ static int debug_to_thread_alive (ptid_t); static void debug_to_stop (void); -static int debug_to_query (int /*char */ , char *, char *, int *); - /* Pointer to array of target architecture structures; the size of the array; the current index into the array; the allocated size of the array. */ @@ -422,7 +420,8 @@ update_current_target (void) INHERIT (to_pid_to_str, t); INHERIT (to_extra_thread_info, t); INHERIT (to_stop, t); - INHERIT (to_query, t); + /* Do not inherit to_read_partial. */ + /* Do not inherit to_write_partial. */ INHERIT (to_rcmd, t); INHERIT (to_enable_exception_callback, t); INHERIT (to_get_current_exception_event, t); @@ -1056,6 +1055,90 @@ target_write_memory_partial (CORE_ADDR memaddr, char *buf, int len, int *err) return target_xfer_memory_partial (memaddr, buf, len, 1, err); } +/* More generic transfers. */ + +LONGEST +target_read_partial (struct target_ops *ops, + enum target_object object, + const char *annex, void *buf, + ULONGEST offset, LONGEST len) +{ + struct target_ops *op; + + /* Find the first target stratum that can handle the request. */ + for (op = ops; + op != NULL && op->to_read_partial == NULL; + op = op->beneath) + ; + if (op == NULL) + return -1; + + /* Now apply the operation at that level. */ + return op->to_read_partial (op, object, annex, buf, offset, len); +} + +LONGEST +target_write_partial (struct target_ops *ops, + enum target_object object, + const char *annex, const void *buf, + ULONGEST offset, LONGEST len) +{ + struct target_ops *op; + + /* Find the first target stratum that can handle the request. */ + for (op = ops; + op != NULL && op->to_write_partial == NULL; + op = op->beneath) + ; + if (op == NULL) + return -1; + + return op->to_write_partial (op, object, annex, buf, offset, len); +} + +/* Wrappers to perform the full transfer. */ +LONGEST +target_read (struct target_ops *ops, + enum target_object object, + const char *annex, void *buf, + ULONGEST offset, LONGEST len) +{ + LONGEST xfered = 0; + while (xfered < len) + { + LONGEST xfer = target_write_partial (ops, object, annex, + (bfd_byte *) buf + xfered, + offset + xfered, len - xfered); + /* Call an observer, notifying them of the xfer progress? */ + if (xfer < 0) + return xfer; + xfered += xfer; + QUIT; + } + return len; +} + +LONGEST +target_write (struct target_ops *ops, + enum target_object object, + const char *annex, const void *buf, + ULONGEST offset, LONGEST len) +{ + LONGEST xfered = 0; + while (xfered < len) + { + LONGEST xfer = target_write_partial (ops, object, annex, + (bfd_byte *) buf + xfered, + offset + xfered, len - xfered); + /* Call an observer, notifying them of the xfer progress? */ + if (xfer < 0) + return xfer; + xfered += xfer; + QUIT; + } + return len; +} + static void target_info (char *args, int from_tty) { @@ -2128,14 +2211,42 @@ debug_to_stop (void) fprintf_unfiltered (gdb_stdlog, "target_stop ()\n"); } -static int -debug_to_query (int type, char *req, char *resp, int *siz) +static LONGEST +debug_to_read_partial (struct target_ops *ops, + enum target_object object, + const char *annex, void *buf, + ULONGEST offset, LONGEST len) { - int retval; + LONGEST retval; - retval = debug_target.to_query (type, req, resp, siz); + retval = target_read_partial (&debug_target, object, annex, buf, offset, + len); - fprintf_unfiltered (gdb_stdlog, "target_query (%c, %s, %s, %d) = %d\n", type, req, resp, *siz, retval); + fprintf_unfiltered (gdb_stdlog, + "target_read_partial (%d, %s, 0x%lx, 0x%s, %s) = %s\n", + (int) object, (annex ? annex : "(null)"), + (long) buf, paddr_nz (offset), + paddr_d (len), paddr_d (retval)); + + return retval; +} + +static LONGEST +debug_to_write_partial (struct target_ops *ops, + enum target_object object, + const char *annex, const void *buf, + ULONGEST offset, LONGEST len) +{ + LONGEST retval; + + retval = target_write_partial (&debug_target, object, annex, buf, offset, + len); + + fprintf_unfiltered (gdb_stdlog, + "target_write_partial (%d, %s, 0x%lx, 0x%s, %s) = %s\n", + (int) object, (annex ? annex : "(null)"), + (long) buf, paddr_nz (offset), + paddr_d (len), paddr_d (retval)); return retval; } @@ -2237,7 +2348,8 @@ setup_target_debug (void) current_target.to_thread_alive = debug_to_thread_alive; current_target.to_find_new_threads = debug_to_find_new_threads; current_target.to_stop = debug_to_stop; - current_target.to_query = debug_to_query; + current_target.to_read_partial = debug_to_read_partial; + current_target.to_write_partial = debug_to_write_partial; current_target.to_rcmd = debug_to_rcmd; current_target.to_enable_exception_callback = debug_to_enable_exception_callback; current_target.to_get_current_exception_event = debug_to_get_current_exception_event; diff --git a/gdb/target.h b/gdb/target.h index 205b8ade14..b8c5a44b06 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -26,6 +26,7 @@ struct objfile; struct ui_file; struct mem_attrib; +struct target_ops; /* This include file defines the interface between the main part of the debugger, and the part which is target-specific, or @@ -175,6 +176,77 @@ extern char *target_signal_to_name (enum target_signal); /* Given a name (SIGHUP, etc.), return its signal. */ enum target_signal target_signal_from_name (char *); +/* Request the transfer of up to LEN 8-bit bytes of the target's + OBJECT. The OFFSET, for a seekable object, specifies the starting + point. The ANNEX can be used to provide additional data-specific + information to the target. + + Return the number of bytes actually transfered, zero when no + further transfer is possible, and -1 when the transfer is not + supported. + + NOTE: cagney/2003-10-17: The current interface does not support a + "retry" mechanism. Instead it assumes that at least one byte will + be transfered on each call. + + NOTE: cagney/2003-10-17: The current interface can lead to + fragmented transfers. Lower target levels should not implement + hacks, such as enlarging the transfer, in an attempt to compensate + for this. Instead, the target stack should be extended so that it + implements supply/collect methods and a look-aside object cache. + With that available, the lowest target can safely and freely "push" + data up the stack. + + NOTE: cagney/2003-10-17: Unlike the old query and the memory + transfer mechanisms, these methods are explicitly parameterized by + the target that it should be applied to. + + NOTE: cagney/2003-10-17: Just like the old query and memory xfer + methods, these new methods perform partial transfers. The only + difference is that these new methods thought to include "partial" + in the name. The old code's failure to do this lead to much + confusion and duplication of effort as each target object attempted + to locally take responsibility for something it didn't have to + worry about. + + NOTE: cagney/2003-10-17: For backward compatibility with the + "target_query" method that this replaced, when BUF, OFFSET and LEN + are NULL/zero, return the "minimum" buffer size. See "remote.c" + for further information. */ + +enum target_object +{ + /* Kernel Object Display transfer. See "kod.c" and "remote.c". */ + TARGET_OBJECT_KOD, + /* AVR target specific transfer. See "avr-tdep.c" and "remote.c". */ + TARGET_OBJECT_AVR, + /* Transfer up-to LEN bytes of memory starting at OFFSET. */ + TARGET_OBJECT_MEORY + /* Possible future ojbects: TARGET_OJBECT_FILE, TARGET_OBJECT_PROC, + TARGET_OBJECT_AUXV, ... */ +}; + +extern LONGEST target_read_partial (struct target_ops *ops, + enum target_object object, + const char *annex, void *buf, + ULONGEST offset, LONGEST len); + +extern LONGEST target_write_partial (struct target_ops *ops, + enum target_object object, + const char *annex, const void *buf, + ULONGEST offset, LONGEST len); + +/* Wrappers to perform the full transfer. */ +extern LONGEST target_read (struct target_ops *ops, + enum target_object object, + const char *annex, void *buf, + ULONGEST offset, LONGEST len); + +extern LONGEST target_write (struct target_ops *ops, + enum target_object object, + const char *annex, const void *buf, + ULONGEST offset, LONGEST len); + /* If certain kinds of activity happen, target_wait should perform callbacks. */ @@ -271,7 +343,6 @@ struct target_ops char *(*to_pid_to_str) (ptid_t); char *(*to_extra_thread_info) (struct thread_info *); void (*to_stop) (void); - int (*to_query) (int /*char */ , char *, char *, int *); void (*to_rcmd) (char *command, struct ui_file *output); struct symtab_and_line *(*to_enable_exception_callback) (enum exception_event_kind, @@ -311,6 +382,16 @@ struct target_ops struct objfile *objfile, CORE_ADDR offset); + /* See above. */ + LONGEST (*to_read_partial) (struct target_ops *ops, + enum target_object object, + const char *annex, void *buf, + ULONGEST offset, LONGEST len); + LONGEST (*to_write_partial) (struct target_ops *ops, + enum target_object object, + const char *annex, const void *buf, + ULONGEST offset, LONGEST len); + int to_magic; /* Need sub-structure for target machine related rather than comm related? */ @@ -722,16 +803,6 @@ extern void target_load (char *arg, int from_tty); #define target_stop current_target.to_stop -/* Queries the target side for some information. The first argument is a - letter specifying the type of the query, which is used to determine who - should process it. The second argument is a string that specifies which - information is desired and the third is a buffer that carries back the - response from the target side. The fourth parameter is the size of the - output buffer supplied. */ - -#define target_query(query_type, query, resp_buffer, bufffer_size) \ - (*current_target.to_query) (query_type, query, resp_buffer, bufffer_size) - /* Send the specified COMMAND to the target's monitor (shell,interpreter) for execution. The result of the query is placed in OUTBUF. */