1 /* GNU Objective C Runtime method related functions. 2 Copyright (C) 2010 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 } 178