forked from Imagelibrary/binutils-gdb
Implement TARGET_OBJECT_STACK_MEMORY.
* NEWS: Add note on new "set stack-cache" option. * corefile.c (read_stack): New function. * dcache.c (dcache_struct): New member ptid. (dcache_enable_p): Mark as obsolete. (show_dcache_enabled_p): Flag option as deprecated. (dcache_invalidate): Update ptid. (dcache_invalidate_line): New function. (dcache_read_line): No longer check cacheable attribute, stack accesses get cached despite attribute. (dcache_init): Set ptid. (dcache_xfer_memory): Flush cache if from different ptid than before. Update cache after write. (dcache_update): New function. (dcache_info): Report ptid. (_initialize_dcache): Update text for `remotecache' to indicate it is obsolete. * dcache.h (dcache_update): Declare. * dwarf2loc.c (dwarf2_evaluate_loc_desc): Mark values on stack with set_value_stack. * frame-unwind.c (frame_unwind_got_memory): Ditto. * gdbcore.h (read_stack): Declare. * memattr.c (mem_enable_command): Call target_dcache_invalidate instead of dcache_invalidate. (mem_disable_command, mem_delete_command): Ditto. * target.c (stack_cache_enabled_p_1): New static global. (stack_cache_enabled_p): New static global. (set_stack_cache_enabled_p): New function. (show_stack_cache_enabled_p): New function. (target_dcache): Make static. (target_dcache_invalidate): New function. (target_load, target_resume): Call target_dcache_invalidate instead of dcache_invalidate. (memory_xfer_partial): New arg object, all callers updated. Check for existing inferior before calling dcache routines. When writing non-TARGET_OBJECT_STACK_MEMORY, notify dcache. (target_xfer_partial): Call memory_xfer_partial for TARGET_OBJECT_STACK_MEMORY. (target_read_stack): New function. (initialize_targets): Install new option `stack-cache'. * target.h: Remove #include of dcache.h. (enum target_object): New value TARGET_OBJECT_STACK_MEMORY. (target_dcache): Delete. (target_dcache_invalidate): Declare. (target_read_stack): Declare. * top.c (prepare_execute_command): New function. (execute_command): Call prepare_execute_command instead of free_all_values. * top.h (prepare_execute_command): Declare. * valops.c (get_value_at): New function. (value_at): Guts moved to get_value_at. (value_at_lazy): Similarly. (value_fetch_lazy): Call read_stack for stack values. * value.c (struct value): New member `stack'. (value_stack, set_value_stack): New functions. * value.h (value_stack, set_value_stack): Declare. * mi/mi-main.c (mi_cmd_execute): Call prepare_execute_command instead of free_all_values. doc/ * gdb.texinfo (Caching Data of Remote Targets): Update text. Mark `set/show remotecache' options as obsolete. Document new `set/show stack-cache' option. Update text for `info dcache'.
This commit is contained in:
88
gdb/dcache.c
88
gdb/dcache.c
@@ -24,6 +24,7 @@
|
||||
#include "gdb_string.h"
|
||||
#include "gdbcore.h"
|
||||
#include "target.h"
|
||||
#include "inferior.h"
|
||||
#include "splay-tree.h"
|
||||
|
||||
/* The data cache could lead to incorrect results because it doesn't
|
||||
@@ -103,6 +104,9 @@ struct dcache_struct
|
||||
|
||||
/* The number of in-use lines in the cache. */
|
||||
int size;
|
||||
|
||||
/* The ptid of last inferior to use cache or null_ptid. */
|
||||
ptid_t ptid;
|
||||
};
|
||||
|
||||
static struct dcache_block *dcache_hit (DCACHE *dcache, CORE_ADDR addr);
|
||||
@@ -117,16 +121,15 @@ static void dcache_info (char *exp, int tty);
|
||||
|
||||
void _initialize_dcache (void);
|
||||
|
||||
static int dcache_enabled_p = 0;
|
||||
static int dcache_enabled_p = 0; /* OBSOLETE */
|
||||
|
||||
static void
|
||||
show_dcache_enabled_p (struct ui_file *file, int from_tty,
|
||||
struct cmd_list_element *c, const char *value)
|
||||
{
|
||||
fprintf_filtered (file, _("Cache use for remote targets is %s.\n"), value);
|
||||
fprintf_filtered (file, _("Deprecated remotecache flag is %s.\n"), value);
|
||||
}
|
||||
|
||||
|
||||
static DCACHE *last_cache; /* Used by info dcache */
|
||||
|
||||
/* Free all the data cache blocks, thus discarding all cached data. */
|
||||
@@ -152,6 +155,23 @@ dcache_invalidate (DCACHE *dcache)
|
||||
dcache->oldest = NULL;
|
||||
dcache->newest = NULL;
|
||||
dcache->size = 0;
|
||||
dcache->ptid = null_ptid;
|
||||
}
|
||||
|
||||
/* Invalidate the line associated with ADDR. */
|
||||
|
||||
static void
|
||||
dcache_invalidate_line (DCACHE *dcache, CORE_ADDR addr)
|
||||
{
|
||||
struct dcache_block *db = dcache_hit (dcache, addr);
|
||||
|
||||
if (db)
|
||||
{
|
||||
splay_tree_remove (dcache->tree, (splay_tree_key) db->addr);
|
||||
db->newer = dcache->freelist;
|
||||
dcache->freelist = db;
|
||||
--dcache->size;
|
||||
}
|
||||
}
|
||||
|
||||
/* If addr is present in the dcache, return the address of the block
|
||||
@@ -198,8 +218,9 @@ dcache_read_line (DCACHE *dcache, struct dcache_block *db)
|
||||
else
|
||||
reg_len = region->hi - memaddr;
|
||||
|
||||
/* Skip non-cacheable/non-readable regions. */
|
||||
if (!region->attrib.cache || region->attrib.mode == MEM_WO)
|
||||
/* Skip non-readable regions. The cache attribute can be ignored,
|
||||
since we may be loading this for a stack access. */
|
||||
if (region->attrib.mode == MEM_WO)
|
||||
{
|
||||
memaddr += reg_len;
|
||||
myaddr += reg_len;
|
||||
@@ -296,7 +317,7 @@ dcache_peek_byte (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr)
|
||||
an area of memory which wasn't present in the cache doesn't cause
|
||||
it to be loaded in.
|
||||
|
||||
Always return 1 to simplify dcache_xfer_memory. */
|
||||
Always return 1 (meaning success) to simplify dcache_xfer_memory. */
|
||||
|
||||
static int
|
||||
dcache_poke_byte (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr)
|
||||
@@ -338,6 +359,7 @@ dcache_init (void)
|
||||
dcache->newest = NULL;
|
||||
dcache->freelist = NULL;
|
||||
dcache->size = 0;
|
||||
dcache->ptid = null_ptid;
|
||||
last_cache = dcache;
|
||||
|
||||
return dcache;
|
||||
@@ -366,7 +388,7 @@ dcache_free (DCACHE *dcache)
|
||||
to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is
|
||||
nonzero.
|
||||
|
||||
Returns length of data written or read; 0 for error. */
|
||||
The meaning of the result is the same as for target_write. */
|
||||
|
||||
int
|
||||
dcache_xfer_memory (struct target_ops *ops, DCACHE *dcache,
|
||||
@@ -378,6 +400,15 @@ dcache_xfer_memory (struct target_ops *ops, DCACHE *dcache,
|
||||
int (*xfunc) (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr);
|
||||
xfunc = should_write ? dcache_poke_byte : dcache_peek_byte;
|
||||
|
||||
/* If this is a different inferior from what we've recorded,
|
||||
flush the cache. */
|
||||
|
||||
if (! ptid_equal (inferior_ptid, dcache->ptid))
|
||||
{
|
||||
dcache_invalidate (dcache);
|
||||
dcache->ptid = inferior_ptid;
|
||||
}
|
||||
|
||||
/* Do write-through first, so that if it fails, we don't write to
|
||||
the cache at all. */
|
||||
|
||||
@@ -385,14 +416,25 @@ dcache_xfer_memory (struct target_ops *ops, DCACHE *dcache,
|
||||
{
|
||||
res = target_write (ops, TARGET_OBJECT_RAW_MEMORY,
|
||||
NULL, myaddr, memaddr, len);
|
||||
if (res < len)
|
||||
return 0;
|
||||
if (res <= 0)
|
||||
return res;
|
||||
/* Update LEN to what was actually written. */
|
||||
len = res;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (!xfunc (dcache, memaddr + i, myaddr + i))
|
||||
return 0;
|
||||
{
|
||||
/* That failed. Discard its cache line so we don't have a
|
||||
partially read line. */
|
||||
dcache_invalidate_line (dcache, memaddr + i);
|
||||
/* If we're writing, we still wrote LEN bytes. */
|
||||
if (should_write)
|
||||
return len;
|
||||
else
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
@@ -407,6 +449,18 @@ dcache_xfer_memory (struct target_ops *ops, DCACHE *dcache,
|
||||
"logically" connected but not actually a single call to one of the
|
||||
memory transfer functions. */
|
||||
|
||||
/* Just update any cache lines which are already present. This is called
|
||||
by memory_xfer_partial in cases where the access would otherwise not go
|
||||
through the cache. */
|
||||
|
||||
void
|
||||
dcache_update (DCACHE *dcache, CORE_ADDR memaddr, gdb_byte *myaddr, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; i++)
|
||||
dcache_poke_byte (dcache, memaddr + i, myaddr + i);
|
||||
}
|
||||
|
||||
static void
|
||||
dcache_print_line (int index)
|
||||
{
|
||||
@@ -474,12 +528,15 @@ dcache_info (char *exp, int tty)
|
||||
printf_filtered (_("Dcache line width %d, maximum size %d\n"),
|
||||
LINE_SIZE, DCACHE_SIZE);
|
||||
|
||||
if (!last_cache)
|
||||
if (!last_cache || ptid_equal (last_cache->ptid, null_ptid))
|
||||
{
|
||||
printf_filtered (_("No data cache available.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
printf_filtered (_("Contains data for %s\n"),
|
||||
target_pid_to_str (last_cache->ptid));
|
||||
|
||||
refcount = 0;
|
||||
|
||||
n = splay_tree_min (last_cache->tree);
|
||||
@@ -507,11 +564,10 @@ _initialize_dcache (void)
|
||||
&dcache_enabled_p, _("\
|
||||
Set cache use for remote targets."), _("\
|
||||
Show cache use for remote targets."), _("\
|
||||
When on, use data caching for remote targets. For many remote targets\n\
|
||||
this option can offer better throughput for reading target memory.\n\
|
||||
Unfortunately, gdb does not currently know anything about volatile\n\
|
||||
registers and thus data caching will produce incorrect results with\n\
|
||||
volatile registers are in use. By default, this option is off."),
|
||||
This used to enable the data cache for remote targets. The cache\n\
|
||||
functionality is now controlled by the memory region system and the\n\
|
||||
\"stack-cache\" flag; \"remotecache\" now does nothing and\n\
|
||||
exists only for compatibility reasons."),
|
||||
NULL,
|
||||
show_dcache_enabled_p,
|
||||
&setlist, &showlist);
|
||||
|
||||
Reference in New Issue
Block a user