| /* GNU Objective C Runtime method related functions. | |
| Copyright (C) 2010-2026 Free Software Foundation, Inc. | |
| Contributed by Nicola Pero | |
| This file is part of GCC. | |
| GCC is free software; you can redistribute it and/or modify it under the | |
| terms of the GNU General Public License as published by the Free Software | |
| Foundation; either version 3, or (at your option) any later version. | |
| GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
| FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | |
| details. | |
| Under Section 7 of GPL version 3, you are granted additional | |
| permissions described in the GCC Runtime Library Exception, version | |
| 3.1, as published by the Free Software Foundation. | |
| You should have received a copy of the GNU General Public License and | |
| a copy of the GCC Runtime Library Exception along with this program; | |
| see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
| <http://www.gnu.org/licenses/>. */ | |
| #include "objc-private/common.h" | |
| #include "objc/runtime.h" | |
| #include "objc-private/module-abi-8.h" /* For runtime structures. */ | |
| #include "objc/thr.h" | |
| #include "objc-private/runtime.h" /* For __objc_runtime_mutex. */ | |
| #include <stdlib.h> /* For malloc. */ | |
| SEL | |
| method_getName (struct objc_method * method) | |
| { | |
| if (method == NULL) | |
| return NULL; | |
| return method->method_name; | |
| } | |
| const char * | |
| method_getTypeEncoding (struct objc_method * method) | |
| { | |
| if (method == NULL) | |
| return NULL; | |
| return method->method_types; | |
| } | |
| IMP | |
| method_getImplementation (struct objc_method * method) | |
| { | |
| if (method == NULL) | |
| return NULL; | |
| return method->method_imp; | |
| } | |
| struct objc_method_description * | |
| method_getDescription (struct objc_method * method) | |
| { | |
| /* Note that the following returns NULL if method is NULL, which is | |
| fine. */ | |
| return (struct objc_method_description *)method; | |
| } | |
| struct objc_method ** | |
| class_copyMethodList (Class class_, unsigned int *numberOfReturnedMethods) | |
| { | |
| unsigned int count = 0; | |
| struct objc_method **returnValue = NULL; | |
| struct objc_method_list* method_list; | |
| if (class_ == Nil) | |
| { | |
| if (numberOfReturnedMethods) | |
| *numberOfReturnedMethods = 0; | |
| return NULL; | |
| } | |
| /* Lock the runtime mutex because the class methods may be | |
| concurrently modified. */ | |
| objc_mutex_lock (__objc_runtime_mutex); | |
| /* Count how many methods we have. */ | |
| method_list = class_->methods; | |
| while (method_list) | |
| { | |
| count = count + method_list->method_count; | |
| method_list = method_list->method_next; | |
| } | |
| if (count != 0) | |
| { | |
| unsigned int i = 0; | |
| /* Allocate enough memory to hold them. */ | |
| returnValue | |
| = (struct objc_method **)(malloc (sizeof (struct objc_method *) | |
| * (count + 1))); | |
| /* Copy the methods. */ | |
| method_list = class_->methods; | |
| while (method_list) | |
| { | |
| int j; | |
| for (j = 0; j < method_list->method_count; j++) | |
| { | |
| returnValue[i] = &(method_list->method_list[j]); | |
| i++; | |
| } | |
| method_list = method_list->method_next; | |
| } | |
| returnValue[i] = NULL; | |
| } | |
| objc_mutex_unlock (__objc_runtime_mutex); | |
| if (numberOfReturnedMethods) | |
| *numberOfReturnedMethods = count; | |
| return returnValue; | |
| } | |
| IMP | |
| method_setImplementation (struct objc_method * method, IMP implementation) | |
| { | |
| IMP old_implementation; | |
| if (method == NULL || implementation == NULL) | |
| return NULL; | |
| /* We lock the runtime mutex so that concurrent calls to change the | |
| same method won't conflict with each other. */ | |
| objc_mutex_lock (__objc_runtime_mutex); | |
| old_implementation = method->method_imp; | |
| method->method_imp = implementation; | |
| /* That was easy :-). But now we need to find all classes that use | |
| this method, and update the IMP in the dispatch tables. */ | |
| __objc_update_classes_with_methods (method, NULL); | |
| objc_mutex_unlock (__objc_runtime_mutex); | |
| return old_implementation; | |
| } | |
| void | |
| method_exchangeImplementations (struct objc_method * method_a, struct objc_method * method_b) | |
| { | |
| IMP old_implementation_a; | |
| IMP old_implementation_b; | |
| if (method_a == NULL || method_b == NULL) | |
| return; | |
| /* We lock the runtime mutex so that concurrent calls to exchange | |
| similar methods won't conflict with each other. Each of them | |
| should be atomic. */ | |
| objc_mutex_lock (__objc_runtime_mutex); | |
| old_implementation_a = method_a->method_imp; | |
| old_implementation_b = method_b->method_imp; | |
| method_a->method_imp = old_implementation_b; | |
| method_b->method_imp = old_implementation_a; | |
| /* That was easy :-). But now we need to find all classes that use | |
| these methods, and update the IMP in the dispatch tables. */ | |
| __objc_update_classes_with_methods (method_a, method_b); | |
| objc_mutex_unlock (__objc_runtime_mutex); | |
| } |