target: consider addressable unit size when reading/writing memory
If we are reading/writing from a memory object, the length represents the number of "addresses" to read/write, so the addressable unit size needs to be taken into account when allocating memory on gdb's side. gdb/ChangeLog: * target.c (target_read): Consider addressable unit size when reading from a memory object. (read_memory_robust): Same. (read_whatever_is_readable): Same. (target_write_with_progress): Consider addressable unit size when writing to a memory object. * target.h (target_read): Update documentation. (target_write): Add documentation.
This commit is contained in:
parent
3374165f51
commit
d309493c38
|
@ -1,3 +1,14 @@
|
|||
2015-06-12 Simon Marchi <simon.marchi@ericsson.com>
|
||||
|
||||
* target.c (target_read): Consider addressable unit size when
|
||||
reading from a memory object.
|
||||
(read_memory_robust): Same.
|
||||
(read_whatever_is_readable): Same.
|
||||
(target_write_with_progress): Consider addressable unit size
|
||||
when writing to a memory object.
|
||||
* target.h (target_read): Update documentation.
|
||||
(target_write): Add documentation.
|
||||
|
||||
2015-06-12 Simon Marchi <simon.marchi@ericsson.com>
|
||||
|
||||
* arch-utils.h (default_addressable_memory_unit_size): New.
|
||||
|
|
35
gdb/target.c
35
gdb/target.c
|
@ -1593,6 +1593,15 @@ target_read (struct target_ops *ops,
|
|||
ULONGEST offset, LONGEST len)
|
||||
{
|
||||
LONGEST xfered_total = 0;
|
||||
int unit_size = 1;
|
||||
|
||||
/* If we are reading from a memory object, find the length of an addressable
|
||||
unit for that architecture. */
|
||||
if (object == TARGET_OBJECT_MEMORY
|
||||
|| object == TARGET_OBJECT_STACK_MEMORY
|
||||
|| object == TARGET_OBJECT_CODE_MEMORY
|
||||
|| object == TARGET_OBJECT_RAW_MEMORY)
|
||||
unit_size = gdbarch_addressable_memory_unit_size (target_gdbarch ());
|
||||
|
||||
while (xfered_total < len)
|
||||
{
|
||||
|
@ -1600,7 +1609,7 @@ target_read (struct target_ops *ops,
|
|||
enum target_xfer_status status;
|
||||
|
||||
status = target_read_partial (ops, object, annex,
|
||||
buf + xfered_total,
|
||||
buf + xfered_total * unit_size,
|
||||
offset + xfered_total, len - xfered_total,
|
||||
&xfered_partial);
|
||||
|
||||
|
@ -1643,6 +1652,7 @@ target_read (struct target_ops *ops,
|
|||
static void
|
||||
read_whatever_is_readable (struct target_ops *ops,
|
||||
const ULONGEST begin, const ULONGEST end,
|
||||
int unit_size,
|
||||
VEC(memory_read_result_s) **result)
|
||||
{
|
||||
gdb_byte *buf = xmalloc (end - begin);
|
||||
|
@ -1709,7 +1719,7 @@ read_whatever_is_readable (struct target_ops *ops,
|
|||
}
|
||||
|
||||
xfer = target_read (ops, TARGET_OBJECT_MEMORY, NULL,
|
||||
buf + (first_half_begin - begin),
|
||||
buf + (first_half_begin - begin) * unit_size,
|
||||
first_half_begin,
|
||||
first_half_end - first_half_begin);
|
||||
|
||||
|
@ -1745,8 +1755,9 @@ read_whatever_is_readable (struct target_ops *ops,
|
|||
/* The [current_end, end) range has been read. */
|
||||
LONGEST region_len = end - current_end;
|
||||
|
||||
r.data = xmalloc (region_len);
|
||||
memcpy (r.data, buf + current_end - begin, region_len);
|
||||
r.data = xmalloc (region_len * unit_size);
|
||||
memcpy (r.data, buf + (current_end - begin) * unit_size,
|
||||
region_len * unit_size);
|
||||
r.begin = current_end;
|
||||
r.end = end;
|
||||
xfree (buf);
|
||||
|
@ -1773,6 +1784,7 @@ read_memory_robust (struct target_ops *ops,
|
|||
const ULONGEST offset, const LONGEST len)
|
||||
{
|
||||
VEC(memory_read_result_s) *result = 0;
|
||||
int unit_size = gdbarch_addressable_memory_unit_size (target_gdbarch ());
|
||||
|
||||
LONGEST xfered_total = 0;
|
||||
while (xfered_total < len)
|
||||
|
@ -1798,7 +1810,7 @@ read_memory_robust (struct target_ops *ops,
|
|||
else
|
||||
{
|
||||
LONGEST to_read = min (len - xfered_total, region_len);
|
||||
gdb_byte *buffer = (gdb_byte *)xmalloc (to_read);
|
||||
gdb_byte *buffer = (gdb_byte *) xmalloc (to_read * unit_size);
|
||||
|
||||
LONGEST xfered_partial =
|
||||
target_read (ops, TARGET_OBJECT_MEMORY, NULL,
|
||||
|
@ -1810,7 +1822,7 @@ read_memory_robust (struct target_ops *ops,
|
|||
/* Got an error reading full chunk. See if maybe we can read
|
||||
some subrange. */
|
||||
xfree (buffer);
|
||||
read_whatever_is_readable (ops, offset + xfered_total,
|
||||
read_whatever_is_readable (ops, offset + xfered_total, unit_size,
|
||||
offset + xfered_total + to_read, &result);
|
||||
xfered_total += to_read;
|
||||
}
|
||||
|
@ -1840,6 +1852,15 @@ target_write_with_progress (struct target_ops *ops,
|
|||
void (*progress) (ULONGEST, void *), void *baton)
|
||||
{
|
||||
LONGEST xfered_total = 0;
|
||||
int unit_size = 1;
|
||||
|
||||
/* If we are writing to a memory object, find the length of an addressable
|
||||
unit for that architecture. */
|
||||
if (object == TARGET_OBJECT_MEMORY
|
||||
|| object == TARGET_OBJECT_STACK_MEMORY
|
||||
|| object == TARGET_OBJECT_CODE_MEMORY
|
||||
|| object == TARGET_OBJECT_RAW_MEMORY)
|
||||
unit_size = gdbarch_addressable_memory_unit_size (target_gdbarch ());
|
||||
|
||||
/* Give the progress callback a chance to set up. */
|
||||
if (progress)
|
||||
|
@ -1851,7 +1872,7 @@ target_write_with_progress (struct target_ops *ops,
|
|||
enum target_xfer_status status;
|
||||
|
||||
status = target_write_partial (ops, object, annex,
|
||||
(gdb_byte *) buf + xfered_total,
|
||||
buf + xfered_total * unit_size,
|
||||
offset + xfered_total, len - xfered_total,
|
||||
&xfered_partial);
|
||||
|
||||
|
|
31
gdb/target.h
31
gdb/target.h
|
@ -265,13 +265,17 @@ typedef enum target_xfer_status
|
|||
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.
|
||||
/* Request that OPS transfer up to LEN addressable units of the target's
|
||||
OBJECT. When reading from a memory object, the size of an addressable unit
|
||||
is architecture dependent and can be found using
|
||||
gdbarch_addressable_memory_unit_size. Otherwise, an addressable unit is 1
|
||||
byte long. BUF should point to a buffer large enough to hold the read data,
|
||||
taking into account the addressable unit size. 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, or a negative error
|
||||
code (an 'enum target_xfer_error' value) if the transfer is not
|
||||
Return the number of addressable units actually transferred, or a negative
|
||||
error code (an 'enum target_xfer_error' value) 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
|
||||
|
@ -300,6 +304,21 @@ extern VEC(memory_read_result_s)* read_memory_robust (struct target_ops *ops,
|
|||
const ULONGEST offset,
|
||||
const LONGEST len);
|
||||
|
||||
/* Request that OPS transfer up to LEN addressable units from BUF to the
|
||||
target's OBJECT. When writing to a memory object, the addressable unit
|
||||
size is architecture dependent and can be found using
|
||||
gdbarch_addressable_memory_unit_size. Otherwise, an addressable unit is 1
|
||||
byte long. 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 addressable units actually transferred, or a negative
|
||||
error code (an 'enum target_xfer_status' value) 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. */
|
||||
|
||||
extern LONGEST target_write (struct target_ops *ops,
|
||||
enum target_object object,
|
||||
const char *annex, const gdb_byte *buf,
|
||||
|
|
Loading…
Reference in New Issue