Add multi-arch code!
This commit is contained in:
Andrew Cagney 1998-12-16 15:01:03 +00:00
parent e81bad50a8
commit dcf46491d8
3 changed files with 835 additions and 1 deletions

View File

@ -1,3 +1,41 @@
start-sanitize-carp start-sanitize-vr4xxx
Thu Dec 17 01:58:16 1998 Andrew Cagney <cagney@chook>
* 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 <cagney@chook> Thu Dec 17 01:34:36 1998 Andrew Cagney <cagney@chook>
* gdbtypes.c (build_gdbtypes): New function. * gdbtypes.c (build_gdbtypes): New function.

View File

@ -22,13 +22,539 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "gdbcmd.h" #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. */ /* Non-zero if we want to trace architecture code. */
#ifndef GDBARCH_DEBUG #ifndef GDBARCH_DEBUG
#define GDBARCH_DEBUG 1 #define GDBARCH_DEBUG 0
#endif #endif
int gdbarch_debug = GDBARCH_DEBUG; 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 = &rego->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. */ /* 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 = BIG_ENDIAN;
target_byte_order_auto = 0; 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 else
{ {
@ -108,6 +643,15 @@ set_endian_little (args, from_tty)
{ {
target_byte_order = LITTLE_ENDIAN; target_byte_order = LITTLE_ENDIAN;
target_byte_order_auto = 0; 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 else
{ {
@ -224,6 +768,24 @@ set_architecture (args, from_tty)
{ {
target_architecture_auto = 1; 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 else
{ {
const struct bfd_arch_info *arch = bfd_scan_arch (args); const struct bfd_arch_info *arch = bfd_scan_arch (args);
@ -242,6 +804,38 @@ info_architecture (args, from_tty)
int from_tty; int from_tty;
{ {
enum bfd_architecture a; 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"); printf_filtered ("Available architectures are:\n");
for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++) for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
{ {
@ -312,10 +906,41 @@ void
set_gdbarch_from_file (abfd) set_gdbarch_from_file (abfd)
bfd *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_architecture_from_file (abfd);
set_endian_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)); extern void _initialize_gdbarch PARAMS ((void));
void void

View File

@ -20,6 +20,177 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef GDBARCH_H #ifndef GDBARCH_H
#define 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 */ /* The target-system-dependant byte order is dynamic */