X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Farch-utils.c;h=887aa9d72239d6f2bc7a5bfd55262182bd9eda89;hb=8758dec1c5c5119a4f9cb59da8375596f0314f94;hp=2b23951fb9b666ed9e5c3085caf86797f3b1429a;hpb=c8f9d51ce2e3eb695d8539d5615d0831ff906b3b;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index 2b23951fb9..887aa9d722 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -1,5 +1,7 @@ /* Dynamic architecture support for GDB, the GNU debugger. - Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + + Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, + Inc. This file is part of GDB. @@ -21,6 +23,7 @@ #include "defs.h" #if GDB_MULTI_ARCH +#include "arch-utils.h" #include "gdbcmd.h" #include "inferior.h" /* enum CALL_DUMMY_LOCATION et.al. */ #else @@ -39,6 +42,7 @@ #endif #include "regcache.h" #include "gdb_assert.h" +#include "sim-regno.h" #include "version.h" @@ -54,14 +58,14 @@ and optionally adjust the pc to point to the correct memory location for inserting the breakpoint. */ -unsigned char * +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 == BIG_ENDIAN) + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) { static unsigned char big_break_insn[] = BIG_BREAKPOINT; *lenptr = sizeof (big_break_insn); @@ -69,7 +73,7 @@ legacy_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr) } #endif #ifdef LITTLE_BREAKPOINT - if (TARGET_BYTE_ORDER != BIG_ENDIAN) + if (TARGET_BYTE_ORDER != BFD_ENDIAN_BIG) { static unsigned char little_break_insn[] = LITTLE_BREAKPOINT; *lenptr = sizeof (little_break_insn); @@ -87,6 +91,22 @@ legacy_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr) return NULL; } +int +legacy_register_sim_regno (int regnum) +{ + /* Only makes sense to supply raw registers. */ + gdb_assert (regnum >= 0 && regnum < NUM_REGS); + /* 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 + (below). */ + if (REGISTER_NAME (regnum) != NULL + && REGISTER_NAME (regnum)[0] != '\0') + return regnum; + else + return LEGACY_SIM_REGNO_IGNORE; +} + int generic_frameless_function_invocation_not (struct frame_info *fi) { @@ -151,11 +171,7 @@ generic_remote_translate_xfer_address (CORE_ADDR gdb_addr, int gdb_len, int generic_prologue_frameless_p (CORE_ADDR ip) { -#ifdef SKIP_PROLOGUE_FRAMELESS_P - return ip == SKIP_PROLOGUE_FRAMELESS_P (ip); -#else return ip == SKIP_PROLOGUE (ip); -#endif } /* New/multi-arched targets should use the correct gdbarch field @@ -193,9 +209,9 @@ default_float_format (struct gdbarch *gdbarch) #endif switch (byte_order) { - case BIG_ENDIAN: + case BFD_ENDIAN_BIG: return &floatformat_ieee_single_big; - case LITTLE_ENDIAN: + case BFD_ENDIAN_LITTLE: return &floatformat_ieee_single_little; default: internal_error (__FILE__, __LINE__, @@ -214,9 +230,9 @@ default_double_format (struct gdbarch *gdbarch) #endif switch (byte_order) { - case BIG_ENDIAN: + case BFD_ENDIAN_BIG: return &floatformat_ieee_double_big; - case LITTLE_ENDIAN: + case BFD_ENDIAN_LITTLE: return &floatformat_ieee_double_little; default: internal_error (__FILE__, __LINE__, @@ -224,6 +240,21 @@ default_double_format (struct gdbarch *gdbarch) } } +void +default_print_float_info (struct gdbarch *gdbarch, struct ui_file *file, + struct frame_info *frame) +{ +#ifdef FLOAT_INFO +#if GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL +#error "FLOAT_INFO defined in multi-arch" +#endif + FLOAT_INFO; +#else + fprintf_filtered (file, "\ +No floating point info available for this processor.\n"); +#endif +} + /* Misc helper functions for targets. */ int @@ -255,13 +286,6 @@ generic_cannot_extract_struct_value_address (char *dummy) return 0; } -int -default_register_sim_regno (int num) -{ - return num; -} - - CORE_ADDR core_addr_identity (CORE_ADDR addr) { @@ -326,7 +350,7 @@ generic_prepare_to_proceed (int select_it) flush_cached_frames (); registers_changed (); stop_pc = wait_pc; - select_frame (get_current_frame (), 0); + 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 @@ -358,6 +382,18 @@ init_frame_pc_default (int fromleaf, struct frame_info *prev) prev->pc = read_pc (); } +void +default_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym) +{ + return; +} + +void +default_coff_make_msymbol_special (int val, struct minimal_symbol *msym) +{ + return; +} + int cannot_register_not (int regnum) { @@ -376,33 +412,66 @@ legacy_virtual_frame_pointer (CORE_ADDR pc, *frame_regnum = FP_REGNUM; *frame_offset = 0; } - -/* Functions to manipulate the endianness of the target. */ -#ifdef TARGET_BYTE_ORDER_SELECTABLE -/* compat - Catch old targets that expect a selectable byte-order to - default to BIG_ENDIAN */ -#ifndef TARGET_BYTE_ORDER_DEFAULT -#define TARGET_BYTE_ORDER_DEFAULT BIG_ENDIAN -#endif -#endif -#if !TARGET_BYTE_ORDER_SELECTABLE_P -#ifndef TARGET_BYTE_ORDER_DEFAULT -/* compat - Catch old non byte-order selectable targets that do not - define TARGET_BYTE_ORDER_DEFAULT and instead expect - TARGET_BYTE_ORDER to be used as the default. For targets that - defined neither TARGET_BYTE_ORDER nor TARGET_BYTE_ORDER_DEFAULT the - below will get a strange compiler warning. */ -#define TARGET_BYTE_ORDER_DEFAULT TARGET_BYTE_ORDER -#endif +/* Assume the world is sane, every register's virtual and real size + is identical. */ + +int +generic_register_size (int regnum) +{ + gdb_assert (regnum >= 0 && regnum < NUM_REGS + NUM_PSEUDO_REGS); + return TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (regnum)); +} + +#if !defined (IN_SIGTRAMP) +#if defined (SIGTRAMP_START) +#define IN_SIGTRAMP(pc, name) \ + ((pc) >= SIGTRAMP_START(pc) \ + && (pc) < SIGTRAMP_END(pc) \ + ) +#else +#define IN_SIGTRAMP(pc, name) \ + (name && STREQ ("_sigtramp", name)) #endif -#ifndef TARGET_BYTE_ORDER_DEFAULT -#define TARGET_BYTE_ORDER_DEFAULT BIG_ENDIAN /* arbitrary */ #endif + +int +legacy_pc_in_sigtramp (CORE_ADDR pc, char *name) +{ + return IN_SIGTRAMP(pc, name); +} + +int +legacy_convert_register_p (int regnum) +{ + return REGISTER_CONVERTIBLE (regnum); +} + +void +legacy_register_to_value (int regnum, struct type *type, + char *from, char *to) +{ + REGISTER_CONVERT_TO_VIRTUAL (regnum, type, from, to); +} + +void +legacy_value_to_register (struct type *type, int regnum, + char *from, char *to) +{ + REGISTER_CONVERT_TO_RAW (type, regnum, from, to); +} + + +/* 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 - TARGET_BYTE_ORDER which is controlled by gdbarch.*. */ -int target_byte_order = TARGET_BYTE_ORDER_DEFAULT; + 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 const char endian_big[] = "big"; @@ -424,20 +493,16 @@ 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 == BIG_ENDIAN ? "big" : "little")); + (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? "big" : "little")); else printf_unfiltered ("The target is assumed to be %s endian\n", - (TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little")); + (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? "big" : "little")); } static void set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c) { - if (!TARGET_BYTE_ORDER_SELECTABLE_P) - { - printf_unfiltered ("Byte order is not selectable."); - } - else if (set_endian_string == endian_auto) + if (set_endian_string == endian_auto) { target_byte_order_auto = 1; } @@ -447,8 +512,8 @@ set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c) if (GDB_MULTI_ARCH) { struct gdbarch_info info; - memset (&info, 0, sizeof info); - info.byte_order = LITTLE_ENDIAN; + 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"); @@ -456,7 +521,7 @@ set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c) } else { - target_byte_order = LITTLE_ENDIAN; + target_byte_order = BFD_ENDIAN_LITTLE; } } else if (set_endian_string == endian_big) @@ -465,8 +530,8 @@ set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c) if (GDB_MULTI_ARCH) { struct gdbarch_info info; - memset (&info, 0, sizeof info); - info.byte_order = BIG_ENDIAN; + 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"); @@ -474,7 +539,7 @@ set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c) } else { - target_byte_order = BIG_ENDIAN; + target_byte_order = BFD_ENDIAN_BIG; } } else @@ -488,33 +553,20 @@ set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c) 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 (TARGET_BYTE_ORDER_SELECTABLE_P) - { - int want; - - if (bfd_big_endian (abfd)) - want = BIG_ENDIAN; - else - want = LITTLE_ENDIAN; - 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 == BIG_ENDIAN ? "big" : "little", - TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little"); - } + if (bfd_big_endian (abfd)) + want = BFD_ENDIAN_BIG; else - { - if (bfd_big_endian (abfd) - ? TARGET_BYTE_ORDER != BIG_ENDIAN - : TARGET_BYTE_ORDER == BIG_ENDIAN) - warning ("%s endian file does not match %s endian target.", - bfd_big_endian (abfd) ? "big" : "little", - TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little"); - } + 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"); } @@ -644,7 +696,7 @@ set_architecture (char *ignore_args, int from_tty, struct cmd_list_element *c) else if (GDB_MULTI_ARCH) { struct gdbarch_info info; - memset (&info, 0, sizeof 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__, @@ -676,7 +728,7 @@ set_gdbarch_from_file (bfd *abfd) if (GDB_MULTI_ARCH) { struct gdbarch_info info; - memset (&info, 0, sizeof info); + gdbarch_info_init (&info); info.abfd = abfd; if (! gdbarch_update_p (info)) error ("Architecture of file not recognized.\n"); @@ -713,7 +765,7 @@ initialize_current_architecture (void) /* determine a default architecture and byte order. */ struct gdbarch_info info; - memset (&info, 0, sizeof (info)); + gdbarch_info_init (&info); /* Find a default architecture. */ if (info.bfd_arch_info == NULL @@ -739,26 +791,24 @@ initialize_current_architecture (void) "initialize_current_architecture: Arch not found"); } - /* take several guesses at a byte order. */ - /* NB: can't use TARGET_BYTE_ORDER_DEFAULT as its definition is - forced above. */ - if (info.byte_order == 0 + /* Take several guesses at a byte order. */ + if (info.byte_order == BFD_ENDIAN_UNKNOWN && default_bfd_vec != NULL) { /* Extract BFD's default vector's byte order. */ switch (default_bfd_vec->byteorder) { case BFD_ENDIAN_BIG: - info.byte_order = BIG_ENDIAN; + info.byte_order = BFD_ENDIAN_BIG; break; case BFD_ENDIAN_LITTLE: - info.byte_order = LITTLE_ENDIAN; + info.byte_order = BFD_ENDIAN_LITTLE; break; default: break; } } - if (info.byte_order == 0) + if (info.byte_order == BFD_ENDIAN_UNKNOWN) { /* look for ``*el-*'' in the target name. */ const char *chp; @@ -766,12 +816,12 @@ initialize_current_architecture (void) if (chp != NULL && chp - 2 >= target_name && strncmp (chp - 2, "el", 2) == 0) - info.byte_order = LITTLE_ENDIAN; + info.byte_order = BFD_ENDIAN_LITTLE; } - if (info.byte_order == 0) + if (info.byte_order == BFD_ENDIAN_UNKNOWN) { /* Wire it to big-endian!!! */ - info.byte_order = BIG_ENDIAN; + info.byte_order = BFD_ENDIAN_BIG; } if (GDB_MULTI_ARCH) @@ -783,7 +833,13 @@ initialize_current_architecture (void) } } else - initialize_non_multiarch (); + { + /* 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 (); + } /* Create the ``set architecture'' command appending ``auto'' to the list of architectures. */ @@ -802,7 +858,7 @@ initialize_current_architecture (void) arches, &set_architecture_string, "Set architecture of target.", &setlist); - c->function.sfunc = set_architecture; + set_cmd_sfunc (c, set_architecture); add_alias_cmd ("processor", "architecture", class_support, 1, &setlist); /* Don't use set_from_show - need to print both auto/manual and current setting. */ @@ -812,6 +868,19 @@ initialize_current_architecture (void) } +/* 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 + 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; +} + /* */ extern initialize_file_ftype _initialize_gdbarch_utils; @@ -824,7 +893,7 @@ _initialize_gdbarch_utils (void) endian_enum, &set_endian_string, "Set endianness of target.", &setlist); - c->function.sfunc = set_endian; + 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,