gdb/
2006-09-21 Vladimir Prus <vladimir@codesourcery.com> Daniel Jacobowitz <dan@codesourcery.com> Nathan Sidwell <nathan@codesourcery.com> * Makefile.in (SFILES): Add memory-map.c and xml-support.c. (memory_map_h, xml_support_h): New. (target_h): Add vec_h dependency. (COMMON_OBS): Add memory-map.o and xml-support.o. (memory-map.o, xml-support.o): New rules. (remote.o): Update. * exceptions.h (enum errors): Add XML_PARSE_ERROR. * infcmd.c (run_command_1, attach_command): Call target_pre_inferior. * memattr.c (default_mem_attrib): Initialize blocksize. (target_mem_region_list, mem_use_target) (target_mem_regions_valid, mem_region_cmp, mem_region_init) (require_user_regions, require_target_regions) (invalidate_target_mem_regions): New. (create_mem_region): Use mem_region_init. (mem_clear): Move higher. (lookup_mem_region): Use require_target_regions. (mem_command): Implement "mem auto". (mem_info_command): Handle target-supplied regions and flash attributes. (mem_enable_command, mem_disable_command, mem_delete_command): Use require_user_regions. (_initialize_mem): Mention "mem auto" in help. * memattr.h (enum mem_access_mode): Add MEM_FLASH. (struct mem_attrib): Add blocksize. (invalidate_target_mem_regions, mem_region_init, mem_region_cmp): New prototypes. * remote.c: Include "memory-map.h". (PACKET_qXfer_memory_map): New enum value. (remote_protocol_features): Add qXfer:memory-map:read. (remote_xfer_partial): Handle memory maps. (remote_memory_map): New. (init_remote_ops, init_remote_async_ops): Set to_memory_map. (_initialize_remote): Register qXfer:memory-map:read. * target.c (update_current_target): Mention to_memory_map. (target_memory_map, target_pre_inferior): New. (target_preopen): Call target_pre_inferior. * target.h: Include "vec.h". (enum target_object): Add TARGET_OBJECT_MEMORY_MAP. (struct target_ops): Add to_memory_map. (target_memory_map, target_pre_inferior): New prototypes. * memory-map.c, memory-map.h, xml-support.c, xml-support.h: New files. gdb/doc/ 2006-09-21 Vladimir Prus <vladimir@codesourcery.com> Daniel Jacobowitz <dan@codesourcery.com> * gdb.texinfo (Memory Region Attributes): Mention target-supplied memory regions and "mem auto".
This commit is contained in:
parent
253c8abb67
commit
fd79eceebf
15 changed files with 875 additions and 24 deletions
|
@ -1,3 +1,49 @@
|
|||
2006-09-21 Vladimir Prus <vladimir@codesourcery.com>
|
||||
Daniel Jacobowitz <dan@codesourcery.com>
|
||||
Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* Makefile.in (SFILES): Add memory-map.c and xml-support.c.
|
||||
(memory_map_h, xml_support_h): New.
|
||||
(target_h): Add vec_h dependency.
|
||||
(COMMON_OBS): Add memory-map.o and xml-support.o.
|
||||
(memory-map.o, xml-support.o): New rules.
|
||||
(remote.o): Update.
|
||||
* exceptions.h (enum errors): Add XML_PARSE_ERROR.
|
||||
* infcmd.c (run_command_1, attach_command): Call target_pre_inferior.
|
||||
* memattr.c (default_mem_attrib): Initialize blocksize.
|
||||
(target_mem_region_list, mem_use_target)
|
||||
(target_mem_regions_valid, mem_region_cmp, mem_region_init)
|
||||
(require_user_regions, require_target_regions)
|
||||
(invalidate_target_mem_regions): New.
|
||||
(create_mem_region): Use mem_region_init.
|
||||
(mem_clear): Move higher.
|
||||
(lookup_mem_region): Use require_target_regions.
|
||||
(mem_command): Implement "mem auto".
|
||||
(mem_info_command): Handle target-supplied regions and flash
|
||||
attributes.
|
||||
(mem_enable_command, mem_disable_command, mem_delete_command): Use
|
||||
require_user_regions.
|
||||
(_initialize_mem): Mention "mem auto" in help.
|
||||
* memattr.h (enum mem_access_mode): Add MEM_FLASH.
|
||||
(struct mem_attrib): Add blocksize.
|
||||
(invalidate_target_mem_regions, mem_region_init, mem_region_cmp): New
|
||||
prototypes.
|
||||
* remote.c: Include "memory-map.h".
|
||||
(PACKET_qXfer_memory_map): New enum value.
|
||||
(remote_protocol_features): Add qXfer:memory-map:read.
|
||||
(remote_xfer_partial): Handle memory maps.
|
||||
(remote_memory_map): New.
|
||||
(init_remote_ops, init_remote_async_ops): Set to_memory_map.
|
||||
(_initialize_remote): Register qXfer:memory-map:read.
|
||||
* target.c (update_current_target): Mention to_memory_map.
|
||||
(target_memory_map, target_pre_inferior): New.
|
||||
(target_preopen): Call target_pre_inferior.
|
||||
* target.h: Include "vec.h".
|
||||
(enum target_object): Add TARGET_OBJECT_MEMORY_MAP.
|
||||
(struct target_ops): Add to_memory_map.
|
||||
(target_memory_map, target_pre_inferior): New prototypes.
|
||||
* memory-map.c, memory-map.h, xml-support.c, xml-support.h: New files.
|
||||
|
||||
2006-09-21 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* ada-lex.l (HIGH_BYTE_POSN, is_digit_in_base, digit_to_int)
|
||||
|
|
|
@ -541,7 +541,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c \
|
|||
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 \
|
||||
|
@ -561,7 +561,8 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c \
|
|||
ui-out.c utils.c ui-file.h ui-file.c \
|
||||
user-regs.c \
|
||||
valarith.c valops.c valprint.c value.c varobj.c vec.c \
|
||||
wrapper.c
|
||||
wrapper.c \
|
||||
xml-support.c
|
||||
|
||||
LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
|
||||
|
||||
|
@ -752,6 +753,7 @@ mips_linux_tdep_h = mips-linux-tdep.h
|
|||
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 $(memattr_h)
|
||||
mn10300_tdep_h = mn10300-tdep.h
|
||||
monitor_h = monitor.h
|
||||
nbsd_tdep_h = nbsd-tdep.h
|
||||
|
@ -801,7 +803,7 @@ stabsread_h = stabsread.h
|
|||
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)
|
||||
terminal_h = terminal.h
|
||||
top_h = top.h
|
||||
tracepoint_h = tracepoint.h
|
||||
|
@ -821,6 +823,7 @@ version_h = version.h
|
|||
wince_stub_h = wince-stub.h
|
||||
wrapper_h = wrapper.h $(gdb_h)
|
||||
xcoffsolib_h = xcoffsolib.h
|
||||
xml_support_h = xml-support.h
|
||||
|
||||
#
|
||||
# gdb/cli/ headers
|
||||
|
@ -961,7 +964,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
|
|||
trad-frame.o \
|
||||
tramp-frame.o \
|
||||
solib.o solib-null.o \
|
||||
prologue-value.o
|
||||
prologue-value.o memory-map.o xml-support.o
|
||||
|
||||
TSOBS = inflow.o
|
||||
|
||||
|
@ -2371,6 +2374,8 @@ mips-tdep.o: mips-tdep.c $(defs_h) $(gdb_string_h) $(gdb_assert_h) \
|
|||
$(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) $(xml_support_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) \
|
||||
|
@ -2500,7 +2505,7 @@ remote.o: remote.c $(defs_h) $(gdb_string_h) $(inferior_h) $(bfd_h) \
|
|||
$(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) \
|
||||
|
@ -2847,6 +2852,8 @@ xcoffread.o: xcoffread.c $(defs_h) $(bfd_h) $(gdb_string_h) $(gdb_stat_h) \
|
|||
$(complaints_h) $(gdb_stabs_h) $(aout_stab_gnu_h)
|
||||
xcoffsolib.o: xcoffsolib.c $(defs_h) $(bfd_h) $(xcoffsolib_h) $(inferior_h) \
|
||||
$(gdbcmd_h) $(symfile_h) $(frame_h) $(gdb_regex_h)
|
||||
xml-support.o: xml-support.c $(defs_h) $(xml_support_h) $(exceptions_h) \
|
||||
$(gdb_string_h)
|
||||
xstormy16-tdep.o: xstormy16-tdep.c $(defs_h) $(frame_h) $(frame_base_h) \
|
||||
$(frame_unwind_h) $(dwarf2_frame_h) $(symtab_h) $(gdbtypes_h) \
|
||||
$(gdbcmd_h) $(gdbcore_h) $(value_h) $(dis_asm_h) $(inferior_h) \
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2006-09-21 Vladimir Prus <vladimir@codesourcery.com>
|
||||
Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* gdb.texinfo (Memory Region Attributes): Mention target-supplied
|
||||
memory regions and "mem auto".
|
||||
|
||||
2006-09-21 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* gdbint.texinfo (Array Containers): New section.
|
||||
|
|
|
@ -6720,9 +6720,12 @@ an unrecognized tag.
|
|||
@cindex memory region attributes
|
||||
|
||||
@dfn{Memory region attributes} allow you to describe special handling
|
||||
required by regions of your target's memory. @value{GDBN} uses attributes
|
||||
to determine whether to allow certain types of memory accesses; whether to
|
||||
use specific width accesses; and whether to cache target memory.
|
||||
required by regions of your target's memory. @value{GDBN} uses
|
||||
attributes to determine whether to allow certain types of memory
|
||||
accesses; whether to use specific width accesses; and whether to cache
|
||||
target memory. By default the description of memory regions is
|
||||
fetched from the target (if the current target supports this), but the
|
||||
user can override the fetched regions.
|
||||
|
||||
Defined memory regions can be individually enabled and disabled. When a
|
||||
memory region is disabled, @value{GDBN} uses the default attributes when
|
||||
|
@ -6742,6 +6745,10 @@ monitored by @value{GDBN}. Note that @var{upper} == 0 is a special
|
|||
case: it is treated as the the target's maximum memory address.
|
||||
(0xffff on 16 bit targets, 0xffffffff on 32 bit targets, etc.)
|
||||
|
||||
@item mem auto
|
||||
Discard any user changes to the memory regions and use target-supplied
|
||||
regions, if available, or no regions if the target does not support.
|
||||
|
||||
@kindex delete mem
|
||||
@item delete mem @var{nums}@dots{}
|
||||
Remove memory regions @var{nums}@dots{} from the list of regions
|
||||
|
|
|
@ -71,6 +71,9 @@ enum errors {
|
|||
more detail. */
|
||||
TLS_GENERIC_ERROR,
|
||||
|
||||
/* Problem parsing an XML document. */
|
||||
XML_PARSE_ERROR,
|
||||
|
||||
/* Add more errors here. */
|
||||
NR_ERRORS
|
||||
};
|
||||
|
|
|
@ -468,6 +468,10 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main)
|
|||
kill_if_already_running (from_tty);
|
||||
clear_breakpoint_hit_counts ();
|
||||
|
||||
/* Clean up any leftovers from other runs. Some other things from
|
||||
this function should probably be moved into target_pre_inferior. */
|
||||
target_pre_inferior (from_tty);
|
||||
|
||||
/* Purge old solib objfiles. */
|
||||
objfile_purge_solibs ();
|
||||
|
||||
|
@ -1847,6 +1851,10 @@ attach_command (char *args, int from_tty)
|
|||
error (_("Not killed."));
|
||||
}
|
||||
|
||||
/* Clean up any leftovers from other runs. Some other things from
|
||||
this function should probably be moved into target_pre_inferior. */
|
||||
target_pre_inferior (from_tty);
|
||||
|
||||
/* Clear out solib state. Otherwise the solib state of the previous
|
||||
inferior might have survived and is entirely wrong for the new
|
||||
target. This has been observed on Linux using glibc 2.3. How to
|
||||
|
|
170
gdb/memattr.c
170
gdb/memattr.c
|
@ -36,12 +36,23 @@ const struct mem_attrib default_mem_attrib =
|
|||
MEM_WIDTH_UNSPECIFIED,
|
||||
0, /* hwbreak */
|
||||
0, /* cache */
|
||||
0 /* verify */
|
||||
0, /* verify */
|
||||
-1 /* Flash blocksize not specified. */
|
||||
};
|
||||
|
||||
VEC(mem_region_s) *mem_region_list;
|
||||
VEC(mem_region_s) *mem_region_list, *target_mem_region_list;
|
||||
static int mem_number = 0;
|
||||
|
||||
/* If this flag is set, the memory region list should be automatically
|
||||
updated from the target. If it is clear, the list is user-controlled
|
||||
and should be left alone. */
|
||||
static int mem_use_target = 1;
|
||||
|
||||
/* If this flag is set, we have tried to fetch the target memory regions
|
||||
since the last time it was invalidated. If that list is still
|
||||
empty, then the target can't supply memory regions. */
|
||||
static int target_mem_regions_valid;
|
||||
|
||||
/* Predicate function which returns true if LHS should sort before RHS
|
||||
in a list of memory regions, useful for VEC_lower_bound. */
|
||||
|
||||
|
@ -52,6 +63,84 @@ mem_region_lessthan (const struct mem_region *lhs,
|
|||
return lhs->lo < rhs->lo;
|
||||
}
|
||||
|
||||
/* A helper function suitable for qsort, used to sort a
|
||||
VEC(mem_region_s) by starting address. */
|
||||
|
||||
int
|
||||
mem_region_cmp (const void *untyped_lhs, const void *untyped_rhs)
|
||||
{
|
||||
const struct mem_region *lhs = untyped_lhs;
|
||||
const struct mem_region *rhs = untyped_rhs;
|
||||
|
||||
if (lhs->lo < rhs->lo)
|
||||
return -1;
|
||||
else if (lhs->lo == rhs->lo)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Allocate a new memory region, with default settings. */
|
||||
|
||||
void
|
||||
mem_region_init (struct mem_region *new)
|
||||
{
|
||||
memset (new, 0, sizeof (struct mem_region));
|
||||
new->enabled_p = 1;
|
||||
new->attrib = default_mem_attrib;
|
||||
}
|
||||
|
||||
/* This function should be called before any command which would
|
||||
modify the memory region list. It will handle switching from
|
||||
a target-provided list to a local list, if necessary. */
|
||||
|
||||
static void
|
||||
require_user_regions (int from_tty)
|
||||
{
|
||||
struct mem_region *m;
|
||||
int ix, length;
|
||||
|
||||
/* If we're already using a user-provided list, nothing to do. */
|
||||
if (!mem_use_target)
|
||||
return;
|
||||
|
||||
/* Switch to a user-provided list (possibly a copy of the current
|
||||
one). */
|
||||
mem_use_target = 0;
|
||||
|
||||
/* If we don't have a target-provided region list yet, then
|
||||
no need to warn. */
|
||||
if (mem_region_list == NULL)
|
||||
return;
|
||||
|
||||
/* Otherwise, let the user know how to get back. */
|
||||
if (from_tty)
|
||||
warning (_("Switching to manual control of memory regions; use "
|
||||
"\"mem auto\" to fetch regions from the target again."));
|
||||
|
||||
/* And create a new list for the user to modify. */
|
||||
length = VEC_length (mem_region_s, target_mem_region_list);
|
||||
mem_region_list = VEC_alloc (mem_region_s, length);
|
||||
for (ix = 0; VEC_iterate (mem_region_s, target_mem_region_list, ix, m); ix++)
|
||||
VEC_quick_push (mem_region_s, mem_region_list, m);
|
||||
}
|
||||
|
||||
/* This function should be called before any command which would
|
||||
read the memory region list, other than those which call
|
||||
require_user_regions. It will handle fetching the
|
||||
target-provided list, if necessary. */
|
||||
|
||||
static void
|
||||
require_target_regions (void)
|
||||
{
|
||||
if (mem_use_target && !target_mem_regions_valid)
|
||||
{
|
||||
target_mem_regions_valid = 1;
|
||||
target_mem_region_list = target_memory_map ();
|
||||
mem_region_list = target_mem_region_list;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
create_mem_region (CORE_ADDR lo, CORE_ADDR hi,
|
||||
const struct mem_attrib *attrib)
|
||||
|
@ -66,6 +155,7 @@ create_mem_region (CORE_ADDR lo, CORE_ADDR hi,
|
|||
return;
|
||||
}
|
||||
|
||||
mem_region_init (&new);
|
||||
new.lo = lo;
|
||||
new.hi = hi;
|
||||
|
||||
|
@ -96,7 +186,6 @@ create_mem_region (CORE_ADDR lo, CORE_ADDR hi,
|
|||
}
|
||||
|
||||
new.number = ++mem_number;
|
||||
new.enabled_p = 1;
|
||||
new.attrib = *attrib;
|
||||
VEC_safe_insert (mem_region_s, mem_region_list, ix, &new);
|
||||
}
|
||||
|
@ -113,6 +202,8 @@ lookup_mem_region (CORE_ADDR addr)
|
|||
CORE_ADDR hi;
|
||||
int ix;
|
||||
|
||||
require_target_regions ();
|
||||
|
||||
/* 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
|
||||
|
@ -148,6 +239,31 @@ lookup_mem_region (CORE_ADDR addr)
|
|||
region.attrib = default_mem_attrib;
|
||||
return ®ion;
|
||||
}
|
||||
|
||||
/* Invalidate any memory regions fetched from the target. */
|
||||
|
||||
void
|
||||
invalidate_target_mem_regions (void)
|
||||
{
|
||||
struct mem_region *m;
|
||||
int ix;
|
||||
|
||||
if (!target_mem_regions_valid)
|
||||
return;
|
||||
|
||||
target_mem_regions_valid = 0;
|
||||
VEC_free (mem_region_s, target_mem_region_list);
|
||||
if (mem_use_target)
|
||||
mem_region_list = NULL;
|
||||
}
|
||||
|
||||
/* Clear memory region list */
|
||||
|
||||
static void
|
||||
mem_clear (void)
|
||||
{
|
||||
VEC_free (mem_region_s, mem_region_list);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
|
@ -160,6 +276,24 @@ mem_command (char *args, int from_tty)
|
|||
if (!args)
|
||||
error_no_arg (_("No mem"));
|
||||
|
||||
/* For "mem auto", switch back to using a target provided list. */
|
||||
if (strcmp (args, "auto") == 0)
|
||||
{
|
||||
if (mem_use_target)
|
||||
return;
|
||||
|
||||
if (mem_region_list != target_mem_region_list)
|
||||
{
|
||||
mem_clear ();
|
||||
mem_region_list = target_mem_region_list;
|
||||
}
|
||||
|
||||
mem_use_target = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
require_user_regions (from_tty);
|
||||
|
||||
tok = strtok (args, " \t");
|
||||
if (!tok)
|
||||
error (_("no lo address"));
|
||||
|
@ -235,6 +369,13 @@ mem_info_command (char *args, int from_tty)
|
|||
struct mem_attrib *attrib;
|
||||
int ix;
|
||||
|
||||
if (mem_use_target)
|
||||
printf_filtered (_("Using memory regions provided by the target.\n"));
|
||||
else
|
||||
printf_filtered (_("Using user-defined memory regions.\n"));
|
||||
|
||||
require_target_regions ();
|
||||
|
||||
if (!mem_region_list)
|
||||
{
|
||||
printf_unfiltered (_("There are no memory regions defined.\n"));
|
||||
|
@ -306,6 +447,9 @@ mem_info_command (char *args, int from_tty)
|
|||
case MEM_WO:
|
||||
printf_filtered ("wo ");
|
||||
break;
|
||||
case MEM_FLASH:
|
||||
printf_filtered ("flash blocksize 0x%x ", attrib->blocksize);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (attrib->width)
|
||||
|
@ -378,6 +522,8 @@ mem_enable_command (char *args, int from_tty)
|
|||
struct mem_region *m;
|
||||
int ix;
|
||||
|
||||
require_user_regions (from_tty);
|
||||
|
||||
dcache_invalidate (target_dcache);
|
||||
|
||||
if (p == 0)
|
||||
|
@ -430,6 +576,8 @@ mem_disable_command (char *args, int from_tty)
|
|||
struct mem_region *m;
|
||||
int ix;
|
||||
|
||||
require_user_regions (from_tty);
|
||||
|
||||
dcache_invalidate (target_dcache);
|
||||
|
||||
if (p == 0)
|
||||
|
@ -455,14 +603,6 @@ mem_disable_command (char *args, int from_tty)
|
|||
}
|
||||
}
|
||||
|
||||
/* Clear memory region list */
|
||||
|
||||
static void
|
||||
mem_clear (void)
|
||||
{
|
||||
VEC_free (mem_region_s, mem_region_list);
|
||||
}
|
||||
|
||||
/* Delete the memory region number NUM. */
|
||||
|
||||
static void
|
||||
|
@ -497,6 +637,8 @@ mem_delete_command (char *args, int from_tty)
|
|||
char *p1;
|
||||
int num;
|
||||
|
||||
require_user_regions (from_tty);
|
||||
|
||||
dcache_invalidate (target_dcache);
|
||||
|
||||
if (p == 0)
|
||||
|
@ -532,8 +674,10 @@ void
|
|||
_initialize_mem (void)
|
||||
{
|
||||
add_com ("mem", class_vars, mem_command, _("\
|
||||
Define attributes for memory region.\n\
|
||||
Usage: mem <lo addr> <hi addr> [<mode> <width> <cache>], \n\
|
||||
Define attributes for memory region or reset memory region handling to\n\
|
||||
target-based.\n\
|
||||
Usage: mem auto\n\
|
||||
mem <lo addr> <hi addr> [<mode> <width> <cache>], \n\
|
||||
where <mode> may be rw (read/write), ro (read-only) or wo (write-only), \n\
|
||||
<width> may be 8, 16, 32, or 64, and \n\
|
||||
<cache> may be cache or nocache"));
|
||||
|
|
|
@ -28,7 +28,10 @@ enum mem_access_mode
|
|||
{
|
||||
MEM_RW, /* read/write */
|
||||
MEM_RO, /* read only */
|
||||
MEM_WO /* write only */
|
||||
MEM_WO, /* write only */
|
||||
|
||||
/* Read/write, but special steps are required to write to it. */
|
||||
MEM_FLASH
|
||||
};
|
||||
|
||||
enum mem_access_width
|
||||
|
@ -66,6 +69,9 @@ struct mem_attrib
|
|||
/* enables memory verification. after a write, memory is re-read
|
||||
to verify that the write was successful. */
|
||||
int verify;
|
||||
|
||||
/* Block size. Only valid if mode == MEM_FLASH. */
|
||||
int blocksize;
|
||||
};
|
||||
|
||||
struct mem_region
|
||||
|
@ -91,4 +97,10 @@ DEF_VEC_O(mem_region_s);
|
|||
|
||||
extern struct mem_region *lookup_mem_region(CORE_ADDR);
|
||||
|
||||
void invalidate_target_mem_regions (void);
|
||||
|
||||
void mem_region_init (struct mem_region *);
|
||||
|
||||
int mem_region_cmp (const void *, const void *);
|
||||
|
||||
#endif /* MEMATTR_H */
|
||||
|
|
273
gdb/memory-map.c
Normal file
273
gdb/memory-map.c
Normal file
|
@ -0,0 +1,273 @@
|
|||
/* 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 "gdb_string.h"
|
||||
|
||||
#if !defined(HAVE_LIBEXPAT)
|
||||
|
||||
VEC(mem_region_s) *
|
||||
parse_memory_map (const char *memory_map)
|
||||
{
|
||||
static int have_warned;
|
||||
|
||||
if (!have_warned)
|
||||
{
|
||||
have_warned = 1;
|
||||
warning (_("Can not parse XML memory map; XML support was disabled "
|
||||
"at compile time"));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else /* HAVE_LIBEXPAT */
|
||||
|
||||
#include "xml-support.h"
|
||||
#include <expat.h>
|
||||
|
||||
/* Internal parsing data passed to all Expat callbacks. */
|
||||
struct memory_map_parsing_data
|
||||
{
|
||||
VEC(mem_region_s) **memory_map;
|
||||
struct mem_region *currently_parsing;
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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 a new memory region and initializes it
|
||||
from attributes. Sets DATA_.currently_parsing 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)
|
||||
{
|
||||
static const XML_Char *type_names[] = {"ram", "rom", "flash", 0};
|
||||
static int type_values[] = { MEM_RW, MEM_RO, MEM_FLASH };
|
||||
struct memory_map_parsing_data *data = data_;
|
||||
struct gdb_exception ex;
|
||||
|
||||
TRY_CATCH (ex, RETURN_MASK_ERROR)
|
||||
{
|
||||
if (strcmp (name, "memory") == 0)
|
||||
{
|
||||
struct mem_region *r;
|
||||
|
||||
r = VEC_safe_push (mem_region_s, *data->memory_map, NULL);
|
||||
mem_region_init (r);
|
||||
|
||||
r->lo = xml_get_integer_attribute (attrs, "start");
|
||||
r->hi = r->lo + xml_get_integer_attribute (attrs, "length");
|
||||
r->attrib.mode = xml_get_enum_value (attrs, "type", type_names,
|
||||
type_values);
|
||||
r->attrib.blocksize = -1;
|
||||
|
||||
data->currently_parsing = r;
|
||||
}
|
||||
else if (strcmp (name, "property") == 0)
|
||||
{
|
||||
if (!data->currently_parsing)
|
||||
throw_error (XML_PARSE_ERROR,
|
||||
_("memory map: found 'property' element outside 'memory'"));
|
||||
|
||||
data->capture_text = 1;
|
||||
|
||||
data->property_name = xml_get_required_attribute (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 a pointer
|
||||
to our memory_map_parsing_data. NAME is the name of the element.
|
||||
|
||||
This function handles the following elements:
|
||||
- 'property' -- check that the property name is 'blocksize' and
|
||||
sets DATA->currently_parsing->attrib.blocksize
|
||||
- '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_PARSE_ERROR,
|
||||
_("Empty content of 'property' element"));
|
||||
char *end = NULL;
|
||||
data->currently_parsing->attrib.blocksize
|
||||
= strtoul (data->character_data, &end, 0);
|
||||
if (*end != '\0')
|
||||
throw_error (XML_PARSE_ERROR,
|
||||
_("Invalid content of the 'blocksize' property"));
|
||||
}
|
||||
else
|
||||
throw_error (XML_PARSE_ERROR,
|
||||
_("Unknown memory region property: %s"), name);
|
||||
|
||||
data->capture_text = 0;
|
||||
}
|
||||
else if (strcmp (name, "memory") == 0)
|
||||
{
|
||||
if (data->currently_parsing->attrib.mode == MEM_FLASH
|
||||
&& data->currently_parsing->attrib.blocksize == -1)
|
||||
throw_error (XML_PARSE_ERROR,
|
||||
_("Flash block size is not set"));
|
||||
|
||||
data->currently_parsing = 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 = xmalloc (len + 1);
|
||||
else
|
||||
{
|
||||
current_size = strlen (data->character_data);
|
||||
data->character_data = xrealloc (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(mem_region_s) **result = p;
|
||||
VEC_free (mem_region_s, *result);
|
||||
*result = NULL;
|
||||
}
|
||||
|
||||
VEC(mem_region_s) *
|
||||
parse_memory_map (const char *memory_map)
|
||||
{
|
||||
VEC(mem_region_s) *result = NULL;
|
||||
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_free_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_PARSE_ERROR, "%s", XML_ErrorString (err));
|
||||
}
|
||||
}
|
||||
if (ex.reason != GDB_NO_ERROR)
|
||||
{
|
||||
if (ex.error == XML_PARSE_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 the result. */
|
||||
discard_cleanups (before_deleting_result);
|
||||
|
||||
out:
|
||||
do_cleanups (back_to);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBEXPAT */
|
34
gdb/memory-map.h
Normal file
34
gdb/memory-map.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* 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 "memattr.h"
|
||||
|
||||
/* 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(mem_region_s) *parse_memory_map (const char *memory_map);
|
||||
|
||||
#endif
|
34
gdb/remote.c
34
gdb/remote.c
|
@ -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
|
||||
|
@ -826,6 +828,7 @@ enum {
|
|||
PACKET_Z3,
|
||||
PACKET_Z4,
|
||||
PACKET_qXfer_auxv,
|
||||
PACKET_qXfer_memory_map,
|
||||
PACKET_qGetTLSAddr,
|
||||
PACKET_qSupported,
|
||||
PACKET_MAX
|
||||
|
@ -2172,7 +2175,9 @@ remote_packet_size (const struct protocol_feature *feature,
|
|||
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
|
||||
|
@ -5312,6 +5317,11 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
|
|||
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;
|
||||
}
|
||||
|
@ -5422,6 +5432,23 @@ remote_rcmd (char *command,
|
|||
}
|
||||
}
|
||||
|
||||
static VEC(mem_region_s) *
|
||||
remote_memory_map (struct target_ops *ops)
|
||||
{
|
||||
VEC(mem_region_s) *result = NULL;
|
||||
char *text = target_read_stralloc (¤t_target,
|
||||
TARGET_OBJECT_MEMORY_MAP, NULL);
|
||||
|
||||
if (text)
|
||||
{
|
||||
struct cleanup *back_to = make_cleanup (xfree, text);
|
||||
result = parse_memory_map (text);
|
||||
do_cleanups (back_to);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
packet_command (char *args, int from_tty)
|
||||
{
|
||||
|
@ -5694,6 +5721,7 @@ Specify the serial device it is connected to\n\
|
|||
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
|
||||
|
@ -5823,6 +5851,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
|
|||
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
|
||||
|
@ -6063,6 +6092,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
|
|||
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);
|
||||
|
|
63
gdb/target.c
63
gdb/target.c
|
@ -464,6 +464,7 @@ update_current_target (void)
|
|||
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
|
||||
|
||||
|
@ -1040,6 +1041,54 @@ target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, int len)
|
|||
return EIO;
|
||||
}
|
||||
|
||||
/* Fetch the target's memory map. */
|
||||
|
||||
VEC(mem_region_s) *
|
||||
target_memory_map (void)
|
||||
{
|
||||
VEC(mem_region_s) *result;
|
||||
struct mem_region *last_one, *this_one;
|
||||
int ix;
|
||||
struct target_ops *t;
|
||||
|
||||
if (targetdebug)
|
||||
fprintf_unfiltered (gdb_stdlog, "target_memory_map ()\n");
|
||||
|
||||
for (t = current_target.beneath; t != NULL; t = t->beneath)
|
||||
if (t->to_memory_map != NULL)
|
||||
break;
|
||||
|
||||
if (t == NULL)
|
||||
return NULL;
|
||||
|
||||
result = t->to_memory_map (t);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
qsort (VEC_address (mem_region_s, result),
|
||||
VEC_length (mem_region_s, result),
|
||||
sizeof (struct mem_region), mem_region_cmp);
|
||||
|
||||
/* Check that regions do not overlap. Simultaneously assign
|
||||
a numbering for the "mem" commands to use to refer to
|
||||
each region. */
|
||||
last_one = NULL;
|
||||
for (ix = 0; VEC_iterate (mem_region_s, result, ix, this_one); ix++)
|
||||
{
|
||||
this_one->number = ix;
|
||||
|
||||
if (last_one && last_one->hi > this_one->lo)
|
||||
{
|
||||
warning (_("Overlapping regions in memory map: ignoring"));
|
||||
VEC_free (mem_region_s, result);
|
||||
return NULL;
|
||||
}
|
||||
last_one = this_one;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef target_stopped_data_address_p
|
||||
int
|
||||
target_stopped_data_address_p (struct target_ops *target)
|
||||
|
@ -1356,6 +1405,18 @@ target_info (char *args, int from_tty)
|
|||
}
|
||||
}
|
||||
|
||||
/* This function is called before any new inferior is created, e.g.
|
||||
by running a program, attaching, or connecting to a target.
|
||||
It cleans up any state from previous invocations which might
|
||||
change between runs. This is a subset of what target_preopen
|
||||
resets (things which might change between targets). */
|
||||
|
||||
void
|
||||
target_pre_inferior (int from_tty)
|
||||
{
|
||||
invalidate_target_mem_regions ();
|
||||
}
|
||||
|
||||
/* This is to be called by the open routine before it does
|
||||
anything. */
|
||||
|
||||
|
@ -1378,6 +1439,8 @@ target_preopen (int from_tty)
|
|||
|
||||
if (target_has_execution)
|
||||
pop_target ();
|
||||
|
||||
target_pre_inferior (from_tty);
|
||||
}
|
||||
|
||||
/* Detach a target after doing deferred register stores. */
|
||||
|
|
27
gdb/target.h
27
gdb/target.h
|
@ -55,6 +55,7 @@ struct bp_target_info;
|
|||
#include "symtab.h"
|
||||
#include "dcache.h"
|
||||
#include "memattr.h"
|
||||
#include "vec.h"
|
||||
|
||||
enum strata
|
||||
{
|
||||
|
@ -198,7 +199,9 @@ enum target_object
|
|||
/* 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, ... */
|
||||
};
|
||||
|
@ -453,6 +456,21 @@ struct target_ops
|
|||
gdb_byte *readbuf, const gdb_byte *writebuf,
|
||||
ULONGEST offset, LONGEST len);
|
||||
|
||||
/* Returns the memory map for the target. A return value of NULL
|
||||
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; target_memory_map will
|
||||
sort regions by starting address. For that reason, this
|
||||
function should not be called directly except via
|
||||
target_memory_map.
|
||||
|
||||
This method should not cache data; if the memory map could
|
||||
change unexpectedly, it should be invalidated, and higher
|
||||
layers will re-fetch it. */
|
||||
VEC(mem_region_s) *(*to_memory_map) (struct target_ops *);
|
||||
|
||||
int to_magic;
|
||||
/* Need sub-structure for target machine related rather than comm related?
|
||||
*/
|
||||
|
@ -576,6 +594,11 @@ extern int xfer_memory (CORE_ADDR, gdb_byte *, int, int,
|
|||
extern int child_xfer_memory (CORE_ADDR, gdb_byte *, int, int,
|
||||
struct mem_attrib *, struct target_ops *);
|
||||
|
||||
/* Fetches the target's memory map. If one is found it is sorted
|
||||
and returned, after some consistency checking. Otherwise, NULL
|
||||
is returned. */
|
||||
VEC(mem_region_s) *target_memory_map (void);
|
||||
|
||||
extern char *child_pid_to_exec_file (int);
|
||||
|
||||
extern char *child_core_file_to_sym_file (char *);
|
||||
|
@ -1127,6 +1150,8 @@ extern int push_target (struct target_ops *);
|
|||
|
||||
extern int unpush_target (struct target_ops *);
|
||||
|
||||
extern void target_pre_inferior (int);
|
||||
|
||||
extern void target_preopen (int);
|
||||
|
||||
extern void pop_target (void);
|
||||
|
|
146
gdb/xml-support.c
Normal file
146
gdb/xml-support.c
Normal file
|
@ -0,0 +1,146 @@
|
|||
/* Helper routines for parsing XML using Expat.
|
||||
|
||||
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"
|
||||
|
||||
/* The contents of this file are only useful if XML support is
|
||||
available. */
|
||||
#ifdef HAVE_LIBEXPAT
|
||||
|
||||
#include "exceptions.h"
|
||||
#include "xml-support.h"
|
||||
|
||||
#include <expat.h>
|
||||
|
||||
#include "gdb_string.h"
|
||||
|
||||
/* Returns the value of attribute ATTR from expat attribute list
|
||||
ATTRLIST. If not found, throws an exception. */
|
||||
|
||||
const XML_Char *
|
||||
xml_get_required_attribute (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_PARSE_ERROR, _("Can't find attribute %s"), attr);
|
||||
}
|
||||
|
||||
/* Parse a field VALSTR that we expect to contain an integer value.
|
||||
The integer is returned in *VALP. The string is parsed with an
|
||||
equivalent to strtoul.
|
||||
|
||||
Returns 0 for success, -1 for error. */
|
||||
|
||||
static int
|
||||
xml_parse_unsigned_integer (const char *valstr, ULONGEST *valp)
|
||||
{
|
||||
const char *endptr;
|
||||
ULONGEST result;
|
||||
|
||||
if (*valstr == '\0')
|
||||
return -1;
|
||||
|
||||
result = strtoulst (valstr, &endptr, 0);
|
||||
if (*endptr != '\0')
|
||||
return -1;
|
||||
|
||||
*valp = result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Gets the value of an integer attribute named ATTR, if it's present.
|
||||
If the attribute is not found, or can't be parsed as integer,
|
||||
throws an exception. */
|
||||
|
||||
ULONGEST
|
||||
xml_get_integer_attribute (const XML_Char **attrs,
|
||||
const XML_Char *attr)
|
||||
{
|
||||
ULONGEST result;
|
||||
const XML_Char *value = xml_get_required_attribute (attrs, attr);
|
||||
|
||||
if (xml_parse_unsigned_integer (value, &result) != 0)
|
||||
{
|
||||
throw_error (XML_PARSE_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. */
|
||||
|
||||
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_required_attribute (attrs, attr);
|
||||
|
||||
int i;
|
||||
for (i = 0; xml_names[i]; ++i)
|
||||
{
|
||||
if (strcmp (xml_names[i], value) == 0)
|
||||
return values[i];
|
||||
}
|
||||
throw_error (XML_PARSE_ERROR,
|
||||
_("Invalid enumerated value in XML: %s"), value);
|
||||
}
|
||||
|
||||
/* Cleanup wrapper for XML_ParserFree, with the correct type
|
||||
for make_cleanup. */
|
||||
|
||||
static void
|
||||
free_xml_parser (void *parser)
|
||||
{
|
||||
XML_ParserFree (parser);
|
||||
}
|
||||
|
||||
/* Register a cleanup to release PARSER. Only the parser itself
|
||||
is freed; another cleanup may be necessary to discard any
|
||||
associated user data. */
|
||||
|
||||
void
|
||||
make_cleanup_free_xml_parser (XML_Parser parser)
|
||||
{
|
||||
make_cleanup (free_xml_parser, parser);
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBEXPAT */
|
45
gdb/xml-support.h
Normal file
45
gdb/xml-support.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* Helper routines for parsing XML using Expat.
|
||||
|
||||
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 XML_SUPPORT_H
|
||||
#define XML_SUPPORT_H
|
||||
|
||||
#include <expat.h>
|
||||
|
||||
/* Helper functions for parsing XML documents. See xml-support.c
|
||||
for more information about these functions. */
|
||||
|
||||
const XML_Char *xml_get_required_attribute (const XML_Char **attrs,
|
||||
const XML_Char *attr);
|
||||
|
||||
ULONGEST xml_get_integer_attribute (const XML_Char **attrs,
|
||||
const XML_Char *attr);
|
||||
|
||||
int xml_get_enum_value (const XML_Char **attrs,
|
||||
const XML_Char *attr,
|
||||
const XML_Char **xml_names,
|
||||
int *values);
|
||||
|
||||
void make_cleanup_free_xml_parser (XML_Parser parser);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue