diff options
-rw-r--r-- | gdb/ChangeLog | 30 | ||||
-rw-r--r-- | gdb/arch-utils.c | 136 | ||||
-rw-r--r-- | gdb/arch-utils.h | 11 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/doc/gdbint.texinfo | 35 | ||||
-rw-r--r-- | gdb/exec.c | 2 | ||||
-rw-r--r-- | gdb/gdbarch.c | 10 | ||||
-rw-r--r-- | gdb/gdbarch.h | 3 | ||||
-rwxr-xr-x | gdb/gdbarch.sh | 13 | ||||
-rw-r--r-- | gdb/remote-sim.c | 2 |
10 files changed, 157 insertions, 90 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f6fd950..2a98c71 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,33 @@ +2006-11-10 Daniel Jacobowitz <dan@codesourcery.com> + + * arch-utils.c (target_byte_order_user): Renamed from + target_byte_order. + (target_byte_order_auto, selected_byte_order): Removed. + (show_endian): Check target_byte_order_user. + (set_endian): Always update the architecture. Set + target_byte_order_user after success. + (target_architecture_auto): Removed. + (target_architecture_user): New. + (selected_architecture_name, show_architecture): Check it. + (set_architecture): Set target_architecture_user after success. + (gdbarch_from_bfd): Check the argument. + (default_byte_order): New. + (initialize_current_architecture): Set the global default + architecture and endianness. + (gdbarch_info_fill): Remove GDBARCH argument. Do not check the + previous architecture. Use exec_bfd, global selected architecture + and endianness, and global defaults. + * arch-utils.h (selected_byte_order): Remove prototype. + (gdbarch_info_fill): Update. + * exec.c (exec_file_attach): Update the architecture after removing + the current file. + * gdbarch.sh: Update comments. + (find_arch_by_info): Remove OLD_GDBARCH argument. Update call to + gdbarch_info_fill. + (gdbarch_find_by_info): Update call to find_arch_by_info. + * gdbarch.h, gdbarch.c: Regenerated. + * remote-sim.c (gdbsim_open): Use TARGET_BYTE_ORDER. + 2006-11-09 Joel Brobecker <brobecker@adacore.com> * sparc-tdep.c (sparc_fetch_instruction): Read instruction diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index 702743d..c1801c9 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -335,24 +335,7 @@ generic_instruction_nullified (struct gdbarch *gdbarch, /* 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. */ -static int target_byte_order = BFD_ENDIAN_BIG; -static int target_byte_order_auto = 1; - -enum bfd_endian -selected_byte_order (void) -{ - if (target_byte_order_auto) - return BFD_ENDIAN_UNKNOWN; - else - return target_byte_order; -} +static int target_byte_order_user = BFD_ENDIAN_UNKNOWN; static const char endian_big[] = "big"; static const char endian_little[] = "little"; @@ -372,7 +355,7 @@ static void show_endian (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - if (target_byte_order_auto) + if (target_byte_order_user != BFD_ENDIAN_UNKNOWN) if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) fprintf_unfiltered (file, _("The target endianness is set automatically " "(currently big endian)\n")); @@ -391,31 +374,37 @@ show_endian (struct ui_file *file, int from_tty, struct cmd_list_element *c, static void set_endian (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) { - struct gdbarch_info info; - target_byte_order_auto = 0; - 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")); + else + target_byte_order_user = BFD_ENDIAN_LITTLE; } else if (set_endian_string == endian_big) { - struct gdbarch_info info; - target_byte_order_auto = 0; - 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")); + else + target_byte_order_user = BFD_ENDIAN_BIG; } else internal_error (__FILE__, __LINE__, _("set_endian: bad value")); + show_endian (gdb_stdout, from_tty, NULL, NULL); } @@ -423,14 +412,14 @@ set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c) enum set_arch { set_arch_auto, set_arch_manual }; -static int target_architecture_auto = 1; +static const struct bfd_arch_info *target_architecture_user; static const char *set_architecture_string; const char * selected_architecture_name (void) { - if (target_architecture_auto) + if (target_architecture_user == NULL) return NULL; else return set_architecture_string; @@ -445,7 +434,7 @@ show_architecture (struct ui_file *file, int from_tty, { const char *arch; arch = TARGET_ARCHITECTURE->printable_name; - if (target_architecture_auto) + if (target_architecture_user == NULL) fprintf_filtered (file, _("\ The target architecture is set automatically (currently %s)\n"), arch); else @@ -460,20 +449,25 @@ The target architecture is assumed to be %s\n"), arch); static void set_architecture (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 { - 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")); if (gdbarch_update_p (info)) - target_architecture_auto = 0; + target_architecture_user = info.bfd_arch_info; else printf_unfiltered (_("Architecture `%s' not recognized.\n"), set_architecture_string); @@ -530,6 +524,13 @@ gdbarch_from_bfd (bfd *abfd) struct gdbarch *new_gdbarch; struct gdbarch_info info; + /* If we call gdbarch_find_by_info without filling in info.abfd, + then it will use the global exec_bfd. That's fine if we don't + have one of those either. And that's the only time we should + reach here with a NULL ABFD argument - when we are discarding + the executable. */ + gdb_assert (abfd != NULL || exec_bfd == NULL); + gdbarch_info_init (&info); info.abfd = abfd; return gdbarch_find_by_info (info); @@ -567,6 +568,8 @@ static const bfd_target *default_bfd_vec = &DEFAULT_BFD_VEC; static const bfd_target *default_bfd_vec; #endif +static int default_byte_order = BFD_ENDIAN_UNKNOWN; + void initialize_current_architecture (void) { @@ -577,10 +580,7 @@ initialize_current_architecture (void) 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) + if (default_bfd_arch == NULL) { /* Choose the architecture by taking the first one alphabetically. */ @@ -594,30 +594,32 @@ 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) + default_bfd_arch = bfd_scan_arch (chosen); + if (default_bfd_arch == NULL) internal_error (__FILE__, __LINE__, _("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. */ 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. */ const char *chp; @@ -625,14 +627,16 @@ initialize_current_architecture (void) if (chp != NULL && chp - 2 >= target_name && strncmp (chp - 2, "el", 2) == 0) - info.byte_order = BFD_ENDIAN_LITTLE; + 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; } + info.byte_order = default_byte_order; + if (! gdbarch_update_p (info)) internal_error (__FILE__, __LINE__, _("initialize_current_architecture: Selection of " @@ -674,48 +678,46 @@ gdbarch_info_init (struct gdbarch_info *info) } /* Similar to init, but this time fill in the blanks. Information is - obtained from the specified architecture, global "set ..." options, - and explicitly initialized INFO fields. */ + obtained from the global "set ..." options and explicitly + initialized INFO fields. */ void -gdbarch_info_fill (struct gdbarch *gdbarch, struct gdbarch_info *info) +gdbarch_info_fill (struct gdbarch_info *info) { + /* Check for the current file. */ + if (info->abfd == NULL) + info->abfd = exec_bfd; + /* "(gdb) set architecture ...". */ if (info->bfd_arch_info == NULL - && !target_architecture_auto - && gdbarch != NULL) - info->bfd_arch_info = gdbarch_bfd_arch_info (gdbarch); + && target_architecture_user) + info->bfd_arch_info = target_architecture_user; 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); - if (info->bfd_arch_info == NULL - && gdbarch != NULL) - info->bfd_arch_info = gdbarch_bfd_arch_info (gdbarch); + /* 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_auto - && gdbarch != NULL) - info->byte_order = gdbarch_byte_order (gdbarch); + && 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 current target. */ - if (info->byte_order == BFD_ENDIAN_UNKNOWN - && gdbarch != NULL) - info->byte_order = gdbarch_byte_order (gdbarch); + : 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; /* "(gdb) set osabi ...". Handled by gdbarch_lookup_osabi. */ if (info->osabi == GDB_OSABI_UNINITIALIZED) info->osabi = gdbarch_lookup_osabi (info->abfd); - if (info->osabi == GDB_OSABI_UNINITIALIZED - && gdbarch != NULL) - info->osabi = gdbarch_osabi (gdbarch); /* Must have at least filled in the architecture. */ gdb_assert (info->bfd_arch_info != NULL); diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h index 533f5af..1fec80f 100644 --- a/gdb/arch-utils.h +++ b/gdb/arch-utils.h @@ -126,10 +126,6 @@ extern int generic_instruction_nullified (struct gdbarch *gdbarch, extern int legacy_register_sim_regno (int regnum); -/* Return the selected byte order, or BFD_ENDIAN_UNKNOWN if no byte - order was explicitly selected. */ -extern enum bfd_endian selected_byte_order (void); - /* Return the selected architecture's name, or NULL if no architecture was explicitly selected. */ extern const char *selected_architecture_name (void); @@ -141,10 +137,9 @@ extern const char *selected_architecture_name (void); extern void gdbarch_info_init (struct gdbarch_info *info); /* Similar to init, but this time fill in the blanks. Information is - obtained from the specified architecture, global "set ..." options, - and explicitly initialized INFO fields. */ -extern void gdbarch_info_fill (struct gdbarch *gdbarch, - struct gdbarch_info *info); + obtained from the global "set ..." options and explicitly + initialized INFO fields. */ +extern void gdbarch_info_fill (struct gdbarch_info *info); /* Return the architecture for ABFD. If no suitable architecture could be find, return NULL. */ diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 8a327df..853f505 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2006-11-10 Daniel Jacobowitz <dan@codesourcery.com> + + * gdbint.texinfo (Target Architecture Definition): Add new + Initializing a New Architecture section. + 2006-10-31 David Taylor <dtaylor@emc.com> * stabs.texinfo (Macro define and undefine): New node describing diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo index cb77108..229fb62 100644 --- a/gdb/doc/gdbint.texinfo +++ b/gdb/doc/gdbint.texinfo @@ -2722,6 +2722,41 @@ architecture, a warning will be issued and the debugging session will continue with the defaults already established for @var{gdbarch}. @end deftypefun +@section Initializing a New Architecture + +Each @code{gdbarch} is associated with a single @sc{bfd} architecture, +via a @code{bfd_arch_@var{arch}} constant. The @code{gdbarch} is +registered by a call to @code{register_gdbarch_init}, usually from +the file's @code{_initialize_@var{filename}} routine, which will +be automatically called during @value{GDBN} startup. The arguments +are a @sc{bfd} architecture constant and an initialization function. + +The initialization function has this type: + +@smallexample +static struct gdbarch * +@var{arch}_gdbarch_init (struct gdbarch_info @var{info}, + struct gdbarch_list *@var{arches}) +@end smallexample + +The @var{info} argument contains parameters used to select the correct +architecture, and @var{arches} is a list of architectures which +have already been created with the same @code{bfd_arch_@var{arch}} +value. + +The initialization function should first make sure that @var{info} +is acceptable, and return @code{NULL} if it is not. Then, it should +search through @var{arches} for an exact match to @var{info}, and +return one if found. Lastly, if no exact match was found, it should +create a new architecture based on @var{info} and return it. + +Only information in @var{info} should be used to choose the new +architecture. Historically, @var{info} could be sparse, and +defaults would be collected from the first element on @var{arches}. +However, @value{GDBN} now fills in @var{info} more thoroughly, +so new @code{gdbarch} initialization functions should not take +defaults from @var{arches}. + @section Registers and Memory @value{GDBN}'s model of the target machine is rather simple. @@ -188,6 +188,8 @@ exec_file_attach (char *filename, int from_tty) { if (from_tty) printf_unfiltered (_("No executable file now.\n")); + + set_gdbarch_from_file (NULL); } else { diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index cad6e04..784816f 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -3987,7 +3987,7 @@ gdbarch_list_lookup_by_info (struct gdbarch_list *arches, that there is no current architecture. */ static struct gdbarch * -find_arch_by_info (struct gdbarch *old_gdbarch, struct gdbarch_info info) +find_arch_by_info (struct gdbarch_info info) { struct gdbarch *new_gdbarch; struct gdbarch_registration *rego; @@ -3997,9 +3997,9 @@ find_arch_by_info (struct gdbarch *old_gdbarch, struct gdbarch_info info) gdb_assert (current_gdbarch == NULL); /* Fill in missing parts of the INFO struct using a number of - sources: "set ..."; INFOabfd supplied; and the existing - architecture. */ - gdbarch_info_fill (old_gdbarch, &info); + 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 != NULL); @@ -4130,7 +4130,7 @@ gdbarch_find_by_info (struct gdbarch_info info) struct gdbarch *old_gdbarch = current_gdbarch_swap_out_hack (); /* Find the specified architecture. */ - struct gdbarch *new_gdbarch = find_arch_by_info (old_gdbarch, info); + struct gdbarch *new_gdbarch = find_arch_by_info (info); /* Restore the existing architecture. */ gdb_assert (current_gdbarch == NULL); diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index a4764f8..1bebaa6 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -1420,8 +1420,7 @@ extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch); ``struct gdbarch'' for this architecture. The INFO parameter is, as far as possible, be pre-initialized with - information obtained from INFO.ABFD or the previously selected - architecture. + information obtained from INFO.ABFD or the global defaults. The ARCHES parameter is a linked list (sorted most recently used) of all the previously created architures for this architecture diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index b3d3547..a815f047 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -943,8 +943,7 @@ extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch); \`\`struct gdbarch'' for this architecture. The INFO parameter is, as far as possible, be pre-initialized with - information obtained from INFO.ABFD or the previously selected - architecture. + information obtained from INFO.ABFD or the global defaults. The ARCHES parameter is a linked list (sorted most recently used) of all the previously created architures for this architecture @@ -2050,7 +2049,7 @@ gdbarch_list_lookup_by_info (struct gdbarch_list *arches, that there is no current architecture. */ static struct gdbarch * -find_arch_by_info (struct gdbarch *old_gdbarch, struct gdbarch_info info) +find_arch_by_info (struct gdbarch_info info) { struct gdbarch *new_gdbarch; struct gdbarch_registration *rego; @@ -2060,9 +2059,9 @@ find_arch_by_info (struct gdbarch *old_gdbarch, struct gdbarch_info info) gdb_assert (current_gdbarch == NULL); /* Fill in missing parts of the INFO struct using a number of - sources: "set ..."; INFOabfd supplied; and the existing - architecture. */ - gdbarch_info_fill (old_gdbarch, &info); + 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 != NULL); @@ -2193,7 +2192,7 @@ gdbarch_find_by_info (struct gdbarch_info info) struct gdbarch *old_gdbarch = current_gdbarch_swap_out_hack (); /* Find the specified architecture. */ - struct gdbarch *new_gdbarch = find_arch_by_info (old_gdbarch, info); + struct gdbarch *new_gdbarch = find_arch_by_info (info); /* Restore the existing architecture. */ gdb_assert (current_gdbarch == NULL); diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c index 9b432b0..cdd41ed 100644 --- a/gdb/remote-sim.c +++ b/gdb/remote-sim.c @@ -506,7 +506,7 @@ gdbsim_open (char *args, int from_tty) strcpy (arg_buf, "gdbsim"); /* 7 */ /* Specify the byte order for the target when it is both selectable and explicitly specified by the user (not auto detected). */ - switch (selected_byte_order ()) + switch (TARGET_BYTE_ORDER) { case BFD_ENDIAN_BIG: strcat (arg_buf, " -E big"); |