X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Farch-utils.c;h=2129c3b2c388670b6f52e85ba62a1370b9a1dad0;hb=036003a671233c43e35b3004f91e4cbd61255cf3;hp=7a4a1db9c5348f9d28871c9333dc9c5f0a77d55a;hpb=d7a27068cd16735b9fbae68775ea7e6cd870ac13;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index 7a4a1db9c5..2129c3b2c3 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -1,13 +1,12 @@ /* Dynamic architecture support for GDB, the GNU debugger. - Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, - Inc. + Copyright (C) 1998-2019 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + 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, @@ -16,203 +15,102 @@ 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. */ + along with this program. If not, see . */ #include "defs.h" -#if GDB_MULTI_ARCH #include "arch-utils.h" #include "gdbcmd.h" -#include "inferior.h" /* enum CALL_DUMMY_LOCATION et.al. */ -#else -/* Just include everything in sight so that the every old definition - of macro is visible. */ -#include "symtab.h" -#include "frame.h" -#include "inferior.h" -#include "breakpoint.h" -#include "gdb_wait.h" -#include "gdbcore.h" -#include "gdbcmd.h" -#include "target.h" -#include "annotate.h" -#endif -#include "gdb_string.h" +#include "inferior.h" /* enum CALL_DUMMY_LOCATION et al. */ +#include "infrun.h" #include "regcache.h" -#include "gdb_assert.h" #include "sim-regno.h" +#include "gdbcore.h" +#include "osabi.h" +#include "target-descriptions.h" +#include "objfiles.h" +#include "language.h" +#include "symtab.h" -#include "version.h" +#include "gdbsupport/version.h" #include "floatformat.h" -/* Use the program counter to determine the contents and size - of a breakpoint instruction. If no target-dependent macro - BREAKPOINT_FROM_PC has been defined to implement this function, - assume that the breakpoint doesn't depend on the PC, and - use the values of the BIG_BREAKPOINT and LITTLE_BREAKPOINT macros. - Return a pointer to a string of bytes that encode a breakpoint - instruction, stores the length of the string to *lenptr, - and optionally adjust the pc to point to the correct memory location - for inserting the breakpoint. */ - -const unsigned char * -legacy_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr) -{ - /* {BIG_,LITTLE_}BREAKPOINT is the sequence of bytes we insert for a - breakpoint. On some machines, breakpoints are handled by the - target environment and we don't have to worry about them here. */ -#ifdef BIG_BREAKPOINT - if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) - { - static unsigned char big_break_insn[] = BIG_BREAKPOINT; - *lenptr = sizeof (big_break_insn); - return big_break_insn; - } -#endif -#ifdef LITTLE_BREAKPOINT - if (TARGET_BYTE_ORDER != BFD_ENDIAN_BIG) - { - static unsigned char little_break_insn[] = LITTLE_BREAKPOINT; - *lenptr = sizeof (little_break_insn); - return little_break_insn; - } -#endif -#ifdef BREAKPOINT - { - static unsigned char break_insn[] = BREAKPOINT; - *lenptr = sizeof (break_insn); - return break_insn; - } -#endif - *lenptr = 0; - return NULL; -} +#include "dis-asm.h" -/* Implementation of extract return value that grubs around in the - register cache. */ -void -legacy_extract_return_value (struct type *type, struct regcache *regcache, - void *valbuf) +int +default_displaced_step_hw_singlestep (struct gdbarch *gdbarch, + struct displaced_step_closure *closure) { - char *registers = deprecated_grub_regcache_for_registers (regcache); - bfd_byte *buf = valbuf; - DEPRECATED_EXTRACT_RETURN_VALUE (type, registers, buf); /* OK */ + return !gdbarch_software_single_step_p (gdbarch); } -/* Implementation of store return value that grubs the register cache. - Takes a local copy of the buffer to avoid const problems. */ -void -legacy_store_return_value (struct type *type, struct regcache *regcache, - const void *buf) +CORE_ADDR +displaced_step_at_entry_point (struct gdbarch *gdbarch) { - bfd_byte *b = alloca (TYPE_LENGTH (type)); - gdb_assert (regcache == current_regcache); - memcpy (b, buf, TYPE_LENGTH (type)); - DEPRECATED_STORE_RETURN_VALUE (type, b); -} + CORE_ADDR addr; + int bp_len; + + addr = entry_point_address (); + /* Inferior calls also use the entry point as a breakpoint location. + We don't want displaced stepping to interfere with those + breakpoints, so leave space. */ + gdbarch_breakpoint_from_pc (gdbarch, &addr, &bp_len); + addr += bp_len * 2; + + return addr; +} int -legacy_register_sim_regno (int regnum) +legacy_register_sim_regno (struct gdbarch *gdbarch, int regnum) { /* Only makes sense to supply raw registers. */ - gdb_assert (regnum >= 0 && regnum < NUM_REGS); + 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 (REGISTER_NAME (regnum) != NULL - && REGISTER_NAME (regnum)[0] != '\0') + if (gdbarch_register_name (gdbarch, regnum) != NULL + && gdbarch_register_name (gdbarch, regnum)[0] != '\0') return regnum; else return LEGACY_SIM_REGNO_IGNORE; } -int -generic_frameless_function_invocation_not (struct frame_info *fi) -{ - return 0; -} - -int -generic_return_value_on_stack_not (struct type *type) -{ - return 0; -} - CORE_ADDR -generic_skip_trampoline_code (CORE_ADDR pc) +generic_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) { return 0; } -int -generic_in_solib_call_trampoline (CORE_ADDR pc, char *name) +CORE_ADDR +generic_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc) { return 0; } int -generic_in_solib_return_trampoline (CORE_ADDR pc, char *name) +generic_in_solib_return_trampoline (struct gdbarch *gdbarch, + CORE_ADDR pc, const char *name) { return 0; } int -generic_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) +generic_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) { return 0; } -const char * -legacy_register_name (int i) -{ -#ifdef REGISTER_NAMES - static char *names[] = REGISTER_NAMES; - if (i < 0 || i >= (sizeof (names) / sizeof (*names))) - return NULL; - else - return names[i]; -#else - internal_error (__FILE__, __LINE__, - "legacy_register_name: called."); - return NULL; -#endif -} - -#if defined (CALL_DUMMY) -LONGEST legacy_call_dummy_words[] = CALL_DUMMY; -#else -LONGEST legacy_call_dummy_words[1]; -#endif -int legacy_sizeof_call_dummy_words = sizeof (legacy_call_dummy_words); - -void -generic_remote_translate_xfer_address (CORE_ADDR gdb_addr, int gdb_len, - CORE_ADDR * rem_addr, int *rem_len) -{ - *rem_addr = gdb_addr; - *rem_len = gdb_len; -} - -int -generic_prologue_frameless_p (CORE_ADDR ip) -{ - return ip == SKIP_PROLOGUE (ip); -} - -/* New/multi-arched targets should use the correct gdbarch field - instead of using this global pointer. */ int -legacy_print_insn (bfd_vma vma, disassemble_info *info) +default_code_of_frame_writable (struct gdbarch *gdbarch, + struct frame_info *frame) { - return (*deprecated_tm_print_insn) (vma, info); + return 1; } -/* Helper functions for INNER_THAN */ +/* Helper functions for gdbarch_inner_than */ int core_addr_lessthan (CORE_ADDR lhs, CORE_ADDR rhs) @@ -226,194 +124,79 @@ core_addr_greaterthan (CORE_ADDR lhs, CORE_ADDR rhs) return (lhs > rhs); } +/* Misc helper functions for targets. */ -/* Helper functions for TARGET_{FLOAT,DOUBLE}_FORMAT */ - -const struct floatformat * -default_float_format (struct gdbarch *gdbarch) -{ -#if GDB_MULTI_ARCH - int byte_order = gdbarch_byte_order (gdbarch); -#else - int byte_order = TARGET_BYTE_ORDER; -#endif - switch (byte_order) - { - case BFD_ENDIAN_BIG: - return &floatformat_ieee_single_big; - case BFD_ENDIAN_LITTLE: - return &floatformat_ieee_single_little; - default: - internal_error (__FILE__, __LINE__, - "default_float_format: bad byte order"); - } -} - - -const struct floatformat * -default_double_format (struct gdbarch *gdbarch) -{ -#if GDB_MULTI_ARCH - int byte_order = gdbarch_byte_order (gdbarch); -#else - int byte_order = TARGET_BYTE_ORDER; -#endif - switch (byte_order) - { - case BFD_ENDIAN_BIG: - return &floatformat_ieee_double_big; - case BFD_ENDIAN_LITTLE: - return &floatformat_ieee_double_little; - default: - internal_error (__FILE__, __LINE__, - "default_double_format: bad byte order"); - } -} - -/* Misc helper functions for targets. */ - -int -frame_num_args_unknown (struct frame_info *fi) -{ - return -1; -} - - -int -generic_register_convertible_not (int num) -{ - return 0; -} - - -/* Under some ABI's that specify the `struct convention' for returning - structures by value, by the time we've returned from the function, - the return value is sitting there in the caller's buffer, but GDB - has no way to find the address of that buffer. - - On such architectures, use this function as your - extract_struct_value_address method. When asked to a struct - returned by value in this fashion, GDB will print a nice error - message, instead of garbage. */ CORE_ADDR -generic_cannot_extract_struct_value_address (char *dummy) +core_addr_identity (struct gdbarch *gdbarch, CORE_ADDR addr) { - return 0; + return addr; } CORE_ADDR -core_addr_identity (CORE_ADDR addr) +convert_from_func_ptr_addr_identity (struct gdbarch *gdbarch, CORE_ADDR addr, + struct target_ops *targ) { return addr; } int -no_op_reg_to_regnum (int reg) +no_op_reg_to_regnum (struct gdbarch *gdbarch, int reg) { return reg; } -/* Default prepare_to_procced(). */ -int -default_prepare_to_proceed (int select_it) +void +default_coff_make_msymbol_special (int val, struct minimal_symbol *msym) { - return 0; + return; } -/* Generic prepare_to_proceed(). This one should be suitable for most - targets that support threads. */ -int -generic_prepare_to_proceed (int select_it) -{ - ptid_t wait_ptid; - struct target_waitstatus wait_status; - - /* Get the last target status returned by target_wait(). */ - get_last_target_status (&wait_ptid, &wait_status); - - /* Make sure we were stopped either at a breakpoint, or because - of a Ctrl-C. */ - if (wait_status.kind != TARGET_WAITKIND_STOPPED - || (wait_status.value.sig != TARGET_SIGNAL_TRAP && - wait_status.value.sig != TARGET_SIGNAL_INT)) - { - return 0; - } - - if (!ptid_equal (wait_ptid, minus_one_ptid) - && !ptid_equal (inferior_ptid, wait_ptid)) - { - /* Switched over from WAIT_PID. */ - CORE_ADDR wait_pc = read_pc_pid (wait_ptid); +/* See arch-utils.h. */ - if (wait_pc != read_pc ()) - { - if (select_it) - { - /* Switch back to WAIT_PID thread. */ - inferior_ptid = wait_ptid; - - /* FIXME: This stuff came from switch_to_thread() in - thread.c (which should probably be a public function). */ - flush_cached_frames (); - registers_changed (); - stop_pc = wait_pc; - select_frame (get_current_frame ()); - } - /* We return 1 to indicate that there is a breakpoint here, - so we need to step over it before continuing to avoid - hitting it straight away. */ - if (breakpoint_here_p (wait_pc)) - { - return 1; - } - } - } - return 0; - +void +default_make_symbol_special (struct symbol *sym, struct objfile *objfile) +{ + return; } +/* See arch-utils.h. */ + CORE_ADDR -init_frame_pc_noop (int fromleaf, struct frame_info *prev) +default_adjust_dwarf2_addr (CORE_ADDR pc) { - /* Do nothing, implies return the same PC value. */ - return get_frame_pc (prev); + return pc; } +/* See arch-utils.h. */ + CORE_ADDR -init_frame_pc_default (int fromleaf, struct frame_info *prev) +default_adjust_dwarf2_line (CORE_ADDR addr, int rel) { - if (fromleaf && DEPRECATED_SAVED_PC_AFTER_CALL_P ()) - return DEPRECATED_SAVED_PC_AFTER_CALL (get_next_frame (prev)); - else if (get_next_frame (prev) != NULL) - return DEPRECATED_FRAME_SAVED_PC (get_next_frame (prev)); - else - return read_pc (); + return addr; } -void -default_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym) -{ - return; -} +/* See arch-utils.h. */ -void -default_coff_make_msymbol_special (int val, struct minimal_symbol *msym) +bool +default_execute_dwarf_cfa_vendor_op (struct gdbarch *gdbarch, gdb_byte op, + struct dwarf2_frame_state *fs) { - return; + return false; } int -cannot_register_not (int regnum) +cannot_register_not (struct gdbarch *gdbarch, int regnum) { return 0; } /* Legacy version of target_virtual_frame_pointer(). Assumes that - there is an FP_REGNUM and that it is the same, cooked or raw. */ + there is an gdbarch_deprecated_fp_regnum and that it is the same, + cooked or raw. */ void -legacy_virtual_frame_pointer (CORE_ADDR pc, +legacy_virtual_frame_pointer (struct gdbarch *gdbarch, + CORE_ADDR pc, int *frame_regnum, LONGEST *frame_offset) { @@ -422,100 +205,95 @@ legacy_virtual_frame_pointer (CORE_ADDR pc, register and an offset can determine this. I think it should instead generate a byte code expression as that would work better with things like Dwarf2's CFI. */ - if (FP_REGNUM >= 0 && FP_REGNUM < NUM_REGS) - *frame_regnum = FP_REGNUM; - else if (SP_REGNUM >= 0 && SP_REGNUM < NUM_REGS) - *frame_regnum = SP_REGNUM; + if (gdbarch_deprecated_fp_regnum (gdbarch) >= 0 + && gdbarch_deprecated_fp_regnum (gdbarch) + < gdbarch_num_regs (gdbarch)) + *frame_regnum = gdbarch_deprecated_fp_regnum (gdbarch); + else if (gdbarch_sp_regnum (gdbarch) >= 0 + && gdbarch_sp_regnum (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 (__FILE__, __LINE__, + _("No virtual frame pointer available")); *frame_offset = 0; } -/* Assume the world is sane, every register's virtual and real size - is identical. */ +/* 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. */ -int -generic_register_size (int regnum) +const struct floatformat ** +default_floatformat_for_type (struct gdbarch *gdbarch, + const char *name, int len) { - gdb_assert (regnum >= 0 && regnum < NUM_REGS + NUM_PSEUDO_REGS); - if (gdbarch_register_type_p (current_gdbarch)) - return TYPE_LENGTH (gdbarch_register_type (current_gdbarch, regnum)); - else - /* FIXME: cagney/2003-03-01: Once all architectures implement - gdbarch_register_type(), this entire function can go away. It - is made obsolete by register_size(). */ - return TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (regnum)); /* OK */ -} + const struct floatformat **format = NULL; -/* Assume all registers are adjacent. */ + 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; +} + int -generic_register_byte (int regnum) +generic_convert_register_p (struct gdbarch *gdbarch, int regnum, + struct type *type) { - int byte; - int i; - gdb_assert (regnum >= 0 && regnum < NUM_REGS + NUM_PSEUDO_REGS); - byte = 0; - for (i = 0; i < regnum; i++) - { - byte += generic_register_size (i); - } - return byte; + return 0; } - int -legacy_pc_in_sigtramp (CORE_ADDR pc, char *name) +default_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type) { -#if !defined (IN_SIGTRAMP) - if (SIGTRAMP_START_P ()) - return (pc) >= SIGTRAMP_START (pc) && (pc) < SIGTRAMP_END (pc); - else - return name && strcmp ("_sigtramp", name) == 0; -#else - return IN_SIGTRAMP (pc, name); -#endif + return 0; } int -legacy_convert_register_p (int regnum) +generic_instruction_nullified (struct gdbarch *gdbarch, + struct regcache *regcache) { - return REGISTER_CONVERTIBLE (regnum); + return 0; } -void -legacy_register_to_value (int regnum, struct type *type, - char *from, char *to) +int +default_remote_register_number (struct gdbarch *gdbarch, + int regno) { - REGISTER_CONVERT_TO_VIRTUAL (regnum, type, from, to); + return regno; } -void -legacy_value_to_register (struct type *type, int regnum, - char *from, char *to) +/* See arch-utils.h. */ + +int +default_vsyscall_range (struct gdbarch *gdbarch, struct mem_range *range) { - REGISTER_CONVERT_TO_RAW (type, regnum, from, to); + return 0; } /* Functions to manipulate the endianness of the target. */ -/* ``target_byte_order'' is only used when non- multi-arch. - Multi-arch targets obtain the current byte order using the - TARGET_BYTE_ORDER gdbarch method. - - The choice of initial value is entirely arbitrary. During startup, - the function initialize_current_architecture() updates this value - based on default byte-order information extracted from BFD. */ -int target_byte_order = BFD_ENDIAN_BIG; -int target_byte_order_auto = 1; +static enum bfd_endian target_byte_order_user = BFD_ENDIAN_UNKNOWN; static const char endian_big[] = "big"; static const char endian_little[] = "little"; static const char endian_auto[] = "auto"; -static const char *endian_enum[] = +static const char *const endian_enum[] = { endian_big, endian_little, @@ -524,237 +302,284 @@ static const char *endian_enum[] = }; static const char *set_endian_string; +enum bfd_endian +selected_byte_order (void) +{ + return target_byte_order_user; +} + /* Called by ``show endian''. */ static void -show_endian (char *args, int from_tty) -{ - if (TARGET_BYTE_ORDER_AUTO) - printf_unfiltered ("The target endianness is set automatically (currently %s endian)\n", - (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? "big" : "little")); +show_endian (struct ui_file *file, int from_tty, struct cmd_list_element *c, + const char *value) +{ + 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")); + else + fprintf_unfiltered (file, _("The target endianness is set automatically " + "(currently little endian)\n")); else - printf_unfiltered ("The target is assumed to be %s endian\n", - (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? "big" : "little")); + if (target_byte_order_user == BFD_ENDIAN_BIG) + fprintf_unfiltered (file, + _("The target is assumed to be big endian\n")); + else + fprintf_unfiltered (file, + _("The target is assumed to be 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_auto = 1; + target_byte_order_user = BFD_ENDIAN_UNKNOWN; + if (! gdbarch_update_p (info)) + internal_error (__FILE__, __LINE__, + _("set_endian: architecture update failed")); } else if (set_endian_string == endian_little) { - target_byte_order_auto = 0; - if (GDB_MULTI_ARCH) - { - struct gdbarch_info info; - gdbarch_info_init (&info); - info.byte_order = BFD_ENDIAN_LITTLE; - if (! gdbarch_update_p (info)) - { - printf_unfiltered ("Little endian target not supported by GDB\n"); - } - } + info.byte_order = BFD_ENDIAN_LITTLE; + if (! gdbarch_update_p (info)) + printf_unfiltered (_("Little endian target not supported by GDB\n")); else - { - target_byte_order = BFD_ENDIAN_LITTLE; - } + target_byte_order_user = BFD_ENDIAN_LITTLE; } else if (set_endian_string == endian_big) { - target_byte_order_auto = 0; - if (GDB_MULTI_ARCH) - { - struct gdbarch_info info; - gdbarch_info_init (&info); - info.byte_order = BFD_ENDIAN_BIG; - if (! gdbarch_update_p (info)) - { - printf_unfiltered ("Big endian target not supported by GDB\n"); - } - } + info.byte_order = BFD_ENDIAN_BIG; + if (! gdbarch_update_p (info)) + printf_unfiltered (_("Big endian target not supported by GDB\n")); else - { - target_byte_order = BFD_ENDIAN_BIG; - } + target_byte_order_user = BFD_ENDIAN_BIG; } else internal_error (__FILE__, __LINE__, - "set_endian: bad value"); - show_endian (NULL, from_tty); + _("set_endian: bad value")); + + show_endian (gdb_stdout, from_tty, NULL, NULL); } -/* Set the endianness from a BFD. */ +/* Given SELECTED, a currently selected BFD architecture, and + TARGET_DESC, the current target description, return what + architecture to use. -static void -set_endian_from_file (bfd *abfd) -{ - int want; - if (GDB_MULTI_ARCH) - internal_error (__FILE__, __LINE__, - "set_endian_from_file: not for multi-arch"); - if (bfd_big_endian (abfd)) - want = BFD_ENDIAN_BIG; - else - want = BFD_ENDIAN_LITTLE; - if (TARGET_BYTE_ORDER_AUTO) - target_byte_order = want; - else if (TARGET_BYTE_ORDER != want) - warning ("%s endian file does not match %s endian target.", - want == BFD_ENDIAN_BIG ? "big" : "little", - TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? "big" : "little"); -} + SELECTED may be NULL, in which case we return the architecture + associated with TARGET_DESC. If SELECTED specifies a variant + 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 + compatible by the target, we can use the target architecture. -/* Functions to manipulate the architecture of the target */ + If SELECTED is obviously incompatible, warn the user. */ -enum set_arch { set_arch_auto, set_arch_manual }; +static const struct bfd_arch_info * +choose_architecture_for_target (const struct target_desc *target_desc, + const struct bfd_arch_info *selected) +{ + const struct bfd_arch_info *from_target = tdesc_architecture (target_desc); + const struct bfd_arch_info *compat1, *compat2; -int target_architecture_auto = 1; + if (selected == NULL) + return from_target; -const char *set_architecture_string; + if (from_target == NULL) + return selected; -/* Old way of changing the current architecture. */ + /* struct bfd_arch_info objects are singletons: that is, there's + supposed to be exactly one instance for a given machine. So you + can tell whether two are equivalent by comparing pointers. */ + if (from_target == selected) + return selected; -extern const struct bfd_arch_info bfd_default_arch_struct; -const struct bfd_arch_info *target_architecture = &bfd_default_arch_struct; -int (*target_architecture_hook) (const struct bfd_arch_info *ap); + /* BFD's 'A->compatible (A, B)' functions return zero if A and B are + incompatible. But if they are compatible, it returns the 'more + featureful' of the two arches. That is, if A can run code + written for B, but B can't run code written for A, then it'll + return A. -static int -arch_ok (const struct bfd_arch_info *arch) -{ - if (GDB_MULTI_ARCH) - internal_error (__FILE__, __LINE__, - "arch_ok: not multi-arched"); - /* Should be performing the more basic check that the binary is - compatible with GDB. */ - /* Check with the target that the architecture is valid. */ - return (target_architecture_hook == NULL - || target_architecture_hook (arch)); -} + Some targets (e.g. MIPS as of 2006-12-04) don't fully + implement this, instead always returning NULL or the first + argument. We detect that case by checking both directions. */ -static void -set_arch (const struct bfd_arch_info *arch, - enum set_arch type) -{ - if (GDB_MULTI_ARCH) - internal_error (__FILE__, __LINE__, - "set_arch: not multi-arched"); - switch (type) + compat1 = selected->compatible (selected, from_target); + compat2 = from_target->compatible (from_target, selected); + + if (compat1 == NULL && compat2 == NULL) { - case set_arch_auto: - if (!arch_ok (arch)) - warning ("Target may not support %s architecture", - arch->printable_name); - target_architecture = arch; - break; - case set_arch_manual: - if (!arch_ok (arch)) - { - printf_unfiltered ("Target does not support `%s' architecture.\n", - arch->printable_name); - } - else - { - target_architecture_auto = 0; - target_architecture = arch; - } - break; + /* BFD considers the architectures incompatible. Check our + target description whether it accepts SELECTED as compatible + anyway. */ + if (tdesc_compatible_p (target_desc, selected)) + return from_target; + + warning (_("Selected architecture %s is not compatible " + "with reported target architecture %s"), + selected->printable_name, from_target->printable_name); + return selected; } - if (gdbarch_debug) - gdbarch_dump (current_gdbarch, gdb_stdlog); -} -/* Set the architecture from arch/machine (deprecated) */ + if (compat1 == NULL) + return compat2; + if (compat2 == NULL) + return compat1; + if (compat1 == compat2) + return compat1; -void -set_architecture_from_arch_mach (enum bfd_architecture arch, - unsigned long mach) -{ - const struct bfd_arch_info *wanted = bfd_lookup_arch (arch, mach); - if (GDB_MULTI_ARCH) - internal_error (__FILE__, __LINE__, - "set_architecture_from_arch_mach: not multi-arched"); - if (wanted != NULL) - set_arch (wanted, set_arch_manual); - else - internal_error (__FILE__, __LINE__, - "gdbarch: hardwired architecture/machine not recognized"); + /* If the two didn't match, but one of them was a default + architecture, assume the more specific one is correct. This + handles the case where an executable or target description just + says "mips", but the other knows which MIPS variant. */ + if (compat1->the_default) + return compat2; + if (compat2->the_default) + return compat1; + + /* We have no idea which one is better. This is a bug, but not + a critical problem; warn the user. */ + warning (_("Selected architecture %s is ambiguous with " + "reported target architecture %s"), + selected->printable_name, from_target->printable_name); + return selected; } -/* Set the architecture from a BFD (deprecated) */ +/* Functions to manipulate the architecture of the target. */ -static void -set_architecture_from_file (bfd *abfd) +enum set_arch { set_arch_auto, set_arch_manual }; + +static const struct bfd_arch_info *target_architecture_user; + +static const char *set_architecture_string; + +const char * +selected_architecture_name (void) { - const struct bfd_arch_info *wanted = bfd_get_arch_info (abfd); - if (GDB_MULTI_ARCH) - internal_error (__FILE__, __LINE__, - "set_architecture_from_file: not multi-arched"); - if (target_architecture_auto) - { - set_arch (wanted, set_arch_auto); - } - else if (wanted != target_architecture) - { - warning ("%s architecture file may be incompatible with %s target.", - wanted->printable_name, - target_architecture->printable_name); - } + if (target_architecture_user == NULL) + return NULL; + else + return set_architecture_string; } - /* Called if the user enters ``show architecture'' without an - argument. */ + argument. */ static void -show_architecture (char *args, int from_tty) +show_architecture (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) { - const char *arch; - arch = TARGET_ARCHITECTURE->printable_name; - if (target_architecture_auto) - printf_filtered ("The target architecture is set automatically (currently %s)\n", arch); + 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); else - printf_filtered ("The target architecture is assumed to be %s\n", arch); + fprintf_filtered (file, _("The target architecture is assumed to be %s\n"), + set_architecture_string); } /* Called if the user enters ``set architecture'' with or without an - argument. */ + 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_auto = 1; + target_architecture_user = NULL; + if (!gdbarch_update_p (info)) + internal_error (__FILE__, __LINE__, + _("could not select an architecture automatically")); } - else if (GDB_MULTI_ARCH) + else { - struct gdbarch_info info; - gdbarch_info_init (&info); 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"); + _("set_architecture: bfd_scan_arch failed")); if (gdbarch_update_p (info)) - target_architecture_auto = 0; + target_architecture_user = info.bfd_arch_info; else - printf_unfiltered ("Architecture `%s' not recognized.\n", + printf_unfiltered (_("Architecture `%s' not recognized.\n"), set_architecture_string); } - else + show_architecture (gdb_stdout, from_tty, NULL, NULL); +} + +/* Try to select a global architecture that matches "info". Return + non-zero if the attempt succeeds. */ +int +gdbarch_update_p (struct gdbarch_info info) +{ + struct gdbarch *new_gdbarch; + + /* Check for the current file. */ + if (info.abfd == NULL) + info.abfd = exec_bfd; + if (info.abfd == NULL) + info.abfd = core_bfd; + + /* Check for the current target description. */ + if (info.target_desc == NULL) + info.target_desc = target_current_description (); + + new_gdbarch = gdbarch_find_by_info (info); + + /* If there no architecture by that name, reject the request. */ + if (new_gdbarch == NULL) { - const struct bfd_arch_info *arch - = bfd_scan_arch (set_architecture_string); - if (arch == NULL) - internal_error (__FILE__, __LINE__, - "set_architecture: bfd_scan_arch failed"); - set_arch (arch, set_arch_manual); + if (gdbarch_debug) + fprintf_unfiltered (gdb_stdlog, "gdbarch_update_p: " + "Architecture not found\n"); + return 0; + } + + /* If it is the same old architecture, accept the request (but don't + swap anything). */ + 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); + return 1; } - show_architecture (NULL, from_tty); + + /* 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); + set_target_gdbarch (new_gdbarch); + + return 1; +} + +/* Return the architecture for ABFD. If no suitable architecture + could be find, return NULL. */ + +struct gdbarch * +gdbarch_from_bfd (bfd *abfd) +{ + struct gdbarch_info info; + gdbarch_info_init (&info); + + info.abfd = abfd; + return gdbarch_find_by_info (info); } /* Set the dynamic target-system-dependent parameters (architecture, @@ -763,19 +588,17 @@ set_architecture (char *ignore_args, int from_tty, struct cmd_list_element *c) void set_gdbarch_from_file (bfd *abfd) { - if (GDB_MULTI_ARCH) - { - struct gdbarch_info info; - gdbarch_info_init (&info); - info.abfd = abfd; - if (! gdbarch_update_p (info)) - error ("Architecture of file not recognized.\n"); - } - else - { - set_architecture_from_file (abfd); - set_endian_from_file (abfd); - } + 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); + + if (gdbarch == NULL) + error (_("Architecture of file not recognized.")); + set_target_gdbarch (gdbarch); } /* Initialize the current architecture. Update the ``set @@ -796,23 +619,22 @@ static const bfd_target *default_bfd_vec = &DEFAULT_BFD_VEC; static const bfd_target *default_bfd_vec; #endif +static enum bfd_endian default_byte_order = BFD_ENDIAN_UNKNOWN; + void initialize_current_architecture (void) { const char **arches = gdbarch_printable_names (); - - /* determine a default architecture and byte order. */ struct gdbarch_info info; + + /* determine a default architecture and byte order. */ gdbarch_info_init (&info); - /* Find a default architecture. */ - if (info.bfd_arch_info == NULL - && default_bfd_arch != NULL) - info.bfd_arch_info = default_bfd_arch; - if (info.bfd_arch_info == NULL) + /* Find a default architecture. */ + if (default_bfd_arch == NULL) { /* Choose the architecture by taking the first one - alphabetically. */ + alphabetically. */ const char *chosen = arches[0]; const char **arch; for (arch = arches; *arch != NULL; arch++) @@ -822,93 +644,79 @@ initialize_current_architecture (void) } if (chosen == NULL) internal_error (__FILE__, __LINE__, - "initialize_current_architecture: No arch"); - info.bfd_arch_info = bfd_scan_arch (chosen); - if (info.bfd_arch_info == NULL) + _("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"); + _("initialize_current_architecture: Arch not found")); } + info.bfd_arch_info = default_bfd_arch; + /* Take several guesses at a byte order. */ - if (info.byte_order == BFD_ENDIAN_UNKNOWN + if (default_byte_order == BFD_ENDIAN_UNKNOWN && default_bfd_vec != NULL) { - /* Extract BFD's default vector's byte order. */ + /* Extract BFD's default vector's byte order. */ switch (default_bfd_vec->byteorder) { case BFD_ENDIAN_BIG: - info.byte_order = BFD_ENDIAN_BIG; + default_byte_order = BFD_ENDIAN_BIG; break; case BFD_ENDIAN_LITTLE: - info.byte_order = BFD_ENDIAN_LITTLE; + default_byte_order = BFD_ENDIAN_LITTLE; break; default: break; } } - if (info.byte_order == BFD_ENDIAN_UNKNOWN) + if (default_byte_order == BFD_ENDIAN_UNKNOWN) { - /* look for ``*el-*'' in the target name. */ + /* look for ``*el-*'' in the target name. */ const char *chp; chp = strchr (target_name, '-'); if (chp != NULL && chp - 2 >= target_name - && strncmp (chp - 2, "el", 2) == 0) - info.byte_order = BFD_ENDIAN_LITTLE; + && startswith (chp - 2, "el")) + default_byte_order = BFD_ENDIAN_LITTLE; } - if (info.byte_order == BFD_ENDIAN_UNKNOWN) + if (default_byte_order == BFD_ENDIAN_UNKNOWN) { /* Wire it to big-endian!!! */ - info.byte_order = BFD_ENDIAN_BIG; + default_byte_order = BFD_ENDIAN_BIG; } - if (GDB_MULTI_ARCH) - { - if (! gdbarch_update_p (info)) - { - internal_error (__FILE__, __LINE__, - "initialize_current_architecture: Selection of initial architecture failed"); - } - } - else - { - /* If the multi-arch logic comes up with a byte-order (from BFD) - use it for the non-multi-arch case. */ - if (info.byte_order != BFD_ENDIAN_UNKNOWN) - target_byte_order = info.byte_order; - initialize_non_multiarch (); - } + info.byte_order = default_byte_order; + info.byte_order_for_code = info.byte_order; + + if (! gdbarch_update_p (info)) + internal_error (__FILE__, __LINE__, + _("initialize_current_architecture: Selection of " + "initial architecture failed")); /* Create the ``set architecture'' command appending ``auto'' to the - list of architectures. */ + list of architectures. */ { - struct cmd_list_element *c; - /* Append ``auto''. */ + /* Append ``auto''. */ int nr; for (nr = 0; arches[nr] != NULL; nr++); - arches = xrealloc (arches, sizeof (char*) * (nr + 2)); + arches = XRESIZEVEC (const char *, arches, nr + 2); arches[nr + 0] = "auto"; arches[nr + 1] = NULL; - /* FIXME: add_set_enum_cmd() uses an array of ``char *'' instead - of ``const char *''. We just happen to know that the casts are - safe. */ - c = add_set_enum_cmd ("architecture", class_support, - arches, &set_architecture_string, - "Set architecture of target.", - &setlist); - set_cmd_sfunc (c, set_architecture); + 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); - /* Don't use set_from_show - need to print both auto/manual and - current setting. */ - add_cmd ("architecture", class_support, show_architecture, - "Show the current target architecture", &showlist); } } /* Initialize a gdbarch info to values that will be automatically overridden. Note: Originally, this ``struct info'' was initialized - using memset(0). Unfortunatly, that ran into problems, namely + 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. */ @@ -917,24 +725,292 @@ gdbarch_info_init (struct gdbarch_info *info) { memset (info, 0, sizeof (struct gdbarch_info)); info->byte_order = BFD_ENDIAN_UNKNOWN; - info->osabi = GDB_OSABI_UNINITIALIZED; + info->byte_order_for_code = info->byte_order; +} + +/* Similar to init, but this time fill in the blanks. Information is + obtained from the global "set ..." options and explicitly + initialized INFO fields. */ + +void +gdbarch_info_fill (struct gdbarch_info *info) +{ + /* "(gdb) set architecture ...". */ + if (info->bfd_arch_info == NULL + && target_architecture_user) + info->bfd_arch_info = target_architecture_user; + /* From the file. */ + if (info->bfd_arch_info == NULL + && info->abfd != NULL + && bfd_get_arch (info->abfd) != bfd_arch_unknown + && bfd_get_arch (info->abfd) != bfd_arch_obscure) + info->bfd_arch_info = bfd_get_arch_info (info->abfd); + /* From the target. */ + if (info->target_desc != NULL) + info->bfd_arch_info = choose_architecture_for_target + (info->target_desc, info->bfd_arch_info); + /* From the default. */ + if (info->bfd_arch_info == NULL) + info->bfd_arch_info = default_bfd_arch; + + /* "(gdb) set byte-order ...". */ + if (info->byte_order == BFD_ENDIAN_UNKNOWN + && target_byte_order_user != BFD_ENDIAN_UNKNOWN) + info->byte_order = target_byte_order_user; + /* From the INFO struct. */ + if (info->byte_order == BFD_ENDIAN_UNKNOWN + && info->abfd != NULL) + info->byte_order = (bfd_big_endian (info->abfd) ? BFD_ENDIAN_BIG + : bfd_little_endian (info->abfd) ? BFD_ENDIAN_LITTLE + : BFD_ENDIAN_UNKNOWN); + /* From the default. */ + 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_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. */ +#ifdef GDB_OSABI_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); +} + +/* Return "current" architecture. If the target is running, this is + the architecture of the selected frame. Otherwise, the "current" + architecture defaults to the target architecture. + + This function should normally be called solely by the command + interpreter routines to determine the architecture to execute a + command in. */ +struct gdbarch * +get_current_arch (void) +{ + if (has_stack_frames ()) + return get_frame_arch (get_selected_frame (NULL)); + else + return target_gdbarch (); +} + +int +default_has_shared_address_space (struct gdbarch *gdbarch) +{ + /* Simply say no. In most unix-like targets each inferior/process + has its own address space. */ + return 0; +} + +int +default_fast_tracepoint_valid_at (struct gdbarch *gdbarch, CORE_ADDR addr, + 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->clear (); + return 1; +} + +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) +{ + return gdbarch_breakpoint_kind_from_pc (gdbarch, pcptr); +} + + +void +default_gen_return_address (struct gdbarch *gdbarch, + struct agent_expr *ax, struct axs_value *value, + CORE_ADDR scope) +{ + error (_("This architecture has no method to collect a return address.")); +} + +int +default_return_in_first_hidden_param_p (struct gdbarch *gdbarch, + struct type *type) +{ + /* 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); +} + +int default_insn_is_call (struct gdbarch *gdbarch, CORE_ADDR addr) +{ + return 0; +} + +int default_insn_is_ret (struct gdbarch *gdbarch, CORE_ADDR addr) +{ + return 0; +} + +int default_insn_is_jump (struct gdbarch *gdbarch, CORE_ADDR addr) +{ + return 0; +} + +void +default_skip_permanent_breakpoint (struct regcache *regcache) +{ + struct gdbarch *gdbarch = regcache->arch (); + CORE_ADDR current_pc = regcache_read_pc (regcache); + int bp_len; + + gdbarch_breakpoint_from_pc (gdbarch, ¤t_pc, &bp_len); + current_pc += bp_len; + regcache_write_pc (regcache, current_pc); +} + +CORE_ADDR +default_infcall_mmap (CORE_ADDR size, unsigned prot) +{ + error (_("This target does not support inferior memory allocation by mmap.")); +} + +void +default_infcall_munmap (CORE_ADDR addr, CORE_ADDR size) +{ + /* Memory reserved by inferior mmap is kept leaked. */ } -/* */ +/* -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). */ -extern initialize_file_ftype _initialize_gdbarch_utils; +std::string +default_gcc_target_options (struct gdbarch *gdbarch) +{ + return string_printf ("-m%d%s", gdbarch_ptr_bit (gdbarch), + (gdbarch_ptr_bit (gdbarch) == 64 + ? " -mcmodel=large" : "")); +} + +/* gdbarch gnu_triplet_regexp method. */ + +const char * +default_gnu_triplet_regexp (struct gdbarch *gdbarch) +{ + 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. */ + +int +default_addressable_memory_unit_size (struct gdbarch *gdbarch) +{ + return 1; +} + +void +default_guess_tracepoint_registers (struct gdbarch *gdbarch, + struct regcache *regcache, + CORE_ADDR addr) +{ + int pc_regno = gdbarch_pc_regnum (gdbarch); + gdb_byte *regs; + + /* This guessing code below only works if the PC register isn't + a pseudo-register. The value of a pseudo-register isn't stored + in the (non-readonly) regcache -- instead it's recomputed + (probably from some other cached raw register) whenever the + register is read. In this case, a custom method implementation + should be used by the architecture. */ + if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch)) + return; + + 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 (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, 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 *frame, CORE_ADDR pc) +{ + return ""; +} void _initialize_gdbarch_utils (void) { - struct cmd_list_element *c; - c = add_set_enum_cmd ("endian", class_support, - endian_enum, &set_endian_string, - "Set endianness of target.", - &setlist); - set_cmd_sfunc (c, set_endian); - /* Don't use set_from_show - need to print both auto/manual and - current setting. */ - add_cmd ("endian", class_support, show_endian, - "Show the current byte-order", &showlist); + add_setshow_enum_cmd ("endian", class_support, + endian_enum, &set_endian_string, + _("Set endianness of target."), + _("Show endianness of target."), + NULL, set_endian, show_endian, + &setlist, &showlist); }