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