163d1a8abSmrg /* KeyMgr backwards-compatibility support for Darwin.
2*ec02198aSmrg    Copyright (C) 2001-2020 Free Software Foundation, Inc.
363d1a8abSmrg 
463d1a8abSmrg This file is part of GCC.
563d1a8abSmrg 
663d1a8abSmrg GCC is free software; you can redistribute it and/or modify it under
763d1a8abSmrg the terms of the GNU General Public License as published by the Free
863d1a8abSmrg Software Foundation; either version 3, or (at your option) any later
963d1a8abSmrg version.
1063d1a8abSmrg 
1163d1a8abSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1263d1a8abSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
1363d1a8abSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1463d1a8abSmrg for more details.
1563d1a8abSmrg 
1663d1a8abSmrg Under Section 7 of GPL version 3, you are granted additional
1763d1a8abSmrg permissions described in the GCC Runtime Library Exception, version
1863d1a8abSmrg 3.1, as published by the Free Software Foundation.
1963d1a8abSmrg 
2063d1a8abSmrg You should have received a copy of the GNU General Public License and
2163d1a8abSmrg a copy of the GCC Runtime Library Exception along with this program;
2263d1a8abSmrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2363d1a8abSmrg <http://www.gnu.org/licenses/>.  */
2463d1a8abSmrg 
2563d1a8abSmrg /* It is incorrect to include config.h here, because this file is being
2663d1a8abSmrg    compiled for the target, and hence definitions concerning only the host
2763d1a8abSmrg    do not apply.  */
2863d1a8abSmrg 
2963d1a8abSmrg #include "tconfig.h"
3063d1a8abSmrg #include "tsystem.h"
3163d1a8abSmrg 
3263d1a8abSmrg /* This file doesn't do anything useful on non-powerpc targets, since they
3363d1a8abSmrg    don't have backwards compatibility anyway.  */
3463d1a8abSmrg 
3563d1a8abSmrg #ifdef __ppc__
3663d1a8abSmrg 
3763d1a8abSmrg /* Homemade decls substituting for getsect.h and dyld.h, so cross
3863d1a8abSmrg    compilation works.  */
3963d1a8abSmrg struct mach_header;
4063d1a8abSmrg extern char *getsectdatafromheader (struct mach_header *, const char *,
4163d1a8abSmrg 				    const char *, unsigned long *);
4263d1a8abSmrg extern void _dyld_register_func_for_add_image
4363d1a8abSmrg   (void (*) (struct mach_header *, unsigned long));
4463d1a8abSmrg extern void _dyld_register_func_for_remove_image
4563d1a8abSmrg   (void (*) (struct mach_header *, unsigned long));
4663d1a8abSmrg 
4763d1a8abSmrg extern void __darwin_gcc3_preregister_frame_info (void);
4863d1a8abSmrg 
4963d1a8abSmrg /* These are from "keymgr.h".  */
5063d1a8abSmrg extern void _init_keymgr (void);
5163d1a8abSmrg extern void *_keymgr_get_and_lock_processwide_ptr (unsigned key);
5263d1a8abSmrg extern void _keymgr_set_and_unlock_processwide_ptr (unsigned key, void *ptr);
5363d1a8abSmrg 
5463d1a8abSmrg extern void *__keymgr_global[];
5563d1a8abSmrg typedef struct _Sinfo_Node {
5663d1a8abSmrg         unsigned int size ;             /*size of this node*/
5763d1a8abSmrg         unsigned short major_version ;  /*API major version.*/
5863d1a8abSmrg         unsigned short minor_version ;  /*API minor version.*/
5963d1a8abSmrg         } _Tinfo_Node ;
6063d1a8abSmrg 
6163d1a8abSmrg /* KeyMgr 3.x is the first one supporting GCC3 stuff natively.  */
6263d1a8abSmrg #define KEYMGR_API_MAJOR_GCC3           3
6363d1a8abSmrg /* ... with these keys.  */
6463d1a8abSmrg #define KEYMGR_GCC3_LIVE_IMAGE_LIST	301     /* loaded images  */
6563d1a8abSmrg #define KEYMGR_GCC3_DW2_OBJ_LIST	302     /* Dwarf2 object list  */
6663d1a8abSmrg 
6763d1a8abSmrg /* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST.  Info about each resident image.  */
6863d1a8abSmrg struct live_images {
6963d1a8abSmrg   unsigned long this_size;                      /* sizeof (live_images)  */
7063d1a8abSmrg   struct mach_header *mh;                       /* the image info  */
7163d1a8abSmrg   unsigned long vm_slide;
7263d1a8abSmrg   void (*destructor)(struct live_images *);     /* destructor for this  */
7363d1a8abSmrg   struct live_images *next;
7463d1a8abSmrg   unsigned int examined_p;
7563d1a8abSmrg   void *fde;
7663d1a8abSmrg   void *object_info;
7763d1a8abSmrg   unsigned long info[2];                        /* Future use.  */
7863d1a8abSmrg };
7963d1a8abSmrg 
8063d1a8abSmrg 
8163d1a8abSmrg /* These routines are used only on Darwin versions before 10.2.
8263d1a8abSmrg    Later versions have equivalent code in the system.
8363d1a8abSmrg    Eventually, they might go away, although it might be a long time...  */
8463d1a8abSmrg 
8563d1a8abSmrg static void darwin_unwind_dyld_remove_image_hook
8663d1a8abSmrg   (struct mach_header *m, unsigned long s);
8763d1a8abSmrg static void darwin_unwind_dyld_remove_image_hook
8863d1a8abSmrg   (struct mach_header *m, unsigned long s);
8963d1a8abSmrg extern void __darwin_gcc3_preregister_frame_info (void);
9063d1a8abSmrg 
9163d1a8abSmrg static void
darwin_unwind_dyld_add_image_hook(struct mach_header * mh,unsigned long slide)9263d1a8abSmrg darwin_unwind_dyld_add_image_hook (struct mach_header *mh, unsigned long slide)
9363d1a8abSmrg {
9463d1a8abSmrg   struct live_images *l = (struct live_images *)calloc (1, sizeof (*l));
9563d1a8abSmrg   l->mh = mh;
9663d1a8abSmrg   l->vm_slide = slide;
9763d1a8abSmrg   l->this_size = sizeof (*l);
9863d1a8abSmrg   l->next = (struct live_images *)
9963d1a8abSmrg 	_keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
10063d1a8abSmrg   _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST, l);
10163d1a8abSmrg }
10263d1a8abSmrg 
10363d1a8abSmrg static void
darwin_unwind_dyld_remove_image_hook(struct mach_header * m,unsigned long s)10463d1a8abSmrg darwin_unwind_dyld_remove_image_hook (struct mach_header *m, unsigned long s)
10563d1a8abSmrg {
10663d1a8abSmrg   struct live_images *top, **lip, *destroy = NULL;
10763d1a8abSmrg 
10863d1a8abSmrg   /* Look for it in the list of live images and delete it.  */
10963d1a8abSmrg 
11063d1a8abSmrg   top = (struct live_images *)
11163d1a8abSmrg 	   _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
11263d1a8abSmrg   for (lip = &top; *lip != NULL; lip = &(*lip)->next)
11363d1a8abSmrg     {
11463d1a8abSmrg       if ((*lip)->mh == m && (*lip)->vm_slide == s)
11563d1a8abSmrg         {
11663d1a8abSmrg           destroy = *lip;
11763d1a8abSmrg           *lip = destroy->next;			/* unlink DESTROY  */
11863d1a8abSmrg 
11963d1a8abSmrg           if (destroy->this_size != sizeof (*destroy))	/* sanity check  */
12063d1a8abSmrg             abort ();
12163d1a8abSmrg 
12263d1a8abSmrg           break;
12363d1a8abSmrg         }
12463d1a8abSmrg     }
12563d1a8abSmrg   _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST, top);
12663d1a8abSmrg 
12763d1a8abSmrg   /* Now that we have unlinked this from the image list, toss it.  */
12863d1a8abSmrg   if (destroy != NULL)
12963d1a8abSmrg     {
13063d1a8abSmrg       if (destroy->destructor != NULL)
13163d1a8abSmrg 	(*destroy->destructor) (destroy);
13263d1a8abSmrg       free (destroy);
13363d1a8abSmrg     }
13463d1a8abSmrg }
13563d1a8abSmrg 
13663d1a8abSmrg void
__darwin_gcc3_preregister_frame_info(void)13763d1a8abSmrg __darwin_gcc3_preregister_frame_info (void)
13863d1a8abSmrg {
13963d1a8abSmrg   const _Tinfo_Node *info;
14063d1a8abSmrg   _init_keymgr ();
14163d1a8abSmrg   info = (_Tinfo_Node *)__keymgr_global[2];
14263d1a8abSmrg   if (info != NULL)
14363d1a8abSmrg     {
14463d1a8abSmrg       if (info->major_version >= KEYMGR_API_MAJOR_GCC3)
14563d1a8abSmrg 	return;
14663d1a8abSmrg       /* Otherwise, use our own add_image_hooks.  */
14763d1a8abSmrg     }
14863d1a8abSmrg 
14963d1a8abSmrg   _dyld_register_func_for_add_image (darwin_unwind_dyld_add_image_hook);
15063d1a8abSmrg   _dyld_register_func_for_remove_image (darwin_unwind_dyld_remove_image_hook);
15163d1a8abSmrg }
15263d1a8abSmrg 
15363d1a8abSmrg #endif  /* __ppc__ */
154