From 29e5738069326d025cb0aecc2aab25186ef669b8 Mon Sep 17 00:00:00 2001 From: "J.T. Conklin" Date: Tue, 23 Jan 2001 22:48:56 +0000 Subject: [PATCH] * exec.c (xfer_memory): Add attrib argument. * infptrace.c (child_xfer_memory): Likewise. * monitor.c (monitor_xfer_memory): Likewise. * remote-adapt.c (adapt_xfer_inferior_memory): Likewise. * remote-array.c (array_xfer_memory): Likewise. * remote-bug.c (bug_xfer_memory): Likewise. * remote-e7000.c (e7000_xfer_inferior_memory): Likewise. * remote-eb.c (eb_xfer_inferior_memory): Likewise. * remote-es.c (es1800_xfer_inferior_memory): Likewise. * remote-mips.c (mips_xfer_memory): Likewise. * remote-mm.c (mm_xfer_inferior_memory): Likewise. * remote-nindy.c (nindy_xfer_inferior_memory): Likewise. * remote-os9k.c (rombug_xfer_inferior_memory): Likewise. * remote-rdi.c (arm_rdi_xfer_memory): Likewise. * remote-rdp.c (remote_rdp_xfer_inferior_memory): Likewise. * remote-sds.c (sds_xfer_memory): Likewise. * remote-sim.c (gdbsim_xfer_inferior_memory): Likewise. * remote-st.c (st2000_xfer_inferior_memory): Likewise. * remote-udi.c (udi_xfer_inferior_memory): Likewise. * remote-vx.c (vx_xfer_memory): Likewise. * remote.c (remote_xfer_memory): Likewise. * target.c (debug_to_xfer_memory, do_xfer_memory): Likewise. * target.h (child_xfer_memory, do_xfer_memory, xfer_memory): Likewise. * target.h (#include "memattr.h"): Added. (target_ops.to_xfer_memory): Add attrib argument. * wince.c (_initialize_inftarg): Removed call to set_dcache_state. * dcache.h (set_dcache_state): Removed declaration. * dcache.c (set_dcache_state): Removed definition * dcache.c: Update module comment, as dcache is now enabled and disabled with memory region attributes instead of by the global variable "remotecache". Add comment describing the interaction between dcache and memory region attributes. (dcache_xfer_memory): Add comment describing benefits of moving cache writeback to a higher level. (dcache_struct): Removed cache_has_stuff field. This was used to record whether the cache had been accessed in order to invalidate it when it was disabled. However, this is not needed because the cache is write through and the code that enables, disables, and deletes memory regions invalidate the cache. Add comment which suggests that we could be more selective and only invalidate those cache lines containing data from those memory regions. (dcache_invalidate): Updated. (dcache_xfer_memory): Updated. (dcache_alloc): Don't abort() if dcache_enabled_p is clear. (dcache_xfer_memory): Removed code that called do_xfer_memory() to perform a uncached transfer if dcache_enabled_p was clear. This function is now only called if caching is enabled for the memory region. (dcache_info): Always print cache info. * target.c (do_xfer_memory): Add attrib argument. (target_xfer_memory, target_xfer_memory_partial): Break transfer into chunks defined by memory regions, pass region attributes to do_xfer_memory(). * dcache.c (dcache_read_line, dcache_write_line): Likewise. * Makefile.in (SFILES): Add memattr.c. (COMMON_OBS): Add memattr.o. (dcache.o): Add target.h to dependencies. * memattr.c: New file. * memattr.h: Likewise. --- gdb/ChangeLog | 66 ++++++ gdb/Makefile.in | 9 +- gdb/dcache.c | 231 ++++++++++++-------- gdb/dcache.h | 5 +- gdb/doc/ChangeLog | 4 + gdb/doc/gdb.texinfo | 134 +++++++++++- gdb/exec.c | 3 +- gdb/infptrace.c | 3 +- gdb/memattr.c | 497 ++++++++++++++++++++++++++++++++++++++++++++ gdb/memattr.h | 72 +++++++ gdb/monitor.c | 9 +- gdb/remote-adapt.c | 6 +- gdb/remote-array.c | 5 +- gdb/remote-bug.c | 5 +- gdb/remote-e7000.c | 6 +- gdb/remote-eb.c | 5 +- gdb/remote-es.c | 8 +- gdb/remote-mips.c | 9 +- gdb/remote-mm.c | 6 +- gdb/remote-nindy.c | 6 +- gdb/remote-os9k.c | 6 +- gdb/remote-rdi.c | 8 +- gdb/remote-rdp.c | 21 +- gdb/remote-sds.c | 8 +- gdb/remote-sim.c | 13 +- gdb/remote-st.c | 6 +- gdb/remote-udi.c | 5 +- gdb/remote-vx.c | 5 +- gdb/remote.c | 7 +- gdb/target.c | 107 ++++++++-- gdb/target.h | 17 +- gdb/wince.c | 3 +- 32 files changed, 1116 insertions(+), 179 deletions(-) create mode 100644 gdb/memattr.c create mode 100644 gdb/memattr.h diff --git a/gdb/ChangeLog b/gdb/ChangeLog index dc1e3e0d3dc..29f8da47d7a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,71 @@ 2001-01-23 J.T. Conklin + + * exec.c (xfer_memory): Add attrib argument. + * infptrace.c (child_xfer_memory): Likewise. + * monitor.c (monitor_xfer_memory): Likewise. + * remote-adapt.c (adapt_xfer_inferior_memory): Likewise. + * remote-array.c (array_xfer_memory): Likewise. + * remote-bug.c (bug_xfer_memory): Likewise. + * remote-e7000.c (e7000_xfer_inferior_memory): Likewise. + * remote-eb.c (eb_xfer_inferior_memory): Likewise. + * remote-es.c (es1800_xfer_inferior_memory): Likewise. + * remote-mips.c (mips_xfer_memory): Likewise. + * remote-mm.c (mm_xfer_inferior_memory): Likewise. + * remote-nindy.c (nindy_xfer_inferior_memory): Likewise. + * remote-os9k.c (rombug_xfer_inferior_memory): Likewise. + * remote-rdi.c (arm_rdi_xfer_memory): Likewise. + * remote-rdp.c (remote_rdp_xfer_inferior_memory): Likewise. + * remote-sds.c (sds_xfer_memory): Likewise. + * remote-sim.c (gdbsim_xfer_inferior_memory): Likewise. + * remote-st.c (st2000_xfer_inferior_memory): Likewise. + * remote-udi.c (udi_xfer_inferior_memory): Likewise. + * remote-vx.c (vx_xfer_memory): Likewise. + * remote.c (remote_xfer_memory): Likewise. + * target.c (debug_to_xfer_memory, do_xfer_memory): Likewise. + * target.h (child_xfer_memory, do_xfer_memory, xfer_memory): Likewise. + + * target.h (#include "memattr.h"): Added. + (target_ops.to_xfer_memory): Add attrib argument. + + * wince.c (_initialize_inftarg): Removed call to set_dcache_state. + * dcache.h (set_dcache_state): Removed declaration. + * dcache.c (set_dcache_state): Removed definition + + * dcache.c: Update module comment, as dcache is now enabled and + disabled with memory region attributes instead of by the global + variable "remotecache". Add comment describing the interaction + between dcache and memory region attributes. + (dcache_xfer_memory): Add comment describing benefits of moving + cache writeback to a higher level. + (dcache_struct): Removed cache_has_stuff field. This was used to + record whether the cache had been accessed in order to invalidate + it when it was disabled. However, this is not needed because the + cache is write through and the code that enables, disables, and + deletes memory regions invalidate the cache. Add comment which + suggests that we could be more selective and only invalidate those + cache lines containing data from those memory regions. + (dcache_invalidate): Updated. + (dcache_xfer_memory): Updated. + (dcache_alloc): Don't abort() if dcache_enabled_p is clear. + (dcache_xfer_memory): Removed code that called do_xfer_memory() to + perform a uncached transfer if dcache_enabled_p was clear. This + function is now only called if caching is enabled for the memory + region. + (dcache_info): Always print cache info. + + * target.c (do_xfer_memory): Add attrib argument. + (target_xfer_memory, target_xfer_memory_partial): Break transfer + into chunks defined by memory regions, pass region attributes to + do_xfer_memory(). + * dcache.c (dcache_read_line, dcache_write_line): Likewise. + + * Makefile.in (SFILES): Add memattr.c. + (COMMON_OBS): Add memattr.o. + (dcache.o): Add target.h to dependencies. + * memattr.c: New file. + * memattr.h: Likewise. + * config/m32r/m32r.mt (GDBSERVER_LIBS): Added ../../intl/libintl.a. * config/mips/vr5000.mt (GDBSERVER_LIBS): Likewise. * config/tic80/tic80.mt (GDBSERVER_LIBS): Likewise. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 9bfe4241e50..1d987a82fea 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1,5 +1,5 @@ # Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -# 1998, 1999, 2000 Free Software Foundation, Inc. +# 1998, 1999, 2000, 2001 Free Software Foundation, Inc. # This file is part of GDB. @@ -521,7 +521,7 @@ SFILES = ax-general.c ax-gdb.c bcache.c blockframe.c breakpoint.c \ varobj.c wrapper.c \ jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \ m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c main.c maint.c \ - mem-break.c minsyms.c mipsread.c nlmread.c objfiles.c \ + memattr.c mem-break.c minsyms.c mipsread.c nlmread.c objfiles.c \ p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c \ printcmd.c remote.c remote-nrom.c scm-exp.c scm-lang.c \ scm-valprint.c source.c stabsread.c stack.c symfile.c \ @@ -664,7 +664,7 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \ expprint.o environ.o stack.o thread.o \ event-loop.o event-top.o inf-loop.o completer.o \ gdbarch.o arch-utils.o gdbtypes.o copying.o $(DEPFILES) \ - mem-break.o target.o parse.o language.o $(YYOBJ) buildsym.o \ + memattr.o mem-break.o target.o parse.o language.o $(YYOBJ) buildsym.o \ kod.o kod-cisco.o \ gdb-events.o \ exec.o bcache.o objfiles.o minsyms.o maint.o demangle.o \ @@ -1288,7 +1288,8 @@ corelow.o: corelow.c $(command_h) $(defs_h) $(gdbcore_h) $(inferior_h) \ cp-valprint.o: cp-valprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \ $(gdbtypes_h) $(symtab_h) $(value_h) gdb_string.h -dcache.o: dcache.c $(dcache_h) $(defs_h) $(gdbcmd_h) gdb_string.h $(gdbcore_h) +dcache.o: dcache.c $(dcache_h) $(defs_h) $(gdbcmd_h) gdb_string.h \ + $(gdbcore_h) target.h dbxread.o: dbxread.c $(breakpoint_h) buildsym.h $(command_h) \ complaints.h $(defs_h) $(expression_h) gdb-stabs.h $(gdbcore_h) \ diff --git a/gdb/dcache.c b/gdb/dcache.c index cdfe4762de4..7973b998ea1 100644 --- a/gdb/dcache.c +++ b/gdb/dcache.c @@ -1,5 +1,5 @@ /* Caching code. - Copyright 1992-1993, 1995, 1998-1999, 2000 Free Software Foundation, Inc. + Copyright 1992-1993, 1995, 1998-1999, 2000, 2001 Free Software Foundation, Inc. This file is part of GDB. @@ -25,14 +25,10 @@ #include "gdbcore.h" #include "target.h" -/* - The data cache could lead to incorrect results because it doesn't know - about volatile variables, thus making it impossible to debug - functions which use memory mapped I/O devices. - - set remotecache 0 - - In those cases. +/* The data cache could lead to incorrect results because it doesn't + know about volatile variables, thus making it impossible to debug + functions which use memory mapped I/O devices. Set the nocache + memory region attribute in those cases. In general the dcache speeds up performance, some speed improvement comes from the actual caching mechanism, but the major gain is in @@ -61,8 +57,10 @@ ENTRY_DIRTY means that the byte has some data in it which should be written out to the remote target one day, but contains correct - data. ENTRY_OK means that the data is the same in the cache as it - is in remote memory. + data. + + ENTRY_OK means that the data is the same in the cache as it is in + remote memory. The ENTRY_DIRTY state is necessary because GDB likes to write large @@ -76,10 +74,22 @@ protocol overhead. This way, all those little writes are bundled up into an entire cache line write in one go, without having to read the cache line in the first place. + */ +/* NOTE: Interaction of dcache and memory region attributes - */ + As there is no requirement that memory region attributes be aligned + to or be a multiple of the dcache page size, dcache_read_line() and + dcache_write_line() must break up the page by memory region. If a + chunk does not have the cache attribute set, an invalid memory type + is set, etc., then the chunk is skipped. Those chunks are handled + in target_xfer_memory() (or target_xfer_memory_partial()). + This doesn't occur very often. The most common occurance is when + the last bit of the .text segment and the first bit of the .data + segment fall within the same dcache page with a ro/cacheable memory + region defined for the .text segment and a rw/non-cacheable memory + region defined for the .data segment. */ /* This value regulates the number of cache blocks stored. Smaller values reduce the time spent searching for a cache @@ -123,6 +133,19 @@ struct dcache_block }; +/* FIXME: dcache_struct used to have a cache_has_stuff field that was + used to record whether the cache had been accessed. This was used + to invalidate the cache whenever caching was (re-)enabled (if the + cache was disabled and later re-enabled, it could contain stale + data). This was not needed because the cache is write through and + the code that enables, disables, and deletes memory region all + invalidate the cache. + + This is overkill, since it also invalidates cache lines from + unrelated regions. One way this could be addressed by adding a + new function that takes an address and a length and invalidates + only those cache lines that match. */ + struct dcache_struct { /* free list */ @@ -135,11 +158,6 @@ struct dcache_struct /* The cache itself. */ struct dcache_block *the_cache; - - /* potentially, if the cache was enabled, and then turned off, and - then turned on again, the stuff in it could be stale, so this is - used to mark it */ - int cache_has_stuff; }; static int dcache_poke_byte (DCACHE *dcache, CORE_ADDR addr, char *ptr); @@ -189,8 +207,6 @@ dcache_invalidate (DCACHE *dcache) db->p = 0; } - dcache->cache_has_stuff = 0; - return; } @@ -224,39 +240,75 @@ dcache_hit (DCACHE *dcache, CORE_ADDR addr) static int dcache_write_line (DCACHE *dcache, register struct dcache_block *db) { - int s; - int e; + CORE_ADDR memaddr; + char *myaddr; + int len; + int res; + int reg_len; + struct mem_region *region; - if (db->anydirty) + if (!db->anydirty) + return 1; + + len = LINE_SIZE; + memaddr = db->addr; + myaddr = db->data; + + while (len > 0) { - for (s = 0; s < LINE_SIZE; s++) + int s; + int e; + int dirty_len; + + region = lookup_mem_region(memaddr); + if (memaddr + len < region->hi) + reg_len = len; + else + reg_len = region->hi - memaddr; + + if (!region->attrib.cache || region->attrib.mode == MEM_RO) + { + memaddr += reg_len; + myaddr += reg_len; + len -= reg_len; + continue; + } + + while (reg_len > 0) { - if (db->state[s] == ENTRY_DIRTY) + s = XFORM(memaddr); + do { + if (db->state[s] == ENTRY_DIRTY) + break; + s++; + reg_len--; + } while (reg_len > 0); + + e = s; + do { + if (db->state[e] != ENTRY_DIRTY) + break; + e++; + reg_len--; + } while (reg_len > 0); + + dirty_len = e - s; + while (dirty_len > 0) { - int len = 0; - for (e = s; e < LINE_SIZE; e++, len++) - if (db->state[e] != ENTRY_DIRTY) - break; - { - /* all bytes from s..s+len-1 need to - be written out */ - int done = 0; - while (done < len) - { - int t = do_xfer_memory (db->addr + s + done, - db->data + s + done, - len - done, 1); - if (t <= 0) - return 0; - done += t; - } - memset (db->state + s, ENTRY_OK, len); - s = e; - } + res = do_xfer_memory(memaddr, myaddr, dirty_len, 1, + ®ion->attrib); + if (res <= 0) + return 0; + + memset (db->state[XFORM(memaddr)], ENTRY_OK, res); + memaddr += res; + myaddr += res; + dirty_len -= res; } } - db->anydirty = 0; } + + db->anydirty = 0; return 1; } @@ -268,6 +320,8 @@ dcache_read_line (DCACHE *dcache, struct dcache_block *db) char *myaddr; int len; int res; + int reg_len; + struct mem_region *region; /* If there are any dirty bytes in the line, it must be written before a new line can be read */ @@ -283,13 +337,32 @@ dcache_read_line (DCACHE *dcache, struct dcache_block *db) while (len > 0) { - res = do_xfer_memory (memaddr, myaddr, len, 0); - if (res <= 0) - return 0; + region = lookup_mem_region(memaddr); + if (memaddr + len < region->hi) + reg_len = len; + else + reg_len = region->hi - memaddr; + + if (!region->attrib.cache || region->attrib.mode == MEM_WO) + { + memaddr += reg_len; + myaddr += reg_len; + len -= reg_len; + continue; + } + + while (reg_len > 0) + { + res = do_xfer_memory (memaddr, myaddr, reg_len, 0, + ®ion->attrib); + if (res <= 0) + return 0; - memaddr += res; - myaddr += res; - len -= res; + memaddr += res; + myaddr += res; + len -= res; + reg_len -= res; + } } memset (db->state, ENTRY_OK, sizeof (db->data)); @@ -306,9 +379,6 @@ dcache_alloc (DCACHE *dcache, CORE_ADDR addr) { register struct dcache_block *db; - if (dcache_enabled_p == 0) - abort (); - /* Take something from the free list */ db = dcache->free_head; if (db) @@ -342,7 +412,7 @@ dcache_alloc (DCACHE *dcache, CORE_ADDR addr) return db; } -/* Writeback any dirty lines to the remote. */ +/* Writeback any dirty lines. */ static int dcache_writeback (DCACHE *dcache) { @@ -452,30 +522,27 @@ dcache_xfer_memory (DCACHE *dcache, CORE_ADDR memaddr, char *myaddr, int len, int should_write) { int i; + int (*xfunc) (DCACHE *dcache, CORE_ADDR addr, char *ptr); + xfunc = should_write ? dcache_poke_byte : dcache_peek_byte; - if (dcache_enabled_p) + for (i = 0; i < len; i++) { - int (*xfunc) (DCACHE *dcache, CORE_ADDR addr, char *ptr); - xfunc = should_write ? dcache_poke_byte : dcache_peek_byte; - - for (i = 0; i < len; i++) - { - if (!xfunc (dcache, memaddr + i, myaddr + i)) - return 0; - } - - if (should_write) - dcache_writeback (dcache); - - dcache->cache_has_stuff = 1; + if (!xfunc (dcache, memaddr + i, myaddr + i)) + return 0; } - else - { - if (dcache->cache_has_stuff) - dcache_invalidate (dcache); - len = do_xfer_memory(memaddr, myaddr, len, should_write); - } + /* FIXME: There may be some benefit from moving the cache writeback + to a higher layer, as it could occur after a sequence of smaller + writes have been completed (as when a stack frame is constructed + for an inferior function call). Note that only moving it up one + level to target_xfer_memory() (also target_xfer_memory_partial()) + is not sufficent, since we want to coalesce memory transfers that + are "logically" connected but not actually a single call to one + of the memory transfer functions. */ + + if (should_write) + dcache_writeback (dcache); + return len; } @@ -484,12 +551,7 @@ dcache_info (char *exp, int tty) { struct dcache_block *p; - if (!dcache_enabled_p) - { - printf_filtered ("Dcache not enabled\n"); - return; - } - printf_filtered ("Dcache enabled, line width %d, depth %d\n", + printf_filtered ("Dcache line width %d, depth %d\n", LINE_SIZE, DCACHE_SIZE); if (last_cache) @@ -513,13 +575,6 @@ dcache_info (char *exp, int tty) } } -/* Turn dcache on or off. */ -void -set_dcache_state (int what) -{ - dcache_enabled_p = !!what; -} - void _initialize_dcache (void) { diff --git a/gdb/dcache.h b/gdb/dcache.h index 079b03790cb..44d16ac64ed 100644 --- a/gdb/dcache.h +++ b/gdb/dcache.h @@ -1,7 +1,7 @@ /* Declarations for caching. Typically used by remote back ends for caching remote memory. - Copyright 1992, 1993 Free Software Foundation, Inc. + Copyright 1992, 1993, 2001 Free Software Foundation, Inc. This file is part of GDB. @@ -39,7 +39,4 @@ void dcache_free (DCACHE *); int dcache_xfer_memory (DCACHE *cache, CORE_ADDR mem, char *my, int len, int should_write); -/* Turn dcache state on or off */ -void set_dcache_state (int); - #endif /* DCACHE_H */ diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 91dd4ae199e..f98d81ba5cf 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2001-01-23 J.T. Conklin + + * gdb.texinfo (Memory region attributes): New manual section. + 2001-01-04 Nicholas Duffek * gdbint.texinfo (POP_FRAME): Document use by return_command. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index aa925657e1a..72f50d95897 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -1,5 +1,5 @@ \input texinfo @c -*-texinfo-*- -@c Copyright 1988-2000 +@c Copyright 1988-2001 @c Free Software Foundation, Inc. @c @c %**start of header @@ -4347,6 +4347,7 @@ Table}. * Convenience Vars:: Convenience variables * Registers:: Registers * Floating Point Hardware:: Floating point hardware +* Memory Region Attributes:: Memory region attributes @end menu @node Expressions @@ -5504,6 +5505,137 @@ floating point chip. Currently, @samp{info float} is supported on the ARM and x86 machines. @end table +@node Memory Region Attributes +@section Memory Region Attributes +@cindex memory region attributes + +@dfn{Memory region attributes} allow you to describe special handling +required by regions of your target's memory. @value{GDBN} uses attributes +to determine whether to allow certain types of memory accesses; whether to +use specific width accesses; and whether to cache target memory. + +Defined memory regions can be individually enabled and disabled. When a +memory region is disabled, @value{GDBN} uses the default attributes when +accessing memory in that region. Similarly, if no memory regions have +been defined, @value{GDBN} uses the default attributes when accessing +all memory. + +When a memory region is defined, it is given a number to identify it; +to enable, disable, or remove a memory region, you specify that number. + +@table @code +@kindex mem +@item mem @var{address1} @var{address1} @var{attributes}@dots{} +Define memory region bounded by @var{address1} and @var{address2} +with attributes @var{attributes}@dots{}. + +@kindex delete mem +@item delete mem @var{nums}@dots{} +Remove memory region numbers @var{nums}. + +@kindex disable mem +@item disable mem @var{nums}@dots{} +Disable memory region numbers @var{nums}. +A disabled memory region is not forgotten. +It may be enabled again later. + +@kindex enable mem +@item enable mem @var{nums}@dots{} +Enable memory region numbers @var{nums}. + +@kindex info mem +@item info mem +Print a table of all defined memory regions, with the following columns +for each region. + +@table @emph +@item Memory Region Number +@item Enabled or Disabled. +Enabled memory regions are marked with @samp{y}. +Disabled memory regions are marked with @samp{n}. + +@item Lo Address +The address defining the inclusive lower bound of the memory region. + +@item Hi Address +The address defining the exclusive upper bound of the memory region. + +@item Attributes +The list of attributes set for this memory region. +@end table +@end table + + +@subsection Attributes + +@subsubsection Memory Access Mode +The access mode attributes set whether @value{GDBN} may make read or +write accesses to a memory region. + +While these attributes prevent @value{GDBN} from performing invalid +memory accesses, they do nothing to prevent the target system, I/O DMA, +etc. from accessing memory. + +@table @code +@item ro +Memory is read only. +@item wo +Memory is write only. +@item rw +Memory is read/write (default). +@end table + +@subsubsection Memory Access Size +The acccess size attributes tells @value{GDBN} to use specific sized +accesses in the memory region. Often memory mapped device registers +require specific sized accesses. If no access size attribute is +specified, @value{GDBN} may use accesses of any size. + +@table @code +@item 8 +Use 8 bit memory accesses. +@item 16 +Use 16 bit memory accesses. +@item 32 +Use 32 bit memory accesses. +@item 64 +Use 64 bit memory accesses. +@end table + +@c @subsubsection Hardware/Software Breakpoints +@c The hardware/software breakpoint attributes set whether @value{GDBN} +@c will use hardware or software breakpoints for the internal breakpoints +@c used by the step, next, finish, until, etc. commands. +@c +@c @table @code +@c @item hwbreak +@c Always use hardware breakpoints +@c @item swbreak (default) +@c @end table + +@subsubsection Data Cache +The data cache attributes set whether @value{GDBN} will cache target +memory. While this generally improves performance by reducing debug +protocol overhead, it can lead to incorrect results because @value{GDBN} +does not know about volatile variables or memory mapped device +registers. + +@table @code +@item cache +Enable @value{GDBN} to cache target memory. +@item nocache (default) +Disable @value{GDBN} from caching target memory. +@end table + +@c @subsubsection Memory Write Verification +@c The memory write verification attributes set whether @value{GDBN} +@c will re-reads data after each write to verify the write was successful. +@c +@c @table @code +@c @item verify +@c @item noverify (default) +@c @end table + @node Languages @chapter Using @value{GDBN} with Different Languages @cindex languages diff --git a/gdb/exec.c b/gdb/exec.c index 6c956bf43f2..e39062beca5 100644 --- a/gdb/exec.c +++ b/gdb/exec.c @@ -1,5 +1,5 @@ /* Work with executable files, for GDB. - Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1997, 1998 + Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1997, 1998, 2001 Free Software Foundation, Inc. This file is part of GDB. @@ -449,6 +449,7 @@ map_vmap (bfd *abfd, bfd *arch) int xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, + struct mem_attrib *attrib, struct target_ops *target) { boolean res; diff --git a/gdb/infptrace.c b/gdb/infptrace.c index 30ceb87c4cc..f7a1a3a7e68 100644 --- a/gdb/infptrace.c +++ b/gdb/infptrace.c @@ -1,5 +1,5 @@ /* Low level Unix child interface to ptrace, for GDB when running under Unix. - Copyright 1988, 89, 90, 91, 92, 93, 94, 95, 96, 1998 + Copyright 1988, 89, 90, 91, 92, 93, 94, 95, 96, 1998, 2001 Free Software Foundation, Inc. This file is part of GDB. @@ -511,6 +511,7 @@ store_inferior_registers (int regno) int child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, + struct mem_attrib *attrib ATTRIBUTE_UNUSED, struct target_ops *target) { register int i; diff --git a/gdb/memattr.c b/gdb/memattr.c new file mode 100644 index 00000000000..5e9e9d5c04e --- /dev/null +++ b/gdb/memattr.c @@ -0,0 +1,497 @@ +/* memattr.c */ +#include "defs.h" +#include "command.h" +#include "gdbcmd.h" +#include "memattr.h" +#include "target.h" +#include "value.h" +#include "language.h" +#include "gdb_string.h" + +/* FIXME: While this conflicts with the enum defined in breakpoint.h, + I used them to be consistant with how breakpoints, tracepoints, and + displays are implemented. It doesn't lose now because breakpoint.h + is not included. */ +enum enable +{ + disabled, + enabled +}; + +const struct mem_attrib default_mem_attrib = +{ + MEM_RW, /* mode */ + MEM_WIDTH_UNSPECIFIED, + false, /* hwbreak */ + false, /* cache */ + false /* verify */ +}; + +static struct mem_region *mem_region_chain = NULL; +static mem_number = 0; + +static struct mem_region * +create_mem_region (CORE_ADDR lo, CORE_ADDR hi, + const struct mem_attrib *attrib) +{ + struct mem_region *n, *p, *new; + + if (lo > hi) + { + printf_unfiltered ("invalid memory region\n"); + return NULL; + } + + n = mem_region_chain; + while (n) + { + /* overlapping node */ + if ((lo >= n->lo && lo <= n->hi) || + (hi >= n->lo && hi <= n->hi)) + { + printf_unfiltered ("overlapping memory region\n"); + return NULL; + } + } + + new = xmalloc (sizeof (struct mem_region)); + new->lo = lo; + new->hi = hi; + new->number = ++mem_number; + new->status = enabled; + new->attrib = *attrib; + + /* link in new node */ + new->next = mem_region_chain; + mem_region_chain = new; + + return new; +} + +static void +delete_mem_region (struct mem_region *m) +{ + free (m); +} + +/* + * Look up the memory region cooresponding to ADDR. + */ +struct mem_region * +lookup_mem_region (CORE_ADDR addr) +{ + static struct mem_region region; + struct mem_region *m; + CORE_ADDR lo; + CORE_ADDR hi; + + /* First we initialize LO and HI so that they describe the entire + memory space. As we process the memory region chain, they are + redefined to describe the minimal region containing ADDR. LO + and HI are used in the case where no memory region is defined + that contains ADDR. If a memory region is disabled, it is + treated as if it does not exist. */ + + lo = (CORE_ADDR) 0; + hi = (CORE_ADDR) ~ 0; + + for (m = mem_region_chain; m; m = m->next) + { + if (m->status == enabled) + { + if (addr >= m->lo && addr < m->hi) + return m; + + if (addr >= m->hi && lo < m->hi) + lo = m->hi; + + if (addr <= m->lo && hi > m->lo) + hi = m->lo; + } + } + + /* Because no region was found, we must cons up one based on what + was learned above. */ + region.lo = lo; + region.hi = hi; + region.attrib = default_mem_attrib; + return ®ion; +} + + +static void +mem_command (char *args, int from_tty) +{ + CORE_ADDR lo, hi; + char *tok; + struct mem_attrib attrib; + + if (!args) + error_no_arg ("No mem"); + + tok = strtok (args, " \t"); + if (!tok) + error ("no lo address"); + lo = parse_and_eval_address (tok); + + tok = strtok (NULL, " \t"); + if (!tok) + error ("no hi address"); + hi = parse_and_eval_address (tok); + + attrib = default_mem_attrib; + while ((tok = strtok (NULL, " \t")) != NULL) + { + if (strcmp (tok, "rw") == 0) + attrib.mode = MEM_RW; + else if (strcmp (tok, "ro") == 0) + attrib.mode = MEM_RO; + else if (strcmp (tok, "wo") == 0) + attrib.mode = MEM_WO; + + else if (strcmp (tok, "8") == 0) + attrib.width = MEM_WIDTH_8; + else if (strcmp (tok, "16") == 0) + { + if ((lo % 2 != 0) || (hi % 2 != 0)) + error ("region bounds not 16 bit aligned"); + attrib.width = MEM_WIDTH_16; + } + else if (strcmp (tok, "32") == 0) + { + if ((lo % 4 != 0) || (hi % 4 != 0)) + error ("region bounds not 32 bit aligned"); + attrib.width = MEM_WIDTH_32; + } + else if (strcmp (tok, "64") == 0) + { + if ((lo % 8 != 0) || (hi % 8 != 0)) + error ("region bounds not 64 bit aligned"); + attrib.width = MEM_WIDTH_64; + } + +#if 0 + else if (strcmp (tok, "hwbreak") == 0) + attrib.hwbreak = true; + else if (strcmp (tok, "swbreak") == 0) + attrib.hwbreak = false; +#endif + + else if (strcmp (tok, "cache") == 0) + attrib.cache = true; + else if (strcmp (tok, "nocache") == 0) + attrib.cache = false; + +#if 0 + else if (strcmp (tok, "verify") == 0) + attrib.verify = true; + else if (strcmp (tok, "noverify") == 0) + attrib.verify = false; +#endif + + else + error ("unknown attribute: %s", tok); + } + + create_mem_region (lo, hi, &attrib); +} + + +static void +mem_info_command (char *args, int from_tty) +{ + struct mem_region *m; + struct mem_attrib *attrib; + + if (!mem_region_chain) + { + printf_unfiltered ("There are no memory regions defined.\n"); + return; + } + + printf_filtered ("Memory regions now in effect:\n"); + for (m = mem_region_chain; m; m = m->next) + { + printf_filtered ("%d: %c\t", + m->number, + m->status ? 'y' : 'n'); + printf_filtered ("%s - ", + local_hex_string_custom ((unsigned long) m->lo, "08l")); + printf_filtered ("%s\t", + local_hex_string_custom ((unsigned long) m->hi, "08l")); + + /* Print a token for each attribute. + + * FIXME: Should we output a comma after each token? It may + * make it easier for users to read, but we'd lose the ability + * to cut-and-paste the list of attributes when defining a new + * region. Perhaps that is not important. + * + * FIXME: If more attributes are added to GDB, the output may + * become cluttered and difficult for users to read. At that + * time, we may want to consider printing tokens only if they + * are different from the default attribute. */ + + attrib = &m->attrib; + switch (attrib->mode) + { + case MEM_RW: + printf_filtered ("rw "); + break; + case MEM_RO: + printf_filtered ("ro "); + break; + case MEM_WO: + printf_filtered ("wo "); + break; + } + + switch (attrib->width) + { + case MEM_WIDTH_8: + printf_filtered ("8 "); + break; + case MEM_WIDTH_16: + printf_filtered ("16 "); + break; + case MEM_WIDTH_32: + printf_filtered ("32 "); + break; + case MEM_WIDTH_64: + printf_filtered ("64 "); + break; + case MEM_WIDTH_UNSPECIFIED: + break; + } + +#if 0 + if (attrib->hwbreak) + printf_filtered ("hwbreak"); + else + printf_filtered ("swbreak"); +#endif + + if (attrib->cache) + printf_filtered ("cache "); + else + printf_filtered ("nocache "); + +#if 0 + if (attrib->verify) + printf_filtered ("verify "); + else + printf_filtered ("noverify "); +#endif + + printf_filtered ("\n"); + + gdb_flush (gdb_stdout); + } +} + + +/* Enable the memory region number NUM. */ + +static void +mem_enable (int num) +{ + struct mem_region *m; + + for (m = mem_region_chain; m; m = m->next) + if (m->number == num) + { + m->status = enabled; + return; + } + printf_unfiltered ("No memory region number %d.\n", num); +} + +static void +mem_enable_command (char *args, int from_tty) +{ + char *p = args; + char *p1; + int num; + struct mem_region *m; + + dcache_invalidate (target_dcache); + + if (p == 0) + { + for (m = mem_region_chain; m; m = m->next) + m->status = enabled; + } + else + while (*p) + { + p1 = p; + while (*p1 >= '0' && *p1 <= '9') + p1++; + if (*p1 && *p1 != ' ' && *p1 != '\t') + error ("Arguments must be memory region numbers."); + + num = atoi (p); + mem_enable (num); + + p = p1; + while (*p == ' ' || *p == '\t') + p++; + } +} + + +/* Disable the memory region number NUM. */ + +static void +mem_disable (int num) +{ + struct mem_region *m; + + for (m = mem_region_chain; m; m = m->next) + if (m->number == num) + { + m->status = disabled; + return; + } + printf_unfiltered ("No memory region number %d.\n", num); +} + +static void +mem_disable_command (char *args, int from_tty) +{ + char *p = args; + char *p1; + int num; + struct mem_region *m; + + dcache_invalidate (target_dcache); + + if (p == 0) + { + for (m = mem_region_chain; m; m = m->next) + m->status = disabled; + } + else + while (*p) + { + p1 = p; + while (*p1 >= '0' && *p1 <= '9') + p1++; + if (*p1 && *p1 != ' ' && *p1 != '\t') + error ("Arguments must be memory region numbers."); + + num = atoi (p); + mem_disable (num); + + p = p1; + while (*p == ' ' || *p == '\t') + p++; + } +} + +/* Clear memory region list */ + +static void +mem_clear (void) +{ + struct mem_region *m; + + while ((m = mem_region_chain) != 0) + { + mem_region_chain = m->next; + delete_mem_region (m); + } +} + +/* Delete the memory region number NUM. */ + +static void +mem_delete (int num) +{ + struct mem_region *m1, *m; + + if (!mem_region_chain) + { + printf_unfiltered ("No memory region number %d.\n", num); + return; + } + + if (mem_region_chain->number == num) + { + m1 = mem_region_chain; + mem_region_chain = m1->next; + delete_mem_region (m1); + } + else + for (m = mem_region_chain; m->next; m = m->next) + { + if (m->next->number == num) + { + m1 = m->next; + m->next = m1->next; + delete_mem_region (m1); + break; + } + } +} + +static void +mem_delete_command (char *args, int from_tty) +{ + char *p = args; + char *p1; + int num; + + dcache_invalidate (target_dcache); + + if (p == 0) + { + if (query ("Delete all memory regions? ")) + mem_clear (); + dont_repeat (); + return; + } + + while (*p) + { + p1 = p; + while (*p1 >= '0' && *p1 <= '9') + p1++; + if (*p1 && *p1 != ' ' && *p1 != '\t') + error ("Arguments must be memory region numbers."); + + num = atoi (p); + mem_delete (num); + + p = p1; + while (*p == ' ' || *p == '\t') + p++; + } + + dont_repeat (); +} + +void +_initialize_mem () +{ + add_com ("mem", class_vars, mem_command, + "Define attributes for memory region."); + + add_cmd ("mem", class_vars, mem_enable_command, + "Enable memory region.\n\ +Arguments are the code numbers of the memory regions to enable.\n\ +Do \"info mem\" to see current list of code numbers.", &enablelist); + + add_cmd ("mem", class_vars, mem_disable_command, + "Disable memory region.\n\ +Arguments are the code numbers of the memory regions to disable.\n\ +Do \"info mem\" to see current list of code numbers.", &disablelist); + + add_cmd ("mem", class_vars, mem_delete_command, + "Delete memory region.\n\ +Arguments are the code numbers of the memory regions to delete.\n\ +Do \"info mem\" to see current list of code numbers.", &deletelist); + + add_info ("mem", mem_info_command, + "Memory region attributes"); +} diff --git a/gdb/memattr.h b/gdb/memattr.h new file mode 100644 index 00000000000..1af276b5169 --- /dev/null +++ b/gdb/memattr.h @@ -0,0 +1,72 @@ +/* memattr.h */ +#ifndef MEMATTR_H +#define MEMATTR_H + +enum mem_access_mode +{ + MEM_RW, /* read/write */ + MEM_RO, /* read only */ + MEM_WO, /* write only */ +}; + +enum mem_access_width +{ + MEM_WIDTH_UNSPECIFIED, + MEM_WIDTH_8, /* 8 bit accesses */ + MEM_WIDTH_16, /* 16 " " */ + MEM_WIDTH_32, /* 32 " " */ + MEM_WIDTH_64 /* 64 " " */ +}; + +/* The set of all attributes that can be set for a memory region. + + This structure was created so that memory attributes can be passed + to target_ functions without exposing the details of memory region + list, which would be necessary if these fields were simply added to + the mem_region structure. + + FIXME: It would be useful if there was a mechanism for targets to + add their own attributes. For example, the number of wait states. */ + +struct mem_attrib +{ + /* read/write, read-only, or write-only */ + enum mem_access_mode mode; + + enum mem_access_width width; + + /* enables hardware breakpoints */ + int hwbreak; + + /* enables host-side caching of memory region data */ + int cache; + + /* enables memory verification. after a write, memory is re-read + to verify that the write was successful. */ + int verify; +}; + +struct mem_region +{ + /* FIXME: memory regions are stored in an unsorted singly-linked + list. This probably won't scale to handle hundreds of memory + regions --- that many could be needed to describe the allowed + access modes for memory mapped i/o device registers. */ + struct mem_region *next; + + CORE_ADDR lo; + CORE_ADDR hi; + + /* Item number of this memory region. */ + int number; + + /* Status of this memory region (enabled or disabled) */ + int status; + + /* Attributes for this region */ + struct mem_attrib attrib; +}; + +extern struct mem_region *lookup_mem_region(CORE_ADDR); + +#endif /* MEMATTR_H */ diff --git a/gdb/monitor.c b/gdb/monitor.c index ea7189b7d99..90e82f3e61b 100644 --- a/gdb/monitor.c +++ b/gdb/monitor.c @@ -1,5 +1,5 @@ /* Remote debugging interface for boot monitors, for GDB. - Copyright 1990-1993, 1995-1997, 1999-2000 Free Software Foundation, Inc. + Copyright 1990-1993, 1995-1997, 1999-2000, 2001 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by Rob Savoye for Cygnus. Resurrected from the ashes by Stu Grossman. @@ -77,7 +77,9 @@ static void monitor_fetch_registers (int regno); static void monitor_store_registers (int regno); static void monitor_prepare_to_store (void); static int monitor_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, - int write, struct target_ops *target); + int write, + struct mem_attrib *attrib, + struct target_ops *target); static void monitor_files_info (struct target_ops *ops); static int monitor_insert_breakpoint (CORE_ADDR addr, char *shadow); static int monitor_remove_breakpoint (CORE_ADDR addr, char *shadow); @@ -1988,7 +1990,8 @@ monitor_read_memory (CORE_ADDR memaddr, char *myaddr, int len) static int monitor_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, - struct target_ops *target) + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { int res; diff --git a/gdb/remote-adapt.c b/gdb/remote-adapt.c index f370d3850ea..44342cbfee4 100644 --- a/gdb/remote-adapt.c +++ b/gdb/remote-adapt.c @@ -1,5 +1,5 @@ /* Remote debugging interface for AMD 290*0 Adapt Monitor Version 2.1d18. - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 2001 Free Software Foundation, Inc. Contributed by David Wood at New York University (wood@lab.ultra.nyu.edu). Adapted from work done at Cygnus Support in remote-eb.c. @@ -1167,7 +1167,9 @@ translate_addr (CORE_ADDR addr) /* FIXME! Merge these two. */ int -adapt_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, int write) +adapt_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { memaddr = translate_addr (memaddr); diff --git a/gdb/remote-array.c b/gdb/remote-array.c index cd3cff3e11e..7f0a6d6d913 100644 --- a/gdb/remote-array.c +++ b/gdb/remote-array.c @@ -1,5 +1,5 @@ /* Remote debugging interface for Array Tech RAID controller.. - Copyright 90, 91, 92, 93, 94, 1995, 1998 Free Software Foundation, Inc. + Copyright 90, 91, 92, 93, 94, 1995, 1998, 2001 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by Rob Savoye for Cygnus. This module talks to a debug monitor called 'MONITOR', which @@ -1026,7 +1026,8 @@ array_read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len) static int array_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, - struct target_ops *target) + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { if (write) return array_write_inferior_memory (memaddr, myaddr, len); diff --git a/gdb/remote-bug.c b/gdb/remote-bug.c index 73d37b7255b..df05975bd06 100644 --- a/gdb/remote-bug.c +++ b/gdb/remote-bug.c @@ -1,7 +1,7 @@ /* Remote debugging interface for Motorola's MVME187BUG monitor, an embedded monitor for the m88k. - Copyright 1992, 1993 Free Software Foundation, Inc. + Copyright 1992, 1993, 2001 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by K. Richard Pixley. This file is part of GDB. @@ -555,7 +555,8 @@ bug_store_register (int regno) int bug_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, - struct target_ops *target) + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { int res; diff --git a/gdb/remote-e7000.c b/gdb/remote-e7000.c index fbe36025e54..b81df8a6c59 100644 --- a/gdb/remote-e7000.c +++ b/gdb/remote-e7000.c @@ -1,5 +1,5 @@ /* Remote debugging interface for Hitachi E7000 ICE, for GDB - Copyright 1993, 1994, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + Copyright 1993, 1994, 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by Steve Chamberlain for Cygnus Support. @@ -1474,7 +1474,9 @@ fast_but_for_the_pause_e7000_read_inferior_memory (CORE_ADDR memaddr, static int e7000_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, - int len, int write, struct target_ops *target) + int len, int write, + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { if (write) return e7000_write_inferior_memory (memaddr, myaddr, len); diff --git a/gdb/remote-eb.c b/gdb/remote-eb.c index 9ccac6f3d8b..4db90712086 100644 --- a/gdb/remote-eb.c +++ b/gdb/remote-eb.c @@ -1,5 +1,5 @@ /* Remote debugging interface for AMD 29000 EBMON on IBM PC, for GDB. - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 2001 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by Jim Kingdon for Cygnus. This file is part of GDB. @@ -879,7 +879,8 @@ eb_prepare_to_store (void) int eb_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, - struct target_ops *target) + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { if (write) return eb_write_inferior_memory (memaddr, myaddr, len); diff --git a/gdb/remote-es.c b/gdb/remote-es.c index 92541a789f7..2d879c1ccc8 100644 --- a/gdb/remote-es.c +++ b/gdb/remote-es.c @@ -1,5 +1,5 @@ /* Memory-access and commands for remote es1800 processes, for GDB. - Copyright (C) 1988, 1992 Free Software Foundation, Inc. + Copyright (C) 1988, 1992, 2001 Free Software Foundation, Inc. This file is added to GDB to make it possible to do debugging via an ES-1800 emulator. The code was originally written by Johan Holmberg @@ -134,7 +134,7 @@ static void es1800_files_info (struct target_ops *); static int es1800_xfer_inferior_memory (CORE_ADDR, char *, int, int, - struct target_ops *); + struct mem_attrib *, struct target_ops *); static void es1800_prepare_to_store (void); @@ -959,7 +959,9 @@ tohex (int nib) static int es1800_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, - int write, struct target_ops *tops) + int write, + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { int origlen = len; int xfersize; diff --git a/gdb/remote-mips.c b/gdb/remote-mips.c index 1905c613b8d..2dff690870c 100644 --- a/gdb/remote-mips.c +++ b/gdb/remote-mips.c @@ -1,5 +1,5 @@ /* Remote debugging interface for MIPS remote debugging protocol. - Copyright 1993, 1994, 1995, 2000 Free Software Foundation, Inc. + Copyright 1993, 1994, 1995, 2000, 2001 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by Ian Lance Taylor . @@ -112,7 +112,9 @@ static int mips_store_word (CORE_ADDR addr, unsigned int value, char *old_contents); static int mips_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, - int write, struct target_ops *ignore); + int write, + struct mem_attrib *attrib, + struct target_ops *target); static void mips_files_info (struct target_ops *ignore); @@ -2069,7 +2071,8 @@ static int mask_address_p = 1; static int mips_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, - struct target_ops *ignore) + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { int i; CORE_ADDR addr; diff --git a/gdb/remote-mm.c b/gdb/remote-mm.c index f6b5408733b..ae4df944b43 100644 --- a/gdb/remote-mm.c +++ b/gdb/remote-mm.c @@ -1,5 +1,5 @@ /* Remote debugging interface for Am290*0 running MiniMON monitor, for GDB. - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 2001 Free Software Foundation, Inc. Originally written by Daniel Mann at AMD. This file is part of GDB. @@ -1173,7 +1173,9 @@ mm_read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len) /* FIXME! Merge these two. */ static int -mm_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, int write) +mm_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { memaddr = translate_addr (memaddr); diff --git a/gdb/remote-nindy.c b/gdb/remote-nindy.c index 691aa726b83..be6a6e96ea3 100644 --- a/gdb/remote-nindy.c +++ b/gdb/remote-nindy.c @@ -1,5 +1,5 @@ /* Memory-access and commands for remote NINDY process, for GDB. - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 2001 Free Software Foundation, Inc. Contributed by Intel Corporation. Modified from remote.c by Chris Benenati. GDB is distributed in the hope that it will be useful, but WITHOUT ANY @@ -476,7 +476,9 @@ nindy_store_registers (int regno) int nindy_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, - int should_write, struct target_ops *target) + int should_write, + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { int res; diff --git a/gdb/remote-os9k.c b/gdb/remote-os9k.c index 08e1d85f524..57baf84dae9 100644 --- a/gdb/remote-os9k.c +++ b/gdb/remote-os9k.c @@ -1,5 +1,5 @@ /* Remote debugging interface for boot monitors, for GDB. - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 2001 Free Software Foundation, Inc. This file is part of GDB. @@ -826,7 +826,9 @@ rombug_read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len) static int rombug_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, - int write, struct target_ops *target) + int write, + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { if (write) return rombug_write_inferior_memory (memaddr, myaddr, len); diff --git a/gdb/remote-rdi.c b/gdb/remote-rdi.c index 0115e4d4ebe..386a0df96a5 100644 --- a/gdb/remote-rdi.c +++ b/gdb/remote-rdi.c @@ -1,5 +1,5 @@ /* GDB interface to ARM RDI library. - Copyright 1997, 1998 Free Software Foundation, Inc. + Copyright 1997, 1998, 2001 Free Software Foundation, Inc. This file is part of GDB. @@ -52,6 +52,7 @@ static void arm_rdi_files_info (struct target_ops *ignore); static int arm_rdi_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int should_write, + struct mem_attrib *attrib, struct target_ops *target); static void arm_rdi_prepare_to_store (void); @@ -626,8 +627,9 @@ arm_rdi_store_registers (int regno) /* ARGSUSED */ static int -arm_rdi_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, - int should_write, struct target_ops *target) +arm_rdi_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int should_write, + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { int rslt, i; diff --git a/gdb/remote-rdp.c b/gdb/remote-rdp.c index 223e2ef5f2f..ccce506537e 100644 --- a/gdb/remote-rdp.c +++ b/gdb/remote-rdp.c @@ -1,5 +1,5 @@ /* Remote debugging for the ARM RDP interface. - Copyright 1994, 1995 Free Software Foundation, Inc. + Copyright 1994, 1995, 2001 Free Software Foundation, Inc. This file is part of GDB. @@ -167,10 +167,10 @@ static int timeout = 2; static char *commandline = NULL; static int -remote_rdp_xfer_inferior_memory (CORE_ADDR memaddr, - char *myaddr, - int len, - int write, struct target_ops *target); +remote_rdp_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, + int write, + struct mem_attrib *attrib, + struct target_ops *target); /* Stuff for talking to the serial layer. */ @@ -873,7 +873,7 @@ exec_swi (int swi, argsin *args) char *copy = alloca (args[2].n); int done = callback->read (callback, args[0].n, copy, args[2].n); if (done > 0) - remote_rdp_xfer_inferior_memory (args[1].n, copy, done, 1, 0); + remote_rdp_xfer_inferior_memory (args[1].n, copy, done, 1, 0, 0); args->n = args[2].n - done; return 1; } @@ -905,10 +905,10 @@ exec_swi (int swi, argsin *args) commandline[255] = '\0'; } remote_rdp_xfer_inferior_memory (args[0].n, - commandline, len + 1, 1, 0); + commandline, len + 1, 1, 0, 0); } else - remote_rdp_xfer_inferior_memory (args[0].n, "", 1, 1, 0); + remote_rdp_xfer_inferior_memory (args[0].n, "", 1, 1, 0, 0); return 1; default: @@ -955,6 +955,7 @@ handle_swi (void) buf, len, 0, + 0, 0); } else @@ -1249,7 +1250,9 @@ remote_rdp_prepare_to_store (void) static int remote_rdp_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, - int write, struct target_ops *target) + int write, + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { /* I infer from D Taylor's code that there's a limit on the amount we can transfer in one chunk.. */ diff --git a/gdb/remote-sds.c b/gdb/remote-sds.c index 96fa4a881ea..56e61b65819 100644 --- a/gdb/remote-sds.c +++ b/gdb/remote-sds.c @@ -1,5 +1,5 @@ /* Remote target communications for serial-line targets using SDS' protocol. - Copyright 1997 Free Software Foundation, Inc. + Copyright 1997, 2001 Free Software Foundation, Inc. This file is part of GDB. @@ -55,7 +55,8 @@ static int sds_read_bytes (CORE_ADDR, char *, int); static void sds_files_info (struct target_ops *ignore); -static int sds_xfer_memory (CORE_ADDR, char *, int, int, struct target_ops *); +static int sds_xfer_memory (CORE_ADDR, char *, int, int, + struct mem_attrib *, struct target_ops *); static void sds_prepare_to_store (void); @@ -657,7 +658,8 @@ sds_read_bytes (CORE_ADDR memaddr, char *myaddr, int len) /* ARGSUSED */ static int sds_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int should_write, - struct target_ops *target) + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { int res; diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c index 8b03b889cef..8c2e75309e6 100644 --- a/gdb/remote-sim.c +++ b/gdb/remote-sim.c @@ -1,5 +1,5 @@ /* Generic remote debugging interface for simulators. - Copyright 1993, 1994, 1996, 1997, 2000 Free Software Foundation, Inc. + Copyright 1993, 1994, 1996, 1997, 2000, 2001 Free Software Foundation, Inc. Contributed by Cygnus Support. Steve Chamberlain (sac@cygnus.com). @@ -91,9 +91,10 @@ static int gdbsim_wait (int pid, struct target_waitstatus *status); static void gdbsim_prepare_to_store (void); -static int gdbsim_xfer_inferior_memory (CORE_ADDR memaddr, - char *myaddr, int len, - int write, struct target_ops *target); +static int gdbsim_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, + int len, int write, + struct mem_attrib *attrib, + struct target_ops *target); static void gdbsim_files_info (struct target_ops *target); @@ -714,7 +715,9 @@ gdbsim_prepare_to_store (void) static int gdbsim_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, - int write, struct target_ops *target) + int write, + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { if (!program_loaded) error ("No program loaded."); diff --git a/gdb/remote-st.c b/gdb/remote-st.c index 85077bb175d..51e96b70d55 100644 --- a/gdb/remote-st.c +++ b/gdb/remote-st.c @@ -1,5 +1,5 @@ /* Remote debugging interface for Tandem ST2000 phone switch, for GDB. - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 2001 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by Jim Kingdon for Cygnus. This file is part of GDB. @@ -556,7 +556,9 @@ st2000_read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len) static int st2000_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, - int write, struct target_ops *target) + int write, + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { if (write) return st2000_write_inferior_memory (memaddr, myaddr, len); diff --git a/gdb/remote-udi.c b/gdb/remote-udi.c index a09c70e384d..3987d87a5ba 100644 --- a/gdb/remote-udi.c +++ b/gdb/remote-udi.c @@ -1,5 +1,5 @@ /* Remote debugging interface for AMD 29k interfaced via UDI, for GDB. - Copyright 1990, 1992, 1995, 2000 Free Software Foundation, Inc. + Copyright 1990, 1992, 1995, 2000, 2001 Free Software Foundation, Inc. Written by Daniel Mann. Contributed by AMD. This file is part of GDB. @@ -923,7 +923,8 @@ translate_addr (CORE_ADDR addr) /* FIXME! Merge these two. */ static int udi_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, - struct target_ops * target) + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { memaddr = translate_addr (memaddr); diff --git a/gdb/remote-vx.c b/gdb/remote-vx.c index 011e1eaa737..4503e773244 100644 --- a/gdb/remote-vx.c +++ b/gdb/remote-vx.c @@ -1,5 +1,5 @@ /* Memory-access and commands for remote VxWorks processes, for GDB. - Copyright (C) 1990-95, 1997-98, 1999 Free Software Foundation, Inc. + Copyright (C) 1990-95, 1997-98, 1999, 2001 Free Software Foundation, Inc. Contributed by Wind River Systems and Cygnus Support. This file is part of GDB. @@ -476,7 +476,8 @@ vx_prepare_to_store (void) static int vx_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, - struct target_ops *target) + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target ATTRIBUTE_UNUSED) { int status; Rptrace ptrace_in; diff --git a/gdb/remote.c b/gdb/remote.c index c990b1e37f5..0140b12b9a9 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -1,5 +1,5 @@ /* Remote target communications for serial-line targets in custom GDB protocol - Copyright 1988, 1991-2000 Free Software Foundation, Inc. + Copyright 1988, 1991-2000, 2001 Free Software Foundation, Inc. This file is part of GDB. @@ -70,6 +70,7 @@ static void remote_files_info (struct target_ops *ignore); static int remote_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int should_write, + struct mem_attrib *attrib, struct target_ops *target); static void remote_prepare_to_store (void); @@ -3543,7 +3544,9 @@ remote_read_bytes (CORE_ADDR memaddr, char *myaddr, int len) /* ARGSUSED */ static int remote_xfer_memory (CORE_ADDR mem_addr, char *buffer, int mem_len, - int should_write, struct target_ops *target) + int should_write, + struct mem_attrib *attrib ATTRIBUTE_UNUSED, + struct target_ops *target) { CORE_ADDR targ_addr; int targ_len; diff --git a/gdb/target.c b/gdb/target.c index ec4d01eff0b..8c76f076868 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1,5 +1,5 @@ /* Select target systems and architectures at runtime for GDB. - Copyright 1990, 1992-1995, 1998-2000 Free Software Foundation, Inc. + Copyright 1990, 1992-1995, 1998-2000, 2001 Free Software Foundation, Inc. Contributed by Cygnus Support. This file is part of GDB. @@ -102,7 +102,8 @@ static void debug_to_store_registers (int); static void debug_to_prepare_to_store (void); static int -debug_to_xfer_memory (CORE_ADDR, char *, int, int, struct target_ops *); +debug_to_xfer_memory (CORE_ADDR, char *, int, int, struct mem_attrib *, + struct target_ops *); static void debug_to_files_info (struct target_ops *); @@ -379,7 +380,7 @@ cleanup_target (struct target_ops *t) (void (*) (void)) noprocess); de_fault (to_xfer_memory, - (int (*) (CORE_ADDR, char *, int, int, struct target_ops *)) + (int (*) (CORE_ADDR, char *, int, int, struct mem_attrib *, struct target_ops *)) nomemory); de_fault (to_files_info, (void (*) (struct target_ops *)) @@ -843,7 +844,8 @@ target_write_memory (CORE_ADDR memaddr, char *myaddr, int len) Result is -1 on error, or the number of bytes transfered. */ int -do_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write) +do_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, + struct mem_attrib *attrib) { int res; int done = 0; @@ -860,7 +862,7 @@ do_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write) /* The quick case is that the top target can handle the transfer. */ res = current_target.to_xfer_memory - (memaddr, myaddr, len, write, ¤t_target); + (memaddr, myaddr, len, write, attrib, ¤t_target); /* If res <= 0 then we call it again in the loop. Ah well. */ if (res <= 0) @@ -871,7 +873,7 @@ do_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write) if (!t->to_has_memory) continue; - res = t->to_xfer_memory (memaddr, myaddr, len, write, t); + res = t->to_xfer_memory (memaddr, myaddr, len, write, attrib, t); if (res > 0) break; /* Handled all or part of xfer */ if (t->to_has_all_memory) @@ -895,6 +897,8 @@ static int target_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write) { int res; + int reg_len; + struct mem_region *region; /* Zero length requests are ok and require no work. */ if (len == 0) @@ -904,22 +908,52 @@ target_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write) while (len > 0) { - res = dcache_xfer_memory(target_dcache, memaddr, myaddr, len, write); - if (res <= 0) + region = lookup_mem_region(memaddr); + if (memaddr + len < region->hi) + reg_len = len; + else + reg_len = region->hi - memaddr; + + switch (region->attrib.mode) { - /* If this address is for nonexistent memory, - read zeros if reading, or do nothing if writing. Return error. */ + case MEM_RO: + if (write) + return EIO; + break; + + case MEM_WO: if (!write) - memset (myaddr, 0, len); - if (errno == 0) return EIO; - else - return errno; + break; } - memaddr += res; - myaddr += res; - len -= res; + while (reg_len > 0) + { + if (region->attrib.cache) + res = dcache_xfer_memory(target_dcache, memaddr, myaddr, + reg_len, write); + else + res = do_xfer_memory(memaddr, myaddr, reg_len, write, + ®ion->attrib); + + if (res <= 0) + { + /* If this address is for nonexistent memory, read zeros + if reading, or do nothing if writing. Return + error. */ + if (!write) + memset (myaddr, 0, len); + if (errno == 0) + return EIO; + else + return errno; + } + + memaddr += res; + myaddr += res; + len -= res; + reg_len -= res; + } } return 0; /* We managed to cover it all somehow. */ @@ -935,6 +969,8 @@ target_xfer_memory_partial (CORE_ADDR memaddr, char *myaddr, int len, int write_p, int *err) { int res; + int reg_len; + struct mem_region *region; /* Zero length requests are ok and require no work. */ if (len == 0) @@ -943,7 +979,38 @@ target_xfer_memory_partial (CORE_ADDR memaddr, char *myaddr, int len, return 0; } - res = dcache_xfer_memory (target_dcache, memaddr, myaddr, len, write_p); + region = lookup_mem_region(memaddr); + if (memaddr + len < region->hi) + reg_len = len; + else + reg_len = region->hi - memaddr; + + switch (region->attrib.mode) + { + case MEM_RO: + if (write_p) + { + *err = EIO; + return 0; + } + break; + + case MEM_WO: + if (write_p) + { + *err = EIO; + return 0; + } + break; + } + + if (region->attrib.cache) + res = dcache_xfer_memory (target_dcache, memaddr, myaddr, + reg_len, write_p); + else + res = do_xfer_memory (memaddr, myaddr, reg_len, write_p, + ®ion->attrib); + if (res <= 0) { if (errno != 0) @@ -2313,11 +2380,13 @@ debug_to_prepare_to_store (void) static int debug_to_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, + struct mem_attrib *attrib, struct target_ops *target) { int retval; - retval = debug_target.to_xfer_memory (memaddr, myaddr, len, write, target); + retval = debug_target.to_xfer_memory (memaddr, myaddr, len, write, + attrib, target); fprintf_unfiltered (gdb_stdlog, "target_xfer_memory (0x%x, xxx, %d, %s, xxx) = %d", diff --git a/gdb/target.h b/gdb/target.h index e1e71d95d34..d007bbab478 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -1,5 +1,5 @@ /* Interface between GDB and target environments, including files and processes - Copyright 1990-1994, 1999, 2000 Free Software Foundation, Inc. + Copyright 1990-1994, 1999, 2000, 2001 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by John Gilmore. This file is part of GDB. @@ -44,6 +44,7 @@ #include "bfd.h" #include "symtab.h" #include "dcache.h" +#include "memattr.h" enum strata { @@ -363,7 +364,9 @@ struct target_ops something at MEMADDR + N. */ int (*to_xfer_memory) (CORE_ADDR memaddr, char *myaddr, - int len, int write, struct target_ops * target); + int len, int write, + struct mem_attrib *attrib, + struct target_ops *target); #if 0 /* Enable this after 4.12. */ @@ -619,7 +622,8 @@ extern void target_detach (char *, int); extern DCACHE *target_dcache; -extern int do_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write); +extern int do_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, + struct mem_attrib *attrib); extern int target_read_string (CORE_ADDR, char **, int, int *); @@ -627,10 +631,11 @@ extern int target_read_memory (CORE_ADDR memaddr, char *myaddr, int len); extern int target_write_memory (CORE_ADDR memaddr, char *myaddr, int len); -extern int xfer_memory (CORE_ADDR, char *, int, int, struct target_ops *); +extern int xfer_memory (CORE_ADDR, char *, int, int, + struct mem_attrib *, struct target_ops *); -extern int -child_xfer_memory (CORE_ADDR, char *, int, int, struct target_ops *); +extern int child_xfer_memory (CORE_ADDR, char *, int, int, + struct mem_attrib *, struct target_ops *); /* Make a single attempt at transfering LEN bytes. On a successful transfer, the number of bytes actually transfered is returned and diff --git a/gdb/wince.c b/gdb/wince.c index 7ee0b60f6c0..bcbe212dab7 100644 --- a/gdb/wince.c +++ b/gdb/wince.c @@ -1,5 +1,5 @@ /* Target-vector operations for controlling Windows CE child processes, for GDB. - Copyright 1999, 2000 Free Software Foundation, Inc. + Copyright 1999, 2000, 2001 Free Software Foundation, Inc. Contributed by Cygnus Solutions, A Red Hat Company. This file is part of GDB. @@ -1975,7 +1975,6 @@ _initialize_inftarg (void) add_show_from_set (set, &showlist); set->function.cfunc = set_upload_type; set_upload_type (NULL, 0); - set_dcache_state (1); add_show_from_set (add_set_cmd ((char *) "debugexec", class_support, var_boolean, -- 2.30.2