unwind-dw2-fde-darwin.c revision 132718
143045Sdillon/* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. 243045Sdillon 3132935Simp This file is part of GCC. 443045Sdillon 543045Sdillon GCC is free software; you can redistribute it and/or modify 6132935Simp it under the terms of the GNU General Public License as published by 7132935Simp the Free Software Foundation; either version 2, or (at your option) 8132935Simp any later version. 9132935Simp 10132935Simp GCC is distributed in the hope that it will be useful, 11132935Simp but WITHOUT ANY WARRANTY; without even the implied warranty of 12132935Simp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13132935Simp GNU General Public License for more details. 14132935Simp 15132935Simp You should have received a copy of the GNU General Public License 16132935Simp along with GCC; see the file COPYING. If not, write to 17132935Simp the Free Software Foundation, 59 Temple Place - Suite 330, 18132935Simp Boston, MA 02111-1307, USA. */ 19132935Simp 20132935Simp/* As a special exception, if you link this library with other files, 21132935Simp some of which are compiled with GCC, to produce an executable, 22132935Simp this library does not by itself cause the resulting executable 23132935Simp to be covered by the GNU General Public License. 24132935Simp This exception does not however invalidate any other reasons why 2543045Sdillon the executable file might be covered by the GNU General Public License. */ 2643045Sdillon 2783551Sdillon/* Locate the FDE entry for a given address, using Darwin's keymgr support. */ 2883551Sdillon 2943045Sdillon#include "tconfig.h" 3043045Sdillon#include <string.h> 3143045Sdillon#include <stdlib.h> 3243045Sdillon#include "dwarf2.h" 3343045Sdillon#include "unwind.h" 3472950Srwatson#define NO_BASE_OF_ENCODED_VALUE 3543045Sdillon#define DWARF2_OBJECT_END_PTR_EXTENSION 36166550Sjhb#include "unwind-pe.h" 3777605Stmm#include "unwind-dw2-fde.h" 3877605Stmm/* Carefully don't include gthr.h. */ 3943045Sdillon 4077605Stmmtypedef int __gthread_mutex_t; 4143045Sdillon#define __gthread_mutex_lock(x) (void)(x) 4243045Sdillon#define __gthread_mutex_unlock(x) (void)(x) 4343045Sdillon 4469793Sobrienstatic const fde * _Unwind_Find_registered_FDE (void *pc, 4543045Sdillon struct dwarf_eh_bases *bases); 4643045Sdillon 4743045Sdillon#define _Unwind_Find_FDE _Unwind_Find_registered_FDE 4843045Sdillon#include "unwind-dw2-fde.c" 4972950Srwatson#undef _Unwind_Find_FDE 5043045Sdillon 5172950Srwatson/* KeyMgr stuff. */ 5272950Srwatson#define KEYMGR_GCC3_LIVE_IMAGE_LIST 301 /* loaded images */ 53166550Sjhb#define KEYMGR_GCC3_DW2_OBJ_LIST 302 /* Dwarf2 object list */ 54217744Suqs 55217744Suqsextern void *_keymgr_get_and_lock_processwide_ptr (int); 56217744Suqsextern void _keymgr_set_and_unlock_processwide_ptr (int, void *); 57166550Sjhbextern void _keymgr_unlock_processwide_ptr (int); 5843045Sdillon 59166550Sjhbstruct mach_header; 60166550Sjhbextern char *getsectdatafromheader (struct mach_header*, const char*, 61166550Sjhb const char *, unsigned long *); 6243045Sdillon 6372950Srwatson/* This is referenced from KEYMGR_GCC3_DW2_OBJ_LIST. */ 6443045Sdillonstruct km_object_info { 6543045Sdillon struct object *seen_objects; 66166550Sjhb struct object *unseen_objects; 6772950Srwatson unsigned spare[2]; 68166550Sjhb}; 69217744Suqs 7043045Sdillon/* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST. Info about each resident image. */ 71166550Sjhbstruct live_images { 72166550Sjhb unsigned long this_size; /* sizeof (live_images) */ 73166550Sjhb struct mach_header *mh; /* the image info */ 74166550Sjhb unsigned long vm_slide; 75166550Sjhb void (*destructor)(struct live_images *); /* destructor for this */ 76166550Sjhb struct live_images *next; 77166550Sjhb unsigned int examined_p; 78166550Sjhb void *fde; 79166550Sjhb void *object_info; 80166550Sjhb unsigned long info[2]; /* Future use. */ 8177605Stmm}; 8277605Stmm 8377605Stmm/* Bits in the examined_p field of struct live_images. */ 8477605Stmmenum { 8577605Stmm EXAMINED_IMAGE_MASK = 1, /* We've seen this one. */ 8677605Stmm ALLOCED_IMAGE_MASK = 2, /* The FDE entries were allocated by 8777605Stmm malloc, and must be freed. This isn't 8877605Stmm used by newer libgcc versions. */ 8977605Stmm IMAGE_IS_TEXT_MASK = 4, /* This image is in the TEXT segment. */ 9072950Srwatson DESTRUCTOR_MAY_BE_CALLED_LIVE = 8 /* The destructor may be called on an 9172950Srwatson object that's part of the live 9243045Sdillon image list. */ 93217744Suqs}; 94217744Suqs 9543045Sdillon/* Delete any data we allocated on a live_images structure. Either 9643045Sdillon IMAGE has already been removed from the 9743045Sdillon KEYMGR_GCC3_LIVE_IMAGE_LIST and the struct will be deleted 9843045Sdillon after we return, or that list is locked and we're being called 9943045Sdillon because this object might be about to be unloaded. Called by 10043045Sdillon KeyMgr. */ 10143045Sdillon 10243045Sdillonstatic void 10343045Sdillonlive_image_destructor (struct live_images *image) 10472950Srwatson{ 10572950Srwatson if (image->object_info) 10672950Srwatson { 107166550Sjhb struct km_object_info *the_obj_info; 10872950Srwatson 10972950Srwatson the_obj_info = 11043045Sdillon _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST); 111166550Sjhb if (the_obj_info) 112217744Suqs { 113217744Suqs seen_objects = the_obj_info->seen_objects; 114217744Suqs unseen_objects = the_obj_info->unseen_objects; 115166550Sjhb 116166550Sjhb /* Free any sorted arrays. */ 117166550Sjhb __deregister_frame_info_bases (image->fde); 118166550Sjhb 119166550Sjhb the_obj_info->seen_objects = seen_objects; 120166550Sjhb the_obj_info->unseen_objects = unseen_objects; 121166550Sjhb } 122166550Sjhb _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST, 123166550Sjhb the_obj_info); 124166550Sjhb 125166550Sjhb free (image->object_info); 126166550Sjhb image->object_info = NULL; 127166550Sjhb if (image->examined_p & ALLOCED_IMAGE_MASK) 128166550Sjhb free (image->fde); 129166550Sjhb image->fde = NULL; 130166550Sjhb } 131166550Sjhb image->examined_p = 0; 132166550Sjhb image->destructor = NULL; 133166550Sjhb} 134166550Sjhb 135166550Sjhb/* Run through the list of live images. If we can allocate memory, 136166550Sjhb give each unseen image a new `struct object'. Even if we can't, 137166550Sjhb check whether the PC is inside the FDE of each unseen image. 138166550Sjhb */ 139166550Sjhb 140166550Sjhbstatic inline const fde * 141166550Sjhbexamine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc) 142166550Sjhb{ 143166550Sjhb const fde *result = NULL; 144166550Sjhb struct live_images *image; 145166550Sjhb 146166550Sjhb image = _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST); 147166550Sjhb 148166550Sjhb for (; image != NULL; image = image->next) 149166550Sjhb if ((image->examined_p & EXAMINED_IMAGE_MASK) == 0) 15077605Stmm { 15177605Stmm char *fde; 15272950Srwatson unsigned long sz; 15377605Stmm 15477605Stmm fde = getsectdatafromheader (image->mh, "__DATA", "__eh_frame", &sz); 15577605Stmm if (fde == NULL) 15672950Srwatson { 157217744Suqs fde = getsectdatafromheader (image->mh, "__TEXT", 158217744Suqs "__eh_frame", &sz); 159217744Suqs if (fde != NULL) 16077605Stmm image->examined_p |= IMAGE_IS_TEXT_MASK; 16177605Stmm } 16277605Stmm 16377605Stmm /* If .eh_frame is empty, don't register at all. */ 16477605Stmm if (fde != NULL && sz > 0) 16572950Srwatson { 16677605Stmm char *real_fde = (fde + image->vm_slide); 16772950Srwatson struct object *ob = NULL; 16872950Srwatson struct object panicob; 16977605Stmm 17077605Stmm if (! dont_alloc) 17177605Stmm ob = calloc (1, sizeof (struct object)); 17277605Stmm dont_alloc |= ob == NULL; 17372950Srwatson if (dont_alloc) 17477605Stmm ob = &panicob; 17577605Stmm 17677605Stmm ob->pc_begin = (void *)-1; 17777605Stmm ob->tbase = 0; 17877605Stmm ob->dbase = 0; 17977605Stmm ob->u.single = (struct dwarf_fde *)real_fde; 18077605Stmm ob->s.i = 0; 18177605Stmm ob->s.b.encoding = DW_EH_PE_omit; 18277605Stmm ob->fde_end = real_fde + sz; 18377605Stmm 18472950Srwatson image->fde = real_fde; 18572950Srwatson 18677605Stmm result = search_object (ob, pc); 18777605Stmm 18877605Stmm if (! dont_alloc) 18972950Srwatson { 19077605Stmm struct object **p; 19177605Stmm 19277605Stmm image->destructor = live_image_destructor; 19377605Stmm image->object_info = ob; 19472950Srwatson 19577605Stmm image->examined_p |= (EXAMINED_IMAGE_MASK 19672950Srwatson | DESTRUCTOR_MAY_BE_CALLED_LIVE); 19777605Stmm 19877605Stmm /* Insert the object into the classified list. */ 19977605Stmm for (p = &seen_objects; *p ; p = &(*p)->next) 20077605Stmm if ((*p)->pc_begin < ob->pc_begin) 20177605Stmm break; 20277605Stmm ob->next = *p; 20377605Stmm *p = ob; 20477605Stmm } 20572950Srwatson 20677605Stmm if (result) 20777605Stmm { 20872950Srwatson int encoding; 20972950Srwatson 21077605Stmm bases->tbase = ob->tbase; 21177605Stmm bases->dbase = ob->dbase; 21277605Stmm 21377605Stmm encoding = ob->s.b.encoding; 21477605Stmm if (ob->s.b.mixed_encoding) 21577605Stmm encoding = get_fde_encoding (result); 21672950Srwatson read_encoded_value_with_base (encoding, 21772950Srwatson base_from_object (encoding, ob), 21872950Srwatson result->pc_begin, 21972950Srwatson (_Unwind_Ptr *)&bases->func); 220166550Sjhb break; 221166550Sjhb } 222166550Sjhb } 223166550Sjhb else 224166550Sjhb image->examined_p |= EXAMINED_IMAGE_MASK; 225166550Sjhb } 226166550Sjhb 227166550Sjhb _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST); 228166550Sjhb 229166550Sjhb return result; 230166550Sjhb} 231166550Sjhb 232166550Sjhbconst fde * 233166550Sjhb_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases) 234166550Sjhb{ 235166550Sjhb struct km_object_info *the_obj_info; 236166550Sjhb const fde *ret = NULL; 237166550Sjhb 238166550Sjhb the_obj_info = 239166550Sjhb _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST); 240166550Sjhb if (! the_obj_info) 241166550Sjhb the_obj_info = calloc (1, sizeof (*the_obj_info)); 242166550Sjhb 243166550Sjhb if (the_obj_info != NULL) 244166550Sjhb { 245166550Sjhb seen_objects = the_obj_info->seen_objects; 246166550Sjhb unseen_objects = the_obj_info->unseen_objects; 247166550Sjhb 248217744Suqs ret = _Unwind_Find_registered_FDE (pc, bases); 249217744Suqs } 25077605Stmm 25172950Srwatson /* OK, didn't find it in the list of FDEs we've seen before, 25277605Stmm so go through and look at the new ones. */ 25377605Stmm if (ret == NULL) 25472950Srwatson ret = examine_objects (pc, bases, the_obj_info == NULL); 25572950Srwatson 25672950Srwatson if (the_obj_info != NULL) 25772950Srwatson { 25872950Srwatson the_obj_info->seen_objects = seen_objects; 25972950Srwatson the_obj_info->unseen_objects = unseen_objects; 26072950Srwatson } 26172950Srwatson _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST, 262 the_obj_info); 263 return ret; 264} 265