comparison tango-0.99.9.patch @ 1650:40bd4a0d4870

Update to work with LLVM 2.7. Removed use of dyn_cast, llvm no compiles without exceptions and rtti by default. We do need exceptions for the libconfig stuff, but rtti isn't necessary (anymore). Debug info needs to be rewritten, as in LLVM 2.7 the format has completely changed. To have something to look at while rewriting, the old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means that you have to define this to compile at the moment. Updated tango 0.99.9 patch to include updated EH runtime code, which is needed for LLVM 2.7 as well.
author Tomas Lindquist Olsen
date Wed, 19 May 2010 12:42:32 +0200
parents 5c0cebff9be8
children
comparison
equal deleted inserted replaced
1649:36da40ecbbe0 1650:40bd4a0d4870
1 Index: tango/core/rt/compiler/ldc/rt/lifetime.d 1 Index: tango/core/rt/compiler/ldc/rt/lifetime.d
2 =================================================================== 2 ===================================================================
3 --- tango/core/rt/compiler/ldc/rt/lifetime.d (revision 5368) 3 --- tango/core/rt/compiler/ldc/rt/lifetime.d (revision 5462)
4 +++ tango/core/rt/compiler/ldc/rt/lifetime.d (working copy) 4 +++ tango/core/rt/compiler/ldc/rt/lifetime.d (working copy)
5 @@ -786,6 +786,7 @@ 5 @@ -786,6 +786,7 @@
6 return *cast(long*)px; 6 return *cast(long*)px;
7 } 7 }
8 8
51 51
52 +/+ 52 +/+
53 53
54 /** 54 /**
55 * 55 *
56 Index: tango/core/rt/compiler/ldc/rt/eh.d
57 ===================================================================
58 --- tango/core/rt/compiler/ldc/rt/eh.d (revision 5462)
59 +++ tango/core/rt/compiler/ldc/rt/eh.d (working copy)
60 @@ -1,38 +1,34 @@
61 /**
62 * This module contains functions and structures required for
63 - * exception handling.
64 + * dwarf exception handling with llvm
65 */
66 module rt.eh;
67
68 -import ldc.cstdarg;
69 -import rt.compiler.util.console;
70 +//debug = EH_personality;
71
72 -// debug = EH_personality;
73 -
74 // current EH implementation works on x86
75 // if it has a working unwind runtime
76 version(X86) {
77 version(linux) version=X86_UNWIND;
78 version(darwin) version=X86_UNWIND;
79 version(solaris) version=X86_UNWIND;
80 - version(freebsd) version=X86_UNWIND;
81 }
82 version(X86_64) {
83 version(linux) version=X86_UNWIND;
84 version(darwin) version=X86_UNWIND;
85 version(solaris) version=X86_UNWIND;
86 - version(freebsd) version=X86_UNWIND;
87 }
88
89 //version = HP_LIBUNWIND;
90
91 private extern(C) void abort();
92 private extern(C) int printf(char*, ...);
93 -private extern(C) int vprintf(char*, va_list va);
94 +//private extern(C) int vprintf(char*, va_list va);
95
96 // D runtime functions
97 extern(C) {
98 - int _d_isbaseof(ClassInfo oc, ClassInfo c);
99 +// int _d_isbaseof(ClassInfo oc, ClassInfo c);
100 + Object _d_dynamic_cast(Object o, ClassInfo c);
101 }
102
103 // libunwind headers
104 @@ -74,16 +70,19 @@
105 // interface to HP's libunwind from http://www.nongnu.org/libunwind/
106 version(HP_LIBUNWIND)
107 {
108 + // Haven't checked whether and how it has _Unwind_Get{Text,Data}RelBase
109 + pragma (msg, "HP_LIBUNWIND interface is out of date and untested");
110 +
111 void __libunwind_Unwind_Resume(_Unwind_Exception *);
112 _Unwind_Reason_Code __libunwind_Unwind_RaiseException(_Unwind_Exception *);
113 ptrdiff_t __libunwind_Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr
114 context);
115 - ptrdiff_t __libunwind_Unwind_GetIP(_Unwind_Context_Ptr context);
116 + size_t __libunwind_Unwind_GetIP(_Unwind_Context_Ptr context);
117 ptrdiff_t __libunwind_Unwind_SetIP(_Unwind_Context_Ptr context,
118 ptrdiff_t new_value);
119 ptrdiff_t __libunwind_Unwind_SetGR(_Unwind_Context_Ptr context, int index,
120 ptrdiff_t new_value);
121 - ptrdiff_t __libunwind_Unwind_GetRegionStart(_Unwind_Context_Ptr context);
122 + size_t __libunwind_Unwind_GetRegionStart(_Unwind_Context_Ptr context);
123
124 alias __libunwind_Unwind_Resume _Unwind_Resume;
125 alias __libunwind_Unwind_RaiseException _Unwind_RaiseException;
126 @@ -94,27 +93,30 @@
127 alias __libunwind_Unwind_SetGR _Unwind_SetGR;
128 alias __libunwind_Unwind_GetRegionStart _Unwind_GetRegionStart;
129 }
130 -else version(X86_UNWIND)
131 +else version(X86_UNWIND)
132 {
133 void _Unwind_Resume(_Unwind_Exception*);
134 _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*);
135 ptrdiff_t _Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr context);
136 - ptrdiff_t _Unwind_GetIP(_Unwind_Context_Ptr context);
137 + size_t _Unwind_GetIP(_Unwind_Context_Ptr context);
138 ptrdiff_t _Unwind_SetIP(_Unwind_Context_Ptr context, ptrdiff_t new_value);
139 ptrdiff_t _Unwind_SetGR(_Unwind_Context_Ptr context, int index,
140 ptrdiff_t new_value);
141 - ptrdiff_t _Unwind_GetRegionStart(_Unwind_Context_Ptr context);
142 + size_t _Unwind_GetRegionStart(_Unwind_Context_Ptr context);
143 +
144 + size_t _Unwind_GetTextRelBase(_Unwind_Context_Ptr);
145 + size_t _Unwind_GetDataRelBase(_Unwind_Context_Ptr);
146 }
147 else
148 {
149 // runtime calls these directly
150 void _Unwind_Resume(_Unwind_Exception*)
151 {
152 - console("_Unwind_Resume is not implemented on this platform.\n");
153 + printf("_Unwind_Resume is not implemented on this platform.\n");
154 }
155 _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*)
156 {
157 - console("_Unwind_RaiseException is not implemented on this platform.\n");
158 + printf("_Unwind_RaiseException is not implemented on this platform.\n");
159 return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
160 }
161 }
162 @@ -122,14 +124,161 @@
163 }
164
165 // error and exit
166 -extern(C) private void fatalerror(char[] format)
167 +extern(C) private void fatalerror(char* format, ...)
168 {
169 - printf("Fatal error in EH code: %.*s\n", format.length, format.ptr);
170 +// va_list args;
171 +// va_start(args, format);
172 + printf("Fatal error in EH code: ");
173 +// vprintf(format, args);
174 + printf("\n");
175 abort();
176 }
177
178
179 -// helpers for reading certain DWARF data
180 +// DWARF EH encoding enum
181 +// See e.g. http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/dwarfext.html
182 +private enum : ubyte {
183 + DW_EH_PE_omit = 0xff, // value is not present
184 +
185 + // value format
186 + DW_EH_PE_absptr = 0x00, // literal pointer
187 + DW_EH_PE_uleb128 = 0x01,
188 + DW_EH_PE_udata2 = 0x02, // unsigned 2-byte
189 + DW_EH_PE_udata4 = 0x03,
190 + DW_EH_PE_udata8 = 0x04,
191 + DW_EH_PE_sleb128 = 0x09,
192 + DW_EH_PE_sdata2 = 0x0a,
193 + DW_EH_PE_sdata4 = 0x0b,
194 + DW_EH_PE_sdata8 = 0x0c,
195 +
196 + // value meaning
197 + DW_EH_PE_pcrel = 0x10, // relative to program counter
198 + DW_EH_PE_textrel = 0x20, // relative to .text
199 + DW_EH_PE_datarel = 0x30, // relative to .got or .eh_frame_hdr
200 + DW_EH_PE_funcrel = 0x40, // relative to beginning of function
201 + DW_EH_PE_aligned = 0x50, // is an aligned void*
202 +
203 + // value is a pointer to the actual value
204 + // this is a mask on top of one of the above
205 + DW_EH_PE_indirect = 0x80
206 +}
207 +
208 +// Helpers for reading DWARF data
209 +
210 +// Given an encoding and a context, return the base to which the encoding is
211 +// relative
212 +private size_t base_of_encoded(_Unwind_Context_Ptr context, ubyte encoding)
213 +{
214 + if (encoding == DW_EH_PE_omit)
215 + return 0;
216 +
217 + switch (encoding & 0x70) // ignore DW_EH_PE_indirect
218 + {
219 + case DW_EH_PE_absptr, DW_EH_PE_pcrel, DW_EH_PE_aligned:
220 + return 0;
221 +
222 + case DW_EH_PE_textrel: return _Unwind_GetTextRelBase(context);
223 + case DW_EH_PE_datarel: return _Unwind_GetDataRelBase(context);
224 + case DW_EH_PE_funcrel: return _Unwind_GetRegionStart(context);
225 +
226 + default: fatalerror("Unrecognized base for DWARF value");
227 + }
228 +}
229 +
230 +// Only defined for fixed-size encodings
231 +private size_t size_of_encoded(ubyte encoding)
232 +{
233 + if (encoding == DW_EH_PE_omit)
234 + return 0;
235 +
236 + switch (encoding & 0x07) // ignore leb128
237 + {
238 + case DW_EH_PE_absptr: return (void*).sizeof;
239 + case DW_EH_PE_udata2: return 2;
240 + case DW_EH_PE_udata4: return 4;
241 + case DW_EH_PE_udata8: return 8;
242 +
243 + default: fatalerror("Unrecognized fixed-size DWARF value encoding");
244 + }
245 +}
246 +
247 +// Actual value readers below: read a value from the given ubyte* into the
248 +// output parameter and return the pointer incremented past the value.
249 +
250 +// Like read_encoded_with_base but gets the base from the given context
251 +private ubyte* read_encoded(_Unwind_Context_Ptr context, ubyte encoding, ubyte* p, out size_t val)
252 +{
253 + return read_encoded_with_base(encoding, base_of_encoded(context, encoding), p, val);
254 +}
255 +
256 +private ubyte* read_encoded_with_base(ubyte encoding, size_t base, ubyte* p, out size_t val)
257 +{
258 + if (encoding == DW_EH_PE_aligned)
259 + {
260 + auto a = cast(size_t)p;
261 + a = (a + (void*).sizeof - 1) & -(void*).sizeof;
262 + val = *cast(size_t*)a;
263 + return cast(ubyte*)(a + (void*).sizeof);
264 + }
265 +
266 + union U
267 + {
268 + size_t ptr;
269 + ushort udata2;
270 + uint udata4;
271 + ulong udata8;
272 + short sdata2;
273 + int sdata4;
274 + long sdata8;
275 + }
276 +
277 + auto u = cast(U*)p;
278 +
279 + size_t result;
280 +
281 + switch (encoding & 0x0f)
282 + {
283 + case DW_EH_PE_absptr:
284 + result = u.ptr;
285 + p += (void*).sizeof;
286 + break;
287 +
288 + case DW_EH_PE_uleb128:
289 + {
290 + p = get_uleb128(p, result);
291 + break;
292 + }
293 + case DW_EH_PE_sleb128:
294 + {
295 + ptrdiff_t sleb128;
296 + p = get_sleb128(p, sleb128);
297 + result = cast(size_t)sleb128;
298 + break;
299 + }
300 +
301 + case DW_EH_PE_udata2: result = cast(size_t)u.udata2; p += 2; break;
302 + case DW_EH_PE_udata4: result = cast(size_t)u.udata4; p += 4; break;
303 + case DW_EH_PE_udata8: result = cast(size_t)u.udata8; p += 8; break;
304 + case DW_EH_PE_sdata2: result = cast(size_t)u.sdata2; p += 2; break;
305 + case DW_EH_PE_sdata4: result = cast(size_t)u.sdata4; p += 4; break;
306 + case DW_EH_PE_sdata8: result = cast(size_t)u.sdata8; p += 8; break;
307 +
308 + default: fatalerror("Unrecognized DWARF value encoding format");
309 + }
310 + if (result)
311 + {
312 + if ((encoding & 0x70) == DW_EH_PE_pcrel)
313 + result += cast(size_t)u;
314 + else
315 + result += base;
316 +
317 + if (encoding & DW_EH_PE_indirect)
318 + result = *cast(size_t*)result;
319 + }
320 + val = result;
321 + return p;
322 +}
323 +
324 private ubyte* get_uleb128(ubyte* addr, ref size_t res)
325 {
326 res = 0;
327 @@ -137,7 +286,7 @@
328
329 // read as long as high bit is set
330 while(*addr & 0x80) {
331 - res |= (*addr & 0x7f) << bitsize;
332 + res |= (*addr & 0x7fU) << bitsize;
333 bitsize += 7;
334 addr += 1;
335 if(bitsize >= size_t.sizeof*8)
336 @@ -153,12 +302,12 @@
337
338 private ubyte* get_sleb128(ubyte* addr, ref ptrdiff_t res)
339 {
340 - res = 0;
341 + size_t tres = 0;
342 size_t bitsize = 0;
343
344 // read as long as high bit is set
345 while(*addr & 0x80) {
346 - res |= (*addr & 0x7f) << bitsize;
347 + tres |= (*addr & 0x7fU) << bitsize;
348 bitsize += 7;
349 addr += 1;
350 if(bitsize >= size_t.sizeof*8)
351 @@ -167,12 +316,14 @@
352 // read last
353 if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize)
354 fatalerror("tried to read sleb128 that exceeded size of size_t");
355 - res |= (*addr) << bitsize;
356 + tres |= (*addr) << bitsize;
357
358 // take care of sign
359 - if(bitsize < size_t.sizeof*8 && ((*addr) & 0x40))
360 - res |= cast(ptrdiff_t)(-1) ^ ((1 << (bitsize+7)) - 1);
361 + if(bitsize < size_t.sizeof*8 && (*addr & 0x40U) != 0)
362 + tres |= cast(size_t)(-1) ^ ((1 << (bitsize+7)) - 1);
363
364 + res = cast(ptrdiff_t)tres;
365 +
366 return addr + 1;
367 }
368
369 @@ -190,8 +341,7 @@
370
371 // the 8-byte string identifying the type of exception
372 // the first 4 are for vendor, the second 4 for language
373 -//TODO: This may be the wrong way around
374 -const char[8] _d_exception_class = "LLDCD1\0\0";
375 +const char[8] _d_exception_class = "LDC_D_10";
376
377
378 //
379 @@ -201,118 +351,174 @@
380 version(X86_UNWIND)
381 {
382
383 +// Various stuff we need
384 +struct Region
385 +{
386 + ubyte* callsite_table;
387 + ubyte* action_table;
388 +
389 + // Note: classinfo_table points past the end of the table
390 + ubyte* classinfo_table;
391 +
392 + size_t start;
393 + size_t lpStart_base; // landing pad base
394 +
395 + ubyte ttypeEnc;
396 + size_t ttype_base; // typeinfo base
397 +
398 + ubyte callSiteEnc;
399 +}
400 +
401 // the personality routine gets called by the unwind handler and is responsible for
402 // reading the EH tables and deciding what to do
403 extern(C) _Unwind_Reason_Code _d_eh_personality(int ver, _Unwind_Action actions, ulong exception_class, _Unwind_Exception* exception_info, _Unwind_Context_Ptr context)
404 {
405 + debug(EH_personality) printf("Entering personality routine, context=%p\n", context);
406 // check ver: the C++ Itanium ABI only allows ver == 1
407 if(ver != 1)
408 + {
409 + debug(EH_personality) printf("eh version mismatch\n");
410 return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
411 + }
412
413 // check exceptionClass
414 //TODO: Treat foreign exceptions with more respect
415 - if((cast(char*)&exception_class)[0..8] != _d_exception_class)
416 + auto wanted_ec = *cast(ulong*)_d_exception_class.ptr;
417 + if(exception_class != wanted_ec)
418 + {
419 + debug(EH_personality) printf("exception class mismatch %p vs %p\n", exception_class, wanted_ec);
420 return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
421 + }
422
423 // find call site table, action table and classinfo table
424 // Note: callsite and action tables do not contain static-length
425 // data and will be parsed as needed
426 - // Note: classinfo_table points past the end of the table
427 - ubyte* callsite_table;
428 - ubyte* action_table;
429 - ClassInfo* classinfo_table;
430 - _d_getLanguageSpecificTables(context, callsite_table, action_table, classinfo_table);
431 - if (!callsite_table)
432 +
433 + Region region;
434 +
435 + _d_getLanguageSpecificTables(context, region);
436 +
437 + // workaround. this should not happen
438 + if (!region.callsite_table)
439 + {
440 + debug(EH_personality) printf("callsite_table is null\n");
441 return _Unwind_Reason_Code.CONTINUE_UNWIND;
442 + }
443
444 + debug(EH_personality) printf("yay, checking\n");
445 + debug(EH_personality) printf("region.start = %p\n", region.start);
446 +
447 /*
448 find landing pad and action table index belonging to ip by walking
449 the callsite_table
450 */
451 - ubyte* callsite_walker = callsite_table;
452 + ubyte* callsite_walker = region.callsite_table;
453 + debug(EH_personality) printf("callsite table at: %p\n", region.callsite_table);
454 + debug(EH_personality) printf("action table at: %p\n", region.action_table);
455 + debug(EH_personality) printf("rtti table at %p\n", region.classinfo_table);
456
457 // get the instruction pointer
458 // will be used to find the right entry in the callsite_table
459 // -1 because it will point past the last instruction
460 - ptrdiff_t ip = _Unwind_GetIP(context) - 1;
461 + debug(EH_personality) printf("check1\n");
462 + size_t ip = _Unwind_GetIP(context) - 1;
463 + debug(EH_personality) printf("check2\n");
464
465 - // address block_start is relative to
466 - ptrdiff_t region_start = _Unwind_GetRegionStart(context);
467 -
468 // table entries
469 - uint block_start_offset, block_size;
470 - ptrdiff_t landing_pad;
471 + size_t landing_pad;
472 size_t action_offset;
473
474 while(true) {
475 // if we've gone through the list and found nothing...
476 - if(callsite_walker >= action_table)
477 + if(callsite_walker >= region.action_table)
478 + {
479 + debug(EH_personality) printf("found nothing\n");
480 return _Unwind_Reason_Code.CONTINUE_UNWIND;
481 + }
482
483 - block_start_offset = *cast(uint*)callsite_walker;
484 - block_size = *(cast(uint*)callsite_walker + 1);
485 - landing_pad = *(cast(uint*)callsite_walker + 2);
486 - if(landing_pad)
487 - landing_pad += region_start;
488 - callsite_walker = get_uleb128(callsite_walker + 3*uint.sizeof, action_offset);
489 + size_t block_start, block_size;
490
491 - debug(EH_personality_verbose) printf("ip=%llx %d %d %llx\n", ip, block_start_offset, block_size, landing_pad);
492 + callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, block_start);
493 + callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, block_size);
494 + callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, landing_pad);
495 + callsite_walker = get_uleb128(callsite_walker, action_offset);
496
497 + debug(EH_personality) printf("*block start offset = %p\n", block_start);
498 + debug(EH_personality) printf(" block size = %p\n", block_size);
499 + debug(EH_personality) printf(" landing pad = %p\n", landing_pad);
500 + debug(EH_personality) printf(" ip=%p %p %p %p\n", ip, block_start, block_size, landing_pad);
501 +
502 // since the list is sorted, as soon as we're past the ip
503 // there's no handler to be found
504 - if(ip < region_start + block_start_offset)
505 + if(ip < region.start + block_start)
506 + {
507 + debug(EH_personality) printf("found nothing2\n");
508 return _Unwind_Reason_Code.CONTINUE_UNWIND;
509 + }
510
511 + if(landing_pad)
512 + landing_pad += region.lpStart_base;
513 +
514 // if we've found our block, exit
515 - if(ip < region_start + block_start_offset + block_size)
516 + if(ip < region.start + block_start + block_size)
517 break;
518 }
519
520 - debug(EH_personality) printf("Found correct landing pad and actionOffset %d\n", action_offset);
521 + debug(EH_personality) printf("Found correct landing pad %p and actionOffset %p\n", landing_pad, action_offset);
522
523 // now we need the exception's classinfo to find a handler
524 // the exception_info is actually a member of a larger _d_exception struct
525 // the runtime allocated. get that now
526 - _d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - _d_exception.unwind_info.offsetof);
527 + _d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - size_t.sizeof); //_d_exception.unwind_info.offsetof);
528
529 // if there's no action offset and no landing pad, continue unwinding
530 if(!action_offset && !landing_pad)
531 return _Unwind_Reason_Code.CONTINUE_UNWIND;
532
533 // if there's no action offset but a landing pad, this is a cleanup handler
534 - else if(!action_offset && landing_pad)
535 - return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context);
536 + else if(!action_offset && landing_pad != 0)
537 + {
538 + debug(EH_personality) printf("installing finally context\n");
539 + return _d_eh_install_finally_context(actions, cast(ptrdiff_t)landing_pad, exception_struct, context);
540 + }
541
542 /*
543 walk action table chain, comparing classinfos using _d_isbaseof
544 */
545 - ubyte* action_walker = action_table + action_offset - 1;
546 + ubyte* action_walker = region.action_table + action_offset - 1;
547
548 - ptrdiff_t ti_offset, next_action_offset;
549 while(true) {
550 + ptrdiff_t ti_offset, next_action_offset;
551 +
552 action_walker = get_sleb128(action_walker, ti_offset);
553 // it is intentional that we not modify action_walker here
554 // next_action_offset is from current action_walker position
555 get_sleb128(action_walker, next_action_offset);
556
557 // negative are 'filters' which we don't use
558 - if(!(ti_offset >= 0))
559 + if(ti_offset < 0)
560 fatalerror("Filter actions are unsupported");
561
562 // zero means cleanup, which we require to be the last action
563 if(ti_offset == 0) {
564 - if(!(next_action_offset == 0))
565 + if(next_action_offset != 0)
566 fatalerror("Cleanup action must be last in chain");
567 - return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context);
568 + return _d_eh_install_finally_context(actions, cast(ptrdiff_t)landing_pad, exception_struct, context);
569 }
570
571 // get classinfo for action and check if the one in the
572 // exception structure is a base
573 - ClassInfo catch_ci = *(classinfo_table - ti_offset);
574 - debug(EH_personality) printf("Comparing catch %s to exception %s\n", catch_ci.name.ptr, exception_struct.exception_object.classinfo.name.ptr);
575 - if(_d_isbaseof(exception_struct.exception_object.classinfo, catch_ci))
576 - return _d_eh_install_catch_context(actions, ti_offset, landing_pad, exception_struct, context);
577 + size_t typeinfo;
578 + auto filter = cast(size_t)ti_offset * size_of_encoded(region.ttypeEnc);
579 + read_encoded_with_base(region.ttypeEnc, region.ttype_base, region.classinfo_table - filter, typeinfo);
580
581 + debug(EH_personality)
582 + printf("classinfo at %zx (enc %zx (size %zx) base %zx ptr %zx)\n", typeinfo, region.ttypeEnc, size_of_encoded(region.ttypeEnc), region.ttype_base, region.classinfo_table - filter);
583 +
584 + auto catch_ci = *cast(ClassInfo*)&typeinfo;
585 + if(_d_dynamic_cast(exception_struct.exception_object, catch_ci) !is null)
586 + return _d_eh_install_catch_context(actions, ti_offset, cast(ptrdiff_t)landing_pad, exception_struct, context);
587 +
588 // we've walked through all actions and found nothing...
589 if(next_action_offset == 0)
590 return _Unwind_Reason_Code.CONTINUE_UNWIND;
591 @@ -356,6 +562,7 @@
592 }
593
594 fatalerror("reached unreachable");
595 +
596 return _Unwind_Reason_Code.FATAL_PHASE2_ERROR;
597 }
598
599 @@ -370,56 +577,78 @@
600 _Unwind_SetGR(context, eh_exception_regno, cast(ptrdiff_t)exception_struct);
601 _Unwind_SetGR(context, eh_selector_regno, 0);
602 _Unwind_SetIP(context, landing_pad);
603 +
604 return _Unwind_Reason_Code.INSTALL_CONTEXT;
605 }
606
607 -private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte* callsite, ref ubyte* action, ref ClassInfo* ci)
608 +private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, out Region region)
609 {
610 - ubyte* data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context);
611 + auto data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context);
612 +
613 + // workaround. this should not be 0...
614 if (!data)
615 {
616 - callsite = null;
617 - action = null;
618 - ci = null;
619 - return;
620 + //printf("language specific data is null\n");
621 + return;
622 }
623
624 - //TODO: Do proper DWARF reading here
625 - if(*data++ != 0xff)
626 - fatalerror("DWARF header has unexpected format 1");
627 + region.start = _Unwind_GetRegionStart(context);
628
629 - if(*data++ != 0x00)
630 - fatalerror("DWARF header has unexpected format 2");
631 - size_t cioffset;
632 - data = get_uleb128(data, cioffset);
633 - ci = cast(ClassInfo*)(data + cioffset);
634 + // Read the C++-style LSDA: this is implementation-defined by GCC but LLVM
635 + // outputs the same kind of table
636
637 - if(*data++ != 0x03)
638 - fatalerror("DWARF header has unexpected format 3");
639 - size_t callsitelength;
640 - data = get_uleb128(data, callsitelength);
641 - action = data + callsitelength;
642 + // Get @LPStart: landing pad offsets are relative to it
643 + auto lpStartEnc = *data++;
644 + if (lpStartEnc == DW_EH_PE_omit)
645 + region.lpStart_base = region.start;
646 + else
647 + data = read_encoded(context, lpStartEnc, data, region.lpStart_base);
648
649 - callsite = data;
650 + // Get @TType: the offset to the handler and typeinfo
651 + region.ttypeEnc = *data++;
652 + if (region.ttypeEnc == DW_EH_PE_omit)
653 + // Not sure about this one...
654 + fatalerror("@TType must not be omitted from DWARF header");
655 +
656 + size_t ciOffset;
657 + data = get_uleb128(data, ciOffset);
658 + region.classinfo_table = data + ciOffset;
659 +
660 + region.ttype_base = base_of_encoded(context, region.ttypeEnc);
661 +
662 + // Get encoding and length of the call site table, which precedes the action
663 + // table.
664 + region.callSiteEnc = *data++;
665 + if (region.callSiteEnc == DW_EH_PE_omit)
666 + fatalerror("Call site table encoding must not be omitted from DWARF header");
667 +
668 + size_t callSiteLength;
669 + region.callsite_table = get_uleb128(data, callSiteLength);
670 + region.action_table = region.callsite_table + callSiteLength;
671 }
672
673 } // end of x86 Linux specific implementation
674
675 -
676 -extern(C) void _d_throw_exception(Object e)
677 +// called to throw object
678 +extern(C)
679 +void _d_throw_exception(Object e)
680 {
681 + //printf("throwing %p, rtti = %p\n", e, **cast(ClassRTTI***)e);
682 if (e !is null)
683 {
684 _d_exception* exc_struct = new _d_exception;
685 exc_struct.unwind_info.exception_class = *cast(ulong*)_d_exception_class.ptr;
686 exc_struct.exception_object = e;
687 _Unwind_Reason_Code ret = _Unwind_RaiseException(&exc_struct.unwind_info);
688 - console("_Unwind_RaiseException failed with reason code: ")(ret)("\n");
689 + printf("Error: returned %d from raise exception.\n", ret);
690 + //console("_Unwind_RaiseException failed with reason code: ")(ret)("\n");
691 }
692 abort();
693 }
694
695 -extern(C) void _d_eh_resume_unwind(_d_exception* exception_struct)
696 +// called to resume unwinding
697 +extern(C)
698 +void _d_eh_resume_unwind(void* exception_struct)
699 {
700 - _Unwind_Resume(&exception_struct.unwind_info);
701 + _Unwind_Resume(&(cast(_d_exception*)exception_struct).unwind_info);
702 }