diff options
Diffstat (limited to 'contrib/gcc/config/darwin-crt2.c')
-rw-r--r-- | contrib/gcc/config/darwin-crt2.c | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/contrib/gcc/config/darwin-crt2.c b/contrib/gcc/config/darwin-crt2.c new file mode 100644 index 0000000..1ea2413 --- /dev/null +++ b/contrib/gcc/config/darwin-crt2.c @@ -0,0 +1,151 @@ +/* KeyMgr backwards-compatibility support for Darwin. + Copyright (C) 2001, 2002 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ + +/* It is incorrect to include config.h here, because this file is being + compiled for the target, and hence definitions concerning only the host + do not apply. */ + +#include "tconfig.h" +#include "tsystem.h" + +/* Homemade decls substituting for getsect.h and dyld.h, so cross + compilation works. */ +struct mach_header; +extern char *getsectdatafromheader (struct mach_header *, const char *, + const char *, unsigned long *); +extern void _dyld_register_func_for_add_image + (void (*) (struct mach_header *, unsigned long)); +extern void _dyld_register_func_for_remove_image + (void (*) (struct mach_header *, unsigned long)); + +extern void __darwin_gcc3_preregister_frame_info (void); + +/* These are from "keymgr.h". */ +extern void _init_keymgr (void); +extern void *_keymgr_get_and_lock_processwide_ptr (unsigned key); +extern void _keymgr_set_and_unlock_processwide_ptr (unsigned key, void *ptr); + +extern void *__keymgr_global[]; +typedef struct _Sinfo_Node { + unsigned int size ; /*size of this node*/ + unsigned short major_version ; /*API major version.*/ + unsigned short minor_version ; /*API minor version.*/ + } _Tinfo_Node ; + +/* KeyMgr 3.x is the first one supporting GCC3 stuff natively. */ +#define KEYMGR_API_MAJOR_GCC3 3 +/* ... with these keys. */ +#define KEYMGR_GCC3_LIVE_IMAGE_LIST 301 /* loaded images */ +#define KEYMGR_GCC3_DW2_OBJ_LIST 302 /* Dwarf2 object list */ + +/* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST. Info about each resident image. */ +struct live_images { + unsigned long this_size; /* sizeof (live_images) */ + struct mach_header *mh; /* the image info */ + unsigned long vm_slide; + void (*destructor)(struct live_images *); /* destructor for this */ + struct live_images *next; + unsigned int examined_p; + void *fde; + void *object_info; + unsigned long info[2]; /* Future use. */ +}; + + +/* These routines are used only on Darwin versions before 10.2. + Later versions have equivalent code in the system. + Eventually, they might go away, although it might be a long time... */ + +static void darwin_unwind_dyld_remove_image_hook + (struct mach_header *m, unsigned long s); +static void darwin_unwind_dyld_remove_image_hook + (struct mach_header *m, unsigned long s); +extern void __darwin_gcc3_preregister_frame_info (void); + +static void +darwin_unwind_dyld_add_image_hook (struct mach_header *mh, unsigned long slide) +{ + struct live_images *l = (struct live_images *)calloc (1, sizeof (*l)); + l->mh = mh; + l->vm_slide = slide; + l->this_size = sizeof (*l); + l->next = (struct live_images *) + _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST); + _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST, l); +} + +static void +darwin_unwind_dyld_remove_image_hook (struct mach_header *m, unsigned long s) +{ + struct live_images *top, **lip, *destroy = NULL; + + /* Look for it in the list of live images and delete it. */ + + top = (struct live_images *) + _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST); + for (lip = ⊤ *lip != NULL; lip = &(*lip)->next) + { + if ((*lip)->mh == m && (*lip)->vm_slide == s) + { + destroy = *lip; + *lip = destroy->next; /* unlink DESTROY */ + + if (destroy->this_size != sizeof (*destroy)) /* sanity check */ + abort (); + + break; + } + } + _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST, top); + + /* Now that we have unlinked this from the image list, toss it. */ + if (destroy != NULL) + { + if (destroy->destructor != NULL) + (*destroy->destructor) (destroy); + free (destroy); + } +} + +void +__darwin_gcc3_preregister_frame_info (void) +{ + const _Tinfo_Node *info; + _init_keymgr (); + info = (_Tinfo_Node *)__keymgr_global[2]; + if (info != NULL) + { + if (info->major_version >= KEYMGR_API_MAJOR_GCC3) + return; + /* Otherwise, use our own add_image_hooks. */ + } + + _dyld_register_func_for_add_image (darwin_unwind_dyld_add_image_hook); + _dyld_register_func_for_remove_image (darwin_unwind_dyld_remove_image_hook); +} |