diff options
Diffstat (limited to 'gdb/target.c')
-rw-r--r-- | gdb/target.c | 80 |
1 files changed, 65 insertions, 15 deletions
diff --git a/gdb/target.c b/gdb/target.c index 6358b00..5700066 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1388,19 +1388,15 @@ memory_xfer_live_readonly_partial (struct target_ops *ops, For docs see target.h, to_xfer_partial. */ static LONGEST -memory_xfer_partial (struct target_ops *ops, enum target_object object, - void *readbuf, const void *writebuf, ULONGEST memaddr, - LONGEST len) +memory_xfer_partial_1 (struct target_ops *ops, enum target_object object, + void *readbuf, const void *writebuf, ULONGEST memaddr, + LONGEST len) { LONGEST res; int reg_len; struct mem_region *region; struct inferior *inf; - /* Zero length requests are ok and require no work. */ - if (len == 0) - return 0; - /* For accesses to unmapped overlay sections, read directly from files. Must do this first, as MEMADDR may need adjustment. */ if (readbuf != NULL && overlay_debugging) @@ -1551,11 +1547,7 @@ memory_xfer_partial (struct target_ops *ops, enum target_object object, if (res <= 0) return -1; else - { - if (readbuf && !show_memory_breakpoints) - breakpoint_restore_shadows (readbuf, memaddr, reg_len); - return res; - } + return res; } /* If none of those methods found the memory we wanted, fall back @@ -1584,9 +1576,6 @@ memory_xfer_partial (struct target_ops *ops, enum target_object object, } while (ops != NULL); - if (res > 0 && readbuf != NULL && !show_memory_breakpoints) - breakpoint_restore_shadows (readbuf, memaddr, reg_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. */ @@ -1606,6 +1595,48 @@ memory_xfer_partial (struct target_ops *ops, enum target_object object, return res; } +/* Perform a partial memory transfer. For docs see target.h, + to_xfer_partial. */ + +static LONGEST +memory_xfer_partial (struct target_ops *ops, enum target_object object, + void *readbuf, const void *writebuf, ULONGEST memaddr, + LONGEST len) +{ + int res; + + /* Zero length requests are ok and require no work. */ + if (len == 0) + return 0; + + /* 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); + + if (res > 0 && !show_memory_breakpoints) + breakpoint_xfer_memory (readbuf, NULL, NULL, memaddr, res); + } + else + { + void *buf; + struct cleanup *old_chain; + + buf = xmalloc (len); + old_chain = make_cleanup (xfree, buf); + memcpy (buf, writebuf, len); + + breakpoint_xfer_memory (NULL, buf, writebuf, memaddr, len); + res = memory_xfer_partial_1 (ops, object, NULL, buf, memaddr, len); + + do_cleanups (old_chain); + } + + return res; +} + static void restore_show_memory_breakpoints (void *arg) { @@ -1761,6 +1792,25 @@ target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, int len) return EIO; } +/* Write LEN bytes from MYADDR to target raw memory at address + MEMADDR. Returns either 0 for success or an errno value 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. */ + +int +target_write_raw_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, int len) +{ + /* Dispatch to the topmost target, not the flattened current_target. + Memory accesses check target->to_has_(all_)memory, and the + flattened target doesn't inherit those. */ + if (target_write (current_target.beneath, TARGET_OBJECT_RAW_MEMORY, NULL, + myaddr, memaddr, len) == len) + return 0; + else + return EIO; +} + /* Fetch the target's memory map. */ VEC(mem_region_s) * |