Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Vladimir Prus <vladimir@codesourcery.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: gdb-patches@sources.redhat.com
Subject: Re: Flash support part 1: memory maps
Date: Mon, 31 Jul 2006 13:00:00 -0000	[thread overview]
Message-ID: <200607311700.42502.vladimir@codesourcery.com> (raw)
In-Reply-To: <uhd1bgf2m.fsf@gnu.org>

[-- Attachment #1: Type: text/plain, Size: 1953 bytes --]

On Friday 21 July 2006 19:20, Eli Zaretskii wrote:
> > From: Vladimir Prus <vladimir@codesourcery.com>
> > Date: Fri, 21 Jul 2006 15:35:29 +0400
> > Cc: gdb-patches@sources.redhat.com
> >
> > > > +  if (!data->character_data)
> > > > +    data->character_data = (char *)malloc (len + 1);
> > > > +  else
> > > > +    {
> > > > +      current_size = strlen (data->character_data);
> > > > +      data->character_data = (char *)realloc (data->character_data,
> > > > +                                              current_size + len +
> > > > 1);
> > >
> > > Why do we need to cast the results of malloc and realloc?
> >
> > Ah, yea, we don't need this in C.
>
> In fact, I think you should replace these with xmalloc and xrealloc.

Here's a patch that does exactly that, and is also based on the current 
mainline (and so uses target_read_stralloc).

2006-07-31  Vladimir Prus  <vladimir@codesourcery.com>

        * Makefile.in (SFILES): Add memory-map.c
        (memory_map_h): New.
        (target_h): Add dependency on memory-map.h.
        (remote.o): Likewise.
        * exceptions.h (enum errors): New value
        XML_MEMORY_MAP_ERROR.
        * remote.c: (struct remote_state): New fields
        current_memory_map and fetched_memory_map.
        (init_remote_state, remote_open_1): Reset the above.
        (PACKET_qXfer_memory_map): New.
        (remote_protocol_features): Register qXfer:memory-map:read.
        (remote_xfer_partial): Handle TARGET_OBJECT_MEMORY_MAP.
        (remote_memory_map): New.
        (init_remote_ops): Register to_memory_map.
        (init_async_remote_ops): Likewise.
        (_initialize_remote): Register qXfer:memory-map:read.
        * target.c (target_memory_map): New.
        * target.h (enum target_object): New value
        TARGET_OBJECT_MEMORY_MAP.
        (struct target_ops): New method to_memory_map.
        (target_memory_map): Declare.
        * memory-map.c: New.
        * memory-map.h: New.

[-- Attachment #2: memory_map__gdb.diff --]
[-- Type: text/x-diff, Size: 31021 bytes --]

=== gdb/target.c
==================================================================
--- gdb/target.c	(/mirrors/gdb)	(revision 319)
+++ gdb/target.c	(/patches/memory_map/gdb)	(revision 319)
@@ -456,6 +456,7 @@
       INHERIT (to_make_corefile_notes, t);
       INHERIT (to_get_thread_local_address, t);
       INHERIT (to_magic, t);
+      /* Do not inherit to_memory_map.  */
     }
 #undef INHERIT
 
@@ -1011,6 +1012,50 @@
     return target_xfer_memory (memaddr, bytes, len, 1);
 }
 
+
+VEC(memory_region) *
+target_memory_map (void)
+{
+  struct target_ops *t;
+    
+  for (t = current_target.beneath; t != NULL; t = t->beneath)
+    if (t->to_memory_map != NULL)
+	{
+          VEC(memory_region) *result;
+          int i;
+
+	  if (targetdebug)
+	    fprintf_unfiltered (gdb_stdlog, "target_memory_map\n");
+
+          result = t->to_memory_map (t);
+
+          qsort (VEC_address (memory_region, result),
+                 VEC_length (memory_region, result),
+                 sizeof (memory_region),
+                 compare_memory_region_starting_address);
+
+          /* Check that regions do not overlap.  */
+          if (!VEC_empty (memory_region, result))
+            for (i = 0; i < VEC_length (memory_region, result) - 1; ++i)
+              {
+                memory_region *this_one = VEC_index (memory_region, result, i);
+                memory_region *next_one = VEC_index 
+                  (memory_region, result, i+1);
+                
+                if (this_one->end > next_one->begin)
+                  {
+                    warning (_("Overlapping regions in memory map: ignoring"));
+                    VEC_free (memory_region, result);
+                    return 0;
+                  }
+              }
+
+	  return result;
+	}
+
+  tcomplain ();
+}
+
 #ifndef target_stopped_data_address_p
 int
 target_stopped_data_address_p (struct target_ops *target)
=== gdb/remote.c
==================================================================
--- gdb/remote.c	(/mirrors/gdb)	(revision 319)
+++ gdb/remote.c	(/patches/memory_map/gdb)	(revision 319)
@@ -60,6 +60,8 @@
 
 #include "remote-fileio.h"
 
+#include "memory-map.h"
+
 /* The size to align memory write packets, when practical.  The protocol
    does not guarantee any alignment, and gdb will generate short
    writes and unaligned writes, but even as a best-effort attempt this
@@ -233,6 +235,15 @@
      a buffer in the stub), this will be set to that packet size.
      Otherwise zero, meaning to use the guessed size.  */
   long explicit_packet_size;
+
+  /* The memory map we've obtained from remote.  */
+  VEC(memory_region) *current_memory_map;
+
+  /* Tells if we've already fetched memory map.  If non-zero,
+     we don't need to try again.  Note that if we've tried to
+     fetch memory map but failed, this field will be non-zero,
+     while CURRENT_MEMORY_MAP will be NULL.  */
+  int fetched_memory_map;
 };
 
 /* This data could be associated with a target, but we do not always
@@ -349,6 +360,9 @@
       rs->buf = xrealloc (rs->buf, rs->buf_size);
     }
 
+  rs->current_memory_map = NULL;
+  rs->fetched_memory_map = 0;
+
   return rsa;
 }
 
@@ -826,6 +840,7 @@
   PACKET_Z3,
   PACKET_Z4,
   PACKET_qXfer_auxv,
+  PACKET_qXfer_memory_map,
   PACKET_qGetTLSAddr,
   PACKET_qSupported,
   PACKET_MAX
@@ -2177,7 +2192,9 @@
 static struct protocol_feature remote_protocol_features[] = {
   { "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
   { "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
-    PACKET_qXfer_auxv }
+    PACKET_qXfer_auxv },
+  { "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet,
+    PACKET_qXfer_memory_map }
 };
 
 static void
@@ -2373,6 +2390,11 @@
   use_threadinfo_query = 1;
   use_threadextra_query = 1;
 
+  /* After connect, memory map is not valid.  */
+  rs->fetched_memory_map = 0;
+  VEC_free (memory_region, rs->current_memory_map);
+  rs->current_memory_map = NULL;
+
   /* The first packet we send to the target is the optional "supported
      packets" request.  If the target can answer this, it will tell us
      which later probes to skip.  */
@@ -5312,6 +5334,11 @@
       return remote_read_qxfer (ops, "auxv", annex, readbuf, offset, len,
 				&remote_protocol_packets[PACKET_qXfer_auxv]);
 
+    case TARGET_OBJECT_MEMORY_MAP:
+      gdb_assert (annex == NULL);
+      return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len,
+				&remote_protocol_packets[PACKET_qXfer_memory_map]);
+      
     default:
       return -1;
     }
@@ -5420,6 +5447,29 @@
     }
 }
 
+static VEC(memory_region) * 
+remote_memory_map (struct target_ops *ops)
+{
+  struct cleanup *back_to = make_cleanup (null_cleanup, 0);
+  struct remote_state *rs = get_remote_state ();
+
+  if (!rs->fetched_memory_map)    
+    {
+      char *text = target_read_stralloc (&current_target, 
+                                         TARGET_OBJECT_MEMORY_MAP, NULL);
+      if (text)
+        {
+          make_cleanup (free_current_contents, &text);
+          
+          rs->fetched_memory_map = 1;
+          rs->current_memory_map = parse_memory_map (text);
+        }
+    }
+      
+  do_cleanups (back_to);  
+  return rs->current_memory_map;
+}
+
 static void
 packet_command (char *args, int from_tty)
 {
@@ -5692,6 +5742,7 @@
   remote_ops.to_has_execution = 1;
   remote_ops.to_has_thread_control = tc_schedlock;	/* can lock scheduler */
   remote_ops.to_magic = OPS_MAGIC;
+  remote_ops.to_memory_map = remote_memory_map;
 }
 
 /* Set up the extended remote vector by making a copy of the standard
@@ -5821,6 +5872,7 @@
   remote_async_ops.to_async = remote_async;
   remote_async_ops.to_async_mask_value = 1;
   remote_async_ops.to_magic = OPS_MAGIC;
+  remote_async_ops.to_memory_map = remote_memory_map;
 }
 
 /* Set up the async extended remote vector by making a copy of the standard
@@ -6061,6 +6113,9 @@
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_auxv],
 			 "qXfer:auxv:read", "read-aux-vector", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_memory_map],
+			 "qXfer:memory-map:read", "memory-map", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qGetTLSAddr],
 			 "qGetTLSAddr", "get-thread-local-storage-address",
 			 0);
=== gdb/target.h
==================================================================
--- gdb/target.h	(/mirrors/gdb)	(revision 319)
+++ gdb/target.h	(/patches/memory_map/gdb)	(revision 319)
@@ -55,6 +55,8 @@
 #include "symtab.h"
 #include "dcache.h"
 #include "memattr.h"
+#include "vec.h"
+#include "memory-map.h"
 
 enum strata
   {
@@ -194,7 +196,9 @@
   /* Transfer auxilliary vector.  */
   TARGET_OBJECT_AUXV,
   /* StackGhost cookie.  See "sparc-tdep.c".  */
-  TARGET_OBJECT_WCOOKIE
+  TARGET_OBJECT_WCOOKIE,
+  /* Target memory map in XML format.  */
+  TARGET_OBJECT_MEMORY_MAP,
 
   /* Possible future objects: TARGET_OBJECT_FILE, TARGET_OBJECT_PROC, ... */
 };
@@ -437,6 +441,20 @@
 				gdb_byte *readbuf, const gdb_byte *writebuf,
 				ULONGEST offset, LONGEST len);
 
+    /* Returns the memory map for the target. The return value of 0 means 
+       that no memory map is available. If a memory address does not fall 
+       within any returned regions, it's assumed to be RAM.  The returned
+       memory regions should not overlap.
+
+       The order of regions does not matter, as target_memory_map will
+       sort regions by starting address anyway. For that reason, this
+       function should not be called directly, only via target_memory_map.
+       
+       This method is expected to cache the data if fetching it is slow.
+       The higher-level code has no way of knowing when memory map
+       could change, and so can't do caching itself.  */
+    VEC(memory_region) * (*to_memory_map) (struct target_ops *);
+
     int to_magic;
     /* Need sub-structure for target machine related rather than comm related?
      */
@@ -575,6 +593,12 @@
 extern int target_write_memory_partial (CORE_ADDR addr, gdb_byte *buf,
 					int len, int *err);
 
+/* Calls the first non-null to_memory_map pointer in target_stack.  
+   Sorts the result by starting address and returns it.  Additionally
+   checks that memory regions do not overlap.  If they do, issues
+   a warning and returns empty vector.  */
+VEC(memory_region) *target_memory_map (void);
+
 extern char *child_pid_to_exec_file (int);
 
 extern char *child_core_file_to_sym_file (char *);
=== gdb/memory-map.c
==================================================================
--- gdb/memory-map.c	(/mirrors/gdb)	(revision 319)
+++ gdb/memory-map.c	(/patches/memory_map/gdb)	(revision 319)
@@ -0,0 +1,364 @@
+/* Routines for handling XML memory maps provided by target.
+
+   Copyright (C) 2006
+   Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#include "defs.h"
+#include "memory-map.h"
+#include "gdb_assert.h"
+#include "exceptions.h"
+
+#include <expat.h>
+
+#include "gdb_string.h"
+
+/* Internal parsing data passed to all Expat callbacks.  */
+struct memory_map_parsing_data
+  {
+    VEC(memory_region) **memory_map;
+    memory_region *currently_parsed;
+    char *character_data;
+    const char* property_name;
+    int capture_text;
+  };
+
+static void
+free_memory_map_parsing_data (void *p_)
+{
+  struct memory_map_parsing_data *p = p_;
+
+  xfree (p->character_data);
+}
+
+
+/* Returns the value of attribute ATTR from expat attribute list ATTRS.
+   If not found, calls 'error'.  */
+const XML_Char *xml_get_attribute_value(const XML_Char **attrs,
+                                        const XML_Char *attr)
+{
+  const XML_Char **p;
+  for (p = attrs; *p; p += 2)
+    {
+      const char *name = p[0];
+      const char *val = p[1];
+
+      if (strcmp (name, attr) == 0)
+        return val;
+    }
+  throw_error (XML_MEMORY_MAP_ERROR, _("Can't find attribute %s"), attr);
+  return 0;
+}
+
+/* Parse a field VALSTR that we expect to contain an integer value.
+   The integer is returned in *VALP.
+   The string is parsed with the strtoul rountine.
+
+   Returns 0 for success, -1 for error.  */
+static int
+xml_parse_unsigned_integer (const char *valstr, unsigned long *valp)
+{
+  char *endptr;
+  unsigned result;
+
+  if (*valstr == '\0')
+    return -1;
+
+  result = strtoul (valstr, &endptr, 0);
+  if (*endptr != '\0')
+    return -1;
+
+  *valp = result;
+  return 0;
+}
+
+/* Gets the value of an integer attribute, if it's present.
+   If the attribute is not found, or can't be parsed as integer,
+   calls error.  */
+static unsigned long
+xml_get_integer_attribute (const XML_Char **attrs,
+                           const XML_Char *attr)
+{
+  unsigned long result;
+  const XML_Char *value = xml_get_attribute_value (attrs, attr);
+
+  if (xml_parse_unsigned_integer (value, &result) != 0)
+    {
+      throw_error (XML_MEMORY_MAP_ERROR, 
+                   _("Can't convert value of attribute %s, %s, to integer"),
+                   attr, value);
+    }  
+  return result;
+}
+
+/* Obtains a value of attribute with enumerated type. In XML, enumerated 
+   attributes have string as a value, and in C, they are represented as
+   values of enumerated type. This function maps the attribute onto 
+   an integer value that can be immediately converted into enumerated
+   type.
+
+   First, obtains the string value of ATTR in ATTRS.
+   Then, finds the index of that value in XML_NAMES, which is a zero-terminated
+   array of strings. If found, returns the element of VALUES with that index.
+   Otherwise throws.  */
+static int
+xml_get_enum_value (const XML_Char **attrs,
+                    const XML_Char *attr,
+                    const XML_Char **xml_names,
+                    int *values)
+{
+  const XML_Char *value = xml_get_attribute_value (attrs, attr);
+
+  int i;
+  for (i = 0; xml_names[i]; ++i)
+    {
+      if (strcmp (xml_names[i], value) == 0)
+        return values[i];
+    }
+  throw_error (XML_MEMORY_MAP_ERROR, 
+               _("Invalid enumerated value in XML: %s"), value);
+}
+
+/* Callback called by Expat on start of element.
+   DATA_ is pointer to memory_map_parsing_data
+   NAME is the name of element
+   ATTRS is the zero-terminated array of attribute names and
+   attribute values.
+
+   This function handles the following elements:
+   - 'memory' -- creates new memory region and initializes it
+     from attributes. sets DATA_.CURRENTLY_PARSED to the new region.
+   - 'properties' -- sets DATA.CAPTURE_TEXT.  */
+static void
+memory_map_start_element (void* data_, const XML_Char *name,
+                          const XML_Char **attrs)
+{
+  struct memory_map_parsing_data *data = data_;
+  struct gdb_exception ex;
+
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
+    {  
+      if (strcmp (name, "memory") == 0)
+        {
+          struct memory_region *r = 
+            VEC_safe_push (memory_region, *data->memory_map, NULL);
+          
+          r->begin = xml_get_integer_attribute (attrs, "start");
+          r->end = r->begin + xml_get_integer_attribute (attrs, "length");
+          
+          {
+            static const XML_Char* names[] = {"ram", "rom", "flash", 0};
+            static int values[] = {TARGET_MEMORY_RAM, TARGET_MEMORY_ROM,
+                                   TARGET_MEMORY_FLASH};
+            
+            r->memory_type = xml_get_enum_value (attrs, "type", names, values);
+          }
+          r->flash_block_size = (unsigned)-1;
+          
+          data->currently_parsed = r;         
+        }
+      else if (strcmp (name, "property") == 0)
+        {
+          if (!data->currently_parsed)
+            throw_error (XML_MEMORY_MAP_ERROR,
+                _("memory map: found 'property' element outside 'memory'"));
+          
+          data->capture_text = 1;
+          
+          data->property_name = xml_get_attribute_value (attrs, "name");
+        }
+    }
+  if (ex.reason < 0)
+    throw_error 
+      (ex.error, _("while parsing element %s:\n%s"), name, ex.message);
+
+}
+
+/* Callback called by Expat on start of element.
+   DATA_ is pointer to memory_map_parsing_data
+   NAME is the name of element
+
+   This function handles the following elements:
+   - 'property' -- check that property name is 'blocksize' and
+     sets DATA->CURRENT_PARSED->FLASH_BLOCK_SIZE
+   - 'memory' verifies that flash block size is set.  */
+static void
+memory_map_end_element (void* data_, const XML_Char *name)
+{
+  struct memory_map_parsing_data *data = data_;
+  struct gdb_exception ex;
+
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
+    {
+      if (strcmp (name, "property") == 0)
+        {
+          if (strcmp (data->property_name, "blocksize") == 0)
+            {          
+              if (!data->character_data)
+                throw_error (XML_MEMORY_MAP_ERROR,
+                             _("Empty content of 'property' element"));
+              char *end = 0;
+              data->currently_parsed->flash_block_size = 
+                strtoul (data->character_data, &end, 0);
+              if (*end != '\0')
+                throw_error (XML_MEMORY_MAP_ERROR,
+                             _("Invalid content of the 'blocksize' property"));
+            }
+          else
+            throw_error (XML_MEMORY_MAP_ERROR,
+                         _("Unknown memory region property: %s"), name);
+          
+          data->capture_text = 0;
+        }
+      else if (strcmp (name, "memory") == 0)
+        {
+          if (data->currently_parsed->memory_type == TARGET_MEMORY_FLASH
+              && data->currently_parsed->flash_block_size == (unsigned)-1)
+            throw_error (XML_MEMORY_MAP_ERROR,
+                         _("Flash block size is not set"));
+     
+          data->currently_parsed = 0;
+          data->character_data = 0;
+        }
+    }
+  if (ex.reason < 0)
+    throw_error 
+      (ex.error, _("while parsing element %s: \n%s"), name, ex.message);
+}
+
+/* Callback called by expat for all character data blocks.
+   DATA_ is the pointer to memory_map_parsing_data.
+   S is the point to character data.
+   LEN is the length of data; the data is not zero-terminated.
+
+   If DATA_->CAPTURE_TEXT is 1, appends this block of characters
+   to DATA_->CHARACTER_DATA.  */
+static void
+memory_map_character_data (void *data_, const XML_Char *s,
+                           int len)
+{
+  struct memory_map_parsing_data *data = data_;
+  int current_size = 0;
+  
+  if (!data->capture_text)
+    return;
+
+  /* Expat interface does not guarantee that a single call to
+     a handler will be made. Actually, one call for each line
+     will be made, and character data can possibly span several
+     lines.
+
+     Take care to realloc the data if needed.
+  */  
+  if (!data->character_data)
+    data->character_data = (char *)malloc (len + 1);
+  else
+    {
+      current_size = strlen (data->character_data);
+      data->character_data = (char *)realloc (data->character_data,
+                                              current_size + len + 1);
+    }
+
+  memcpy (data->character_data + current_size, s, len);
+  data->character_data[current_size + len] = '\0';
+}
+
+static void
+clear_result (void *p)
+{
+  VEC(memory_region) **result = p;
+  VEC_free (memory_region, *result);
+  *result = 0;
+}
+
+static void
+cleanup_XML_parser (void *p)
+{
+  XML_Parser parser = p;
+  XML_ParserFree (parser);
+}
+
+
+VEC(memory_region) *
+parse_memory_map (const char *memory_map)
+{
+  VEC(memory_region) *result = 0;
+  struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
+  struct cleanup *before_deleting_result;
+  struct cleanup *saved;
+  volatile struct gdb_exception ex;
+  int ok = 0;
+
+  struct memory_map_parsing_data data = {};
+
+  XML_Parser parser = XML_ParserCreateNS (NULL, '!');
+  if (parser == NULL)
+    goto out;
+  
+  make_cleanup (cleanup_XML_parser, parser);
+  make_cleanup (free_memory_map_parsing_data, &data);
+  /* Note: 'clear_result' will zero 'result'.  */
+  before_deleting_result = make_cleanup (clear_result, &result);
+  
+        
+  XML_SetElementHandler (parser, memory_map_start_element,
+                         memory_map_end_element);
+  XML_SetCharacterDataHandler (parser, memory_map_character_data);
+  XML_SetUserData (parser, &data);
+  data.memory_map = &result;
+
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
+    { 
+      if (XML_Parse (parser, memory_map, strlen (memory_map), 1)
+          != XML_STATUS_OK)
+        {
+          enum XML_Error err = XML_GetErrorCode (parser);
+          
+          throw_error (XML_MEMORY_MAP_ERROR, "%s", XML_ErrorString (err));
+        }
+    }
+  if (ex.reason != GDB_NO_ERROR)
+    {
+      if (ex.error == XML_MEMORY_MAP_ERROR)
+        {
+          /* Just report it.  */
+          warning (_("Could not parse XML memory map: %s"), ex.message);
+        }
+      else
+        {
+          throw_exception (ex);
+        }
+    }
+  else
+    {
+      /* Parsed successfully, don't need to delete result.  */
+      discard_cleanups (before_deleting_result);
+    }
+      
+ out:
+  do_cleanups (back_to);
+  return result;
+}
+
+int compare_memory_region_starting_address (const void* a, const void *b)
+{
+  ULONGEST a_begin = ((memory_region *)a)->begin;
+  ULONGEST b_begin = ((memory_region *)b)->begin;
+  return a_begin - b_begin;
+}
=== gdb/memory-map.h
==================================================================
--- gdb/memory-map.h	(/mirrors/gdb)	(revision 319)
+++ gdb/memory-map.h	(/patches/memory_map/gdb)	(revision 319)
@@ -0,0 +1,142 @@
+/* Routines for handling XML memory maps provided by target.
+
+   Copyright (C) 2006
+   Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+
+#ifndef MEMORY_MAP_H
+#define MEMORY_MAP_H
+
+#include "vec.h"
+
+/* Describes various kinds of memory regions.  */
+enum memory_region_type
+  {
+    /* Memory that can be freely written and read.  */
+    TARGET_MEMORY_RAM,
+    /* Memory that can't be written at all.  */
+    TARGET_MEMORY_ROM,
+    /* Memory that can be written only using special operations.  */
+    TARGET_MEMORY_FLASH
+  };
+
+/* Describes properties of a memory range.  */
+typedef struct memory_region
+  {
+    /* The first address of the region.  */
+    ULONGEST begin;
+    /* The past-the-end address of the region.  */
+    ULONGEST end;
+    /* Type of the memory in this region.  */
+    enum memory_region_type memory_type;
+    /* The size of flash memory sector.  Some flash chips have non-uniform 
+       sector sizes, for example small sectors at beginning and end. 
+       In this case gdb will have to have several memory_region objects each
+       one having uniform sector size. 
+       This field is defined only of MEMORY_TYPE == TARGET_MEMORY_FLASH.  */
+    unsigned flash_block_size;
+  } memory_region;
+
+DEF_VEC_O(memory_region);
+
+/* Casts both A and B to memory_region, compares they starting addresses
+   and returns value less than zero, equal to zero, or greater then zero
+   if A's starting address is less than B's starting address, equal to,
+   or greater then, respectively.  This function is suitable for sorting
+   vector of memory_regions with the qsort function.  */
+int compare_memory_region_starting_address (const void* a, const void *b);
+
+/* Parses XML memory map passed as argument and returns the memory
+   regions it describes.  On any error, emits error message and
+   returns 0. Does not throw.  Ownership of result is passed to the caller.  */
+VEC(memory_region) *parse_memory_map (const char *memory_map);
+
+#endif
+/* Routines for handling XML memory maps provided by target.
+
+   Copyright (C) 2006
+   Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+
+#ifndef MEMORY_MAP_H
+#define MEMORY_MAP_H
+
+#include "vec.h"
+
+/* Describes various kinds of memory regions.  */
+enum memory_region_type
+  {
+    /* Memory that can be freely written and read.  */
+    TARGET_MEMORY_RAM,
+    /* Memory that can't be written at all.  */
+    TARGET_MEMORY_ROM,
+    /* Memory that can be written only using special operations.  */
+    TARGET_MEMORY_FLASH
+  };
+
+/* Describes properties of a memory range.  */
+typedef struct memory_region
+  {
+    /* The first address of the region.  */
+    ULONGEST begin;
+    /* The past-the-end address of the region.  */
+    ULONGEST end;
+    /* Type of the memory in this region.  */
+    enum memory_region_type memory_type;
+    /* The size of flash memory sector.  Some flash chips have non-uniform 
+       sector sizes, for example small sectors at beginning and end. 
+       In this case gdb will have to have several memory_region objects each
+       one having uniform sector size. 
+       This field is defined only of MEMORY_TYPE == TARGET_MEMORY_FLASH.  */
+    unsigned flash_block_size;
+  } memory_region;
+
+DEF_VEC_O(memory_region);
+
+/* Casts both A and B to memory_region, compares they starting addresses
+   and returns value less than zero, equal to zero, or greater then zero
+   if A's starting address is less than B's starting address, equal to,
+   or greater then, respectively.  This function is suitable for sorting
+   vector of memory_regions with the qsort function.  */
+int compare_memory_region_starting_address (const void* a, const void *b);
+
+/* Parses XML memory map passed as argument and returns the memory
+   regions it describes.  On any error, emits error message and
+   returns 0. Does not throw.  Ownership of result is passed to the caller.  */
+VEC(memory_region) *parse_memory_map (const char *memory_map);
+
+#endif
=== gdb/symfile.c
==================================================================
--- gdb/symfile.c	(/mirrors/gdb)	(revision 319)
+++ gdb/symfile.c	(/patches/memory_map/gdb)	(revision 319)
@@ -1521,15 +1521,6 @@
    we don't want to run a subprocess.  On the other hand, I'm not sure how
    performance compares.  */
 
-static int download_write_size = 512;
-static void
-show_download_write_size (struct ui_file *file, int from_tty,
-			  struct cmd_list_element *c, const char *value)
-{
-  fprintf_filtered (file, _("\
-The write size used when downloading a program is %s.\n"),
-		    value);
-}
 static int validate_download = 0;
 
 /* Callback service function for generic_load (bfd_map_over_sections).  */
@@ -1570,11 +1561,6 @@
 	  const char *sect_name = bfd_get_section_name (abfd, asec);
 	  bfd_size_type sent;
 
-	  if (download_write_size > 0 && size > download_write_size)
-	    block_size = download_write_size;
-	  else
-	    block_size = size;
-
 	  buffer = xmalloc (size);
 	  old_chain = make_cleanup (xfree, buffer);
 
@@ -1591,8 +1577,6 @@
 	      int len;
 	      bfd_size_type this_transfer = size - sent;
 
-	      if (this_transfer >= block_size)
-		this_transfer = block_size;
 	      len = target_write_memory_partial (lma, buffer,
 						 this_transfer, &err);
 	      if (err)
@@ -3806,19 +3790,6 @@
   add_info ("extensions", info_ext_lang_command,
 	    _("All filename extensions associated with a source language."));
 
-  add_setshow_integer_cmd ("download-write-size", class_obscure,
-			   &download_write_size, _("\
-Set the write size used when downloading a program."), _("\
-Show the write size used when downloading a program."), _("\
-Only used when downloading a program onto a remote\n\
-target. Specify zero, or a negative value, to disable\n\
-blocked writes. The actual size of each transfer is also\n\
-limited by the size of the target packet and the memory\n\
-cache."),
-			   NULL,
-			   show_download_write_size,
-			   &setlist, &showlist);
-
   debug_file_directory = xstrdup (DEBUGDIR);
   add_setshow_optional_filename_cmd ("debug-file-directory", class_support,
 				     &debug_file_directory, _("\
=== gdb/NEWS
==================================================================
--- gdb/NEWS	(/mirrors/gdb)	(revision 319)
+++ gdb/NEWS	(/patches/memory_map/gdb)	(revision 319)
@@ -18,6 +18,8 @@
 Kernel Object Display, an embedded debugging feature which only worked with
 an obsolete version of Cisco IOS.
 
+The 'download_write_size' variable.
+
 * New remote packets
 
 qSupported:
=== gdb/Makefile.in
==================================================================
--- gdb/Makefile.in	(/mirrors/gdb)	(revision 319)
+++ gdb/Makefile.in	(/patches/memory_map/gdb)	(revision 319)
@@ -535,7 +535,7 @@
 	language.c linespec.c \
 	m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c \
 	macrotab.c macroexp.c macrocmd.c macroscope.c main.c maint.c \
-	mdebugread.c memattr.c mem-break.c minsyms.c mipsread.c \
+	mdebugread.c memattr.c mem-break.c minsyms.c mipsread.c memory-map.c \
 	nlmread.c \
 	objc-exp.y objc-lang.c \
 	objfiles.c osabi.c observer.c \
@@ -745,6 +745,7 @@
 mips_mdebug_tdep_h = mips-mdebug-tdep.h
 mipsnbsd_tdep_h = mipsnbsd-tdep.h
 mips_tdep_h = mips-tdep.h
+memory_map_h = memory-map.h $(vec_h)
 mn10300_tdep_h = mn10300-tdep.h
 monitor_h = monitor.h
 nbsd_tdep_h = nbsd-tdep.h
@@ -794,7 +795,8 @@
 stack_h = stack.h
 symfile_h = symfile.h
 symtab_h = symtab.h
-target_h = target.h $(bfd_h) $(symtab_h) $(dcache_h) $(memattr_h)
+target_h = target.h $(bfd_h) $(symtab_h) $(dcache_h) $(memattr_h) $(vec_h) \
+    $(memory_map_h)
 terminal_h = terminal.h
 top_h = top.h
 tracepoint_h = tracepoint.h
@@ -953,7 +955,7 @@
 	trad-frame.o \
 	tramp-frame.o \
 	solib.o solib-null.o \
-	prologue-value.o
+	prologue-value.o vec.o memory-map.o
 
 TSOBS = inflow.o
 
@@ -2359,6 +2361,8 @@
 	$(floatformat_h)
 mipsv4-nat.o: mipsv4-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(target_h) \
 	$(regcache_h) $(gregset_h)
+memory-map.o: memory-map.c $(defs_h) $(memory_map_h) $(gdb_assert_h) \
+	$(exceptions_h) $(gdb_string_h)
 mn10300-linux-tdep.o: mn10300-linux-tdep.c $(defs_h) $(gdbcore_h) \
 	$(gdb_string_h) $(regcache_h) $(mn10300_tdep_h) $(gdb_assert_h) \
 	$(bfd_h) $(elf_bfd_h) $(osabi_h) $(regset_h) $(solib_svr4_h) \
@@ -2487,7 +2491,7 @@
 	$(gdb_stabs_h) $(gdbthread_h) $(remote_h) $(regcache_h) $(value_h) \
 	$(gdb_assert_h) $(event_loop_h) $(event_top_h) $(inf_loop_h) \
 	$(serial_h) $(gdbcore_h) $(remote_fileio_h) $(solib_h) $(observer_h) \
-	$(cli_decode_h) $(cli_setshow_h)
+	$(cli_decode_h) $(cli_setshow_h) $(memory_map_h)
 remote-e7000.o: remote-e7000.c $(defs_h) $(gdbcore_h) $(gdbarch_h) \
 	$(inferior_h) $(target_h) $(value_h) $(command_h) $(gdb_string_h) \
 	$(exceptions_h) $(gdbcmd_h) $(serial_h) $(remote_utils_h) \
=== gdb/exceptions.h
==================================================================
--- gdb/exceptions.h	(/mirrors/gdb)	(revision 319)
+++ gdb/exceptions.h	(/patches/memory_map/gdb)	(revision 319)
@@ -71,6 +71,9 @@
      more detail.  */
   TLS_GENERIC_ERROR,
 
+  /* Problem parsing XML memory map.  */
+  XML_MEMORY_MAP_ERROR,
+
   /* Add more errors here.  */
   NR_ERRORS
 };

  reply	other threads:[~2006-07-31 13:00 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-07-20  9:41 Vladimir Prus
2006-07-20 19:32 ` Eli Zaretskii
2006-07-21 11:35   ` Vladimir Prus
2006-07-21 15:20     ` Eli Zaretskii
2006-07-31 13:00       ` Vladimir Prus [this message]
2006-07-31 13:20         ` Vladimir Prus
2006-07-31 22:09           ` Mark Kettenis
2006-08-01  0:53             ` Daniel Jacobowitz
2006-08-01  5:11             ` Vladimir Prus
2006-08-16 20:05 ` Daniel Jacobowitz
2006-09-21 13:56   ` Daniel Jacobowitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200607311700.42502.vladimir@codesourcery.com \
    --to=vladimir@codesourcery.com \
    --cc=eliz@gnu.org \
    --cc=gdb-patches@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox