1117395Skan/* KeyMgr backwards-compatibility support for Darwin.
2169689Skan   Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
3117395Skan
4117395SkanThis file is part of GCC.
5117395Skan
6117395SkanGCC is free software; you can redistribute it and/or modify it under
7117395Skanthe terms of the GNU General Public License as published by the Free
8117395SkanSoftware Foundation; either version 2, or (at your option) any later
9117395Skanversion.
10117395Skan
11117395SkanIn addition to the permissions in the GNU General Public License, the
12117395SkanFree Software Foundation gives you unlimited permission to link the
13117395Skancompiled version of this file into combinations with other programs,
14117395Skanand to distribute those combinations without any restriction coming
15117395Skanfrom the use of this file.  (The General Public License restrictions
16117395Skando apply in other respects; for example, they cover modification of
17117395Skanthe file, and distribution when not linked into a combine
18117395Skanexecutable.)
19117395Skan
20117395SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
21117395SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
22117395SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
23117395Skanfor more details.
24117395Skan
25117395SkanYou should have received a copy of the GNU General Public License
26117395Skanalong with GCC; see the file COPYING.  If not, write to the Free
27169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
28169689Skan02110-1301, USA.  */
29117395Skan
30117395Skan/* It is incorrect to include config.h here, because this file is being
31117395Skan   compiled for the target, and hence definitions concerning only the host
32117395Skan   do not apply.  */
33117395Skan
34117395Skan#include "tconfig.h"
35117395Skan#include "tsystem.h"
36117395Skan
37169689Skan/* This file doesn't do anything useful on non-powerpc targets, since they
38169689Skan   don't have backwards compatibility anyway.  */
39169689Skan
40169689Skan#ifdef __ppc__
41169689Skan
42117395Skan/* Homemade decls substituting for getsect.h and dyld.h, so cross
43117395Skan   compilation works.  */
44117395Skanstruct mach_header;
45117395Skanextern char *getsectdatafromheader (struct mach_header *, const char *,
46117395Skan				    const char *, unsigned long *);
47117395Skanextern void _dyld_register_func_for_add_image
48117395Skan  (void (*) (struct mach_header *, unsigned long));
49117395Skanextern void _dyld_register_func_for_remove_image
50117395Skan  (void (*) (struct mach_header *, unsigned long));
51117395Skan
52117395Skanextern void __darwin_gcc3_preregister_frame_info (void);
53117395Skan
54117395Skan/* These are from "keymgr.h".  */
55117395Skanextern void _init_keymgr (void);
56117395Skanextern void *_keymgr_get_and_lock_processwide_ptr (unsigned key);
57117395Skanextern void _keymgr_set_and_unlock_processwide_ptr (unsigned key, void *ptr);
58117395Skan
59117395Skanextern void *__keymgr_global[];
60117395Skantypedef struct _Sinfo_Node {
61117395Skan        unsigned int size ;             /*size of this node*/
62117395Skan        unsigned short major_version ;  /*API major version.*/
63117395Skan        unsigned short minor_version ;  /*API minor version.*/
64117395Skan        } _Tinfo_Node ;
65117395Skan
66117395Skan/* KeyMgr 3.x is the first one supporting GCC3 stuff natively.  */
67117395Skan#define KEYMGR_API_MAJOR_GCC3           3
68117395Skan/* ... with these keys.  */
69117395Skan#define KEYMGR_GCC3_LIVE_IMAGE_LIST	301     /* loaded images  */
70117395Skan#define KEYMGR_GCC3_DW2_OBJ_LIST	302     /* Dwarf2 object list  */
71117395Skan
72117395Skan/* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST.  Info about each resident image.  */
73117395Skanstruct live_images {
74117395Skan  unsigned long this_size;                      /* sizeof (live_images)  */
75117395Skan  struct mach_header *mh;                       /* the image info  */
76117395Skan  unsigned long vm_slide;
77117395Skan  void (*destructor)(struct live_images *);     /* destructor for this  */
78117395Skan  struct live_images *next;
79117395Skan  unsigned int examined_p;
80117395Skan  void *fde;
81117395Skan  void *object_info;
82117395Skan  unsigned long info[2];                        /* Future use.  */
83117395Skan};
84117395Skan
85117395Skan
86117395Skan/* These routines are used only on Darwin versions before 10.2.
87117395Skan   Later versions have equivalent code in the system.
88117395Skan   Eventually, they might go away, although it might be a long time...  */
89117395Skan
90117395Skanstatic void darwin_unwind_dyld_remove_image_hook
91117395Skan  (struct mach_header *m, unsigned long s);
92117395Skanstatic void darwin_unwind_dyld_remove_image_hook
93117395Skan  (struct mach_header *m, unsigned long s);
94117395Skanextern void __darwin_gcc3_preregister_frame_info (void);
95117395Skan
96117395Skanstatic void
97117395Skandarwin_unwind_dyld_add_image_hook (struct mach_header *mh, unsigned long slide)
98117395Skan{
99117395Skan  struct live_images *l = (struct live_images *)calloc (1, sizeof (*l));
100117395Skan  l->mh = mh;
101117395Skan  l->vm_slide = slide;
102117395Skan  l->this_size = sizeof (*l);
103117395Skan  l->next = (struct live_images *)
104117395Skan	_keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
105117395Skan  _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST, l);
106117395Skan}
107117395Skan
108117395Skanstatic void
109117395Skandarwin_unwind_dyld_remove_image_hook (struct mach_header *m, unsigned long s)
110117395Skan{
111117395Skan  struct live_images *top, **lip, *destroy = NULL;
112117395Skan
113117395Skan  /* Look for it in the list of live images and delete it.  */
114117395Skan
115117395Skan  top = (struct live_images *)
116117395Skan	   _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
117117395Skan  for (lip = ⊤ *lip != NULL; lip = &(*lip)->next)
118117395Skan    {
119117395Skan      if ((*lip)->mh == m && (*lip)->vm_slide == s)
120117395Skan        {
121117395Skan          destroy = *lip;
122117395Skan          *lip = destroy->next;			/* unlink DESTROY  */
123117395Skan
124117395Skan          if (destroy->this_size != sizeof (*destroy))	/* sanity check  */
125117395Skan            abort ();
126117395Skan
127117395Skan          break;
128117395Skan        }
129117395Skan    }
130117395Skan  _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST, top);
131117395Skan
132117395Skan  /* Now that we have unlinked this from the image list, toss it.  */
133117395Skan  if (destroy != NULL)
134117395Skan    {
135117395Skan      if (destroy->destructor != NULL)
136117395Skan	(*destroy->destructor) (destroy);
137117395Skan      free (destroy);
138117395Skan    }
139117395Skan}
140117395Skan
141117395Skanvoid
142117395Skan__darwin_gcc3_preregister_frame_info (void)
143117395Skan{
144117395Skan  const _Tinfo_Node *info;
145117395Skan  _init_keymgr ();
146117395Skan  info = (_Tinfo_Node *)__keymgr_global[2];
147117395Skan  if (info != NULL)
148117395Skan    {
149117395Skan      if (info->major_version >= KEYMGR_API_MAJOR_GCC3)
150117395Skan	return;
151117395Skan      /* Otherwise, use our own add_image_hooks.  */
152117395Skan    }
153117395Skan
154117395Skan  _dyld_register_func_for_add_image (darwin_unwind_dyld_add_image_hook);
155117395Skan  _dyld_register_func_for_remove_image (darwin_unwind_dyld_remove_image_hook);
156117395Skan}
157169689Skan
158169689Skan#endif  /* __ppc__ */
159