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
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 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
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;
		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 =
		    read_value(landingpads_start_enc, &ptr);
		    (uintptr_t)read_value(landingpads_start_enc, &ptr);

	if ((lsda->typestable_enc = *ptr++) != DW_EH_PE_omit) {
		uintptr_t tmp = read_uleb128(&ptr);
		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 = read_uleb128(&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
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 +
		    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);
		    (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
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 = read_sleb128(&ptr);
		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 = read_sleb128(&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 = read_value(lsda->typestable_enc, &tmp);
			c = resolve_value(c, lsda->typestable_enc,
			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
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),
		    __builtin_extend_pointer(e->object));
		    (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
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),
		    __builtin_extend_pointer(e));
		    (uintptr_t)e);
		_Unwind_SetGR(ctx, __builtin_eh_return_data_regno(1), 0);
		_Unwind_SetIP(ctx, landingpad);

		return _URC_INSTALL_CONTEXT;
	}

	abort();