1 /* Copyright (C) 2001-2021 Free Software Foundation, Inc.
2 
3    This file is part of GCC.
4 
5    GCC is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3, or (at your option)
8    any later version.
9 
10    GCC is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    Under Section 7 of GPL version 3, you are granted additional
16    permissions described in the GCC Runtime Library Exception, version
17    3.1, as published by the Free Software Foundation.
18 
19    You should have received a copy of the GNU General Public License and
20    a copy of the GCC Runtime Library Exception along with this program;
21    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
22    <http://www.gnu.org/licenses/>.  */
23 
24 /* Locate the FDE entry for a given address, using Darwin's keymgr support.  */
25 
26 #include "tconfig.h"
27 #include "tsystem.h"
28 #include <string.h>
29 #include <stdlib.h>
30 #include "dwarf2.h"
31 #include "unwind.h"
32 #define NO_BASE_OF_ENCODED_VALUE
33 #define DWARF2_OBJECT_END_PTR_EXTENSION
34 #include "unwind-pe.h"
35 #include "unwind-dw2-fde.h"
36 /* Carefully don't include gthr.h.  */
37 
38 typedef int __gthread_mutex_t;
39 #define __gthread_mutex_lock(x)  (void)(x)
40 #define __gthread_mutex_unlock(x) (void)(x)
41 
42 static const fde * _Unwind_Find_registered_FDE (void *pc,
43 						struct dwarf_eh_bases *bases);
44 
45 #define _Unwind_Find_FDE _Unwind_Find_registered_FDE
46 #include "unwind-dw2-fde.c"
47 #undef _Unwind_Find_FDE
48 
49 /* KeyMgr stuff.  */
50 #define KEYMGR_GCC3_LIVE_IMAGE_LIST     301     /* loaded images  */
51 #define KEYMGR_GCC3_DW2_OBJ_LIST        302     /* Dwarf2 object list  */
52 
53 extern void *_keymgr_get_and_lock_processwide_ptr (int);
54 extern void _keymgr_set_and_unlock_processwide_ptr (int, void *);
55 extern void _keymgr_unlock_processwide_ptr (int);
56 
57 struct mach_header;
58 struct mach_header_64;
59 extern char *getsectdatafromheader (struct mach_header*, const char*,
60 				    const char *, unsigned long *);
61 extern char *getsectdatafromheader_64 (struct mach_header_64*, const char*,
62 				       const char *, unsigned long *);
63 
64 /* This is referenced from KEYMGR_GCC3_DW2_OBJ_LIST.  */
65 struct km_object_info {
66   struct object *seen_objects;
67   struct object *unseen_objects;
68   unsigned spare[2];
69 };
70 
71 /* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST.  Info about each resident image.  */
72 struct live_images {
73   unsigned long this_size;                      /* sizeof (live_images)  */
74   struct mach_header *mh;                       /* the image info  */
75   unsigned long vm_slide;
76   void (*destructor)(struct live_images *);     /* destructor for this  */
77   struct live_images *next;
78   unsigned int examined_p;
79   void *fde;
80   void *object_info;
81   unsigned long info[2];                        /* Future use.  */
82 };
83 
84 /* Bits in the examined_p field of struct live_images.  */
85 enum {
86   EXAMINED_IMAGE_MASK = 1,	/* We've seen this one.  */
87   ALLOCED_IMAGE_MASK = 2,	/* The FDE entries were allocated by
88 				   malloc, and must be freed.  This isn't
89 				   used by newer libgcc versions.  */
90   IMAGE_IS_TEXT_MASK = 4,	/* This image is in the TEXT segment.  */
91   DESTRUCTOR_MAY_BE_CALLED_LIVE = 8  /* The destructor may be called on an
92 					object that's part of the live
93 					image list.  */
94 };
95 
96 /* Delete any data we allocated on a live_images structure.  Either
97    IMAGE has already been removed from the
98    KEYMGR_GCC3_LIVE_IMAGE_LIST and the struct will be deleted
99    after we return, or that list is locked and we're being called
100    because this object might be about to be unloaded.  Called by
101    KeyMgr.  */
102 
103 static void
live_image_destructor(struct live_images * image)104 live_image_destructor (struct live_images *image)
105 {
106   if (image->object_info)
107     {
108       struct km_object_info *the_obj_info;
109 
110       the_obj_info =
111 	_keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
112       if (the_obj_info)
113 	{
114 	  seen_objects = the_obj_info->seen_objects;
115 	  unseen_objects = the_obj_info->unseen_objects;
116 
117 	  /* Free any sorted arrays.  */
118 	  __deregister_frame_info_bases (image->fde);
119 
120 	  the_obj_info->seen_objects = seen_objects;
121 	  the_obj_info->unseen_objects = unseen_objects;
122 	}
123       _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
124 					      the_obj_info);
125 
126       free (image->object_info);
127       image->object_info = NULL;
128       if (image->examined_p & ALLOCED_IMAGE_MASK)
129 	free (image->fde);
130       image->fde = NULL;
131     }
132   image->examined_p = 0;
133   image->destructor = NULL;
134 }
135 
136 /* Run through the list of live images.  If we can allocate memory,
137    give each unseen image a new `struct object'.  Even if we can't,
138    check whether the PC is inside the FDE of each unseen image.
139  */
140 
141 static inline const fde *
examine_objects(void * pc,struct dwarf_eh_bases * bases,int dont_alloc)142 examine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc)
143 {
144   const fde *result = NULL;
145   struct live_images *image;
146 
147   image = _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
148 
149   for (; image != NULL; image = image->next)
150     if ((image->examined_p & EXAMINED_IMAGE_MASK) == 0)
151       {
152 	char *fde = NULL;
153 	unsigned long sz;
154 
155 	/* For ppc only check whether or not we have __DATA eh frames.  */
156 #ifdef __ppc__
157 	fde = getsectdatafromheader (image->mh, "__DATA", "__eh_frame", &sz);
158 #endif
159 
160 	if (fde == NULL)
161 	  {
162 #if __LP64__
163 	    fde = getsectdatafromheader_64 ((struct mach_header_64 *) image->mh,
164 					    "__TEXT", "__eh_frame", &sz);
165 #else
166 	    fde = getsectdatafromheader (image->mh, "__TEXT",
167 					 "__eh_frame", &sz);
168 #endif
169 	    if (fde != NULL)
170 	      image->examined_p |= IMAGE_IS_TEXT_MASK;
171 	  }
172 
173 	/* If .eh_frame is empty, don't register at all.  */
174 	if (fde != NULL && sz > 0)
175 	  {
176 	    char *real_fde = (fde + image->vm_slide);
177 	    struct object *ob = NULL;
178 	    struct object panicob;
179 
180 	    if (! dont_alloc)
181 	      ob = calloc (1, sizeof (struct object));
182 	    dont_alloc |= ob == NULL;
183 	    if (dont_alloc)
184 	      ob = &panicob;
185 
186 	    ob->pc_begin = (void *)-1;
187 	    ob->tbase = 0;
188 	    ob->dbase = 0;
189 	    ob->u.single = (struct dwarf_fde *)real_fde;
190 	    ob->s.i = 0;
191 	    ob->s.b.encoding = DW_EH_PE_omit;
192 	    ob->fde_end = real_fde + sz;
193 
194 	    image->fde = real_fde;
195 
196 	    result = search_object (ob, pc);
197 
198 	    if (! dont_alloc)
199 	      {
200 		struct object **p;
201 
202 		image->destructor = live_image_destructor;
203 		image->object_info = ob;
204 
205 		image->examined_p |= (EXAMINED_IMAGE_MASK
206 				      | DESTRUCTOR_MAY_BE_CALLED_LIVE);
207 
208 		/* Insert the object into the classified list.  */
209 		for (p = &seen_objects; *p ; p = &(*p)->next)
210 		  if ((*p)->pc_begin < ob->pc_begin)
211 		    break;
212 		ob->next = *p;
213 		*p = ob;
214 	      }
215 
216 	    if (result)
217 	      {
218 		int encoding;
219 		_Unwind_Ptr func;
220 
221 		bases->tbase = ob->tbase;
222 		bases->dbase = ob->dbase;
223 
224 		encoding = ob->s.b.encoding;
225 		if (ob->s.b.mixed_encoding)
226 		  encoding = get_fde_encoding (result);
227 		read_encoded_value_with_base (encoding,
228 					      base_from_object (encoding, ob),
229 					      result->pc_begin, &func);
230 		bases->func = (void *) func;
231 		break;
232 	      }
233 	  }
234 	else
235 	  image->examined_p |= EXAMINED_IMAGE_MASK;
236       }
237 
238   _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
239 
240   return result;
241 }
242 
243 const fde *
_Unwind_Find_FDE(void * pc,struct dwarf_eh_bases * bases)244 _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
245 {
246   struct km_object_info *the_obj_info;
247   const fde *ret = NULL;
248 
249   the_obj_info =
250     _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
251   if (! the_obj_info)
252     the_obj_info = calloc (1, sizeof (*the_obj_info));
253 
254   if (the_obj_info != NULL)
255     {
256       seen_objects = the_obj_info->seen_objects;
257       unseen_objects = the_obj_info->unseen_objects;
258 
259       ret = _Unwind_Find_registered_FDE (pc, bases);
260     }
261 
262   /* OK, didn't find it in the list of FDEs we've seen before,
263      so go through and look at the new ones.  */
264   if (ret == NULL)
265     ret = examine_objects (pc, bases, the_obj_info == NULL);
266 
267   if (the_obj_info != NULL)
268     {
269       the_obj_info->seen_objects = seen_objects;
270       the_obj_info->unseen_objects = unseen_objects;
271     }
272   _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
273 					  the_obj_info);
274   return ret;
275 }
276