+2014-02-11 Yao Qi <yao@codesourcery.com>
+
+ * target.h (enum target_xfer_error): Rename to ...
+ (enum target_xfer_status): ... it. New. All users updated.
+ (enum target_xfer_status) <TARGET_XFER_OK>, <TARGET_XFER_EOF>:
+ New.
+ (TARGET_XFER_STATUS_ERROR_P): New macro.
+ (target_xfer_error_to_string): Remove declaration.
+ (target_xfer_status_to_string): Declare.
+ (target_xfer_partial_ftype): Adjust it.
+ (struct target_ops) <to_xfer_partial>: Return
+ target_xfer_status. Add argument xfered_len. Update
+ comments.
+ * target.c (target_xfer_error_to_string): Rename to ...
+ (target_xfer_status_to_string): ... it. New. All callers
+ updated.
+ (target_read_live_memory): Likewise. Call target_xfer_partial
+ instead of target_read.
+ (memory_xfer_live_readonly_partial): Return
+ target_xfer_status. Add argument xfered_len.
+ (raw_memory_xfer_partial): Likewise.
+ (memory_xfer_partial_1): Likewise.
+ (memory_xfer_partial): Likewise.
+ (target_xfer_partial): Likewise. Check *XFERED_LEN is set
+ properly. Update debug message.
+ (default_xfer_partial, current_xfer_partial): Likewise.
+ (target_write_partial): Likewise.
+ (target_read_partial): Likewise. All callers updated.
+ (read_whatever_is_readable): Likewise.
+ (target_write_with_progress): Likewise.
+ (target_read_alloc_1): Likewise.
+
+ * aix-thread.c (aix_thread_xfer_partial): Likewise.
+ * auxv.c (procfs_xfer_auxv): Likewise.
+ (ld_so_xfer_auxv, memory_xfer_auxv): Likewise.
+ * bfd-target.c (target_bfd_xfer_partial): Likewise.
+ * bsd-kvm.c (bsd_kvm_xfer_partial): Likewise.
+ * bsd-uthread.c (bsd_uthread_xfer_partia): Likewise.
+ * corefile.c (read_memory): Adjust.
+ * corelow.c (core_xfer_partial): Likewise.
+ * ctf.c (ctf_xfer_partial): Likewise.
+ * darwin-nat.c (darwin_read_dyld_info): Likewise. All callers
+ updated.
+ (darwin_xfer_partial): Likewise.
+ * exec.c (section_table_xfer_memory_partial): Likewise. All
+ callers updated.
+ (exec_xfer_partial): Likewise.
+ * exec.h (section_table_xfer_memory_partial): Update
+ declaration.
+ * gnu-nat.c (gnu_xfer_memory): Likewise. Assert 'res' is not
+ negative.
+ (gnu_xfer_partial): Likewise.
+ * ia64-hpux-nat.c (ia64_hpux_xfer_memory_no_bs): Likewise.
+ (ia64_hpux_xfer_memory, ia64_hpux_xfer_uregs): Likewise.
+ (ia64_hpux_xfer_solib_got): Likewise.
+ * inf-ptrace.c (inf_ptrace_xfer_partial): Likewise. Change
+ type of 'partial_len' to ULONGEST.
+ * inf-ttrace.c (inf_ttrace_xfer_partial): Likewise.
+ * linux-nat.c (linux_xfer_siginfo ): Likewise.
+ (linux_nat_xfer_partial): Likewise.
+ (linux_proc_xfer_partial, linux_xfer_partial): Likewise.
+ (linux_proc_xfer_spu, linux_nat_xfer_osdata): Likewise.
+ * monitor.c (monitor_xfer_memory): Likewise.
+ (monitor_xfer_partial): Likewise.
+ * procfs.c (procfs_xfer_partial): Likewise.
+ * record-btrace.c (record_btrace_xfer_partial): Likewise.
+ * record-full.c (record_full_xfer_partial): Likewise.
+ (record_full_core_xfer_partial): Likewise.
+ * remote-sim.c (gdbsim_xfer_memory): Likewise.
+ (gdbsim_xfer_partial): Likewise.
+ * remote.c (remote_write_bytes_aux): Likewise. All callers
+ updated.
+ (remote_write_bytes, remote_read_bytes): Likewise. All
+ callers updated.
+ (remote_flash_erase): Likewise. All callers updated.
+ (remote_write_qxfer): Likewise. All callers updated.
+ (remote_read_qxfer): Likewise. All callers updated.
+ (remote_xfer_partial): Likewise.
+ * rs6000-nat.c (rs6000_xfer_partial): Likewise.
+ (rs6000_xfer_shared_libraries): Likewise.
+ * sol-thread.c (sol_thread_xfer_partial): Likewise.
+ (sol_thread_xfer_partial): Likewise.
+ * sparc-nat.c (sparc_xfer_wcookie): Likewise.
+ (sparc_xfer_partial): Likewise.
+ * spu-linux-nat.c (spu_proc_xfer_spu): Likewise. All callers
+ updated.
+ (spu_xfer_partial): Likewise.
+ * spu-multiarch.c (spu_xfer_partial): Likewise.
+ * tracepoint.c (tfile_xfer_partial): Likewise.
+ * windows-nat.c (windows_xfer_memory): Likewise.
+ (windows_xfer_shared_libraries): Likewise.
+ (windows_xfer_partial): Likewise.
+ * valprint.c: Replace 'target_xfer_error' with
+ 'target_xfer_status' in comments.
+
2014-02-11 Simon Marchi <simon.marchi@ericsson.com> (tiny patch)
Checked in by Joel Brobecker <brobecker@adacore.com>.
inferior's OBJECT:ANNEX space and GDB's READBUF/WRITEBUF buffer.
Return the number of bytes actually transferred. */
-static LONGEST
+static enum target_xfer_status
aix_thread_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
struct cleanup *old_chain = save_inferior_ptid ();
- LONGEST xfer;
+ enum target_xfer_status xfer;
struct target_ops *beneath = find_target_beneath (ops);
inferior_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
- xfer = beneath->to_xfer_partial (beneath, object, annex,
- readbuf, writebuf, offset, len);
+ xfer = beneath->to_xfer_partial (beneath, object, annex, readbuf,
+ writebuf, offset, len, xfered_len);
do_cleanups (old_chain);
return xfer;
/* This function handles access via /proc/PID/auxv, which is a common
method for native targets. */
-static LONGEST
+static enum target_xfer_status
procfs_xfer_auxv (gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset,
- ULONGEST len)
+ ULONGEST len,
+ ULONGEST *xfered_len)
{
char *pathname;
int fd;
- LONGEST n;
+ ssize_t l;
pathname = xstrprintf ("/proc/%d/auxv", ptid_get_pid (inferior_ptid));
fd = gdb_open_cloexec (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY, 0);
if (offset != (ULONGEST) 0
&& lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
- n = -1;
+ l = -1;
else if (readbuf != NULL)
- n = read (fd, readbuf, len);
+ l = read (fd, readbuf, (size_t) len);
else
- n = write (fd, writebuf, len);
+ l = write (fd, writebuf, (size_t) len);
(void) close (fd);
- return n;
+ if (l < 0)
+ return TARGET_XFER_E_IO;
+ else if (l == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = (ULONGEST) l;
+ return TARGET_XFER_OK;
+ }
}
/* This function handles access via ld.so's symbol `_dl_auxv'. */
-static LONGEST
+static enum target_xfer_status
ld_so_xfer_auxv (gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset,
- ULONGEST len)
+ ULONGEST len, ULONGEST *xfered_len)
{
struct minimal_symbol *msym;
CORE_ADDR data_address, pointer_address;
if (writebuf != NULL)
{
if (target_write_memory (data_address, writebuf, len) == 0)
- return len;
+ {
+ *xfered_len = (ULONGEST) len;
+ return TARGET_XFER_OK;
+ }
else
return TARGET_XFER_E_IO;
}
return TARGET_XFER_E_IO;
if (extract_typed_address (ptr_buf, ptr_type) == AT_NULL)
- return 0;
+ return TARGET_XFER_EOF;
}
retval = 0;
block &= -auxv_pair_size;
if (block == 0)
- return retval;
+ break;
if (target_read_memory (data_address, readbuf, block) != 0)
{
if (block <= auxv_pair_size)
- return retval;
+ break;
block = auxv_pair_size;
continue;
retval += auxv_pair_size;
if (extract_typed_address (readbuf, ptr_type) == AT_NULL)
- return retval;
+ {
+ *xfered_len = (ULONGEST) retval;
+ return TARGET_XFER_OK;
+ }
readbuf += auxv_pair_size;
block -= auxv_pair_size;
}
}
- return retval;
+ *xfered_len = (ULONGEST) retval;
+ return TARGET_XFER_OK;
}
/* This function is called like a to_xfer_partial hook, but must be
called with TARGET_OBJECT_AUXV. It handles access to AUXV. */
-LONGEST
+enum target_xfer_status
memory_xfer_auxv (struct target_ops *ops,
enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset,
- ULONGEST len)
+ ULONGEST len, ULONGEST *xfered_len)
{
gdb_assert (object == TARGET_OBJECT_AUXV);
gdb_assert (readbuf || writebuf);
if (current_inferior ()->attach_flag != 0)
{
- LONGEST retval;
+ enum target_xfer_status ret;
- retval = ld_so_xfer_auxv (readbuf, writebuf, offset, len);
- if (retval != -1)
- return retval;
+ ret = ld_so_xfer_auxv (readbuf, writebuf, offset, len, xfered_len);
+ if (ret != TARGET_XFER_E_IO)
+ return ret;
}
- return procfs_xfer_auxv (readbuf, writebuf, offset, len);
+ return procfs_xfer_auxv (readbuf, writebuf, offset, len, xfered_len);
}
/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
struct target_section_table table;
};
-static LONGEST
+static enum target_xfer_status
target_bfd_xfer_partial (struct target_ops *ops,
enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
switch (object)
{
{
struct target_bfd_data *data = ops->to_data;
return section_table_xfer_memory_partial (readbuf, writebuf,
- offset, len,
+ offset, len, xfered_len,
data->table.sections,
data->table.sections_end,
NULL);
return nbytes;
}
-static LONGEST
+static enum target_xfer_status
bsd_kvm_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
switch (object)
{
case TARGET_OBJECT_MEMORY:
- return bsd_kvm_xfer_memory (offset, len, readbuf, writebuf);
+ {
+ LONGEST ret = bsd_kvm_xfer_memory (offset, len, readbuf, writebuf);
+
+ if (ret < 0)
+ return TARGET_XFER_E_IO;
+ else if (ret == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = (ULONGEST) ret;
+ return TARGET_XFER_OK;
+ }
+ }
default:
return TARGET_XFER_E_IO;
/* FIXME: This function is only there because otherwise GDB tries to
invoke deprecate_xfer_memory. */
-static LONGEST
+static enum target_xfer_status
bsd_uthread_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
gdb_assert (ops->beneath->to_xfer_partial);
return ops->beneath->to_xfer_partial (ops->beneath, object, annex, readbuf,
- writebuf, offset, len);
+ writebuf, offset, len, xfered_len);
}
static ptid_t
\f
char *
-memory_error_message (enum target_xfer_error err,
+memory_error_message (enum target_xfer_status err,
struct gdbarch *gdbarch, CORE_ADDR memaddr)
{
switch (err)
paddress (gdbarch, memaddr));
default:
internal_error (__FILE__, __LINE__,
- "unhandled target_xfer_error: %s (%s)",
- target_xfer_error_to_string (err),
+ "unhandled target_xfer_status: %s (%s)",
+ target_xfer_status_to_string (err),
plongest (err));
}
}
/* Report a memory error by throwing a suitable exception. */
void
-memory_error (enum target_xfer_error err, CORE_ADDR memaddr)
+memory_error (enum target_xfer_status err, CORE_ADDR memaddr)
{
char *str;
enum errors exception = GDB_NO_ERROR;
void
read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
{
- LONGEST xfered = 0;
+ ULONGEST xfered = 0;
while (xfered < len)
{
- LONGEST xfer = target_xfer_partial (current_target.beneath,
- TARGET_OBJECT_MEMORY, NULL,
- myaddr + xfered, NULL,
- memaddr + xfered, len - xfered);
+ enum target_xfer_status status;
+ ULONGEST xfered_len;
- if (xfer == 0)
+ status = target_xfer_partial (current_target.beneath,
+ TARGET_OBJECT_MEMORY, NULL,
+ myaddr + xfered, NULL,
+ memaddr + xfered, len - xfered,
+ &xfered_len);
+
+ if (status == TARGET_XFER_EOF)
memory_error (TARGET_XFER_E_IO, memaddr + xfered);
- if (xfer < 0)
- memory_error (xfer, memaddr + xfered);
- xfered += xfer;
+
+ if (TARGET_XFER_STATUS_ERROR_P (status))
+ memory_error (status, memaddr + xfered);
+
+ gdb_assert (status == TARGET_XFER_OK);
+ xfered += xfered_len;
QUIT;
}
}
return len;
}
-static LONGEST
+static enum target_xfer_status
core_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
- ULONGEST len)
+ ULONGEST len, ULONGEST *xfered_len)
{
switch (object)
{
case TARGET_OBJECT_MEMORY:
return section_table_xfer_memory_partial (readbuf, writebuf,
- offset, len,
+ offset, len, xfered_len,
core_data->sections,
core_data->sections_end,
NULL);
size = bfd_section_size (core_bfd, section);
if (offset >= size)
- return 0;
+ return TARGET_XFER_EOF;
size -= offset;
if (size > len)
size = len;
- if (size > 0
- && !bfd_get_section_contents (core_bfd, section, readbuf,
- (file_ptr) offset, size))
+
+ if (size == 0)
+ return TARGET_XFER_EOF;
+ if (!bfd_get_section_contents (core_bfd, section, readbuf,
+ (file_ptr) offset, size))
{
warning (_("Couldn't read NT_AUXV note in core file."));
return TARGET_XFER_E_IO;
}
- return size;
+ *xfered_len = (ULONGEST) size;
+ return TARGET_XFER_OK;
}
return TARGET_XFER_E_IO;
size -= offset;
if (size > len)
size = len;
- if (size > 0
- && !bfd_get_section_contents (core_bfd, section, readbuf,
- (file_ptr) offset, size))
+
+ if (size == 0)
+ return TARGET_XFER_EOF;
+ if (!bfd_get_section_contents (core_bfd, section, readbuf,
+ (file_ptr) offset, size))
{
warning (_("Couldn't read StackGhost cookie in core file."));
return TARGET_XFER_E_IO;
}
- return size;
+ *xfered_len = (ULONGEST) size;
+ return TARGET_XFER_OK;
+
}
return TARGET_XFER_E_IO;
{
if (writebuf)
return TARGET_XFER_E_IO;
- return
- gdbarch_core_xfer_shared_libraries (core_gdbarch,
- readbuf, offset, len);
+ else
+ {
+ *xfered_len = gdbarch_core_xfer_shared_libraries (core_gdbarch,
+ readbuf,
+ offset, len);
+
+ if (*xfered_len == 0)
+ return TARGET_XFER_EOF;
+ else
+ return TARGET_XFER_OK;
+ }
}
/* FALL THROUGH */
{
if (writebuf)
return TARGET_XFER_E_IO;
- return
- gdbarch_core_xfer_shared_libraries_aix (core_gdbarch,
- readbuf, offset, len);
+ else
+ {
+ *xfered_len
+ = gdbarch_core_xfer_shared_libraries_aix (core_gdbarch,
+ readbuf, offset,
+ len);
+
+ if (*xfered_len == 0)
+ return TARGET_XFER_EOF;
+ else
+ return TARGET_XFER_OK;
+ }
}
/* FALL THROUGH */
size = bfd_section_size (core_bfd, section);
if (offset >= size)
- return 0;
+ return TARGET_XFER_EOF;
size -= offset;
if (size > len)
size = len;
- if (size > 0
- && !bfd_get_section_contents (core_bfd, section, readbuf,
- (file_ptr) offset, size))
+
+ if (size == 0)
+ return TARGET_XFER_EOF;
+ if (!bfd_get_section_contents (core_bfd, section, readbuf,
+ (file_ptr) offset, size))
{
warning (_("Couldn't read SPU section in core file."));
return TARGET_XFER_E_IO;
}
- return size;
+ *xfered_len = (ULONGEST) size;
+ return TARGET_XFER_OK;
}
else if (readbuf)
{
list.pos = 0;
list.written = 0;
bfd_map_over_sections (core_bfd, add_to_spuid_list, &list);
- return list.written;
+
+ if (list.written == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = (ULONGEST) list.written;
+ return TARGET_XFER_OK;
+ }
}
return TARGET_XFER_E_IO;
case TARGET_OBJECT_SIGNAL_INFO:
if (readbuf)
- return get_core_siginfo (core_bfd, readbuf, offset, len);
+ {
+ LONGEST l = get_core_siginfo (core_bfd, readbuf, offset, len);
+
+ if (l > 0)
+ {
+ *xfered_len = len;
+ return TARGET_XFER_OK;
+ }
+ }
return TARGET_XFER_E_IO;
default:
if (ops->beneath != NULL)
return ops->beneath->to_xfer_partial (ops->beneath, object,
annex, readbuf,
- writebuf, offset, len);
+ writebuf, offset, len,
+ xfered_len);
return TARGET_XFER_E_IO;
}
}
OFFSET is within the range, read the contents from events to
READBUF. */
-static LONGEST
+static enum target_xfer_status
ctf_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
- ULONGEST len)
+ ULONGEST len, ULONGEST *xfered_len)
{
/* We're only doing regular memory for now. */
if (object != TARGET_OBJECT_MEMORY)
/* Restore the position. */
bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), pos);
- return amt;
+ if (amt == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = amt;
+ return TARGET_XFER_OK;
+ }
}
if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0)
amt = bfd_get_section_contents (exec_bfd, s,
readbuf, offset - vma, amt);
- return amt;
+
+ if (amt == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = amt;
+ return TARGET_XFER_OK;
+ }
}
}
}
#ifdef TASK_DYLD_INFO_COUNT
/* This is not available in Darwin 9. */
-static int
+static enum target_xfer_status
darwin_read_dyld_info (task_t task, CORE_ADDR addr, gdb_byte *rdaddr,
- ULONGEST length)
+ ULONGEST length, ULONGEST *xfered_len)
{
struct task_dyld_info task_dyld_info;
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
kern_return_t kret;
if (addr >= sz)
- return 0;
+ return TARGET_XFER_EOF;
kret = task_info (task, TASK_DYLD_INFO, (task_info_t) &task_dyld_info, &count);
MACH_CHECK_ERROR (kret);
if (addr + length > sz)
length = sz - addr;
memcpy (rdaddr, (char *)&task_dyld_info + addr, length);
- return length;
+ *xfered_len = (ULONGEST) length;
+ return TARGET_XFER_OK;
}
#endif
darwin_xfer_partial (struct target_ops *ops,
enum target_object object, const char *annex,
gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
struct inferior *inf = current_inferior ();
switch (object)
{
case TARGET_OBJECT_MEMORY:
- return darwin_read_write_inferior (inf->private->task, offset,
- readbuf, writebuf, len);
+ {
+ int l = darwin_read_write_inferior (inf->private->task, offset,
+ readbuf, writebuf, len);
+
+ if (l == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ gdb_assert (l > 0);
+ *xfered_len = (ULONGEST) l;
+ return TARGET_XFER_OK;
+ }
+ }
#ifdef TASK_DYLD_INFO_COUNT
case TARGET_OBJECT_DARWIN_DYLD_INFO:
if (writebuf != NULL || readbuf == NULL)
/* Support only read. */
return TARGET_XFER_E_IO;
}
- return darwin_read_dyld_info (inf->private->task, offset, readbuf, len);
+ return darwin_read_dyld_info (inf->private->task, offset, readbuf, len,
+ xfered_len);
#endif
default:
return TARGET_XFER_E_IO;
return memory;
}
-int
+enum target_xfer_status
section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len,
struct target_section *sections,
struct target_section *sections_end,
const char *section_name)
res = bfd_get_section_contents (abfd, asect,
readbuf, memaddr - p->addr,
len);
- return (res != 0) ? len : 0;
+
+ if (res != 0)
+ {
+ *xfered_len = len;
+ return TARGET_XFER_OK;
+ }
+ else
+ return TARGET_XFER_EOF;
}
else if (memaddr >= p->endaddr)
{
res = bfd_get_section_contents (abfd, asect,
readbuf, memaddr - p->addr,
len);
- return (res != 0) ? len : 0;
+ if (res != 0)
+ {
+ *xfered_len = len;
+ return TARGET_XFER_OK;
+ }
+ else
+ return TARGET_XFER_EOF;
}
}
}
- return 0; /* We can't help. */
+ return TARGET_XFER_EOF; /* We can't help. */
}
static struct target_section_table *
return current_target_sections;
}
-static LONGEST
+static enum target_xfer_status
exec_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
struct target_section_table *table = target_get_section_table (ops);
if (object == TARGET_OBJECT_MEMORY)
return section_table_xfer_memory_partial (readbuf, writebuf,
- offset, len,
+ offset, len, xfered_len,
table->sections,
table->sections_end,
NULL);
One, and only one, of readbuf or writebuf must be non-NULL. */
-extern int section_table_xfer_memory_partial (gdb_byte *, const gdb_byte *,
- ULONGEST, ULONGEST,
- struct target_section *,
- struct target_section *,
- const char *);
+extern enum target_xfer_status
+ section_table_xfer_memory_partial (gdb_byte *,
+ const gdb_byte *,
+ ULONGEST, ULONGEST, ULONGEST *,
+ struct target_section *,
+ struct target_section *,
+ const char *);
/* Set the loaded address of a section. */
extern void exec_set_section_address (const char *, int, CORE_ADDR);
/* Report a memory error with error(). */
-extern void memory_error (enum target_xfer_error status, CORE_ADDR memaddr);
+extern void memory_error (enum target_xfer_status status, CORE_ADDR memaddr);
/* The string 'memory_error' would use as exception message. Space
for the result is malloc'd, caller must free. */
-extern char *memory_error_message (enum target_xfer_error err,
+extern char *memory_error_message (enum target_xfer_status err,
struct gdbarch *gdbarch, CORE_ADDR memaddr);
/* Like target_read_memory, but report an error if can't read. */
/* Helper for gnu_xfer_partial that handles memory transfers. */
-static LONGEST
+static enum target_xfer_status
gnu_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf,
- CORE_ADDR memaddr, ULONGEST len)
+ CORE_ADDR memaddr, ULONGEST len, ULONGEST *xfered_len)
{
task_t task = (gnu_current_inf
? (gnu_current_inf->task
host_address_to_string (readbuf));
res = gnu_read_inferior (task, memaddr, readbuf, len);
}
+ gdb_assert (res >= 0);
if (res == 0)
return TARGET_XFER_E_IO;
- return res;
+ else
+ {
+ *xfered_len = (ULONGEST) res;
+ return TARGET_XFER_OK;
+ }
}
/* Target to_xfer_partial implementation. */
-static LONGEST
+static enum target_xfer_status
gnu_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
switch (object)
{
case TARGET_OBJECT_MEMORY:
- return gnu_xfer_memory (readbuf, writebuf, offset, len);
-
+ return gnu_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
default:
return TARGET_XFER_E_IO;
}
/* The "xfer_partial" routine for a memory region that is completely
outside of the backing-store region. */
-static LONGEST
+static enum target_xfer_status
ia64_hpux_xfer_memory_no_bs (struct target_ops *ops, const char *annex,
gdb_byte *readbuf, const gdb_byte *writebuf,
- CORE_ADDR addr, LONGEST len)
+ CORE_ADDR addr, LONGEST len,
+ ULONGEST *xfered_len)
{
/* Memory writes need to be aligned on 16byte boundaries, at least
when writing in the text section. On the other hand, the size
NULL /* write */,
aligned_addr, addr - aligned_addr);
if (status <= 0)
- return 0;
+ return TARGET_XFER_EOF;
memcpy (aligned_buf + (addr - aligned_addr), writebuf, len);
return super_xfer_partial (ops, TARGET_OBJECT_MEMORY, annex,
NULL /* read */, aligned_buf /* write */,
- aligned_addr, aligned_len);
+ aligned_addr, aligned_len, xfered_len);
}
else
/* Memory read or properly aligned memory write. */
return super_xfer_partial (ops, TARGET_OBJECT_MEMORY, annex, readbuf,
- writebuf, addr, len);
+ writebuf, addr, len, xfered_len);
}
/* Read LEN bytes at ADDR from memory, and store it in BUF. This memory
/* The "xfer_partial" target_ops routine for ia64-hpux, in the case
where the requested object is TARGET_OBJECT_MEMORY. */
-static LONGEST
+static enum target_xfer_status
ia64_hpux_xfer_memory (struct target_ops *ops, const char *annex,
gdb_byte *readbuf, const gdb_byte *writebuf,
- CORE_ADDR addr, ULONGEST len)
+ CORE_ADDR addr, ULONGEST len, ULONGEST *xfered_len)
{
CORE_ADDR bsp, bspstore;
CORE_ADDR start_addr, short_len;
status = ia64_hpux_xfer_memory_no_bs (ops, annex, readbuf, writebuf,
addr, short_len);
if (status <= 0)
- return 0;
+ return TARGET_XFER_EOF;
}
/* 2. Memory region after BSP. */
writebuf ? writebuf + (start_addr - addr) : NULL,
start_addr, short_len);
if (status <= 0)
- return 0;
+ return TARGET_XFER_EOF;
}
/* 3. Memory region between BSPSTORE and BSP. */
writebuf ? writebuf + (start_addr - addr) : NULL,
start_addr, short_len);
if (status < 0)
- return 0;
+ return TARGET_XFER_EOF;
}
- return len;
+ *xfered_len = len;
+ return TARGET_XFER_OK;
}
/* Handle the transfer of TARGET_OBJECT_HPUX_UREGS objects on ia64-hpux.
we do not currently do not need these transfers), and will raise
a failed assertion if WRITEBUF is not NULL. */
-static LONGEST
+static enum target_xfer_status
ia64_hpux_xfer_uregs (struct target_ops *ops, const char *annex,
gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST offset, LONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
int status;
status = ia64_hpux_read_register_from_save_state_t (offset, readbuf, len);
if (status < 0)
return TARGET_XFER_E_IO;
- return len;
+
+ *xfered_len = (ULONGEST) len;
+ return TARGET_XFER_OK;
}
/* Handle the transfer of TARGET_OBJECT_HPUX_SOLIB_GOT objects on ia64-hpux.
we do not currently do not need these transfers), and will raise
a failed assertion if WRITEBUF is not NULL. */
-static LONGEST
+static enum target_xfer_status
ia64_hpux_xfer_solib_got (struct target_ops *ops, const char *annex,
gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
CORE_ADDR fun_addr;
/* The linkage pointer. We use a uint64_t to make sure that the size
gdb_assert (writebuf == NULL);
if (offset > sizeof (got))
- return 0;
+ return TARGET_XFER_EOF;
fun_addr = string_to_core_addr (annex);
got = ia64_hpux_get_solib_linkage_addr (fun_addr);
len = sizeof (got) - offset;
memcpy (readbuf, &got + offset, len);
- return len;
+ *xfered_len = (ULONGEST) len;
+ return TARGET_XFER_OK;
}
/* The "to_xfer_partial" target_ops routine for ia64-hpux. */
-static LONGEST
+static enum target_xfer_status
ia64_hpux_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
- LONGEST val;
+ enum target_xfer_status val;
if (object == TARGET_OBJECT_MEMORY)
- val = ia64_hpux_xfer_memory (ops, annex, readbuf, writebuf, offset, len);
+ val = ia64_hpux_xfer_memory (ops, annex, readbuf, writebuf, offset, len,
+ xfered_len);
else if (object == TARGET_OBJECT_HPUX_UREGS)
- val = ia64_hpux_xfer_uregs (ops, annex, readbuf, writebuf, offset, len);
+ val = ia64_hpux_xfer_uregs (ops, annex, readbuf, writebuf, offset, len,
+ xfered_len);
else if (object == TARGET_OBJECT_HPUX_SOLIB_GOT)
val = ia64_hpux_xfer_solib_got (ops, annex, readbuf, writebuf, offset,
- len);
+ len, xfered_len);
else
val = super_xfer_partial (ops, object, annex, readbuf, writebuf, offset,
- len);
+ len, xfered_len);
return val;
}
inferior's OBJECT:ANNEX space and GDB's READBUF/WRITEBUF buffer.
Return the number of bytes actually transferred. */
-static LONGEST
+static enum target_xfer_status
inf_ptrace_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
pid_t pid = ptid_get_pid (inferior_ptid);
errno = 0;
if (ptrace (PT_IO, pid, (caddr_t)&piod, 0) == 0)
- /* Return the actual number of bytes read or written. */
- return piod.piod_len;
+ {
+ *xfered_len = piod.piod_len;
+ /* Return the actual number of bytes read or written. */
+ return TARGET_XFER_OK;
+ }
/* If the PT_IO request is somehow not supported, fallback on
using PT_WRITE_D/PT_READ_D. Otherwise we will return zero
to indicate failure. */
if (errno != EINVAL)
- return 0;
+ return TARGET_XFER_EOF;
}
#endif
{
gdb_byte byte[sizeof (PTRACE_TYPE_RET)];
} buffer;
ULONGEST rounded_offset;
- LONGEST partial_len;
+ ULONGEST partial_len;
/* Round the start offset down to the next long word
boundary. */
(PTRACE_TYPE_ARG3)(uintptr_t)rounded_offset,
buffer.word);
if (errno)
- return 0;
+ return TARGET_XFER_EOF;
}
}
(PTRACE_TYPE_ARG3)(uintptr_t)rounded_offset,
0);
if (errno)
- return 0;
+ return TARGET_XFER_EOF;
/* Copy appropriate bytes out of the buffer. */
memcpy (readbuf, buffer.byte + (offset - rounded_offset),
partial_len);
}
- return partial_len;
+ *xfered_len = partial_len;
+ return TARGET_XFER_OK;
}
case TARGET_OBJECT_UNWIND_TABLE:
errno = 0;
if (ptrace (PT_IO, pid, (caddr_t)&piod, 0) == 0)
- /* Return the actual number of bytes read or written. */
- return piod.piod_len;
+ {
+ *xfered_len = piod.piod_len;
+ /* Return the actual number of bytes read or written. */
+ return TARGET_XFER_OK;
+ }
}
#endif
return TARGET_XFER_E_IO;
return len;
}
-static LONGEST
+static enum target_xfer_status
inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
switch (object)
{
case TARGET_OBJECT_MEMORY:
- return inf_ttrace_xfer_memory (offset, len, readbuf, writebuf);
+ {
+ LONGEST val = inf_ttrace_xfer_memory (offset, len, readbuf, writebuf);
+
+ if (val == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = (ULONGEST) val;
+ return TARGET_XFER_OK;
+ }
+ }
case TARGET_OBJECT_UNWIND_TABLE:
return TARGET_XFER_E_IO;
}
}
-static LONGEST
+static enum target_xfer_status
linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
int pid;
siginfo_t siginfo;
return TARGET_XFER_E_IO;
}
- return len;
+ *xfered_len = len;
+ return TARGET_XFER_OK;
}
-static LONGEST
+static enum target_xfer_status
linux_nat_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
struct cleanup *old_chain;
- LONGEST xfer;
+ enum target_xfer_status xfer;
if (object == TARGET_OBJECT_SIGNAL_INFO)
return linux_xfer_siginfo (ops, object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
/* The target is connected but no live inferior is selected. Pass
this request down to a lower stratum (e.g., the executable
file). */
if (object == TARGET_OBJECT_MEMORY && ptid_equal (inferior_ptid, null_ptid))
- return 0;
+ return TARGET_XFER_EOF;
old_chain = save_inferior_ptid ();
inferior_ptid = pid_to_ptid (ptid_get_lwp (inferior_ptid));
xfer = linux_ops->to_xfer_partial (ops, object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
do_cleanups (old_chain);
return xfer;
can be much more efficient than banging away at PTRACE_PEEKTEXT,
but it doesn't support writes. */
-static LONGEST
+static enum target_xfer_status
linux_proc_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, LONGEST len)
+ ULONGEST offset, LONGEST len, ULONGEST *xfered_len)
{
LONGEST ret;
int fd;
/* Don't bother for one word. */
if (len < 3 * sizeof (long))
- return 0;
+ return TARGET_XFER_EOF;
/* We could keep this file open and cache it - possibly one per
thread. That requires some juggling, but is even faster. */
ptid_get_pid (inferior_ptid));
fd = gdb_open_cloexec (filename, O_RDONLY | O_LARGEFILE, 0);
if (fd == -1)
- return 0;
+ return TARGET_XFER_EOF;
/* If pread64 is available, use it. It's faster if the kernel
supports it (only one syscall), and it's 64-bit safe even on
ret = len;
close (fd);
- return ret;
+
+ if (ret == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = ret;
+ return TARGET_XFER_OK;
+ }
}
/* Implement the to_xfer_partial interface for the TARGET_OBJECT_SPU
object type, using the /proc file system. */
-static LONGEST
+
+static enum target_xfer_status
linux_proc_xfer_spu (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
char buf[128];
int fd = 0;
if (!readbuf)
return TARGET_XFER_E_IO;
else
- return spu_enumerate_spu_ids (pid, readbuf, offset, len);
+ {
+ LONGEST l = spu_enumerate_spu_ids (pid, readbuf, offset, len);
+
+ if (l < 0)
+ return TARGET_XFER_E_IO;
+ else if (l == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = (ULONGEST) l;
+ return TARGET_XFER_OK;
+ }
+ }
}
xsnprintf (buf, sizeof buf, "/proc/%d/fd/%s", pid, annex);
&& lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
{
close (fd);
- return 0;
+ return TARGET_XFER_EOF;
}
if (writebuf)
ret = read (fd, readbuf, (size_t) len);
close (fd);
- return ret;
+
+ if (ret < 0)
+ return TARGET_XFER_E_IO;
+ else if (ret == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = (ULONGEST) ret;
+ return TARGET_XFER_OK;
+ }
}
do_cleanups (cleanup);
}
-static LONGEST
+static enum target_xfer_status
linux_nat_xfer_osdata (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
gdb_assert (object == TARGET_OBJECT_OSDATA);
- return linux_common_xfer_osdata (annex, readbuf, offset, len);
+ *xfered_len = linux_common_xfer_osdata (annex, readbuf, offset, len);
+ if (*xfered_len == 0)
+ return TARGET_XFER_EOF;
+ else
+ return TARGET_XFER_OK;
}
-static LONGEST
+static enum target_xfer_status
linux_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
- LONGEST xfer;
+ enum target_xfer_status xfer;
if (object == TARGET_OBJECT_AUXV)
return memory_xfer_auxv (ops, object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
if (object == TARGET_OBJECT_OSDATA)
return linux_nat_xfer_osdata (ops, object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
if (object == TARGET_OBJECT_SPU)
return linux_proc_xfer_spu (ops, object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
/* GDB calculates all the addresses in possibly larget width of the address.
Address width needs to be masked before its final use - either by
}
xfer = linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf,
- offset, len);
- if (xfer != 0)
+ offset, len, xfered_len);
+ if (xfer != TARGET_XFER_EOF)
return xfer;
return super_xfer_partial (ops, object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
}
static void
/* Helper for monitor_xfer_partial that handles memory transfers.
Arguments are like target_xfer_partial. */
-static LONGEST
+static enum target_xfer_status
monitor_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST memaddr, ULONGEST len)
+ ULONGEST memaddr, ULONGEST len, ULONGEST *xfered_len)
{
int res;
res = monitor_read_memory (memaddr, readbuf, len);
}
- if (res == 0)
+ if (res <= 0)
return TARGET_XFER_E_IO;
- return res;
+ else
+ {
+ *xfered_len = (ULONGEST) res;
+ return TARGET_XFER_OK;
+ }
}
/* Target to_xfer_partial implementation. */
-static LONGEST
+static enum target_xfer_status
monitor_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
switch (object)
{
case TARGET_OBJECT_MEMORY:
- return monitor_xfer_memory (readbuf, writebuf, offset, len);
+ return monitor_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
default:
return TARGET_XFER_E_IO;
/* Perform a partial transfer to/from the specified object. For
memory transfers, fall back to the old memory xfer functions. */
-static LONGEST
+static enum target_xfer_status
procfs_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
switch (object)
{
#ifdef NEW_PROC_API
case TARGET_OBJECT_AUXV:
return memory_xfer_auxv (ops, object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
#endif
default:
if (ops->beneath != NULL)
return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
- readbuf, writebuf, offset, len);
+ readbuf, writebuf, offset, len,
+ xfered_len);
return TARGET_XFER_E_IO;
}
}
/* The to_xfer_partial method of target record-btrace. */
-static LONGEST
+static enum target_xfer_status
record_btrace_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
- ULONGEST len)
+ ULONGEST len, ULONGEST *xfered_len)
{
struct target_ops *t;
/* We do not allow writing memory in general. */
if (writebuf != NULL)
- return TARGET_XFER_E_UNAVAILABLE;
+ {
+ *xfered_len = len;
+ return TARGET_XFER_E_UNAVAILABLE;
+ }
/* We allow reading readonly memory. */
section = target_section_by_addr (ops, offset);
}
}
+ *xfered_len = len;
return TARGET_XFER_E_UNAVAILABLE;
}
}
for (ops = ops->beneath; ops != NULL; ops = ops->beneath)
if (ops->to_xfer_partial != NULL)
return ops->to_xfer_partial (ops, object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
+ *xfered_len = len;
return TARGET_XFER_E_UNAVAILABLE;
}
In replay mode, we cannot write memory unles we are willing to
invalidate the record/replay log from this point forward. */
-static LONGEST
+static enum target_xfer_status
record_full_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
- ULONGEST len)
+ ULONGEST len, ULONGEST *xfered_len)
{
if (!record_full_gdb_operation_disable
&& (object == TARGET_OBJECT_MEMORY
return record_full_beneath_to_xfer_partial
(record_full_beneath_to_xfer_partial_ops, object, annex,
- readbuf, writebuf, offset, len);
+ readbuf, writebuf, offset, len, xfered_len);
}
/* This structure represents a breakpoint inserted while the record
/* "to_xfer_partial" method for prec over corefile. */
-static LONGEST
+static enum target_xfer_status
record_full_core_xfer_partial (struct target_ops *ops,
enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
- ULONGEST len)
+ ULONGEST len, ULONGEST *xfered_len)
{
if (object == TARGET_OBJECT_MEMORY)
{
{
if (readbuf)
memset (readbuf, 0, len);
- return len;
+
+ *xfered_len = len;
+ return TARGET_XFER_OK;
}
/* Get record_full_core_buf_entry. */
for (entry = record_full_core_buf_list; entry;
&entry->buf))
{
xfree (entry);
- return 0;
+ return TARGET_XFER_EOF;
}
entry->prev = record_full_core_buf_list;
record_full_core_buf_list = entry;
return record_full_beneath_to_xfer_partial
(record_full_beneath_to_xfer_partial_ops,
object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
memcpy (readbuf, entry->buf + sec_offset,
(size_t) len);
}
- return len;
+ *xfered_len = len;
+ return TARGET_XFER_OK;
}
}
return record_full_beneath_to_xfer_partial
(record_full_beneath_to_xfer_partial_ops, object, annex,
- readbuf, writebuf, offset, len);
+ readbuf, writebuf, offset, len, xfered_len);
}
/* "to_insert_breakpoint" method for prec over corefile. */
/* Helper for gdbsim_xfer_partial that handles memory transfers.
Arguments are like target_xfer_partial. */
-static LONGEST
+static enum target_xfer_status
gdbsim_xfer_memory (struct target_ops *target,
gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST memaddr, ULONGEST len)
+ ULONGEST memaddr, ULONGEST len, ULONGEST *xfered_len)
{
struct sim_inferior_data *sim_data
= get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NOT_NEEDED);
request to be passed to a lower target, hopefully an exec
file. */
if (!target->to_has_memory (target))
- return 0;
+ return TARGET_XFER_EOF;
if (!sim_data->program_loaded)
error (_("No program loaded."));
if (remote_debug && len > 0)
dump_mem (readbuf, len);
}
- return l;
+ if (l > 0)
+ {
+ *xfered_len = (ULONGEST) l;
+ return TARGET_XFER_OK;
+ }
+ else if (l == 0)
+ return TARGET_XFER_EOF;
+ else
+ return TARGET_XFER_E_IO;
}
/* Target to_xfer_partial implementation. */
-static LONGEST
+static enum target_xfer_status
gdbsim_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
switch (object)
{
case TARGET_OBJECT_MEMORY:
- return gdbsim_xfer_memory (ops, readbuf, writebuf, offset, len);
+ return gdbsim_xfer_memory (ops, readbuf, writebuf, offset, len,
+ xfered_len);
default:
return TARGET_XFER_E_IO;
If USE_LENGTH is 0, then the <LENGTH> field and the preceding comma
are omitted.
- Returns the number of bytes transferred, or a negative value (an
- 'enum target_xfer_error' value) for error. Only transfer a single
- packet. */
+ Return the transferred status, error or OK (an
+ 'enum target_xfer_status' value). Save the number of bytes
+ transferred in *XFERED_LEN. Only transfer a single packet. */
-static LONGEST
+static enum target_xfer_status
remote_write_bytes_aux (const char *header, CORE_ADDR memaddr,
const gdb_byte *myaddr, ULONGEST len,
- char packet_format, int use_length)
+ ULONGEST *xfered_len, char packet_format,
+ int use_length)
{
struct remote_state *rs = get_remote_state ();
char *p;
_("remote_write_bytes_aux: bad packet format"));
if (len == 0)
- return 0;
+ return TARGET_XFER_EOF;
payload_size = get_memory_write_packet_size ();
/* Return NR_BYTES, not TODO, in case escape chars caused us to send
fewer bytes than we'd planned. */
- return nr_bytes;
+ *xfered_len = (ULONGEST) nr_bytes;
+ return TARGET_XFER_OK;
}
/* Write memory data directly to the remote machine.
MYADDR is the address of the buffer in our space.
LEN is the number of bytes.
- Returns number of bytes transferred, or a negative value (an 'enum
- target_xfer_error' value) for error. Only transfer a single
- packet. */
+ Return the transferred status, error or OK (an
+ 'enum target_xfer_status' value). Save the number of bytes
+ transferred in *XFERED_LEN. Only transfer a single packet. */
-static LONGEST
-remote_write_bytes (CORE_ADDR memaddr, const gdb_byte *myaddr, ULONGEST len)
+static enum target_xfer_status
+remote_write_bytes (CORE_ADDR memaddr, const gdb_byte *myaddr, ULONGEST len,
+ ULONGEST *xfered_len)
{
char *packet_format = 0;
}
return remote_write_bytes_aux (packet_format,
- memaddr, myaddr, len, packet_format[0], 1);
+ memaddr, myaddr, len, xfered_len,
+ packet_format[0], 1);
}
/* Read memory data directly from the remote machine.
MYADDR is the address of the buffer in our space.
LEN is the number of bytes.
- Returns number of bytes transferred, or a negative value (an 'enum
- target_xfer_error' value) for error. */
+ Return the transferred status, error or OK (an
+ 'enum target_xfer_status' value). Save the number of bytes
+ transferred in *XFERED_LEN. */
-static LONGEST
-remote_read_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, ULONGEST len)
+static enum target_xfer_status
+remote_read_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, ULONGEST len,
+ ULONGEST *xfered_len)
{
struct remote_state *rs = get_remote_state ();
int max_buf_size; /* Max size of packet output buffer. */
p = rs->buf;
i = hex2bin (p, myaddr, todo);
/* Return what we have. Let higher layers handle partial reads. */
- return i;
+ *xfered_len = (ULONGEST) i;
+ return TARGET_XFER_OK;
}
\f
do_cleanups (back_to);
}
-static LONGEST
-remote_flash_write (struct target_ops *ops,
- ULONGEST address, LONGEST length,
- const gdb_byte *data)
+static enum target_xfer_status
+remote_flash_write (struct target_ops *ops, ULONGEST address,
+ ULONGEST length, ULONGEST *xfered_len,
+ const gdb_byte *data)
{
int saved_remote_timeout = remote_timeout;
- LONGEST ret;
+ enum target_xfer_status ret;
struct cleanup *back_to = make_cleanup (restore_remote_timeout,
- &saved_remote_timeout);
+ &saved_remote_timeout);
remote_timeout = remote_flash_timeout;
- ret = remote_write_bytes_aux ("vFlashWrite:", address, data, length, 'X', 0);
+ ret = remote_write_bytes_aux ("vFlashWrite:", address, data, length,
+ xfered_len,'X', 0);
do_cleanups (back_to);
return ret;
into remote target. The number of bytes written to the remote
target is returned, or -1 for error. */
-static LONGEST
+static enum target_xfer_status
remote_write_qxfer (struct target_ops *ops, const char *object_name,
const char *annex, const gdb_byte *writebuf,
- ULONGEST offset, LONGEST len,
+ ULONGEST offset, LONGEST len, ULONGEST *xfered_len,
struct packet_config *packet)
{
int i, buf_len;
return TARGET_XFER_E_IO;
unpack_varlen_hex (rs->buf, &n);
- return n;
+
+ *xfered_len = n;
+ return TARGET_XFER_OK;
}
/* Read OBJECT_NAME/ANNEX from the remote target using a qXfer packet.
EOF. PACKET is checked and updated to indicate whether the remote
target supports this object. */
-static LONGEST
+static enum target_xfer_status
remote_read_qxfer (struct target_ops *ops, const char *object_name,
const char *annex,
gdb_byte *readbuf, ULONGEST offset, LONGEST len,
+ ULONGEST *xfered_len,
struct packet_config *packet)
{
struct remote_state *rs = get_remote_state ();
if (strcmp (object_name, rs->finished_object) == 0
&& strcmp (annex ? annex : "", rs->finished_annex) == 0
&& offset == rs->finished_offset)
- return 0;
+ return TARGET_XFER_EOF;
+
/* Otherwise, we're now reading something different. Discard
the cache. */
rs->finished_offset = offset + i;
}
- return i;
+ if (i == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = i;
+ return TARGET_XFER_OK;
+ }
}
-static LONGEST
+static enum target_xfer_status
remote_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
struct remote_state *rs;
int i;
/* Handle memory using the standard memory routines. */
if (object == TARGET_OBJECT_MEMORY)
{
- LONGEST xfered;
-
/* If the remote target is connected but not running, we should
pass this request down to a lower stratum (e.g. the executable
file). */
if (!target_has_execution)
- return 0;
+ return TARGET_XFER_EOF;
if (writebuf != NULL)
- xfered = remote_write_bytes (offset, writebuf, len);
+ return remote_write_bytes (offset, writebuf, len, xfered_len);
else
- xfered = remote_read_bytes (offset, readbuf, len);
-
- return xfered;
+ return remote_read_bytes (offset, readbuf, len, xfered_len);
}
/* Handle SPU memory using qxfer packets. */
{
if (readbuf)
return remote_read_qxfer (ops, "spu", annex, readbuf, offset, len,
- &remote_protocol_packets
- [PACKET_qXfer_spu_read]);
+ xfered_len, &remote_protocol_packets
+ [PACKET_qXfer_spu_read]);
else
return remote_write_qxfer (ops, "spu", annex, writebuf, offset, len,
- &remote_protocol_packets
- [PACKET_qXfer_spu_write]);
+ xfered_len, &remote_protocol_packets
+ [PACKET_qXfer_spu_write]);
}
/* Handle extra signal info using qxfer packets. */
{
if (readbuf)
return remote_read_qxfer (ops, "siginfo", annex, readbuf, offset, len,
- &remote_protocol_packets
+ xfered_len, &remote_protocol_packets
[PACKET_qXfer_siginfo_read]);
else
return remote_write_qxfer (ops, "siginfo", annex,
- writebuf, offset, len,
+ writebuf, offset, len, xfered_len,
&remote_protocol_packets
[PACKET_qXfer_siginfo_write]);
}
{
if (readbuf)
return remote_read_qxfer (ops, "statictrace", annex,
- readbuf, offset, len,
+ readbuf, offset, len, xfered_len,
&remote_protocol_packets
[PACKET_qXfer_statictrace_read]);
else
switch (object)
{
case TARGET_OBJECT_FLASH:
- return remote_flash_write (ops, offset, len, writebuf);
+ return remote_flash_write (ops, offset, len, xfered_len,
+ writebuf);
default:
return TARGET_XFER_E_IO;
case TARGET_OBJECT_AUXV:
gdb_assert (annex == NULL);
return remote_read_qxfer (ops, "auxv", annex, readbuf, offset, len,
+ xfered_len,
&remote_protocol_packets[PACKET_qXfer_auxv]);
case TARGET_OBJECT_AVAILABLE_FEATURES:
return remote_read_qxfer
- (ops, "features", annex, readbuf, offset, len,
+ (ops, "features", annex, readbuf, offset, len, xfered_len,
&remote_protocol_packets[PACKET_qXfer_features]);
case TARGET_OBJECT_LIBRARIES:
return remote_read_qxfer
- (ops, "libraries", annex, readbuf, offset, len,
+ (ops, "libraries", annex, readbuf, offset, len, xfered_len,
&remote_protocol_packets[PACKET_qXfer_libraries]);
case TARGET_OBJECT_LIBRARIES_SVR4:
return remote_read_qxfer
- (ops, "libraries-svr4", annex, readbuf, offset, len,
+ (ops, "libraries-svr4", annex, readbuf, offset, len, xfered_len,
&remote_protocol_packets[PACKET_qXfer_libraries_svr4]);
case TARGET_OBJECT_MEMORY_MAP:
gdb_assert (annex == NULL);
return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len,
+ xfered_len,
&remote_protocol_packets[PACKET_qXfer_memory_map]);
case TARGET_OBJECT_OSDATA:
/* Should only get here if we're connected. */
gdb_assert (rs->remote_desc);
return remote_read_qxfer
- (ops, "osdata", annex, readbuf, offset, len,
+ (ops, "osdata", annex, readbuf, offset, len, xfered_len,
&remote_protocol_packets[PACKET_qXfer_osdata]);
case TARGET_OBJECT_THREADS:
gdb_assert (annex == NULL);
return remote_read_qxfer (ops, "threads", annex, readbuf, offset, len,
+ xfered_len,
&remote_protocol_packets[PACKET_qXfer_threads]);
case TARGET_OBJECT_TRACEFRAME_INFO:
gdb_assert (annex == NULL);
return remote_read_qxfer
- (ops, "traceframe-info", annex, readbuf, offset, len,
+ (ops, "traceframe-info", annex, readbuf, offset, len, xfered_len,
&remote_protocol_packets[PACKET_qXfer_traceframe_info]);
case TARGET_OBJECT_FDPIC:
return remote_read_qxfer (ops, "fdpic", annex, readbuf, offset, len,
+ xfered_len,
&remote_protocol_packets[PACKET_qXfer_fdpic]);
case TARGET_OBJECT_OPENVMS_UIB:
return remote_read_qxfer (ops, "uib", annex, readbuf, offset, len,
+ xfered_len,
&remote_protocol_packets[PACKET_qXfer_uib]);
case TARGET_OBJECT_BTRACE:
return remote_read_qxfer (ops, "btrace", annex, readbuf, offset, len,
+ xfered_len,
&remote_protocol_packets[PACKET_qXfer_btrace]);
default:
getpkt (&rs->buf, &rs->buf_size, 0);
strcpy ((char *) readbuf, rs->buf);
- return strlen ((char *) readbuf);
+ *xfered_len = strlen ((char *) readbuf);
+ return TARGET_XFER_OK;
}
static int
inferior's OBJECT:ANNEX space and GDB's READBUF/WRITEBUF buffer.
Return the number of bytes actually transferred. */
-static LONGEST
+static enum target_xfer_status
rs6000_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
pid_t pid = ptid_get_pid (inferior_ptid);
int arch64 = ARCH64 ();
case TARGET_OBJECT_LIBRARIES_AIX:
return rs6000_xfer_shared_libraries (ops, object, annex,
readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
case TARGET_OBJECT_MEMORY:
{
union
(int *) (uintptr_t) rounded_offset,
buffer.word, NULL);
if (errno)
- return 0;
+ return TARGET_XFER_EOF;
}
if (readbuf)
(int *)(uintptr_t)rounded_offset,
0, NULL);
if (errno)
- return 0;
+ return TARGET_XFER_EOF;
/* Copy appropriate bytes out of the buffer. */
memcpy (readbuf, buffer.byte + (offset - rounded_offset),
partial_len);
}
- return partial_len;
+ *xfered_len = (ULONGEST) partial_len;
+ return TARGET_XFER_OK;
}
default:
/* Implement the to_xfer_partial target_ops method for
TARGET_OBJECT_LIBRARIES_AIX objects. */
-static LONGEST
+static enum target_xfer_status
rs6000_xfer_shared_libraries
(struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
gdb_byte *ldi_buf;
ULONGEST result;
xfree (ldi_buf);
do_cleanups (cleanup);
- return result;
+
+ if (result == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = result;
+ return TARGET_XFER_OK;
+ }
}
void _initialize_rs6000_nat (void);
target_write_partial for details of each variant. One, and only
one, of readbuf or writebuf must be non-NULL. */
-static LONGEST
+static enum target_xfer_status
sol_thread_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
- int retval;
+ enum target_xfer_status retval;
struct cleanup *old_chain;
struct target_ops *beneath = find_target_beneath (ops);
inferior_ptid = procfs_first_available ();
}
- retval = beneath->to_xfer_partial (beneath, object, annex,
- readbuf, writebuf, offset, len);
+ retval = beneath->to_xfer_partial (beneath, object, annex, readbuf,
+ writebuf, offset, len, xfered_len);
do_cleanups (old_chain);
\f
/* Fetch StackGhost Per-Process XOR cookie. */
-static LONGEST
+static enum target_xfer_status
sparc_xfer_wcookie (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
unsigned long wcookie = 0;
char *buf = (char *)&wcookie;
gdb_assert (readbuf && writebuf == NULL);
if (offset == sizeof (unsigned long))
- return 0; /* Signal EOF. */
+ return TARGET_XFER_EOF; /* Signal EOF. */
if (offset > sizeof (unsigned long))
return TARGET_XFER_E_IO;
len = sizeof (unsigned long) - offset;
memcpy (readbuf, buf + offset, len);
- return len;
+ *xfered_len = (ULONGEST) len;
+ return TARGET_XFER_OK;
}
target_xfer_partial_ftype *inf_ptrace_xfer_partial;
-static LONGEST
+static enum target_xfer_status
sparc_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
if (object == TARGET_OBJECT_WCOOKIE)
return sparc_xfer_wcookie (ops, object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
return inf_ptrace_xfer_partial (ops, object, annex, readbuf, writebuf,
- offset, len);
+ offset, len, xfered_len);
}
\f
/* Create a prototype generic SPARC target. The client can override
/* Copy LEN bytes at OFFSET in spufs file ANNEX into/from READBUF or WRITEBUF,
using the /proc file system. */
-static LONGEST
+static enum target_xfer_status
spu_proc_xfer_spu (const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
char buf[128];
int fd = 0;
int pid = ptid_get_pid (inferior_ptid);
if (!annex)
- return 0;
+ return TARGET_XFER_EOF;
xsnprintf (buf, sizeof buf, "/proc/%d/fd/%s", pid, annex);
fd = open (buf, writebuf? O_WRONLY : O_RDONLY);
&& lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
{
close (fd);
- return 0;
+ return TARGET_XFER_EOF;
}
if (writebuf)
ret = read (fd, readbuf, (size_t) len);
close (fd);
- return ret;
+ if (ret < 0)
+ return TARGET_XFER_E_IO;
+ else if (ret == 0)
+ return TARGET_XFER_EOF;
+ else
+ {
+ *xfered_len = (ULONGEST) ret;
+ return TARGET_XFER_OK;
+ }
}
gdb_byte id[128];
char annex[32];
- int len;
+ ULONGEST len;
+ enum target_xfer_status status;
/* Read object ID. */
xsnprintf (annex, sizeof annex, "%d/object-id", inferior_fd);
- len = spu_proc_xfer_spu (annex, id, NULL, 0, sizeof id);
- if (len <= 0 || len >= sizeof id)
+ status = spu_proc_xfer_spu (annex, id, NULL, 0, sizeof id, &len);
+ if (status != TARGET_XFER_OK || len >= sizeof id)
return;
id[len] = 0;
addr = strtoulst ((const char *) id, NULL, 16);
gdb_byte buf[16 * SPU_NUM_GPRS];
char annex[32];
int i;
+ ULONGEST len;
xsnprintf (annex, sizeof annex, "%d/regs", fd);
- if (spu_proc_xfer_spu (annex, buf, NULL, 0, sizeof buf) == sizeof buf)
+ if ((spu_proc_xfer_spu (annex, buf, NULL, 0, sizeof buf, &len)
+ == TARGET_XFER_OK)
+ && len == sizeof buf)
for (i = 0; i < SPU_NUM_GPRS; i++)
regcache_raw_supply (regcache, i, buf + i*16);
}
gdb_byte buf[16 * SPU_NUM_GPRS];
char annex[32];
int i;
+ ULONGEST len;
for (i = 0; i < SPU_NUM_GPRS; i++)
regcache_raw_collect (regcache, i, buf + i*16);
xsnprintf (annex, sizeof annex, "%d/regs", fd);
- spu_proc_xfer_spu (annex, NULL, buf, 0, sizeof buf);
+ spu_proc_xfer_spu (annex, NULL, buf, 0, sizeof buf, &len);
}
}
/* Override the to_xfer_partial routine. */
-static LONGEST
+static enum target_xfer_status
spu_xfer_partial (struct target_ops *ops,
enum target_object object, const char *annex,
gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
if (object == TARGET_OBJECT_SPU)
- return spu_proc_xfer_spu (annex, readbuf, writebuf, offset, len);
+ return spu_proc_xfer_spu (annex, readbuf, writebuf, offset, len,
+ xfered_len);
if (object == TARGET_OBJECT_MEMORY)
{
char mem_annex[32], lslr_annex[32];
gdb_byte buf[32];
ULONGEST lslr;
- LONGEST ret;
+ enum target_xfer_status ret;
/* We must be stopped on a spu_run system call. */
if (!parse_spufs_run (&fd, &addr))
- return 0;
+ return TARGET_XFER_EOF;
/* Use the "mem" spufs file to access SPU local store. */
xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd);
- ret = spu_proc_xfer_spu (mem_annex, readbuf, writebuf, offset, len);
- if (ret > 0)
+ ret = spu_proc_xfer_spu (mem_annex, readbuf, writebuf, offset, len,
+ xfered_len);
+ if (ret == TARGET_XFER_OK)
return ret;
/* SPU local store access wraps the address around at the
trying the original address first, and getting end-of-file. */
xsnprintf (lslr_annex, sizeof lslr_annex, "%d/lslr", fd);
memset (buf, 0, sizeof buf);
- if (spu_proc_xfer_spu (lslr_annex, buf, NULL, 0, sizeof buf) <= 0)
+ if (spu_proc_xfer_spu (lslr_annex, buf, NULL, 0, sizeof buf, xfered_len)
+ != TARGET_XFER_OK)
return ret;
lslr = strtoulst ((const char *) buf, NULL, 16);
return spu_proc_xfer_spu (mem_annex, readbuf, writebuf,
- offset & lslr, len);
+ offset & lslr, len, xfered_len);
}
return TARGET_XFER_E_IO;
}
/* Override the to_xfer_partial routine. */
-static LONGEST
+static enum target_xfer_status
spu_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
struct target_ops *ops_beneath = find_target_beneath (ops);
while (ops_beneath && !ops_beneath->to_xfer_partial)
char mem_annex[32], lslr_annex[32];
gdb_byte buf[32];
ULONGEST lslr;
- LONGEST ret;
+ enum target_xfer_status ret;
if (fd >= 0)
{
xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd);
ret = ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU,
mem_annex, readbuf, writebuf,
- addr, len);
- if (ret > 0)
+ addr, len, xfered_len);
+ if (ret == TARGET_XFER_OK)
return ret;
/* SPU local store access wraps the address around at the
memset (buf, 0, sizeof buf);
if (ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU,
lslr_annex, buf, NULL,
- 0, sizeof buf) <= 0)
+ 0, sizeof buf, xfered_len)
+ != TARGET_XFER_OK)
return ret;
lslr = strtoulst ((char *) buf, NULL, 16);
return ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU,
mem_annex, readbuf, writebuf,
- addr & lslr, len);
+ addr & lslr, len, xfered_len);
}
}
return ops_beneath->to_xfer_partial (ops_beneath, object, annex,
- readbuf, writebuf, offset, len);
+ readbuf, writebuf, offset, len, xfered_len);
}
/* Override the to_search_memory routine. */
}
const char *
-target_xfer_error_to_string (enum target_xfer_error err)
+target_xfer_status_to_string (enum target_xfer_status err)
{
#define CASE(X) case X: return #X
switch (err)
/* Read memory from the live target, even if currently inspecting a
traceframe. The return is the same as that of target_read. */
-static LONGEST
+static enum target_xfer_status
target_read_live_memory (enum target_object object,
- ULONGEST memaddr, gdb_byte *myaddr, ULONGEST len)
+ ULONGEST memaddr, gdb_byte *myaddr, ULONGEST len,
+ ULONGEST *xfered_len)
{
- LONGEST ret;
+ enum target_xfer_status ret;
struct cleanup *cleanup;
/* Switch momentarily out of tfind mode so to access live memory.
cleanup = make_cleanup_restore_traceframe_number ();
set_traceframe_number (-1);
- ret = target_read (current_target.beneath, object, NULL,
- myaddr, memaddr, len);
+ ret = target_xfer_partial (current_target.beneath, object, NULL,
+ myaddr, NULL, memaddr, len, xfered_len);
do_cleanups (cleanup);
return ret;
For interface/parameters/return description see target.h,
to_xfer_partial. */
-static LONGEST
+static enum target_xfer_status
memory_xfer_live_readonly_partial (struct target_ops *ops,
enum target_object object,
gdb_byte *readbuf, ULONGEST memaddr,
- ULONGEST len)
+ ULONGEST len, ULONGEST *xfered_len)
{
struct target_section *secp;
struct target_section_table *table;
{
/* Entire transfer is within this section. */
return target_read_live_memory (object, memaddr,
- readbuf, len);
+ readbuf, len, xfered_len);
}
else if (memaddr >= p->endaddr)
{
/* This section overlaps the transfer. Just do half. */
len = p->endaddr - memaddr;
return target_read_live_memory (object, memaddr,
- readbuf, len);
+ readbuf, len, xfered_len);
}
}
}
}
- return 0;
+ return TARGET_XFER_EOF;
}
/* Read memory from more than one valid target. A core file, for
instance, could have some of memory but delegate other bits to
the target below it. So, we must manually try all targets. */
-static LONGEST
+static enum target_xfer_status
raw_memory_xfer_partial (struct target_ops *ops, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST memaddr, LONGEST len)
+ const gdb_byte *writebuf, ULONGEST memaddr, LONGEST len,
+ ULONGEST *xfered_len)
{
- LONGEST res;
+ enum target_xfer_status res;
do
{
res = ops->to_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL,
- readbuf, writebuf, memaddr, len);
- if (res > 0)
+ readbuf, writebuf, memaddr, len,
+ xfered_len);
+ if (res == TARGET_XFER_OK)
break;
/* Stop if the target reports that the memory is not available. */
/* Perform a partial memory transfer.
For docs see target.h, to_xfer_partial. */
-static LONGEST
+static enum target_xfer_status
memory_xfer_partial_1 (struct target_ops *ops, enum target_object object,
gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST memaddr,
- ULONGEST len)
+ ULONGEST len, ULONGEST *xfered_len)
{
- LONGEST res;
+ enum target_xfer_status res;
int reg_len;
struct mem_region *region;
struct inferior *inf;
memaddr = overlay_mapped_address (memaddr, section);
return section_table_xfer_memory_partial (readbuf, writebuf,
- memaddr, len,
+ memaddr, len, xfered_len,
table->sections,
table->sections_end,
section_name);
{
table = target_get_section_table (ops);
return section_table_xfer_memory_partial (readbuf, writebuf,
- memaddr, len,
+ memaddr, len, xfered_len,
table->sections,
table->sections_end,
NULL);
/* This goes through the topmost target again. */
res = memory_xfer_live_readonly_partial (ops, object,
- readbuf, memaddr, len);
- if (res > 0)
- return res;
-
- /* No use trying further, we know some memory starting
- at MEMADDR isn't available. */
- return TARGET_XFER_E_UNAVAILABLE;
+ readbuf, memaddr,
+ len, xfered_len);
+ if (res == TARGET_XFER_OK)
+ return TARGET_XFER_OK;
+ else
+ {
+ /* No use trying further, we know some memory starting
+ at MEMADDR isn't available. */
+ *xfered_len = len;
+ return TARGET_XFER_E_UNAVAILABLE;
+ }
}
/* Don't try to read more than how much is available, in
|| (code_cache_enabled_p () && object == TARGET_OBJECT_CODE_MEMORY)))
{
DCACHE *dcache = target_dcache_get_or_init ();
+ int l;
if (readbuf != NULL)
- res = dcache_xfer_memory (ops, dcache, memaddr, readbuf, reg_len, 0);
+ l = dcache_xfer_memory (ops, dcache, memaddr, readbuf, reg_len, 0);
else
/* FIXME drow/2006-08-09: If we're going to preserve const
correctness dcache_xfer_memory should take readbuf and
writebuf. */
- res = dcache_xfer_memory (ops, dcache, memaddr, (void *) writebuf,
+ l = dcache_xfer_memory (ops, dcache, memaddr, (void *) writebuf,
reg_len, 1);
- if (res <= 0)
- return -1;
+ if (l <= 0)
+ return TARGET_XFER_E_IO;
else
- return res;
+ {
+ *xfered_len = (ULONGEST) l;
+ return TARGET_XFER_OK;
+ }
}
/* If none of those methods found the memory we wanted, fall back
to_xfer_partial is enough; if it doesn't recognize an object
it will call the to_xfer_partial of the next target down.
But for memory this won't do. Memory is the only target
- object which can be read from more than one valid target. */
- res = raw_memory_xfer_partial (ops, readbuf, writebuf, memaddr, reg_len);
+ object which can be read from more than one valid target.
+ A core file, for instance, could have some of memory but
+ delegate other bits to the target below it. So, we must
+ manually try all targets. */
+
+ res = raw_memory_xfer_partial (ops, readbuf, writebuf, memaddr, reg_len,
+ xfered_len);
/* Make sure the cache gets updated no matter what - if we are writing
to the stack. Even if this write is not tagged as such, we still need
to update the cache. */
- if (res > 0
+ if (res == TARGET_XFER_OK
&& inf != NULL
&& writebuf != NULL
&& target_dcache_init_p ()
{
DCACHE *dcache = target_dcache_get ();
- dcache_update (dcache, memaddr, (void *) writebuf, res);
+ dcache_update (dcache, memaddr, (void *) writebuf, reg_len);
}
/* If we still haven't got anything, return the last error. We
/* Perform a partial memory transfer. For docs see target.h,
to_xfer_partial. */
-static LONGEST
+static enum target_xfer_status
memory_xfer_partial (struct target_ops *ops, enum target_object object,
- gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST memaddr,
- ULONGEST len)
+ gdb_byte *readbuf, const gdb_byte *writebuf,
+ ULONGEST memaddr, ULONGEST len, ULONGEST *xfered_len)
{
- int res;
+ enum target_xfer_status res;
/* Zero length requests are ok and require no work. */
if (len == 0)
- return 0;
+ return TARGET_XFER_EOF;
/* Fill in READBUF with breakpoint shadows, or WRITEBUF with
breakpoint insns, thus hiding out from higher layers whether
there are software breakpoints inserted in the code stream. */
if (readbuf != NULL)
{
- res = memory_xfer_partial_1 (ops, object, readbuf, NULL, memaddr, len);
+ res = memory_xfer_partial_1 (ops, object, readbuf, NULL, memaddr, len,
+ xfered_len);
- if (res > 0 && !show_memory_breakpoints)
+ if (res == TARGET_XFER_OK && !show_memory_breakpoints)
breakpoint_xfer_memory (readbuf, NULL, NULL, memaddr, res);
}
else
memcpy (buf, writebuf, len);
breakpoint_xfer_memory (NULL, buf, writebuf, memaddr, len);
- res = memory_xfer_partial_1 (ops, object, NULL, buf, memaddr, len);
+ res = memory_xfer_partial_1 (ops, object, NULL, buf, memaddr, len,
+ xfered_len);
do_cleanups (old_chain);
}
/* For docs see target.h, to_xfer_partial. */
-LONGEST
+enum target_xfer_status
target_xfer_partial (struct target_ops *ops,
enum target_object object, const char *annex,
gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
- LONGEST retval;
+ enum target_xfer_status retval;
gdb_assert (ops->to_xfer_partial != NULL);
/* Transfer is done when LEN is zero. */
if (len == 0)
- return 0;
+ return TARGET_XFER_EOF;
if (writebuf && !may_write_memory)
error (_("Writing to memory is not allowed (addr %s, len %s)"),
core_addr_to_string_nz (offset), plongest (len));
+ *xfered_len = 0;
+
/* If this is a memory transfer, let the memory-specific code
have a look at it instead. Memory transfers are more
complicated. */
if (object == TARGET_OBJECT_MEMORY || object == TARGET_OBJECT_STACK_MEMORY
|| object == TARGET_OBJECT_CODE_MEMORY)
retval = memory_xfer_partial (ops, object, readbuf,
- writebuf, offset, len);
+ writebuf, offset, len, xfered_len);
else if (object == TARGET_OBJECT_RAW_MEMORY)
{
/* Request the normal memory object from other layers. */
- retval = raw_memory_xfer_partial (ops, readbuf, writebuf, offset, len);
+ retval = raw_memory_xfer_partial (ops, readbuf, writebuf, offset, len,
+ xfered_len);
}
else
retval = ops->to_xfer_partial (ops, object, annex, readbuf,
- writebuf, offset, len);
+ writebuf, offset, len, xfered_len);
if (targetdebug)
{
fprintf_unfiltered (gdb_stdlog,
"%s:target_xfer_partial "
- "(%d, %s, %s, %s, %s, %s) = %s",
+ "(%d, %s, %s, %s, %s, %s) = %d, %s",
ops->to_shortname,
(int) object,
(annex ? annex : "(null)"),
host_address_to_string (readbuf),
host_address_to_string (writebuf),
core_addr_to_string_nz (offset),
- pulongest (len), plongest (retval));
+ pulongest (len), retval,
+ pulongest (*xfered_len));
if (readbuf)
myaddr = readbuf;
if (writebuf)
myaddr = writebuf;
- if (retval > 0 && myaddr != NULL)
+ if (retval == TARGET_XFER_OK && myaddr != NULL)
{
int i;
fputs_unfiltered (", bytes =", gdb_stdlog);
- for (i = 0; i < retval; i++)
+ for (i = 0; i < *xfered_len; i++)
{
if ((((intptr_t) &(myaddr[i])) & 0xf) == 0)
{
fputc_unfiltered ('\n', gdb_stdlog);
}
+
+ /* Check implementations of to_xfer_partial update *XFERED_LEN
+ properly. Do assertion after printing debug messages, so that we
+ can find more clues on assertion failure from debugging messages. */
+ if (retval == TARGET_XFER_OK || retval == TARGET_XFER_E_UNAVAILABLE)
+ gdb_assert (*xfered_len > 0);
+
return retval;
}
/* Read LEN bytes of target memory at address MEMADDR, placing the
results in GDB's memory at MYADDR. Returns either 0 for success or
- a target_xfer_error value if any error occurs.
+ TARGET_XFER_E_IO if any error occurs.
If an error occurs, no guarantee is made about the contents of the data at
MYADDR. In particular, the caller should not depend upon partial reads
}
/* Write LEN bytes from MYADDR to target memory at address MEMADDR.
- Returns either 0 for success or a target_xfer_error value if any
+ Returns either 0 for success or TARGET_XFER_E_IO if any
error occurs. If an error occurs, no guarantee is made about how
much data got written. Callers that can deal with partial writes
should call target_write. */
}
/* Write LEN bytes from MYADDR to target raw memory at address
- MEMADDR. Returns either 0 for success or a target_xfer_error value
+ MEMADDR. Returns either 0 for success or TARGET_XFER_E_IO
if any error occurs. If an error occurs, no guarantee is made
about how much data got written. Callers that can deal with
partial writes should call target_write. */
/* More generic transfers. */
-static LONGEST
+static enum target_xfer_status
default_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
if (object == TARGET_OBJECT_MEMORY
&& ops->deprecated_xfer_memory != NULL)
xfered = ops->deprecated_xfer_memory (offset, readbuf, len,
0/*read*/, NULL, ops);
if (xfered > 0)
- return xfered;
+ {
+ *xfered_len = (ULONGEST) xfered;
+ return TARGET_XFER_E_IO;
+ }
else if (xfered == 0 && errno == 0)
/* "deprecated_xfer_memory" uses 0, cross checked against
ERRNO as one indication of an error. */
- return 0;
+ return TARGET_XFER_EOF;
else
- return -1;
+ return TARGET_XFER_E_IO;
}
else if (ops->beneath != NULL)
return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
- readbuf, writebuf, offset, len);
+ readbuf, writebuf, offset, len,
+ xfered_len);
else
- return -1;
+ return TARGET_XFER_E_IO;
}
/* The xfer_partial handler for the topmost target. Unlike the default,
it does not need to handle memory specially; it just passes all
requests down the stack. */
-static LONGEST
+static enum target_xfer_status
current_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
if (ops->beneath != NULL)
return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
- readbuf, writebuf, offset, len);
+ readbuf, writebuf, offset, len,
+ xfered_len);
else
- return -1;
+ return TARGET_XFER_E_IO;
}
/* Target vector read/write partial wrapper functions. */
-static LONGEST
+static enum target_xfer_status
target_read_partial (struct target_ops *ops,
enum target_object object,
const char *annex, gdb_byte *buf,
- ULONGEST offset, LONGEST len)
+ ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
- return target_xfer_partial (ops, object, annex, buf, NULL, offset, len);
+ return target_xfer_partial (ops, object, annex, buf, NULL, offset, len,
+ xfered_len);
}
static LONGEST
target_write_partial (struct target_ops *ops,
enum target_object object,
const char *annex, const gdb_byte *buf,
- ULONGEST offset, LONGEST len)
+ ULONGEST offset, LONGEST len, ULONGEST *xfered_len)
{
- return target_xfer_partial (ops, object, annex, NULL, buf, offset, len);
+ return target_xfer_partial (ops, object, annex, NULL, buf, offset, len,
+ xfered_len);
}
/* Wrappers to perform the full transfer. */
while (xfered < len)
{
- LONGEST xfer = target_read_partial (ops, object, annex,
- (gdb_byte *) buf + xfered,
- offset + xfered, len - xfered);
+ ULONGEST xfered_len;
+ enum target_xfer_status status;
+
+ status = target_read_partial (ops, object, annex,
+ (gdb_byte *) buf + xfered,
+ offset + xfered, len - xfered,
+ &xfered_len);
/* Call an observer, notifying them of the xfer progress? */
- if (xfer == 0)
+ if (status == TARGET_XFER_EOF)
return xfered;
- if (xfer < 0)
+ else if (status == TARGET_XFER_OK)
+ {
+ xfered += xfered_len;
+ QUIT;
+ }
+ else
return -1;
- xfered += xfer;
- QUIT;
+
}
return len;
}
ULONGEST current_end = end;
int forward;
memory_read_result_s r;
+ ULONGEST xfered_len;
/* If we previously failed to read 1 byte, nothing can be done here. */
if (end - begin <= 1)
if not. This heuristic is meant to permit reading accessible memory
at the boundary of accessible region. */
if (target_read_partial (ops, TARGET_OBJECT_MEMORY, NULL,
- buf, begin, 1) == 1)
+ buf, begin, 1, &xfered_len) == TARGET_XFER_OK)
{
forward = 1;
++current_begin;
}
else if (target_read_partial (ops, TARGET_OBJECT_MEMORY, NULL,
- buf + (end-begin) - 1, end - 1, 1) == 1)
+ buf + (end-begin) - 1, end - 1, 1,
+ &xfered_len) == TARGET_XFER_OK)
{
forward = 0;
--current_end;
while (xfered < len)
{
- LONGEST xfer = target_write_partial (ops, object, annex,
- (gdb_byte *) buf + xfered,
- offset + xfered, len - xfered);
+ ULONGEST xfered_len;
+ enum target_xfer_status status;
+
+ status = target_write_partial (ops, object, annex,
+ (gdb_byte *) buf + xfered,
+ offset + xfered, len - xfered,
+ &xfered_len);
- if (xfer == 0)
+ if (status == TARGET_XFER_EOF)
return xfered;
- if (xfer < 0)
+ if (TARGET_XFER_STATUS_ERROR_P (status))
return -1;
+ gdb_assert (status == TARGET_XFER_OK);
if (progress)
- (*progress) (xfer, baton);
+ (*progress) (xfered_len, baton);
- xfered += xfer;
+ xfered += xfered_len;
QUIT;
}
return len;
{
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
buf_pos = 0;
while (1)
{
- n = target_read_partial (ops, object, annex, &buf[buf_pos],
- buf_pos, buf_alloc - buf_pos - padding);
- if (n < 0)
- {
- /* An error occurred. */
- xfree (buf);
- return -1;
- }
- else if (n == 0)
+ ULONGEST xfered_len;
+ enum target_xfer_status status;
+
+ status = target_read_partial (ops, object, annex, &buf[buf_pos],
+ buf_pos, buf_alloc - buf_pos - padding,
+ &xfered_len);
+
+ if (status == TARGET_XFER_EOF)
{
/* Read all there was. */
if (buf_pos == 0)
*buf_p = buf;
return buf_pos;
}
+ else if (status != TARGET_XFER_OK)
+ {
+ /* An error occurred. */
+ xfree (buf);
+ return TARGET_XFER_E_IO;
+ }
- buf_pos += n;
+ buf_pos += xfered_len;
/* If the buffer is filling up, expand it. */
if (buf_alloc < buf_pos * 2)
/* Possible future objects: TARGET_OBJECT_FILE, ... */
};
-/* Possible error codes returned by target_xfer_partial, etc. */
+/* Possible values returned by target_xfer_partial, etc. */
-enum target_xfer_error
+enum target_xfer_status
{
+ /* Some bytes are transferred. */
+ TARGET_XFER_OK = 1,
+
+ /* No further transfer is possible. */
+ TARGET_XFER_EOF = 0,
+
/* Generic I/O error. Note that it's important that this is '-1',
as we still have target_xfer-related code returning hardcoded
'-1' on error. */
/* Keep list in sync with target_xfer_error_to_string. */
};
+#define TARGET_XFER_STATUS_ERROR_P(STATUS) ((STATUS) < TARGET_XFER_EOF)
+
/* Return the string form of ERR. */
-extern const char *target_xfer_error_to_string (enum target_xfer_error err);
+extern const char *target_xfer_status_to_string (enum target_xfer_status err);
/* Enumeration of the kinds of traceframe searches that a target may
be able to perform. */
typedef struct static_tracepoint_marker *static_tracepoint_marker_p;
DEF_VEC_P(static_tracepoint_marker_p);
-typedef LONGEST
+typedef enum target_xfer_status
target_xfer_partial_ftype (struct target_ops *ops,
enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset,
- ULONGEST len);
+ ULONGEST len,
+ ULONGEST *xfered_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.
- Return the number of bytes actually transfered, zero when no
- further transfer is possible, and a negative error code (really
- an 'enum target_xfer_error' value) 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.
+ Return the transferred status, error or OK (an
+ 'enum target_xfer_status' value). Save the number of bytes
+ actually transferred in *XFERED_LEN if transfer is successful
+ (TARGET_XFER_OK) or the number unavailable bytes if the requested
+ data is unavailable (TARGET_XFER_E_UNAVAILABLE). *XFERED_LEN
+ 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
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,
- ULONGEST offset, ULONGEST len);
+ enum target_xfer_status (*to_xfer_partial) (struct target_ops *ops,
+ enum target_object object,
+ const char *annex,
+ gdb_byte *readbuf,
+ const gdb_byte *writebuf,
+ ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len);
/* Returns the memory map for the target. A return value of NULL
means that no memory map is available. If a memory address
}
}
-static LONGEST
+static enum target_xfer_status
tfile_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
/* We're only doing regular memory for now. */
if (object != TARGET_OBJECT_MEMORY)
if (maddr != offset)
lseek (trace_fd, offset - maddr, SEEK_CUR);
tfile_read (readbuf, amt);
- return amt;
+ *xfered_len = amt;
+ return TARGET_XFER_OK;
}
/* Skip over this block. */
if (amt > len)
amt = len;
- amt = bfd_get_section_contents (exec_bfd, s,
- readbuf, offset - vma, amt);
- return amt;
+ *xfered_len = bfd_get_section_contents (exec_bfd, s,
+ readbuf, offset - vma, amt);
+ return TARGET_XFER_OK;
}
}
}
/* Read LEN bytes of target memory at address MEMADDR, placing the
results in GDB's memory at MYADDR. Returns a count of the bytes
- actually read, and optionally a target_xfer_error value in the
+ actually read, and optionally a target_xfer_status value in the
location pointed to by ERRPTR if ERRPTR is non-null. */
/* FIXME: cagney/1999-10-14: Only used by val_print_string. Can this
each. Fetch at most FETCHLIMIT characters. BUFFER will be set to a newly
allocated buffer containing the string, which the caller is responsible to
free, and BYTES_READ will be set to the number of bytes read. Returns 0 on
- success, or a target_xfer_error on failure.
+ success, or a target_xfer_status on failure.
If LEN > 0, reads the lesser of LEN or FETCHLIMIT characters
(including eventual NULs in the middle or end of the string).
/* Helper for windows_xfer_partial that handles memory transfers.
Arguments are like target_xfer_partial. */
-static LONGEST
+static enum target_xfer_status
windows_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST memaddr, ULONGEST len)
+ ULONGEST memaddr, ULONGEST len, ULONGEST *xfered_len)
{
SIZE_T done = 0;
BOOL success;
if (!success)
lasterror = GetLastError ();
}
+ *xfered_len = (ULONGEST) done;
if (!success && lasterror == ERROR_PARTIAL_COPY && done > 0)
- return done;
+ return TARGET_XFER_OK;
else
- return success ? done : TARGET_XFER_E_IO;
+ return success ? TARGET_XFER_OK : TARGET_XFER_E_IO;
}
static void
return normal_pid_to_str (ptid);
}
-static LONGEST
+static enum target_xfer_status
windows_xfer_shared_libraries (struct target_ops *ops,
- enum target_object object, const char *annex,
- gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len)
+ enum target_object object, const char *annex,
+ gdb_byte *readbuf, const gdb_byte *writebuf,
+ ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
struct obstack obstack;
const char *buf;
}
obstack_free (&obstack, NULL);
- return len;
+ *xfered_len = (ULONGEST) len;
+ return TARGET_XFER_OK;
}
-static LONGEST
+static enum target_xfer_status
windows_xfer_partial (struct target_ops *ops, enum target_object object,
- const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len)
+ const char *annex, gdb_byte *readbuf,
+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
switch (object)
{
case TARGET_OBJECT_MEMORY:
- return windows_xfer_memory (readbuf, writebuf, offset, len);
+ return windows_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
case TARGET_OBJECT_LIBRARIES:
return windows_xfer_shared_libraries (ops, object, annex, readbuf,
- writebuf, offset, len);
+ writebuf, offset, len, xfered_len);
default:
if (ops->beneath != NULL)
return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
- readbuf, writebuf, offset, len);
+ readbuf, writebuf, offset, len,
+ xfered_len);
return TARGET_XFER_E_IO;
}
}