17d62b00eSchristos /* Target description support for GDB. 27d62b00eSchristos 3*6881a400Schristos Copyright (C) 2018-2023 Free Software Foundation, Inc. 47d62b00eSchristos 57d62b00eSchristos This file is part of GDB. 67d62b00eSchristos 77d62b00eSchristos This program is free software; you can redistribute it and/or modify 87d62b00eSchristos it under the terms of the GNU General Public License as published by 97d62b00eSchristos the Free Software Foundation; either version 3 of the License, or 107d62b00eSchristos (at your option) any later version. 117d62b00eSchristos 127d62b00eSchristos This program is distributed in the hope that it will be useful, 137d62b00eSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 147d62b00eSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 157d62b00eSchristos GNU General Public License for more details. 167d62b00eSchristos 177d62b00eSchristos You should have received a copy of the GNU General Public License 187d62b00eSchristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 197d62b00eSchristos 207d62b00eSchristos #include "common-defs.h" 217d62b00eSchristos #include "gdbsupport/tdesc.h" 227d62b00eSchristos 237d62b00eSchristos tdesc_reg::tdesc_reg (struct tdesc_feature *feature, const std::string &name_, 247d62b00eSchristos int regnum, int save_restore_, const char *group_, 257d62b00eSchristos int bitsize_, const char *type_) 267d62b00eSchristos : name (name_), target_regnum (regnum), 277d62b00eSchristos save_restore (save_restore_), 287d62b00eSchristos group (group_ != NULL ? group_ : ""), 297d62b00eSchristos bitsize (bitsize_), 307d62b00eSchristos type (type_ != NULL ? type_ : "<unknown>") 317d62b00eSchristos { 327d62b00eSchristos /* If the register's type is target-defined, look it up now. We may not 337d62b00eSchristos have easy access to the containing feature when we want it later. */ 347d62b00eSchristos tdesc_type = tdesc_named_type (feature, type.c_str ()); 357d62b00eSchristos } 367d62b00eSchristos 377d62b00eSchristos /* Predefined types. */ 387d62b00eSchristos static tdesc_type_builtin tdesc_predefined_types[] = 397d62b00eSchristos { 407d62b00eSchristos { "bool", TDESC_TYPE_BOOL }, 417d62b00eSchristos { "int8", TDESC_TYPE_INT8 }, 427d62b00eSchristos { "int16", TDESC_TYPE_INT16 }, 437d62b00eSchristos { "int32", TDESC_TYPE_INT32 }, 447d62b00eSchristos { "int64", TDESC_TYPE_INT64 }, 457d62b00eSchristos { "int128", TDESC_TYPE_INT128 }, 467d62b00eSchristos { "uint8", TDESC_TYPE_UINT8 }, 477d62b00eSchristos { "uint16", TDESC_TYPE_UINT16 }, 487d62b00eSchristos { "uint32", TDESC_TYPE_UINT32 }, 497d62b00eSchristos { "uint64", TDESC_TYPE_UINT64 }, 507d62b00eSchristos { "uint128", TDESC_TYPE_UINT128 }, 517d62b00eSchristos { "code_ptr", TDESC_TYPE_CODE_PTR }, 527d62b00eSchristos { "data_ptr", TDESC_TYPE_DATA_PTR }, 537d62b00eSchristos { "ieee_half", TDESC_TYPE_IEEE_HALF }, 547d62b00eSchristos { "ieee_single", TDESC_TYPE_IEEE_SINGLE }, 557d62b00eSchristos { "ieee_double", TDESC_TYPE_IEEE_DOUBLE }, 567d62b00eSchristos { "arm_fpa_ext", TDESC_TYPE_ARM_FPA_EXT }, 577d62b00eSchristos { "i387_ext", TDESC_TYPE_I387_EXT }, 587d62b00eSchristos { "bfloat16", TDESC_TYPE_BFLOAT16 } 597d62b00eSchristos }; 607d62b00eSchristos 617d62b00eSchristos void tdesc_feature::accept (tdesc_element_visitor &v) const 627d62b00eSchristos { 637d62b00eSchristos v.visit_pre (this); 647d62b00eSchristos 657d62b00eSchristos for (const tdesc_type_up &type : types) 667d62b00eSchristos type->accept (v); 677d62b00eSchristos 687d62b00eSchristos for (const tdesc_reg_up ® : registers) 697d62b00eSchristos reg->accept (v); 707d62b00eSchristos 717d62b00eSchristos v.visit_post (this); 727d62b00eSchristos } 737d62b00eSchristos 747d62b00eSchristos bool tdesc_feature::operator== (const tdesc_feature &other) const 757d62b00eSchristos { 767d62b00eSchristos if (name != other.name) 777d62b00eSchristos return false; 787d62b00eSchristos 797d62b00eSchristos if (registers.size () != other.registers.size ()) 807d62b00eSchristos return false; 817d62b00eSchristos 827d62b00eSchristos for (int ix = 0; ix < registers.size (); ix++) 837d62b00eSchristos { 847d62b00eSchristos const tdesc_reg_up ®1 = registers[ix]; 857d62b00eSchristos const tdesc_reg_up ®2 = other.registers[ix]; 867d62b00eSchristos 877d62b00eSchristos if (reg1 != reg2 && *reg1 != *reg2) 887d62b00eSchristos return false; 897d62b00eSchristos } 907d62b00eSchristos 917d62b00eSchristos if (types.size () != other.types.size ()) 927d62b00eSchristos return false; 937d62b00eSchristos 947d62b00eSchristos for (int ix = 0; ix < types.size (); ix++) 957d62b00eSchristos { 967d62b00eSchristos const tdesc_type_up &type1 = types[ix]; 977d62b00eSchristos const tdesc_type_up &type2 = other.types[ix]; 987d62b00eSchristos 997d62b00eSchristos if (type1 != type2 && *type1 != *type2) 1007d62b00eSchristos return false; 1017d62b00eSchristos } 1027d62b00eSchristos 1037d62b00eSchristos return true; 1047d62b00eSchristos } 1057d62b00eSchristos 1067d62b00eSchristos /* Lookup a predefined type. */ 1077d62b00eSchristos 1087d62b00eSchristos static struct tdesc_type * 1097d62b00eSchristos tdesc_predefined_type (enum tdesc_type_kind kind) 1107d62b00eSchristos { 1117d62b00eSchristos for (int ix = 0; ix < ARRAY_SIZE (tdesc_predefined_types); ix++) 1127d62b00eSchristos if (tdesc_predefined_types[ix].kind == kind) 1137d62b00eSchristos return &tdesc_predefined_types[ix]; 1147d62b00eSchristos 1157d62b00eSchristos gdb_assert_not_reached ("bad predefined tdesc type"); 1167d62b00eSchristos } 1177d62b00eSchristos 1187d62b00eSchristos /* See gdbsupport/tdesc.h. */ 1197d62b00eSchristos 1207d62b00eSchristos struct tdesc_type * 1217d62b00eSchristos tdesc_named_type (const struct tdesc_feature *feature, const char *id) 1227d62b00eSchristos { 1237d62b00eSchristos /* First try target-defined types. */ 1247d62b00eSchristos for (const tdesc_type_up &type : feature->types) 1257d62b00eSchristos if (type->name == id) 1267d62b00eSchristos return type.get (); 1277d62b00eSchristos 1287d62b00eSchristos /* Next try the predefined types. */ 1297d62b00eSchristos for (int ix = 0; ix < ARRAY_SIZE (tdesc_predefined_types); ix++) 1307d62b00eSchristos if (tdesc_predefined_types[ix].name == id) 1317d62b00eSchristos return &tdesc_predefined_types[ix]; 1327d62b00eSchristos 1337d62b00eSchristos return NULL; 1347d62b00eSchristos } 1357d62b00eSchristos 1367d62b00eSchristos /* See gdbsupport/tdesc.h. */ 1377d62b00eSchristos 1387d62b00eSchristos void 1397d62b00eSchristos tdesc_create_reg (struct tdesc_feature *feature, const char *name, 1407d62b00eSchristos int regnum, int save_restore, const char *group, 1417d62b00eSchristos int bitsize, const char *type) 1427d62b00eSchristos { 1437d62b00eSchristos tdesc_reg *reg = new tdesc_reg (feature, name, regnum, save_restore, 1447d62b00eSchristos group, bitsize, type); 1457d62b00eSchristos 1467d62b00eSchristos feature->registers.emplace_back (reg); 1477d62b00eSchristos } 1487d62b00eSchristos 1497d62b00eSchristos /* See gdbsupport/tdesc.h. */ 1507d62b00eSchristos 1517d62b00eSchristos struct tdesc_type * 1527d62b00eSchristos tdesc_create_vector (struct tdesc_feature *feature, const char *name, 1537d62b00eSchristos struct tdesc_type *field_type, int count) 1547d62b00eSchristos { 1557d62b00eSchristos tdesc_type_vector *type = new tdesc_type_vector (name, field_type, count); 1567d62b00eSchristos feature->types.emplace_back (type); 1577d62b00eSchristos 1587d62b00eSchristos return type; 1597d62b00eSchristos } 1607d62b00eSchristos 1617d62b00eSchristos /* See gdbsupport/tdesc.h. */ 1627d62b00eSchristos 1637d62b00eSchristos tdesc_type_with_fields * 1647d62b00eSchristos tdesc_create_struct (struct tdesc_feature *feature, const char *name) 1657d62b00eSchristos { 1667d62b00eSchristos tdesc_type_with_fields *type 1677d62b00eSchristos = new tdesc_type_with_fields (name, TDESC_TYPE_STRUCT); 1687d62b00eSchristos feature->types.emplace_back (type); 1697d62b00eSchristos 1707d62b00eSchristos return type; 1717d62b00eSchristos } 1727d62b00eSchristos 1737d62b00eSchristos /* See gdbsupport/tdesc.h. */ 1747d62b00eSchristos 1757d62b00eSchristos void 1767d62b00eSchristos tdesc_set_struct_size (tdesc_type_with_fields *type, int size) 1777d62b00eSchristos { 1787d62b00eSchristos gdb_assert (type->kind == TDESC_TYPE_STRUCT); 1797d62b00eSchristos gdb_assert (size > 0); 1807d62b00eSchristos type->size = size; 1817d62b00eSchristos } 1827d62b00eSchristos 1837d62b00eSchristos /* See gdbsupport/tdesc.h. */ 1847d62b00eSchristos 1857d62b00eSchristos tdesc_type_with_fields * 1867d62b00eSchristos tdesc_create_union (struct tdesc_feature *feature, const char *name) 1877d62b00eSchristos { 1887d62b00eSchristos tdesc_type_with_fields *type 1897d62b00eSchristos = new tdesc_type_with_fields (name, TDESC_TYPE_UNION); 1907d62b00eSchristos feature->types.emplace_back (type); 1917d62b00eSchristos 1927d62b00eSchristos return type; 1937d62b00eSchristos } 1947d62b00eSchristos 1957d62b00eSchristos /* See gdbsupport/tdesc.h. */ 1967d62b00eSchristos 1977d62b00eSchristos tdesc_type_with_fields * 1987d62b00eSchristos tdesc_create_flags (struct tdesc_feature *feature, const char *name, 1997d62b00eSchristos int size) 2007d62b00eSchristos { 2017d62b00eSchristos gdb_assert (size > 0); 2027d62b00eSchristos 2037d62b00eSchristos tdesc_type_with_fields *type 2047d62b00eSchristos = new tdesc_type_with_fields (name, TDESC_TYPE_FLAGS, size); 2057d62b00eSchristos feature->types.emplace_back (type); 2067d62b00eSchristos 2077d62b00eSchristos return type; 2087d62b00eSchristos } 2097d62b00eSchristos 2107d62b00eSchristos /* See gdbsupport/tdesc.h. */ 2117d62b00eSchristos 2127d62b00eSchristos tdesc_type_with_fields * 2137d62b00eSchristos tdesc_create_enum (struct tdesc_feature *feature, const char *name, 2147d62b00eSchristos int size) 2157d62b00eSchristos { 2167d62b00eSchristos gdb_assert (size > 0); 2177d62b00eSchristos 2187d62b00eSchristos tdesc_type_with_fields *type 2197d62b00eSchristos = new tdesc_type_with_fields (name, TDESC_TYPE_ENUM, size); 2207d62b00eSchristos feature->types.emplace_back (type); 2217d62b00eSchristos 2227d62b00eSchristos return type; 2237d62b00eSchristos } 2247d62b00eSchristos 2257d62b00eSchristos /* See gdbsupport/tdesc.h. */ 2267d62b00eSchristos 2277d62b00eSchristos void 2287d62b00eSchristos tdesc_add_field (tdesc_type_with_fields *type, const char *field_name, 2297d62b00eSchristos struct tdesc_type *field_type) 2307d62b00eSchristos { 2317d62b00eSchristos gdb_assert (type->kind == TDESC_TYPE_UNION 2327d62b00eSchristos || type->kind == TDESC_TYPE_STRUCT); 2337d62b00eSchristos 2347d62b00eSchristos /* Initialize start and end so we know this is not a bit-field 2357d62b00eSchristos when we print-c-tdesc. */ 2367d62b00eSchristos type->fields.emplace_back (field_name, field_type, -1, -1); 2377d62b00eSchristos } 2387d62b00eSchristos 2397d62b00eSchristos /* See gdbsupport/tdesc.h. */ 2407d62b00eSchristos 2417d62b00eSchristos void 2427d62b00eSchristos tdesc_add_typed_bitfield (tdesc_type_with_fields *type, const char *field_name, 2437d62b00eSchristos int start, int end, struct tdesc_type *field_type) 2447d62b00eSchristos { 2457d62b00eSchristos gdb_assert (type->kind == TDESC_TYPE_STRUCT 2467d62b00eSchristos || type->kind == TDESC_TYPE_FLAGS); 2477d62b00eSchristos gdb_assert (start >= 0 && end >= start); 2487d62b00eSchristos 2497d62b00eSchristos type->fields.emplace_back (field_name, field_type, start, end); 2507d62b00eSchristos } 2517d62b00eSchristos 2527d62b00eSchristos /* See gdbsupport/tdesc.h. */ 2537d62b00eSchristos 2547d62b00eSchristos void 2557d62b00eSchristos tdesc_add_bitfield (tdesc_type_with_fields *type, const char *field_name, 2567d62b00eSchristos int start, int end) 2577d62b00eSchristos { 2587d62b00eSchristos struct tdesc_type *field_type; 2597d62b00eSchristos 2607d62b00eSchristos gdb_assert (start >= 0 && end >= start); 2617d62b00eSchristos 2627d62b00eSchristos if (type->size > 4) 2637d62b00eSchristos field_type = tdesc_predefined_type (TDESC_TYPE_UINT64); 2647d62b00eSchristos else 2657d62b00eSchristos field_type = tdesc_predefined_type (TDESC_TYPE_UINT32); 2667d62b00eSchristos 2677d62b00eSchristos tdesc_add_typed_bitfield (type, field_name, start, end, field_type); 2687d62b00eSchristos } 2697d62b00eSchristos 2707d62b00eSchristos /* See gdbsupport/tdesc.h. */ 2717d62b00eSchristos 2727d62b00eSchristos void 2737d62b00eSchristos tdesc_add_flag (tdesc_type_with_fields *type, int start, 2747d62b00eSchristos const char *flag_name) 2757d62b00eSchristos { 2767d62b00eSchristos gdb_assert (type->kind == TDESC_TYPE_FLAGS 2777d62b00eSchristos || type->kind == TDESC_TYPE_STRUCT); 2787d62b00eSchristos 2797d62b00eSchristos type->fields.emplace_back (flag_name, 2807d62b00eSchristos tdesc_predefined_type (TDESC_TYPE_BOOL), 2817d62b00eSchristos start, start); 2827d62b00eSchristos } 2837d62b00eSchristos 2847d62b00eSchristos /* See gdbsupport/tdesc.h. */ 2857d62b00eSchristos 2867d62b00eSchristos void 2877d62b00eSchristos tdesc_add_enum_value (tdesc_type_with_fields *type, int value, 2887d62b00eSchristos const char *name) 2897d62b00eSchristos { 2907d62b00eSchristos gdb_assert (type->kind == TDESC_TYPE_ENUM); 2917d62b00eSchristos type->fields.emplace_back (name, 2927d62b00eSchristos tdesc_predefined_type (TDESC_TYPE_INT32), 2937d62b00eSchristos value, -1); 2947d62b00eSchristos } 2957d62b00eSchristos 2967d62b00eSchristos void print_xml_feature::visit_pre (const tdesc_feature *e) 2977d62b00eSchristos { 2987d62b00eSchristos add_line ("<feature name=\"%s\">", e->name.c_str ()); 2997d62b00eSchristos indent (1); 3007d62b00eSchristos } 3017d62b00eSchristos 3027d62b00eSchristos void print_xml_feature::visit_post (const tdesc_feature *e) 3037d62b00eSchristos { 3047d62b00eSchristos indent (-1); 3057d62b00eSchristos add_line ("</feature>"); 3067d62b00eSchristos } 3077d62b00eSchristos 3087d62b00eSchristos void print_xml_feature::visit (const tdesc_type_builtin *t) 3097d62b00eSchristos { 3107d62b00eSchristos error (_("xml output is not supported for type \"%s\"."), t->name.c_str ()); 3117d62b00eSchristos } 3127d62b00eSchristos 3137d62b00eSchristos void print_xml_feature::visit (const tdesc_type_vector *t) 3147d62b00eSchristos { 3157d62b00eSchristos add_line ("<vector id=\"%s\" type=\"%s\" count=\"%d\"/>", 3167d62b00eSchristos t->name.c_str (), t->element_type->name.c_str (), t->count); 3177d62b00eSchristos } 3187d62b00eSchristos 3197d62b00eSchristos void print_xml_feature::visit (const tdesc_type_with_fields *t) 3207d62b00eSchristos { 3217d62b00eSchristos const static char *types[] = { "struct", "union", "flags", "enum" }; 3227d62b00eSchristos 3237d62b00eSchristos gdb_assert (t->kind >= TDESC_TYPE_STRUCT && t->kind <= TDESC_TYPE_ENUM); 3247d62b00eSchristos 3257d62b00eSchristos std::string tmp; 3267d62b00eSchristos 3277d62b00eSchristos string_appendf (tmp, 3287d62b00eSchristos "<%s id=\"%s\"", types[t->kind - TDESC_TYPE_STRUCT], 3297d62b00eSchristos t->name.c_str ()); 3307d62b00eSchristos 3317d62b00eSchristos switch (t->kind) 3327d62b00eSchristos { 3337d62b00eSchristos case TDESC_TYPE_STRUCT: 3347d62b00eSchristos case TDESC_TYPE_FLAGS: 3357d62b00eSchristos if (t->size > 0) 3367d62b00eSchristos string_appendf (tmp, " size=\"%d\"", t->size); 3377d62b00eSchristos string_appendf (tmp, ">"); 3387d62b00eSchristos add_line (tmp); 3397d62b00eSchristos 3407d62b00eSchristos for (const tdesc_type_field &f : t->fields) 3417d62b00eSchristos { 3427d62b00eSchristos tmp.clear (); 3437d62b00eSchristos string_appendf (tmp, " <field name=\"%s\"", f.name.c_str ()); 3447d62b00eSchristos if (f.start != -1) 3457d62b00eSchristos string_appendf (tmp, " start=\"%d\" end=\"%d\"", f.start, 3467d62b00eSchristos f.end); 3477d62b00eSchristos string_appendf (tmp, " type=\"%s\"/>", 3487d62b00eSchristos f.type->name.c_str ()); 3497d62b00eSchristos add_line (tmp); 3507d62b00eSchristos } 3517d62b00eSchristos break; 3527d62b00eSchristos 3537d62b00eSchristos case TDESC_TYPE_ENUM: 354*6881a400Schristos if (t->size > 0) 355*6881a400Schristos string_appendf (tmp, " size=\"%d\"", t->size); 3567d62b00eSchristos string_appendf (tmp, ">"); 3577d62b00eSchristos add_line (tmp); 358*6881a400Schristos /* The 'start' of the field is reused as the enum value. The 'end' 359*6881a400Schristos of the field is always set to -1 for enum values. */ 3607d62b00eSchristos for (const tdesc_type_field &f : t->fields) 361*6881a400Schristos add_line (" <evalue name=\"%s\" value=\"%d\"/>", 3627d62b00eSchristos f.name.c_str (), f.start); 3637d62b00eSchristos break; 3647d62b00eSchristos 3657d62b00eSchristos case TDESC_TYPE_UNION: 3667d62b00eSchristos string_appendf (tmp, ">"); 3677d62b00eSchristos add_line (tmp); 3687d62b00eSchristos for (const tdesc_type_field &f : t->fields) 3697d62b00eSchristos add_line (" <field name=\"%s\" type=\"%s\"/>", 3707d62b00eSchristos f.name.c_str (), f.type->name.c_str ()); 3717d62b00eSchristos break; 3727d62b00eSchristos 3737d62b00eSchristos default: 3747d62b00eSchristos error (_("xml output is not supported for type \"%s\"."), 3757d62b00eSchristos t->name.c_str ()); 3767d62b00eSchristos } 3777d62b00eSchristos 3787d62b00eSchristos add_line ("</%s>", types[t->kind - TDESC_TYPE_STRUCT]); 3797d62b00eSchristos } 3807d62b00eSchristos 3817d62b00eSchristos void print_xml_feature::visit (const tdesc_reg *r) 3827d62b00eSchristos { 3837d62b00eSchristos std::string tmp; 3847d62b00eSchristos 3857d62b00eSchristos string_appendf (tmp, 3867d62b00eSchristos "<reg name=\"%s\" bitsize=\"%d\" type=\"%s\" regnum=\"%ld\"", 3877d62b00eSchristos r->name.c_str (), r->bitsize, r->type.c_str (), 3887d62b00eSchristos r->target_regnum); 3897d62b00eSchristos 3907d62b00eSchristos if (r->group.length () > 0) 3917d62b00eSchristos string_appendf (tmp, " group=\"%s\"", r->group.c_str ()); 3927d62b00eSchristos 3937d62b00eSchristos if (r->save_restore == 0) 3947d62b00eSchristos string_appendf (tmp, " save-restore=\"no\""); 3957d62b00eSchristos 3967d62b00eSchristos string_appendf (tmp, "/>"); 3977d62b00eSchristos 3987d62b00eSchristos add_line (tmp); 3997d62b00eSchristos } 4007d62b00eSchristos 4017d62b00eSchristos void print_xml_feature::visit_pre (const target_desc *e) 4027d62b00eSchristos { 4037d62b00eSchristos #ifndef IN_PROCESS_AGENT 4047d62b00eSchristos add_line ("<?xml version=\"1.0\"?>"); 4057d62b00eSchristos add_line ("<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"); 4067d62b00eSchristos add_line ("<target>"); 4077d62b00eSchristos indent (1); 4087d62b00eSchristos if (tdesc_architecture_name (e)) 4097d62b00eSchristos add_line ("<architecture>%s</architecture>", 4107d62b00eSchristos tdesc_architecture_name (e)); 4117d62b00eSchristos 4127d62b00eSchristos const char *osabi = tdesc_osabi_name (e); 4137d62b00eSchristos if (osabi != nullptr) 4147d62b00eSchristos add_line ("<osabi>%s</osabi>", osabi); 4157d62b00eSchristos 4167d62b00eSchristos const std::vector<tdesc_compatible_info_up> &compatible_list 4177d62b00eSchristos = tdesc_compatible_info_list (e); 4187d62b00eSchristos for (const auto &c : compatible_list) 4197d62b00eSchristos add_line ("<compatible>%s</compatible>", 4207d62b00eSchristos tdesc_compatible_info_arch_name (c)); 4217d62b00eSchristos #endif 4227d62b00eSchristos } 4237d62b00eSchristos 4247d62b00eSchristos void print_xml_feature::visit_post (const target_desc *e) 4257d62b00eSchristos { 4267d62b00eSchristos indent (-1); 4277d62b00eSchristos add_line ("</target>"); 4287d62b00eSchristos } 4297d62b00eSchristos 4307d62b00eSchristos /* See gdbsupport/tdesc.h. */ 4317d62b00eSchristos 4327d62b00eSchristos void 4337d62b00eSchristos print_xml_feature::add_line (const std::string &str) 4347d62b00eSchristos { 4357d62b00eSchristos string_appendf (*m_buffer, "%*s", m_depth, ""); 4367d62b00eSchristos string_appendf (*m_buffer, "%s", str.c_str ()); 4377d62b00eSchristos string_appendf (*m_buffer, "\n"); 4387d62b00eSchristos } 4397d62b00eSchristos 4407d62b00eSchristos /* See gdbsupport/tdesc.h. */ 4417d62b00eSchristos 4427d62b00eSchristos void 4437d62b00eSchristos print_xml_feature::add_line (const char *fmt, ...) 4447d62b00eSchristos { 4457d62b00eSchristos std::string tmp; 4467d62b00eSchristos 4477d62b00eSchristos va_list ap; 4487d62b00eSchristos va_start (ap, fmt); 4497d62b00eSchristos string_vappendf (tmp, fmt, ap); 4507d62b00eSchristos va_end (ap); 4517d62b00eSchristos add_line (tmp); 4527d62b00eSchristos } 453