aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog21
-rw-r--r--gdb/auxv.c44
-rw-r--r--gdb/auxv.h8
-rw-r--r--gdb/avr-tdep.c36
-rw-r--r--gdb/ia64-tdep.c30
-rw-r--r--gdb/linux-nat.c3
-rw-r--r--gdb/procfs.c3
-rw-r--r--gdb/remote.c46
-rw-r--r--gdb/sparc-tdep.c2
-rw-r--r--gdb/target.c80
-rw-r--r--gdb/target.h98
11 files changed, 206 insertions, 165 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index fdad78f..c1445bc 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,26 @@
2006-07-12 Daniel Jacobowitz <dan@codesourcery.com>
+ * target.c (target_read): Stop if target_read_partial returns 0
+ when some bytes have already been read.
+ (target_write): Likewise for target_write_partial.
+ (target_read_partial, target_write_partial): Make static.
+ (target_read_alloc): New.
+ * target.h: Doc fixes.
+ (target_read_partial, target_write_partial): Delete prototypes.
+ (target_read_alloc): New prototype.
+
+ * auxv.c (target_auxv_read): Delete.
+ (target_auxv_search, fprint_target_auxv): Use target_read_alloc.
+ * auxv.h (target_auxv_read): Delete prototype.
+ * avr-tdep.c (avr_io_reg_read_command): Use target_read_alloc.
+ * ia64-tdep.c (getunwind_table, get_kernel_table): Likewise.
+ * linux-nat.c (linux_nat_make_corefile_notes): Likewise.
+ * procfs.c (procfs_make_note_section): Likewise.
+ * remote.c (remote_xfer_partial): Don't loop here.
+ * sparc-tdep.c (sparc_fetch_wcookie): Use target_read.
+
+2006-07-12 Daniel Jacobowitz <dan@codesourcery.com>
+
* arm-linux-tdep.c: Doc fixes.
(ARM_SIGCONTEXT_R0, ARM_UCONTEXT_SIGCONTEXT)
(ARM_OLD_RT_SIGFRAME_SIGINFO, ARM_OLD_RT_SIGFRAME_UCONTEXT)
diff --git a/gdb/auxv.c b/gdb/auxv.c
index 557da3d..d822c7f 100644
--- a/gdb/auxv.c
+++ b/gdb/auxv.c
@@ -1,6 +1,6 @@
/* Auxiliary vector support for GDB, the GNU debugger.
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GDB.
@@ -76,43 +76,6 @@ procfs_xfer_auxv (struct target_ops *ops,
return n;
}
-/* Read all the auxv data into a contiguous xmalloc'd buffer,
- stored in *DATA. Return the size in bytes of this data.
- If zero, there is no data and *DATA is null.
- if < 0, there was an error and *DATA is null. */
-LONGEST
-target_auxv_read (struct target_ops *ops, gdb_byte **data)
-{
- size_t auxv_alloc = 512, auxv_pos = 0;
- gdb_byte *auxv = xmalloc (auxv_alloc);
- int n;
-
- while (1)
- {
- n = target_read_partial (ops, TARGET_OBJECT_AUXV,
- NULL, &auxv[auxv_pos], 0,
- auxv_alloc - auxv_pos);
- if (n <= 0)
- break;
- auxv_pos += n;
- if (auxv_pos < auxv_alloc) /* Read all there was. */
- break;
- gdb_assert (auxv_pos == auxv_alloc);
- auxv_alloc *= 2;
- auxv = xrealloc (auxv, auxv_alloc);
- }
-
- if (auxv_pos == 0)
- {
- xfree (auxv);
- *data = NULL;
- return n;
- }
-
- *data = auxv;
- return auxv_pos;
-}
-
/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
Return 0 if *READPTR is already at the end of the buffer.
Return -1 if there is insufficient buffer for a whole entry.
@@ -148,7 +111,7 @@ target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
{
CORE_ADDR type, val;
gdb_byte *data;
- int n = target_auxv_read (ops, &data);
+ LONGEST n = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL, &data);
gdb_byte *ptr = data;
int ents = 0;
@@ -184,7 +147,8 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
{
CORE_ADDR type, val;
gdb_byte *data;
- int len = target_auxv_read (ops, &data);
+ LONGEST len = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL,
+ &data);
gdb_byte *ptr = data;
int ents = 0;
diff --git a/gdb/auxv.h b/gdb/auxv.h
index 92f7b54..49723b8 100644
--- a/gdb/auxv.h
+++ b/gdb/auxv.h
@@ -1,6 +1,6 @@
/* Auxiliary vector support for GDB, the GNU debugger.
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GDB.
@@ -31,12 +31,6 @@
struct target_ops; /* Forward declaration. */
-/* Read all the auxv data into a contiguous xmalloc'd buffer,
- stored in *DATA. Return the size in bytes of this data.
- If zero, there is no data and *DATA is null.
- if < 0, there was an error and *DATA is null. */
-extern LONGEST target_auxv_read (struct target_ops *ops, gdb_byte **data);
-
/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
Return 0 if *READPTR is already at the end of the buffer.
Return -1 if there is insufficient buffer for a whole entry.
diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c
index 9c6566e..f61e5a0 100644
--- a/gdb/avr-tdep.c
+++ b/gdb/avr-tdep.c
@@ -1,7 +1,7 @@
/* Target-dependent code for Atmel AVR, for GDB.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005 Free Software Foundation, Inc.
+ 2005, 2006 Free Software Foundation, Inc.
This file is part of GDB.
@@ -1323,35 +1323,22 @@ static void
avr_io_reg_read_command (char *args, int from_tty)
{
LONGEST bufsiz = 0;
- char buf[400];
+ gdb_byte *buf;
char query[400];
char *p;
unsigned int nreg = 0;
unsigned int val;
int i, j, k, step;
- /* Just get the maximum buffer size. */
- bufsiz = target_read_partial (&current_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;
- }
- if (bufsiz > sizeof (buf))
- bufsiz = sizeof (buf);
-
/* Find out how many io registers the target has. */
- strcpy (query, "avr.io_reg");
- target_read_partial (&current_target, TARGET_OBJECT_AVR, query, buf, 0,
- bufsiz);
+ bufsiz = target_read_alloc (&current_target, TARGET_OBJECT_AVR,
+ "avr.io_reg", &buf);
- if (strncmp (buf, "", bufsiz) == 0)
+ if (bufsiz <= 0)
{
fprintf_unfiltered (gdb_stderr,
- _("info io_registers NOT supported by target\n"));
+ _("ERR: info io_registers NOT supported "
+ "by current target\n"));
return;
}
@@ -1359,9 +1346,12 @@ avr_io_reg_read_command (char *args, int from_tty)
{
fprintf_unfiltered (gdb_stderr,
_("Error fetching number of io registers\n"));
+ xfree (buf);
return;
}
+ xfree (buf);
+
reinitialize_more_filter ();
printf_unfiltered (_("Target has %u io registers:\n\n"), nreg);
@@ -1377,8 +1367,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_read_partial (&current_target, TARGET_OBJECT_AVR, query, buf,
- 0, bufsiz);
+ bufsiz = target_read_alloc (&current_target, TARGET_OBJECT_AVR,
+ query, &buf);
p = buf;
for (k = i; k < (i + j); k++)
@@ -1393,6 +1383,8 @@ avr_io_reg_read_command (char *args, int from_tty)
break;
}
}
+
+ xfree (buf);
}
}
diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c
index 897d272..a65c56f 100644
--- a/gdb/ia64-tdep.c
+++ b/gdb/ia64-tdep.c
@@ -1,7 +1,7 @@
/* Target-dependent code for the IA-64 for GDB, the GNU debugger.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software
- Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of GDB.
@@ -2458,8 +2458,8 @@ ia64_access_mem (unw_addr_space_t as,
}
/* Call low-level function to access the kernel unwind table. */
-static int
-getunwind_table (void *buf, size_t len)
+static LONGEST
+getunwind_table (gdb_byte **buf_p)
{
LONGEST x;
@@ -2470,10 +2470,11 @@ getunwind_table (void *buf, size_t len)
we want to preserve fall back to the running kernel's table, then
we should find a way to override the corefile layer's
xfer_partial method. */
- x = target_read_partial (&current_target, TARGET_OBJECT_UNWIND_TABLE, NULL,
- buf, 0, len);
- return (int)x;
+ x = target_read_alloc (&current_target, TARGET_OBJECT_UNWIND_TABLE,
+ NULL, buf_p);
+
+ return x;
}
/* Get the kernel unwind table. */
@@ -2484,14 +2485,15 @@ get_kernel_table (unw_word_t ip, unw_dyn_info_t *di)
if (!ktab)
{
+ gdb_byte *ktab_buf;
size_t size;
- size = getunwind_table (NULL, 0);
- if ((int)size < 0)
- return -UNW_ENOINFO;
- ktab_size = size;
- ktab = xmalloc (ktab_size);
- getunwind_table (ktab, ktab_size);
-
+
+ ktab_size = getunwind_table (&ktab_buf);
+ if (ktab_size <= 0)
+ return -UNW_ENOINFO;
+ else
+ ktab = (struct ia64_table_entry *) ktab_buf;
+
for (etab = ktab; etab->start_offset; ++etab)
etab->info_offset += KERNEL_START;
}
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 932119e..6c63ba9 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -2697,7 +2697,8 @@ linux_nat_make_corefile_notes (bfd *obfd, int *note_size)
note_data = thread_args.note_data;
}
- auxv_len = target_auxv_read (&current_target, &auxv);
+ auxv_len = target_read_alloc (&current_target, TARGET_OBJECT_AUXV,
+ NULL, &auxv);
if (auxv_len > 0)
{
note_data = elfcore_write_note (obfd, note_data, note_size,
diff --git a/gdb/procfs.c b/gdb/procfs.c
index 03fcadd..23ee3fb 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -6130,7 +6130,8 @@ procfs_make_note_section (bfd *obfd, int *note_size)
note_data = thread_args.note_data;
}
- auxv_len = target_auxv_read (&current_target, &auxv);
+ auxv_len = target_read_alloc (&current_target, TARGET_OBJECT_AUXV,
+ NULL, &auxv);
if (auxv_len > 0)
{
note_data = elfcore_write_note (obfd, note_data, note_size,
diff --git a/gdb/remote.c b/gdb/remote.c
index da0f5ca..eef8bf2 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -5147,35 +5147,23 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
case TARGET_OBJECT_AUXV:
if (remote_protocol_packets[PACKET_qPart_auxv].support != PACKET_DISABLE)
{
- unsigned int total = 0;
- while (len > 0)
- {
- LONGEST n = min ((get_remote_packet_size () - 2) / 2, len);
- snprintf (rs->buf, get_remote_packet_size (),
- "qPart:auxv:read::%s,%s",
- phex_nz (offset, sizeof offset),
- phex_nz (n, sizeof n));
- i = putpkt (rs->buf);
- if (i < 0)
- return total > 0 ? total : i;
- rs->buf[0] = '\0';
- getpkt (&rs->buf, &rs->buf_size, 0);
- if (packet_ok (rs->buf, &remote_protocol_packets[PACKET_qPart_auxv])
- != PACKET_OK)
- return total > 0 ? total : -1;
- if (strcmp (rs->buf, "OK") == 0)
- break; /* Got EOF indicator. */
- /* Got some data. */
- i = hex2bin (rs->buf, readbuf, len);
- if (i > 0)
- {
- readbuf = (void *) ((char *) readbuf + i);
- offset += i;
- len -= i;
- total += i;
- }
- }
- return total;
+ LONGEST n = min ((get_remote_packet_size () - 2) / 2, len);
+ snprintf (rs->buf, get_remote_packet_size (),
+ "qPart:auxv:read::%s,%s",
+ phex_nz (offset, sizeof offset),
+ phex_nz (n, sizeof n));
+ i = putpkt (rs->buf);
+ if (i < 0)
+ return i;
+ rs->buf[0] = '\0';
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ if (packet_ok (rs->buf, &remote_protocol_packets[PACKET_qPart_auxv])
+ != PACKET_OK)
+ return -1;
+ if (strcmp (rs->buf, "OK") == 0)
+ return 0; /* Got EOF indicator. */
+ /* Got some data. */
+ return hex2bin (rs->buf, readbuf, len);
}
return -1;
diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
index 797e240..6c6f276 100644
--- a/gdb/sparc-tdep.c
+++ b/gdb/sparc-tdep.c
@@ -158,7 +158,7 @@ sparc_fetch_wcookie (void)
gdb_byte buf[8];
int len;
- len = target_read_partial (ops, TARGET_OBJECT_WCOOKIE, NULL, buf, 0, 8);
+ len = target_read (ops, TARGET_OBJECT_WCOOKIE, NULL, buf, 0, 8);
if (len == -1)
return 0;
diff --git a/gdb/target.c b/gdb/target.c
index bcb47de..c378ce5 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -1341,7 +1341,7 @@ default_xfer_partial (struct target_ops *ops, enum target_object object,
(inbuf, outbuf)", instead of separate read/write methods, make life
easier. */
-LONGEST
+static LONGEST
target_read_partial (struct target_ops *ops,
enum target_object object,
const char *annex, gdb_byte *buf,
@@ -1350,7 +1350,7 @@ target_read_partial (struct target_ops *ops,
return target_xfer_partial (ops, object, annex, buf, NULL, offset, len);
}
-LONGEST
+static LONGEST
target_write_partial (struct target_ops *ops,
enum target_object object,
const char *annex, const gdb_byte *buf,
@@ -1373,8 +1373,9 @@ target_read (struct target_ops *ops,
(gdb_byte *) buf + xfered,
offset + xfered, len - xfered);
/* Call an observer, notifying them of the xfer progress? */
- if (xfer <= 0)
- /* Call memory_error? */
+ if (xfer == 0)
+ return xfered;
+ if (xfer < 0)
return -1;
xfered += xfer;
QUIT;
@@ -1395,8 +1396,9 @@ target_write (struct target_ops *ops,
(gdb_byte *) buf + xfered,
offset + xfered, len - xfered);
/* Call an observer, notifying them of the xfer progress? */
- if (xfer <= 0)
- /* Call memory_error? */
+ if (xfer == 0)
+ return xfered;
+ if (xfer < 0)
return -1;
xfered += xfer;
QUIT;
@@ -1404,6 +1406,72 @@ target_write (struct target_ops *ops,
return len;
}
+/* Wrapper to perform a full read of unknown size. OBJECT/ANNEX will
+ be read using OPS. The return value will be -1 if the transfer
+ fails or is not supported; 0 if the object is empty; or the length
+ of the object otherwise. If a positive value is returned, a
+ sufficiently large buffer will be allocated using xmalloc and
+ returned in *BUF_P containing the contents of the object.
+
+ This method should be used for objects sufficiently small to store
+ in a single xmalloc'd buffer, when no fixed bound on the object's
+ size is known in advance. Don't try to read TARGET_OBJECT_MEMORY
+ through this function. */
+
+LONGEST
+target_read_alloc (struct target_ops *ops,
+ enum target_object object,
+ const char *annex, gdb_byte **buf_p)
+{
+ size_t buf_alloc, buf_pos;
+ gdb_byte *buf;
+ LONGEST n;
+
+ /* This function does not have a length parameter; it reads the
+ entire OBJECT). Also, it doesn't support objects fetched partly
+ from one target and partly from another (in a different stratum,
+ e.g. a core file and an executable). Both reasons make it
+ unsuitable for reading memory. */
+ gdb_assert (object != TARGET_OBJECT_MEMORY);
+
+ /* Start by reading up to 4K at a time. The target will throttle
+ this number down if necessary. */
+ buf_alloc = 4096;
+ buf = xmalloc (buf_alloc);
+ buf_pos = 0;
+ while (1)
+ {
+ n = target_read_partial (ops, object, annex, &buf[buf_pos],
+ buf_pos, buf_alloc - buf_pos);
+ if (n < 0)
+ {
+ /* An error occurred. */
+ xfree (buf);
+ return -1;
+ }
+ else if (n == 0)
+ {
+ /* Read all there was. */
+ if (buf_pos == 0)
+ xfree (buf);
+ else
+ *buf_p = buf;
+ return buf_pos;
+ }
+
+ buf_pos += n;
+
+ /* If the buffer is filling up, expand it. */
+ if (buf_alloc < buf_pos * 2)
+ {
+ buf_alloc *= 2;
+ buf = xrealloc (buf, buf_alloc);
+ }
+
+ QUIT;
+ }
+}
+
/* Memory transfer methods. */
void
diff --git a/gdb/target.h b/gdb/target.h
index 7018c52..2bb47fb 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -180,38 +180,8 @@ 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. */
+/* Target objects which can be transfered using target_read,
+ target_write, et cetera. */
enum target_object
{
@@ -229,17 +199,17 @@ enum target_object
/* Possible future objects: TARGET_OBJECT_FILE, TARGET_OBJECT_PROC, ... */
};
-extern LONGEST target_read_partial (struct target_ops *ops,
- enum target_object object,
- const char *annex, gdb_byte *buf,
- ULONGEST offset, LONGEST len);
+/* Request that OPS transfer 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.
-extern LONGEST target_write_partial (struct target_ops *ops,
- enum target_object object,
- const char *annex, const gdb_byte *buf,
- ULONGEST offset, LONGEST len);
+ Return the number of bytes actually transfered, or -1 if the
+ transfer is not supported or otherwise fails. Return of a positive
+ value less than LEN indicates that no further transfer is possible.
+ Unlike the raw to_xfer_partial interface, callers of these
+ functions do not need to retry partial transfers. */
-/* Wrappers to perform the full transfer. */
extern LONGEST target_read (struct target_ops *ops,
enum target_object object,
const char *annex, gdb_byte *buf,
@@ -250,6 +220,22 @@ extern LONGEST target_write (struct target_ops *ops,
const char *annex, const gdb_byte *buf,
ULONGEST offset, LONGEST len);
+/* Wrapper to perform a full read of unknown size. OBJECT/ANNEX will
+ be read using OPS. The return value will be -1 if the transfer
+ fails or is not supported; 0 if the object is empty; or the length
+ of the object otherwise. If a positive value is returned, a
+ sufficiently large buffer will be allocated using xmalloc and
+ returned in *BUF_P containing the contents of the object.
+
+ This method should be used for objects sufficiently small to store
+ in a single xmalloc'd buffer, when no fixed bound on the object's
+ size is known in advance. Don't try to read TARGET_OBJECT_MEMORY
+ through this function. */
+
+extern LONGEST target_read_alloc (struct target_ops *ops,
+ enum target_object object,
+ const char *annex, gdb_byte **buf_p);
+
/* Wrappers to target read/write that perform memory transfers. They
throw an error if the memory transfer fails.
@@ -409,9 +395,33 @@ struct target_ops
CORE_ADDR load_module_addr,
CORE_ADDR offset);
- /* Perform partial transfers on OBJECT. See target_read_partial
- and target_write_partial for details of each variant. One, and
- only one, of readbuf or writebuf must be non-NULL. */
+ /* Request that OPS transfer 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. Return of a positive value smaller than LEN does
+ not indicate the end of the object, only the end of the
+ transfer; higher level code should continue transferring if
+ desired. This is handled in target.c.
+
+ The interface does not support a "retry" mechanism. Instead it
+ assumes that at least one byte will be transfered on each
+ successful 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.
+
+ See target_read and target_write for more information. One,
+ and only one, of readbuf or writebuf must be non-NULL. */
+
LONGEST (*to_xfer_partial) (struct target_ops *ops,
enum target_object object, const char *annex,
gdb_byte *readbuf, const gdb_byte *writebuf,