172445Sassar/* KeyMgr backwards-compatibility support for Darwin.
2233294Sstas   Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
3233294Sstas
4233294SstasThis file is part of GCC.
572445Sassar
6233294SstasGCC is free software; you can redistribute it and/or modify it under
7233294Sstasthe terms of the GNU General Public License as published by the Free
8233294SstasSoftware Foundation; either version 2, or (at your option) any later
972445Sassarversion.
10233294Sstas
11233294SstasIn addition to the permissions in the GNU General Public License, the
1272445SassarFree Software Foundation gives you unlimited permission to link the
13233294Sstascompiled version of this file into combinations with other programs,
14233294Sstasand to distribute those combinations without any restriction coming
15233294Sstasfrom the use of this file.  (The General Public License restrictions
1672445Sassardo apply in other respects; for example, they cover modification of
17233294Sstasthe file, and distribution when not linked into a combine
18233294Sstasexecutable.)
19233294Sstas
2072445SassarGCC is distributed in the hope that it will be useful, but WITHOUT ANY
21233294SstasWARRANTY; without even the implied warranty of MERCHANTABILITY or
22233294SstasFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
23233294Sstasfor more details.
24233294Sstas
25233294SstasYou should have received a copy of the GNU General Public License
26233294Sstasalong with GCC; see the file COPYING.  If not, write to the Free
27233294SstasSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
28233294Sstas02110-1301, USA.  */
29233294Sstas
30233294Sstas/* It is incorrect to include config.h here, because this file is being
31233294Sstas   compiled for the target, and hence definitions concerning only the host
3272445Sassar   do not apply.  */
3372445Sassar
3472445Sassar#include "tconfig.h"
3572445Sassar#include "tsystem.h"
3672445Sassar
3772445Sassar/* This file doesn't do anything useful on non-powerpc targets, since they
3872445Sassar   don't have backwards compatibility anyway.  */
3972445Sassar
4090926Snectar#ifdef __ppc__
4190926Snectar
4272445Sassar/* Homemade decls substituting for getsect.h and dyld.h, so cross
4372445Sassar   compilation works.  */
4472445Sassarstruct mach_header;
4572445Sassarextern char *getsectdatafromheader (struct mach_header *, const char *,
4672445Sassar				    const char *, unsigned long *);
4772445Sassarextern void _dyld_register_func_for_add_image
4872445Sassar  (void (*) (struct mach_header *, unsigned long));
4990926Snectarextern void _dyld_register_func_for_remove_image
5072445Sassar  (void (*) (struct mach_header *, unsigned long));
5172445Sassar
5272445Sassarextern void __darwin_gcc3_preregister_frame_info (void);
5372445Sassar
5472445Sassar/* These are from "keymgr.h".  */
5572445Sassarextern void _init_keymgr (void);
5690926Snectarextern void *_keymgr_get_and_lock_processwide_ptr (unsigned key);
5790926Snectarextern void _keymgr_set_and_unlock_processwide_ptr (unsigned key, void *ptr);
58178825Sdfr
5972445Sassarextern void *__keymgr_global[];
6090926Snectartypedef struct _Sinfo_Node {
6172445Sassar        unsigned int size ;             /*size of this node*/
6272445Sassar        unsigned short major_version ;  /*API major version.*/
6390926Snectar        unsigned short minor_version ;  /*API minor version.*/
6490926Snectar        } _Tinfo_Node ;
6590926Snectar
6690926Snectar/* KeyMgr 3.x is the first one supporting GCC3 stuff natively.  */
6790926Snectar#define KEYMGR_API_MAJOR_GCC3           3
6890926Snectar/* ... with these keys.  */
6990926Snectar#define KEYMGR_GCC3_LIVE_IMAGE_LIST	301     /* loaded images  */
7090926Snectar#define KEYMGR_GCC3_DW2_OBJ_LIST	302     /* Dwarf2 object list  */
7172445Sassar
72178825Sdfr/* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST.  Info about each resident image.  */
73178825Sdfrstruct live_images {
7472445Sassar  unsigned long this_size;                      /* sizeof (live_images)  */
75233294Sstas  struct mach_header *mh;                       /* the image info  */
7672445Sassar  unsigned long vm_slide;
7772445Sassar  void (*destructor)(struct live_images *);     /* destructor for this  */
7872445Sassar  struct live_images *next;
7972445Sassar  unsigned int examined_p;
8072445Sassar  void *fde;
8172445Sassar  void *object_info;
8272445Sassar  unsigned long info[2];                        /* Future use.  */
8372445Sassar};
8472445Sassar
8572445Sassar
8672445Sassar/* These routines are used only on Darwin versions before 10.2.
8772445Sassar   Later versions have equivalent code in the system.
8872445Sassar   Eventually, they might go away, although it might be a long time...  */
8972445Sassar
9072445Sassarstatic void darwin_unwind_dyld_remove_image_hook
9172445Sassar  (struct mach_header *m, unsigned long s);
9272445Sassarstatic void darwin_unwind_dyld_remove_image_hook
9372445Sassar  (struct mach_header *m, unsigned long s);
9472445Sassarextern void __darwin_gcc3_preregister_frame_info (void);
9572445Sassar
9672445Sassarstatic void
9772445Sassardarwin_unwind_dyld_add_image_hook (struct mach_header *mh, unsigned long slide)
9872445Sassar{
9972445Sassar  struct live_images *l = (struct live_images *)calloc (1, sizeof (*l));
10072445Sassar  l->mh = mh;
10172445Sassar  l->vm_slide = slide;
10272445Sassar  l->this_size = sizeof (*l);
10372445Sassar  l->next = (struct live_images *)
10472445Sassar	_keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
10572445Sassar  _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST, l);
10672445Sassar}
10772445Sassar
10872445Sassarstatic void
10990926Snectardarwin_unwind_dyld_remove_image_hook (struct mach_header *m, unsigned long s)
11072445Sassar{
11172445Sassar  struct live_images *top, **lip, *destroy = NULL;
11272445Sassar
11372445Sassar  /* Look for it in the list of live images and delete it.  */
11472445Sassar
11572445Sassar  top = (struct live_images *)
11672445Sassar	   _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
11772445Sassar  for (lip = ⊤ *lip != NULL; lip = &(*lip)->next)
11872445Sassar    {
11972445Sassar      if ((*lip)->mh == m && (*lip)->vm_slide == s)
12072445Sassar        {
121233294Sstas          destroy = *lip;
12272445Sassar          *lip = destroy->next;			/* unlink DESTROY  */
12372445Sassar
12472445Sassar          if (destroy->this_size != sizeof (*destroy))	/* sanity check  */
125233294Sstas            abort ();
12672445Sassar
12772445Sassar          break;
12872445Sassar        }
12972445Sassar    }
13090926Snectar  _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST, top);
131233294Sstas
13272445Sassar  /* Now that we have unlinked this from the image list, toss it.  */
13372445Sassar  if (destroy != NULL)
13472445Sassar    {
13572445Sassar      if (destroy->destructor != NULL)
13672445Sassar	(*destroy->destructor) (destroy);
13772445Sassar      free (destroy);
13872445Sassar    }
13972445Sassar}
14072445Sassar
14172445Sassarvoid
14272445Sassar__darwin_gcc3_preregister_frame_info (void)
14372445Sassar{
14472445Sassar  const _Tinfo_Node *info;
14572445Sassar  _init_keymgr ();
14672445Sassar  info = (_Tinfo_Node *)__keymgr_global[2];
14772445Sassar  if (info != NULL)
14872445Sassar    {
14972445Sassar      if (info->major_version >= KEYMGR_API_MAJOR_GCC3)
15072445Sassar	return;
15172445Sassar      /* Otherwise, use our own add_image_hooks.  */
15290926Snectar    }
15372445Sassar
15472445Sassar  _dyld_register_func_for_add_image (darwin_unwind_dyld_add_image_hook);
15572445Sassar  _dyld_register_func_for_remove_image (darwin_unwind_dyld_remove_image_hook);
15672445Sassar}
15772445Sassar
15872445Sassar#endif  /* __ppc__ */
159178825Sdfr