1 /* GNU Objective C Runtime selector related functions
2    Copyright (C) 1993-2019 Free Software Foundation, Inc.
3    Contributed by Kresten Krab Thorup
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation; either version 3, or (at your option) any later version.
10 
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14 details.
15 
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
19 
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 <http://www.gnu.org/licenses/>.  */
24 
25 #include "objc-private/common.h"
26 #include "objc/runtime.h"
27 #include "objc/thr.h"
28 #include "objc-private/hash.h"
29 #include "objc-private/objc-list.h"
30 #include "objc-private/module-abi-8.h"
31 #include "objc-private/runtime.h"
32 #include "objc-private/sarray.h"
33 #include "objc-private/selector.h"
34 #include <stdlib.h>                    /* For malloc.  */
35 
36 /* Initial selector hash table size. Value doesn't matter much.  */
37 #define SELECTOR_HASH_SIZE 128
38 
39 /* Tables mapping selector names to uid and opposite.  */
40 static struct sarray *__objc_selector_array = 0; /* uid -> sel  !T:MUTEX */
41 static struct sarray *__objc_selector_names = 0; /* uid -> name !T:MUTEX */
42 static cache_ptr      __objc_selector_hash  = 0; /* name -> uid !T:MUTEX */
43 
44 /* Number of selectors stored in each of the above tables.  */
45 unsigned int __objc_selector_max_index = 0;     /* !T:MUTEX */
46 
47 /* Forward-declare an internal function.  */
48 static SEL
49 __sel_register_typed_name (const char *name, const char *types,
50 			   struct objc_selector *orig, BOOL is_const);
51 
__objc_init_selector_tables(void)52 void __objc_init_selector_tables (void)
53 {
54   __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
55   __objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
56   __objc_selector_hash
57     = objc_hash_new (SELECTOR_HASH_SIZE,
58 		     (hash_func_type) objc_hash_string,
59 		     (compare_func_type) objc_compare_strings);
60 }
61 
62 /* Register a bunch of selectors from the table of selectors in a
63    module.  'selectors' should not be NULL.  The list is terminated by
64    a selectors with a NULL sel_id.  The selectors are assumed to
65    contain the 'name' in the sel_id field; this is replaced with the
66    final selector id after they are registered.  */
67 void
__objc_register_selectors_from_module(struct objc_selector * selectors)68 __objc_register_selectors_from_module (struct objc_selector *selectors)
69 {
70   int i;
71 
72   for (i = 0; selectors[i].sel_id; ++i)
73     {
74       const char *name, *type;
75       name = (char *) selectors[i].sel_id;
76       type = (char *) selectors[i].sel_types;
77       /* Constructors are constant static data and we can safely store
78 	 pointers to them in the runtime structures, so we set
79 	 is_const == YES.  */
80       __sel_register_typed_name (name, type, (struct objc_selector *) &(selectors[i]),
81 				 /* is_const */ YES);
82     }
83 }
84 
85 /* This routine is given a class and records all of the methods in its
86    class structure in the record table.  */
87 void
__objc_register_selectors_from_class(Class class)88 __objc_register_selectors_from_class (Class class)
89 {
90   struct objc_method_list * method_list;
91 
92   method_list = class->methods;
93   while (method_list)
94     {
95       __objc_register_selectors_from_list (method_list);
96       method_list = method_list->method_next;
97     }
98 }
99 
100 
101 /* This routine is given a list of methods and records each of the
102    methods in the record table.  This is the routine that does the
103    actual recording work.
104 
105    The name and type pointers in the method list must be permanent and
106    immutable.  */
107 void
__objc_register_selectors_from_list(struct objc_method_list * method_list)108 __objc_register_selectors_from_list (struct objc_method_list *method_list)
109 {
110   int i = 0;
111 
112   objc_mutex_lock (__objc_runtime_mutex);
113   while (i < method_list->method_count)
114     {
115       Method method = &method_list->method_list[i];
116       if (method->method_name)
117 	{
118 	  method->method_name
119 	    = __sel_register_typed_name ((const char *) method->method_name,
120 					 method->method_types, 0, YES);
121 	}
122       i += 1;
123     }
124   objc_mutex_unlock (__objc_runtime_mutex);
125 }
126 
127 /* The same as __objc_register_selectors_from_list, but works on a
128    struct objc_method_description_list* instead of a struct
129    objc_method_list*.  This is only used for protocols, which have
130    lists of method descriptions, not methods.  */
131 void
__objc_register_selectors_from_description_list(struct objc_method_description_list * method_list)132 __objc_register_selectors_from_description_list
133 (struct objc_method_description_list *method_list)
134 {
135   int i = 0;
136 
137   objc_mutex_lock (__objc_runtime_mutex);
138   while (i < method_list->count)
139     {
140       struct objc_method_description *method = &method_list->list[i];
141       if (method->name)
142 	{
143 	  method->name
144 	    = __sel_register_typed_name ((const char *) method->name,
145 					 method->types, 0, YES);
146 	}
147       i += 1;
148     }
149   objc_mutex_unlock (__objc_runtime_mutex);
150 }
151 
152 /* Register instance methods as class methods for root classes.  */
__objc_register_instance_methods_to_class(Class class)153 void __objc_register_instance_methods_to_class (Class class)
154 {
155   struct objc_method_list *method_list;
156   struct objc_method_list *class_method_list;
157   int max_methods_no = 16;
158   struct objc_method_list *new_list;
159   Method curr_method;
160 
161   /* Only if a root class. */
162   if (class->super_class)
163     return;
164 
165   /* Allocate a method list to hold the new class methods.  */
166   new_list = objc_calloc (sizeof (struct objc_method_list)
167 			  + sizeof (struct objc_method[max_methods_no]), 1);
168   method_list = class->methods;
169   class_method_list = class->class_pointer->methods;
170   curr_method = &new_list->method_list[0];
171 
172   /* Iterate through the method lists for the class.  */
173   while (method_list)
174     {
175       int i;
176 
177       /* Iterate through the methods from this method list.  */
178       for (i = 0; i < method_list->method_count; i++)
179 	{
180 	  Method mth = &method_list->method_list[i];
181 	  if (mth->method_name
182 	      && ! search_for_method_in_list (class_method_list,
183 					      mth->method_name))
184 	    {
185 	      /* This instance method isn't a class method.  Add it
186 		 into the new_list. */
187 	      *curr_method = *mth;
188 
189 	      /* Reallocate the method list if necessary.  */
190 	      if (++new_list->method_count == max_methods_no)
191 		new_list =
192 		  objc_realloc (new_list, sizeof (struct objc_method_list)
193 				+ sizeof (struct
194 					  objc_method[max_methods_no += 16]));
195 	      curr_method = &new_list->method_list[new_list->method_count];
196 	    }
197 	}
198 
199       method_list = method_list->method_next;
200     }
201 
202   /* If we created any new class methods then attach the method list
203      to the class.  */
204   if (new_list->method_count)
205     {
206       new_list =
207  	objc_realloc (new_list, sizeof (struct objc_method_list)
208 		      + sizeof (struct objc_method[new_list->method_count]));
209       new_list->method_next = class->class_pointer->methods;
210       class->class_pointer->methods = new_list;
211     }
212   else
213     objc_free(new_list);
214 
215   __objc_update_dispatch_table_for_class (class->class_pointer);
216 }
217 
218 BOOL
sel_isEqual(SEL s1,SEL s2)219 sel_isEqual (SEL s1, SEL s2)
220 {
221   if (s1 == 0 || s2 == 0)
222     return s1 == s2;
223   else
224     return s1->sel_id == s2->sel_id;
225 }
226 
227 /* Return YES iff t1 and t2 have same method types.  Ignore the
228    argframe layout.  */
229 static BOOL
sel_types_match(const char * t1,const char * t2)230 sel_types_match (const char *t1, const char *t2)
231 {
232   if (! t1 || ! t2)
233     return NO;
234   while (*t1 && *t2)
235     {
236       if (*t1 == '+') t1++;
237       if (*t2 == '+') t2++;
238       while (isdigit ((unsigned char) *t1)) t1++;
239       while (isdigit ((unsigned char) *t2)) t2++;
240       /* xxx Remove these next two lines when qualifiers are put in
241 	 all selectors, not just Protocol selectors.  */
242       t1 = objc_skip_type_qualifiers (t1);
243       t2 = objc_skip_type_qualifiers (t2);
244       if (! *t1 && ! *t2)
245 	return YES;
246       if (*t1 != *t2)
247 	return NO;
248       t1++;
249       t2++;
250     }
251   return NO;
252 }
253 
254 /* Return selector representing name.  */
255 SEL
sel_get_any_uid(const char * name)256 sel_get_any_uid (const char *name)
257 {
258   struct objc_list *l;
259   sidx i;
260 
261   objc_mutex_lock (__objc_runtime_mutex);
262 
263   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
264   if (soffset_decode (i) == 0)
265     {
266       objc_mutex_unlock (__objc_runtime_mutex);
267       return 0;
268     }
269 
270   l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
271   objc_mutex_unlock (__objc_runtime_mutex);
272 
273   if (l == 0)
274     return 0;
275 
276   return (SEL) l->head;
277 }
278 
279 SEL
sel_getTypedSelector(const char * name)280 sel_getTypedSelector (const char *name)
281 {
282   sidx i;
283 
284   if (name == NULL)
285     return NULL;
286 
287   objc_mutex_lock (__objc_runtime_mutex);
288 
289   /* Look for a typed selector.  */
290   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
291   if (i != 0)
292     {
293       struct objc_list *l;
294       SEL returnValue = NULL;
295 
296       for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
297 	   l; l = l->tail)
298 	{
299 	  SEL s = (SEL) l->head;
300 	  if (s->sel_types)
301 	    {
302 	      if (returnValue == NULL)
303 		{
304 		  /* First typed selector that we find.  Keep it in
305 		     returnValue, but keep checking as we want to
306 		     detect conflicts.  */
307 		  returnValue = s;
308 		}
309 	      else
310 		{
311 		  /* We had already found a typed selectors, so we
312 		     have multiple ones.  Double-check that they have
313 		     different types, just in case for some reason we
314 		     got duplicates with the same types.  If so, it's
315 		     OK, we'll ignore the duplicate.  */
316 		  if (returnValue->sel_types == s->sel_types)
317 		    continue;
318 		  else if (sel_types_match (returnValue->sel_types, s->sel_types))
319 		    continue;
320 		  else
321 		    {
322 		      /* The types of the two selectors are different;
323 			 it's a conflict.  Too bad.  Return NULL.  */
324 		      objc_mutex_unlock (__objc_runtime_mutex);
325 		      return NULL;
326 		    }
327 		}
328 	    }
329 	}
330 
331       if (returnValue != NULL)
332 	{
333 	  objc_mutex_unlock (__objc_runtime_mutex);
334 	  return returnValue;
335 	}
336     }
337 
338   /* No typed selector found.  Return NULL.  */
339   objc_mutex_unlock (__objc_runtime_mutex);
340   return 0;
341 }
342 
343 SEL *
sel_copyTypedSelectorList(const char * name,unsigned int * numberOfReturnedSelectors)344 sel_copyTypedSelectorList (const char *name, unsigned int *numberOfReturnedSelectors)
345 {
346   unsigned int count = 0;
347   SEL *returnValue = NULL;
348   sidx i;
349 
350   if (name == NULL)
351     {
352       if (numberOfReturnedSelectors)
353 	*numberOfReturnedSelectors = 0;
354       return NULL;
355     }
356 
357   objc_mutex_lock (__objc_runtime_mutex);
358 
359   /* Count how many selectors we have.  */
360   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
361   if (i != 0)
362     {
363       struct objc_list *selector_list = NULL;
364       selector_list = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
365 
366       /* Count how many selectors we have.  */
367       {
368 	struct objc_list *l;
369 	for (l = selector_list; l; l = l->tail)
370 	  count++;
371       }
372 
373       if (count != 0)
374 	{
375 	  /* Allocate enough memory to hold them.  */
376 	  returnValue = (SEL *)(malloc (sizeof (SEL) * (count + 1)));
377 
378 	  /* Copy the selectors.  */
379 	  {
380 	    unsigned int j;
381 	    for (j = 0; j < count; j++)
382 	      {
383 		returnValue[j] = (SEL)(selector_list->head);
384 		selector_list = selector_list->tail;
385 	      }
386 	    returnValue[j] = NULL;
387 	  }
388 	}
389     }
390 
391   objc_mutex_unlock (__objc_runtime_mutex);
392 
393   if (numberOfReturnedSelectors)
394     *numberOfReturnedSelectors = count;
395 
396   return returnValue;
397 }
398 
399 /* Get the name of a selector.  If the selector is unknown, the empty
400    string "" is returned.  */
sel_getName(SEL selector)401 const char *sel_getName (SEL selector)
402 {
403   const char *ret;
404 
405   if (selector == NULL)
406     return "<null selector>";
407 
408   objc_mutex_lock (__objc_runtime_mutex);
409   if ((soffset_decode ((sidx)selector->sel_id) > 0)
410       && (soffset_decode ((sidx)selector->sel_id) <= __objc_selector_max_index))
411     ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
412   else
413     ret = 0;
414   objc_mutex_unlock (__objc_runtime_mutex);
415   return ret;
416 }
417 
418 BOOL
sel_is_mapped(SEL selector)419 sel_is_mapped (SEL selector)
420 {
421   unsigned int idx = soffset_decode ((sidx)selector->sel_id);
422   return ((idx > 0) && (idx <= __objc_selector_max_index));
423 }
424 
sel_getTypeEncoding(SEL selector)425 const char *sel_getTypeEncoding (SEL selector)
426 {
427   if (selector)
428     return selector->sel_types;
429   else
430     return 0;
431 }
432 
433 /* The uninstalled dispatch table.  */
434 extern struct sarray *__objc_uninstalled_dtable;
435 
436 /* __sel_register_typed_name allocates lots of struct objc_selector:s
437    of 8 (16, if pointers are 64 bits) bytes at startup. To reduce the
438    number of malloc calls and memory lost to malloc overhead, we
439    allocate objc_selector:s in blocks here. This is only called from
440    __sel_register_typed_name, and __sel_register_typed_name may only
441    be called when __objc_runtime_mutex is locked.
442 
443    Note that the objc_selector:s allocated from
444    __sel_register_typed_name are never freed.
445 
446    62 because 62 * sizeof (struct objc_selector) = 496 (992). This
447    should let malloc add some overhead and use a nice, round 512
448    (1024) byte chunk.  */
449 #define SELECTOR_POOL_SIZE 62
450 static struct objc_selector *selector_pool;
451 static int selector_pool_left;
452 
453 static struct objc_selector *
pool_alloc_selector(void)454 pool_alloc_selector(void)
455 {
456   if (!selector_pool_left)
457     {
458       selector_pool = objc_malloc (sizeof (struct objc_selector)
459 				   * SELECTOR_POOL_SIZE);
460       selector_pool_left = SELECTOR_POOL_SIZE;
461     }
462   return &selector_pool[--selector_pool_left];
463 }
464 
465 /* Store the passed selector name in the selector record and return
466    its selector value (value returned by sel_get_uid).  Assume that
467    the calling function has locked down __objc_runtime_mutex.  The
468    'is_const' parameter tells us if the name and types parameters are
469    really constant or not.  If YES then they are constant and we can
470    just store the pointers.  If NO then we need to copy name and types
471    because the pointers may disappear later on.  If the 'orig'
472    parameter is not NULL, then we are registering a selector from a
473    module, and 'orig' is that selector.  In this case, we can put the
474    selector in the tables if needed, and orig->sel_id is updated with
475    the selector ID of the registered selector, and 'orig' is
476    returned.  */
477 static SEL
__sel_register_typed_name(const char * name,const char * types,struct objc_selector * orig,BOOL is_const)478 __sel_register_typed_name (const char *name, const char *types,
479 			   struct objc_selector *orig, BOOL is_const)
480 {
481   struct objc_selector *j;
482   sidx i;
483   struct objc_list *l;
484 
485   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
486   if (soffset_decode (i) != 0)
487     {
488       /* There are already selectors with that name.  Examine them to
489 	 see if the one we're registering already exists.  */
490       for (l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
491 	   l; l = l->tail)
492 	{
493 	  SEL s = (SEL)l->head;
494 	  if (types == 0 || s->sel_types == 0)
495 	    {
496 	      if (s->sel_types == types)
497 		{
498 		  if (orig)
499 		    {
500 		      orig->sel_id = (void *)i;
501 		      return orig;
502 		    }
503 		  else
504 		    return s;
505 		}
506 	    }
507 	  else if (sel_types_match (s->sel_types, types))
508 	    {
509 	      if (orig)
510 		{
511 		  orig->sel_id = (void *)i;
512 		  return orig;
513 		}
514 	      else
515 		return s;
516 	    }
517 	}
518       /* A selector with this specific name/type combination does not
519 	 exist yet.  We need to register it.  */
520       if (orig)
521 	j = orig;
522       else
523 	j = pool_alloc_selector ();
524 
525       j->sel_id = (void *)i;
526       /* Can we use the pointer or must we copy types ?  Don't copy if
527 	 NULL.  */
528       if ((is_const) || (types == 0))
529 	j->sel_types = types;
530       else
531 	{
532 	  j->sel_types = (char *)objc_malloc (strlen (types) + 1);
533 	  strcpy ((char *)j->sel_types, types);
534 	}
535       l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
536     }
537   else
538     {
539       /* There are no other selectors with this name registered in the
540 	 runtime tables.  */
541       const char *new_name;
542 
543       /* Determine i.  */
544       __objc_selector_max_index += 1;
545       i = soffset_encode (__objc_selector_max_index);
546 
547       /* Prepare the selector.  */
548       if (orig)
549 	j = orig;
550       else
551 	j = pool_alloc_selector ();
552 
553       j->sel_id = (void *)i;
554       /* Can we use the pointer or must we copy types ?  Don't copy if
555 	 NULL.  */
556       if (is_const || (types == 0))
557 	j->sel_types = types;
558       else
559 	{
560 	  j->sel_types = (char *)objc_malloc (strlen (types) + 1);
561 	  strcpy ((char *)j->sel_types, types);
562 	}
563 
564       /* Since this is the first selector with this name, we need to
565 	 register the correspondence between 'i' (the sel_id) and
566 	 'name' (the actual string) in __objc_selector_names and
567 	 __objc_selector_hash.  */
568 
569       /* Can we use the pointer or must we copy name ?  Don't copy if
570 	 NULL.  (FIXME: Can the name really be NULL here ?)  */
571       if (is_const || (name == 0))
572 	new_name = name;
573       else
574 	{
575 	  new_name = (char *)objc_malloc (strlen (name) + 1);
576 	  strcpy ((char *)new_name, name);
577 	}
578 
579       /* This maps the sel_id to the name.  */
580       sarray_at_put_safe (__objc_selector_names, i, (void *)new_name);
581 
582       /* This maps the name to the sel_id.  */
583       objc_hash_add (&__objc_selector_hash, (void *)new_name, (void *)i);
584 
585       l = 0;
586     }
587 
588   DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
589 		(long)soffset_decode (i));
590 
591   /* Now add the selector to the list of selectors with that id.  */
592   l = list_cons ((void *)j, l);
593   sarray_at_put_safe (__objc_selector_array, i, (void *)l);
594 
595   sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
596 
597   return (SEL)j;
598 }
599 
600 SEL
sel_registerName(const char * name)601 sel_registerName (const char *name)
602 {
603   SEL ret;
604 
605   if (name == NULL)
606     return NULL;
607 
608   objc_mutex_lock (__objc_runtime_mutex);
609   /* Assume that name is not constant static memory and needs to be
610      copied before put into a runtime structure.  is_const == NO.  */
611   ret = __sel_register_typed_name (name, 0, 0, NO);
612   objc_mutex_unlock (__objc_runtime_mutex);
613 
614   return ret;
615 }
616 
617 SEL
sel_registerTypedName(const char * name,const char * type)618 sel_registerTypedName (const char *name, const char *type)
619 {
620   SEL ret;
621 
622   if (name == NULL)
623     return NULL;
624 
625   objc_mutex_lock (__objc_runtime_mutex);
626   /* Assume that name and type are not constant static memory and need
627      to be copied before put into a runtime structure.  is_const ==
628      NO.  */
629   ret = __sel_register_typed_name (name, type, 0, NO);
630   objc_mutex_unlock (__objc_runtime_mutex);
631 
632   return ret;
633 }
634 
635 /* Return the selector representing name.  */
636 SEL
sel_getUid(const char * name)637 sel_getUid (const char *name)
638 {
639   return sel_registerTypedName (name, 0);
640 }
641