1 /* 2 * Copyright 2012 Piotr Caban for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include "cppexcept.h" 20 21 #ifdef _MSC_VER 22 #define __ASM_VTABLE(name,funcs) 23 #else 24 #ifdef _WIN64 25 26 #define VTABLE_ADD_FUNC(name) "\t.quad " THISCALL_NAME(name) "\n" 27 28 #define __ASM_VTABLE(name,funcs) \ 29 __asm__(".data\n" \ 30 "\t.balign 8\n" \ 31 "\t.quad " __ASM_NAME(#name "_rtti") "\n" \ 32 "\t.globl " __ASM_NAME(#name "_vtable") "\n" \ 33 __ASM_NAME(#name "_vtable") ":\n" \ 34 funcs "\n\t.text") 35 36 #else 37 38 #define VTABLE_ADD_FUNC(name) "\t.long " THISCALL_NAME(name) "\n" 39 40 #define __ASM_VTABLE(name,funcs) \ 41 __asm__(".data\n" \ 42 "\t.balign 4\n" \ 43 "\t.long " __ASM_NAME(#name "_rtti") "\n" \ 44 "\t.globl " __ASM_NAME(#name "_vtable") "\n" \ 45 __ASM_NAME(#name "_vtable") ":\n" \ 46 funcs "\n\t.text") 47 48 #endif /* _WIN64 */ 49 #endif // _MSC_VER 50 51 #ifndef __x86_64__ 52 53 #define DEFINE_RTTI_BASE(name, base_classes_no, mangled_name) \ 54 static type_info name ## _type_info = { \ 55 &type_info_vtable, \ 56 NULL, \ 57 mangled_name \ 58 }; \ 59 \ 60 static const rtti_base_descriptor name ## _rtti_base_descriptor = { \ 61 &name ##_type_info, \ 62 base_classes_no, \ 63 { 0, -1, 0}, \ 64 64 \ 65 }; 66 67 #define DEFINE_RTTI_DATA(name, off, base_classes_no, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name) \ 68 DEFINE_RTTI_BASE(name, base_classes_no, mangled_name) \ 69 \ 70 static const rtti_base_array name ## _rtti_base_array = { \ 71 { \ 72 &name ## _rtti_base_descriptor, \ 73 cl1, \ 74 cl2, \ 75 cl3, \ 76 cl4, \ 77 cl5, \ 78 cl6, \ 79 cl7, \ 80 cl8, \ 81 cl9, \ 82 } \ 83 }; \ 84 \ 85 static const rtti_object_hierarchy name ## _hierarchy = { \ 86 0, \ 87 0, \ 88 base_classes_no+1, \ 89 &name ## _rtti_base_array \ 90 }; \ 91 \ 92 const rtti_object_locator name ## _rtti = { \ 93 0, \ 94 off, \ 95 0, \ 96 &name ## _type_info, \ 97 &name ## _hierarchy \ 98 }; 99 100 #else 101 102 #define __DEFINE_RTTI_BASE(name, base_classes_no, mangled_name) \ 103 static type_info name ## _type_info = { \ 104 &type_info_vtable, \ 105 NULL, \ 106 mangled_name \ 107 }; \ 108 \ 109 static rtti_base_descriptor name ## _rtti_base_descriptor = { \ 110 0xdeadbeef, \ 111 base_classes_no, \ 112 { 0, -1, 0}, \ 113 64 \ 114 }; 115 116 #define DEFINE_RTTI_BASE(name, base_classes_no, mangled_name) \ 117 __DEFINE_RTTI_BASE(name, base_classes_no, mangled_name) \ 118 \ 119 static void init_ ## name ## _rtti(char *base) \ 120 { \ 121 name ## _rtti_base_descriptor.type_descriptor = (char*)&name ## _type_info - base; \ 122 } 123 124 #define DEFINE_RTTI_DATA(name, off, base_classes_no, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name) \ 125 __DEFINE_RTTI_BASE(name, base_classes_no, mangled_name) \ 126 \ 127 static rtti_base_array name ## _rtti_base_array = { \ 128 { \ 129 0xdeadbeef, \ 130 0xdeadbeef, \ 131 0xdeadbeef, \ 132 0xdeadbeef, \ 133 0xdeadbeef, \ 134 0xdeadbeef, \ 135 0xdeadbeef, \ 136 0xdeadbeef, \ 137 0xdeadbeef, \ 138 0xdeadbeef, \ 139 } \ 140 }; \ 141 \ 142 static rtti_object_hierarchy name ## _hierarchy = { \ 143 0, \ 144 0, \ 145 base_classes_no+1, \ 146 0xdeadbeef \ 147 }; \ 148 \ 149 rtti_object_locator name ## _rtti = { \ 150 1, \ 151 off, \ 152 0, \ 153 0xdeadbeef, \ 154 0xdeadbeef, \ 155 0xdeadbeef \ 156 };\ 157 \ 158 static void init_ ## name ## _rtti(char *base) \ 159 { \ 160 name ## _rtti_base_descriptor.type_descriptor = (char*)&name ## _type_info - base; \ 161 name ## _rtti_base_array.bases[0] = (char*)&name ## _rtti_base_descriptor - base; \ 162 name ## _rtti_base_array.bases[1] = (char*)cl1 - base; \ 163 name ## _rtti_base_array.bases[2] = (char*)cl2 - base; \ 164 name ## _rtti_base_array.bases[3] = (char*)cl3 - base; \ 165 name ## _rtti_base_array.bases[4] = (char*)cl4 - base; \ 166 name ## _rtti_base_array.bases[5] = (char*)cl5 - base; \ 167 name ## _rtti_base_array.bases[6] = (char*)cl6 - base; \ 168 name ## _rtti_base_array.bases[7] = (char*)cl7 - base; \ 169 name ## _rtti_base_array.bases[8] = (char*)cl8 - base; \ 170 name ## _rtti_base_array.bases[9] = (char*)cl9 - base; \ 171 name ## _hierarchy.base_classes = (char*)&name ## _rtti_base_array - base; \ 172 name ## _rtti.type_descriptor = (char*)&name ## _type_info - base; \ 173 name ## _rtti.type_hierarchy = (char*)&name ## _hierarchy - base; \ 174 name ## _rtti.object_locator = (char*)&name ## _rtti - base; \ 175 } 176 177 #endif 178 179 #define DEFINE_RTTI_DATA0(name, off, mangled_name) \ 180 DEFINE_RTTI_DATA(name, off, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, mangled_name) 181 #define DEFINE_RTTI_DATA1(name, off, cl1, mangled_name) \ 182 DEFINE_RTTI_DATA(name, off, 1, cl1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, mangled_name) 183 #define DEFINE_RTTI_DATA2(name, off, cl1, cl2, mangled_name) \ 184 DEFINE_RTTI_DATA(name, off, 2, cl1, cl2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, mangled_name) 185 #define DEFINE_RTTI_DATA3(name, off, cl1, cl2, cl3, mangled_name) \ 186 DEFINE_RTTI_DATA(name, off, 3, cl1, cl2, cl3, NULL, NULL, NULL, NULL, NULL, NULL, mangled_name) 187 #define DEFINE_RTTI_DATA4(name, off, cl1, cl2, cl3, cl4, mangled_name) \ 188 DEFINE_RTTI_DATA(name, off, 4, cl1, cl2, cl3, cl4, NULL, NULL, NULL, NULL, NULL, mangled_name) 189 #define DEFINE_RTTI_DATA8(name, off, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, mangled_name) \ 190 DEFINE_RTTI_DATA(name, off, 8, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, NULL, mangled_name) 191 #define DEFINE_RTTI_DATA9(name, off, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name) \ 192 DEFINE_RTTI_DATA(name, off, 9, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name) 193 194 #ifndef __x86_64__ 195 196 typedef struct _rtti_base_descriptor 197 { 198 const type_info *type_descriptor; 199 int num_base_classes; 200 this_ptr_offsets offsets; /* offsets for computing the this pointer */ 201 unsigned int attributes; 202 } rtti_base_descriptor; 203 204 typedef struct _rtti_base_array 205 { 206 const rtti_base_descriptor *bases[10]; /* First element is the class itself */ 207 } rtti_base_array; 208 209 typedef struct _rtti_object_hierarchy 210 { 211 unsigned int signature; 212 unsigned int attributes; 213 int array_len; /* Size of the array pointed to by 'base_classes' */ 214 const rtti_base_array *base_classes; 215 } rtti_object_hierarchy; 216 217 typedef struct _rtti_object_locator 218 { 219 unsigned int signature; 220 int base_class_offset; 221 unsigned int flags; 222 const type_info *type_descriptor; 223 const rtti_object_hierarchy *type_hierarchy; 224 } rtti_object_locator; 225 226 #else 227 228 typedef struct 229 { 230 unsigned int type_descriptor; 231 int num_base_classes; 232 this_ptr_offsets offsets; /* offsets for computing the this pointer */ 233 unsigned int attributes; 234 } rtti_base_descriptor; 235 236 typedef struct 237 { 238 unsigned int bases[10]; /* First element is the class itself */ 239 } rtti_base_array; 240 241 typedef struct 242 { 243 unsigned int signature; 244 unsigned int attributes; 245 int array_len; /* Size of the array pointed to by 'base_classes' */ 246 unsigned int base_classes; 247 } rtti_object_hierarchy; 248 249 typedef struct 250 { 251 unsigned int signature; 252 int base_class_offset; 253 unsigned int flags; 254 unsigned int type_descriptor; 255 unsigned int type_hierarchy; 256 unsigned int object_locator; 257 } rtti_object_locator; 258 259 #endif 260 261 #ifdef __ASM_USE_THISCALL_WRAPPER 262 263 #define CALL_VTBL_FUNC(this, off, ret, type, args) ((ret (WINAPI*)type)&vtbl_wrapper_##off)args 264 265 extern void *vtbl_wrapper_0; 266 extern void *vtbl_wrapper_4; 267 extern void *vtbl_wrapper_8; 268 extern void *vtbl_wrapper_12; 269 extern void *vtbl_wrapper_16; 270 extern void *vtbl_wrapper_20; 271 extern void *vtbl_wrapper_24; 272 extern void *vtbl_wrapper_28; 273 extern void *vtbl_wrapper_32; 274 extern void *vtbl_wrapper_36; 275 extern void *vtbl_wrapper_40; 276 extern void *vtbl_wrapper_44; 277 extern void *vtbl_wrapper_48; 278 279 #else 280 281 #define CALL_VTBL_FUNC(this, off, ret, type, args) ((ret (__thiscall***)type)this)[0][off/4]args 282 283 #endif 284 285 exception* __thiscall exception_ctor(exception*, const char**); 286 287 extern const vtable_ptr type_info_vtable; 288 289 #ifdef __REACTOS__ 290 void * __thiscall type_info_vector_dtor(type_info * _this, unsigned int flags); 291 #endif 292 293 #define CREATE_TYPE_INFO_VTABLE \ 294 DEFINE_THISCALL_WRAPPER(type_info_vector_dtor,8) \ 295 void * __thiscall type_info_vector_dtor(type_info * _this, unsigned int flags) \ 296 { \ 297 if (flags & 2) \ 298 { \ 299 /* we have an array, with the number of elements stored before the first object */ \ 300 INT_PTR i, *ptr = (INT_PTR *)_this - 1; \ 301 \ 302 for (i = *ptr - 1; i >= 0; i--) free(_this[i].name); \ 303 free(ptr); \ 304 } \ 305 else \ 306 { \ 307 free(_this->name); \ 308 if (flags & 1) free(_this); \ 309 } \ 310 return _this; \ 311 } \ 312 \ 313 DEFINE_RTTI_DATA0( type_info, 0, ".?AVtype_info@@" ) \ 314 \ 315 __ASM_BLOCK_BEGIN(type_info_vtables) \ 316 __ASM_VTABLE(type_info, \ 317 VTABLE_ADD_FUNC(type_info_vector_dtor)); \ 318 __ASM_BLOCK_END 319