configure.ac (arm*-*-linux-gnueabi): Don't disable building of libobjc for ARM EABI Linux.
* configure.ac (arm*-*-linux-gnueabi): Don't disable building of libobjc for ARM EABI Linux. * configure: Regenerate. libobjc/ * exception.c (__objc_exception_class): Initialise as constant array for ARM EABI. Change macro to static const for non-ARM EABI. (ObjcException): Add note about structure layout. Remove landingPad and handlerSwitchValue for ARM EABI. (get_ttype_entry): Add __ARM_EABI_UNWINDER__ version of function. (CONTINUE_UNWINDING): Define for ARM EABI/otherwise cases. (PERSONALITY_FUNCTION): Use ARM EABI-specific arguments, and add ARM EABI unwinding support. (objc_exception_throw): Use memcpy to initialise exception class. From-SVN: r136215
This commit is contained in:
parent
d750887f5f
commit
3f6383d38b
|
@ -1,3 +1,8 @@
|
||||||
|
2008-05-30 Julian Brown <julian@codesourcery.com>
|
||||||
|
|
||||||
|
* configure.ac (arm*-*-linux-gnueabi): Don't disable building
|
||||||
|
of libobjc for ARM EABI Linux.
|
||||||
|
* configure: Regenerate.
|
||||||
|
|
||||||
2008-05-18 Xinliang David Li <davidxl@google.com>
|
2008-05-18 Xinliang David Li <davidxl@google.com>
|
||||||
|
|
||||||
|
|
|
@ -2309,7 +2309,6 @@ case "${target}" in
|
||||||
;;
|
;;
|
||||||
arm*-*-linux-gnueabi)
|
arm*-*-linux-gnueabi)
|
||||||
noconfigdirs="$noconfigdirs target-qthreads"
|
noconfigdirs="$noconfigdirs target-qthreads"
|
||||||
noconfigdirs="$noconfigdirs target-libobjc"
|
|
||||||
case ${with_newlib} in
|
case ${with_newlib} in
|
||||||
no) noconfigdirs="$noconfigdirs target-newlib target-libgloss"
|
no) noconfigdirs="$noconfigdirs target-newlib target-libgloss"
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -563,7 +563,6 @@ case "${target}" in
|
||||||
;;
|
;;
|
||||||
arm*-*-linux-gnueabi)
|
arm*-*-linux-gnueabi)
|
||||||
noconfigdirs="$noconfigdirs target-qthreads"
|
noconfigdirs="$noconfigdirs target-qthreads"
|
||||||
noconfigdirs="$noconfigdirs target-libobjc"
|
|
||||||
case ${with_newlib} in
|
case ${with_newlib} in
|
||||||
no) noconfigdirs="$noconfigdirs target-newlib target-libgloss"
|
no) noconfigdirs="$noconfigdirs target-newlib target-libgloss"
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -1,3 +1,16 @@
|
||||||
|
2008-05-30 Julian Brown <julian@codesourcery.com>
|
||||||
|
|
||||||
|
* exception.c (__objc_exception_class): Initialise as constant
|
||||||
|
array for ARM EABI. Change macro to static const for non-ARM EABI.
|
||||||
|
(ObjcException): Add note about structure layout. Remove landingPad
|
||||||
|
and handlerSwitchValue for ARM EABI.
|
||||||
|
(get_ttype_entry): Add __ARM_EABI_UNWINDER__ version
|
||||||
|
of function.
|
||||||
|
(CONTINUE_UNWINDING): Define for ARM EABI/otherwise cases.
|
||||||
|
(PERSONALITY_FUNCTION): Use ARM EABI-specific arguments, and add
|
||||||
|
ARM EABI unwinding support.
|
||||||
|
(objc_exception_throw): Use memcpy to initialise exception class.
|
||||||
|
|
||||||
2008-05-25 Alan Modra <amodra@bigpond.net.au>
|
2008-05-25 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
* encoding.c (strip_array_types): Rename from get_inner_array_type.
|
* encoding.c (strip_array_types): Rename from get_inner_array_type.
|
||||||
|
|
|
@ -31,16 +31,25 @@ Boston, MA 02110-1301, USA. */
|
||||||
#include "unwind-pe.h"
|
#include "unwind-pe.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __ARM_EABI_UNWINDER__
|
||||||
|
|
||||||
|
const _Unwind_Exception_Class __objc_exception_class
|
||||||
|
= {'G', 'N', 'U', 'C', 'O', 'B', 'J', 'C'};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
/* This is the exception class we report -- "GNUCOBJC". */
|
/* This is the exception class we report -- "GNUCOBJC". */
|
||||||
#define __objc_exception_class \
|
static const _Unwind_Exception_Class __objc_exception_class
|
||||||
((((((((_Unwind_Exception_Class) 'G' \
|
= ((((((((_Unwind_Exception_Class) 'G'
|
||||||
<< 8 | (_Unwind_Exception_Class) 'N') \
|
<< 8 | (_Unwind_Exception_Class) 'N')
|
||||||
<< 8 | (_Unwind_Exception_Class) 'U') \
|
<< 8 | (_Unwind_Exception_Class) 'U')
|
||||||
<< 8 | (_Unwind_Exception_Class) 'C') \
|
|
||||||
<< 8 | (_Unwind_Exception_Class) 'O') \
|
|
||||||
<< 8 | (_Unwind_Exception_Class) 'B') \
|
|
||||||
<< 8 | (_Unwind_Exception_Class) 'J') \
|
|
||||||
<< 8 | (_Unwind_Exception_Class) 'C')
|
<< 8 | (_Unwind_Exception_Class) 'C')
|
||||||
|
<< 8 | (_Unwind_Exception_Class) 'O')
|
||||||
|
<< 8 | (_Unwind_Exception_Class) 'B')
|
||||||
|
<< 8 | (_Unwind_Exception_Class) 'J')
|
||||||
|
<< 8 | (_Unwind_Exception_Class) 'C');
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This is the object that is passed around by the Objective C runtime
|
/* This is the object that is passed around by the Objective C runtime
|
||||||
to represent the exception in flight. */
|
to represent the exception in flight. */
|
||||||
|
@ -50,12 +59,18 @@ struct ObjcException
|
||||||
/* This bit is needed in order to interact with the unwind runtime. */
|
/* This bit is needed in order to interact with the unwind runtime. */
|
||||||
struct _Unwind_Exception base;
|
struct _Unwind_Exception base;
|
||||||
|
|
||||||
/* The actual object we want to throw. */
|
/* The actual object we want to throw. Note: must come immediately after
|
||||||
|
unwind header. */
|
||||||
id value;
|
id value;
|
||||||
|
|
||||||
|
#ifdef __ARM_EABI_UNWINDER__
|
||||||
|
/* Note: we use the barrier cache defined in the unwind control block for
|
||||||
|
ARM EABI. */
|
||||||
|
#else
|
||||||
/* Cache some internal unwind data between phase 1 and phase 2. */
|
/* Cache some internal unwind data between phase 1 and phase 2. */
|
||||||
_Unwind_Ptr landingPad;
|
_Unwind_Ptr landingPad;
|
||||||
int handlerSwitchValue;
|
int handlerSwitchValue;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,6 +121,24 @@ parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __ARM_EABI_UNWINDER__
|
||||||
|
|
||||||
|
static Class
|
||||||
|
get_ttype_entry (struct lsda_header_info *info, _uleb128_t i)
|
||||||
|
{
|
||||||
|
_Unwind_Ptr ptr;
|
||||||
|
|
||||||
|
ptr = (_Unwind_Ptr) (info->TType - (i * 4));
|
||||||
|
ptr = _Unwind_decode_target2 (ptr);
|
||||||
|
|
||||||
|
if (ptr)
|
||||||
|
return objc_get_class ((const char *) ptr);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
static Class
|
static Class
|
||||||
get_ttype_entry (struct lsda_header_info *info, _Unwind_Word i)
|
get_ttype_entry (struct lsda_header_info *info, _Unwind_Word i)
|
||||||
{
|
{
|
||||||
|
@ -122,6 +155,8 @@ get_ttype_entry (struct lsda_header_info *info, _Unwind_Word i)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Like unto the method of the same name on Object, but takes an id. */
|
/* Like unto the method of the same name on Object, but takes an id. */
|
||||||
/* ??? Does this bork the meta-type system? Can/should we look up an
|
/* ??? Does this bork the meta-type system? Can/should we look up an
|
||||||
isKindOf method on the id? */
|
isKindOf method on the id? */
|
||||||
|
@ -150,12 +185,32 @@ isKindOf (id value, Class target)
|
||||||
#define PERSONALITY_FUNCTION __gnu_objc_personality_v0
|
#define PERSONALITY_FUNCTION __gnu_objc_personality_v0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __ARM_EABI_UNWINDER__
|
||||||
|
|
||||||
|
#define CONTINUE_UNWINDING \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (__gnu_unwind_frame(ue_header, context) != _URC_OK) \
|
||||||
|
return _URC_FAILURE; \
|
||||||
|
return _URC_CONTINUE_UNWIND; \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
_Unwind_Reason_Code
|
||||||
|
PERSONALITY_FUNCTION (_Unwind_State state,
|
||||||
|
struct _Unwind_Exception *ue_header,
|
||||||
|
struct _Unwind_Context *context)
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
|
||||||
|
|
||||||
_Unwind_Reason_Code
|
_Unwind_Reason_Code
|
||||||
PERSONALITY_FUNCTION (int version,
|
PERSONALITY_FUNCTION (int version,
|
||||||
_Unwind_Action actions,
|
_Unwind_Action actions,
|
||||||
_Unwind_Exception_Class exception_class,
|
_Unwind_Exception_Class exception_class,
|
||||||
struct _Unwind_Exception *ue_header,
|
struct _Unwind_Exception *ue_header,
|
||||||
struct _Unwind_Context *context)
|
struct _Unwind_Context *context)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
struct ObjcException *xh = (struct ObjcException *) ue_header;
|
struct ObjcException *xh = (struct ObjcException *) ue_header;
|
||||||
|
|
||||||
|
@ -165,19 +220,65 @@ PERSONALITY_FUNCTION (int version,
|
||||||
const unsigned char *p;
|
const unsigned char *p;
|
||||||
_Unwind_Ptr landing_pad, ip;
|
_Unwind_Ptr landing_pad, ip;
|
||||||
int handler_switch_value;
|
int handler_switch_value;
|
||||||
int saw_cleanup = 0, saw_handler;
|
int saw_cleanup = 0, saw_handler, foreign_exception;
|
||||||
void *return_object;
|
void *return_object;
|
||||||
|
int ip_before_insn = 0;
|
||||||
|
|
||||||
|
#ifdef __ARM_EABI_UNWINDER__
|
||||||
|
_Unwind_Action actions;
|
||||||
|
|
||||||
|
switch (state & _US_ACTION_MASK)
|
||||||
|
{
|
||||||
|
case _US_VIRTUAL_UNWIND_FRAME:
|
||||||
|
actions = _UA_SEARCH_PHASE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _US_UNWIND_FRAME_STARTING:
|
||||||
|
actions = _UA_CLEANUP_PHASE;
|
||||||
|
if (!(state & _US_FORCE_UNWIND)
|
||||||
|
&& ue_header->barrier_cache.sp == _Unwind_GetGR (context, 13))
|
||||||
|
actions |= _UA_HANDLER_FRAME;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _US_UNWIND_FRAME_RESUME:
|
||||||
|
CONTINUE_UNWINDING;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
actions |= state & _US_FORCE_UNWIND;
|
||||||
|
|
||||||
|
/* TODO: Foreign exceptions need some attention (e.g. rethrowing doesn't
|
||||||
|
work). */
|
||||||
|
foreign_exception = 0;
|
||||||
|
|
||||||
|
/* The dwarf unwinder assumes the context structure holds things like the
|
||||||
|
function and LSDA pointers. The ARM implementation caches these in
|
||||||
|
the exception header (UCB). To avoid rewriting everything we make the
|
||||||
|
virtual IP register point at the UCB. */
|
||||||
|
ip = (_Unwind_Ptr) ue_header;
|
||||||
|
_Unwind_SetGR (context, 12, ip);
|
||||||
|
|
||||||
|
#else /* !__ARM_EABI_UNWINDER. */
|
||||||
/* Interface version check. */
|
/* Interface version check. */
|
||||||
if (version != 1)
|
if (version != 1)
|
||||||
return _URC_FATAL_PHASE1_ERROR;
|
return _URC_FATAL_PHASE1_ERROR;
|
||||||
|
|
||||||
|
foreign_exception = (exception_class != __objc_exception_class);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Shortcut for phase 2 found handler for domestic exception. */
|
/* Shortcut for phase 2 found handler for domestic exception. */
|
||||||
if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
|
if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
|
||||||
&& exception_class == __objc_exception_class)
|
&& !foreign_exception)
|
||||||
{
|
{
|
||||||
|
#ifdef __ARM_EABI_UNWINDER__
|
||||||
|
handler_switch_value = (int) ue_header->barrier_cache.bitpattern[1];
|
||||||
|
landing_pad = (_Unwind_Ptr) ue_header->barrier_cache.bitpattern[3];
|
||||||
|
#else
|
||||||
handler_switch_value = xh->handlerSwitchValue;
|
handler_switch_value = xh->handlerSwitchValue;
|
||||||
landing_pad = xh->landingPad;
|
landing_pad = xh->landingPad;
|
||||||
|
#endif
|
||||||
goto install_context;
|
goto install_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,12 +287,18 @@ PERSONALITY_FUNCTION (int version,
|
||||||
|
|
||||||
/* If no LSDA, then there are no handlers or cleanups. */
|
/* If no LSDA, then there are no handlers or cleanups. */
|
||||||
if (! language_specific_data)
|
if (! language_specific_data)
|
||||||
return _URC_CONTINUE_UNWIND;
|
CONTINUE_UNWINDING;
|
||||||
|
|
||||||
/* Parse the LSDA header. */
|
/* Parse the LSDA header. */
|
||||||
p = parse_lsda_header (context, language_specific_data, &info);
|
p = parse_lsda_header (context, language_specific_data, &info);
|
||||||
info.ttype_base = base_of_encoded_value (info.ttype_encoding, context);
|
info.ttype_base = base_of_encoded_value (info.ttype_encoding, context);
|
||||||
|
#ifdef HAVE_GETIPINFO
|
||||||
|
ip = _Unwind_GetIPInfo (context, &ip_before_insn);
|
||||||
|
#else
|
||||||
ip = _Unwind_GetIP (context) - 1;
|
ip = _Unwind_GetIP (context) - 1;
|
||||||
|
#endif
|
||||||
|
if (!ip_before_insn)
|
||||||
|
--ip;
|
||||||
landing_pad = 0;
|
landing_pad = 0;
|
||||||
action_record = 0;
|
action_record = 0;
|
||||||
handler_switch_value = 0;
|
handler_switch_value = 0;
|
||||||
|
@ -250,7 +357,7 @@ PERSONALITY_FUNCTION (int version,
|
||||||
/* If ip is not present in the table, C++ would call terminate. */
|
/* If ip is not present in the table, C++ would call terminate. */
|
||||||
/* ??? As with Java, it's perhaps better to tweek the LSDA to
|
/* ??? As with Java, it's perhaps better to tweek the LSDA to
|
||||||
that no-action is mapped to no-entry. */
|
that no-action is mapped to no-entry. */
|
||||||
return _URC_CONTINUE_UNWIND;
|
CONTINUE_UNWINDING;
|
||||||
|
|
||||||
found_something:
|
found_something:
|
||||||
saw_cleanup = 0;
|
saw_cleanup = 0;
|
||||||
|
@ -287,8 +394,7 @@ PERSONALITY_FUNCTION (int version,
|
||||||
|
|
||||||
/* During forced unwinding, we only run cleanups. With a
|
/* During forced unwinding, we only run cleanups. With a
|
||||||
foreign exception class, we have no class info to match. */
|
foreign exception class, we have no class info to match. */
|
||||||
else if ((actions & _UA_FORCE_UNWIND)
|
else if ((actions & _UA_FORCE_UNWIND) || foreign_exception)
|
||||||
|| exception_class != __objc_exception_class)
|
|
||||||
;
|
;
|
||||||
|
|
||||||
else if (ar_filter > 0)
|
else if (ar_filter > 0)
|
||||||
|
@ -318,18 +424,24 @@ PERSONALITY_FUNCTION (int version,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! saw_handler && ! saw_cleanup)
|
if (! saw_handler && ! saw_cleanup)
|
||||||
return _URC_CONTINUE_UNWIND;
|
CONTINUE_UNWINDING;
|
||||||
|
|
||||||
if (actions & _UA_SEARCH_PHASE)
|
if (actions & _UA_SEARCH_PHASE)
|
||||||
{
|
{
|
||||||
if (!saw_handler)
|
if (!saw_handler)
|
||||||
return _URC_CONTINUE_UNWIND;
|
CONTINUE_UNWINDING;
|
||||||
|
|
||||||
/* For domestic exceptions, we cache data from phase 1 for phase 2. */
|
/* For domestic exceptions, we cache data from phase 1 for phase 2. */
|
||||||
if (exception_class == __objc_exception_class)
|
if (!foreign_exception)
|
||||||
{
|
{
|
||||||
|
#ifdef __ARM_EABI_UNWINDER__
|
||||||
|
ue_header->barrier_cache.sp = _Unwind_GetGR (context, 13);
|
||||||
|
ue_header->barrier_cache.bitpattern[1] = (_uw) handler_switch_value;
|
||||||
|
ue_header->barrier_cache.bitpattern[3] = (_uw) landing_pad;
|
||||||
|
#else
|
||||||
xh->handlerSwitchValue = handler_switch_value;
|
xh->handlerSwitchValue = handler_switch_value;
|
||||||
xh->landingPad = landing_pad;
|
xh->landingPad = landing_pad;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return _URC_HANDLER_FOUND;
|
return _URC_HANDLER_FOUND;
|
||||||
}
|
}
|
||||||
|
@ -361,7 +473,9 @@ void
|
||||||
objc_exception_throw (id value)
|
objc_exception_throw (id value)
|
||||||
{
|
{
|
||||||
struct ObjcException *header = calloc (1, sizeof (*header));
|
struct ObjcException *header = calloc (1, sizeof (*header));
|
||||||
header->base.exception_class = __objc_exception_class;
|
|
||||||
|
memcpy (&header->base.exception_class, &__objc_exception_class,
|
||||||
|
sizeof (__objc_exception_class));
|
||||||
header->base.exception_cleanup = __objc_exception_cleanup;
|
header->base.exception_cleanup = __objc_exception_cleanup;
|
||||||
header->value = value;
|
header->value = value;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue