aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog30
-rw-r--r--gdb/arch-utils.c136
-rw-r--r--gdb/arch-utils.h11
-rw-r--r--gdb/doc/ChangeLog5
-rw-r--r--gdb/doc/gdbint.texinfo35
-rw-r--r--gdb/exec.c2
-rw-r--r--gdb/gdbarch.c10
-rw-r--r--gdb/gdbarch.h3
-rwxr-xr-xgdb/gdbarch.sh13
-rw-r--r--gdb/remote-sim.c2
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.
diff --git a/gdb/exec.c b/gdb/exec.c
index 9653c24..4ef2f7a 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -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");