This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: [RFC]: memory region attributes


>>>>> "jtc" == J T Conklin <jtc@redback.com> writes:
jtc> I noticed after I submitted the patch that memattr.c did not entirely
jtc> conform to the coding standards.  I've run it through gindent, so you
jtc> can assume that much has been fixed.

And I just noticed that the diffs for memattr.[ch] weren't even in the
patch, since they were newly added files.  Bleh.  Not my day.

I'm enclosing an entirely new patch --- please ignore the previous one.

        --jtc

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.47
diff -c -r1.47 Makefile.in
*** Makefile.in	2000/11/10 23:02:56	1.47
--- Makefile.in	2000/11/22 02:02:24
***************
*** 488,494 ****
  	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 \
  	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 \
--- 488,494 ----
  	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 \
! 	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 \
***************
*** 625,631 ****
  	expprint.o environ.o stack.o thread.o \
  	event-loop.o event-top.o inf-loop.o \
  	gdbarch.o arch-utils.o gdbtypes.o copying.o $(DEPFILES) \
! 	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 \
--- 625,631 ----
  	expprint.o environ.o stack.o thread.o \
  	event-loop.o event-top.o inf-loop.o \
  	gdbarch.o arch-utils.o gdbtypes.o copying.o $(DEPFILES) \
! 	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 \
***************
*** 1246,1252 ****
  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)
  
  dbxread.o: dbxread.c $(breakpoint_h) buildsym.h $(command_h) \
  	complaints.h $(defs_h) $(expression_h) gdb-stabs.h $(gdbcore_h) \
--- 1246,1253 ----
  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) target.h
  
  dbxread.o: dbxread.c $(breakpoint_h) buildsym.h $(command_h) \
  	complaints.h $(defs_h) $(expression_h) gdb-stabs.h $(gdbcore_h) \
Index: dcache.c
===================================================================
RCS file: /cvs/src/src/gdb/dcache.c,v
retrieving revision 1.10
diff -c -r1.10 dcache.c
*** dcache.c	2000/11/03 22:00:56	1.10
--- dcache.c	2000/11/22 02:02:24
***************
*** 25,39 ****
  #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.
- 
     In general the dcache speeds up performance, some speed improvement
     comes from the actual caching mechanism, but the major gain is in
     the reduction of the remote protocol overhead; instead of reading
--- 25,35 ----
  #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 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
     the reduction of the remote protocol overhead; instead of reading
***************
*** 61,70 ****
  
     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.
  
  
     The ENTRY_DIRTY state is necessary because GDB likes to write large
     lumps of memory in small bits.  If the caching mechanism didn't
     maintain the DIRTY information, then something like a two byte
--- 57,68 ----
  
     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.
  
+ 
     The ENTRY_DIRTY state is necessary because GDB likes to write large
     lumps of memory in small bits.  If the caching mechanism didn't
     maintain the DIRTY information, then something like a two byte
***************
*** 76,85 ****
     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.
- 
- 
   */
  
  
  /* This value regulates the number of cache blocks stored.
     Smaller values reduce the time spent searching for a cache
--- 74,95 ----
     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,128 ****
--- 133,151 ----
    };
  
  
+ /* 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,145 ****
  
      /* 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);
--- 158,163 ----
***************
*** 189,196 ****
        db->p = 0;
      }
  
-   dcache->cache_has_stuff = 0;
- 
    return;
  }
  
--- 207,212 ----
***************
*** 224,262 ****
  static int
  dcache_write_line (DCACHE *dcache, register struct dcache_block *db)
  {
!   int s;
!   int e;
  
!   if (db->anydirty)
      {
!       for (s = 0; s < LINE_SIZE; s++)
  	{
! 	  if (db->state[s] == ENTRY_DIRTY)
  	    {
! 	      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;
! 	      }
  	    }
  	}
-       db->anydirty = 0;
      }
    return 1;
  }
  
--- 240,314 ----
  static int
  dcache_write_line (DCACHE *dcache, register struct dcache_block *db)
  {
!   CORE_ADDR memaddr;
!   char *myaddr;
!   int len;
!   int res;
!   int reg_len;
!   struct mem_region *region;
  
!   if (!db->anydirty)
!     return 1;
! 
!   len = LINE_SIZE;
!   memaddr = db->addr;
!   myaddr  = db->data;
! 
!   while (len > 0)
      {
!       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)
! 	{
! 	  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)
  	    {
! 	      res = do_xfer_memory(memaddr, myaddr, dirty_len, 1,
! 				   &region->attrib);
! 	      if (res <= 0)
! 		return 0;
! 
! 	      memset (db->state[XFORM(memaddr)], ENTRY_OK, res);
! 	      memaddr   += res;
! 	      myaddr    += res;
! 	      dirty_len -= res;
  	    }
  	}
      }
+ 
+   db->anydirty = 0;
    return 1;
  }
  
***************
*** 268,273 ****
--- 320,327 ----
    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,295 ****
  
    while (len > 0)
      {
!       res = do_xfer_memory (memaddr, myaddr, len, 0);
!       if (res <= 0)
! 	return 0;
  
!       memaddr += res;
!       myaddr  += res;
!       len     -= res;
      }
  
    memset (db->state, ENTRY_OK, sizeof (db->data));
--- 337,368 ----
  
    while (len > 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,
! 				&region->attrib);
! 	  if (res <= 0)
! 	    return 0;
  
! 	  memaddr += res;
! 	  myaddr  += res;
! 	  len     -= res;
! 	  reg_len -= res;
! 	}
      }
  
    memset (db->state, ENTRY_OK, sizeof (db->data));
***************
*** 306,314 ****
  {
    register struct dcache_block *db;
  
-   if (dcache_enabled_p == 0)
-     abort ();
- 
    /* Take something from the free list */
    db = dcache->free_head;
    if (db)
--- 379,384 ----
***************
*** 342,348 ****
    return db;
  }
  
! /* Writeback any dirty lines to the remote. */
  static int
  dcache_writeback (DCACHE *dcache)
  {
--- 412,418 ----
    return db;
  }
  
! /* Writeback any dirty lines. */
  static int
  dcache_writeback (DCACHE *dcache)
  {
***************
*** 452,481 ****
  		    int should_write)
  {
    int i;
  
!   if (dcache_enabled_p)
      {
!       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;
      }
-   else
-     {
-       if (dcache->cache_has_stuff)
- 	dcache_invalidate (dcache);
  
!       len = do_xfer_memory(memaddr, myaddr, len, should_write);
!     }
    return len;
  }
  
--- 522,548 ----
  		    int should_write)
  {
    int 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;
      }
  
!   /* 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,495 ****
  {
    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",
  		   LINE_SIZE, DCACHE_SIZE);
  
    if (last_cache)
--- 551,557 ----
  {
    struct dcache_block *p;
  
!   printf_filtered ("Dcache line width %d, depth %d\n",
  		   LINE_SIZE, DCACHE_SIZE);
  
    if (last_cache)
***************
*** 511,523 ****
  	  printf_filtered ("\n");
  	}
      }
- }
- 
- /* Turn dcache on or off. */
- void
- set_dcache_state (int what)
- {
-   dcache_enabled_p = !!what;
  }
  
  void
--- 573,578 ----
Index: dcache.h
===================================================================
RCS file: /cvs/src/src/gdb/dcache.h,v
retrieving revision 1.6
diff -c -r1.6 dcache.h
*** dcache.h	2000/11/03 22:00:56	1.6
--- dcache.h	2000/11/22 02:02:24
***************
*** 39,45 ****
  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 */
--- 39,42 ----
Index: exec.c
===================================================================
RCS file: /cvs/src/src/gdb/exec.c,v
retrieving revision 1.6
diff -c -r1.6 exec.c
*** exec.c	2000/07/30 01:48:25	1.6
--- exec.c	2000/11/22 02:02:24
***************
*** 448,453 ****
--- 448,454 ----
  
  int
  xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
+ 	     struct mem_attrib *attrib,
  	     struct target_ops *target)
  {
    boolean res;
Index: infptrace.c
===================================================================
RCS file: /cvs/src/src/gdb/infptrace.c,v
retrieving revision 1.6
diff -c -r1.6 infptrace.c
*** infptrace.c	2000/09/09 01:38:49	1.6
--- infptrace.c	2000/11/22 02:02:24
***************
*** 511,516 ****
--- 511,517 ----
  
  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;
Index: memattr.c
===================================================================
RCS file: memattr.c
diff -N memattr.c
*** /dev/null	Tue May  5 13:32:27 1998
--- memattr.c	Tue Nov 21 18:02:25 2000
***************
*** 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 &region;
+ }
+ 
+ 
+ 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");
+ }
Index: memattr.h
===================================================================
RCS file: memattr.h
diff -N memattr.h
*** /dev/null	Tue May  5 13:32:27 1998
--- memattr.h	Tue Nov 21 18:02:25 2000
***************
*** 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 */
Index: monitor.c
===================================================================
RCS file: /cvs/src/src/gdb/monitor.c,v
retrieving revision 1.14
diff -c -r1.14 monitor.c
*** monitor.c	2000/11/03 22:00:56	1.14
--- monitor.c	2000/11/22 02:02:25
***************
*** 77,83 ****
  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);
  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);
--- 77,85 ----
  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 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,1994 ****
  
  static int
  monitor_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
! 		     struct target_ops *target)
  {
    int res;
  
--- 1990,1997 ----
  
  static int
  monitor_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
! 		     struct mem_attrib *attrib ATTRIBUTE_UNUSED,
! 		     struct target_ops *target ATTRIBUTE_UNUSED)
  {
    int res;
  
Index: remote-adapt.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-adapt.c,v
retrieving revision 1.5
diff -c -r1.5 remote-adapt.c
*** remote-adapt.c	2000/10/02 00:49:55	1.5
--- remote-adapt.c	2000/11/22 02:02:26
***************
*** 1167,1173 ****
  
  /* FIXME!  Merge these two.  */
  int
! adapt_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, int write)
  {
  
    memaddr = translate_addr (memaddr);
--- 1167,1175 ----
  
  /* FIXME!  Merge these two.  */
  int
! 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);
Index: remote-array.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-array.c,v
retrieving revision 1.7
diff -c -r1.7 remote-array.c
*** remote-array.c	2000/10/02 00:49:55	1.7
--- remote-array.c	2000/11/22 02:02:26
***************
*** 1026,1032 ****
  
  static int
  array_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
! 		   struct target_ops *target)
  {
    if (write)
      return array_write_inferior_memory (memaddr, myaddr, len);
--- 1026,1033 ----
  
  static int
  array_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
! 		   struct mem_attrib *attrib ATTRIBUTE_UNUSED,
! 		   struct target_ops *target ATTRIBUTE_UNUSED)
  {
    if (write)
      return array_write_inferior_memory (memaddr, myaddr, len);
Index: remote-bug.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-bug.c,v
retrieving revision 1.8
diff -c -r1.8 remote-bug.c
*** remote-bug.c	2000/11/03 22:00:56	1.8
--- remote-bug.c	2000/11/22 02:02:27
***************
*** 555,561 ****
  
  int
  bug_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
! 		 struct target_ops *target)
  {
    int res;
  
--- 555,562 ----
  
  int
  bug_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
! 		 struct mem_attrib *attrib ATTRIBUTE_UNUSED,
! 		 struct target_ops *target ATTRIBUTE_UNUSED)
  {
    int res;
  
Index: remote-e7000.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-e7000.c,v
retrieving revision 1.10
diff -c -r1.10 remote-e7000.c
*** remote-e7000.c	2000/10/30 21:50:57	1.10
--- remote-e7000.c	2000/11/22 02:02:28
***************
*** 1474,1480 ****
  
  static int
  e7000_xfer_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr,
! 			    int len, int write, struct target_ops *target)
  {
    if (write)
      return e7000_write_inferior_memory (memaddr, myaddr, len);
--- 1474,1482 ----
  
  static int
  e7000_xfer_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr,
! 			    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);
Index: remote-eb.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-eb.c,v
retrieving revision 1.5
diff -c -r1.5 remote-eb.c
*** remote-eb.c	2000/10/06 21:50:56	1.5
--- remote-eb.c	2000/11/22 02:02:28
***************
*** 879,885 ****
  
  int
  eb_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
! 			 struct target_ops *target)
  {
    if (write)
      return eb_write_inferior_memory (memaddr, myaddr, len);
--- 879,886 ----
  
  int
  eb_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
! 			 struct mem_attrib *attrib ATTRIBUTE_UNUSED,
! 			 struct target_ops *target ATTRIBUTE_UNUSED)
  {
    if (write)
      return eb_write_inferior_memory (memaddr, myaddr, len);
Index: remote-es.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-es.c,v
retrieving revision 1.6
diff -c -r1.6 remote-es.c
*** remote-es.c	2000/10/30 21:50:57	1.6
--- remote-es.c	2000/11/22 02:02:29
***************
*** 134,140 ****
  
  static int
  es1800_xfer_inferior_memory (CORE_ADDR, char *, int, int,
! 			     struct target_ops *);
  
  static void es1800_prepare_to_store (void);
  
--- 134,140 ----
  
  static int
  es1800_xfer_inferior_memory (CORE_ADDR, char *, int, int,
! 			     struct mem_attrib *, struct target_ops *);
  
  static void es1800_prepare_to_store (void);
  
***************
*** 959,965 ****
  
  static int
  es1800_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len,
! 			     int write, struct target_ops *tops)
  {
    int origlen = len;
    int xfersize;
--- 959,967 ----
  
  static int
  es1800_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len,
! 			     int write, 
! 			     struct mem_attrib *attrib ATTRIBUTE_UNUSED,
! 			     struct target_ops *target ATTRIBUTE_UNUSED)
  {
    int origlen = len;
    int xfersize;
Index: remote-mips.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-mips.c,v
retrieving revision 1.10
diff -c -r1.10 remote-mips.c
*** remote-mips.c	2000/09/12 17:20:09	1.10
--- remote-mips.c	2000/11/22 02:02:31
***************
*** 112,118 ****
  			    char *old_contents);
  
  static int mips_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
! 			     int write, struct target_ops *ignore);
  
  static void mips_files_info (struct target_ops *ignore);
  
--- 112,120 ----
  			    char *old_contents);
  
  static int mips_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
! 			     int write, 
! 			     struct mem_attrib *attrib,
! 			     struct target_ops *target);
  
  static void mips_files_info (struct target_ops *ignore);
  
***************
*** 2069,2075 ****
  
  static int
  mips_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
! 		  struct target_ops *ignore)
  {
    int i;
    CORE_ADDR addr;
--- 2071,2078 ----
  
  static int
  mips_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
! 		  struct mem_attrib *attrib ATTRIBUTE_UNUSED,
! 		  struct target_ops *target ATTRIBUTE_UNUSED)
  {
    int i;
    CORE_ADDR addr;
Index: remote-mm.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-mm.c,v
retrieving revision 1.4
diff -c -r1.4 remote-mm.c
*** remote-mm.c	2000/10/06 21:50:56	1.4
--- remote-mm.c	2000/11/22 02:02:34
***************
*** 1173,1179 ****
  
  /* FIXME!  Merge these two.  */
  static int
! mm_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, int write)
  {
  
    memaddr = translate_addr (memaddr);
--- 1173,1181 ----
  
  /* FIXME!  Merge these two.  */
  static int
! 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);
Index: remote-nindy.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-nindy.c,v
retrieving revision 1.9
diff -c -r1.9 remote-nindy.c
*** remote-nindy.c	2000/11/03 22:00:56	1.9
--- remote-nindy.c	2000/11/22 02:02:35
***************
*** 476,482 ****
  
  int
  nindy_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len,
! 			    int should_write, struct target_ops *target)
  {
    int res;
  
--- 476,484 ----
  
  int
  nindy_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len,
! 			    int should_write, 
! 			    struct mem_attrib *attrib ATTRIBUTE_UNUSED,
! 			    struct target_ops *target ATTRIBUTE_UNUSED)
  {
    int res;
  
Index: remote-os9k.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-os9k.c,v
retrieving revision 1.7
diff -c -r1.7 remote-os9k.c
*** remote-os9k.c	2000/10/10 05:17:25	1.7
--- remote-os9k.c	2000/11/22 02:02:36
***************
*** 826,832 ****
  
  static int
  rombug_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len,
! 			     int write, struct target_ops *target)
  {
    if (write)
      return rombug_write_inferior_memory (memaddr, myaddr, len);
--- 826,834 ----
  
  static int
  rombug_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len,
! 			     int write, 
! 			     struct mem_attrib *attrib ATTRIBUTE_UNUSED,
! 			     struct target_ops *target ATTRIBUTE_UNUSED)
  {
    if (write)
      return rombug_write_inferior_memory (memaddr, myaddr, len);
Index: remote-rdi.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-rdi.c,v
retrieving revision 1.9
diff -c -r1.9 remote-rdi.c
*** remote-rdi.c	2000/10/12 22:56:31	1.9
--- remote-rdi.c	2000/11/22 02:02:37
***************
*** 52,57 ****
--- 52,58 ----
  
  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,633 ****
  
  /* ARGSUSED */
  static int
! arm_rdi_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
! 		     int should_write, struct target_ops *target)
  {
    int rslt, i;
  
--- 627,635 ----
  
  /* ARGSUSED */
  static int
! 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;
  
Index: remote-rdp.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-rdp.c,v
retrieving revision 1.7
diff -c -r1.7 remote-rdp.c
*** remote-rdp.c	2000/10/30 21:50:57	1.7
--- remote-rdp.c	2000/11/22 02:02:38
***************
*** 167,176 ****
  static char *commandline = NULL;
  
  static int
! remote_rdp_xfer_inferior_memory (CORE_ADDR memaddr,
! 				 char *myaddr,
! 				 int len,
! 				 int write, struct target_ops *target);
  
  
  /* Stuff for talking to the serial layer. */
--- 167,176 ----
  static char *commandline = NULL;
  
  static int
! 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,879 ****
  	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);
  	args->n = args[2].n - done;
  	return 1;
        }
--- 873,879 ----
  	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, 0);
  	args->n = args[2].n - done;
  	return 1;
        }
***************
*** 905,914 ****
  	      commandline[255] = '\0';
  	    }
  	  remote_rdp_xfer_inferior_memory (args[0].n,
! 					   commandline, len + 1, 1, 0);
  	}
        else
! 	remote_rdp_xfer_inferior_memory (args[0].n, "", 1, 1, 0);
        return 1;
  
      default:
--- 905,914 ----
  	      commandline[255] = '\0';
  	    }
  	  remote_rdp_xfer_inferior_memory (args[0].n,
! 					   commandline, len + 1, 1, 0, 0);
  	}
        else
! 	remote_rdp_xfer_inferior_memory (args[0].n, "", 1, 1, 0, 0);
        return 1;
  
      default:
***************
*** 955,960 ****
--- 955,961 ----
  					       buf,
  					       len,
  					       0,
+ 					       0,
  					       0);
  	    }
  	  else
***************
*** 1249,1255 ****
  
  static int
  remote_rdp_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len,
! 				 int write, struct target_ops *target)
  {
    /* I infer from D Taylor's code that there's a limit on the amount
       we can transfer in one chunk.. */
--- 1250,1258 ----
  
  static int
  remote_rdp_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len,
! 				 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.. */
Index: remote-sds.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-sds.c,v
retrieving revision 1.9
diff -c -r1.9 remote-sds.c
*** remote-sds.c	2000/11/03 22:00:56	1.9
--- remote-sds.c	2000/11/22 02:02:39
***************
*** 55,61 ****
  
  static void sds_files_info (struct target_ops *ignore);
  
! static int sds_xfer_memory (CORE_ADDR, char *, int, int, struct target_ops *);
  
  static void sds_prepare_to_store (void);
  
--- 55,62 ----
  
  static void sds_files_info (struct target_ops *ignore);
  
! static int sds_xfer_memory (CORE_ADDR, char *, int, int, 
! 			    struct mem_attrib *, struct target_ops *);
  
  static void sds_prepare_to_store (void);
  
***************
*** 657,663 ****
  /* ARGSUSED */
  static int
  sds_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int should_write,
! 		 struct target_ops *target)
  {
    int res;
  
--- 658,665 ----
  /* ARGSUSED */
  static int
  sds_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 res;
  
Index: remote-sim.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-sim.c,v
retrieving revision 1.8
diff -c -r1.8 remote-sim.c
*** remote-sim.c	2000/10/12 21:39:21	1.8
--- remote-sim.c	2000/11/22 02:02:40
***************
*** 91,99 ****
  
  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 void gdbsim_files_info (struct target_ops *target);
  
--- 91,100 ----
  
  static void gdbsim_prepare_to_store (void);
  
! 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,720 ****
  
  static int
  gdbsim_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len,
! 			     int write, struct target_ops *target)
  {
    if (!program_loaded)
      error ("No program loaded.");
--- 715,723 ----
  
  static int
  gdbsim_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len,
! 			     int write, 
! 			     struct mem_attrib *attrib ATTRIBUTE_UNUSED,
! 			     struct target_ops *target ATTRIBUTE_UNUSED)
  {
    if (!program_loaded)
      error ("No program loaded.");
Index: remote-st.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-st.c,v
retrieving revision 1.5
diff -c -r1.5 remote-st.c
*** remote-st.c	2000/10/16 06:42:28	1.5
--- remote-st.c	2000/11/22 02:02:40
***************
*** 556,562 ****
  
  static int
  st2000_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len,
! 			     int write, struct target_ops *target)
  {
    if (write)
      return st2000_write_inferior_memory (memaddr, myaddr, len);
--- 556,564 ----
  
  static int
  st2000_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len,
! 			     int write, 
! 			     struct mem_attrib *attrib ATTRIBUTE_UNUSED,
! 			     struct target_ops *target ATTRIBUTE_UNUSED)
  {
    if (write)
      return st2000_write_inferior_memory (memaddr, myaddr, len);
Index: remote-udi.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-udi.c,v
retrieving revision 1.7
diff -c -r1.7 remote-udi.c
*** remote-udi.c	2000/08/02 05:17:27	1.7
--- remote-udi.c	2000/11/22 02:02:42
***************
*** 923,929 ****
  /* FIXME!  Merge these two.  */
  static int
  udi_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
! 			  struct target_ops * target)
  {
  
    memaddr = translate_addr (memaddr);
--- 923,930 ----
  /* FIXME!  Merge these two.  */
  static int
  udi_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);
Index: remote-vx.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-vx.c,v
retrieving revision 1.9
diff -c -r1.9 remote-vx.c
*** remote-vx.c	2000/10/30 21:50:57	1.9
--- remote-vx.c	2000/11/22 02:02:42
***************
*** 476,482 ****
  
  static int
  vx_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
! 		struct target_ops *target)
  {
    int status;
    Rptrace ptrace_in;
--- 476,483 ----
  
  static int
  vx_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
! 		struct mem_attrib *attrib ATTRIBUTE_UNUSED,
! 		struct target_ops *target ATTRIBUTE_UNUSED)
  {
    int status;
    Rptrace ptrace_in;
Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.29
diff -c -r1.29 remote.c
*** remote.c	2000/11/20 02:06:18	1.29
--- remote.c	2000/11/22 02:02:46
***************
*** 70,75 ****
--- 70,76 ----
  
  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);
***************
*** 3536,3542 ****
  /* ARGSUSED */
  static int
  remote_xfer_memory (CORE_ADDR mem_addr, char *buffer, int mem_len,
! 		    int should_write, struct target_ops *target)
  {
    CORE_ADDR targ_addr;
    int targ_len;
--- 3537,3545 ----
  /* ARGSUSED */
  static int
  remote_xfer_memory (CORE_ADDR mem_addr, char *buffer, int mem_len,
! 		    int should_write,
! 		    struct mem_attrib *attrib ATTRIBUTE_UNUSED,
! 		    struct target_ops *target)
  {
    CORE_ADDR targ_addr;
    int targ_len;
Index: target.c
===================================================================
RCS file: /cvs/src/src/gdb/target.c,v
retrieving revision 1.16
diff -c -r1.16 target.c
*** target.c	2000/11/21 10:26:07	1.16
--- target.c	2000/11/22 02:02:47
***************
*** 102,108 ****
  static void debug_to_prepare_to_store (void);
  
  static int
! debug_to_xfer_memory (CORE_ADDR, char *, int, int, struct target_ops *);
  
  static void debug_to_files_info (struct target_ops *);
  
--- 102,109 ----
  static void debug_to_prepare_to_store (void);
  
  static int
! 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,385 ****
  	    (void (*) (void)) 
  	    noprocess);
    de_fault (to_xfer_memory, 
! 	    (int (*) (CORE_ADDR, char *, int, int, struct target_ops *)) 
  	    nomemory);
    de_fault (to_files_info, 
  	    (void (*) (struct target_ops *)) 
--- 380,386 ----
  	    (void (*) (void)) 
  	    noprocess);
    de_fault (to_xfer_memory, 
! 	    (int (*) (CORE_ADDR, char *, int, int, struct mem_attrib *, struct target_ops *)) 
  	    nomemory);
    de_fault (to_files_info, 
  	    (void (*) (struct target_ops *)) 
***************
*** 843,849 ****
     Result is -1 on error, or the number of bytes transfered.  */
  
  int
! do_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write)
  {
    int res;
    int done = 0;
--- 844,851 ----
     Result is -1 on error, or the number of bytes transfered.  */
  
  int
! do_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
! 		struct mem_attrib *attrib)
  {
    int res;
    int done = 0;
***************
*** 860,866 ****
  
    /* The quick case is that the top target can handle the transfer.  */
    res = current_target.to_xfer_memory
!     (memaddr, myaddr, len, write, &current_target);
  
    /* If res <= 0 then we call it again in the loop.  Ah well. */
    if (res <= 0)
--- 862,868 ----
  
    /* The quick case is that the top target can handle the transfer.  */
    res = current_target.to_xfer_memory
!     (memaddr, myaddr, len, write, attrib, &current_target);
  
    /* If res <= 0 then we call it again in the loop.  Ah well. */
    if (res <= 0)
***************
*** 871,877 ****
  	  if (!t->to_has_memory)
  	    continue;
  
! 	  res = t->to_xfer_memory (memaddr, myaddr, len, write, t);
  	  if (res > 0)
  	    break;		/* Handled all or part of xfer */
  	  if (t->to_has_all_memory)
--- 873,879 ----
  	  if (!t->to_has_memory)
  	    continue;
  
! 	  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,900 ****
--- 897,904 ----
  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,925 ****
  
    while (len > 0)
      {
!       res = dcache_xfer_memory(target_dcache, memaddr, myaddr, len, write);
!       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;
      }
    
    return 0;			/* We managed to cover it all somehow. */
--- 908,959 ----
  
    while (len > 0)
      {
!       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)
! 	    return EIO;
! 	  break;
! 	  
! 	case MEM_WO:
  	  if (!write)
  	    return EIO;
! 	  break;
  	}
+ 
+       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,
+ 				 &region->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,940 ****
--- 969,976 ----
  			    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)
***************
*** 942,949 ****
        *err = 0;
        return 0;
      }
  
!   res = dcache_xfer_memory (target_dcache, memaddr, myaddr, len, write_p);
    if (res <= 0)
      {
        if (errno != 0)
--- 978,1016 ----
        *err = 0;
        return 0;
      }
+ 
+   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,
! 			  &region->attrib);
!       
    if (res <= 0)
      {
        if (errno != 0)
***************
*** 2313,2323 ****
  
  static int
  debug_to_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
  		      struct target_ops *target)
  {
    int retval;
  
!   retval = debug_target.to_xfer_memory (memaddr, myaddr, len, write, target);
  
    fprintf_unfiltered (gdb_stdlog,
  		      "target_xfer_memory (0x%x, xxx, %d, %s, xxx) = %d",
--- 2380,2392 ----
  
  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,
! 					attrib, target);
  
    fprintf_unfiltered (gdb_stdlog,
  		      "target_xfer_memory (0x%x, xxx, %d, %s, xxx) = %d",
Index: target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.9
diff -c -r1.9 target.h
*** target.h	2000/11/21 10:26:07	1.9
--- target.h	2000/11/22 02:02:48
***************
*** 44,49 ****
--- 44,50 ----
  #include "bfd.h"
  #include "symtab.h"
  #include "dcache.h"
+ #include "memattr.h"
  
  enum strata
    {
***************
*** 363,369 ****
         something at MEMADDR + N.  */
  
      int (*to_xfer_memory) (CORE_ADDR memaddr, char *myaddr,
! 			   int len, int write, struct target_ops * target);
  
  #if 0
      /* Enable this after 4.12.  */
--- 364,372 ----
         something at MEMADDR + N.  */
  
      int (*to_xfer_memory) (CORE_ADDR memaddr, char *myaddr,
! 			   int len, int write, 
! 			   struct mem_attrib *attrib,
! 			   struct target_ops *target);
  
  #if 0
      /* Enable this after 4.12.  */
***************
*** 619,625 ****
  
  extern DCACHE *target_dcache;
  
! extern int do_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write);
  
  extern int target_read_string (CORE_ADDR, char **, int, int *);
  
--- 622,629 ----
  
  extern DCACHE *target_dcache;
  
! 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,636 ****
  
  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
! child_xfer_memory (CORE_ADDR, char *, int, int, struct target_ops *);
  
  /* Make a single attempt at transfering LEN bytes.  On a successful
     transfer, the number of bytes actually transfered is returned and
--- 631,641 ----
  
  extern int target_write_memory (CORE_ADDR memaddr, char *myaddr, int len);
  
! 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 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
Index: wince.c
===================================================================
RCS file: /cvs/src/src/gdb/wince.c,v
retrieving revision 1.10
diff -c -r1.10 wince.c
*** wince.c	2000/11/03 22:00:56	1.10
--- wince.c	2000/11/22 02:02:50
***************
*** 1975,1981 ****
    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,
--- 1975,1980 ----




-- 
J.T. Conklin
RedBack Networks

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]