a121b7c1ac
This is the remainder boring constification that all looks more of less borderline obvious IMO. gdb/ChangeLog: 2017-04-05 Pedro Alves <palves@redhat.com> * ada-exp.y (yyerror): Constify. * ada-lang.c (bound_name, get_selections) (ada_variant_discrim_type) (ada_variant_discrim_name, ada_value_struct_elt) (ada_lookup_struct_elt_type, is_unchecked_variant) (ada_which_variant_applies, standard_exc, ada_get_next_arg) (catch_ada_exception_command_split) (catch_ada_assert_command_split, catch_assert_command) (ada_op_name): Constify. * ada-lang.h (ada_yyerror, get_selections) (ada_variant_discrim_name, ada_value_struct_elt): Constify. * arc-tdep.c (arc_print_frame_cache): Constify. * arm-tdep.c (arm_skip_stub): Constify. * ax-gdb.c (gen_binop, gen_struct_ref_recursive, gen_struct_ref) (gen_aggregate_elt_ref): Constify. * bcache.c (print_bcache_statistics): Constify. * bcache.h (print_bcache_statistics): Constify. * break-catch-throw.c (catch_exception_command_1): * breakpoint.c (struct ep_type_description::description): Constify. (add_solib_catchpoint): Constify. (catch_fork_command_1): Add cast. (add_catch_command): Constify. * breakpoint.h (add_catch_command, add_solib_catchpoint): Constify. * bsd-uthread.c (bsd_uthread_state): Constify. * buildsym.c (patch_subfile_names): Constify. * buildsym.h (next_symbol_text_func, patch_subfile_names): Constify. * c-exp.y (yyerror): Constify. (token::oper): Constify. * c-lang.h (c_yyerror, cp_print_class_member): Constify. * c-varobj.c (cplus_describe_child): Constify. * charset.c (find_charset_names): Add cast. (find_charset_names): Constify array and add const_cast. * cli/cli-cmds.c (complete_command, cd_command): Constify. (edit_command): Constify. * cli/cli-decode.c (lookup_cmd): Constify. * cli/cli-dump.c (dump_memory_command, dump_value_command): Constify. (struct dump_context): Constify. (add_dump_command, restore_command): Constify. * cli/cli-script.c (get_command_line): Constify. * cli/cli-script.h (get_command_line): Constify. * cli/cli-utils.c (check_for_argument): Constify. * cli/cli-utils.h (check_for_argument): Constify. * coff-pe-read.c (struct read_pe_section_data): Constify. * command.h (lookup_cmd): Constify. * common/print-utils.c (decimal2str): Constify. * completer.c (gdb_print_filename): Constify. * corefile.c (set_gnutarget): Constify. * cp-name-parser.y (yyerror): Constify. * cp-valprint.c (cp_print_class_member): Constify. * cris-tdep.c (cris_register_name, crisv32_register_name): Constify. * d-exp.y (yyerror): Constify. (struct token::oper): Constify. * d-lang.h (d_yyerror): Constify. * dbxread.c (struct header_file_location::name): Constify. (add_old_header_file, add_new_header_file, last_function_name) (dbx_next_symbol_text, add_bincl_to_list) (find_corresponding_bincl_psymtab, set_namestring) (find_stab_function_addr, read_dbx_symtab, start_psymtab) (dbx_end_psymtab, read_ofile_symtab, process_one_symbol): * defs.h (command_line_input, print_address_symbolic) (deprecated_readline_begin_hook): Constify. * dwarf2read.c (anonymous_struct_prefix, dwarf_bool_name): Constify. * event-top.c (handle_line_of_input): Constify and add cast. * exceptions.c (catch_errors): Constify. * exceptions.h (catch_errors): Constify. * expprint.c (print_subexp_standard, op_string, op_name) (op_name_standard, dump_raw_expression, dump_raw_expression): * expression.h (op_name, op_string, dump_raw_expression): Constify. * f-exp.y (yyerror): Constify. (struct token::oper): Constify. (struct f77_boolean_val::name): Constify. * f-lang.c (f_word_break_characters): Constify. * f-lang.h (f_yyerror): Constify. * fork-child.c (fork_inferior): Add cast. * frv-tdep.c (struct gdbarch_tdep::register_names): Constify. (new_variant): Constify. * gdbarch.sh (pstring_ptr, pstring_list): Constify. * gdbarch.c: Regenerate. * gdbcore.h (set_gnutarget): Constify. * go-exp.y (yyerror): Constify. (token::oper): Constify. * go-lang.h (go_yyerror): Constify. * go32-nat.c (go32_sysinfo): Constify. * guile/scm-breakpoint.c (gdbscm_breakpoint_expression): Constify. * guile/scm-cmd.c (cmdscm_function): Constify. * guile/scm-param.c (pascm_param_value): Constify. * h8300-tdep.c (h8300_register_name, h8300s_register_name) (h8300sx_register_name): Constify. * hppa-tdep.c (hppa32_register_name, hppa64_register_name): Constify. * ia64-tdep.c (ia64_register_names): Constify. * infcmd.c (construct_inferior_arguments): Constify. (path_command, attach_post_wait): Constify. * language.c (show_range_command, show_case_command) (unk_lang_error): Constify. * language.h (language_defn::la_error) (language_defn::la_name_of_this): Constify. * linespec.c (decode_line_2): Constify. * linux-thread-db.c (thread_db_err_str): Constify. * lm32-tdep.c (lm32_register_name): Constify. * m2-exp.y (yyerror): Constify. * m2-lang.h (m2_yyerror): Constify. * m32r-tdep.c (m32r_register_names): Constify and make static. * m68hc11-tdep.c (m68hc11_register_names): Constify. * m88k-tdep.c (m88k_register_name): Constify. * macroexp.c (appendmem): Constify. * mdebugread.c (fdr_name, add_data_symbol, parse_type) (upgrade_type, parse_external, parse_partial_symbols) (mdebug_next_symbol_text, cross_ref, mylookup_symbol, new_psymtab) (new_symbol): Constify. * memattr.c (mem_info_command): Constify. * mep-tdep.c (register_name_from_keyword): Constify. * mi/mi-cmd-env.c (mi_cmd_env_path, _initialize_mi_cmd_env): Constify. * mi/mi-cmd-stack.c (list_args_or_locals): Constify. * mi/mi-cmd-var.c (mi_cmd_var_show_attributes): Constify. * mi/mi-main.c (captured_mi_execute_command): Constify and add cast. (mi_execute_async_cli_command): Constify. * mips-tdep.c (mips_register_name): Constify. * mn10300-tdep.c (register_name, mn10300_generic_register_name) (am33_register_name, am33_2_register_name) * moxie-tdep.c (moxie_register_names): Constify. * nat/linux-osdata.c (osdata_type): Constify fields. * nto-tdep.c (nto_parse_redirection): Constify. * objc-lang.c (lookup_struct_typedef, lookup_objc_class) (lookup_child_selector): Constify. (objc_methcall::name): Constify. * objc-lang.h (lookup_objc_class, lookup_child_selector) (lookup_struct_typedef): Constify. * objfiles.c (pc_in_section): Constify. * objfiles.h (pc_in_section): Constify. * p-exp.y (struct token::oper): Constify. (yyerror): Constify. * p-lang.h (pascal_yyerror): Constify. * parser-defs.h (op_name_standard): Constify. (op_print::string): Constify. (exp_descriptor::op_name): Constify. * printcmd.c (print_address_symbolic): Constify. * psymtab.c (print_partial_symbols): Constify. * python/py-breakpoint.c (stop_func): Constify. (bppy_get_expression): Constify. * python/py-cmd.c (cmdpy_completer::name): Constify. (cmdpy_function): Constify. * python/py-event.c (evpy_add_attribute) (gdbpy_initialize_event_generic): Constify. * python/py-event.h (evpy_add_attribute) (gdbpy_initialize_event_generic): Constify. * python/py-evts.c (add_new_registry): Constify. * python/py-finishbreakpoint.c (outofscope_func): Constify. * python/py-framefilter.c (get_py_iter_from_func): Constify. * python/py-inferior.c (get_buffer): Add cast. * python/py-param.c (parm_constant::name): Constify. * python/py-unwind.c (fprint_frame_id): Constify. * python/python.c (gdbpy_parameter_value): Constify. * remote-fileio.c (remote_fio_func_map): Make 'name' const. * remote.c (memory_packet_config::name): Constify. (show_packet_config_cmd, remote_write_bytes) (remote_buffer_add_string): * reverse.c (exec_reverse_once): Constify. * rs6000-tdep.c (variant::name, variant::description): Constify. * rust-exp.y (rustyyerror): Constify. * rust-lang.c (rust_op_name): Constify. * rust-lang.h (rustyyerror): Constify. * serial.h (serial_ops::name): Constify. * sh-tdep.c (sh_sh_register_name, sh_sh3_register_name) (sh_sh3e_register_name, sh_sh2e_register_name) (sh_sh2a_register_name, sh_sh2a_nofpu_register_name) (sh_sh_dsp_register_name, sh_sh3_dsp_register_name) (sh_sh4_register_name, sh_sh4_nofpu_register_name) (sh_sh4al_dsp_register_name): Constify. * sh64-tdep.c (sh64_register_name): Constify. * solib-darwin.c (lookup_symbol_from_bfd): Constify. * spu-tdep.c (spu_register_name, info_spu_dma_cmdlist): Constify. * stabsread.c (patch_block_stabs, read_type_number) (ref_map::stabs, ref_add, process_reference) (symbol_reference_defined, define_symbol, define_symbol) (error_type, read_type, read_member_functions, read_cpp_abbrev) (read_one_struct_field, read_struct_fields, read_baseclasses) (read_tilde_fields, read_struct_type, read_array_type) (read_enum_type, read_sun_builtin_type, read_sun_floating_type) (read_huge_number, read_range_type, read_args, common_block_start) (find_name_end): Constify. * stabsread.h (common_block_start, define_symbol) (process_one_symbol, symbol_reference_defined, ref_add): * symfile.c (get_section_index, add_symbol_file_command): * symfile.h (get_section_index): Constify. * target-descriptions.c (tdesc_type::name): Constify. (tdesc_free_type): Add cast. * target.c (find_default_run_target): (add_deprecated_target_alias, find_default_run_target) (target_announce_detach): Constify. (do_option): Constify. * target.h (add_deprecated_target_alias): Constify. * thread.c (print_thread_info_1): Constify. * top.c (deprecated_readline_begin_hook, command_line_input): Constify. (init_main): Add casts. * top.h (handle_line_of_input): Constify. * tracefile-tfile.c (tfile_write_uploaded_tsv): Constify. * tracepoint.c (tvariables_info_1, trace_status_mi): Constify. (tfind_command): Rename to ... (tfind_command_1): ... this and constify. (tfind_command): New function. (tfind_end_command, tfind_start_command): Adjust. (encode_source_string): Constify. * tracepoint.h (encode_source_string): Constify. * tui/tui-data.c (tui_partial_win_by_name): Constify. * tui/tui-data.h (tui_partial_win_by_name): Constify. * tui/tui-source.c (tui_set_source_content_nil): Constify. * tui/tui-source.h (tui_set_source_content_nil): Constify. * tui/tui-win.c (parse_scrolling_args): Constify. * tui/tui-windata.c (tui_erase_data_content): Constify. * tui/tui-windata.h (tui_erase_data_content): Constify. * tui/tui-winsource.c (tui_erase_source_content): Constify. * tui/tui.c (tui_enable): Add cast. * utils.c (defaulted_query): Constify. (init_page_info): Add cast. (puts_debug, subset_compare): Constify. * utils.h (subset_compare): Constify. * varobj.c (varobj_format_string): Constify. * varobj.h (varobj_format_string): Constify. * vax-tdep.c (vax_register_name): Constify. * windows-nat.c (windows_detach): Constify. * xcoffread.c (process_linenos, xcoff_next_symbol_text): Constify. * xml-support.c (gdb_xml_end_element): Constify. * xml-tdesc.c (tdesc_start_reg): Constify. * xstormy16-tdep.c (xstormy16_register_name): Constify. * xtensa-tdep.c (xtensa_find_register_by_name): Constify. * xtensa-tdep.h (xtensa_register_t::name): Constify. gdb/gdbserver/ChangeLog: 2017-04-05 Pedro Alves <palves@redhat.com> * gdbreplay.c (sync_error): Constify. * linux-x86-low.c (push_opcode): Constify.
800 lines
24 KiB
C
800 lines
24 KiB
C
/* XML target description support for GDB.
|
||
|
||
Copyright (C) 2006-2017 Free Software Foundation, Inc.
|
||
|
||
Contributed by CodeSourcery.
|
||
|
||
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 3 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, see <http://www.gnu.org/licenses/>. */
|
||
|
||
#include "defs.h"
|
||
#include "target.h"
|
||
#include "target-descriptions.h"
|
||
#include "xml-support.h"
|
||
#include "xml-tdesc.h"
|
||
#include "osabi.h"
|
||
#include "filenames.h"
|
||
|
||
/* Maximum sizes.
|
||
This is just to catch obviously wrong values. */
|
||
#define MAX_FIELD_SIZE 65536
|
||
#define MAX_FIELD_BITSIZE (MAX_FIELD_SIZE * TARGET_CHAR_BIT)
|
||
#define MAX_VECTOR_SIZE 65536
|
||
|
||
#if !defined(HAVE_LIBEXPAT)
|
||
|
||
/* Parse DOCUMENT into a target description. Or don't, since we don't have
|
||
an XML parser. */
|
||
|
||
static struct target_desc *
|
||
tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
|
||
void *fetcher_baton)
|
||
{
|
||
static int have_warned;
|
||
|
||
if (!have_warned)
|
||
{
|
||
have_warned = 1;
|
||
warning (_("Can not parse XML target description; XML support was "
|
||
"disabled at compile time"));
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
#else /* HAVE_LIBEXPAT */
|
||
|
||
/* A record of every XML description we have parsed. We never discard
|
||
old descriptions, because we never discard gdbarches. As long as we
|
||
have a gdbarch referencing this description, we want to have a copy
|
||
of it here, so that if we parse the same XML document again we can
|
||
return the same "struct target_desc *"; if they are not singletons,
|
||
then we will create unnecessary duplicate gdbarches. See
|
||
gdbarch_list_lookup_by_info. */
|
||
|
||
struct tdesc_xml_cache
|
||
{
|
||
const char *xml_document;
|
||
struct target_desc *tdesc;
|
||
};
|
||
typedef struct tdesc_xml_cache tdesc_xml_cache_s;
|
||
DEF_VEC_O(tdesc_xml_cache_s);
|
||
|
||
static VEC(tdesc_xml_cache_s) *xml_cache;
|
||
|
||
/* Callback data for target description parsing. */
|
||
|
||
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 struct or union we are currently parsing, or last parsed. */
|
||
struct tdesc_type *current_type;
|
||
|
||
/* The byte size of the current struct/flags type, if specified. Zero
|
||
if not specified. Flags values must specify a size. */
|
||
int current_type_size;
|
||
};
|
||
|
||
/* Handle the end of an <architecture> element and its value. */
|
||
|
||
static void
|
||
tdesc_end_arch (struct gdb_xml_parser *parser,
|
||
const struct gdb_xml_element *element,
|
||
void *user_data, const char *body_text)
|
||
{
|
||
struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data;
|
||
const struct bfd_arch_info *arch;
|
||
|
||
arch = bfd_scan_arch (body_text);
|
||
if (arch == NULL)
|
||
gdb_xml_error (parser, _("Target description specified unknown "
|
||
"architecture \"%s\""), body_text);
|
||
set_tdesc_architecture (data->tdesc, arch);
|
||
}
|
||
|
||
/* Handle the end of an <osabi> element and its value. */
|
||
|
||
static void
|
||
tdesc_end_osabi (struct gdb_xml_parser *parser,
|
||
const struct gdb_xml_element *element,
|
||
void *user_data, const char *body_text)
|
||
{
|
||
struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data;
|
||
enum gdb_osabi osabi;
|
||
|
||
osabi = osabi_from_tdesc_string (body_text);
|
||
if (osabi == GDB_OSABI_UNKNOWN)
|
||
warning (_("Target description specified unknown osabi \"%s\""),
|
||
body_text);
|
||
else
|
||
set_tdesc_osabi (data->tdesc, osabi);
|
||
}
|
||
|
||
/* Handle the end of a <compatible> element and its value. */
|
||
|
||
static void
|
||
tdesc_end_compatible (struct gdb_xml_parser *parser,
|
||
const struct gdb_xml_element *element,
|
||
void *user_data, const char *body_text)
|
||
{
|
||
struct tdesc_parsing_data *data = (struct tdesc_parsing_data *) user_data;
|
||
const struct bfd_arch_info *arch;
|
||
|
||
arch = bfd_scan_arch (body_text);
|
||
tdesc_add_compatible (data->tdesc, arch);
|
||
}
|
||
|
||
/* Handle the start of a <target> element. */
|
||
|
||
static void
|
||
tdesc_start_target (struct gdb_xml_parser *parser,
|
||
const struct gdb_xml_element *element,
|
||
void *user_data, VEC(gdb_xml_value_s) *attributes)
|
||
{
|
||
char *version = (char *) xml_find_attribute (attributes, "version")->value;
|
||
|
||
if (strcmp (version, "1.0") != 0)
|
||
gdb_xml_error (parser,
|
||
_("Target description has unsupported version \"%s\""),
|
||
version);
|
||
}
|
||
|
||
/* 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 = (struct tdesc_parsing_data *) user_data;
|
||
char *name = (char *) xml_find_attribute (attributes, "name")->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 = (struct tdesc_parsing_data *) user_data;
|
||
struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
|
||
int ix = 0, length;
|
||
char *name, *group;
|
||
const char *type;
|
||
int bitsize, regnum, save_restore;
|
||
|
||
length = VEC_length (gdb_xml_value_s, attributes);
|
||
|
||
name = (char *) 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 = (char *) attrs[ix++].value;
|
||
else
|
||
type = "int";
|
||
|
||
if (ix < length && strcmp (attrs[ix].name, "group") == 0)
|
||
group = (char *) 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 = (struct tdesc_parsing_data *) user_data;
|
||
char *id = (char *) xml_find_attribute (attributes, "id")->value;
|
||
|
||
data->current_type = tdesc_create_union (data->current_feature, id);
|
||
data->current_type_size = 0;
|
||
}
|
||
|
||
/* Handle the start of a <struct> element. Initialize the type and
|
||
record it with the current feature. */
|
||
|
||
static void
|
||
tdesc_start_struct (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 = (struct tdesc_parsing_data *) user_data;
|
||
char *id = (char *) xml_find_attribute (attributes, "id")->value;
|
||
struct tdesc_type *type;
|
||
struct gdb_xml_value *attr;
|
||
|
||
type = tdesc_create_struct (data->current_feature, id);
|
||
data->current_type = type;
|
||
data->current_type_size = 0;
|
||
|
||
attr = xml_find_attribute (attributes, "size");
|
||
if (attr != NULL)
|
||
{
|
||
ULONGEST size = * (ULONGEST *) attr->value;
|
||
|
||
if (size > MAX_FIELD_SIZE)
|
||
{
|
||
gdb_xml_error (parser,
|
||
_("Struct size %s is larger than maximum (%d)"),
|
||
pulongest (size), MAX_FIELD_SIZE);
|
||
}
|
||
tdesc_set_struct_size (type, size);
|
||
data->current_type_size = size;
|
||
}
|
||
}
|
||
|
||
static void
|
||
tdesc_start_flags (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 = (struct tdesc_parsing_data *) user_data;
|
||
char *id = (char *) xml_find_attribute (attributes, "id")->value;
|
||
ULONGEST size = * (ULONGEST *)
|
||
xml_find_attribute (attributes, "size")->value;
|
||
struct tdesc_type *type;
|
||
|
||
if (size > MAX_FIELD_SIZE)
|
||
{
|
||
gdb_xml_error (parser,
|
||
_("Flags size %s is larger than maximum (%d)"),
|
||
pulongest (size), MAX_FIELD_SIZE);
|
||
}
|
||
type = tdesc_create_flags (data->current_feature, id, size);
|
||
|
||
data->current_type = type;
|
||
data->current_type_size = size;
|
||
}
|
||
|
||
static void
|
||
tdesc_start_enum (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 = (struct tdesc_parsing_data *) user_data;
|
||
char *id = (char *) xml_find_attribute (attributes, "id")->value;
|
||
int size = * (ULONGEST *)
|
||
xml_find_attribute (attributes, "size")->value;
|
||
struct tdesc_type *type;
|
||
|
||
if (size > MAX_FIELD_SIZE)
|
||
{
|
||
gdb_xml_error (parser,
|
||
_("Enum size %s is larger than maximum (%d)"),
|
||
pulongest (size), MAX_FIELD_SIZE);
|
||
}
|
||
type = tdesc_create_enum (data->current_feature, id, size);
|
||
|
||
data->current_type = type;
|
||
data->current_type_size = 0;
|
||
}
|
||
|
||
/* Handle the start of a <field> element. Attach the field to the
|
||
current struct, union or flags. */
|
||
|
||
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 = (struct tdesc_parsing_data *) user_data;
|
||
struct gdb_xml_value *attr;
|
||
struct tdesc_type *field_type;
|
||
char *field_name, *field_type_id;
|
||
int start, end;
|
||
|
||
field_name = (char *) xml_find_attribute (attributes, "name")->value;
|
||
|
||
attr = xml_find_attribute (attributes, "type");
|
||
if (attr != NULL)
|
||
{
|
||
field_type_id = (char *) attr->value;
|
||
field_type = tdesc_named_type (data->current_feature, field_type_id);
|
||
}
|
||
else
|
||
{
|
||
field_type_id = NULL;
|
||
field_type = NULL;
|
||
}
|
||
|
||
attr = xml_find_attribute (attributes, "start");
|
||
if (attr != NULL)
|
||
{
|
||
ULONGEST ul_start = * (ULONGEST *) attr->value;
|
||
|
||
if (ul_start > MAX_FIELD_BITSIZE)
|
||
{
|
||
gdb_xml_error (parser,
|
||
_("Field start %s is larger than maximum (%d)"),
|
||
pulongest (ul_start), MAX_FIELD_BITSIZE);
|
||
}
|
||
start = ul_start;
|
||
}
|
||
else
|
||
start = -1;
|
||
|
||
attr = xml_find_attribute (attributes, "end");
|
||
if (attr != NULL)
|
||
{
|
||
ULONGEST ul_end = * (ULONGEST *) attr->value;
|
||
|
||
if (ul_end > MAX_FIELD_BITSIZE)
|
||
{
|
||
gdb_xml_error (parser,
|
||
_("Field end %s is larger than maximum (%d)"),
|
||
pulongest (ul_end), MAX_FIELD_BITSIZE);
|
||
}
|
||
end = ul_end;
|
||
}
|
||
else
|
||
end = -1;
|
||
|
||
if (start != -1)
|
||
{
|
||
struct tdesc_type *t = data->current_type;
|
||
|
||
/* Older versions of gdb can't handle elided end values.
|
||
Stick with that for now, to help ensure backward compatibility.
|
||
E.g., If a newer gdbserver is talking to an older gdb. */
|
||
if (end == -1)
|
||
gdb_xml_error (parser, _("Missing end value"));
|
||
|
||
if (data->current_type_size == 0)
|
||
gdb_xml_error (parser,
|
||
_("Bitfields must live in explicitly sized types"));
|
||
|
||
if (field_type_id != NULL
|
||
&& strcmp (field_type_id, "bool") == 0
|
||
&& start != end)
|
||
{
|
||
gdb_xml_error (parser,
|
||
_("Boolean fields must be one bit in size"));
|
||
}
|
||
|
||
if (end >= 64)
|
||
gdb_xml_error (parser,
|
||
_("Bitfield \"%s\" goes past "
|
||
"64 bits (unsupported)"),
|
||
field_name);
|
||
|
||
/* Assume that the bit numbering in XML is "lsb-zero". Most
|
||
architectures other than PowerPC use this ordering. In the
|
||
future, we can add an XML tag to indicate "msb-zero" numbering. */
|
||
if (start > end)
|
||
gdb_xml_error (parser, _("Bitfield \"%s\" has start after end"),
|
||
field_name);
|
||
if (end >= data->current_type_size * TARGET_CHAR_BIT)
|
||
gdb_xml_error (parser, _("Bitfield \"%s\" does not fit in struct"),
|
||
field_name);
|
||
|
||
if (field_type != NULL)
|
||
tdesc_add_typed_bitfield (t, field_name, start, end, field_type);
|
||
else if (start == end)
|
||
tdesc_add_flag (t, start, field_name);
|
||
else
|
||
tdesc_add_bitfield (t, field_name, start, end);
|
||
}
|
||
else if (start == -1 && end != -1)
|
||
gdb_xml_error (parser, _("End specified but not start"));
|
||
else if (field_type_id != NULL)
|
||
{
|
||
/* TDESC_TYPE_FLAGS values are explicitly sized, so the following test
|
||
catches adding non-bitfield types to flags as well. */
|
||
if (data->current_type_size != 0)
|
||
gdb_xml_error (parser,
|
||
_("Explicitly sized type cannot "
|
||
"contain non-bitfield \"%s\""),
|
||
field_name);
|
||
|
||
if (field_type == NULL)
|
||
gdb_xml_error (parser, _("Field \"%s\" references undefined "
|
||
"type \"%s\""),
|
||
field_name, field_type_id);
|
||
|
||
tdesc_add_field (data->current_type, field_name, field_type);
|
||
}
|
||
else
|
||
gdb_xml_error (parser, _("Field \"%s\" has neither type nor bit position"),
|
||
field_name);
|
||
}
|
||
|
||
/* Handle the start of an <evalue> element. Attach the value to the
|
||
current enum. */
|
||
|
||
static void
|
||
tdesc_start_enum_value (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 = (struct tdesc_parsing_data *) user_data;
|
||
struct gdb_xml_value *attr;
|
||
char *field_name;
|
||
ULONGEST ul_value;
|
||
int value;
|
||
|
||
field_name = (char *) xml_find_attribute (attributes, "name")->value;
|
||
|
||
attr = xml_find_attribute (attributes, "value");
|
||
ul_value = * (ULONGEST *) attr->value;
|
||
if (ul_value > INT_MAX)
|
||
{
|
||
gdb_xml_error (parser,
|
||
_("Enum value %s is larger than maximum (%d)"),
|
||
pulongest (ul_value), INT_MAX);
|
||
}
|
||
value = ul_value;
|
||
|
||
tdesc_add_enum_value (data->current_type, value, field_name);
|
||
}
|
||
|
||
/* 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 = (struct tdesc_parsing_data *) user_data;
|
||
struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
|
||
struct tdesc_type *field_type;
|
||
char *id, *field_type_id;
|
||
ULONGEST count;
|
||
|
||
id = (char *) attrs[0].value;
|
||
field_type_id = (char *) attrs[1].value;
|
||
count = * (ULONGEST *) attrs[2].value;
|
||
|
||
if (count > MAX_VECTOR_SIZE)
|
||
{
|
||
gdb_xml_error (parser,
|
||
_("Vector size %s is larger than maximum (%d)"),
|
||
pulongest (count), MAX_VECTOR_SIZE);
|
||
}
|
||
|
||
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);
|
||
|
||
tdesc_create_vector (data->current_feature, id, field_type, count);
|
||
}
|
||
|
||
/* The elements and attributes of an XML target description. */
|
||
|
||
static const struct gdb_xml_attribute field_attributes[] = {
|
||
{ "name", GDB_XML_AF_NONE, NULL, NULL },
|
||
{ "type", GDB_XML_AF_OPTIONAL, NULL, NULL },
|
||
{ "start", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
|
||
{ "end", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
|
||
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
||
};
|
||
|
||
static const struct gdb_xml_attribute enum_value_attributes[] = {
|
||
{ "name", GDB_XML_AF_NONE, NULL, NULL },
|
||
{ "value", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
|
||
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
||
};
|
||
|
||
static const struct gdb_xml_element struct_union_children[] = {
|
||
{ "field", field_attributes, NULL, GDB_XML_EF_REPEATABLE,
|
||
tdesc_start_field, NULL },
|
||
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
|
||
};
|
||
|
||
static const struct gdb_xml_element enum_children[] = {
|
||
{ "evalue", enum_value_attributes, NULL, GDB_XML_EF_REPEATABLE,
|
||
tdesc_start_enum_value, NULL },
|
||
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
|
||
};
|
||
|
||
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 struct_union_attributes[] = {
|
||
{ "id", GDB_XML_AF_NONE, NULL, NULL },
|
||
{ "size", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL},
|
||
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
||
};
|
||
|
||
static const struct gdb_xml_attribute flags_attributes[] = {
|
||
{ "id", GDB_XML_AF_NONE, NULL, NULL },
|
||
{ "size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL},
|
||
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
||
};
|
||
|
||
static const struct gdb_xml_attribute enum_attributes[] = {
|
||
{ "id", GDB_XML_AF_NONE, NULL, NULL },
|
||
{ "size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, 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 },
|
||
{ "struct", struct_union_attributes, struct_union_children,
|
||
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
|
||
tdesc_start_struct, NULL },
|
||
{ "union", struct_union_attributes, struct_union_children,
|
||
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
|
||
tdesc_start_union, NULL },
|
||
{ "flags", flags_attributes, struct_union_children,
|
||
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
|
||
tdesc_start_flags, NULL },
|
||
{ "enum", enum_attributes, enum_children,
|
||
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
|
||
tdesc_start_enum, NULL },
|
||
{ "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_attribute target_attributes[] = {
|
||
{ "version", GDB_XML_AF_NONE, NULL, NULL },
|
||
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
||
};
|
||
|
||
static const struct gdb_xml_element target_children[] = {
|
||
{ "architecture", NULL, NULL, GDB_XML_EF_OPTIONAL,
|
||
NULL, tdesc_end_arch },
|
||
{ "osabi", NULL, NULL, GDB_XML_EF_OPTIONAL,
|
||
NULL, tdesc_end_osabi },
|
||
{ "compatible", NULL, NULL, GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
|
||
NULL, tdesc_end_compatible },
|
||
{ "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", target_attributes, target_children, GDB_XML_EF_NONE,
|
||
tdesc_start_target, NULL },
|
||
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
|
||
};
|
||
|
||
/* Parse DOCUMENT into a target description and return it. */
|
||
|
||
static struct target_desc *
|
||
tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
|
||
void *fetcher_baton)
|
||
{
|
||
struct cleanup *back_to, *result_cleanup;
|
||
struct tdesc_parsing_data data;
|
||
struct tdesc_xml_cache *cache;
|
||
char *expanded_text;
|
||
int ix;
|
||
|
||
/* Expand all XInclude directives. */
|
||
expanded_text = xml_process_xincludes (_("target description"),
|
||
document, fetcher, fetcher_baton, 0);
|
||
if (expanded_text == NULL)
|
||
{
|
||
warning (_("Could not load XML target description; ignoring"));
|
||
return NULL;
|
||
}
|
||
|
||
/* Check for an exact match in the list of descriptions we have
|
||
previously parsed. strcmp is a slightly inefficient way to
|
||
do this; an SHA-1 checksum would work as well. */
|
||
for (ix = 0; VEC_iterate (tdesc_xml_cache_s, xml_cache, ix, cache); ix++)
|
||
if (strcmp (cache->xml_document, expanded_text) == 0)
|
||
{
|
||
xfree (expanded_text);
|
||
return cache->tdesc;
|
||
}
|
||
|
||
back_to = make_cleanup (null_cleanup, NULL);
|
||
|
||
memset (&data, 0, sizeof (struct tdesc_parsing_data));
|
||
data.tdesc = allocate_target_description ();
|
||
result_cleanup = make_cleanup_free_target_description (data.tdesc);
|
||
make_cleanup (xfree, expanded_text);
|
||
|
||
if (gdb_xml_parse_quick (_("target description"), "gdb-target.dtd",
|
||
tdesc_elements, expanded_text, &data) == 0)
|
||
{
|
||
/* Parsed successfully. */
|
||
struct tdesc_xml_cache new_cache;
|
||
|
||
new_cache.xml_document = expanded_text;
|
||
new_cache.tdesc = data.tdesc;
|
||
VEC_safe_push (tdesc_xml_cache_s, xml_cache, &new_cache);
|
||
discard_cleanups (result_cleanup);
|
||
do_cleanups (back_to);
|
||
return data.tdesc;
|
||
}
|
||
else
|
||
{
|
||
warning (_("Could not load XML target description; ignoring"));
|
||
do_cleanups (back_to);
|
||
return NULL;
|
||
}
|
||
}
|
||
#endif /* HAVE_LIBEXPAT */
|
||
|
||
|
||
/* Read an XML target description from FILENAME. Parse it, and return
|
||
the parsed description. */
|
||
|
||
const struct target_desc *
|
||
file_read_description_xml (const char *filename)
|
||
{
|
||
struct target_desc *tdesc;
|
||
char *tdesc_str;
|
||
struct cleanup *back_to;
|
||
|
||
tdesc_str = xml_fetch_content_from_file (filename, NULL);
|
||
if (tdesc_str == NULL)
|
||
{
|
||
warning (_("Could not open \"%s\""), filename);
|
||
return NULL;
|
||
}
|
||
|
||
back_to = make_cleanup (xfree, tdesc_str);
|
||
|
||
tdesc = tdesc_parse_xml (tdesc_str, xml_fetch_content_from_file,
|
||
(void *) ldirname (filename).c_str ());
|
||
do_cleanups (back_to);
|
||
|
||
return tdesc;
|
||
}
|
||
|
||
/* Read a string representation of available features from the target,
|
||
using TARGET_OBJECT_AVAILABLE_FEATURES. The returned string is
|
||
malloc allocated and NUL-terminated. NAME should be a non-NULL
|
||
string identifying the XML document we want; the top level document
|
||
is "target.xml". Other calls may be performed for the DTD or
|
||
for <xi:include>. */
|
||
|
||
static char *
|
||
fetch_available_features_from_target (const char *name, void *baton_)
|
||
{
|
||
struct target_ops *ops = (struct target_ops *) baton_;
|
||
|
||
/* Read this object as a string. This ensures that a NUL
|
||
terminator is added. */
|
||
return target_read_stralloc (ops,
|
||
TARGET_OBJECT_AVAILABLE_FEATURES,
|
||
name);
|
||
}
|
||
|
||
|
||
/* Read an XML target description using OPS. Parse it, and return the
|
||
parsed description. */
|
||
|
||
const struct target_desc *
|
||
target_read_description_xml (struct target_ops *ops)
|
||
{
|
||
struct target_desc *tdesc;
|
||
char *tdesc_str;
|
||
struct cleanup *back_to;
|
||
|
||
tdesc_str = fetch_available_features_from_target ("target.xml", ops);
|
||
if (tdesc_str == NULL)
|
||
return NULL;
|
||
|
||
back_to = make_cleanup (xfree, tdesc_str);
|
||
tdesc = tdesc_parse_xml (tdesc_str,
|
||
fetch_available_features_from_target,
|
||
ops);
|
||
do_cleanups (back_to);
|
||
|
||
return tdesc;
|
||
}
|
||
|
||
/* Fetches an XML target description using OPS, processing
|
||
includes, but not parsing it. Used to dump whole tdesc
|
||
as a single XML file. */
|
||
|
||
char *
|
||
target_fetch_description_xml (struct target_ops *ops)
|
||
{
|
||
#if !defined(HAVE_LIBEXPAT)
|
||
static int have_warned;
|
||
|
||
if (!have_warned)
|
||
{
|
||
have_warned = 1;
|
||
warning (_("Can not fetch XML target description; XML support was "
|
||
"disabled at compile time"));
|
||
}
|
||
|
||
return NULL;
|
||
#else
|
||
struct target_desc *tdesc;
|
||
char *tdesc_str;
|
||
char *expanded_text;
|
||
struct cleanup *back_to;
|
||
|
||
tdesc_str = fetch_available_features_from_target ("target.xml", ops);
|
||
if (tdesc_str == NULL)
|
||
return NULL;
|
||
|
||
back_to = make_cleanup (xfree, tdesc_str);
|
||
expanded_text = xml_process_xincludes (_("target description"),
|
||
tdesc_str,
|
||
fetch_available_features_from_target, ops, 0);
|
||
do_cleanups (back_to);
|
||
if (expanded_text == NULL)
|
||
{
|
||
warning (_("Could not load XML target description; ignoring"));
|
||
return NULL;
|
||
}
|
||
|
||
return expanded_text;
|
||
#endif
|
||
}
|