ObjFW  Check-in [ce6282e019]

Overview
Comment:Fix exceptions on 32 bit systems.

There still seems to be an issue with Clang on 32 bit systems, but it
works with GCC now.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: ce6282e019b46b7fd6b3c4fc9ec570498b6f7c1ee3152e2d4fee32b86a39ab63
User & Date: js on 2012-07-07 11:29:53
Other Links: manifest | tags
Context
2012-07-07
17:03
Use -funwind-tables to work around a clang bug. check-in: 5ca9e69394 user: js tags: trunk
11:29
Fix exceptions on 32 bit systems. check-in: ce6282e019 user: js tags: trunk
11:12
atomic.h: Add missing cast. check-in: 61d0a2e987 user: js tags: trunk
Changes

Modified src/runtime/exception.m from [775286f90c] to [467b03e18b].

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
	uintptr_t typestable_base;
	uint8_t callsites_enc;
	const uint8_t *callsites, *actiontable;
};

extern _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception*);
extern void* _Unwind_GetLanguageSpecificData(struct _Unwind_Context*);
extern uint64_t _Unwind_GetRegionStart(struct _Unwind_Context*);
extern uint64_t _Unwind_GetDataRelBase(struct _Unwind_Context*);
extern uint64_t _Unwind_GetTextRelBase(struct _Unwind_Context*);
extern uint64_t _Unwind_GetIP(struct _Unwind_Context*);
extern void _Unwind_SetIP(struct _Unwind_Context*, uint64_t);
extern void _Unwind_SetGR(struct _Unwind_Context*, int, uint64_t);
extern void _Unwind_DeleteException(struct _Unwind_Exception*);

static objc_uncaught_exception_handler uncaught_exception_handler;

static uint64_t
read_uleb128(const uint8_t **ptr)
{







|
|
|
|
|
|







86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
	uintptr_t typestable_base;
	uint8_t callsites_enc;
	const uint8_t *callsites, *actiontable;
};

extern _Unwind_Reason_Code _Unwind_RaiseException(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*);
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);
extern void _Unwind_DeleteException(struct _Unwind_Exception*);

static objc_uncaught_exception_handler uncaught_exception_handler;

static uint64_t
read_uleb128(const uint8_t **ptr)
{
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
{
	if (value == 0)
		return 0;

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

	if (enc & DW_EH_PE_indirect)
		value = *(uint64_t*)value;

	return value;
}

static void
read_lsda(struct _Unwind_Context *ctx, const uint8_t *ptr, struct lsda *lsda)
{
	uint8_t landingpads_start_enc;
	uintptr_t callsites_size;

	lsda->region_start = _Unwind_GetRegionStart(ctx);
	lsda->landingpads_start = lsda->region_start;
	lsda->typestable = NULL;

	if ((landingpads_start_enc = *ptr++) != DW_EH_PE_omit)
		lsda->landingpads_start =
		    read_value(landingpads_start_enc, &ptr);

	if ((lsda->typestable_enc = *ptr++) != DW_EH_PE_omit) {
		uintptr_t tmp = read_uleb128(&ptr);
		lsda->typestable = ptr + tmp;
	}

	lsda->typestable_base = get_base(ctx, lsda->typestable_enc);

	lsda->callsites_enc = *ptr++;
	callsites_size = read_uleb128(&ptr);
	lsda->callsites = ptr;

	lsda->actiontable = lsda->callsites + callsites_size;
}

static BOOL
find_callsite(struct _Unwind_Context *ctx, struct lsda *lsda,







|
















|


|






|







224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
{
	if (value == 0)
		return 0;

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

	if (enc & DW_EH_PE_indirect)
		value = *(uint64_t*)(uintptr_t)value;

	return value;
}

static void
read_lsda(struct _Unwind_Context *ctx, const uint8_t *ptr, struct lsda *lsda)
{
	uint8_t landingpads_start_enc;
	uintptr_t callsites_size;

	lsda->region_start = _Unwind_GetRegionStart(ctx);
	lsda->landingpads_start = lsda->region_start;
	lsda->typestable = NULL;

	if ((landingpads_start_enc = *ptr++) != DW_EH_PE_omit)
		lsda->landingpads_start =
		    (uintptr_t)read_value(landingpads_start_enc, &ptr);

	if ((lsda->typestable_enc = *ptr++) != DW_EH_PE_omit) {
		uintptr_t tmp = (uintptr_t)read_uleb128(&ptr);
		lsda->typestable = ptr + tmp;
	}

	lsda->typestable_base = get_base(ctx, lsda->typestable_enc);

	lsda->callsites_enc = *ptr++;
	callsites_size = (uintptr_t)read_uleb128(&ptr);
	lsda->callsites = ptr;

	lsda->actiontable = lsda->callsites + callsites_size;
}

static BOOL
find_callsite(struct _Unwind_Context *ctx, struct lsda *lsda,
273
274
275
276
277
278
279
280
281
282

283
284
285
286
287
288
289
290

	ptr = lsda->callsites;
	while (ptr < lsda->actiontable) {
		uintptr_t callsite_start, callsite_len, callsite_landingpad;
		uintptr_t callsite_action;

		callsite_start = lsda->region_start +
		    read_value(lsda->callsites_enc, &ptr);
		callsite_len = read_value(lsda->callsites_enc, &ptr);
		callsite_landingpad = read_value(lsda->callsites_enc, &ptr);

		callsite_action = read_uleb128(&ptr);

		/* We can stop if we passed IP, as the table is sorted */
		if (callsite_start >= ip)
			break;

		if (callsite_start + callsite_len >= ip) {
			if (callsite_landingpad != 0)







|
|
|
>
|







273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291

	ptr = lsda->callsites;
	while (ptr < lsda->actiontable) {
		uintptr_t callsite_start, callsite_len, callsite_landingpad;
		uintptr_t callsite_action;

		callsite_start = lsda->region_start +
		    (uintptr_t)read_value(lsda->callsites_enc, &ptr);
		callsite_len = (uintptr_t)read_value(lsda->callsites_enc, &ptr);
		callsite_landingpad =
		    (uintptr_t)read_value(lsda->callsites_enc, &ptr);
		callsite_action = (uintptr_t)read_uleb128(&ptr);

		/* We can stop if we passed IP, as the table is sorted */
		if (callsite_start >= ip)
			break;

		if (callsite_start + callsite_len >= ip) {
			if (callsite_landingpad != 0)
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
{
	uint8_t found = 0;
	const uint8_t *ptr;
	intptr_t filter, displacement;

	do {
		ptr = actionrecords;
		filter = read_sleb128(&ptr);

		/*
		 * Get the next action record. Since read_sleb128 modifies ptr,
		 * we first set the actionrecord to the current ptr and then
		 * add the displacement.
		 */
		actionrecords = ptr;
		displacement = read_sleb128(&ptr);
		actionrecords += displacement;

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

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

			class = (c != 0 ? objc_get_class((const char*)c) : Nil);

			if (class_matches(class, e->object)) {
				*filtervalue = filter;
				return (found | HANDLER_FOUND);







|







|









|
|







326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
{
	uint8_t found = 0;
	const uint8_t *ptr;
	intptr_t filter, displacement;

	do {
		ptr = actionrecords;
		filter = (intptr_t)read_sleb128(&ptr);

		/*
		 * Get the next action record. Since read_sleb128 modifies ptr,
		 * we first set the actionrecord to the current ptr and then
		 * add the displacement.
		 */
		actionrecords = ptr;
		displacement = (intptr_t)read_sleb128(&ptr);
		actionrecords += displacement;

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

			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);

			class = (c != 0 ? objc_get_class((const char*)c) : Nil);

			if (class_matches(class, e->object)) {
				*filtervalue = filter;
				return (found | HANDLER_FOUND);
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
	 */
	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),
		    __builtin_extend_pointer(e->object));
		_Unwind_SetGR(ctx, __builtin_eh_return_data_regno(1),
		    e->filter);
		_Unwind_SetIP(ctx, e->landingpad);

		return _URC_INSTALL_CONTEXT;
	}








|







391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
	 */
	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);
		_Unwind_SetGR(ctx, __builtin_eh_return_data_regno(1),
		    e->filter);
		_Unwind_SetIP(ctx, e->landingpad);

		return _URC_INSTALL_CONTEXT;
	}

430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
			e->filter = filter;
		}

		return _URC_HANDLER_FOUND;
	} else if (actions & _UA_CLEANUP_PHASE) {
		/* For cleanup, reg #0 must be the exception and reg #1 zero */
		_Unwind_SetGR(ctx, __builtin_eh_return_data_regno(0),
		    __builtin_extend_pointer(e));
		_Unwind_SetGR(ctx, __builtin_eh_return_data_regno(1), 0);
		_Unwind_SetIP(ctx, landingpad);

		return _URC_INSTALL_CONTEXT;
	}

	abort();







|







431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
			e->filter = filter;
		}

		return _URC_HANDLER_FOUND;
	} else if (actions & _UA_CLEANUP_PHASE) {
		/* For cleanup, reg #0 must be the exception and reg #1 zero */
		_Unwind_SetGR(ctx, __builtin_eh_return_data_regno(0),
		    (uintptr_t)e);
		_Unwind_SetGR(ctx, __builtin_eh_return_data_regno(1), 0);
		_Unwind_SetIP(ctx, landingpad);

		return _URC_INSTALL_CONTEXT;
	}

	abort();