From dcf46491d817c78708176a83fb034a7b72664d0c Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Wed, 16 Dec 1998 15:01:03 +0000 Subject: [PATCH] CARP: Add multi-arch code! --- gdb/ChangeLog | 38 ++++ gdb/gdbarch.c | 627 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- gdb/gdbarch.h | 171 ++++++++++++++++ 3 files changed, 835 insertions(+), 1 deletion(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0f55ca4..840415d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,41 @@ +start-sanitize-carp start-sanitize-vr4xxx +Thu Dec 17 01:58:16 1998 Andrew Cagney + + * gdbarch.h (GDB_MULTI_ARCH): New macro, default to zero. + (current_gdbarch): Current architecture pointer. + * gdbarch.c (struct gdbarch): Define. + + * gdbarch.h (TARGET_ARCHITECTURE, TARGET_BYTE_ORDER, + TARGET_LONG_BIT, TARGET_LONG_LONG_BIT, TARGET_PTR_BIT): When + multi-arch force definition. + * gdbarch.h, gdbarch.c (gdbarch_tdep, gdbarch_bfd_arch_info, + gdbarch_byte_order, {set,}gdbarch_long_bit, + {set,}gdbarch_long_long_bit, {set,}gdbarch_ptr_bit): Corresponding + functions. + + * gdbarch.h (struct gdbarch_list, struct gdbarch_info, + gdbarch_init_ftype), gdbarch.c (register_gdbarch_init): Mechanism + for registering an architecture with GDB. + (gdbarch_list_lookup_by_info, gdbarch_alloc, gdbarch_update, + verify_gdbarch): Support functions. + + * gdbarch.h (gdbarch_data_ftype), gdbarch.c + (register_gdbarch_data, gdbarch_data): Mechanism for maintaining + per-architecture pointers. + (init_gdbarch_data): Support functions. + + * gdbarch.h (gdbarch_swap_ftype), gdbarch.c + (register_gdbarch_swap): Ditto for swapped memory regions. + (init_gdbarch_swap, swapout_gdbarch_swap, swapin_gdbarch_swap): + Support functions. + + * gdbarch.c (set_endian_big, set_endian_little, set_architecture, + info_architecture, set_gdbarch_from_file): Hook in multi-arch + code by calling gdbarch_update. + (default_gdbarch): Default multi-arch vector. Use host's type + system for values. + +end-sanitize-carp end-sanitize-vr4xxx Thu Dec 17 01:34:36 1998 Andrew Cagney * gdbtypes.c (build_gdbtypes): New function. diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index a3d1024..263ee73 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -22,13 +22,539 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gdbcmd.h" +/* start-sanitize-carp start-sanitize-vr4xxx */ +/* Convenience macro for allocting memory. */ + +#ifndef XMALLOC +#define XMALLOC(TYPE) (TYPE*) xmalloc (sizeof (TYPE)) +#endif + +/* end-sanitize-carp end-sanitize-vr4xxx */ + /* Non-zero if we want to trace architecture code. */ #ifndef GDBARCH_DEBUG -#define GDBARCH_DEBUG 1 +#define GDBARCH_DEBUG 0 #endif int gdbarch_debug = GDBARCH_DEBUG; +/* start-sanitize-carp start-sanitize-vr4xxx */ + +/* Maintain the struct gdbarch object */ + +struct gdbarch +{ + /* basic architectural information */ + const struct bfd_arch_info *bfd_arch_info; + int byte_order; + + /* target specific vector. */ + struct gdbarch_tdep *tdep; + + /* per-architecture data-pointers */ + int nr_data; + void **data; + + /* per-architecture swap-regions */ + struct gdbarch_swap *swap; + + /* Multi-arch values. + + When adding to the below you must also: declare/define set/get + value functions; override the corresponding macro in gdbarch.h; + initialize the value in gdbarch_alloc() (if zero is an unsuitable + default); confirm that the target updated the value correctly in + verify_gdbarch(); add a fprintf_unfiltered call to + gdbarch_update() so that the new field is dumped out; append an + initial value to the static variable DEFAULT_GDBARCH (base values + on the host's c-type system). */ + + int long_bit; + int long_long_bit; + int ptr_bit; + +}; + + +struct gdbarch_tdep * +gdbarch_tdep (gdbarch) + struct gdbarch *gdbarch; +{ + return gdbarch->tdep; +} + +const struct bfd_arch_info * +gdbarch_bfd_arch_info (gdbarch) + struct gdbarch *gdbarch; +{ + return gdbarch->bfd_arch_info; +} + +int +gdbarch_byte_order (gdbarch) + struct gdbarch *gdbarch; +{ + return gdbarch->byte_order; +} + +int +gdbarch_long_bit (gdbarch) + struct gdbarch *gdbarch; +{ + return gdbarch->long_bit; +} + +void +set_gdbarch_long_bit (gdbarch, long_bit) + struct gdbarch *gdbarch; + int long_bit; +{ + gdbarch->long_bit = long_bit; +} + +int +gdbarch_long_long_bit (gdbarch) + struct gdbarch *gdbarch; +{ + return gdbarch->long_long_bit; +} + +void +set_gdbarch_long_long_bit (gdbarch, long_long_bit) + struct gdbarch *gdbarch; + int long_long_bit; +{ + gdbarch->long_long_bit = long_long_bit; +} + +int +gdbarch_ptr_bit (gdbarch) + struct gdbarch *gdbarch; +{ + return gdbarch->ptr_bit; +} + +void +set_gdbarch_ptr_bit (gdbarch, ptr_bit) + struct gdbarch *gdbarch; + int ptr_bit; +{ + gdbarch->ptr_bit = ptr_bit; +} + + +/* Ensure that all values in a GDBARCH are reasonable. XXX - should + this instead return a success/fail indication? */ + +static void +verify_gdbarch (gdbarch) + struct gdbarch *gdbarch; +{ + /* fundamental */ + if (gdbarch->byte_order == 0) + fatal ("verify_gdbarch: byte-order unset"); + if (gdbarch->bfd_arch_info == NULL) + fatal ("verify_gdbarch: bfd_arch_info unset"); + /* more general */ + if (gdbarch->long_bit == 0) + fatal ("verify_gdbarch: long_bit invalid"); + if (gdbarch->long_long_bit == 0) + fatal ("verify_gdbarch: long_long_bit invalid"); + if (gdbarch->ptr_bit == 0) + fatal ("verify_gdbarch: ptr_bit invalid"); +} + + +/* Keep a registrary of per-architecture data-pointers required by GDB + modules. */ + +struct gdbarch_data +{ + int index; +}; + +struct gdbarch_data_registration +{ + gdbarch_data_ftype *init; + struct gdbarch_data *data; + struct gdbarch_data_registration *next; +}; + +struct gdbarch_data_registrary +{ + int nr; + struct gdbarch_data_registration *registrations; +}; + +struct gdbarch_data_registrary gdbarch_data_registrary = +{ + 0, NULL, +}; + +struct gdbarch_data * +register_gdbarch_data (init) + gdbarch_data_ftype *init; +{ + struct gdbarch_data_registration **curr; + for (curr = &gdbarch_data_registrary.registrations; + (*curr) != NULL; + curr = &(*curr)->next); + (*curr) = XMALLOC (struct gdbarch_data_registration); + (*curr)->next = NULL; + (*curr)->init = init; + (*curr)->data = XMALLOC (struct gdbarch_data); + (*curr)->data->index = gdbarch_data_registrary.nr++; + return (*curr)->data; +} + + +/* Walk through all the registered users initializing each in turn. */ + +static void init_gdbarch_data PARAMS ((struct gdbarch *)); +static void +init_gdbarch_data (gdbarch) + struct gdbarch *gdbarch; +{ + struct gdbarch_data_registration *rego; + gdbarch->nr_data = gdbarch_data_registrary.nr + 1; + gdbarch->data = xmalloc (sizeof (void*) * gdbarch->nr_data); + for (rego = gdbarch_data_registrary.registrations; + rego != NULL; + rego = rego->next) + { + if (rego->data->index < gdbarch->nr_data) + gdbarch->data[rego->data->index] = rego->init (); + } +} + + +/* Return the current value of the specified per-architecture + data-pointer. */ + +void * +gdbarch_data (data) + struct gdbarch_data *data; +{ + if (data->index >= current_gdbarch->nr_data) + fatal ("gdbarch_data: request for non-existant data."); + return current_gdbarch->data[data->index]; +} + + + +/* Keep a registrary of swaped data required by GDB modules. */ + +struct gdbarch_swap +{ + void *swap; + struct gdbarch_swap_registration *source; + struct gdbarch_swap *next; +}; + +struct gdbarch_swap_registration +{ + void *data; + unsigned long sizeof_data; + gdbarch_swap_ftype *init; + struct gdbarch_swap_registration *next; +}; + +struct gdbarch_swap_registrary +{ + int nr; + struct gdbarch_swap_registration *registrations; +}; + +struct gdbarch_swap_registrary gdbarch_swap_registrary = +{ + 0, NULL, +}; + +void +register_gdbarch_swap (data, sizeof_data, init) + void *data; + unsigned long sizeof_data; + gdbarch_swap_ftype *init; +{ + struct gdbarch_swap_registration **rego; + for (rego = &gdbarch_swap_registrary.registrations; + (*rego) != NULL; + rego = &(*rego)->next); + (*rego) = XMALLOC (struct gdbarch_swap_registration); + (*rego)->next = NULL; + (*rego)->init = init; + (*rego)->data = data; + (*rego)->sizeof_data = sizeof_data; +} + + +static void init_gdbarch_swap PARAMS ((struct gdbarch *)); +static void +init_gdbarch_swap (gdbarch) + struct gdbarch *gdbarch; +{ + struct gdbarch_swap_registration *rego; + struct gdbarch_swap **curr = &gdbarch->swap; + for (rego = gdbarch_swap_registrary.registrations; + rego != NULL; + rego = rego->next) + { + if (rego->data != NULL) + { + (*curr) = XMALLOC (struct gdbarch_swap); + (*curr)->source = rego; + (*curr)->swap = xmalloc (rego->sizeof_data); + (*curr)->next = NULL; + memset (rego->data, 0, rego->sizeof_data); + curr = &(*curr)->next; + } + if (rego->init != NULL) + rego->init (); + } +} + +static void swapout_gdbarch_swap PARAMS ((struct gdbarch *)); +static void +swapout_gdbarch_swap (gdbarch) + struct gdbarch *gdbarch; +{ + struct gdbarch_swap *curr; + for (curr = gdbarch->swap; + curr != NULL; + curr = curr->next) + memcpy (curr->swap, curr->source->data, curr->source->sizeof_data); +} + +static void swapin_gdbarch_swap PARAMS ((struct gdbarch *)); +static void +swapin_gdbarch_swap (gdbarch) + struct gdbarch *gdbarch; +{ + struct gdbarch_swap *curr; + for (curr = gdbarch->swap; + curr != NULL; + curr = curr->next) + memcpy (curr->source->data, curr->swap, curr->source->sizeof_data); +} + + +/* Keep a registrary of the architectures known by GDB. */ + +struct gdbarch_init_registration +{ + enum bfd_architecture bfd_architecture; + gdbarch_init_ftype *init; + struct gdbarch_list *arches; + struct gdbarch_init_registration *next; +}; + +static struct gdbarch_init_registration *gdbarch_init_registrary = NULL; + +void +register_gdbarch_init (bfd_architecture, init) + enum bfd_architecture bfd_architecture; + gdbarch_init_ftype *init; +{ + struct gdbarch_init_registration **curr; + const struct bfd_arch_info *bfd_arch_info; + /* Check that BFD reconizes this architecture */ + bfd_arch_info = bfd_lookup_arch (bfd_architecture, 0); + if (bfd_arch_info == NULL) + { + fatal ("Attempt to register unknown architecture (%d)", bfd_architecture); + } + /* Check that we haven't seen this architecture before */ + for (curr = &gdbarch_init_registrary; + (*curr) != NULL; + curr = &(*curr)->next) + { + if (bfd_architecture == (*curr)->bfd_architecture) + fatal ("Duplicate registraration of architecture (%s)", + bfd_arch_info->printable_name); + } + /* log it */ + if (gdbarch_debug) + fprintf_unfiltered (stderr, "register_gdbarch_init (%s, 0x%08lx)\n", + bfd_arch_info->printable_name, + (long) init); + /* Append it */ + (*curr) = XMALLOC (struct gdbarch_init_registration); + (*curr)->bfd_architecture = bfd_architecture; + (*curr)->init = init; + (*curr)->arches = NULL; + (*curr)->next = NULL; +} + + + +/* Look for an architecture using gdbarch_info. Base search on only + BFD_ARCH_INFO and BYTE_ORDER. */ + +struct gdbarch_list * +gdbarch_list_lookup_by_info (arches, info) + struct gdbarch_list *arches; + const struct gdbarch_info *info; +{ + for (; arches != NULL; arches = arches->next) + { + if (info->bfd_arch_info != arches->gdbarch->bfd_arch_info) + continue; + if (info->byte_order != arches->gdbarch->byte_order) + continue; + return arches; + } + return NULL; +} + + +/* Create a new ``struct gdbarch'' based in information provied by + ``struct gdbarch_info'' */ + +struct gdbarch * +gdbarch_alloc (info, tdep) + const struct gdbarch_info *info; + struct gdbarch_tdep *tdep; +{ + struct gdbarch *gdbarch = XMALLOC (struct gdbarch); + memset (gdbarch, 0, sizeof (*gdbarch)); + + gdbarch->tdep = tdep; + + gdbarch->bfd_arch_info = info->bfd_arch_info; + gdbarch->byte_order = info->byte_order; + + return gdbarch; +} + +/* Update the current architecture. Return ZERO if the update request + failed. */ + +int +gdbarch_update (info) + struct gdbarch_info info; +{ + struct gdbarch *new_gdbarch; + struct gdbarch_list **list; + struct gdbarch_init_registration *rego; + + /* Fill in any missing bits. Most important is the bfd_architecture + which is used to select the target architecture. */ + if (info.bfd_architecture == bfd_arch_unknown) + { + if (info.bfd_arch_info != NULL) + info.bfd_architecture = info.bfd_arch_info->arch; + else if (info.abfd != NULL) + info.bfd_architecture = bfd_get_arch (info.abfd); + /* FIXME - should query BFD for its default architecture. */ + else + info.bfd_architecture = current_gdbarch->bfd_arch_info->arch; + } + if (info.bfd_arch_info == NULL) + { + if (target_architecture_auto && info.abfd != NULL) + info.bfd_arch_info = bfd_get_arch_info (info.abfd); + else + info.bfd_arch_info = current_gdbarch->bfd_arch_info; + } + if (info.byte_order == 0) + { + if (target_byte_order_auto && info.abfd != NULL) + info.byte_order = (bfd_big_endian (info.abfd) ? BIG_ENDIAN + : bfd_little_endian (info.abfd) ? LITTLE_ENDIAN + : 0); + else + info.byte_order = current_gdbarch->byte_order; + } + /* A default for abfd? */ + + /* Find the target that knows about this architecture. */ + for (rego = gdbarch_init_registrary; + rego != NULL && rego->bfd_architecture != info.bfd_architecture; + rego = rego->next); + if (rego == NULL) + { + if (gdbarch_debug) + fprintf_unfiltered (stderr, "gdbarch_update: No matching architecture\n"); + return 0; + } + + /* Ask the target for a replacement architecture. */ + new_gdbarch = rego->init (&info, rego->arches); + + /* Did the target like it? No. Reject the change. */ + if (new_gdbarch == NULL) + { + if (gdbarch_debug) + fprintf_unfiltered (stderr, "gdbarch_update: Target rejected architecture\n"); + return 0; + } + + /* Did the architecture change? No. Do nothing. */ + if (current_gdbarch == new_gdbarch) + { + if (gdbarch_debug) + fprintf_unfiltered (stderr, "gdbarch_update: Architecture 0x%08lx (%s) unchanged\n", + (long) new_gdbarch, + new_gdbarch->bfd_arch_info->printable_name); + return 1; + } + + /* Swap all data belonging to the old target out */ + swapout_gdbarch_swap (current_gdbarch); + + /* Is this a pre-existing architecture? Yes. Swap it in. */ + for (list = ®o->arches; + (*list) != NULL; + list = &(*list)->next) + { + if ((*list)->gdbarch == new_gdbarch) + { + if (gdbarch_debug) + fprintf_unfiltered (stderr, "gdbarch_update: Previous architecture 0x%08lx (%s) selected\n", + (long) new_gdbarch, + new_gdbarch->bfd_arch_info->printable_name); + current_gdbarch = new_gdbarch; + swapin_gdbarch_swap (new_gdbarch); + return 1; + } + } + + /* Append this new architecture to this targets list. */ + (*list) = XMALLOC (struct gdbarch_list); + (*list)->next = NULL; + (*list)->gdbarch = new_gdbarch; + + /* Switch to this new architecture. Dump it out. */ + current_gdbarch = new_gdbarch; + if (gdbarch_debug) + { + fprintf_unfiltered (stderr, "gdbarch_update: New architecture 0x%08lx (%s) selected\n", + (long) new_gdbarch, + new_gdbarch->bfd_arch_info->printable_name); + fprintf_unfiltered (stderr, "TARGET_BYTE_ORDER = %d\n", TARGET_BYTE_ORDER); + fprintf_unfiltered (stderr, "TARGET_LONG_BIT = %d\n", TARGET_LONG_BIT); + fprintf_unfiltered (stderr, "TARGET_LONG_LONG_BIT = %d\n", TARGET_LONG_LONG_BIT); + fprintf_unfiltered (stderr, "TARGET_PTR_BIT = %d\n", TARGET_PTR_BIT); + } + + /* Check that the newly installed architecture is valid. */ + verify_gdbarch (new_gdbarch); + + /* Initialize the per-architecture memory (swap) areas. + CURRENT_GDBARCH must be update before these modules are + called. */ + init_gdbarch_swap (new_gdbarch); + + /* Initialize the per-architecture data-pointer of all parties that + registered an interest in this architecture. CURRENT_GDBARCH + must be updated before these modules are called. */ + init_gdbarch_data (new_gdbarch); + + return 1; +} + + +/* end-sanitize-carp end-sanitize-vr4xxx */ /* Functions to manipulate the endianness of the target. */ @@ -89,6 +615,15 @@ set_endian_big (args, from_tty) { target_byte_order = BIG_ENDIAN; target_byte_order_auto = 0; + /* start-sanitize-carp start-sanitize-vr4xxx */ + if (GDB_MULTI_ARCH) + { + struct gdbarch_info info; + memset (&info, 0, sizeof info); + info.byte_order = BIG_ENDIAN; + gdbarch_update (info); + } + /* end-sanitize-carp end-sanitize-vr4xxx */ } else { @@ -108,6 +643,15 @@ set_endian_little (args, from_tty) { target_byte_order = LITTLE_ENDIAN; target_byte_order_auto = 0; + /* start-sanitize-carp start-sanitize-vr4xxx */ + if (GDB_MULTI_ARCH) + { + struct gdbarch_info info; + memset (&info, 0, sizeof info); + info.byte_order = LITTLE_ENDIAN; + gdbarch_update (info); + } + /* end-sanitize-carp end-sanitize-vr4xxx */ } else { @@ -224,6 +768,24 @@ set_architecture (args, from_tty) { target_architecture_auto = 1; } + /* start-sanitize-carp start-sanitize-vr4xxx */ + else if (GDB_MULTI_ARCH) + { + const struct bfd_arch_info *arch = bfd_scan_arch (args); + if (arch == NULL) + printf_unfiltered ("Architecture `%s' not reconized.\n", args); + else + { + struct gdbarch_info info; + memset (&info, 0, sizeof info); + info.bfd_arch_info = arch; + if (gdbarch_update (info)) + target_architecture_auto = 0; + else + printf_unfiltered ("Architecture `%s' not reconized.\n", args); + } + } + /* end-sanitize-carp end-sanitize-vr4xxx */ else { const struct bfd_arch_info *arch = bfd_scan_arch (args); @@ -242,6 +804,38 @@ info_architecture (args, from_tty) int from_tty; { enum bfd_architecture a; + /* start-sanitize-carp start-sanitize-vr4xxx */ + if (GDB_MULTI_ARCH) + { + if (gdbarch_init_registrary != NULL) + { + struct gdbarch_init_registration *rego; + printf_filtered ("Available architectures are:\n"); + for (rego = gdbarch_init_registrary; + rego != NULL; + rego = rego->next) + { + const struct bfd_arch_info *ap; + ap = bfd_lookup_arch (rego->bfd_architecture, 0); + if (ap != NULL) + { + do + { + printf_filtered (" %s", ap->printable_name); + ap = ap->next; + } + while (ap != NULL); + printf_filtered ("\n"); + } + } + } + else + { + printf_filtered ("There are no available architectures.\n"); + } + return; + } + /* end-sanitize-carp end-sanitize-vr4xxx */ printf_filtered ("Available architectures are:\n"); for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++) { @@ -312,10 +906,41 @@ void set_gdbarch_from_file (abfd) bfd *abfd; { + /* start-sanitize-carp start-sanitize-vr4xxx */ + if (GDB_MULTI_ARCH) + { + struct gdbarch_info info; + memset (&info, 0, sizeof info); + info.abfd = abfd; + gdbarch_update (info); + return; + } + /* end-sanitize-carp end-sanitize-vr4xxx */ set_architecture_from_file (abfd); set_endian_from_file (abfd); } +/* start-sanitize-carp start-sanitize-vr4xxx */ + +/* The default architecture uses host values (for want of a better + choice). */ + +struct gdbarch default_gdbarch = { + /* basic architecture information */ + &bfd_default_arch_struct, + TARGET_BYTE_ORDER_DEFAULT, + /* target specific vector */ + NULL, + /*per-architecture data-pointers and swap regions */ + 0, NULL, NULL, + /* Multi-arch values */ + 8 * sizeof (long), /* long */ + 8 * sizeof (LONGEST), /* long long */ + 8 * sizeof (void*), /* ptr */ +}; +struct gdbarch *current_gdbarch = &default_gdbarch; + +/* end-sanitize-carp end-sanitize-vr4xxx */ extern void _initialize_gdbarch PARAMS ((void)); void diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 098db4c..a6a18be 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -20,6 +20,177 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef GDBARCH_H #define GDBARCH_H +/* start-sanitize-carp start-sanitize-vr4xxx */ + +#ifndef GDB_MULTI_ARCH +#define GDB_MULTI_ARCH 0 +#endif + +extern struct gdbarch *current_gdbarch; + + +/* When GDB_MULTI_ARCH override any earlier definitions of the + below. */ + +extern const struct bfd_arch_info *gdbarch_bfd_arch_info PARAMS ((struct gdbarch*)); +#if GDB_MULTI_ARCH +#undef TARGET_ARCHITECTURE +#define TARGET_ARCHITECTURE (gdbarch_bfd_arch_info (current_gdbarch)) +#endif + +extern int gdbarch_byte_order PARAMS ((struct gdbarch*)); +#if GDB_MULTI_ARCH +#undef TARGET_BYTE_ORDER +#define TARGET_BYTE_ORDER (gdbarch_byte_order (current_gdbarch)) +#endif + +extern int gdbarch_long_bit PARAMS ((struct gdbarch*)); +extern void set_gdbarch_long_bit PARAMS ((struct gdbarch*, int)); +#if GDB_MULTI_ARCH +#undef TARGET_LONG_BIT +#define TARGET_LONG_BIT (gdbarch_long_bit (current_gdbarch)) +#endif + +extern int gdbarch_long_long_bit PARAMS ((struct gdbarch*)); +extern void set_gdbarch_long_long_bit PARAMS ((struct gdbarch*, int)); +#if GDB_MULTI_ARCH +#undef TARGET_LONG_LONG_BIT +#define TARGET_LONG_LONG_BIT (gdbarch_long_long_bit (current_gdbarch)) +#endif + +extern int gdbarch_ptr_bit PARAMS ((struct gdbarch*)); +extern void set_gdbarch_ptr_bit PARAMS ((struct gdbarch*, int)); +#if GDB_MULTI_ARCH +#undef TARGET_PTR_BIT +#define TARGET_PTR_BIT (gdbarch_ptr_bit (current_gdbarch)) +#endif + +extern struct gdbarch_tdep *gdbarch_tdep PARAMS ((struct gdbarch*)); + + +/* Mechanism for co-ordinating the selection of a specific + architecture. + + GDB targets (*-tdep.c) can register an interest in a specific + architecture. Other GDB components can register a need to maintain + per-architecture data. + + The mechanisms below ensures that only a loose connection between + the set-architecture command and the various GDB components exists. + Each component can independantly register their need to maintain + architecture specific data with gdbarch. + + Pragmatics: + + Previously, a single TARGET_ARCHITECTURE_HOOK was provided. It + didn't scale. + + The more traditional mega-struct containing architecture specific + data for all the various GDB components was also considered. Since + GDB is built from a variable number of (fairly independant) + components this global aproach was considered non-applicable. */ + + +/* Register a new architectural family with GDB. + + Register support for the specified architecture with GDB. When + ever gdbarch determines that this architecture has been selected, + the specifed INIT function is called. + + INIT takes two parameters: INFO which contains the information + available to gdbarch about the (possibly new) architecture; ARCHES + which is a list of the previously created ``struct gdbarch'' for + this architecture. Fields within the structure INFO which have no + previous value are set to defaults: BFD_ARCHITECTURE - + bfd_arch_unknown; BFD_ARCH_INFO - NULL; BYTE_ORDER - 0; ABFD - + NULL; + + The INIT function shall return any of: NULL indicating that it + doesn't reconize the selected architecture; an existing ``struct + gdbarch'' from the ARCHES list (indicating that the new + architecture is just a synonym for an earlier architecture); create + and then return a new ``struct gdbarch'' for this new architecture + (using gdbarch_alloc()). */ + +struct gdbarch_list +{ + struct gdbarch *gdbarch; + struct gdbarch_list *next; +}; + +struct gdbarch_info +{ + enum bfd_architecture bfd_architecture; + const struct bfd_arch_info *bfd_arch_info; + int byte_order; + bfd *abfd; +}; + +typedef struct gdbarch *(gdbarch_init_ftype) PARAMS ((const struct gdbarch_info *info, struct gdbarch_list *arches)); + +extern void register_gdbarch_init PARAMS ((enum bfd_architecture, gdbarch_init_ftype *)); + +/* Helper function. Search ARCHES for a gdbarch that matches + information provided by INFO. */ + +extern struct gdbarch_list *gdbarch_list_lookup_by_info PARAMS ((struct gdbarch_list *arches, const struct gdbarch_info *info)); + +/* Helper function. Create a preliminary ``struct gdbarch''. Perform + basic initialization using values from the INFO structure. */ + +extern struct gdbarch *gdbarch_alloc PARAMS ((const struct gdbarch_info *, struct gdbarch_tdep *)); + +/* Helper function. Force the updating of the current architecture. + Used by targets that have added their own target specific + architecture manipulation commands. */ + +extern int gdbarch_update PARAMS ((struct gdbarch_info)); + + + +/* Register per-architecture data-pointer. + + Reserve space for a per-architecture data-pointer. An identifier + for the reserved data-pointer is returned. That identifer should + be saved in a local static. + + When a new architecture is selected, INIT() is called. When a + previous architecture is re-selected, the per-architecture + data-pointer for that previous architecture is restored (INIT() is + not called). + + INIT() shall return the initial value for the per-architecture + data-pointer for the current architecture. + + Multiple registrarants for any architecture are allowed (and + strongly encouraged). */ + +typedef void *(gdbarch_data_ftype) PARAMS ((void)); +extern struct gdbarch_data *register_gdbarch_data PARAMS ((gdbarch_data_ftype *init)); + + +/* Return the value of the per-architecture data-pointer for the + current architecture. */ + +extern void *gdbarch_data PARAMS ((struct gdbarch_data*)); + + +/* Register per-architecture memory region. + + For legacy code, provide a memory-region swap mechanism. + Per-architecture memory blocks are created, these being swapped + whenever the architecture is changed. For a new architecture, the + memory region is initialized with zero (0) and the INIT function is + called. + + Memory regions are swapped / initialized in the order that they are + registered. NULL DATA and/or INIT values can be specified. */ + +typedef void (gdbarch_swap_ftype) PARAMS ((void)); +extern void register_gdbarch_swap PARAMS ((void *data, unsigned long size, gdbarch_swap_ftype *init)); + + +/* end-sanitize-carp end-sanitize-vr4xxx */ /* The target-system-dependant byte order is dynamic */ -- 2.7.4