Deleted Added
full compact
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 ---