Home | History | Annotate | Line # | Download | only in libobjc
      1       1.1  mrg /* GNU Objective C Runtime method related functions.
      2  1.1.1.11  mrg    Copyright (C) 2010-2024 Free Software Foundation, Inc.
      3       1.1  mrg    Contributed by Nicola Pero
      4       1.1  mrg 
      5       1.1  mrg This file is part of GCC.
      6       1.1  mrg 
      7       1.1  mrg GCC is free software; you can redistribute it and/or modify it under the
      8       1.1  mrg terms of the GNU General Public License as published by the Free Software
      9       1.1  mrg Foundation; either version 3, or (at your option) any later version.
     10       1.1  mrg 
     11       1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     12       1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
     13       1.1  mrg FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
     14       1.1  mrg details.
     15       1.1  mrg 
     16       1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     17       1.1  mrg permissions described in the GCC Runtime Library Exception, version
     18       1.1  mrg 3.1, as published by the Free Software Foundation.
     19       1.1  mrg 
     20       1.1  mrg You should have received a copy of the GNU General Public License and
     21       1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     22       1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23       1.1  mrg <http://www.gnu.org/licenses/>.  */
     24       1.1  mrg 
     25       1.1  mrg #include "objc-private/common.h"
     26       1.1  mrg #include "objc/runtime.h"
     27       1.1  mrg #include "objc-private/module-abi-8.h" /* For runtime structures.   */
     28       1.1  mrg #include "objc/thr.h"
     29       1.1  mrg #include "objc-private/runtime.h"      /* For __objc_runtime_mutex.  */
     30       1.1  mrg #include <stdlib.h>                    /* For malloc.  */
     31       1.1  mrg 
     32       1.1  mrg SEL
     33       1.1  mrg method_getName (struct objc_method * method)
     34       1.1  mrg {
     35       1.1  mrg   if (method == NULL)
     36       1.1  mrg     return NULL;
     37       1.1  mrg 
     38       1.1  mrg   return method->method_name;
     39       1.1  mrg }
     40       1.1  mrg 
     41       1.1  mrg const char *
     42       1.1  mrg method_getTypeEncoding (struct objc_method * method)
     43       1.1  mrg {
     44       1.1  mrg   if (method == NULL)
     45       1.1  mrg     return NULL;
     46       1.1  mrg 
     47       1.1  mrg   return method->method_types;
     48       1.1  mrg }
     49       1.1  mrg 
     50       1.1  mrg IMP
     51       1.1  mrg method_getImplementation (struct objc_method * method)
     52       1.1  mrg {
     53       1.1  mrg   if (method == NULL)
     54       1.1  mrg     return NULL;
     55       1.1  mrg 
     56       1.1  mrg   return method->method_imp;
     57       1.1  mrg }
     58       1.1  mrg 
     59       1.1  mrg struct objc_method_description *
     60       1.1  mrg method_getDescription (struct objc_method * method)
     61       1.1  mrg {
     62       1.1  mrg   /* Note that the following returns NULL if method is NULL, which is
     63       1.1  mrg      fine.  */
     64       1.1  mrg   return (struct objc_method_description *)method;
     65       1.1  mrg }
     66       1.1  mrg 
     67       1.1  mrg struct objc_method **
     68       1.1  mrg class_copyMethodList (Class class_, unsigned int *numberOfReturnedMethods)
     69       1.1  mrg {
     70       1.1  mrg   unsigned int count = 0;
     71       1.1  mrg   struct objc_method **returnValue = NULL;
     72       1.1  mrg   struct objc_method_list* method_list;
     73       1.1  mrg 
     74       1.1  mrg   if (class_ == Nil)
     75       1.1  mrg     {
     76       1.1  mrg       if (numberOfReturnedMethods)
     77       1.1  mrg 	*numberOfReturnedMethods = 0;
     78       1.1  mrg       return NULL;
     79       1.1  mrg     }
     80       1.1  mrg 
     81       1.1  mrg   /* Lock the runtime mutex because the class methods may be
     82       1.1  mrg      concurrently modified.  */
     83       1.1  mrg   objc_mutex_lock (__objc_runtime_mutex);
     84       1.1  mrg 
     85       1.1  mrg   /* Count how many methods we have.  */
     86       1.1  mrg   method_list = class_->methods;
     87       1.1  mrg 
     88       1.1  mrg   while (method_list)
     89       1.1  mrg     {
     90       1.1  mrg       count = count + method_list->method_count;
     91       1.1  mrg       method_list = method_list->method_next;
     92       1.1  mrg     }
     93       1.1  mrg 
     94       1.1  mrg   if (count != 0)
     95       1.1  mrg     {
     96       1.1  mrg       unsigned int i = 0;
     97       1.1  mrg 
     98       1.1  mrg       /* Allocate enough memory to hold them.  */
     99       1.1  mrg       returnValue
    100       1.1  mrg 	= (struct objc_method **)(malloc (sizeof (struct objc_method *)
    101       1.1  mrg 					  * (count + 1)));
    102       1.1  mrg 
    103       1.1  mrg       /* Copy the methods.  */
    104       1.1  mrg       method_list = class_->methods;
    105       1.1  mrg 
    106       1.1  mrg       while (method_list)
    107       1.1  mrg 	{
    108       1.1  mrg 	  int j;
    109       1.1  mrg 	  for (j = 0; j < method_list->method_count; j++)
    110       1.1  mrg 	    {
    111       1.1  mrg 	      returnValue[i] = &(method_list->method_list[j]);
    112       1.1  mrg 	      i++;
    113       1.1  mrg 	    }
    114       1.1  mrg 	  method_list = method_list->method_next;
    115       1.1  mrg 	}
    116       1.1  mrg 
    117       1.1  mrg       returnValue[i] = NULL;
    118       1.1  mrg     }
    119       1.1  mrg 
    120       1.1  mrg   objc_mutex_unlock (__objc_runtime_mutex);
    121       1.1  mrg 
    122       1.1  mrg   if (numberOfReturnedMethods)
    123       1.1  mrg     *numberOfReturnedMethods = count;
    124       1.1  mrg 
    125       1.1  mrg   return returnValue;
    126       1.1  mrg }
    127       1.1  mrg 
    128       1.1  mrg IMP
    129       1.1  mrg method_setImplementation (struct objc_method * method, IMP implementation)
    130       1.1  mrg {
    131       1.1  mrg   IMP old_implementation;
    132       1.1  mrg 
    133       1.1  mrg   if (method == NULL  ||  implementation == NULL)
    134       1.1  mrg     return NULL;
    135       1.1  mrg 
    136       1.1  mrg   /* We lock the runtime mutex so that concurrent calls to change the
    137       1.1  mrg      same method won't conflict with each other.  */
    138       1.1  mrg   objc_mutex_lock (__objc_runtime_mutex);
    139       1.1  mrg 
    140       1.1  mrg   old_implementation = method->method_imp;
    141       1.1  mrg   method->method_imp = implementation;
    142       1.1  mrg 
    143       1.1  mrg   /* That was easy :-).  But now we need to find all classes that use
    144       1.1  mrg      this method, and update the IMP in the dispatch tables.  */
    145       1.1  mrg   __objc_update_classes_with_methods (method, NULL);
    146       1.1  mrg 
    147       1.1  mrg   objc_mutex_unlock (__objc_runtime_mutex);
    148       1.1  mrg 
    149       1.1  mrg   return old_implementation;
    150       1.1  mrg }
    151       1.1  mrg 
    152       1.1  mrg void
    153       1.1  mrg method_exchangeImplementations (struct objc_method * method_a, struct objc_method * method_b)
    154       1.1  mrg {
    155       1.1  mrg   IMP old_implementation_a;
    156       1.1  mrg   IMP old_implementation_b;
    157       1.1  mrg 
    158       1.1  mrg   if (method_a == NULL  ||  method_b == NULL)
    159       1.1  mrg     return;
    160       1.1  mrg 
    161       1.1  mrg   /* We lock the runtime mutex so that concurrent calls to exchange
    162       1.1  mrg      similar methods won't conflict with each other.  Each of them
    163       1.1  mrg      should be atomic.  */
    164       1.1  mrg   objc_mutex_lock (__objc_runtime_mutex);
    165       1.1  mrg 
    166       1.1  mrg   old_implementation_a = method_a->method_imp;
    167       1.1  mrg   old_implementation_b = method_b->method_imp;
    168       1.1  mrg 
    169       1.1  mrg   method_a->method_imp = old_implementation_b;
    170       1.1  mrg   method_b->method_imp = old_implementation_a;
    171       1.1  mrg 
    172       1.1  mrg   /* That was easy :-).  But now we need to find all classes that use
    173       1.1  mrg      these methods, and update the IMP in the dispatch tables.  */
    174       1.1  mrg   __objc_update_classes_with_methods (method_a, method_b);
    175       1.1  mrg 
    176       1.1  mrg   objc_mutex_unlock (__objc_runtime_mutex);
    177       1.1  mrg }
    178