diff --git a/gdb/corefile.c b/gdb/corefile.c index e74630b..69971ea 100644 --- a/gdb/corefile.c +++ b/gdb/corefile.c @@ -228,6 +228,7 @@ memory_error (int status, CORE_ADDR memaddr) } /* Same as target_read_memory, but report an error if can't read. */ + void read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len) { @@ -237,6 +238,17 @@ read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len) memory_error (status, memaddr); } +/* Same as target_read_stack, but report an error if can't read. */ + +void +read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, int len) +{ + int status; + status = target_read_stack (memaddr, myaddr, len); + if (status != 0) + memory_error (status, memaddr); +} + /* Argument / return result struct for use with do_captured_read_memory_integer(). MEMADDR and LEN are filled in by gdb_read_memory_integer(). RESULT is the contents that were diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 16d8cee..120269d 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -264,6 +264,7 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, retval = allocate_value (SYMBOL_TYPE (var)); VALUE_LVAL (retval) = lval_memory; set_value_lazy (retval, 1); + set_value_stack (retval, 1); set_value_address (retval, address); } diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c index 98d6b43..866a156 100644 --- a/gdb/frame-unwind.c +++ b/gdb/frame-unwind.c @@ -151,7 +151,7 @@ frame_unwind_got_memory (struct frame_info *frame, int regnum, CORE_ADDR addr) { struct gdbarch *gdbarch = get_frame_arch (frame); - return value_at_lazy (register_type (gdbarch, regnum), addr); + return value_at_lazy_stack (register_type (gdbarch, regnum), addr); } /* Return a value which indicates that FRAME's saved version of diff --git a/gdb/gdbcore.h b/gdb/gdbcore.h index ec3e1a8..d303c44 100644 --- a/gdb/gdbcore.h +++ b/gdb/gdbcore.h @@ -47,6 +47,10 @@ extern void memory_error (int status, CORE_ADDR memaddr); extern void read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len); +/* Like target_read_stack, but report an error if can't read. */ + +extern void read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, int len); + /* Read an integer from debugged memory, given address and number of bytes. */ diff --git a/gdb/target.c b/gdb/target.c index 8c3b2bd..7c04b3c 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1132,8 +1132,9 @@ target_section_by_addr (struct target_ops *target, CORE_ADDR addr) value are just as for target_xfer_partial. */ static LONGEST -memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf, - ULONGEST memaddr, LONGEST len) +memory_xfer_partial (struct target_ops *ops, enum target_object object, + void *readbuf, const void *writebuf, ULONGEST memaddr, + LONGEST len) { LONGEST res; int reg_len; @@ -1212,7 +1213,8 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf return -1; } - if (region->attrib.cache) + if (region->attrib.cache + || (dcache_stack_enabled_p && object == TARGET_OBJECT_STACK_MEMORY)) { if (readbuf != NULL) res = dcache_xfer_memory (ops, target_dcache, memaddr, readbuf, @@ -1234,6 +1236,15 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf } } + /* 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 (readbuf == NULL && !region->attrib.cache && + dcache_stack_enabled_p && object != TARGET_OBJECT_STACK_MEMORY) + { + dcache_update (target_dcache, memaddr, (void *) writebuf, reg_len); + } + /* If none of those methods found the memory we wanted, fall back to a target partial transfer. Normally a single call to to_xfer_partial is enough; if it doesn't recognize an object @@ -1297,8 +1308,9 @@ target_xfer_partial (struct target_ops *ops, /* 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) - retval = memory_xfer_partial (ops, readbuf, writebuf, offset, len); + if (object == TARGET_OBJECT_MEMORY || object == TARGET_OBJECT_STACK_MEMORY) + retval = memory_xfer_partial (ops, object, readbuf, + writebuf, offset, len); else { enum target_object raw_object = object; @@ -1380,6 +1392,23 @@ target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len) return EIO; } +/* Like target_read_memory, but specify explicitly that this is a read from + the target's stack. This may trigger different cache behavior. */ + +int +target_read_stack (CORE_ADDR memaddr, 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_read (current_target.beneath, TARGET_OBJECT_STACK_MEMORY, NULL, + myaddr, memaddr, len) == len) + return 0; + else + return EIO; +} + int target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, int len) { diff --git a/gdb/target.h b/gdb/target.h index 89d99bb..efdbcea 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -202,6 +202,10 @@ enum target_object Target implementations of to_xfer_partial never need to handle this object, and most callers should not use it. */ TARGET_OBJECT_RAW_MEMORY, + /* Memory known to be part of the target's stack. This is cached even + if it is not in a region marked as such, since it is known to be + "normal" RAM. */ + TARGET_OBJECT_STACK_MEMORY, /* Kernel Unwind Table. See "ia64-tdep.c". */ TARGET_OBJECT_UNWIND_TABLE, /* Transfer auxilliary vector. */ @@ -663,6 +667,8 @@ extern int target_read_string (CORE_ADDR, char **, int, int *); extern int target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len); +extern int target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, int len); + extern int target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, int len); diff --git a/gdb/valops.c b/gdb/valops.c index 1d19393..a07c495 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -562,6 +562,39 @@ value_one (struct type *type, enum lval_type lv) return val; } +/* Helper function for value_at, value_at_lazy, and value_at_lazy_stack. */ + +static struct value * +get_value_at (struct type *type, CORE_ADDR addr, int lazy, int stack) +{ + struct value *val; + + if (TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID) + error (_("Attempt to dereference a generic pointer.")); + + if (lazy) + { + val = allocate_value_lazy (type); + } + else + { + val = allocate_value (type); + + if (stack) + read_stack (addr, value_contents_all_raw (val), TYPE_LENGTH (type)); + else + read_memory (addr, value_contents_all_raw (val), TYPE_LENGTH (type)); + } + + if (stack) + set_value_stack (val, 1); + + VALUE_LVAL (val) = lval_memory; + set_value_address (val, addr); + + return val; +} + /* Return a value with type TYPE located at ADDR. Call value_at only if the data needs to be fetched immediately; @@ -577,19 +610,7 @@ value_one (struct type *type, enum lval_type lv) struct value * value_at (struct type *type, CORE_ADDR addr) { - struct value *val; - - if (TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID) - error (_("Attempt to dereference a generic pointer.")); - - val = allocate_value (type); - - read_memory (addr, value_contents_all_raw (val), TYPE_LENGTH (type)); - - VALUE_LVAL (val) = lval_memory; - set_value_address (val, addr); - - return val; + return get_value_at (type, addr, 0, 0); } /* Return a lazy value with type TYPE located at ADDR (cf. value_at). */ @@ -597,17 +618,17 @@ value_at (struct type *type, CORE_ADDR addr) struct value * value_at_lazy (struct type *type, CORE_ADDR addr) { - struct value *val; - - if (TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID) - error (_("Attempt to dereference a generic pointer.")); + return get_value_at (type, addr, 1, 0); +} - val = allocate_value_lazy (type); +/* Return a lazy value with type TYPE located at ADDR (cf. value_at). If + and when the value is actually fetched, it will be marked as a stack + access. */ - VALUE_LVAL (val) = lval_memory; - set_value_address (val, addr); - - return val; +struct value * +value_at_lazy_stack (struct type *type, CORE_ADDR addr) +{ + return get_value_at (type, addr, 1, 1); } /* Called only from the value_contents and value_contents_all() @@ -634,8 +655,12 @@ value_fetch_lazy (struct value *val) CORE_ADDR addr = value_address (val); int length = TYPE_LENGTH (check_typedef (value_enclosing_type (val))); - if (length) - read_memory (addr, value_contents_all_raw (val), length); + if (length) { + if (value_stack (val)) + read_stack (addr, value_contents_all_raw (val), length); + else + read_memory (addr, value_contents_all_raw (val), length); + } } else if (VALUE_LVAL (val) == lval_register) { diff --git a/gdb/value.c b/gdb/value.c index 7566921..9e70b1c 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -190,6 +190,10 @@ struct value /* If value is a variable, is it initialized or not. */ int initialized; + /* If value is from the stack. If this is set, read_stack will be + used instead of read_memory to enable extra caching. */ + int stack; + /* Actual contents of the value. Target byte-order. NULL or not valid if lazy is nonzero. */ gdb_byte *contents; @@ -433,6 +437,18 @@ set_value_lazy (struct value *value, int val) value->lazy = val; } +int +value_stack (struct value *value) +{ + return value->stack; +} + +void +set_value_stack (struct value *value, int val) +{ + value->stack = val; +} + const gdb_byte * value_contents (struct value *value) { diff --git a/gdb/value.h b/gdb/value.h index c31cce5..c23b0df 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -214,6 +214,9 @@ extern void *value_computed_closure (struct value *value); extern int value_lazy (struct value *); extern void set_value_lazy (struct value *value, int val); +extern int value_stack (struct value *); +extern void set_value_stack (struct value *value, int val); + /* value_contents() and value_contents_raw() both return the address of the gdb buffer used to hold a copy of the contents of the lval. value_contents() is used when the contents of the buffer are needed @@ -342,6 +345,7 @@ extern struct value *value_from_decfloat (struct type *type, extern struct value *value_at (struct type *type, CORE_ADDR addr); extern struct value *value_at_lazy (struct type *type, CORE_ADDR addr); +extern struct value *value_at_lazy_stack (struct type *type, CORE_ADDR addr); extern struct value *value_from_contents_and_address (struct type *, const gdb_byte *,