|
|
|
@ -1161,6 +1161,27 @@ extern void *gdbarch_obstack_zalloc (struct gdbarch *gdbarch, long size); |
|
|
|
extern int gdbarch_update_p (struct gdbarch_info info); |
|
|
|
|
|
|
|
|
|
|
|
/* Helper function. Find an architecture matching info. |
|
|
|
|
|
|
|
INFO should be initialized using gdbarch_info_init, relevant fields |
|
|
|
set, and then finished using gdbarch_info_fill. |
|
|
|
|
|
|
|
Returns the corresponding architecture, or NULL if no matching |
|
|
|
architecture was found. "current_gdbarch" is not updated. */ |
|
|
|
|
|
|
|
extern struct gdbarch *gdbarch_find_by_info (struct gdbarch_info info); |
|
|
|
|
|
|
|
|
|
|
|
/* Helper function. Set the global "current_gdbarch" to "gdbarch". |
|
|
|
|
|
|
|
FIXME: kettenis/20031124: Of the functions that follow, only |
|
|
|
gdbarch_from_bfd is supposed to survive. The others will |
|
|
|
dissappear since in the future GDB will (hopefully) be truly |
|
|
|
multi-arch. However, for now we're still stuck with the concept of |
|
|
|
a single active architecture. */ |
|
|
|
|
|
|
|
extern void deprecated_current_gdbarch_select_hack (struct gdbarch *gdbarch); |
|
|
|
|
|
|
|
|
|
|
|
/* Register per-architecture data-pointer. |
|
|
|
|
|
|
|
@ -2111,19 +2132,24 @@ gdbarch_list_lookup_by_info (struct gdbarch_list *arches, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Update the current architecture. Return ZERO if the update request |
|
|
|
failed. */ |
|
|
|
/* Find an architecture that matches the specified INFO. Create a new |
|
|
|
architecture if needed. Return that new architecture. Assumes |
|
|
|
that there is no current architecture. */ |
|
|
|
|
|
|
|
int |
|
|
|
gdbarch_update_p (struct gdbarch_info info) |
|
|
|
static struct gdbarch * |
|
|
|
find_arch_by_info (struct gdbarch *old_gdbarch, struct gdbarch_info info) |
|
|
|
{ |
|
|
|
struct gdbarch *new_gdbarch; |
|
|
|
struct gdbarch *old_gdbarch; |
|
|
|
struct gdbarch_registration *rego; |
|
|
|
|
|
|
|
/* The existing architecture has been swapped out - all this code |
|
|
|
works from a clean slate. */ |
|
|
|
gdb_assert (current_gdbarch == NULL); |
|
|
|
|
|
|
|
/* Fill in missing parts of the INFO struct using a number of |
|
|
|
sources: \`\`set ...''; INFOabfd supplied; existing target. */ |
|
|
|
gdbarch_info_fill (current_gdbarch, &info); |
|
|
|
sources: "set ..."; INFOabfd supplied; and the existing |
|
|
|
architecture. */ |
|
|
|
gdbarch_info_fill (old_gdbarch, &info); |
|
|
|
|
|
|
|
/* Must have found some sort of architecture. */ |
|
|
|
gdb_assert (info.bfd_arch_info != NULL); |
|
|
|
@ -2131,28 +2157,28 @@ gdbarch_update_p (struct gdbarch_info info) |
|
|
|
if (gdbarch_debug) |
|
|
|
{ |
|
|
|
fprintf_unfiltered (gdb_stdlog, |
|
|
|
"gdbarch_update: info.bfd_arch_info %s\n", |
|
|
|
"find_arch_by_info: info.bfd_arch_info %s\n", |
|
|
|
(info.bfd_arch_info != NULL |
|
|
|
? info.bfd_arch_info->printable_name |
|
|
|
: "(null)")); |
|
|
|
fprintf_unfiltered (gdb_stdlog, |
|
|
|
"gdbarch_update: info.byte_order %d (%s)\n", |
|
|
|
"find_arch_by_info: info.byte_order %d (%s)\n", |
|
|
|
info.byte_order, |
|
|
|
(info.byte_order == BFD_ENDIAN_BIG ? "big" |
|
|
|
: info.byte_order == BFD_ENDIAN_LITTLE ? "little" |
|
|
|
: "default")); |
|
|
|
fprintf_unfiltered (gdb_stdlog, |
|
|
|
"gdbarch_update: info.osabi %d (%s)\n", |
|
|
|
"find_arch_by_info: info.osabi %d (%s)\n", |
|
|
|
info.osabi, gdbarch_osabi_name (info.osabi)); |
|
|
|
fprintf_unfiltered (gdb_stdlog, |
|
|
|
"gdbarch_update: info.abfd 0x%lx\n", |
|
|
|
"find_arch_by_info: info.abfd 0x%lx\n", |
|
|
|
(long) info.abfd); |
|
|
|
fprintf_unfiltered (gdb_stdlog, |
|
|
|
"gdbarch_update: info.tdep_info 0x%lx\n", |
|
|
|
"find_arch_by_info: info.tdep_info 0x%lx\n", |
|
|
|
(long) info.tdep_info); |
|
|
|
} |
|
|
|
|
|
|
|
/* Find the target that knows about this architecture. */ |
|
|
|
/* Find the tdep code that knows about this architecture. */ |
|
|
|
for (rego = gdbarch_registry; |
|
|
|
rego != NULL; |
|
|
|
rego = rego->next) |
|
|
|
@ -2161,82 +2187,61 @@ gdbarch_update_p (struct gdbarch_info info) |
|
|
|
if (rego == NULL) |
|
|
|
{ |
|
|
|
if (gdbarch_debug) |
|
|
|
fprintf_unfiltered (gdb_stdlog, "gdbarch_update: No matching architecture\\n"); |
|
|
|
fprintf_unfiltered (gdb_stdlog, "find_arch_by_info: " |
|
|
|
"No matching architecture\n"); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* Swap the data belonging to the old target out setting the |
|
|
|
installed data to zero. This stops the ->init() function trying |
|
|
|
to refer to the previous architecture's global data structures. */ |
|
|
|
current_gdbarch_swap_out_hack (); |
|
|
|
|
|
|
|
/* Save the previously selected architecture, setting the global to |
|
|
|
NULL. This stops ->init() trying to use the previous |
|
|
|
architecture's configuration. The previous architecture may not |
|
|
|
even be of the same architecture family. The most recent |
|
|
|
architecture of the same family is found at the head of the |
|
|
|
rego->arches list. */ |
|
|
|
old_gdbarch = current_gdbarch; |
|
|
|
current_gdbarch = NULL; |
|
|
|
|
|
|
|
/* Ask the target for a replacement architecture. */ |
|
|
|
/* Ask the tdep code for an architecture that matches "info". */ |
|
|
|
new_gdbarch = rego->init (info, rego->arches); |
|
|
|
|
|
|
|
/* Did the target like it? No. Reject the change and revert to the |
|
|
|
old architecture. */ |
|
|
|
/* Did the tdep code like it? No. Reject the change and revert to |
|
|
|
the old architecture. */ |
|
|
|
if (new_gdbarch == NULL) |
|
|
|
{ |
|
|
|
if (gdbarch_debug) |
|
|
|
fprintf_unfiltered (gdb_stdlog, "gdbarch_update: Target rejected architecture\\n"); |
|
|
|
current_gdbarch_swap_in_hack (old_gdbarch); |
|
|
|
return 0; |
|
|
|
fprintf_unfiltered (gdb_stdlog, "find_arch_by_info: " |
|
|
|
"Target rejected architecture\n"); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
/* Did the architecture change? No. Oops, put the old architecture |
|
|
|
back. */ |
|
|
|
if (old_gdbarch == new_gdbarch) |
|
|
|
/* Is this a pre-existing architecture (as determined by already |
|
|
|
being initialized)? Move it to the front of the architecture |
|
|
|
list (keeping the list sorted Most Recently Used). */ |
|
|
|
if (new_gdbarch->initialized_p) |
|
|
|
{ |
|
|
|
struct gdbarch_list **list; |
|
|
|
struct gdbarch_list *this; |
|
|
|
if (gdbarch_debug) |
|
|
|
fprintf_unfiltered (gdb_stdlog, "gdbarch_update: Architecture 0x%08lx (%s) unchanged\\n", |
|
|
|
fprintf_unfiltered (gdb_stdlog, "find_arch_by_info: " |
|
|
|
"Previous architecture 0x%08lx (%s) selected\n", |
|
|
|
(long) new_gdbarch, |
|
|
|
new_gdbarch->bfd_arch_info->printable_name); |
|
|
|
current_gdbarch_swap_in_hack (old_gdbarch); |
|
|
|
return 1; |
|
|
|
/* Find the existing arch in the list. */ |
|
|
|
for (list = ®o->arches; |
|
|
|
(*list) != NULL && (*list)->gdbarch != new_gdbarch; |
|
|
|
list = &(*list)->next); |
|
|
|
/* It had better be in the list of architectures. */ |
|
|
|
gdb_assert ((*list) != NULL && (*list)->gdbarch == new_gdbarch); |
|
|
|
/* Unlink THIS. */ |
|
|
|
this = (*list); |
|
|
|
(*list) = this->next; |
|
|
|
/* Insert THIS at the front. */ |
|
|
|
this->next = rego->arches; |
|
|
|
rego->arches = this; |
|
|
|
/* Return it. */ |
|
|
|
return new_gdbarch; |
|
|
|
} |
|
|
|
|
|
|
|
/* Is this a pre-existing architecture? Yes. Move it to the front |
|
|
|
of the list of architectures (keeping the list sorted Most |
|
|
|
Recently Used) and then copy it in. */ |
|
|
|
{ |
|
|
|
struct gdbarch_list **list; |
|
|
|
for (list = ®o->arches; |
|
|
|
(*list) != NULL; |
|
|
|
list = &(*list)->next) |
|
|
|
{ |
|
|
|
if ((*list)->gdbarch == new_gdbarch) |
|
|
|
{ |
|
|
|
struct gdbarch_list *this; |
|
|
|
if (gdbarch_debug) |
|
|
|
fprintf_unfiltered (gdb_stdlog, |
|
|
|
"gdbarch_update: Previous architecture 0x%08lx (%s) selected\n", |
|
|
|
(long) new_gdbarch, |
|
|
|
new_gdbarch->bfd_arch_info->printable_name); |
|
|
|
/* Unlink this. */ |
|
|
|
this = (*list); |
|
|
|
(*list) = this->next; |
|
|
|
/* Insert in the front. */ |
|
|
|
this->next = rego->arches; |
|
|
|
rego->arches = this; |
|
|
|
/* Copy the new architecture in. */ |
|
|
|
current_gdbarch_swap_in_hack (new_gdbarch); |
|
|
|
architecture_changed_event (); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* Prepend this new architecture to the architecture list (keep the |
|
|
|
list sorted Most Recently Used). */ |
|
|
|
/* It's a new architecture. */ |
|
|
|
if (gdbarch_debug) |
|
|
|
fprintf_unfiltered (gdb_stdlog, "find_arch_by_info: " |
|
|
|
"New architecture 0x%08lx (%s) selected\n", |
|
|
|
(long) new_gdbarch, |
|
|
|
new_gdbarch->bfd_arch_info->printable_name); |
|
|
|
|
|
|
|
/* Insert the new architecture into the front of the architecture |
|
|
|
list (keep the list sorted Most Recently Used). */ |
|
|
|
{ |
|
|
|
struct gdbarch_list *this = XMALLOC (struct gdbarch_list); |
|
|
|
this->next = rego->arches; |
|
|
|
@ -2244,37 +2249,59 @@ gdbarch_update_p (struct gdbarch_info info) |
|
|
|
rego->arches = this; |
|
|
|
} |
|
|
|
|
|
|
|
/* Switch to this new architecture marking it initialized. */ |
|
|
|
current_gdbarch = new_gdbarch; |
|
|
|
current_gdbarch->initialized_p = 1; |
|
|
|
if (gdbarch_debug) |
|
|
|
{ |
|
|
|
fprintf_unfiltered (gdb_stdlog, |
|
|
|
"gdbarch_update: New architecture 0x%08lx (%s) selected\\n", |
|
|
|
(long) new_gdbarch, |
|
|
|
new_gdbarch->bfd_arch_info->printable_name); |
|
|
|
} |
|
|
|
|
|
|
|
/* Check that the newly installed architecture is valid. Plug in |
|
|
|
any post init values. */ |
|
|
|
new_gdbarch->dump_tdep = rego->dump_tdep; |
|
|
|
verify_gdbarch (new_gdbarch); |
|
|
|
new_gdbarch->initialized_p = 1; |
|
|
|
|
|
|
|
/* Initialize the per-architecture memory (swap) areas. |
|
|
|
CURRENT_GDBARCH must be update before these modules are |
|
|
|
called. */ |
|
|
|
/* Initialize any per-architecture swap areas. This phase requires |
|
|
|
a valid global CURRENT_GDBARCH. Set it momentarially, and then |
|
|
|
swap the entire architecture out. */ |
|
|
|
current_gdbarch = new_gdbarch; |
|
|
|
current_gdbarch_swap_init_hack (); |
|
|
|
|
|
|
|
/* Initialize the per-architecture data. CURRENT_GDBARCH |
|
|
|
must be updated before these modules are called. */ |
|
|
|
architecture_changed_event (); |
|
|
|
current_gdbarch_swap_out_hack (); |
|
|
|
|
|
|
|
if (gdbarch_debug) |
|
|
|
gdbarch_dump (current_gdbarch, gdb_stdlog); |
|
|
|
gdbarch_dump (new_gdbarch, gdb_stdlog); |
|
|
|
|
|
|
|
return new_gdbarch; |
|
|
|
} |
|
|
|
|
|
|
|
struct gdbarch * |
|
|
|
gdbarch_find_by_info (struct gdbarch_info info) |
|
|
|
{ |
|
|
|
/* Save the previously selected architecture, setting the global to |
|
|
|
NULL. This stops things like gdbarch->init() trying to use the |
|
|
|
previous architecture's configuration. The previous architecture |
|
|
|
may not even be of the same architecture family. The most recent |
|
|
|
architecture of the same family is found at the head of the |
|
|
|
rego->arches list. */ |
|
|
|
struct gdbarch *old_gdbarch = current_gdbarch_swap_out_hack (); |
|
|
|
|
|
|
|
/* Find the specified architecture. */ |
|
|
|
struct gdbarch *new_gdbarch = find_arch_by_info (old_gdbarch, info); |
|
|
|
|
|
|
|
/* Restore the existing architecture. */ |
|
|
|
gdb_assert (current_gdbarch == NULL); |
|
|
|
current_gdbarch_swap_in_hack (old_gdbarch); |
|
|
|
|
|
|
|
return 1; |
|
|
|
return new_gdbarch; |
|
|
|
} |
|
|
|
|
|
|
|
/* Make the specified architecture current, swapping the existing one |
|
|
|
out. */ |
|
|
|
|
|
|
|
void |
|
|
|
deprecated_current_gdbarch_select_hack (struct gdbarch *new_gdbarch) |
|
|
|
{ |
|
|
|
gdb_assert (new_gdbarch != NULL); |
|
|
|
gdb_assert (current_gdbarch != NULL); |
|
|
|
gdb_assert (new_gdbarch->initialized_p); |
|
|
|
current_gdbarch_swap_out_hack (); |
|
|
|
current_gdbarch_swap_in_hack (new_gdbarch); |
|
|
|
architecture_changed_event (); |
|
|
|
} |
|
|
|
|
|
|
|
extern void _initialize_gdbarch (void); |
|
|
|
|
|
|
|
|