(root)/
gcc-13.2.0/
libobjc/
methods.c
       1  /* GNU Objective C Runtime method related functions.
       2     Copyright (C) 2010-2023 Free Software Foundation, Inc.
       3     Contributed by Nicola Pero
       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-private/module-abi-8.h" /* For runtime structures.   */
      28  #include "objc/thr.h"
      29  #include "objc-private/runtime.h"      /* For __objc_runtime_mutex.  */
      30  #include <stdlib.h>                    /* For malloc.  */
      31  
      32  SEL
      33  method_getName (struct objc_method * method)
      34  {
      35    if (method == NULL)
      36      return NULL;
      37  
      38    return method->method_name;
      39  }
      40  
      41  const char *
      42  method_getTypeEncoding (struct objc_method * method)
      43  {
      44    if (method == NULL)
      45      return NULL;
      46  
      47    return method->method_types;
      48  }
      49  
      50  IMP
      51  method_getImplementation (struct objc_method * method)
      52  {
      53    if (method == NULL)
      54      return NULL;
      55  
      56    return method->method_imp;
      57  }
      58  
      59  struct objc_method_description *
      60  method_getDescription (struct objc_method * method)
      61  {
      62    /* Note that the following returns NULL if method is NULL, which is
      63       fine.  */
      64    return (struct objc_method_description *)method;
      65  }
      66  
      67  struct objc_method **
      68  class_copyMethodList (Class class_, unsigned int *numberOfReturnedMethods)
      69  {
      70    unsigned int count = 0;
      71    struct objc_method **returnValue = NULL;
      72    struct objc_method_list* method_list;
      73  
      74    if (class_ == Nil)
      75      {
      76        if (numberOfReturnedMethods)
      77  	*numberOfReturnedMethods = 0;
      78        return NULL;
      79      }
      80  
      81    /* Lock the runtime mutex because the class methods may be
      82       concurrently modified.  */
      83    objc_mutex_lock (__objc_runtime_mutex);
      84  
      85    /* Count how many methods we have.  */
      86    method_list = class_->methods;
      87  
      88    while (method_list)
      89      {
      90        count = count + method_list->method_count;
      91        method_list = method_list->method_next;
      92      }
      93  
      94    if (count != 0)
      95      {
      96        unsigned int i = 0;
      97        
      98        /* Allocate enough memory to hold them.  */
      99        returnValue 
     100  	= (struct objc_method **)(malloc (sizeof (struct objc_method *) 
     101  					  * (count + 1)));
     102        
     103        /* Copy the methods.  */
     104        method_list = class_->methods;
     105        
     106        while (method_list)
     107  	{
     108  	  int j;
     109  	  for (j = 0; j < method_list->method_count; j++)
     110  	    {
     111  	      returnValue[i] = &(method_list->method_list[j]);
     112  	      i++;
     113  	    }
     114  	  method_list = method_list->method_next;
     115  	}
     116        
     117        returnValue[i] = NULL;
     118      }
     119  
     120    objc_mutex_unlock (__objc_runtime_mutex);
     121  
     122    if (numberOfReturnedMethods)
     123      *numberOfReturnedMethods = count;
     124  
     125    return returnValue;
     126  }
     127  
     128  IMP
     129  method_setImplementation (struct objc_method * method, IMP implementation)
     130  {
     131    IMP old_implementation;
     132  
     133    if (method == NULL  ||  implementation == NULL)
     134      return NULL;
     135  
     136    /* We lock the runtime mutex so that concurrent calls to change the
     137       same method won't conflict with each other.  */
     138    objc_mutex_lock (__objc_runtime_mutex);
     139  
     140    old_implementation = method->method_imp;
     141    method->method_imp = implementation;
     142  
     143    /* That was easy :-).  But now we need to find all classes that use
     144       this method, and update the IMP in the dispatch tables.  */
     145    __objc_update_classes_with_methods (method, NULL);
     146  
     147    objc_mutex_unlock (__objc_runtime_mutex);
     148  
     149    return old_implementation;
     150  }
     151  
     152  void
     153  method_exchangeImplementations (struct objc_method * method_a, struct objc_method * method_b)
     154  {
     155    IMP old_implementation_a;
     156    IMP old_implementation_b;
     157  
     158    if (method_a == NULL  ||  method_b == NULL)
     159      return;
     160  
     161    /* We lock the runtime mutex so that concurrent calls to exchange
     162       similar methods won't conflict with each other.  Each of them
     163       should be atomic.  */
     164    objc_mutex_lock (__objc_runtime_mutex);
     165  
     166    old_implementation_a = method_a->method_imp;
     167    old_implementation_b = method_b->method_imp;
     168  
     169    method_a->method_imp = old_implementation_b;
     170    method_b->method_imp = old_implementation_a;
     171  
     172    /* That was easy :-).  But now we need to find all classes that use
     173       these methods, and update the IMP in the dispatch tables.  */
     174    __objc_update_classes_with_methods (method_a, method_b);
     175  
     176    objc_mutex_unlock (__objc_runtime_mutex);
     177  }