* Makefile.in (arm-tdep.o, eval.o, target-descriptions.o)

(xml-tdesc.o): Update.
	* xml-support.c: Add a comment.
	(gdb_xml_enums_boolean): New variable.
	(gdb_xml_parse_attr_enum): Use strcasecmp.
	* xml-support.h (gdb_xml_enums_boolean): Declare.
	* xml-tdesc.c (struct tdesc_parsing_data): Record current_feature,
	next_regnum, and current_union.
	(tdesc_start_feature, tdesc_start_reg, tdesc_start_union)
	(tdesc_end_union, tdesc_start_field, tdesc_start_vector)
	(field_attributes, union_children, reg_attributes, union_attributes)
	(vector_attributes, feature_attributes, feature_children): New.
	(target_children): Make static.  Add <feature>.
	(tdesc_elements): Make static.
	* target-descriptions.c (struct tdesc_reg, tdesc_reg_p, type_p)
	(struct tdesc_feature, tdesc_feature_p): New types.
	(struct target_desc): Add features member.
	(struct tdesc_arch_data, tdesc_data): New.
	(target_find_description): Clarify error message.  Warn about
	ignored register descriptions.
	(tdesc_has_registers, tdesc_find_feature, tdesc_feature_name)
	(tdesc_named_type, tdesc_data_init, tdesc_data_alloc)
	(tdesc_data_cleanup, tdesc_numbered_register)
	(tdesc_numbered_register_choices, tdesc_find_register)
	(tdesc_register_name, tdesc_register_type)
	(tdesc_remote_register_number, tdesc_register_reggroup_p)
	(set_tdesc_pseudo_register_name, set_tdesc_pseudo_register_type)
	(set_tdesc_pseudo_register_reggroup_p, tdesc_use_registers)
	(tdesc_free_reg, tdesc_create_reg, tdesc_free_feature)
	(tdesc_create_feature, tdesc_record_type): New.
	(free_target_description): Free features.
	(_initialize_target_descriptions): Initialize tdesc_data.
	* arch-utils.c (default_remote_register_number): New.
	* arch-utils.h (default_remote_register_number): New prototype.
	* target-descriptions.h (set_tdesc_pseudo_register_name)
	(set_tdesc_pseudo_register_type, set_tdesc_pseudo_register_reggroup_p)
	(tdesc_use_registers, tdesc_data_alloc, tdesc_data_cleanup)
	(tdesc_numbered_register, tdesc_numbered_register_choices)
	(tdesc_has_registers, tdesc_find_feature, tdesc_feature_name)
	(tdesc_named_type, tdesc_create_feature, tdesc_record_type)
	(tdesc_create_reg): Declare.
	* gdbarch.sh (remote_register_number): New entry.
	* gdbarch.c, gdbarch.h: Regenerate.
	* remote.c (init_remote_state): Use gdbarch_remote_register_number.
	* features/gdb-target.dtd: Add feature, reg, vector, union, and field.

	* arm-tdep.c (arm_register_aliases): New.
	(arm_register_name_strings): Rename to...
	(arm_register_names): ...this.  Make const.  Delete the old version.
	(current_option, arm_register_byte): Delete.
	(set_disassembly_style): Simplify.  Do not adjust arm_register_names.
	(value_of_arm_user_reg): New.
	(arm_gdbarch_init): Verify any described registers.  Call
	tdesc_use_registers.  Don't use arm_register_byte.  Create aliases
	for standard register names.
	(_initialize_arm_tdep): Do not adjust arm_register_names.
	* user-regs.c (struct user_reg): Add baton member.
	(append_user_reg, user_reg_add_builtin, user_regs_init)
	(user_reg_add, value_of_user_reg): Use a baton for user
	register functions.
	* std-regs.c: Update.
	* user-regs.h (user_reg_read_ftype, user_reg_add_builtin)
	(user_reg_add): Add baton argument.
	* NEWS: Mention target description register support.
	* features/arm-core.xml, features/arm-fpa.xml: New.
	* eval.c (evaluate_subexp_standard): Allow ptype $register
	when the program is not running.

	* gdb.texinfo (-target-disconnect): Use @smallexample.
	(Requirements): Add anchor for Expat.  Update description.
	(Target Descriptions): Mention Expat.
	(Target Description Format): Document new elements.  Use
	@smallexample.
	(Predefined Target Types, Standard Target Features): New sections.
	* doc/gdbint.texinfo (Target Descriptions): New section.

	* gdb.xml/single-reg.xml, gdb.xml/tdesc-regs.exp,
	gdb.xml/core-only.xml, gdb.xml/extra-regs.xml: New files.
This commit is contained in:
Daniel Jacobowitz 2007-02-08 21:00:36 +00:00
parent 1183581f7f
commit 123dc83914
30 changed files with 1857 additions and 114 deletions

View File

@ -1,3 +1,73 @@
2007-02-08 Daniel Jacobowitz <dan@codesourcery.com>
* Makefile.in (arm-tdep.o, eval.o, target-descriptions.o)
(xml-tdesc.o): Update.
* xml-support.c: Add a comment.
(gdb_xml_enums_boolean): New variable.
(gdb_xml_parse_attr_enum): Use strcasecmp.
* xml-support.h (gdb_xml_enums_boolean): Declare.
* xml-tdesc.c (struct tdesc_parsing_data): Record current_feature,
next_regnum, and current_union.
(tdesc_start_feature, tdesc_start_reg, tdesc_start_union)
(tdesc_end_union, tdesc_start_field, tdesc_start_vector)
(field_attributes, union_children, reg_attributes, union_attributes)
(vector_attributes, feature_attributes, feature_children): New.
(target_children): Make static. Add <feature>.
(tdesc_elements): Make static.
* target-descriptions.c (struct tdesc_reg, tdesc_reg_p, type_p)
(struct tdesc_feature, tdesc_feature_p): New types.
(struct target_desc): Add features member.
(struct tdesc_arch_data, tdesc_data): New.
(target_find_description): Clarify error message. Warn about
ignored register descriptions.
(tdesc_has_registers, tdesc_find_feature, tdesc_feature_name)
(tdesc_named_type, tdesc_data_init, tdesc_data_alloc)
(tdesc_data_cleanup, tdesc_numbered_register)
(tdesc_numbered_register_choices, tdesc_find_register)
(tdesc_register_name, tdesc_register_type)
(tdesc_remote_register_number, tdesc_register_reggroup_p)
(set_tdesc_pseudo_register_name, set_tdesc_pseudo_register_type)
(set_tdesc_pseudo_register_reggroup_p, tdesc_use_registers)
(tdesc_free_reg, tdesc_create_reg, tdesc_free_feature)
(tdesc_create_feature, tdesc_record_type): New.
(free_target_description): Free features.
(_initialize_target_descriptions): Initialize tdesc_data.
* arch-utils.c (default_remote_register_number): New.
* arch-utils.h (default_remote_register_number): New prototype.
* target-descriptions.h (set_tdesc_pseudo_register_name)
(set_tdesc_pseudo_register_type, set_tdesc_pseudo_register_reggroup_p)
(tdesc_use_registers, tdesc_data_alloc, tdesc_data_cleanup)
(tdesc_numbered_register, tdesc_numbered_register_choices)
(tdesc_has_registers, tdesc_find_feature, tdesc_feature_name)
(tdesc_named_type, tdesc_create_feature, tdesc_record_type)
(tdesc_create_reg): Declare.
* gdbarch.sh (remote_register_number): New entry.
* gdbarch.c, gdbarch.h: Regenerate.
* remote.c (init_remote_state): Use gdbarch_remote_register_number.
* features/gdb-target.dtd: Add feature, reg, vector, union, and field.
* arm-tdep.c (arm_register_aliases): New.
(arm_register_name_strings): Rename to...
(arm_register_names): ...this. Make const. Delete the old version.
(current_option, arm_register_byte): Delete.
(set_disassembly_style): Simplify. Do not adjust arm_register_names.
(value_of_arm_user_reg): New.
(arm_gdbarch_init): Verify any described registers. Call
tdesc_use_registers. Don't use arm_register_byte. Create aliases
for standard register names.
(_initialize_arm_tdep): Do not adjust arm_register_names.
* user-regs.c (struct user_reg): Add baton member.
(append_user_reg, user_reg_add_builtin, user_regs_init)
(user_reg_add, value_of_user_reg): Use a baton for user
register functions.
* std-regs.c: Update.
* user-regs.h (user_reg_read_ftype, user_reg_add_builtin)
(user_reg_add): Add baton argument.
* NEWS: Mention target description register support.
* features/arm-core.xml, features/arm-fpa.xml: New.
* eval.c (evaluate_subexp_standard): Allow ptype $register
when the program is not running.
2007-02-09 Nick Roberts <nickrob@snap.net.nz>
* mi/mi-cmd-var.c (mi_cmd_var_create): Add value field.

View File

@ -1823,7 +1823,8 @@ arm-tdep.o: arm-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(gdbcmd_h) \
$(frame_unwind_h) $(frame_base_h) $(trad_frame_h) $(arm_tdep_h) \
$(gdb_sim_arm_h) $(elf_bfd_h) $(coff_internal_h) $(elf_arm_h) \
$(gdb_assert_h) $(bfd_in2_h) $(libcoff_h) $(objfiles_h) \
$(dwarf2_frame_h) $(gdbtypes_h) $(prologue_value_h)
$(dwarf2_frame_h) $(gdbtypes_h) $(prologue_value_h) \
$(target_descriptions_h) $(user_regs_h)
auxv.o: auxv.c $(defs_h) $(target_h) $(gdbtypes_h) $(command_h) \
$(inferior_h) $(valprint_h) $(gdb_assert_h) $(auxv_h) \
$(elf_common_h)
@ -1986,7 +1987,7 @@ eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \
$(f_lang_h) $(cp_abi_h) $(infcall_h) $(objc_lang_h) $(block_h) \
$(parser_defs_h) $(cp_support_h) $(gdb_assert_h) $(exceptions_h) \
$(uiout_h)
$(uiout_h) $(regcache_h)
event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
$(gdb_string_h) $(exceptions_h) $(gdb_assert_h) $(gdb_select_h)
event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
@ -2793,7 +2794,8 @@ target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \
$(exceptions_h) $(target_descriptions_h)
target-descriptions.o: target-descriptions.c $(defs_h) $(arch_utils_h) \
$(target_h) $(target_descriptions_h) $(vec_h) $(xml_tdesc_h) \
$(gdbcmd_h) $(gdb_assert_h)
$(gdbcmd_h) $(gdb_assert_h) $(gdbtypes_h) $(reggroups_h) \
$(xml_support_h) $(gdb_obstack_h) $(hashtab_h)
target-memory.o: target-memory.c $(defs_h) $(vec_h) $(target_h) \
$(memory_map_h) $(gdb_assert_h)
thread.o: thread.c $(defs_h) $(symtab_h) $(frame_h) $(inferior_h) \
@ -2892,7 +2894,8 @@ xcoffread.o: xcoffread.c $(defs_h) $(bfd_h) $(gdb_string_h) $(gdb_stat_h) \
xcoffsolib.o: xcoffsolib.c $(defs_h) $(bfd_h) $(xcoffsolib_h) $(inferior_h) \
$(gdbcmd_h) $(symfile_h) $(frame_h) $(gdb_regex_h)
xml-tdesc.o: xml-tdesc.c $(defs_h) $(target_h) $(target_descriptions_h) \
$(xml_tdesc_h) $(xml_support_h) $(filenames_h) $(gdb_assert_h)
$(xml_tdesc_h) $(xml_support_h) $(filenames_h) $(gdb_assert_h) \
$(gdbtypes_h)
xml-support.o: xml-support.c $(defs_h) $(xml_support_h) $(exceptions_h) \
$(gdbcmd_h) $(gdb_string_h) $(gdb_expat_h) $(safe_ctype_h)
xstormy16-tdep.o: xstormy16-tdep.c $(defs_h) $(frame_h) $(frame_base_h) \

View File

@ -18,6 +18,10 @@ a local file or over the remote serial protocol.
* Arrays of explicitly SIGNED or UNSIGNED CHARs are now printed as arrays
of numbers.
* Target descriptions can now describe target-specific registers,
for architectures which have implemented the support (currently
only ARM).
* New commands
set mem inaccessible-by-default

View File

@ -263,6 +263,13 @@ generic_instruction_nullified (struct gdbarch *gdbarch,
return 0;
}
int
default_remote_register_number (struct gdbarch *gdbarch,
int regno)
{
return regno;
}
/* Functions to manipulate the endianness of the target. */

View File

@ -109,6 +109,9 @@ extern int default_stabs_argument_has_addr (struct gdbarch *gdbarch,
extern int generic_instruction_nullified (struct gdbarch *gdbarch,
struct regcache *regcache);
int default_remote_register_number (struct gdbarch *gdbarch,
int regno);
/* For compatibility with older architectures, returns
(LEGACY_SIM_REGNO_IGNORE) when the register doesn't have a valid
name. */

View File

@ -41,6 +41,8 @@
#include "dwarf2-frame.h"
#include "gdbtypes.h"
#include "prologue-value.h"
#include "target-descriptions.h"
#include "user-regs.h"
#include "arm-tdep.h"
#include "gdb/sim-arm.h"
@ -103,13 +105,58 @@ static const char *arm_abi_string = "auto";
/* Number of different reg name sets (options). */
static int num_disassembly_options;
/* We have more registers than the disassembler as gdb can print the value
of special registers as well.
The general register names are overwritten by whatever is being used by
the disassembler at the moment. We also adjust the case of cpsr and fps. */
/* The standard register names, and all the valid aliases for them. */
static const struct
{
const char *name;
int regnum;
} arm_register_aliases[] = {
/* Basic register numbers. */
{ "r0", 0 },
{ "r1", 1 },
{ "r2", 2 },
{ "r3", 3 },
{ "r4", 4 },
{ "r5", 5 },
{ "r6", 6 },
{ "r7", 7 },
{ "r8", 8 },
{ "r9", 9 },
{ "r10", 10 },
{ "r11", 11 },
{ "r12", 12 },
{ "r13", 13 },
{ "r14", 14 },
{ "r15", 15 },
/* Synonyms (argument and variable registers). */
{ "a1", 0 },
{ "a2", 1 },
{ "a3", 2 },
{ "a4", 3 },
{ "v1", 4 },
{ "v2", 5 },
{ "v3", 6 },
{ "v4", 7 },
{ "v5", 8 },
{ "v6", 9 },
{ "v7", 10 },
{ "v8", 11 },
/* Other platform-specific names for r9. */
{ "sb", 9 },
{ "tr", 9 },
/* Special names. */
{ "ip", 12 },
{ "sp", 13 },
{ "lr", 14 },
{ "pc", 15 },
/* Names used by GCC (not listed in the ARM EABI). */
{ "sl", 10 },
{ "fp", 11 },
/* A special name from the older ATPCS. */
{ "wr", 7 },
};
/* Initial value: Register names used in ARM's ISA documentation. */
static char * arm_register_name_strings[] =
static const char *const arm_register_names[] =
{"r0", "r1", "r2", "r3", /* 0 1 2 3 */
"r4", "r5", "r6", "r7", /* 4 5 6 7 */
"r8", "r9", "r10", "r11", /* 8 9 10 11 */
@ -117,15 +164,12 @@ static char * arm_register_name_strings[] =
"f0", "f1", "f2", "f3", /* 16 17 18 19 */
"f4", "f5", "f6", "f7", /* 20 21 22 23 */
"fps", "cpsr" }; /* 24 25 */
static char **arm_register_names = arm_register_name_strings;
/* Valid register name styles. */
static const char **valid_disassembly_styles;
/* Disassembly style to use. Default to "std" register names. */
static const char *disassembly_style;
/* Index to that option in the opcodes table. */
static int current_option;
/* This is used to keep the bfd arch_info in sync with the disassembly
style. */
@ -1343,23 +1387,6 @@ arm_register_type (struct gdbarch *gdbarch, int regnum)
return builtin_type_uint32;
}
/* Index within `registers' of the first byte of the space for
register N. */
static int
arm_register_byte (int regnum)
{
if (regnum < ARM_F0_REGNUM)
return regnum * INT_REGISTER_SIZE;
else if (regnum < ARM_PS_REGNUM)
return (NUM_GREGS * INT_REGISTER_SIZE
+ (regnum - ARM_F0_REGNUM) * FP_REGISTER_SIZE);
else
return (NUM_GREGS * INT_REGISTER_SIZE
+ NUM_FREGS * FP_REGISTER_SIZE
+ (regnum - ARM_FPS_REGNUM) * STATUS_REGISTER_SIZE);
}
/* Map GDB internal REGNUM onto the Arm simulator register numbers. */
static int
arm_register_sim_regno (int regnum)
@ -2461,32 +2488,13 @@ arm_register_name (int i)
static void
set_disassembly_style (void)
{
const char *setname, *setdesc, *const *regnames;
int numregs, j;
int current;
/* Find the style that the user wants in the opcodes table. */
int current = 0;
numregs = get_arm_regnames (current, &setname, &setdesc, &regnames);
while ((disassembly_style != setname)
&& (current < num_disassembly_options))
get_arm_regnames (++current, &setname, &setdesc, &regnames);
current_option = current;
/* Fill our copy. */
for (j = 0; j < numregs; j++)
arm_register_names[j] = (char *) regnames[j];
/* Adjust case. */
if (isupper (*regnames[ARM_PC_REGNUM]))
{
arm_register_names[ARM_FPS_REGNUM] = "FPS";
arm_register_names[ARM_PS_REGNUM] = "CPSR";
}
else
{
arm_register_names[ARM_FPS_REGNUM] = "fps";
arm_register_names[ARM_PS_REGNUM] = "cpsr";
}
/* Find the style that the user wants. */
for (current = 0; current < num_disassembly_options; current++)
if (disassembly_style == valid_disassembly_styles[current])
break;
gdb_assert (current < num_disassembly_options);
/* Synchronize the disassembler. */
set_arm_regname_option (current);
@ -2544,6 +2552,13 @@ arm_write_pc (CORE_ADDR pc, ptid_t ptid)
write_register_pid (ARM_PS_REGNUM, val & ~(CORE_ADDR) 0x20, ptid);
}
}
static struct value *
value_of_arm_user_reg (struct frame_info *frame, const void *baton)
{
const int *reg_p = baton;
return value_of_register (*reg_p, frame);
}
static enum gdb_osabi
arm_elf_osabi_sniffer (bfd *abfd)
@ -2580,6 +2595,65 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
struct gdbarch_list *best_arch;
enum arm_abi_kind arm_abi = arm_abi_global;
enum arm_float_model fp_model = arm_fp_model;
struct tdesc_arch_data *tdesc_data = NULL;
int i;
/* Check any target description for validity. */
if (tdesc_has_registers (info.target_desc))
{
/* For most registers we require GDB's default names; but also allow
the numeric names for sp / lr / pc, as a convenience. */
static const char *const arm_sp_names[] = { "r13", "sp", NULL };
static const char *const arm_lr_names[] = { "r14", "lr", NULL };
static const char *const arm_pc_names[] = { "r15", "pc", NULL };
const struct tdesc_feature *feature;
int i, valid_p;
feature = tdesc_find_feature (info.target_desc,
"org.gnu.gdb.arm.core");
if (feature == NULL)
return NULL;
tdesc_data = tdesc_data_alloc ();
valid_p = 1;
for (i = 0; i < ARM_SP_REGNUM; i++)
valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
arm_register_names[i]);
valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
ARM_SP_REGNUM,
arm_sp_names);
valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
ARM_LR_REGNUM,
arm_lr_names);
valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
ARM_PC_REGNUM,
arm_pc_names);
valid_p &= tdesc_numbered_register (feature, tdesc_data,
ARM_PS_REGNUM, "cpsr");
if (!valid_p)
{
tdesc_data_cleanup (tdesc_data);
return NULL;
}
feature = tdesc_find_feature (info.target_desc,
"org.gnu.gdb.arm.fpa");
if (feature != NULL)
{
valid_p = 1;
for (i = ARM_F0_REGNUM; i <= ARM_FPS_REGNUM; i++)
valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
arm_register_names[i]);
if (!valid_p)
{
tdesc_data_cleanup (tdesc_data);
return NULL;
}
}
}
/* If we have an object to base this architecture on, try to determine
its ABI. */
@ -2709,7 +2783,11 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
}
if (best_arch != NULL)
return best_arch->gdbarch;
{
if (tdesc_data != NULL)
tdesc_data_cleanup (tdesc_data);
return best_arch->gdbarch;
}
tdep = xcalloc (1, sizeof (struct gdbarch_tdep));
gdbarch = gdbarch_alloc (&info, tdep);
@ -2784,7 +2862,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_deprecated_fp_regnum (gdbarch, ARM_FP_REGNUM); /* ??? */
set_gdbarch_sp_regnum (gdbarch, ARM_SP_REGNUM);
set_gdbarch_pc_regnum (gdbarch, ARM_PC_REGNUM);
set_gdbarch_deprecated_register_byte (gdbarch, arm_register_byte);
set_gdbarch_num_regs (gdbarch, NUM_GREGS + NUM_FREGS + NUM_SREGS);
set_gdbarch_register_type (gdbarch, arm_register_type);
@ -2842,6 +2919,16 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
}
if (tdesc_data)
tdesc_use_registers (gdbarch, tdesc_data);
/* Add standard register aliases. We add aliases even for those
nanes which are used by the current architecture - it's simpler,
and does no harm, since nothing ever lists user registers. */
for (i = 0; i < ARRAY_SIZE (arm_register_aliases); i++)
user_reg_add (gdbarch, arm_register_aliases[i].name,
value_of_arm_user_reg, &arm_register_aliases[i].regnum);
return gdbarch;
}
@ -2906,13 +2993,11 @@ _initialize_arm_tdep (void)
length = snprintf (rdptr, rest, "%s - %s\n", setname, setdesc);
rdptr += length;
rest -= length;
/* Copy the default names (if found) and synchronize disassembler. */
/* When we find the default names, tell the disassembler to use
them. */
if (!strcmp (setname, "std"))
{
disassembly_style = setname;
current_option = i;
for (j = 0; j < numregs; j++)
arm_register_names[j] = (char *) regnames[j];
set_arm_regname_option (i);
}
}

View File

@ -1,3 +1,13 @@
2007-02-08 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.texinfo (-target-disconnect): Use @smallexample.
(Requirements): Add anchor for Expat. Update description.
(Target Descriptions): Mention Expat.
(Target Description Format): Document new elements. Use
@smallexample.
(Predefined Target Types, Standard Target Features): New sections.
* doc/gdbint.texinfo (Target Descriptions): New section.
2007-02-07 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.texinfo (Target Description Format): Add section on XInclude.

View File

@ -21047,9 +21047,9 @@ The corresponding @value{GDBN} command is @samp{detach}.
@subsubheading Synopsis
@example
@smallexample
-target-disconnect
@end example
@end smallexample
Disconnect from the remote target. There's no output and the target is
generally not resumed.
@ -22222,6 +22222,7 @@ working C90 compiler, e.g.@: GCC.
@heading Tools/packages optional for building @value{GDBN}
@table @asis
@item Expat
@anchor{Expat}
@value{GDBN} can use the Expat XML parsing library. This library may be
included with your operating system distribution; if it is not, you
can get the latest version from @url{http://expat.sourceforge.net}.
@ -22229,8 +22230,8 @@ The @code{configure} script will search for this library in several
standard locations; if it is installed in an unusual path, you can
use the @option{--with-libexpat-prefix} option to specify its location.
Expat is used currently only used to implement some remote-specific
features.
Expat is used for remote protocol memory maps (@pxref{Memory map format})
and for target descriptions (@pxref{Target Descriptions}).
@end table
@ -25738,9 +25739,15 @@ actually describe its own features. This lets @value{GDBN} support
processor variants it has never seen before --- to the extent that the
descriptions are accurate, and that @value{GDBN} understands them.
@value{GDBN} must be compiled with Expat support to support XML target
descriptions. @xref{Expat}.
@menu
* Retrieving Descriptions:: How descriptions are fetched from a target.
* Target Description Format:: The contents of a target description.
* Predefined Target Types:: Standard types available for target
descriptions.
* Standard Target Features:: Features @value{GDBN} knows about.
@end menu
@node Retrieving Descriptions
@ -25787,32 +25794,35 @@ check that your feature descriptions are well-formed and valid.
However, to help people unfamiliar with XML write descriptions for
their targets, we also describe the grammar here.
At the moment, target descriptions can only provide minimal information
about the architecture of the remote target. @value{GDBN} can use this
information to autoconfigure, or to warn you if you connect to an
unsupported target.
Target descriptions can identify the architecture of the remote target
and (for some architectures) provide information about custom register
sets. @value{GDBN} can use this information to autoconfigure for your
target, or to warn you if you connect to an unsupported target.
Here is a simple target description:
@example
@smallexample
<target>
<architecture>i386:x86-64</architecture>
</target>
@end example
@end smallexample
@noindent
This minimal description only says that the target uses
the x86-64 architecture.
A target description has the overall form:
A target description has the following overall form, with [ ] marking
optional elements and @dots{} marking repeatable elements. The elements
are explained further below.
@example
@smallexample
<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target>
<architecture>@var{arch name}</architecture>
@r{[}@var{architecture}@r{]}
@r{[}@var{feature}@dots{}@r{]}
</target>
@end example
@end smallexample
@noindent
The description is generally insensitive to whitespace and line
@ -25821,10 +25831,6 @@ declaration and document type declaration can generally be omitted
(@value{GDBN} does not require them), but specifying them may be
useful for XML validation tools.
The content of the @samp{<architecture>} element is an architecture
name, from the same selection accepted by @code{set architecture}
(@pxref{Targets, ,Specifying a Debugging Target}).
@subsection Inclusion
@cindex target descriptions, inclusion
@cindex XInclude
@ -25838,9 +25844,9 @@ share files between different possible target descriptions. You can
divide a description into multiple files by replacing any element of
the target description with an inclusion directive of the form:
@example
@smallexample
<xi:include href="@var{document}"/>
@end example
@end smallexample
@noindent
When @value{GDBN} encounters an element of this form, it will retrieve
@ -25852,6 +25858,208 @@ current description was read from a file, @value{GDBN} will look for
@var{document} as a file in the same directory where it found the
original description.
@subsection Architecture
@cindex <architecture>
An @samp{<architecture>} element has this form:
@smallexample
<architecture>@var{arch}</architecture>
@end smallexample
@var{arch} is an architecture name from the same selection
accepted by @code{set architecture} (@pxref{Targets, ,Specifying a
Debugging Target}).
@subsection Features
@cindex <feature>
Each @samp{<feature>} describes some logical portion of the target
system. Features are currently used to describe available CPU
registers and the types of their contents. A @samp{<feature>} element
has this form:
@smallexample
<feature name="@var{name}">
@r{[}@var{type}@dots{}@r{]}
@var{reg}@dots{}
</feature>
@end smallexample
@noindent
Each feature's name should be unique within the description. The name
of a feature does not matter unless @value{GDBN} has some special
knowledge of the contents of that feature; if it does, the feature
should have its standard name. @xref{Standard Target Features}.
@subsection Types
Any register's value is a collection of bits which @value{GDBN} must
interpret. The default interpretation is a two's complement integer,
but other types can be requested by name in the register description.
Some predefined types are provided by @value{GDBN} (@pxref{Predefined
Target Types}), and the description can define additional composite types.
Each type element must have an @samp{id} attribute, which gives
a unique (within the containing @samp{<feature>}) name to the type.
Types must be defined before they are used.
@cindex <vector>
Some targets offer vector registers, which can be treated as arrays
of scalar elements. These types are written as @samp{<vector>} elements,
specifying the array element type, @var{type}, and the number of elements,
@var{count}:
@smallexample
<vector id="@var{id}" type="@var{type}" count="@var{count}"/>
@end smallexample
@cindex <union>
If a register's value is usefully viewed in multiple ways, define it
with a union type containing the useful representations. The
@samp{<union>} element contains one or more @samp{<field>} elements,
each of which has a @var{name} and a @var{type}:
@smallexample
<union id="@var{id}">
<field name="@var{name}" type="@var{type}"/>
@dots{}
</union>
@end smallexample
@subsection Registers
@cindex <reg>
Each register is represented as an element with this form:
@smallexample
<reg name="@var{name}"
bitsize="@var{size}"
@r{[}regnum="@var{num}"@r{]}
@r{[}save-restore="@var{save-restore}"@r{]}
@r{[}type="@var{type}"@r{]}
@r{[}group="@var{group}"@r{]}/>
@end smallexample
@noindent
The components are as follows:
@table @var
@item name
The register's name; it must be unique within the target description.
@item bitsize
The register's size, in bits.
@item regnum
The register's number. If omitted, a register's number is one greater
than that of the previous register (either in the current feature or in
a preceeding feature); the first register in the target description
defaults to zero. This register number is used to read or write
the register; e.g.@: it is used in the remote @code{p} and @code{P}
packets, and registers appear in the @code{g} and @code{G} packets
in order of increasing register number.
@item save-restore
Whether the register should be preserved across inferior function
calls; this must be either @code{yes} or @code{no}. The default is
@code{yes}, which is appropriate for most registers except for
some system control registers; this is not related to the target's
ABI.
@item type
The type of the register. @var{type} may be a predefined type, a type
defined in the current feature, or one of the special types @code{int}
and @code{float}. @code{int} is an integer type of the correct size
for @var{bitsize}, and @code{float} is a floating point type (in the
architecture's normal floating point format) of the correct size for
@var{bitsize}. The default is @code{int}.
@item group
The register group to which this register belongs. @var{group} must
be either @code{general}, @code{float}, or @code{vector}. If no
@var{group} is specified, @value{GDBN} will not display the register
in @code{info registers}.
@end table
@node Predefined Target Types
@section Predefined Target Types
@cindex target descriptions, predefined types
Type definitions in the self-description can build up composite types
from basic building blocks, but can not define fundamental types. Instead,
standard identifiers are provided by @value{GDBN} for the fundamental
types. The currently supported types are:
@table @code
@item int8
@itemx int16
@itemx int32
@itemx int64
Signed integer types holding the specified number of bits.
@item uint8
@itemx uint16
@itemx uint32
@itemx uint64
Unsigned integer types holding the specified number of bits.
@item code_ptr
@itemx data_ptr
Pointers to unspecified code and data. The program counter and
any dedicated return address register may be marked as code
pointers; printing a code pointer converts it into a symbolic
address. The stack pointer and any dedicated address registers
may be marked as data pointers.
@item arm_fpa_ext
The 12-byte extended precision format used by ARM FPA registers.
@end table
@node Standard Target Features
@section Standard Target Features
@cindex target descriptions, standard features
A target description must contain either no registers or all the
target's registers. If the description contains no registers, then
@value{GDBN} will assume a default register layout, selected based on
the architecture. If the description contains any registers, the
default layout will not be used; the standard registers must be
described in the target description, in such a way that @value{GDBN}
can recognize them.
This is accomplished by giving specific names to feature elements
which contain standard registers. @value{GDBN} will look for features
with those names and verify that they contain the expected registers;
if any known feature is missing required registers, or if any required
feature is missing, @value{GDBN} will reject the target
description. You can add additional registers to any of the
standard features --- @value{GDBN} will display them just as if
they were added to an unrecognized feature.
This section lists the known features and their expected contents.
Sample XML documents for these features are included in the
@value{GDBN} source tree, in the directory @file{gdb/features}.
Names recognized by @value{GDBN} should include the name of the
company or organization which selected the name, and the overall
architecture to which the feature applies; so e.g.@: the feature
containing ARM core registers is named @samp{org.gnu.gdb.arm.core}.
@subsection ARM Features
@cindex target descriptions, ARM features
The @samp{org.gnu.gdb.arm.core} feature is required for ARM targets.
It should contain registers @samp{r0} through @samp{r13}, @samp{sp},
@samp{lr}, @samp{pc}, and @samp{cpsr}.
The @samp{org.gnu.gdb.arm.fpa} feature is optional. If present, it
should contain registers @samp{f0} through @samp{f7} and @samp{fps}.
@include gpl.texi

View File

@ -80,6 +80,7 @@ as the mechanisms that adapt @value{GDBN} to specific hosts and targets.
* Language Support::
* Host Definition::
* Target Architecture Definition::
* Target Descriptions::
* Target Vector Definition::
* Native Debugging::
* Support Libraries::
@ -4512,6 +4513,135 @@ The @file{tm-@var{arch}.h} can be deleted. @file{@var{arch}.mt} and
@file{configure.in} updated.
@node Target Descriptions
@chapter Target Descriptions
@cindex target descriptions
The target architecture definition (@pxref{Target Architecture Definition})
contains @value{GDBN}'s hard-coded knowledge about an architecture. For
some platforms, it is handy to have more flexible knowledge about a specific
instance of the architecture---for instance, a processor or development board.
@dfn{Target descriptions} provide a mechanism for the user to tell @value{GDBN}
more about what their target supports, or for the target to tell @value{GDBN}
directly.
For details on writing, automatically supplying, and manually selecting
target descriptions, see @ref{Target Descriptions, , , gdb,
Debugging with @value{GDBN}}. This section will cover some related
topics about the @value{GDBN} internals.
@menu
* Target Descriptions Implementation::
* Adding Target Described Register Support::
@end menu
@node Target Descriptions Implementation
@section Target Descriptions Implementation
@cindex target descriptions, implementation
Before @value{GDBN} connects to a new target, or runs a new program on
an existing target, it discards any existing target description and
reverts to a default gdbarch. Then, after connecting, it looks for a
new target description by calling @code{target_find_description}.
A description may come from a user specified file (XML), the remote
@samp{qXfer:features:read} packet (also XML), or from any custom
@code{to_read_description} routine in the target vector. For instance,
the remote target supports guessing whether a MIPS target is 32-bit or
64-bit based on the size of the @samp{g} packet.
If any target description is found, @value{GDBN} creates a new gdbarch
incorporating the description by calling @code{gdbarch_update_p}. Any
@samp{<architecture>} element is handled first, to determine which
architecture's gdbarch initialization routine is called to create the
new architecture. Then the initialization routine is called, and has
a chance to adjust the constructed architecture based on the contents
of the target description. For instance, it can recognize any
properties set by a @code{to_read_description} routine. Also
see @ref{Adding Target Described Register Support}.
@node Adding Target Described Register Support
@section Adding Target Described Register Support
@cindex target descriptions, adding register support
Target descriptions can report additional registers specific to an
instance of the target. But it takes a little work in the architecture
specific routines to support this.
A target description must either have no registers or a complete
set---this avoids complexity in trying to merge standard registers
with the target defined registers. It is the architecture's
responsibility to validate that a description with registers has
everything it needs. To keep architecture code simple, the same
mechanism is used to assign fixed internal register numbers to
standard registers.
If @code{tdesc_has_registers} returns 1, the description contains
registers. The architecture's @code{gdbarch_init} routine should:
@itemize @bullet
@item
Call @code{tdesc_data_alloc} to allocate storage, early, before
searching for a matching gdbarch or allocating a new one.
@item
Use @code{tdesc_find_feature} to locate standard features by name.
@item
Use @code{tdesc_numbered_register} and @code{tdesc_numbered_register_choices}
to locate the expected registers in the standard features.
@item
Return @code{NULL} if a required feature is missing, or if any standard
feature is missing expected registers. This will produce a warning that
the description was incomplete.
@item
Free the allocated data before returning, unless @code{tdesc_use_registers}
is called.
@item
Call @code{set_gdbarch_num_regs} as usual, with a number higher than any
fixed number passed to @code{tdesc_numbered_register}.
@item
Call @code{tdesc_use_registers} after creating a new gdbarch, before
returning it.
@end itemize
After @code{tdesc_use_registers} has been called, the architecture's
@code{register_name}, @code{register_type}, and @code{register_reggroup_p}
routines will not be called; that information will be taken from
the target description. @code{num_regs} may be increased to account
for any additional registers in the description.
Pseudo-registers require some extra care:
@itemize @bullet
@item
Using @code{tdesc_numbered_register} allows the architecture to give
constant register numbers to standard architectural registers, e.g.@:
as an @code{enum} in @file{@var{arch}-tdep.h}. But because
pseudo-registers are always numbered above @code{num_regs},
which may be increased by the description, constant numbers
can not be used for pseudos. They must be numbered relative to
@code{num_regs} instead.
@item
The description will not describe pseudo-registers, so the
architecture must call @code{set_tdesc_pseudo_register_name},
@code{set_tdesc_pseudo_register_type}, and
@code{set_tdesc_pseudo_register_reggroup_p} to supply routines
describing pseudo registers. These routines will be passed
internal register numbers, so the same routines used for the
gdbarch equivalents are usually suitable.
@end itemize
@node Target Vector Definition
@chapter Target Vector Definition

View File

@ -39,6 +39,7 @@
#include "cp-support.h"
#include "ui-out.h"
#include "exceptions.h"
#include "regcache.h"
#include "gdb_assert.h"
@ -500,8 +501,12 @@ evaluate_subexp_standard (struct type *expect_type,
case OP_REGISTER:
{
int regno = longest_to_int (exp->elts[pc + 1].longconst);
struct value *val = value_of_register (regno, get_selected_frame (NULL));
struct value *val;
(*pos) += 2;
if (noside == EVAL_AVOID_SIDE_EFFECTS)
val = value_zero (register_type (current_gdbarch, regno), not_lval);
else
val = value_of_register (regno, get_selected_frame (NULL));
if (val == NULL)
error (_("Value of register %s not available."),
frame_map_regnum_to_name (get_selected_frame (NULL), regno));

31
gdb/features/arm-core.xml Normal file
View File

@ -0,0 +1,31 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2007 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.arm.core">
<reg name="r0" bitsize="32"/>
<reg name="r1" bitsize="32"/>
<reg name="r2" bitsize="32"/>
<reg name="r3" bitsize="32"/>
<reg name="r4" bitsize="32"/>
<reg name="r5" bitsize="32"/>
<reg name="r6" bitsize="32"/>
<reg name="r7" bitsize="32"/>
<reg name="r8" bitsize="32"/>
<reg name="r9" bitsize="32"/>
<reg name="r10" bitsize="32"/>
<reg name="r11" bitsize="32"/>
<reg name="r12" bitsize="32"/>
<reg name="sp" bitsize="32"/>
<reg name="lr" bitsize="32"/>
<reg name="pc" bitsize="32"/>
<!-- The CPSR is register 25, rather than register 16, because
the FPA registers historically were placed between the PC
and the CPSR in the "g" packet. -->
<reg name="cpsr" bitsize="32" regnum="25"/>
</feature>

23
gdb/features/arm-fpa.xml Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2007 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.arm.fpa">
<!-- f0's regnum is set explicitly, because the FPA registers
historically were placed between the PC and the CPSR in the "g"
packet - in the middle of org.gnu.gdb.arm.core. -->
<reg name="f0" bitsize="96" type="arm_fpa_ext" regnum="16"/>
<reg name="f1" bitsize="96" type="arm_fpa_ext"/>
<reg name="f2" bitsize="96" type="arm_fpa_ext"/>
<reg name="f3" bitsize="96" type="arm_fpa_ext"/>
<reg name="f4" bitsize="96" type="arm_fpa_ext"/>
<reg name="f5" bitsize="96" type="arm_fpa_ext"/>
<reg name="f6" bitsize="96" type="arm_fpa_ext"/>
<reg name="f7" bitsize="96" type="arm_fpa_ext"/>
<reg name="fps" bitsize="32"/>
</feature>

View File

@ -6,9 +6,38 @@
<!-- The root element of a GDB target description is <target>. -->
<!ELEMENT target (architecture?)>
<!ELEMENT target (architecture?, feature*)>
<!ELEMENT architecture (#PCDATA)>
<!ELEMENT feature ((vector | union)*, reg*)>
<!ATTLIST feature
name ID #REQUIRED>
<!ELEMENT reg (description*)>
<!ATTLIST reg
name CDATA #REQUIRED
bitsize CDATA #REQUIRED
regnum CDATA #IMPLIED
save-restore (yes | no) 'yes'
type CDATA 'int'
group CDATA #IMPLIED
>
<!ELEMENT vector EMPTY>
<!ATTLIST vector
id CDATA #REQUIRED
type CDATA #REQUIRED
count CDATA #REQUIRED>
<!ELEMENT union (field+)>
<!ATTLIST union
id CDATA #REQUIRED>
<!ELEMENT field EMPTY>
<!ATTLIST field
name CDATA #REQUIRED
type CDATA #REQUIRED>
<!ENTITY % xinclude SYSTEM "xinclude.dtd">
%xinclude;

View File

@ -203,6 +203,7 @@ struct gdbarch
CORE_ADDR decr_pc_after_break;
CORE_ADDR deprecated_function_start_offset;
gdbarch_remote_translate_xfer_address_ftype *remote_translate_xfer_address;
gdbarch_remote_register_number_ftype *remote_register_number;
gdbarch_fetch_tls_load_module_address_ftype *fetch_tls_load_module_address;
CORE_ADDR frame_args_skip;
gdbarch_unwind_pc_ftype *unwind_pc;
@ -330,6 +331,7 @@ struct gdbarch startup_gdbarch =
0, /* decr_pc_after_break */
0, /* deprecated_function_start_offset */
generic_remote_translate_xfer_address, /* remote_translate_xfer_address */
default_remote_register_number, /* remote_register_number */
0, /* fetch_tls_load_module_address */
0, /* frame_args_skip */
0, /* unwind_pc */
@ -440,6 +442,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
current_gdbarch->memory_insert_breakpoint = default_memory_insert_breakpoint;
current_gdbarch->memory_remove_breakpoint = default_memory_remove_breakpoint;
current_gdbarch->remote_translate_xfer_address = generic_remote_translate_xfer_address;
current_gdbarch->remote_register_number = default_remote_register_number;
current_gdbarch->stabs_argument_has_addr = default_stabs_argument_has_addr;
current_gdbarch->convert_from_func_ptr_addr = convert_from_func_ptr_addr_identity;
current_gdbarch->addr_bits_remove = core_addr_identity;
@ -584,6 +587,7 @@ verify_gdbarch (struct gdbarch *current_gdbarch)
/* Skip verify of decr_pc_after_break, invalid_p == 0 */
/* Skip verify of deprecated_function_start_offset, invalid_p == 0 */
/* Skip verify of remote_translate_xfer_address, invalid_p == 0 */
/* Skip verify of remote_register_number, invalid_p == 0 */
/* Skip verify of fetch_tls_load_module_address, has predicate */
/* Skip verify of frame_args_skip, invalid_p == 0 */
/* Skip verify of unwind_pc, has predicate */
@ -1441,6 +1445,9 @@ gdbarch_dump (struct gdbarch *current_gdbarch, struct ui_file *file)
fprintf_unfiltered (file,
"gdbarch_dump: regset_from_core_section = <0x%lx>\n",
(long) current_gdbarch->regset_from_core_section);
fprintf_unfiltered (file,
"gdbarch_dump: remote_register_number = <0x%lx>\n",
(long) current_gdbarch->remote_register_number);
fprintf_unfiltered (file,
"gdbarch_dump: remote_translate_xfer_address = <0x%lx>\n",
(long) current_gdbarch->remote_translate_xfer_address);
@ -2989,6 +2996,23 @@ set_gdbarch_remote_translate_xfer_address (struct gdbarch *gdbarch,
gdbarch->remote_translate_xfer_address = remote_translate_xfer_address;
}
int
gdbarch_remote_register_number (struct gdbarch *gdbarch, int regno)
{
gdb_assert (gdbarch != NULL);
gdb_assert (gdbarch->remote_register_number != NULL);
if (gdbarch_debug >= 2)
fprintf_unfiltered (gdb_stdlog, "gdbarch_remote_register_number called\n");
return gdbarch->remote_register_number (gdbarch, regno);
}
void
set_gdbarch_remote_register_number (struct gdbarch *gdbarch,
gdbarch_remote_register_number_ftype remote_register_number)
{
gdbarch->remote_register_number = remote_register_number;
}
int
gdbarch_fetch_tls_load_module_address_p (struct gdbarch *gdbarch)
{

View File

@ -947,6 +947,13 @@ typedef void (gdbarch_remote_translate_xfer_address_ftype) (struct gdbarch *gdba
extern void gdbarch_remote_translate_xfer_address (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR gdb_addr, int gdb_len, CORE_ADDR *rem_addr, int *rem_len);
extern void set_gdbarch_remote_translate_xfer_address (struct gdbarch *gdbarch, gdbarch_remote_translate_xfer_address_ftype *remote_translate_xfer_address);
/* Return the remote protocol register number associated with this
register. Normally the identity mapping. */
typedef int (gdbarch_remote_register_number_ftype) (struct gdbarch *gdbarch, int regno);
extern int gdbarch_remote_register_number (struct gdbarch *gdbarch, int regno);
extern void set_gdbarch_remote_register_number (struct gdbarch *gdbarch, gdbarch_remote_register_number_ftype *remote_register_number);
/* Fetch the target specific address used to represent a load module. */
#if defined (FETCH_TLS_LOAD_MODULE_ADDRESS)

View File

@ -574,6 +574,10 @@ v:=:CORE_ADDR:deprecated_function_start_offset:::0:::0
m::void:remote_translate_xfer_address:struct regcache *regcache, CORE_ADDR gdb_addr, int gdb_len, CORE_ADDR *rem_addr, int *rem_len:regcache, gdb_addr, gdb_len, rem_addr, rem_len::generic_remote_translate_xfer_address::0
# Return the remote protocol register number associated with this
# register. Normally the identity mapping.
m::int:remote_register_number:int regno:regno::default_remote_register_number::0
# Fetch the target specific address used to represent a load module.
F:=:CORE_ADDR:fetch_tls_load_module_address:struct objfile *objfile:objfile
#

View File

@ -334,12 +334,13 @@ init_remote_state (struct gdbarch *gdbarch)
rsa = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct remote_arch_state);
/* Assume a 1:1 regnum<->pnum table. */
/* Use the architecture to build a regnum<->pnum table, which will be
1:1 unless a feature set specifies otherwise. */
rsa->regs = GDBARCH_OBSTACK_CALLOC (gdbarch, NUM_REGS, struct packet_reg);
for (regnum = 0; regnum < NUM_REGS; regnum++)
{
struct packet_reg *r = &rsa->regs[regnum];
r->pnum = regnum;
r->pnum = gdbarch_remote_register_number (gdbarch, regnum);
r->regnum = regnum;
}

View File

@ -53,7 +53,7 @@ build_builtin_type_frame_reg (void)
}
static struct value *
value_of_builtin_frame_reg (struct frame_info *frame)
value_of_builtin_frame_reg (struct frame_info *frame, const void *baton)
{
struct value *val;
gdb_byte *buf;
@ -72,7 +72,7 @@ value_of_builtin_frame_reg (struct frame_info *frame)
}
static struct value *
value_of_builtin_frame_fp_reg (struct frame_info *frame)
value_of_builtin_frame_fp_reg (struct frame_info *frame, const void *baton)
{
if (DEPRECATED_FP_REGNUM >= 0)
/* NOTE: cagney/2003-04-24: Since the mere presence of "fp" in the
@ -96,7 +96,7 @@ value_of_builtin_frame_fp_reg (struct frame_info *frame)
}
static struct value *
value_of_builtin_frame_pc_reg (struct frame_info *frame)
value_of_builtin_frame_pc_reg (struct frame_info *frame, const void *baton)
{
if (PC_REGNUM >= 0)
return value_of_register (PC_REGNUM, frame);
@ -114,7 +114,7 @@ value_of_builtin_frame_pc_reg (struct frame_info *frame)
}
static struct value *
value_of_builtin_frame_sp_reg (struct frame_info *frame)
value_of_builtin_frame_sp_reg (struct frame_info *frame, const void *baton)
{
#ifdef SP_REGNUM
if (SP_REGNUM >= 0)
@ -124,7 +124,7 @@ value_of_builtin_frame_sp_reg (struct frame_info *frame)
}
static struct value *
value_of_builtin_frame_ps_reg (struct frame_info *frame)
value_of_builtin_frame_ps_reg (struct frame_info *frame, const void *baton)
{
#ifdef PS_REGNUM
if (PS_REGNUM >= 0)
@ -147,14 +147,14 @@ _initialize_frame_reg (void)
/* Frame based $fp, $pc, $sp and $ps. These only come into play
when the target does not define its own version of these
registers. */
user_reg_add_builtin ("fp", value_of_builtin_frame_fp_reg);
user_reg_add_builtin ("pc", value_of_builtin_frame_pc_reg);
user_reg_add_builtin ("sp", value_of_builtin_frame_sp_reg);
user_reg_add_builtin ("ps", value_of_builtin_frame_ps_reg);
user_reg_add_builtin ("fp", value_of_builtin_frame_fp_reg, NULL);
user_reg_add_builtin ("pc", value_of_builtin_frame_pc_reg, NULL);
user_reg_add_builtin ("sp", value_of_builtin_frame_sp_reg, NULL);
user_reg_add_builtin ("ps", value_of_builtin_frame_ps_reg, NULL);
/* NOTE: cagney/2002-04-05: For moment leave the $frame / $gdbframe
/ $gdb.frame disabled. It isn't yet clear which of the many
options is the best. */
if (0)
user_reg_add_builtin ("frame", value_of_builtin_frame_reg);
user_reg_add_builtin ("frame", value_of_builtin_frame_reg, NULL);
}

View File

@ -24,12 +24,17 @@
#include "defs.h"
#include "arch-utils.h"
#include "gdbcmd.h"
#include "gdbtypes.h"
#include "reggroups.h"
#include "target.h"
#include "target-descriptions.h"
#include "vec.h"
#include "xml-support.h"
#include "xml-tdesc.h"
#include "gdb_assert.h"
#include "gdb_obstack.h"
#include "hashtab.h"
/* Types. */
@ -40,6 +45,69 @@ typedef struct property
} property_s;
DEF_VEC_O(property_s);
/* An individual register from a target description. */
typedef struct tdesc_reg
{
/* The name of this register. In standard features, it may be
recognized by the architecture support code, or it may be purely
for the user. */
char *name;
/* The register number used by this target to refer to this
register. This is used for remote p/P packets and to determine
the ordering of registers in the remote g/G packets. */
long target_regnum;
/* If this flag is set, GDB should save and restore this register
around calls to an inferior function. */
int save_restore;
/* The name of the register group containing this register, or NULL
if the group should be automatically determined from the
register's type. If this is "general", "float", or "vector", the
corresponding "info" command should display this register's
value. It can be an arbitrary string, but should be limited to
alphanumeric characters and internal hyphens. Currently other
strings are ignored (treated as NULL). */
char *group;
/* The size of the register, in bits. */
int bitsize;
/* The type of the register. This string corresponds to either
a named type from the target description or a predefined
type from GDB. */
char *type;
/* The target-described type corresponding to TYPE, if found. */
struct type *gdb_type;
} *tdesc_reg_p;
DEF_VEC_P(tdesc_reg_p);
/* A named type from a target description. */
typedef struct type *type_p;
DEF_VEC_P(type_p);
/* A feature from a target description. Each feature is a collection
of other elements, e.g. registers and types. */
typedef struct tdesc_feature
{
/* The name of this feature. It may be recognized by the architecture
support code. */
char *name;
/* The registers associated with this feature. */
VEC(tdesc_reg_p) *registers;
/* The types associated with this feature. */
VEC(type_p) *types;
} *tdesc_feature_p;
DEF_VEC_P(tdesc_feature_p);
/* A target description. */
struct target_desc
{
/* The architecture reported by the target, if any. */
@ -47,6 +115,30 @@ struct target_desc
/* Any architecture-specific properties specified by the target. */
VEC(property_s) *properties;
/* The features associated with this target. */
VEC(tdesc_feature_p) *features;
};
/* Per-architecture data associated with a target description. The
target description may be shared by multiple architectures, but
this data is private to one gdbarch. */
struct tdesc_arch_data
{
/* A list of registers, indexed by GDB's internal register number.
During initialization of the gdbarch this list is used to store
registers which the architecture assigns a fixed register number.
Registers which are NULL in this array, or off the end, are
treated as zero-sized and nameless (i.e. placeholders in the
numbering). */
VEC(tdesc_reg_p) *registers;
/* Functions which report the register name, type, and reggroups for
pseudo-registers. */
gdbarch_register_name_ftype *pseudo_register_name;
gdbarch_register_type_ftype *pseudo_register_type;
gdbarch_register_reggroup_p_ftype *pseudo_register_reggroup_p;
};
/* Global state. These variables are associated with the current
@ -72,6 +164,11 @@ static const struct target_desc *current_target_desc;
static char *target_description_filename;
/* A handle for architecture-specific data associated with the
target description (see struct tdesc_arch_data). */
static struct gdbarch_data *tdesc_data;
/* Fetch the current target's description, and switch the current
architecture to one which incorporates that description. */
@ -116,7 +213,17 @@ target_find_description (void)
gdbarch_info_init (&info);
info.target_desc = current_target_desc;
if (!gdbarch_update_p (info))
warning (_("Could not use target-supplied description"));
warning (_("Architecture rejected target-supplied description"));
else
{
struct tdesc_arch_data *data;
data = gdbarch_data (current_gdbarch, tdesc_data);
if (tdesc_has_registers (current_target_desc)
&& data->registers == NULL)
warning (_("Target-supplied registers are not supported "
"by the current architecture"));
}
}
/* Now that we know this description is usable, record that we
@ -158,7 +265,7 @@ target_current_description (void)
}
/* Direct accessors for feature sets. */
/* Direct accessors for target descriptions. */
/* Return the string value of a property named KEY, or NULL if the
property was not specified. */
@ -187,8 +294,529 @@ tdesc_architecture (const struct target_desc *target_desc)
}
/* Return 1 if this target description includes any registers. */
int
tdesc_has_registers (const struct target_desc *target_desc)
{
int ix;
struct tdesc_feature *feature;
if (target_desc == NULL)
return 0;
for (ix = 0;
VEC_iterate (tdesc_feature_p, target_desc->features, ix, feature);
ix++)
if (! VEC_empty (tdesc_reg_p, feature->registers))
return 1;
return 0;
}
/* Return the feature with the given name, if present, or NULL if
the named feature is not found. */
const struct tdesc_feature *
tdesc_find_feature (const struct target_desc *target_desc,
const char *name)
{
int ix;
struct tdesc_feature *feature;
for (ix = 0;
VEC_iterate (tdesc_feature_p, target_desc->features, ix, feature);
ix++)
if (strcmp (feature->name, name) == 0)
return feature;
return NULL;
}
/* Return the name of FEATURE. */
const char *
tdesc_feature_name (const struct tdesc_feature *feature)
{
return feature->name;
}
/* Return the type associated with ID in the context of FEATURE, or
NULL if none. */
struct type *
tdesc_named_type (const struct tdesc_feature *feature, const char *id)
{
int ix;
struct type *gdb_type;
/* First try target-defined types. */
for (ix = 0; VEC_iterate (type_p, feature->types, ix, gdb_type); ix++)
if (strcmp (TYPE_NAME (gdb_type), id) == 0)
return gdb_type;
/* Next try some predefined types. Note that none of these types
depend on the current architecture; some of the builtin_type_foo
variables are swapped based on the architecture. */
if (strcmp (id, "int8") == 0)
return builtin_type_int8;
if (strcmp (id, "int16") == 0)
return builtin_type_int16;
if (strcmp (id, "int32") == 0)
return builtin_type_int32;
if (strcmp (id, "int64") == 0)
return builtin_type_int64;
if (strcmp (id, "uint8") == 0)
return builtin_type_uint8;
if (strcmp (id, "uint16") == 0)
return builtin_type_uint16;
if (strcmp (id, "uint32") == 0)
return builtin_type_uint32;
if (strcmp (id, "uint64") == 0)
return builtin_type_uint64;
if (strcmp (id, "code_ptr") == 0)
return builtin_type_void_func_ptr;
if (strcmp (id, "data_ptr") == 0)
return builtin_type_void_data_ptr;
if (strcmp (id, "arm_fpa_ext") == 0)
return builtin_type_arm_ext;
return NULL;
}
/* Support for registers from target descriptions. */
/* Construct the per-gdbarch data. */
static void *
tdesc_data_init (struct obstack *obstack)
{
struct tdesc_arch_data *data;
data = OBSTACK_ZALLOC (obstack, struct tdesc_arch_data);
return data;
}
/* Similar, but for the temporary copy used during architecture
initialization. */
struct tdesc_arch_data *
tdesc_data_alloc (void)
{
return XZALLOC (struct tdesc_arch_data);
}
/* Free something allocated by tdesc_data_alloc, if it is not going
to be used (for instance if it was unsuitable for the
architecture). */
void
tdesc_data_cleanup (void *data_untyped)
{
struct tdesc_arch_data *data = data_untyped;
VEC_free (tdesc_reg_p, data->registers);
xfree (data);
}
/* Search FEATURE for a register named NAME. */
int
tdesc_numbered_register (const struct tdesc_feature *feature,
struct tdesc_arch_data *data,
int regno, const char *name)
{
int ixr;
struct tdesc_reg *reg;
for (ixr = 0;
VEC_iterate (tdesc_reg_p, feature->registers, ixr, reg);
ixr++)
if (strcasecmp (reg->name, name) == 0)
{
/* Make sure the vector includes a REGNO'th element. */
while (regno >= VEC_length (tdesc_reg_p, data->registers))
VEC_safe_push (tdesc_reg_p, data->registers, NULL);
VEC_replace (tdesc_reg_p, data->registers, regno, reg);
return 1;
}
return 0;
}
/* Search FEATURE for a register whose name is in NAMES. */
int
tdesc_numbered_register_choices (const struct tdesc_feature *feature,
struct tdesc_arch_data *data,
int regno, const char *const names[])
{
int i;
for (i = 0; names[i] != NULL; i++)
if (tdesc_numbered_register (feature, data, regno, names[i]))
return 1;
return 0;
}
/* Look up a register by its GDB internal register number. */
static struct tdesc_reg *
tdesc_find_register (struct gdbarch *gdbarch, int regno)
{
struct tdesc_reg *reg;
struct tdesc_arch_data *data;
data = gdbarch_data (gdbarch, tdesc_data);
if (regno < VEC_length (tdesc_reg_p, data->registers))
return VEC_index (tdesc_reg_p, data->registers, regno);
else
return NULL;
}
static const char *
tdesc_register_name (int regno)
{
struct tdesc_reg *reg = tdesc_find_register (current_gdbarch, regno);
int num_regs = gdbarch_num_regs (current_gdbarch);
int num_pseudo_regs = gdbarch_num_pseudo_regs (current_gdbarch);
if (reg != NULL)
return reg->name;
if (regno >= num_regs && regno < num_regs + num_pseudo_regs)
{
struct tdesc_arch_data *data = gdbarch_data (current_gdbarch,
tdesc_data);
gdb_assert (data->pseudo_register_name != NULL);
return data->pseudo_register_name (regno);
}
return "";
}
static struct type *
tdesc_register_type (struct gdbarch *gdbarch, int regno)
{
struct tdesc_reg *reg = tdesc_find_register (gdbarch, regno);
int num_regs = gdbarch_num_regs (gdbarch);
int num_pseudo_regs = gdbarch_num_pseudo_regs (gdbarch);
if (reg == NULL && regno >= num_regs && regno < num_regs + num_pseudo_regs)
{
struct tdesc_arch_data *data = gdbarch_data (gdbarch, tdesc_data);
gdb_assert (data->pseudo_register_type != NULL);
return data->pseudo_register_type (gdbarch, regno);
}
if (reg == NULL)
/* Return "int0_t", since "void" has a misleading size of one. */
return builtin_type_int0;
/* First check for a predefined or target defined type. */
if (reg->gdb_type)
return reg->gdb_type;
/* Next try size-sensitive type shortcuts. */
if (strcmp (reg->type, "float") == 0)
{
if (reg->bitsize == gdbarch_float_bit (gdbarch))
return builtin_type_float;
else if (reg->bitsize == gdbarch_double_bit (gdbarch))
return builtin_type_double;
else if (reg->bitsize == gdbarch_long_double_bit (gdbarch))
return builtin_type_long_double;
}
else if (strcmp (reg->type, "int") == 0)
{
if (reg->bitsize == gdbarch_long_bit (gdbarch))
return builtin_type_long;
else if (reg->bitsize == TARGET_CHAR_BIT)
return builtin_type_char;
else if (reg->bitsize == gdbarch_short_bit (gdbarch))
return builtin_type_short;
else if (reg->bitsize == gdbarch_int_bit (gdbarch))
return builtin_type_int;
else if (reg->bitsize == gdbarch_long_long_bit (gdbarch))
return builtin_type_long_long;
else if (reg->bitsize == gdbarch_ptr_bit (gdbarch))
/* A bit desperate by this point... */
return builtin_type_void_data_ptr;
}
else
internal_error (__FILE__, __LINE__,
"Register \"%s\" has an unknown type \"%s\"",
reg->name, reg->type);
warning (_("Register \"%s\" has an unsupported size (%d bits)"),
reg->name, reg->bitsize);
return builtin_type_long;
}
static int
tdesc_remote_register_number (struct gdbarch *gdbarch, int regno)
{
struct tdesc_reg *reg = tdesc_find_register (gdbarch, regno);
if (reg != NULL)
return reg->target_regnum;
else
return -1;
}
/* Check whether REGNUM is a member of REGGROUP. Registers from the
target description may be classified as general, float, or vector.
Registers with no group specified go to the default reggroup
function and are handled by type.
Arbitrary strings (other than "general", "float", and "vector")
from the description are not used; they cause the register to be
displayed in "info all-registers" but excluded from "info
registers" et al. The names of containing features are also not
used. This might be extended to display registers in some more
useful groupings.
The save-restore flag is also implemented here. */
static int
tdesc_register_reggroup_p (struct gdbarch *gdbarch, int regno,
struct reggroup *reggroup)
{
int num_regs = gdbarch_num_regs (gdbarch);
int num_pseudo_regs = gdbarch_num_pseudo_regs (gdbarch);
struct tdesc_reg *reg = tdesc_find_register (gdbarch, regno);
if (reg == NULL && regno >= num_regs && regno < num_regs + num_pseudo_regs)
{
struct tdesc_arch_data *data = gdbarch_data (gdbarch, tdesc_data);
gdb_assert (data->pseudo_register_reggroup_p != NULL);
return data->pseudo_register_reggroup_p (gdbarch, regno, reggroup);
}
if (reg != NULL && reg->group != NULL)
{
int general_p = 0, float_p = 0, vector_p = 0;
if (strcmp (reg->group, "general") == 0)
general_p = 1;
else if (strcmp (reg->group, "float") == 0)
float_p = 1;
else if (strcmp (reg->group, "vector") == 0)
vector_p = 1;
if (reggroup == float_reggroup)
return float_p;
if (reggroup == vector_reggroup)
return vector_p;
if (reggroup == general_reggroup)
return general_p;
}
if (reg != NULL
&& (reggroup == save_reggroup || reggroup == restore_reggroup))
return reg->save_restore;
return default_register_reggroup_p (gdbarch, regno, reggroup);
}
/* Record architecture-specific functions to call for pseudo-register
support. */
void
set_tdesc_pseudo_register_name (struct gdbarch *gdbarch,
gdbarch_register_name_ftype *pseudo_name)
{
struct tdesc_arch_data *data = gdbarch_data (gdbarch, tdesc_data);
data->pseudo_register_name = pseudo_name;
}
void
set_tdesc_pseudo_register_type (struct gdbarch *gdbarch,
gdbarch_register_type_ftype *pseudo_type)
{
struct tdesc_arch_data *data = gdbarch_data (gdbarch, tdesc_data);
data->pseudo_register_type = pseudo_type;
}
void
set_tdesc_pseudo_register_reggroup_p
(struct gdbarch *gdbarch,
gdbarch_register_reggroup_p_ftype *pseudo_reggroup_p)
{
struct tdesc_arch_data *data = gdbarch_data (gdbarch, tdesc_data);
data->pseudo_register_reggroup_p = pseudo_reggroup_p;
}
/* Update GDBARCH to use the target description for registers. */
void
tdesc_use_registers (struct gdbarch *gdbarch,
struct tdesc_arch_data *early_data)
{
int num_regs = gdbarch_num_regs (gdbarch);
int i, ixf, ixr;
const struct target_desc *target_desc;
struct tdesc_feature *feature;
struct tdesc_reg *reg;
struct tdesc_arch_data *data;
htab_t reg_hash;
target_desc = gdbarch_target_desc (gdbarch);
/* We can't use the description for registers if it doesn't describe
any. This function should only be called after validating
registers, so the caller should know that registers are
included. */
gdb_assert (tdesc_has_registers (target_desc));
data = gdbarch_data (gdbarch, tdesc_data);
data->registers = early_data->registers;
xfree (early_data);
/* Build up a set of all registers, so that we can assign register
numbers where needed. The hash table expands as necessary, so
the initial size is arbitrary. */
reg_hash = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
for (ixf = 0;
VEC_iterate (tdesc_feature_p, target_desc->features, ixf, feature);
ixf++)
for (ixr = 0;
VEC_iterate (tdesc_reg_p, feature->registers, ixr, reg);
ixr++)
{
void **slot = htab_find_slot (reg_hash, reg, INSERT);
*slot = reg;
}
/* Remove any registers which were assigned numbers by the
architecture. */
for (ixr = 0; VEC_iterate (tdesc_reg_p, data->registers, ixr, reg); ixr++)
if (reg)
htab_remove_elt (reg_hash, reg);
/* Assign numbers to the remaining registers and add them to the
list of registers. The new numbers are always above NUM_REGS.
Iterate over the features, not the hash table, so that the order
matches that in the target description. */
gdb_assert (VEC_length (tdesc_reg_p, data->registers) <= num_regs);
while (VEC_length (tdesc_reg_p, data->registers) < num_regs)
VEC_safe_push (tdesc_reg_p, data->registers, NULL);
for (ixf = 0;
VEC_iterate (tdesc_feature_p, target_desc->features, ixf, feature);
ixf++)
for (ixr = 0;
VEC_iterate (tdesc_reg_p, feature->registers, ixr, reg);
ixr++)
if (htab_find (reg_hash, reg) != NULL)
{
VEC_safe_push (tdesc_reg_p, data->registers, reg);
num_regs++;
}
htab_delete (reg_hash);
/* Update the architecture. */
set_gdbarch_num_regs (gdbarch, num_regs);
set_gdbarch_register_name (gdbarch, tdesc_register_name);
set_gdbarch_register_type (gdbarch, tdesc_register_type);
set_gdbarch_remote_register_number (gdbarch,
tdesc_remote_register_number);
set_gdbarch_register_reggroup_p (gdbarch, tdesc_register_reggroup_p);
}
/* Methods for constructing a target description. */
static void
tdesc_free_reg (struct tdesc_reg *reg)
{
xfree (reg->name);
xfree (reg->type);
xfree (reg->group);
xfree (reg);
}
void
tdesc_create_reg (struct tdesc_feature *feature, const char *name,
int regnum, int save_restore, const char *group,
int bitsize, const char *type)
{
struct tdesc_reg *reg = XZALLOC (struct tdesc_reg);
reg->name = xstrdup (name);
reg->target_regnum = regnum;
reg->save_restore = save_restore;
reg->group = group ? xstrdup (group) : NULL;
reg->bitsize = bitsize;
reg->type = type ? xstrdup (type) : NULL;
/* If the register's type is target-defined, look it up now. We may not
have easy access to the containing feature when we want it later. */
reg->gdb_type = tdesc_named_type (feature, reg->type);
VEC_safe_push (tdesc_reg_p, feature->registers, reg);
}
static void
tdesc_free_feature (struct tdesc_feature *feature)
{
struct tdesc_reg *reg;
int ix;
for (ix = 0; VEC_iterate (tdesc_reg_p, feature->registers, ix, reg); ix++)
tdesc_free_reg (reg);
VEC_free (tdesc_reg_p, feature->registers);
/* There is no easy way to free xmalloc-allocated types, nor is
there a way to allocate types on an obstack not associated with
an objfile. Therefore we never free types. Since we only ever
parse an identical XML document once, this memory leak is mostly
contained. */
VEC_free (type_p, feature->types);
xfree (feature->name);
xfree (feature);
}
struct tdesc_feature *
tdesc_create_feature (struct target_desc *tdesc, const char *name)
{
struct tdesc_feature *new_feature = XZALLOC (struct tdesc_feature);
new_feature->name = xstrdup (name);
VEC_safe_push (tdesc_feature_p, tdesc->features, new_feature);
return new_feature;
}
void
tdesc_record_type (struct tdesc_feature *feature, struct type *type)
{
/* The type's ID should be used as its TYPE_NAME. */
gdb_assert (TYPE_NAME (type) != NULL);
VEC_safe_push (type_p, feature->types, type);
}
struct target_desc *
allocate_target_description (void)
{
@ -199,9 +827,16 @@ static void
free_target_description (void *arg)
{
struct target_desc *target_desc = arg;
struct tdesc_feature *feature;
struct property *prop;
int ix;
for (ix = 0;
VEC_iterate (tdesc_feature_p, target_desc->features, ix, feature);
ix++)
tdesc_free_feature (feature);
VEC_free (tdesc_feature_p, target_desc->features);
for (ix = 0;
VEC_iterate (property_s, target_desc->properties, ix, prop);
ix++)
@ -305,6 +940,8 @@ unset_tdesc_filename_cmd (char *args, int from_tty)
void
_initialize_target_descriptions (void)
{
tdesc_data = gdbarch_data_register_pre_init (tdesc_data_init);
add_prefix_cmd ("tdesc", class_maintenance, set_tdesc_cmd, _("\
Set target description specific variables."),
&tdesc_set_cmdlist, "set tdesc ",

View File

@ -24,7 +24,12 @@
#ifndef TARGET_DESCRIPTIONS_H
#define TARGET_DESCRIPTIONS_H 1
struct tdesc_feature;
struct tdesc_arch_data;
struct tdesc_reg;
struct target_desc;
struct target_ops;
struct type;
/* Fetch the current target's description, and switch the current
architecture to one which incorporates that description. */
@ -42,6 +47,65 @@ void target_clear_description (void);
const struct target_desc *target_current_description (void);
/* Record architecture-specific functions to call for pseudo-register
support. If tdesc_use_registers is called and NUM_PSEUDO_REGS
is greater than zero, then these should be called as well.
They are equivalent to the gdbarch methods with similar names,
except that they will only be called for pseudo registers. */
void set_tdesc_pseudo_register_name
(struct gdbarch *gdbarch, gdbarch_register_name_ftype *pseudo_name);
void set_tdesc_pseudo_register_type
(struct gdbarch *gdbarch, gdbarch_register_type_ftype *pseudo_type);
void set_tdesc_pseudo_register_reggroup_p
(struct gdbarch *gdbarch,
gdbarch_register_reggroup_p_ftype *pseudo_reggroup_p);
/* Update GDBARCH to use the target description for registers. Fixed
register assignments are taken from EARLY_DATA, which is freed.
All registers which have not been assigned fixed numbers are given
numbers above the current value of NUM_REGS. NUM_REGS and various
register-related predicates are updated to refer to the target
description. This function should only be called from the
architecture's gdbarch initialization routine, and only after
successfully validating the required registers. */
void tdesc_use_registers (struct gdbarch *gdbarch,
struct tdesc_arch_data *early_data);
/* Allocate initial data for validation of a target description during
gdbarch initialization. */
struct tdesc_arch_data *tdesc_data_alloc (void);
/* Clean up data allocated by tdesc_data_alloc. This should only
be called to discard the data; tdesc_use_registers takes ownership
of its EARLY_DATA argument. */
void tdesc_data_cleanup (void *data_untyped);
/* Search FEATURE for a register named NAME. Record REGNO and the
register in DATA; when tdesc_use_registers is called, REGNO will be
assigned to the register. 1 is returned if the register was found,
0 if it was not. */
int tdesc_numbered_register (const struct tdesc_feature *feature,
struct tdesc_arch_data *data,
int regno, const char *name);
/* Search FEATURE for a register with any of the names from NAMES
(NULL-terminated). Record REGNO and the register in DATA; when
tdesc_use_registers is called, REGNO will be assigned to the
register. 1 is returned if the register was found, 0 if it was
not. */
int tdesc_numbered_register_choices (const struct tdesc_feature *feature,
struct tdesc_arch_data *data,
int regno, const char *const names[]);
/* Accessors for target descriptions. */
/* Return the BFD architecture associated with this target
@ -56,14 +120,41 @@ const struct bfd_arch_info *tdesc_architecture
const char *tdesc_property (const struct target_desc *,
const char *key);
/* Return 1 if this target description describes any registers. */
int tdesc_has_registers (const struct target_desc *);
/* Return the feature with the given name, if present, or NULL if
the named feature is not found. */
const struct tdesc_feature *tdesc_find_feature (const struct target_desc *,
const char *name);
/* Return the name of FEATURE. */
const char *tdesc_feature_name (const struct tdesc_feature *feature);
/* Return the type associated with ID in the context of FEATURE, or
NULL if none. */
struct type *tdesc_named_type (const struct tdesc_feature *feature,
const char *id);
/* Methods for constructing a target description. */
struct target_desc *allocate_target_description (void);
struct cleanup *make_cleanup_free_target_description (struct target_desc *);
void set_tdesc_architecture (struct target_desc *,
const struct bfd_arch_info *);
void set_tdesc_property (struct target_desc *,
const char *key, const char *value);
struct tdesc_feature *tdesc_create_feature (struct target_desc *tdesc,
const char *name);
void tdesc_record_type (struct tdesc_feature *feature, struct type *type);
void tdesc_create_reg (struct tdesc_feature *feature, const char *name,
int regnum, int save_restore, const char *group,
int bitsize, const char *type);
#endif /* TARGET_DESCRIPTIONS_H */

View File

@ -1,3 +1,8 @@
2007-02-08 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.xml/single-reg.xml, gdb.xml/tdesc-regs.exp,
gdb.xml/core-only.xml, gdb.xml/extra-regs.xml: New files.
2007-02-08 Nick Roberts <nickrob@snap.net.nz>
* gdb.mi/mi-var-block.exp, gdb.mi/mi2-var-block.exp

View File

@ -0,0 +1,3 @@
<target>
<xi:include href="core-regs.xml"/>
</target>

View File

@ -0,0 +1,16 @@
<target>
<xi:include href="core-regs.xml"/>
<feature name="extra">
<vector id="v4int8" type="int8" count="4"/>
<vector id="v2int16" type="int16" count="2"/>
<union id="vecint">
<field name="v4" type="v4int8"/>
<field name="v2" type="v2int16"/>
</union>
<reg name="extrareg" bitsize="32"/>
<reg name="uintreg" bitsize="32" type="uint32"/>
<reg name="vecreg" bitsize="32" type="v4int8"/>
<reg name="unionreg" bitsize="32" type="vecint"/>
</feature>
</target>

View File

@ -0,0 +1,5 @@
<target>
<feature name="single">
<reg name="one" bitsize="32"/>
</feature>
</target>

View File

@ -0,0 +1,95 @@
# Copyright 2007 Free Software Foundation, Inc.
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
if {[gdb_skip_xml_test]} {
unsupported "tdesc-regs.exp"
return -1
}
gdb_start
# To test adding registers, we need a core set of registers for this
# architecture, or the description will be rejected.
set core-regs ""
switch -glob -- [istarget] {
"*arm-*-*" {
set core-regs arm-core
}
"xscale-*-*" {
set core-regs arm-core
}
}
# If no core registers were specified, assume this target does not
# support target-defined registers. Verify that we get a warning if
# we try to use them. This not only tests the warning, but also
# reminds maintainers to add test support when they add the feature.
if {[string equal ${core-regs} ""]} {
gdb_test "set tdesc file $srcdir/$subdir/single-reg.xml" \
"warning: Target-supplied registers are not supported.*" \
"set tdesc file single-reg.xml"
unsupported "register tests"
return 0
}
# Otherwise, we support both XML and target defined registers.
# Make sure we reject a description missing standard registers,
# like the PC.
gdb_test "set tdesc file $srcdir/$subdir/single-reg.xml" \
"warning: Architecture rejected target-supplied description" \
"set tdesc file single-reg.xml"
# Copy the core registers into the objdir if necessary, so that they
# will be found by <xi:include>.
file delete "core-regs.xml"
file copy "$srcdir/../features/${core-regs}.xml" "core-regs.xml"
# Similarly, we need to copy files under test into the objdir.
proc load_description { file errmsg } {
global srcdir
global subdir
global gdb_prompt
file delete "regs.xml"
file copy "$srcdir/$subdir/$file" "regs.xml"
# Anchor the test output, so that error messages are detected.
set cmd "set tdesc filename regs.xml"
set msg "set tdesc filename $file"
set cmd_regex [string_to_regexp $cmd]
gdb_test_multiple $cmd $msg {
-re "^$cmd_regex\r\n$errmsg$gdb_prompt $" {
pass $msg
}
}
}
load_description "extra-regs.xml" ""
gdb_test "ptype \$extrareg" "type = (int|long|long long)"
gdb_test "ptype \$uintreg" "type = uint32_t"
gdb_test "ptype \$vecreg" "type = int8_t \\\[4\\\]"
gdb_test "ptype \$unionreg" \
"type = union {\r\n *v4int8 v4;\r\n *v2int16 v2;\r\n}"
gdb_test "ptype \$unionreg.v4" "type = int8_t \\\[4\\\]"
load_description "core-only.xml" ""
# The extra register from the previous description should be gone.
gdb_test "ptype \$extrareg" "type = void"
file delete "core-regs.xml"
file delete "regs.xml"

View File

@ -41,7 +41,8 @@
struct user_reg
{
const char *name;
struct value *(*read) (struct frame_info * frame);
struct value *(*read) (struct frame_info * frame, const void *baton);
const void *baton;
struct user_reg *next;
};
@ -59,7 +60,8 @@ struct gdb_user_regs
static void
append_user_reg (struct gdb_user_regs *regs, const char *name,
user_reg_read_ftype *read, struct user_reg *reg)
user_reg_read_ftype *read, const void *baton,
struct user_reg *reg)
{
/* The caller is responsible for allocating memory needed to store
the register. By doing this, the function can operate on a
@ -67,6 +69,7 @@ append_user_reg (struct gdb_user_regs *regs, const char *name,
gdb_assert (reg != NULL);
reg->name = name;
reg->read = read;
reg->baton = baton;
reg->next = NULL;
(*regs->last) = reg;
regs->last = &(*regs->last)->next;
@ -77,9 +80,10 @@ append_user_reg (struct gdb_user_regs *regs, const char *name,
static struct gdb_user_regs builtin_user_regs = { NULL, &builtin_user_regs.first };
void
user_reg_add_builtin (const char *name, user_reg_read_ftype *read)
user_reg_add_builtin (const char *name, user_reg_read_ftype *read,
const void *baton)
{
append_user_reg (&builtin_user_regs, name, read,
append_user_reg (&builtin_user_regs, name, read, baton,
XMALLOC (struct user_reg));
}
@ -95,14 +99,14 @@ user_regs_init (struct gdbarch *gdbarch)
struct gdb_user_regs *regs = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct gdb_user_regs);
regs->last = &regs->first;
for (reg = builtin_user_regs.first; reg != NULL; reg = reg->next)
append_user_reg (regs, reg->name, reg->read,
append_user_reg (regs, reg->name, reg->read, reg->baton,
GDBARCH_OBSTACK_ZALLOC (gdbarch, struct user_reg));
return regs;
}
void
user_reg_add (struct gdbarch *gdbarch, const char *name,
user_reg_read_ftype *read)
user_reg_read_ftype *read, const void *baton)
{
struct gdb_user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
if (regs == NULL)
@ -112,7 +116,7 @@ user_reg_add (struct gdbarch *gdbarch, const char *name,
regs = user_regs_init (gdbarch);
deprecated_set_gdbarch_data (gdbarch, user_regs_data, regs);
}
append_user_reg (regs, name, read,
append_user_reg (regs, name, read, baton,
GDBARCH_OBSTACK_ZALLOC (gdbarch, struct user_reg));
}
@ -199,7 +203,7 @@ value_of_user_reg (int regnum, struct frame_info *frame)
+ gdbarch_num_pseudo_regs (gdbarch));
struct user_reg *reg = usernum_to_user_reg (gdbarch, regnum - maxregs);
gdb_assert (reg != NULL);
return reg->read (frame);
return reg->read (frame, reg->baton);
}
extern initialize_file_ftype _initialize_user_regs; /* -Wmissing-prototypes */

View File

@ -57,15 +57,16 @@ extern const char *user_reg_map_regnum_to_name (struct gdbarch *gdbarch,
bytes as, at the time the register is being added, the type needed
to describe the register has not bee initialized. */
typedef struct value *(user_reg_read_ftype) (struct frame_info *frame);
typedef struct value *(user_reg_read_ftype) (struct frame_info *frame,
const void *baton);
extern struct value *value_of_user_reg (int regnum, struct frame_info *frame);
/* Add a builtin register (present in all architectures). */
extern void user_reg_add_builtin (const char *name,
user_reg_read_ftype *read);
user_reg_read_ftype *read, const void *baton);
/* Add a per-architecture frame register. */
extern void user_reg_add (struct gdbarch *gdbarch, const char *name,
user_reg_read_ftype *read);
user_reg_read_ftype *read, const void *baton);
#endif

View File

@ -40,6 +40,8 @@ static int debug_xml;
we just want to avoid running out of stack on loops. */
#define MAX_XINCLUDE_DEPTH 30
/* Simplified XML parser infrastructure. */
/* A parsing level -- used to keep track of the current element
nesting. */
struct scope_level
@ -631,6 +633,14 @@ gdb_xml_parse_attr_ulongest (struct gdb_xml_parser *parser,
return ret;
}
/* A handler_data for yes/no boolean values. */
const struct gdb_xml_enum gdb_xml_enums_boolean[] = {
{ "yes", 1 },
{ "no", 0 },
{ NULL, 0 }
};
/* Map NAME to VALUE. A struct gdb_xml_enum * should be saved as the
value of handler_data when using gdb_xml_parse_attr_enum to parse a
fixed list of possible strings. The list is terminated by an entry
@ -645,7 +655,7 @@ gdb_xml_parse_attr_enum (struct gdb_xml_parser *parser,
void *ret;
for (enums = attribute->handler_data; enums->name != NULL; enums++)
if (strcmp (enums->name, value) == 0)
if (strcasecmp (enums->name, value) == 0)
break;
if (enums->name == NULL)

View File

@ -209,6 +209,9 @@ struct gdb_xml_enum
ULONGEST value;
};
/* A handler_data for yes/no boolean values. */
extern const struct gdb_xml_enum gdb_xml_enums_boolean[];
extern gdb_xml_attribute_handler gdb_xml_parse_attr_enum;
/* Parse an integer string into a ULONGEST and return it, or call

View File

@ -23,6 +23,7 @@
Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "gdbtypes.h"
#include "target.h"
#include "target-descriptions.h"
#include "xml-support.h"
@ -79,6 +80,16 @@ struct tdesc_parsing_data
{
/* The target description we are building. */
struct target_desc *tdesc;
/* The target feature we are currently parsing, or last parsed. */
struct tdesc_feature *current_feature;
/* The register number to use for the next register we see, if
it does not have its own. This starts at zero. */
int next_regnum;
/* The union we are currently parsing, or last parsed. */
struct type *current_union;
};
/* Handle the end of an <architecture> element and its value. */
@ -98,15 +109,233 @@ tdesc_end_arch (struct gdb_xml_parser *parser,
set_tdesc_architecture (data->tdesc, arch);
}
/* Handle the start of a <feature> element. */
static void
tdesc_start_feature (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data, VEC(gdb_xml_value_s) *attributes)
{
struct tdesc_parsing_data *data = user_data;
char *name = VEC_index (gdb_xml_value_s, attributes, 0)->value;
data->current_feature = tdesc_create_feature (data->tdesc, name);
}
/* Handle the start of a <reg> element. Fill in the optional
attributes and attach it to the containing feature. */
static void
tdesc_start_reg (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data, VEC(gdb_xml_value_s) *attributes)
{
struct tdesc_parsing_data *data = user_data;
struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
int ix = 0, length;
char *name, *group, *type;
int bitsize, regnum, save_restore;
length = VEC_length (gdb_xml_value_s, attributes);
name = attrs[ix++].value;
bitsize = * (ULONGEST *) attrs[ix++].value;
if (ix < length && strcmp (attrs[ix].name, "regnum") == 0)
regnum = * (ULONGEST *) attrs[ix++].value;
else
regnum = data->next_regnum;
if (ix < length && strcmp (attrs[ix].name, "type") == 0)
type = attrs[ix++].value;
else
type = "int";
if (ix < length && strcmp (attrs[ix].name, "group") == 0)
group = attrs[ix++].value;
else
group = NULL;
if (ix < length && strcmp (attrs[ix].name, "save-restore") == 0)
save_restore = * (ULONGEST *) attrs[ix++].value;
else
save_restore = 1;
if (strcmp (type, "int") != 0
&& strcmp (type, "float") != 0
&& tdesc_named_type (data->current_feature, type) == NULL)
gdb_xml_error (parser, _("Register \"%s\" has unknown type \"%s\""),
name, type);
tdesc_create_reg (data->current_feature, name, regnum, save_restore, group,
bitsize, type);
data->next_regnum = regnum + 1;
}
/* Handle the start of a <union> element. Initialize the type and
record it with the current feature. */
static void
tdesc_start_union (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data, VEC(gdb_xml_value_s) *attributes)
{
struct tdesc_parsing_data *data = user_data;
char *id = VEC_index (gdb_xml_value_s, attributes, 0)->value;
struct type *type;
type = init_composite_type (NULL, TYPE_CODE_UNION);
TYPE_NAME (type) = xstrdup (id);
tdesc_record_type (data->current_feature, type);
data->current_union = type;
}
/* Handle the end of a <union> element. */
static void
tdesc_end_union (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data, const char *body_text)
{
struct tdesc_parsing_data *data = user_data;
int i;
/* If any of the children of this union are vectors, flag the union
as a vector also. This allows e.g. a union of two vector types
to show up automatically in "info vector". */
for (i = 0; i < TYPE_NFIELDS (data->current_union); i++)
if (TYPE_VECTOR (TYPE_FIELD_TYPE (data->current_union, i)))
{
TYPE_FLAGS (data->current_union) |= TYPE_FLAG_VECTOR;
break;
}
}
/* Handle the start of a <field> element. Attach the field to the
current union. */
static void
tdesc_start_field (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data, VEC(gdb_xml_value_s) *attributes)
{
struct tdesc_parsing_data *data = user_data;
struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
struct type *type, *field_type;
char *field_name, *field_type_id;
field_name = attrs[0].value;
field_type_id = attrs[1].value;
field_type = tdesc_named_type (data->current_feature, field_type_id);
if (field_type == NULL)
gdb_xml_error (parser, _("Union field \"%s\" references undefined "
"type \"%s\""),
field_name, field_type_id);
append_composite_type_field (data->current_union, xstrdup (field_name),
field_type);
}
/* Handle the start of a <vector> element. Initialize the type and
record it with the current feature. */
static void
tdesc_start_vector (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data, VEC(gdb_xml_value_s) *attributes)
{
struct tdesc_parsing_data *data = user_data;
struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
struct type *type, *field_type, *range_type;
char *id, *field_type_id;
int count;
id = attrs[0].value;
field_type_id = attrs[1].value;
count = * (ULONGEST *) attrs[2].value;
field_type = tdesc_named_type (data->current_feature, field_type_id);
if (field_type == NULL)
gdb_xml_error (parser, _("Vector \"%s\" references undefined type \"%s\""),
id, field_type_id);
/* A vector is just an array plus a special flag. */
range_type = create_range_type (NULL, builtin_type_int, 0, count - 1);
type = create_array_type (NULL, field_type, range_type);
TYPE_NAME (type) = xstrdup (id);
TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
tdesc_record_type (data->current_feature, type);
}
/* The elements and attributes of an XML target description. */
const struct gdb_xml_element target_children[] = {
{ "architecture", NULL, NULL, GDB_XML_EF_OPTIONAL,
NULL, tdesc_end_arch },
static const struct gdb_xml_attribute field_attributes[] = {
{ "name", GDB_XML_AF_NONE, NULL, NULL },
{ "type", GDB_XML_AF_NONE, NULL, NULL },
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
static const struct gdb_xml_element union_children[] = {
{ "field", field_attributes, NULL, GDB_XML_EF_REPEATABLE,
tdesc_start_field, NULL },
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};
const struct gdb_xml_element tdesc_elements[] = {
static const struct gdb_xml_attribute reg_attributes[] = {
{ "name", GDB_XML_AF_NONE, NULL, NULL },
{ "bitsize", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
{ "regnum", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
{ "type", GDB_XML_AF_OPTIONAL, NULL, NULL },
{ "group", GDB_XML_AF_OPTIONAL, NULL, NULL },
{ "save-restore", GDB_XML_AF_OPTIONAL,
gdb_xml_parse_attr_enum, gdb_xml_enums_boolean },
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
static const struct gdb_xml_attribute union_attributes[] = {
{ "id", GDB_XML_AF_NONE, NULL, NULL },
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
static const struct gdb_xml_attribute vector_attributes[] = {
{ "id", GDB_XML_AF_NONE, NULL, NULL },
{ "type", GDB_XML_AF_NONE, NULL, NULL },
{ "count", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
static const struct gdb_xml_attribute feature_attributes[] = {
{ "name", GDB_XML_AF_NONE, NULL, NULL },
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
static const struct gdb_xml_element feature_children[] = {
{ "reg", reg_attributes, NULL,
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
tdesc_start_reg, NULL },
{ "union", union_attributes, union_children,
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
tdesc_start_union, tdesc_end_union },
{ "vector", vector_attributes, NULL,
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
tdesc_start_vector, NULL },
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};
static const struct gdb_xml_element target_children[] = {
{ "architecture", NULL, NULL, GDB_XML_EF_OPTIONAL,
NULL, tdesc_end_arch },
{ "feature", feature_attributes, feature_children,
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
tdesc_start_feature, NULL },
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};
static const struct gdb_xml_element tdesc_elements[] = {
{ "target", NULL, target_children, GDB_XML_EF_NONE,
NULL, NULL },
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }