ObjFW  Check-in [d55f62409f]

Overview
Comment:Don't use ARM EHABI if __ARM_DWARF_EH__ is defined
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: d55f62409f58c0e8b753eb9ae7015165f6f9446a1e9b143b77181ea297b4eae1
User & Date: js on 2016-06-08 23:05:01
Other Links: manifest | tags
Context
2016-06-08
23:17
lookup-asm-arm-elf.S: Add support for big endian check-in: 411f73bcf6 user: js tags: trunk
23:05
Don't use ARM EHABI if __ARM_DWARF_EH__ is defined check-in: d55f62409f user: js tags: trunk
2016-06-07
22:56
Add support for reusing OFStreams after close check-in: 1de551cb5f user: js tags: trunk
Changes

Modified src/exceptions/OFException.m from [cf73e10b2d] to [a913b4b6a3].

55
56
57
58
59
60
61




62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*
 * Define HAVE_DWARF_EXCEPTIONS if HAVE_SEH_EXCEPTIONS is defined, as SEH
 * exceptions are implemented as a wrapper around DWARF exceptions.
 */
#ifdef HAVE_SEH_EXCEPTIONS
# define HAVE_DWARF_EXCEPTIONS
#endif





#ifdef HAVE_DWARF_EXCEPTIONS
struct _Unwind_Context;
typedef enum {
	_URC_OK		  = 0,
	_URC_END_OF_STACK = 5
}_Unwind_Reason_Code;

struct backtrace_ctx {
	void **backtrace;
	uint8_t i;
};

extern _Unwind_Reason_Code _Unwind_Backtrace(
    _Unwind_Reason_Code(*)(struct _Unwind_Context*, void*), void*);
# ifdef OF_ARM
extern int _Unwind_VRS_Get(struct _Unwind_Context*, int, uint32_t, int, void*);
# else
extern uintptr_t _Unwind_GetIP(struct _Unwind_Context*);
# endif
#endif

#if !defined(HAVE_STRERROR_R) && defined(OF_HAVE_THREADS)
static of_mutex_t mutex;

static void __attribute__((__constructor__))







>
>
>
>















|
|

|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/*
 * Define HAVE_DWARF_EXCEPTIONS if HAVE_SEH_EXCEPTIONS is defined, as SEH
 * exceptions are implemented as a wrapper around DWARF exceptions.
 */
#ifdef HAVE_SEH_EXCEPTIONS
# define HAVE_DWARF_EXCEPTIONS
#endif

#if defined(OF_ARM) && !defined(__ARM_DWARF_EH__)
# define HAVE_ARM_EHABI_EXCEPTIONS
#endif

#ifdef HAVE_DWARF_EXCEPTIONS
struct _Unwind_Context;
typedef enum {
	_URC_OK		  = 0,
	_URC_END_OF_STACK = 5
}_Unwind_Reason_Code;

struct backtrace_ctx {
	void **backtrace;
	uint8_t i;
};

extern _Unwind_Reason_Code _Unwind_Backtrace(
    _Unwind_Reason_Code(*)(struct _Unwind_Context*, void*), void*);
# ifndef HAVE_ARM_EHABI_EXCEPTIONS
extern uintptr_t _Unwind_GetIP(struct _Unwind_Context*);
# else
extern int _Unwind_VRS_Get(struct _Unwind_Context*, int, uint32_t, int, void*);
# endif
#endif

#if !defined(HAVE_STRERROR_R) && defined(OF_HAVE_THREADS)
static of_mutex_t mutex;

static void __attribute__((__constructor__))
211
212
213
214
215
216
217


218
219
220
221
222
223
224
225
226
227
228
229
230
231
#ifdef HAVE_DWARF_EXCEPTIONS
static _Unwind_Reason_Code
backtrace_callback(struct _Unwind_Context *ctx, void *data)
{
	struct backtrace_ctx *bt = data;

	if (bt->i < OF_BACKTRACE_SIZE) {


# ifdef OF_ARM
		uintptr_t ip;

		_Unwind_VRS_Get(ctx, 0, 15, 0, &ip);
		bt->backtrace[bt->i++] = (void*)(ip & ~1);
# else
		bt->backtrace[bt->i++] = (void*)_Unwind_GetIP(ctx);
# endif
		return _URC_OK;
	}

	return _URC_END_OF_STACK;
}
#endif







>
>
|




<
<







215
216
217
218
219
220
221
222
223
224
225
226
227
228


229
230
231
232
233
234
235
#ifdef HAVE_DWARF_EXCEPTIONS
static _Unwind_Reason_Code
backtrace_callback(struct _Unwind_Context *ctx, void *data)
{
	struct backtrace_ctx *bt = data;

	if (bt->i < OF_BACKTRACE_SIZE) {
# ifndef HAVE_ARM_EHABI_EXCEPTIONS
		bt->backtrace[bt->i++] = (void*)_Unwind_GetIP(ctx);
# else
		uintptr_t ip;

		_Unwind_VRS_Get(ctx, 0, 15, 0, &ip);
		bt->backtrace[bt->i++] = (void*)(ip & ~1);


# endif
		return _URC_OK;
	}

	return _URC_END_OF_STACK;
}
#endif

Modified src/runtime/exception.m from [f01e2fc526] to [190697da2f].

34
35
36
37
38
39
40




41
42
43
44
45
46
47
# define _Unwind_RaiseException _Unwind_SjLj_RaiseException
# define __builtin_eh_return_data_regno(i) (i)
#elif defined(HAVE_SEH_EXCEPTIONS)
# define PERSONALITY gnu_objc_personality
#else
# error Unknown exception type!
#endif





static const uint64_t objc_exception_class = 0x474E55434F424A43; /* GNUCOBJC */

#define _UA_SEARCH_PHASE  0x01
#define _UA_CLEANUP_PHASE 0x02
#define _UA_HANDLER_FRAME 0x04
#define _UA_FORCE_UNWIND  0x08







>
>
>
>







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# define _Unwind_RaiseException _Unwind_SjLj_RaiseException
# define __builtin_eh_return_data_regno(i) (i)
#elif defined(HAVE_SEH_EXCEPTIONS)
# define PERSONALITY gnu_objc_personality
#else
# error Unknown exception type!
#endif

#if defined(OF_ARM) && !defined(__ARM_DWARF_EH__)
# define HAVE_ARM_EHABI_EXCEPTIONS
#endif

static const uint64_t objc_exception_class = 0x474E55434F424A43; /* GNUCOBJC */

#define _UA_SEARCH_PHASE  0x01
#define _UA_CLEANUP_PHASE 0x02
#define _UA_HANDLER_FRAME 0x04
#define _UA_FORCE_UNWIND  0x08
84
85
86
87
88
89
90

91









92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
	_URC_FAILURE		= 9
} _Unwind_Reason_Code;

struct objc_exception {
	struct _Unwind_Exception {
		uint64_t class;
		void (*cleanup)(_Unwind_Reason_Code, struct _Unwind_Exception*);

#ifdef OF_ARM









		/* From "Exception Handling ABI for the ARM(R) Architecture" */
		struct {
			uint32_t reserved1, reserved2, reserved3, reserved4;
			uint32_t reserved;
		} unwinder_cache;
		struct {
			uint32_t sp;
			uint32_t bitpattern[5];
		} barrier_cache;
		struct {
			uint32_t bitpattern[4];
		} cleanup_cache;
		struct {
			uint32_t fnstart;
			uint32_t *ehtp;
			uint32_t additional;
			uint32_t reserved1;
		} pr_cache;
		long long int : 0;
#else
# ifdef HAVE_SEH_EXCEPTIONS
		uint64_t private[6];
# else
		/*
		 * The Itanium Exception ABI says to have those and never touch
		 * them.
		 */
		uint64_t private1, private2;
# endif
#endif
	} exception;
	id object;
#ifndef OF_ARM
	uintptr_t landingpad;
	intptr_t filter;
#endif
};

struct lsda {
	uintptr_t region_start, landingpads_start;







>
|
>
>
>
>
>
>
>
>
>



















<
<
<
<
<
<
<
<
<
<



|







88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124










125
126
127
128
129
130
131
132
133
134
135
	_URC_FAILURE		= 9
} _Unwind_Reason_Code;

struct objc_exception {
	struct _Unwind_Exception {
		uint64_t class;
		void (*cleanup)(_Unwind_Reason_Code, struct _Unwind_Exception*);
#ifndef HAVE_ARM_EHABI_EXCEPTIONS
# ifdef HAVE_SEH_EXCEPTIONS
		uint64_t private[6];
# else
		/*
		 * The Itanium Exception ABI says to have those and never touch
		 * them.
		 */
		uint64_t private1, private2;
# endif
#else
		/* From "Exception Handling ABI for the ARM(R) Architecture" */
		struct {
			uint32_t reserved1, reserved2, reserved3, reserved4;
			uint32_t reserved;
		} unwinder_cache;
		struct {
			uint32_t sp;
			uint32_t bitpattern[5];
		} barrier_cache;
		struct {
			uint32_t bitpattern[4];
		} cleanup_cache;
		struct {
			uint32_t fnstart;
			uint32_t *ehtp;
			uint32_t additional;
			uint32_t reserved1;
		} pr_cache;
		long long int : 0;










#endif
	} exception;
	id object;
#ifndef HAVE_ARM_EHABI_EXCEPTIONS
	uintptr_t landingpad;
	intptr_t filter;
#endif
};

struct lsda {
	uintptr_t region_start, landingpads_start;
139
140
141
142
143
144
145


146




147
148
149
150
151
152
153
extern _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception*);
extern void _Unwind_DeleteException(struct _Unwind_Exception*);
extern void* _Unwind_GetLanguageSpecificData(struct _Unwind_Context*);
extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context*);
extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context*);
extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context*);



#ifdef OF_ARM




extern _Unwind_Reason_Code __gnu_unwind_frame(struct _Unwind_Exception*,
    struct _Unwind_Context*);
extern int _Unwind_VRS_Get(struct _Unwind_Context*, int, uint32_t, int, void*);
extern int _Unwind_VRS_Set(struct _Unwind_Context*, int, uint32_t, int, void*);

# define CONTINUE_UNWIND					\
	{							\







>
>
|
>
>
>
>







143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
extern _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception*);
extern void _Unwind_DeleteException(struct _Unwind_Exception*);
extern void* _Unwind_GetLanguageSpecificData(struct _Unwind_Context*);
extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context*);
extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context*);
extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context*);

#ifndef HAVE_ARM_EHABI_EXCEPTIONS
# define CONTINUE_UNWIND return _URC_CONTINUE_UNWIND

extern uintptr_t _Unwind_GetIP(struct _Unwind_Context*);
extern void _Unwind_SetIP(struct _Unwind_Context*, uintptr_t);
extern void _Unwind_SetGR(struct _Unwind_Context*, int, uintptr_t);
#else
extern _Unwind_Reason_Code __gnu_unwind_frame(struct _Unwind_Exception*,
    struct _Unwind_Context*);
extern int _Unwind_VRS_Get(struct _Unwind_Context*, int, uint32_t, int, void*);
extern int _Unwind_VRS_Set(struct _Unwind_Context*, int, uint32_t, int, void*);

# define CONTINUE_UNWIND					\
	{							\
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

static inline void
_Unwind_SetIP(struct _Unwind_Context *ctx, uintptr_t value)
{
	uintptr_t thumb = _Unwind_GetGR(ctx, 15) & 1;
	_Unwind_SetGR(ctx, 15, (value | thumb));
}
#else
# define CONTINUE_UNWIND return _URC_CONTINUE_UNWIND

extern uintptr_t _Unwind_GetIP(struct _Unwind_Context*);
extern void _Unwind_SetIP(struct _Unwind_Context*, uintptr_t);
extern void _Unwind_SetGR(struct _Unwind_Context*, int, uintptr_t);
#endif

#ifdef HAVE_SEH_EXCEPTIONS
extern EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void*,
    PCONTEXT, PDISPATCHER_CONTEXT, _Unwind_Reason_Code(*)(int, int, uint64_t,
    struct _Unwind_Exception*, struct _Unwind_Context*));
#endif







<
<
<
<
<
<







189
190
191
192
193
194
195






196
197
198
199
200
201
202

static inline void
_Unwind_SetIP(struct _Unwind_Context *ctx, uintptr_t value)
{
	uintptr_t thumb = _Unwind_GetGR(ctx, 15) & 1;
	_Unwind_SetGR(ctx, 15, (value | thumb));
}






#endif

#ifdef HAVE_SEH_EXCEPTIONS
extern EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void*,
    PCONTEXT, PDISPATCHER_CONTEXT, _Unwind_Reason_Code(*)(int, int, uint64_t,
    struct _Unwind_Exception*, struct _Unwind_Context*));
#endif
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
		abort();
	}
#undef READ

	return value;
}

#ifndef OF_ARM
static uint64_t
resolve_value(uint64_t value, uint8_t enc, const uint8_t *start, uint64_t base)
{
	if (value == 0)
		return 0;

	value += ((enc & 0x70) == DW_EH_PE_pcrel ? (uintptr_t)start : base);







|







316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
		abort();
	}
#undef READ

	return value;
}

#ifndef HAVE_ARM_EHABI_EXCEPTIONS
static uint64_t
resolve_value(uint64_t value, uint8_t enc, const uint8_t *start, uint64_t base)
{
	if (value == 0)
		return 0;

	value += ((enc & 0x70) == DW_EH_PE_pcrel ? (uintptr_t)start : base);
459
460
461
462
463
464
465


466






467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490

		if (filter > 0 && !(actions & _UA_FORCE_UNWIND) && !foreign) {
			Class class;
			const char *className;
			uintptr_t c;
			const uint8_t *tmp;



#ifdef OF_ARM






			tmp = lsda->typestable - (filter * 4);
			c = *(uintptr_t*)(void*)tmp;

			if (c != 0) {
				c += (uintptr_t)tmp;
# if defined(OF_LINUX) || defined(OF_NETBSD)
				c = *(uintptr_t*)c;
# endif
			}
#else
			uintptr_t i;

			i = filter * size_for_encoding(lsda->typestable_enc);
			tmp = lsda->typestable - i;
			c = (uintptr_t)read_value(lsda->typestable_enc, &tmp);
			c = (uintptr_t)resolve_value(c, lsda->typestable_enc,
			    lsda->typestable - i, lsda->typestable_base);
#endif

			className = (const char*)c;

			if (className != NULL && *className != '\0' &&
			    strcmp(className, "@id") != 0)
				class = objc_getRequiredClass(className);







>
>
|
>
>
>
>
>
>









<
<
<
<
<
<
<
<







463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487








488
489
490
491
492
493
494

		if (filter > 0 && !(actions & _UA_FORCE_UNWIND) && !foreign) {
			Class class;
			const char *className;
			uintptr_t c;
			const uint8_t *tmp;

#ifndef HAVE_ARM_EHABI_EXCEPTIONS
			uintptr_t i;

			i = filter * size_for_encoding(lsda->typestable_enc);
			tmp = lsda->typestable - i;
			c = (uintptr_t)read_value(lsda->typestable_enc, &tmp);
			c = (uintptr_t)resolve_value(c, lsda->typestable_enc,
			    lsda->typestable - i, lsda->typestable_base);
#else
			tmp = lsda->typestable - (filter * 4);
			c = *(uintptr_t*)(void*)tmp;

			if (c != 0) {
				c += (uintptr_t)tmp;
# if defined(OF_LINUX) || defined(OF_NETBSD)
				c = *(uintptr_t*)c;
# endif
			}








#endif

			className = (const char*)c;

			if (className != NULL && *className != '\0' &&
			    strcmp(className, "@id") != 0)
				class = objc_getRequiredClass(className);
500
501
502
503
504
505
506

507







508
509
510
511
512
513
514
		else
			abort();
	} while (displacement != 0);

	return 0;
}


#ifdef OF_ARM







_Unwind_Reason_Code
PERSONALITY(uint32_t state, struct _Unwind_Exception *ex,
    struct _Unwind_Context *ctx)
{
	int version = 1;
	uint64_t ex_class = ex->class;
	int actions;







>
|
>
>
>
>
>
>
>







504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
		else
			abort();
	} while (displacement != 0);

	return 0;
}

#ifndef HAVE_ARM_EHABI_EXCEPTIONS
# ifdef HAVE_SEH_EXCEPTIONS
static
# endif
_Unwind_Reason_Code
PERSONALITY(int version, int actions, uint64_t ex_class,
    struct _Unwind_Exception *ex, struct _Unwind_Context *ctx)
{
#else
_Unwind_Reason_Code
PERSONALITY(uint32_t state, struct _Unwind_Exception *ex,
    struct _Unwind_Context *ctx)
{
	int version = 1;
	uint64_t ex_class = ex->class;
	int actions;
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
	case 2:	/* _US_UNWIND_FRAME_RESUME */
		CONTINUE_UNWIND;
	default:
		return _URC_FAILURE;
	}

	_Unwind_SetGR(ctx, 12, (uintptr_t)ex);
#else
# ifdef HAVE_SEH_EXCEPTIONS
static
# endif
_Unwind_Reason_Code
PERSONALITY(int version, int actions, uint64_t ex_class,
    struct _Unwind_Exception *ex, struct _Unwind_Context *ctx)
{
#endif
	struct objc_exception *e = (struct objc_exception*)ex;
	bool foreign = (ex_class != objc_exception_class);
	const uint8_t *lsda_addr, *actionrecords;
	struct lsda lsda;
	uintptr_t landingpad = 0;
	uint8_t found = 0;







<
<
<
<
<
<
<
<







537
538
539
540
541
542
543








544
545
546
547
548
549
550
	case 2:	/* _US_UNWIND_FRAME_RESUME */
		CONTINUE_UNWIND;
	default:
		return _URC_FAILURE;
	}

	_Unwind_SetGR(ctx, 12, (uintptr_t)ex);








#endif
	struct objc_exception *e = (struct objc_exception*)ex;
	bool foreign = (ex_class != objc_exception_class);
	const uint8_t *lsda_addr, *actionrecords;
	struct lsda lsda;
	uintptr_t landingpad = 0;
	uint8_t found = 0;
556
557
558
559
560
561
562
563




564
565
566
567
568
569
570
571
572
573
574
575
576
577
	if (actions & _UA_HANDLER_FRAME && !foreign) {
		/*
		 * For handlers, reg #0 must be the exception's object and reg
		 * #1 the filter.
		 */
		_Unwind_SetGR(ctx, __builtin_eh_return_data_regno(0),
		    (uintptr_t)e->object);
#ifdef OF_ARM




		_Unwind_SetGR(ctx, __builtin_eh_return_data_regno(1),
		    ex->barrier_cache.bitpattern[1]);
		_Unwind_SetIP(ctx, ex->barrier_cache.bitpattern[3]);
#else
		_Unwind_SetGR(ctx, __builtin_eh_return_data_regno(1),
		    e->filter);
		_Unwind_SetIP(ctx, e->landingpad);
#endif

		_Unwind_DeleteException(ex);

		return _URC_INSTALL_CONTEXT;
	}








|
>
>
>
>



<
<
<
<







560
561
562
563
564
565
566
567
568
569
570
571
572
573
574




575
576
577
578
579
580
581
	if (actions & _UA_HANDLER_FRAME && !foreign) {
		/*
		 * For handlers, reg #0 must be the exception's object and reg
		 * #1 the filter.
		 */
		_Unwind_SetGR(ctx, __builtin_eh_return_data_regno(0),
		    (uintptr_t)e->object);
#ifndef HAVE_ARM_EHABI_EXCEPTIONS
		_Unwind_SetGR(ctx, __builtin_eh_return_data_regno(1),
		    e->filter);
		_Unwind_SetIP(ctx, e->landingpad);
#else
		_Unwind_SetGR(ctx, __builtin_eh_return_data_regno(1),
		    ex->barrier_cache.bitpattern[1]);
		_Unwind_SetIP(ctx, ex->barrier_cache.bitpattern[3]);




#endif

		_Unwind_DeleteException(ex);

		return _URC_INSTALL_CONTEXT;
	}

594
595
596
597
598
599
600
601



602
603
604
605
606
607
608
609
610
611
612
613
614
		CONTINUE_UNWIND;

	if (actions & _UA_SEARCH_PHASE) {
		if (!(found & HANDLER_FOUND) || foreign)
			CONTINUE_UNWIND;

		/* Cache it so we don't have to search it again in phase 2 */
#ifdef OF_ARM



		ex->barrier_cache.sp = _Unwind_GetGR(ctx, 13);
		ex->barrier_cache.bitpattern[1] = filter;
		ex->barrier_cache.bitpattern[3] = landingpad;
#else
		e->landingpad = landingpad;
		e->filter = filter;
#endif

		return _URC_HANDLER_FOUND;
	} else if (actions & _UA_CLEANUP_PHASE) {
		if (!(found & CLEANUP_FOUND))
			CONTINUE_UNWIND;








|
>
>
>



<
<
<







598
599
600
601
602
603
604
605
606
607
608
609
610
611



612
613
614
615
616
617
618
		CONTINUE_UNWIND;

	if (actions & _UA_SEARCH_PHASE) {
		if (!(found & HANDLER_FOUND) || foreign)
			CONTINUE_UNWIND;

		/* Cache it so we don't have to search it again in phase 2 */
#ifndef HAVE_ARM_EHABI_EXCEPTIONS
		e->landingpad = landingpad;
		e->filter = filter;
#else
		ex->barrier_cache.sp = _Unwind_GetGR(ctx, 13);
		ex->barrier_cache.bitpattern[1] = filter;
		ex->barrier_cache.bitpattern[3] = landingpad;



#endif

		return _URC_HANDLER_FOUND;
	} else if (actions & _UA_CLEANUP_PHASE) {
		if (!(found & CLEANUP_FOUND))
			CONTINUE_UNWIND;