/* Dynamic architecture support for GDB, the GNU debugger.
- Copyright (C) 1998-2017 Free Software Foundation, Inc.
+ Copyright (C) 1998-2023 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "arch-utils.h"
-#include "buildsym.h"
#include "gdbcmd.h"
#include "inferior.h" /* enum CALL_DUMMY_LOCATION et al. */
#include "infrun.h"
#include "objfiles.h"
#include "language.h"
#include "symtab.h"
+#include "dummy-frame.h"
+#include "frame-unwind.h"
+#include "reggroups.h"
+#include "auxv.h"
+#include "observable.h"
+#include "solib-target.h"
-#include "version.h"
+#include "gdbsupport/version.h"
#include "floatformat.h"
+#include "dis-asm.h"
-struct displaced_step_closure *
-simple_displaced_step_copy_insn (struct gdbarch *gdbarch,
- CORE_ADDR from, CORE_ADDR to,
- struct regcache *regs)
-{
- size_t len = gdbarch_max_insn_length (gdbarch);
- gdb_byte *buf = (gdb_byte *) xmalloc (len);
-
- read_memory (from, buf, len);
- write_memory (to, buf, len);
-
- if (debug_displaced)
- {
- fprintf_unfiltered (gdb_stdlog, "displaced: copy %s->%s: ",
- paddress (gdbarch, from), paddress (gdbarch, to));
- displaced_step_dump_bytes (gdb_stdlog, buf, len);
- }
-
- return (struct displaced_step_closure *) buf;
-}
-
-
-void
-simple_displaced_step_free_closure (struct gdbarch *gdbarch,
- struct displaced_step_closure *closure)
-{
- xfree (closure);
-}
-
-int
-default_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
- struct displaced_step_closure *closure)
+bool
+default_displaced_step_hw_singlestep (struct gdbarch *gdbarch)
{
return !gdbarch_software_single_step_p (gdbarch);
}
gdb_assert (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch));
/* NOTE: cagney/2002-05-13: The old code did it this way and it is
suspected that some GDB/SIM combinations may rely on this
- behavour. The default should be one2one_register_sim_regno
+ behaviour. The default should be one2one_register_sim_regno
(below). */
- if (gdbarch_register_name (gdbarch, regnum) != NULL
- && gdbarch_register_name (gdbarch, regnum)[0] != '\0')
+ if (gdbarch_register_name (gdbarch, regnum)[0] != '\0')
return regnum;
else
return LEGACY_SIM_REGNO_IGNORE;
}
+/* See arch-utils.h */
+
CORE_ADDR
-generic_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
+default_remove_non_address_bits (struct gdbarch *gdbarch, CORE_ADDR pointer)
+{
+ /* By default, just return the pointer value. */
+ return pointer;
+}
+
+/* See arch-utils.h */
+
+std::string
+default_memtag_to_string (struct gdbarch *gdbarch, struct value *tag)
+{
+ error (_("This architecture has no method to convert a memory tag to"
+ " a string."));
+}
+
+/* See arch-utils.h */
+
+bool
+default_tagged_address_p (struct gdbarch *gdbarch, struct value *address)
+{
+ /* By default, assume the address is untagged. */
+ return false;
+}
+
+/* See arch-utils.h */
+
+bool
+default_memtag_matches_p (struct gdbarch *gdbarch, struct value *address)
+{
+ /* By default, assume the tags match. */
+ return true;
+}
+
+/* See arch-utils.h */
+
+bool
+default_set_memtags (struct gdbarch *gdbarch, struct value *address,
+ size_t length, const gdb::byte_vector &tags,
+ memtag_type tag_type)
+{
+ /* By default, return true (successful); */
+ return true;
+}
+
+/* See arch-utils.h */
+
+struct value *
+default_get_memtag (struct gdbarch *gdbarch, struct value *address,
+ memtag_type tag_type)
+{
+ /* By default, return no tag. */
+ return nullptr;
+}
+
+CORE_ADDR
+generic_skip_trampoline_code (frame_info_ptr frame, CORE_ADDR pc)
{
return 0;
}
int
default_code_of_frame_writable (struct gdbarch *gdbarch,
- struct frame_info *frame)
+ frame_info_ptr frame)
{
return 1;
}
return addr;
}
+/* See arch-utils.h. */
+
+bool
+default_execute_dwarf_cfa_vendor_op (struct gdbarch *gdbarch, gdb_byte op,
+ struct dwarf2_frame_state *fs)
+{
+ return false;
+}
+
int
cannot_register_not (struct gdbarch *gdbarch, int regnum)
{
*frame_regnum = gdbarch_deprecated_fp_regnum (gdbarch);
else if (gdbarch_sp_regnum (gdbarch) >= 0
&& gdbarch_sp_regnum (gdbarch)
- < gdbarch_num_regs (gdbarch))
+ < gdbarch_num_regs (gdbarch))
*frame_regnum = gdbarch_sp_regnum (gdbarch);
else
/* Should this be an internal error? I guess so, it is reflecting
an architectural limitation in the current design. */
- internal_error (__FILE__, __LINE__,
- _("No virtual frame pointer available"));
+ internal_error (_("No virtual frame pointer available"));
*frame_offset = 0;
}
+/* Return a floating-point format for a floating-point variable of
+ length LEN in bits. If non-NULL, NAME is the name of its type.
+ If no suitable type is found, return NULL. */
+
+const struct floatformat **
+default_floatformat_for_type (struct gdbarch *gdbarch,
+ const char *name, int len)
+{
+ const struct floatformat **format = NULL;
+
+ /* Check if this is a bfloat16 type. It has the same size as the
+ IEEE half float type, so we use the base type name to tell them
+ apart. */
+ if (name != nullptr && strcmp (name, "__bf16") == 0
+ && len == gdbarch_bfloat16_bit (gdbarch))
+ format = gdbarch_bfloat16_format (gdbarch);
+ else if (len == gdbarch_half_bit (gdbarch))
+ format = gdbarch_half_format (gdbarch);
+ else if (len == gdbarch_float_bit (gdbarch))
+ format = gdbarch_float_format (gdbarch);
+ else if (len == gdbarch_double_bit (gdbarch))
+ format = gdbarch_double_format (gdbarch);
+ else if (len == gdbarch_long_double_bit (gdbarch))
+ format = gdbarch_long_double_format (gdbarch);
+ /* On i386 the 'long double' type takes 96 bits,
+ while the real number of used bits is only 80,
+ both in processor and in memory.
+ The code below accepts the real bit size. */
+ else if (gdbarch_long_double_format (gdbarch) != NULL
+ && len == gdbarch_long_double_format (gdbarch)[0]->totalsize)
+ format = gdbarch_long_double_format (gdbarch);
+
+ return format;
+}
\f
int
generic_convert_register_p (struct gdbarch *gdbarch, int regnum,
endian_auto,
NULL,
};
-static const char *set_endian_string;
+static const char *set_endian_string = endian_auto;
enum bfd_endian
selected_byte_order (void)
{
if (target_byte_order_user == BFD_ENDIAN_UNKNOWN)
if (gdbarch_byte_order (get_current_arch ()) == BFD_ENDIAN_BIG)
- fprintf_unfiltered (file, _("The target endianness is set automatically "
- "(currently big endian)\n"));
+ gdb_printf (file, _("The target endianness is set automatically "
+ "(currently big endian).\n"));
else
- fprintf_unfiltered (file, _("The target endianness is set automatically "
- "(currently little endian)\n"));
+ gdb_printf (file, _("The target endianness is set automatically "
+ "(currently little endian).\n"));
else
if (target_byte_order_user == BFD_ENDIAN_BIG)
- fprintf_unfiltered (file,
- _("The target is assumed to be big endian\n"));
+ gdb_printf (file,
+ _("The target is set to big endian.\n"));
else
- fprintf_unfiltered (file,
- _("The target is assumed to be little endian\n"));
+ gdb_printf (file,
+ _("The target is set to little endian.\n"));
}
static void
-set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c)
+set_endian (const char *ignore_args, int from_tty, struct cmd_list_element *c)
{
struct gdbarch_info info;
- gdbarch_info_init (&info);
-
if (set_endian_string == endian_auto)
{
target_byte_order_user = BFD_ENDIAN_UNKNOWN;
if (! gdbarch_update_p (info))
- internal_error (__FILE__, __LINE__,
- _("set_endian: architecture update failed"));
+ internal_error (_("set_endian: architecture update failed"));
}
else if (set_endian_string == endian_little)
{
info.byte_order = BFD_ENDIAN_LITTLE;
if (! gdbarch_update_p (info))
- printf_unfiltered (_("Little endian target not supported by GDB\n"));
+ gdb_printf (gdb_stderr,
+ _("Little endian target not supported by GDB\n"));
else
target_byte_order_user = BFD_ENDIAN_LITTLE;
}
{
info.byte_order = BFD_ENDIAN_BIG;
if (! gdbarch_update_p (info))
- printf_unfiltered (_("Big endian target not supported by GDB\n"));
+ gdb_printf (gdb_stderr,
+ _("Big endian target not supported by GDB\n"));
else
target_byte_order_user = BFD_ENDIAN_BIG;
}
else
- internal_error (__FILE__, __LINE__,
- _("set_endian: bad value"));
+ internal_error (_("set_endian: bad value"));
show_endian (gdb_stdout, from_tty, NULL, NULL);
}
SELECTED may be NULL, in which case we return the architecture
associated with TARGET_DESC. If SELECTED specifies a variant
- of the architecture associtated with TARGET_DESC, return the
+ of the architecture associated with TARGET_DESC, return the
more specific of the two.
If SELECTED is a different architecture, but it is accepted as
struct cmd_list_element *c, const char *value)
{
if (target_architecture_user == NULL)
- fprintf_filtered (file, _("The target architecture is set "
- "automatically (currently %s)\n"),
- gdbarch_bfd_arch_info (get_current_arch ())->printable_name);
+ gdb_printf (file, _("The target architecture is set to "
+ "\"auto\" (currently \"%s\").\n"),
+ gdbarch_bfd_arch_info (get_current_arch ())->printable_name);
else
- fprintf_filtered (file, _("The target architecture is assumed to be %s\n"),
- set_architecture_string);
+ gdb_printf (file, _("The target architecture is set to \"%s\".\n"),
+ set_architecture_string);
}
argument. */
static void
-set_architecture (char *ignore_args, int from_tty, struct cmd_list_element *c)
+set_architecture (const char *ignore_args,
+ int from_tty, struct cmd_list_element *c)
{
struct gdbarch_info info;
- gdbarch_info_init (&info);
-
if (strcmp (set_architecture_string, "auto") == 0)
{
target_architecture_user = NULL;
if (!gdbarch_update_p (info))
- internal_error (__FILE__, __LINE__,
- _("could not select an architecture automatically"));
+ internal_error (_("could not select an architecture automatically"));
}
else
{
info.bfd_arch_info = bfd_scan_arch (set_architecture_string);
if (info.bfd_arch_info == NULL)
- internal_error (__FILE__, __LINE__,
- _("set_architecture: bfd_scan_arch failed"));
+ internal_error (_("set_architecture: bfd_scan_arch failed"));
if (gdbarch_update_p (info))
target_architecture_user = info.bfd_arch_info;
else
- printf_unfiltered (_("Architecture `%s' not recognized.\n"),
- set_architecture_string);
+ gdb_printf (gdb_stderr,
+ _("Architecture `%s' not recognized.\n"),
+ set_architecture_string);
}
show_architecture (gdb_stdout, from_tty, NULL, NULL);
}
/* Check for the current file. */
if (info.abfd == NULL)
- info.abfd = exec_bfd;
+ info.abfd = current_program_space->exec_bfd ();
if (info.abfd == NULL)
info.abfd = core_bfd;
if (new_gdbarch == NULL)
{
if (gdbarch_debug)
- fprintf_unfiltered (gdb_stdlog, "gdbarch_update_p: "
- "Architecture not found\n");
+ gdb_printf (gdb_stdlog, "gdbarch_update_p: "
+ "Architecture not found\n");
return 0;
}
if (new_gdbarch == target_gdbarch ())
{
if (gdbarch_debug)
- fprintf_unfiltered (gdb_stdlog, "gdbarch_update_p: "
- "Architecture %s (%s) unchanged\n",
- host_address_to_string (new_gdbarch),
- gdbarch_bfd_arch_info (new_gdbarch)->printable_name);
+ gdb_printf (gdb_stdlog, "gdbarch_update_p: "
+ "Architecture %s (%s) unchanged\n",
+ host_address_to_string (new_gdbarch),
+ gdbarch_bfd_arch_info (new_gdbarch)->printable_name);
return 1;
}
/* It's a new architecture, swap it in. */
if (gdbarch_debug)
- fprintf_unfiltered (gdb_stdlog, "gdbarch_update_p: "
- "New architecture %s (%s) selected\n",
- host_address_to_string (new_gdbarch),
- gdbarch_bfd_arch_info (new_gdbarch)->printable_name);
+ gdb_printf (gdb_stdlog, "gdbarch_update_p: "
+ "New architecture %s (%s) selected\n",
+ host_address_to_string (new_gdbarch),
+ gdbarch_bfd_arch_info (new_gdbarch)->printable_name);
set_target_gdbarch (new_gdbarch);
return 1;
gdbarch_from_bfd (bfd *abfd)
{
struct gdbarch_info info;
- gdbarch_info_init (&info);
info.abfd = abfd;
return gdbarch_find_by_info (info);
struct gdbarch_info info;
struct gdbarch *gdbarch;
- gdbarch_info_init (&info);
info.abfd = abfd;
info.target_desc = target_current_description ();
gdbarch = gdbarch_find_by_info (info);
static enum bfd_endian default_byte_order = BFD_ENDIAN_UNKNOWN;
+/* Printable names of architectures. Used as the enum list of the
+ "set arch" command. */
+static std::vector<const char *> arches;
+
void
initialize_current_architecture (void)
{
- const char **arches = gdbarch_printable_names ();
- struct gdbarch_info info;
-
- /* determine a default architecture and byte order. */
- gdbarch_info_init (&info);
+ arches = gdbarch_printable_names ();
/* Find a default architecture. */
if (default_bfd_arch == NULL)
/* Choose the architecture by taking the first one
alphabetically. */
const char *chosen = arches[0];
- const char **arch;
- for (arch = arches; *arch != NULL; arch++)
+
+ for (const char *arch : arches)
{
- if (strcmp (*arch, chosen) < 0)
- chosen = *arch;
+ if (strcmp (arch, chosen) < 0)
+ chosen = arch;
}
+
if (chosen == NULL)
- internal_error (__FILE__, __LINE__,
- _("initialize_current_architecture: No arch"));
+ internal_error (_("initialize_current_architecture: No arch"));
+
default_bfd_arch = bfd_scan_arch (chosen);
if (default_bfd_arch == NULL)
- internal_error (__FILE__, __LINE__,
- _("initialize_current_architecture: Arch not found"));
+ internal_error (_("initialize_current_architecture: Arch not found"));
}
+ gdbarch_info info;
info.bfd_arch_info = default_bfd_arch;
/* Take several guesses at a byte order. */
info.byte_order_for_code = info.byte_order;
if (! gdbarch_update_p (info))
- internal_error (__FILE__, __LINE__,
- _("initialize_current_architecture: Selection of "
+ internal_error (_("initialize_current_architecture: Selection of "
"initial architecture failed"));
/* Create the ``set architecture'' command appending ``auto'' to the
list of architectures. */
{
/* Append ``auto''. */
- int nr;
- for (nr = 0; arches[nr] != NULL; nr++);
- arches = XRESIZEVEC (const char *, arches, nr + 2);
- arches[nr + 0] = "auto";
- arches[nr + 1] = NULL;
- add_setshow_enum_cmd ("architecture", class_support,
- arches, &set_architecture_string,
- _("Set architecture of target."),
- _("Show architecture of target."), NULL,
- set_architecture, show_architecture,
- &setlist, &showlist);
- add_alias_cmd ("processor", "architecture", class_support, 1, &setlist);
+ set_architecture_string = "auto";
+ arches.push_back (set_architecture_string);
+ arches.push_back (nullptr);
+ set_show_commands architecture_cmds
+ = add_setshow_enum_cmd ("architecture", class_support,
+ arches.data (), &set_architecture_string,
+ _("Set architecture of target."),
+ _("Show architecture of target."), NULL,
+ set_architecture, show_architecture,
+ &setlist, &showlist);
+ add_alias_cmd ("processor", architecture_cmds.set, class_support, 1,
+ &setlist);
}
}
-
-/* Initialize a gdbarch info to values that will be automatically
- overridden. Note: Originally, this ``struct info'' was initialized
- using memset(0). Unfortunately, that ran into problems, namely
- BFD_ENDIAN_BIG is zero. An explicit initialization function that
- can explicitly set each field to a well defined value is used. */
-
-void
-gdbarch_info_init (struct gdbarch_info *info)
-{
- memset (info, 0, sizeof (struct gdbarch_info));
- info->byte_order = BFD_ENDIAN_UNKNOWN;
- info->byte_order_for_code = info->byte_order;
- info->osabi = GDB_OSABI_UNINITIALIZED;
-}
-
/* Similar to init, but this time fill in the blanks. Information is
obtained from the global "set ..." options and explicitly
initialized INFO fields. */
if (info->byte_order == BFD_ENDIAN_UNKNOWN)
info->byte_order = default_byte_order;
info->byte_order_for_code = info->byte_order;
+ /* Wire the default to the last selected byte order. */
+ default_byte_order = info->byte_order;
/* "(gdb) set osabi ...". Handled by gdbarch_lookup_osabi. */
/* From the manual override, or from file. */
- if (info->osabi == GDB_OSABI_UNINITIALIZED)
+ if (info->osabi == GDB_OSABI_UNKNOWN)
info->osabi = gdbarch_lookup_osabi (info->abfd);
/* From the target. */
+
if (info->osabi == GDB_OSABI_UNKNOWN && info->target_desc != NULL)
info->osabi = tdesc_osabi (info->target_desc);
/* From the configured default. */
if (info->osabi == GDB_OSABI_UNKNOWN)
info->osabi = GDB_OSABI_DEFAULT;
#endif
+ /* If we still don't know which osabi to pick, pick none. */
+ if (info->osabi == GDB_OSABI_UNKNOWN)
+ info->osabi = GDB_OSABI_NONE;
/* Must have at least filled in the architecture. */
gdb_assert (info->bfd_arch_info != NULL);
int
default_fast_tracepoint_valid_at (struct gdbarch *gdbarch, CORE_ADDR addr,
- char **msg)
+ std::string *msg)
{
/* We don't know if maybe the target has some way to do fast
tracepoints that doesn't need gdbarch, so always say yes. */
if (msg)
- *msg = NULL;
+ msg->clear ();
return 1;
}
-void
-default_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
- int *kindptr)
+const gdb_byte *
+default_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
+ int *lenptr)
+{
+ int kind = gdbarch_breakpoint_kind_from_pc (gdbarch, pcptr);
+
+ return gdbarch_sw_breakpoint_from_kind (gdbarch, kind, lenptr);
+}
+int
+default_breakpoint_kind_from_current_state (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ CORE_ADDR *pcptr)
{
- gdbarch_breakpoint_from_pc (gdbarch, pcptr, kindptr);
+ return gdbarch_breakpoint_kind_from_pc (gdbarch, pcptr);
}
+
void
default_gen_return_address (struct gdbarch *gdbarch,
struct agent_expr *ax, struct axs_value *value,
/* Usually, the return value's address is stored the in the "first hidden"
parameter if the return value should be passed by reference, as
specified in ABI. */
- return language_pass_by_reference (type);
+ return !(language_pass_by_reference (type).trivially_copyable);
}
int default_insn_is_call (struct gdbarch *gdbarch, CORE_ADDR addr)
return 0;
}
+/* See arch-utils.h. */
+
+bool
+default_program_breakpoint_here_p (struct gdbarch *gdbarch,
+ CORE_ADDR address)
+{
+ int len;
+ const gdb_byte *bpoint = gdbarch_breakpoint_from_pc (gdbarch, &address, &len);
+
+ /* Software breakpoints unsupported? */
+ if (bpoint == nullptr)
+ return false;
+
+ gdb_byte *target_mem = (gdb_byte *) alloca (len);
+
+ /* Enable the automatic memory restoration from breakpoints while
+ we read the memory. Otherwise we may find temporary breakpoints, ones
+ inserted by GDB, and flag them as permanent breakpoints. */
+ scoped_restore restore_memory
+ = make_scoped_restore_show_memory_breakpoints (0);
+
+ if (target_read_memory (address, target_mem, len) == 0)
+ {
+ /* Check if this is a breakpoint instruction for this architecture,
+ including ones used by GDB. */
+ if (memcmp (target_mem, bpoint, len) == 0)
+ return true;
+ }
+
+ return false;
+}
+
void
default_skip_permanent_breakpoint (struct regcache *regcache)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
CORE_ADDR current_pc = regcache_read_pc (regcache);
int bp_len;
/* -mcmodel=large is used so that no GOT (Global Offset Table) is needed to be
created in inferior memory by GDB (normally it is set by ld.so). */
-char *
+std::string
default_gcc_target_options (struct gdbarch *gdbarch)
{
- return xstrprintf ("-m%d%s", gdbarch_ptr_bit (gdbarch),
- gdbarch_ptr_bit (gdbarch) == 64 ? " -mcmodel=large" : "");
+ return string_printf ("-m%d%s", gdbarch_ptr_bit (gdbarch),
+ (gdbarch_ptr_bit (gdbarch) == 64
+ ? " -mcmodel=large" : ""));
}
/* gdbarch gnu_triplet_regexp method. */
return gdbarch_bfd_arch_info (gdbarch)->arch_name;
}
-/* Default method for gdbarch_addressable_memory_unit_size. By default, a memory byte has
- a size of 1 octet. */
+/* Default method for gdbarch_addressable_memory_unit_size. The default is
+ based on the bits_per_byte defined in the bfd library for the current
+ architecture, this is usually 8-bits, and so this function will usually
+ return 1 indicating 1 byte is 1 octet. */
int
default_addressable_memory_unit_size (struct gdbarch *gdbarch)
{
- return 1;
+ return gdbarch_bfd_arch_info (gdbarch)->bits_per_byte / 8;
}
void
regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
gdbarch_byte_order (gdbarch), addr);
- regcache_raw_supply (regcache, pc_regno, regs);
+ regcache->raw_supply (pc_regno, regs);
+}
+
+int
+default_print_insn (bfd_vma memaddr, disassemble_info *info)
+{
+ disassembler_ftype disassemble_fn;
+
+ disassemble_fn = disassembler (info->arch, info->endian == BFD_ENDIAN_BIG,
+ info->mach, current_program_space->exec_bfd ());
+
+ gdb_assert (disassemble_fn != NULL);
+ return (*disassemble_fn) (memaddr, info);
+}
+
+/* See arch-utils.h. */
+
+CORE_ADDR
+gdbarch_skip_prologue_noexcept (gdbarch *gdbarch, CORE_ADDR pc) noexcept
+{
+ CORE_ADDR new_pc = pc;
+
+ try
+ {
+ new_pc = gdbarch_skip_prologue (gdbarch, pc);
+ }
+ catch (const gdb_exception &ex)
+ {}
+
+ return new_pc;
+}
+
+/* See arch-utils.h. */
+
+bool
+default_in_indirect_branch_thunk (gdbarch *gdbarch, CORE_ADDR pc)
+{
+ return false;
+}
+
+/* See arch-utils.h. */
+
+ULONGEST
+default_type_align (struct gdbarch *gdbarch, struct type *type)
+{
+ return 0;
+}
+
+/* See arch-utils.h. */
+
+std::string
+default_get_pc_address_flags (frame_info_ptr frame, CORE_ADDR pc)
+{
+ return "";
+}
+
+/* See arch-utils.h. */
+void
+default_read_core_file_mappings
+ (struct gdbarch *gdbarch,
+ struct bfd *cbfd,
+ read_core_file_mappings_pre_loop_ftype pre_loop_cb,
+ read_core_file_mappings_loop_ftype loop_cb)
+{
+}
+
+CORE_ADDR
+default_get_return_buf_addr (struct type *val_type, frame_info_ptr cur_frame)
+{
+ return 0;
}
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_gdbarch_utils;
+/* Non-zero if we want to trace architecture code. */
+
+#ifndef GDBARCH_DEBUG
+#define GDBARCH_DEBUG 0
+#endif
+unsigned int gdbarch_debug = GDBARCH_DEBUG;
+static void
+show_gdbarch_debug (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ gdb_printf (file, _("Architecture debugging is %s.\n"), value);
+}
+
+static const char *
+pformat (struct gdbarch *gdbarch, const struct floatformat **format)
+{
+ if (format == NULL)
+ return "(null)";
+
+ int format_index = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE ? 1 : 0;
+ return format[format_index]->name;
+}
+
+static const char *
+pstring (const char *string)
+{
+ if (string == NULL)
+ return "(null)";
+ return string;
+}
+
+static const char *
+pstring_ptr (char **string)
+{
+ if (string == NULL || *string == NULL)
+ return "(null)";
+ return *string;
+}
+
+/* Helper function to print a list of strings, represented as "const
+ char *const *". The list is printed comma-separated. */
+
+static const char *
+pstring_list (const char *const *list)
+{
+ static char ret[100];
+ const char *const *p;
+ size_t offset = 0;
+
+ if (list == NULL)
+ return "(null)";
+
+ ret[0] = '\0';
+ for (p = list; *p != NULL && offset < sizeof (ret); ++p)
+ {
+ size_t s = xsnprintf (ret + offset, sizeof (ret) - offset, "%s, ", *p);
+ offset += 2 + s;
+ }
+
+ if (offset > 0)
+ {
+ gdb_assert (offset - 2 < sizeof (ret));
+ ret[offset - 2] = '\0';
+ }
+
+ return ret;
+}
+
+#include "gdbarch.c"
+
+obstack *gdbarch_obstack (gdbarch *arch)
+{
+ return &arch->obstack;
+}
+
+/* See gdbarch.h. */
+
+char *
+gdbarch_obstack_strdup (struct gdbarch *arch, const char *string)
+{
+ return obstack_strdup (&arch->obstack, string);
+}
+
+
+/* Free a gdbarch struct. This should never happen in normal
+ operation --- once you've created a gdbarch, you keep it around.
+ However, if an architecture's init function encounters an error
+ building the structure, it may need to clean up a partially
+ constructed gdbarch. */
+
+void
+gdbarch_free (struct gdbarch *arch)
+{
+ gdb_assert (arch != NULL);
+ gdb_assert (!arch->initialized_p);
+ delete arch;
+}
+
+/* See gdbarch.h. */
+
+struct gdbarch_tdep_base *
+gdbarch_tdep_1 (struct gdbarch *gdbarch)
+{
+ if (gdbarch_debug >= 2)
+ gdb_printf (gdb_stdlog, "gdbarch_tdep_1 called\n");
+ return gdbarch->tdep;
+}
+
+registry<gdbarch> *
+registry_accessor<gdbarch>::get (gdbarch *arch)
+{
+ return &arch->registry_fields;
+}
+
+/* Keep a registry of the architectures known by GDB. */
+
+struct gdbarch_registration
+{
+ enum bfd_architecture bfd_architecture;
+ gdbarch_init_ftype *init;
+ gdbarch_dump_tdep_ftype *dump_tdep;
+ struct gdbarch_list *arches;
+ struct gdbarch_registration *next;
+};
+
+static struct gdbarch_registration *gdbarch_registry = NULL;
+
+std::vector<const char *>
+gdbarch_printable_names ()
+{
+ /* Accumulate a list of names based on the registed list of
+ architectures. */
+ std::vector<const char *> arches;
+
+ for (gdbarch_registration *rego = gdbarch_registry;
+ rego != nullptr;
+ rego = rego->next)
+ {
+ const struct bfd_arch_info *ap
+ = bfd_lookup_arch (rego->bfd_architecture, 0);
+ if (ap == nullptr)
+ internal_error (_("gdbarch_architecture_names: multi-arch unknown"));
+ do
+ {
+ arches.push_back (ap->printable_name);
+ ap = ap->next;
+ }
+ while (ap != NULL);
+ }
+
+ return arches;
+}
+
+
+void
+gdbarch_register (enum bfd_architecture bfd_architecture,
+ gdbarch_init_ftype *init,
+ gdbarch_dump_tdep_ftype *dump_tdep)
+{
+ struct gdbarch_registration **curr;
+ const struct bfd_arch_info *bfd_arch_info;
+
+ /* Check that BFD recognizes this architecture */
+ bfd_arch_info = bfd_lookup_arch (bfd_architecture, 0);
+ if (bfd_arch_info == NULL)
+ {
+ internal_error (_("gdbarch: Attempt to register "
+ "unknown architecture (%d)"),
+ bfd_architecture);
+ }
+ /* Check that we haven't seen this architecture before. */
+ for (curr = &gdbarch_registry;
+ (*curr) != NULL;
+ curr = &(*curr)->next)
+ {
+ if (bfd_architecture == (*curr)->bfd_architecture)
+ internal_error (_("gdbarch: Duplicate registration "
+ "of architecture (%s)"),
+ bfd_arch_info->printable_name);
+ }
+ /* log it */
+ if (gdbarch_debug)
+ gdb_printf (gdb_stdlog, "gdbarch_register (%s, %s)\n",
+ bfd_arch_info->printable_name,
+ host_address_to_string (init));
+ /* Append it */
+ (*curr) = XNEW (struct gdbarch_registration);
+ (*curr)->bfd_architecture = bfd_architecture;
+ (*curr)->init = init;
+ (*curr)->dump_tdep = dump_tdep;
+ (*curr)->arches = NULL;
+ (*curr)->next = NULL;
+}
+
+/* Look for an architecture using gdbarch_info. */
+
+struct gdbarch_list *
+gdbarch_list_lookup_by_info (struct gdbarch_list *arches,
+ const struct gdbarch_info *info)
+{
+ for (; arches != NULL; arches = arches->next)
+ {
+ if (info->bfd_arch_info != arches->gdbarch->bfd_arch_info)
+ continue;
+ if (info->byte_order != arches->gdbarch->byte_order)
+ continue;
+ if (info->osabi != arches->gdbarch->osabi)
+ continue;
+ if (info->target_desc != arches->gdbarch->target_desc)
+ continue;
+ return arches;
+ }
+ return NULL;
+}
+
+
+/* Find an architecture that matches the specified INFO. Create a new
+ architecture if needed. Return that new architecture. */
+
+struct gdbarch *
+gdbarch_find_by_info (struct gdbarch_info info)
+{
+ struct gdbarch *new_gdbarch;
+ struct gdbarch_registration *rego;
+
+ /* Fill in missing parts of the INFO struct using a number of
+ sources: "set ..."; INFOabfd supplied; and the global
+ defaults. */
+ gdbarch_info_fill (&info);
+
+ /* Must have found some sort of architecture. */
+ gdb_assert (info.bfd_arch_info != nullptr);
+
+ if (gdbarch_debug)
+ {
+ gdb_printf (gdb_stdlog,
+ "gdbarch_find_by_info: info.bfd_arch_info %s\n",
+ (info.bfd_arch_info != nullptr
+ ? info.bfd_arch_info->printable_name
+ : "(null)"));
+ gdb_printf (gdb_stdlog,
+ "gdbarch_find_by_info: info.byte_order %d (%s)\n",
+ info.byte_order,
+ (info.byte_order == BFD_ENDIAN_BIG ? "big"
+ : info.byte_order == BFD_ENDIAN_LITTLE ? "little"
+ : "default"));
+ gdb_printf (gdb_stdlog,
+ "gdbarch_find_by_info: info.osabi %d (%s)\n",
+ info.osabi, gdbarch_osabi_name (info.osabi));
+ gdb_printf (gdb_stdlog,
+ "gdbarch_find_by_info: info.abfd %s\n",
+ host_address_to_string (info.abfd));
+ }
+
+ /* Find the tdep code that knows about this architecture. */
+ for (rego = gdbarch_registry;
+ rego != nullptr;
+ rego = rego->next)
+ if (rego->bfd_architecture == info.bfd_arch_info->arch)
+ break;
+ if (rego == nullptr)
+ {
+ if (gdbarch_debug)
+ gdb_printf (gdb_stdlog, "gdbarch_find_by_info: "
+ "No matching architecture\n");
+ return nullptr;
+ }
+
+ /* Ask the tdep code for an architecture that matches "info". */
+ new_gdbarch = rego->init (info, rego->arches);
+
+ /* Did the tdep code like it? No. Reject the change and revert to
+ the old architecture. */
+ if (new_gdbarch == nullptr)
+ {
+ if (gdbarch_debug)
+ gdb_printf (gdb_stdlog, "gdbarch_find_by_info: "
+ "Target rejected architecture\n");
+ return nullptr;
+ }
+
+ /* Is this a pre-existing architecture (as determined by already
+ being initialized)? Move it to the front of the architecture
+ list (keeping the list sorted Most Recently Used). */
+ if (new_gdbarch->initialized_p)
+ {
+ struct gdbarch_list **list;
+ struct gdbarch_list *self;
+ if (gdbarch_debug)
+ gdb_printf (gdb_stdlog, "gdbarch_find_by_info: "
+ "Previous architecture %s (%s) selected\n",
+ host_address_to_string (new_gdbarch),
+ new_gdbarch->bfd_arch_info->printable_name);
+ /* Find the existing arch in the list. */
+ for (list = ®o->arches;
+ (*list) != nullptr && (*list)->gdbarch != new_gdbarch;
+ list = &(*list)->next);
+ /* It had better be in the list of architectures. */
+ gdb_assert ((*list) != nullptr && (*list)->gdbarch == new_gdbarch);
+ /* Unlink SELF. */
+ self = (*list);
+ (*list) = self->next;
+ /* Insert SELF at the front. */
+ self->next = rego->arches;
+ rego->arches = self;
+ /* Return it. */
+ return new_gdbarch;
+ }
+
+ /* It's a new architecture. */
+ if (gdbarch_debug)
+ gdb_printf (gdb_stdlog, "gdbarch_find_by_info: "
+ "New architecture %s (%s) selected\n",
+ host_address_to_string (new_gdbarch),
+ new_gdbarch->bfd_arch_info->printable_name);
+
+ /* Insert the new architecture into the front of the architecture
+ list (keep the list sorted Most Recently Used). */
+ {
+ struct gdbarch_list *self = XNEW (struct gdbarch_list);
+ self->next = rego->arches;
+ self->gdbarch = new_gdbarch;
+ rego->arches = self;
+ }
+
+ /* Check that the newly installed architecture is valid. Plug in
+ any post init values. */
+ new_gdbarch->dump_tdep = rego->dump_tdep;
+ verify_gdbarch (new_gdbarch);
+ new_gdbarch->initialized_p = true;
+
+ if (gdbarch_debug)
+ gdbarch_dump (new_gdbarch, gdb_stdlog);
+
+ return new_gdbarch;
+}
+
+/* Make the specified architecture current. */
+
+void
+set_target_gdbarch (struct gdbarch *new_gdbarch)
+{
+ gdb_assert (new_gdbarch != NULL);
+ gdb_assert (new_gdbarch->initialized_p);
+ current_inferior ()->gdbarch = new_gdbarch;
+ gdb::observers::architecture_changed.notify (new_gdbarch);
+ registers_changed ();
+}
+
+/* Return the current inferior's arch. */
+
+struct gdbarch *
+target_gdbarch (void)
+{
+ return current_inferior ()->gdbarch;
+}
+void _initialize_gdbarch_utils ();
void
-_initialize_gdbarch_utils (void)
+_initialize_gdbarch_utils ()
{
add_setshow_enum_cmd ("endian", class_support,
endian_enum, &set_endian_string,
_("Show endianness of target."),
NULL, set_endian, show_endian,
&setlist, &showlist);
+ add_setshow_zuinteger_cmd ("arch", class_maintenance, &gdbarch_debug, _("\
+Set architecture debugging."), _("\
+Show architecture debugging."), _("\
+When non-zero, architecture debugging is enabled."),
+ NULL,
+ show_gdbarch_debug,
+ &setdebuglist, &showdebuglist);
}