From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6023 invoked by alias); 31 Jul 2006 13:00:58 -0000 Received: (qmail 6012 invoked by uid 22791); 31 Jul 2006 13:00:54 -0000 X-Spam-Check-By: sourceware.org Received: from potter.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Mon, 31 Jul 2006 13:00:49 +0000 Received: (qmail 27874 invoked from network); 31 Jul 2006 13:00:47 -0000 Received: from unknown (HELO zigzag.lvk.cs.msu.su) (vladimir@127.0.0.2) by mail.codesourcery.com with ESMTPA; 31 Jul 2006 13:00:47 -0000 From: Vladimir Prus To: Eli Zaretskii Subject: Re: Flash support part 1: memory maps Date: Mon, 31 Jul 2006 13:00:00 -0000 User-Agent: KMail/1.7.2 Cc: gdb-patches@sources.redhat.com References: <200607201341.34070.vladimir@codesourcery.com> <200607211535.30236.vladimir@codesourcery.com> In-Reply-To: MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_67fzEtVcidX24Bn" Message-Id: <200607311700.42502.vladimir@codesourcery.com> Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2006-07/txt/msg00426.txt.bz2 --Boundary-00=_67fzEtVcidX24Bn Content-Type: text/plain; charset="koi8-r" Content-Transfer-Encoding: 7bit Content-Disposition: inline Content-length: 1953 On Friday 21 July 2006 19:20, Eli Zaretskii wrote: > > From: Vladimir Prus > > 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 * 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. --Boundary-00=_67fzEtVcidX24Bn Content-Type: text/x-diff; charset="koi8-r"; name="memory_map__gdb.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="memory_map__gdb.diff" Content-length: 31021 === 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 (¤t_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 + +#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 }; --Boundary-00=_67fzEtVcidX24Bn--