exception.cc (233235) | exception.cc (245304) |
---|---|
1/* 2 * Copyright 2010-2011 PathScale, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. --- 18 unchanged lines hidden (view full) --- 27#include <stdlib.h> 28#include <dlfcn.h> 29#include <stdio.h> 30#include <string.h> 31#include <stdint.h> 32#include <pthread.h> 33#include "typeinfo.h" 34#include "dwarf_eh.h" | 1/* 2 * Copyright 2010-2011 PathScale, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. --- 18 unchanged lines hidden (view full) --- 27#include <stdlib.h> 28#include <dlfcn.h> 29#include <stdio.h> 30#include <string.h> 31#include <stdint.h> 32#include <pthread.h> 33#include "typeinfo.h" 34#include "dwarf_eh.h" |
35#include "atomic.h" |
|
35#include "cxxabi.h" 36 37#pragma weak pthread_key_create 38#pragma weak pthread_setspecific 39#pragma weak pthread_getspecific 40#pragma weak pthread_once 41 42using namespace ABI_NAMESPACE; --- 107 unchanged lines hidden (view full) --- 150 * in ABI spec [3.3.1]). 151 */ 152 int emergencyBuffersHeld; 153 /** 154 * The exception currently running in a cleanup. 155 */ 156 _Unwind_Exception *currentCleanup; 157 /** | 36#include "cxxabi.h" 37 38#pragma weak pthread_key_create 39#pragma weak pthread_setspecific 40#pragma weak pthread_getspecific 41#pragma weak pthread_once 42 43using namespace ABI_NAMESPACE; --- 107 unchanged lines hidden (view full) --- 151 * in ABI spec [3.3.1]). 152 */ 153 int emergencyBuffersHeld; 154 /** 155 * The exception currently running in a cleanup. 156 */ 157 _Unwind_Exception *currentCleanup; 158 /** |
159 * Our state with respect to foreign exceptions. Usually none, set to 160 * caught if we have just caught an exception and rethrown if we are 161 * rethrowing it. 162 */ 163 enum 164 { 165 none, 166 caught, 167 rethrown 168 } foreign_exception_state; 169 /** |
|
158 * The public part of this structure, accessible from outside of this 159 * module. 160 */ 161 __cxa_eh_globals globals; 162}; 163/** 164 * Dependent exception. This 165 */ --- 137 unchanged lines hidden (view full) --- 303 * Cleanup function called when a thread exists to make certain that all of the 304 * per-thread data is deleted. 305 */ 306static void thread_cleanup(void* thread_info) 307{ 308 __cxa_thread_info *info = (__cxa_thread_info*)thread_info; 309 if (info->globals.caughtExceptions) 310 { | 170 * The public part of this structure, accessible from outside of this 171 * module. 172 */ 173 __cxa_eh_globals globals; 174}; 175/** 176 * Dependent exception. This 177 */ --- 137 unchanged lines hidden (view full) --- 315 * Cleanup function called when a thread exists to make certain that all of the 316 * per-thread data is deleted. 317 */ 318static void thread_cleanup(void* thread_info) 319{ 320 __cxa_thread_info *info = (__cxa_thread_info*)thread_info; 321 if (info->globals.caughtExceptions) 322 { |
311 free_exception_list(info->globals.caughtExceptions); | 323 // If this is a foreign exception, ask it to clean itself up. 324 if (info->foreign_exception_state != __cxa_thread_info::none) 325 { 326 _Unwind_Exception *e = (_Unwind_Exception*)info->globals.caughtExceptions; 327 e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e); 328 } 329 else 330 { 331 free_exception_list(info->globals.caughtExceptions); 332 } |
312 } 313 free(thread_info); 314} 315 316 317/** 318 * Once control used to protect the key creation. 319 */ --- 455 unchanged lines hidden (view full) --- 775 * ABI function. Rethrows the current exception. Does not remove the 776 * exception from the stack or decrement its handler count - the compiler is 777 * expected to set the landing pad for this function to the end of the catch 778 * block, and then call _Unwind_Resume() to continue unwinding once 779 * __cxa_end_catch() has been called and any cleanup code has been run. 780 */ 781extern "C" void __cxa_rethrow() 782{ | 333 } 334 free(thread_info); 335} 336 337 338/** 339 * Once control used to protect the key creation. 340 */ --- 455 unchanged lines hidden (view full) --- 796 * ABI function. Rethrows the current exception. Does not remove the 797 * exception from the stack or decrement its handler count - the compiler is 798 * expected to set the landing pad for this function to the end of the catch 799 * block, and then call _Unwind_Resume() to continue unwinding once 800 * __cxa_end_catch() has been called and any cleanup code has been run. 801 */ 802extern "C" void __cxa_rethrow() 803{ |
783 __cxa_eh_globals *globals = __cxa_get_globals(); | 804 __cxa_thread_info *ti = thread_info_fast(); 805 __cxa_eh_globals *globals = &ti->globals; |
784 // Note: We don't remove this from the caught list here, because 785 // __cxa_end_catch will be called when we unwind out of the try block. We 786 // could probably make this faster by providing an alternative rethrow 787 // function and ensuring that all cleanup code is run before calling it, so 788 // we can skip the top stack frame when unwinding. 789 __cxa_exception *ex = globals->caughtExceptions; 790 791 if (0 == ex) 792 { 793 fprintf(stderr, 794 "Attempting to rethrow an exception that doesn't exist!\n"); 795 std::terminate(); 796 } 797 | 806 // Note: We don't remove this from the caught list here, because 807 // __cxa_end_catch will be called when we unwind out of the try block. We 808 // could probably make this faster by providing an alternative rethrow 809 // function and ensuring that all cleanup code is run before calling it, so 810 // we can skip the top stack frame when unwinding. 811 __cxa_exception *ex = globals->caughtExceptions; 812 813 if (0 == ex) 814 { 815 fprintf(stderr, 816 "Attempting to rethrow an exception that doesn't exist!\n"); 817 std::terminate(); 818 } 819 |
820 if (ti->foreign_exception_state != __cxa_thread_info::none) 821 { 822 ti->foreign_exception_state = __cxa_thread_info::rethrown; 823 _Unwind_Exception *e = (_Unwind_Exception*)ex; 824 _Unwind_Reason_Code err = _Unwind_Resume_or_Rethrow(e); 825 report_failure(err, ex); 826 return; 827 } 828 |
|
798 assert(ex->handlerCount > 0 && "Rethrowing uncaught exception!"); 799 800 // ex->handlerCount will be decremented in __cxa_end_catch in enclosing 801 // catch block 802 803 // Make handler count negative. This will tell __cxa_end_catch that 804 // exception was rethrown and exception object should not be destroyed 805 // when handler count become zero --- 37 unchanged lines hidden (view full) --- 843 * object. If ex is 0 then it is assumed to be a foreign exception and only 844 * matches cleanups. 845 */ 846static bool check_type_signature(__cxa_exception *ex, 847 const std::type_info *type, 848 void *&adjustedPtr) 849{ 850 void *exception_ptr = (void*)(ex+1); | 829 assert(ex->handlerCount > 0 && "Rethrowing uncaught exception!"); 830 831 // ex->handlerCount will be decremented in __cxa_end_catch in enclosing 832 // catch block 833 834 // Make handler count negative. This will tell __cxa_end_catch that 835 // exception was rethrown and exception object should not be destroyed 836 // when handler count become zero --- 37 unchanged lines hidden (view full) --- 874 * object. If ex is 0 then it is assumed to be a foreign exception and only 875 * matches cleanups. 876 */ 877static bool check_type_signature(__cxa_exception *ex, 878 const std::type_info *type, 879 void *&adjustedPtr) 880{ 881 void *exception_ptr = (void*)(ex+1); |
851 const std::type_info *ex_type = ex->exceptionType; | 882 const std::type_info *ex_type = ex ? ex->exceptionType : 0; |
852 | 883 |
853 bool is_ptr = ex_type->__is_pointer_p(); | 884 bool is_ptr = ex ? ex_type->__is_pointer_p() : false; |
854 if (is_ptr) 855 { 856 exception_ptr = *(void**)exception_ptr; 857 } 858 // Always match a catchall, even with a foreign exception 859 // 860 // Note: A 0 here is a catchall, not a cleanup, so we return true to 861 // indicate that we found a catch. --- 44 unchanged lines hidden (view full) --- 906 while (action_record) 907 { 908 int filter = read_sleb128(&action_record); 909 dw_eh_ptr_t action_record_offset_base = action_record; 910 int displacement = read_sleb128(&action_record); 911 action_record = displacement ? 912 action_record_offset_base + displacement : 0; 913 // We only check handler types for C++ exceptions - foreign exceptions | 885 if (is_ptr) 886 { 887 exception_ptr = *(void**)exception_ptr; 888 } 889 // Always match a catchall, even with a foreign exception 890 // 891 // Note: A 0 here is a catchall, not a cleanup, so we return true to 892 // indicate that we found a catch. --- 44 unchanged lines hidden (view full) --- 937 while (action_record) 938 { 939 int filter = read_sleb128(&action_record); 940 dw_eh_ptr_t action_record_offset_base = action_record; 941 int displacement = read_sleb128(&action_record); 942 action_record = displacement ? 943 action_record_offset_base + displacement : 0; 944 // We only check handler types for C++ exceptions - foreign exceptions |
914 // are only allowed for cleanup. 915 if (filter > 0 && 0 != ex) | 945 // are only allowed for cleanups and catchalls. 946 if (filter > 0) |
916 { 917 std::type_info *handler_type = get_type_info_entry(context, lsda, filter); 918 if (check_type_signature(ex, handler_type, adjustedPtr)) 919 { 920 *selector = filter; 921 return handler_catch; 922 } 923 } --- 204 unchanged lines hidden (view full) --- 1128 * C++ exceptions) of the unadjusted pointer (for foreign exceptions). 1129 */ 1130#if __GNUC__ > 3 && __GNUC_MINOR__ > 2 1131extern "C" void *__cxa_begin_catch(void *e) throw() 1132#else 1133extern "C" void *__cxa_begin_catch(void *e) 1134#endif 1135{ | 947 { 948 std::type_info *handler_type = get_type_info_entry(context, lsda, filter); 949 if (check_type_signature(ex, handler_type, adjustedPtr)) 950 { 951 *selector = filter; 952 return handler_catch; 953 } 954 } --- 204 unchanged lines hidden (view full) --- 1159 * C++ exceptions) of the unadjusted pointer (for foreign exceptions). 1160 */ 1161#if __GNUC__ > 3 && __GNUC_MINOR__ > 2 1162extern "C" void *__cxa_begin_catch(void *e) throw() 1163#else 1164extern "C" void *__cxa_begin_catch(void *e) 1165#endif 1166{ |
1136 // Decrement the uncaught exceptions count 1137 __cxa_eh_globals *globals = __cxa_get_globals(); | 1167 // We can't call the fast version here, because if the first exception that 1168 // we see is a foreign exception then we won't have called it yet. 1169 __cxa_thread_info *ti = thread_info(); 1170 __cxa_eh_globals *globals = &ti->globals; |
1138 globals->uncaughtExceptions--; 1139 _Unwind_Exception *exceptionObject = (_Unwind_Exception*)e; 1140 1141 if (isCXXException(exceptionObject->exception_class)) 1142 { 1143 __cxa_exception *ex = exceptionFromPointer(exceptionObject); 1144 1145 if (ex->handlerCount == 0) --- 26 unchanged lines hidden (view full) --- 1172 // } 1173 // } 1174 ex->handlerCount = -ex->handlerCount + 1; 1175 } 1176 else 1177 { 1178 ex->handlerCount++; 1179 } | 1171 globals->uncaughtExceptions--; 1172 _Unwind_Exception *exceptionObject = (_Unwind_Exception*)e; 1173 1174 if (isCXXException(exceptionObject->exception_class)) 1175 { 1176 __cxa_exception *ex = exceptionFromPointer(exceptionObject); 1177 1178 if (ex->handlerCount == 0) --- 26 unchanged lines hidden (view full) --- 1205 // } 1206 // } 1207 ex->handlerCount = -ex->handlerCount + 1; 1208 } 1209 else 1210 { 1211 ex->handlerCount++; 1212 } |
1213 ti->foreign_exception_state = __cxa_thread_info::none; |
|
1180 1181 return ex->adjustedPtr; 1182 } | 1214 1215 return ex->adjustedPtr; 1216 } |
1217 else 1218 { 1219 // If this is a foreign exception, then we need to be able to 1220 // store it. We can't chain foreign exceptions, so we give up 1221 // if there are already some outstanding ones. 1222 if (globals->caughtExceptions != 0) 1223 { 1224 std::terminate(); 1225 } 1226 globals->caughtExceptions = (__cxa_exception*)exceptionObject; 1227 ti->foreign_exception_state = __cxa_thread_info::caught; 1228 } |
|
1183 // exceptionObject is the pointer to the _Unwind_Exception within the 1184 // __cxa_exception. The throw object is after this 1185 return ((char*)exceptionObject + sizeof(_Unwind_Exception)); 1186} 1187 1188 1189 1190/** 1191 * ABI function called when exiting a catch block. This will free the current 1192 * exception if it is no longer referenced in other catch blocks. 1193 */ 1194extern "C" void __cxa_end_catch() 1195{ 1196 // We can call the fast version here because the slow version is called in 1197 // __cxa_throw(), which must have been called before we end a catch block | 1229 // exceptionObject is the pointer to the _Unwind_Exception within the 1230 // __cxa_exception. The throw object is after this 1231 return ((char*)exceptionObject + sizeof(_Unwind_Exception)); 1232} 1233 1234 1235 1236/** 1237 * ABI function called when exiting a catch block. This will free the current 1238 * exception if it is no longer referenced in other catch blocks. 1239 */ 1240extern "C" void __cxa_end_catch() 1241{ 1242 // We can call the fast version here because the slow version is called in 1243 // __cxa_throw(), which must have been called before we end a catch block |
1198 __cxa_eh_globals *globals = __cxa_get_globals_fast(); | 1244 __cxa_thread_info *ti = thread_info_fast(); 1245 __cxa_eh_globals *globals = &ti->globals; |
1199 __cxa_exception *ex = globals->caughtExceptions; 1200 1201 assert(0 != ex && "Ending catch when no exception is on the stack!"); | 1246 __cxa_exception *ex = globals->caughtExceptions; 1247 1248 assert(0 != ex && "Ending catch when no exception is on the stack!"); |
1249 1250 if (ti->foreign_exception_state != __cxa_thread_info::none) 1251 { 1252 globals->caughtExceptions = 0; 1253 if (ti->foreign_exception_state != __cxa_thread_info::rethrown) 1254 { 1255 _Unwind_Exception *e = (_Unwind_Exception*)ti->globals.caughtExceptions; 1256 e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e); 1257 } 1258 ti->foreign_exception_state = __cxa_thread_info::none; 1259 return; 1260 } |
|
1202 1203 bool deleteException = true; 1204 1205 if (ex->handlerCount < 0) 1206 { 1207 // exception was rethrown. Exception should not be deleted even if 1208 // handlerCount become zero. 1209 // Code pattern: --- 113 unchanged lines hidden (view full) --- 1323 /** 1324 * Sets the function that will be called when an exception specification is 1325 * violated. 1326 */ 1327 unexpected_handler set_unexpected(unexpected_handler f) throw() 1328 { 1329 if (thread_local_handlers) { return pathscale::set_unexpected(f); } 1330 | 1261 1262 bool deleteException = true; 1263 1264 if (ex->handlerCount < 0) 1265 { 1266 // exception was rethrown. Exception should not be deleted even if 1267 // handlerCount become zero. 1268 // Code pattern: --- 113 unchanged lines hidden (view full) --- 1382 /** 1383 * Sets the function that will be called when an exception specification is 1384 * violated. 1385 */ 1386 unexpected_handler set_unexpected(unexpected_handler f) throw() 1387 { 1388 if (thread_local_handlers) { return pathscale::set_unexpected(f); } 1389 |
1331 return __sync_lock_test_and_set(&unexpectedHandler, f); | 1390 return ATOMIC_SWAP(&terminateHandler, f); |
1332 } 1333 /** 1334 * Sets the function that is called to terminate the program. 1335 */ 1336 terminate_handler set_terminate(terminate_handler f) throw() 1337 { 1338 if (thread_local_handlers) { return pathscale::set_terminate(f); } | 1391 } 1392 /** 1393 * Sets the function that is called to terminate the program. 1394 */ 1395 terminate_handler set_terminate(terminate_handler f) throw() 1396 { 1397 if (thread_local_handlers) { return pathscale::set_terminate(f); } |
1339 return __sync_lock_test_and_set(&terminateHandler, f); | 1398 1399 return ATOMIC_SWAP(&terminateHandler, f); |
1340 } 1341 /** 1342 * Terminates the program, calling a custom terminate implementation if 1343 * required. 1344 */ 1345 void terminate() 1346 { 1347 static __cxa_thread_info *info = thread_info_fast(); --- 37 unchanged lines hidden (view full) --- 1385 */ 1386 unexpected_handler get_unexpected() throw() 1387 { 1388 __cxa_thread_info *info = thread_info(); 1389 if (info->unexpectedHandler) 1390 { 1391 return info->unexpectedHandler; 1392 } | 1400 } 1401 /** 1402 * Terminates the program, calling a custom terminate implementation if 1403 * required. 1404 */ 1405 void terminate() 1406 { 1407 static __cxa_thread_info *info = thread_info_fast(); --- 37 unchanged lines hidden (view full) --- 1445 */ 1446 unexpected_handler get_unexpected() throw() 1447 { 1448 __cxa_thread_info *info = thread_info(); 1449 if (info->unexpectedHandler) 1450 { 1451 return info->unexpectedHandler; 1452 } |
1393 return unexpectedHandler; | 1453 return ATOMIC_LOAD(&unexpectedHandler); |
1394 } 1395 /** 1396 * Returns the current terminate handler. 1397 */ 1398 terminate_handler get_terminate() throw() 1399 { 1400 __cxa_thread_info *info = thread_info(); 1401 if (info->terminateHandler) 1402 { 1403 return info->terminateHandler; 1404 } | 1454 } 1455 /** 1456 * Returns the current terminate handler. 1457 */ 1458 terminate_handler get_terminate() throw() 1459 { 1460 __cxa_thread_info *info = thread_info(); 1461 if (info->terminateHandler) 1462 { 1463 return info->terminateHandler; 1464 } |
1405 return terminateHandler; | 1465 return ATOMIC_LOAD(&terminateHandler); |
1406 } 1407} 1408#ifdef __arm__ 1409extern "C" _Unwind_Exception *__cxa_get_cleanup(void) 1410{ 1411 __cxa_thread_info *info = thread_info_fast(); 1412 _Unwind_Exception *exceptionObject = info->currentCleanup; 1413 if (isCXXException(exceptionObject->exception_class)) --- 29 unchanged lines hidden --- | 1466 } 1467} 1468#ifdef __arm__ 1469extern "C" _Unwind_Exception *__cxa_get_cleanup(void) 1470{ 1471 __cxa_thread_info *info = thread_info_fast(); 1472 _Unwind_Exception *exceptionObject = info->currentCleanup; 1473 if (isCXXException(exceptionObject->exception_class)) --- 29 unchanged lines hidden --- |