root/tango-0.99.9.patch
| Revision 1650:40bd4a0d4870, 23.6 kB (checked in by Tomas Lindquist Olsen, 2 years ago) |
|---|
-
tango/core/rt/compiler/ldc/rt/lifetime.d
old new 786 786 return *cast(long*)px; 787 787 } 788 788 789 +/ 789 790 790 791 /** 791 792 * … … 849 850 850 851 851 852 /** 852 * 853 * Appends a single element to an array. 853 854 */ 854 extern (C) byte[] _d_arrayappendcT(TypeInfo ti, ref byte[] x, ...)855 extern (C) byte[] _d_arrayappendcT(TypeInfo ti, void* array, void* element) 855 856 { 857 auto x = cast(byte[]*)array; 856 858 auto sizeelem = ti.next.tsize(); // array element size 857 859 auto info = gc_query(x.ptr); 858 860 auto length = x.length; … … 879 881 assert(newcap >= newlength * sizeelem); 880 882 newdata = cast(byte *)gc_malloc(newcap + 1, info.attr); 881 883 memcpy(newdata, x.ptr, length * sizeelem); 882 (cast(void**) (&x))[1] = newdata;884 (cast(void**)x)[1] = newdata; 883 885 } 884 886 L1: 885 byte *argp = cast(byte *) (&ti + 2);887 byte *argp = cast(byte *)element; 886 888 887 *cast(size_t *) &x = newlength;889 *cast(size_t *)x = newlength; 888 890 x.ptr[length * sizeelem .. newsize] = argp[0 .. sizeelem]; 889 891 assert((cast(size_t)x.ptr & 15) == 0); 890 892 assert(gc_sizeOf(x.ptr) > x.length * sizeelem); 891 return x;893 return *x; 892 894 } 893 895 894 896 … … 1128 1130 return result; 1129 1131 } 1130 1132 1133 /+ 1131 1134 1132 1135 /** 1133 1136 * -
tango/core/rt/compiler/ldc/rt/eh.d
old new 1 1 /** 2 2 * This module contains functions and structures required for 3 * exception handling.3 * dwarf exception handling with llvm 4 4 */ 5 5 module rt.eh; 6 6 7 import ldc.cstdarg; 8 import rt.compiler.util.console; 7 //debug = EH_personality; 9 8 10 // debug = EH_personality;11 12 9 // current EH implementation works on x86 13 10 // if it has a working unwind runtime 14 11 version(X86) { 15 12 version(linux) version=X86_UNWIND; 16 13 version(darwin) version=X86_UNWIND; 17 14 version(solaris) version=X86_UNWIND; 18 version(freebsd) version=X86_UNWIND;19 15 } 20 16 version(X86_64) { 21 17 version(linux) version=X86_UNWIND; 22 18 version(darwin) version=X86_UNWIND; 23 19 version(solaris) version=X86_UNWIND; 24 version(freebsd) version=X86_UNWIND;25 20 } 26 21 27 22 //version = HP_LIBUNWIND; 28 23 29 24 private extern(C) void abort(); 30 25 private extern(C) int printf(char*, ...); 31 private extern(C) int vprintf(char*, va_list va);26 //private extern(C) int vprintf(char*, va_list va); 32 27 33 28 // D runtime functions 34 29 extern(C) { 35 int _d_isbaseof(ClassInfo oc, ClassInfo c); 30 // int _d_isbaseof(ClassInfo oc, ClassInfo c); 31 Object _d_dynamic_cast(Object o, ClassInfo c); 36 32 } 37 33 38 34 // libunwind headers … … 74 70 // interface to HP's libunwind from http://www.nongnu.org/libunwind/ 75 71 version(HP_LIBUNWIND) 76 72 { 73 // Haven't checked whether and how it has _Unwind_Get{Text,Data}RelBase 74 pragma (msg, "HP_LIBUNWIND interface is out of date and untested"); 75 77 76 void __libunwind_Unwind_Resume(_Unwind_Exception *); 78 77 _Unwind_Reason_Code __libunwind_Unwind_RaiseException(_Unwind_Exception *); 79 78 ptrdiff_t __libunwind_Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr 80 79 context); 81 ptrdiff_t __libunwind_Unwind_GetIP(_Unwind_Context_Ptr context);80 size_t __libunwind_Unwind_GetIP(_Unwind_Context_Ptr context); 82 81 ptrdiff_t __libunwind_Unwind_SetIP(_Unwind_Context_Ptr context, 83 82 ptrdiff_t new_value); 84 83 ptrdiff_t __libunwind_Unwind_SetGR(_Unwind_Context_Ptr context, int index, 85 84 ptrdiff_t new_value); 86 ptrdiff_t __libunwind_Unwind_GetRegionStart(_Unwind_Context_Ptr context);85 size_t __libunwind_Unwind_GetRegionStart(_Unwind_Context_Ptr context); 87 86 88 87 alias __libunwind_Unwind_Resume _Unwind_Resume; 89 88 alias __libunwind_Unwind_RaiseException _Unwind_RaiseException; … … 94 93 alias __libunwind_Unwind_SetGR _Unwind_SetGR; 95 94 alias __libunwind_Unwind_GetRegionStart _Unwind_GetRegionStart; 96 95 } 97 else version(X86_UNWIND) 96 else version(X86_UNWIND) 98 97 { 99 98 void _Unwind_Resume(_Unwind_Exception*); 100 99 _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*); 101 100 ptrdiff_t _Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr context); 102 ptrdiff_t _Unwind_GetIP(_Unwind_Context_Ptr context);101 size_t _Unwind_GetIP(_Unwind_Context_Ptr context); 103 102 ptrdiff_t _Unwind_SetIP(_Unwind_Context_Ptr context, ptrdiff_t new_value); 104 103 ptrdiff_t _Unwind_SetGR(_Unwind_Context_Ptr context, int index, 105 104 ptrdiff_t new_value); 106 ptrdiff_t _Unwind_GetRegionStart(_Unwind_Context_Ptr context); 105 size_t _Unwind_GetRegionStart(_Unwind_Context_Ptr context); 106 107 size_t _Unwind_GetTextRelBase(_Unwind_Context_Ptr); 108 size_t _Unwind_GetDataRelBase(_Unwind_Context_Ptr); 107 109 } 108 110 else 109 111 { 110 112 // runtime calls these directly 111 113 void _Unwind_Resume(_Unwind_Exception*) 112 114 { 113 console("_Unwind_Resume is not implemented on this platform.\n");115 printf("_Unwind_Resume is not implemented on this platform.\n"); 114 116 } 115 117 _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*) 116 118 { 117 console("_Unwind_RaiseException is not implemented on this platform.\n");119 printf("_Unwind_RaiseException is not implemented on this platform.\n"); 118 120 return _Unwind_Reason_Code.FATAL_PHASE1_ERROR; 119 121 } 120 122 } … … 122 124 } 123 125 124 126 // error and exit 125 extern(C) private void fatalerror(char [] format)127 extern(C) private void fatalerror(char* format, ...) 126 128 { 127 printf("Fatal error in EH code: %.*s\n", format.length, format.ptr); 129 // va_list args; 130 // va_start(args, format); 131 printf("Fatal error in EH code: "); 132 // vprintf(format, args); 133 printf("\n"); 128 134 abort(); 129 135 } 130 136 131 137 132 // helpers for reading certain DWARF data 138 // DWARF EH encoding enum 139 // See e.g. http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/dwarfext.html 140 private enum : ubyte { 141 DW_EH_PE_omit = 0xff, // value is not present 142 143 // value format 144 DW_EH_PE_absptr = 0x00, // literal pointer 145 DW_EH_PE_uleb128 = 0x01, 146 DW_EH_PE_udata2 = 0x02, // unsigned 2-byte 147 DW_EH_PE_udata4 = 0x03, 148 DW_EH_PE_udata8 = 0x04, 149 DW_EH_PE_sleb128 = 0x09, 150 DW_EH_PE_sdata2 = 0x0a, 151 DW_EH_PE_sdata4 = 0x0b, 152 DW_EH_PE_sdata8 = 0x0c, 153 154 // value meaning 155 DW_EH_PE_pcrel = 0x10, // relative to program counter 156 DW_EH_PE_textrel = 0x20, // relative to .text 157 DW_EH_PE_datarel = 0x30, // relative to .got or .eh_frame_hdr 158 DW_EH_PE_funcrel = 0x40, // relative to beginning of function 159 DW_EH_PE_aligned = 0x50, // is an aligned void* 160 161 // value is a pointer to the actual value 162 // this is a mask on top of one of the above 163 DW_EH_PE_indirect = 0x80 164 } 165 166 // Helpers for reading DWARF data 167 168 // Given an encoding and a context, return the base to which the encoding is 169 // relative 170 private size_t base_of_encoded(_Unwind_Context_Ptr context, ubyte encoding) 171 { 172 if (encoding == DW_EH_PE_omit) 173 return 0; 174 175 switch (encoding & 0x70) // ignore DW_EH_PE_indirect 176 { 177 case DW_EH_PE_absptr, DW_EH_PE_pcrel, DW_EH_PE_aligned: 178 return 0; 179 180 case DW_EH_PE_textrel: return _Unwind_GetTextRelBase(context); 181 case DW_EH_PE_datarel: return _Unwind_GetDataRelBase(context); 182 case DW_EH_PE_funcrel: return _Unwind_GetRegionStart(context); 183 184 default: fatalerror("Unrecognized base for DWARF value"); 185 } 186 } 187 188 // Only defined for fixed-size encodings 189 private size_t size_of_encoded(ubyte encoding) 190 { 191 if (encoding == DW_EH_PE_omit) 192 return 0; 193 194 switch (encoding & 0x07) // ignore leb128 195 { 196 case DW_EH_PE_absptr: return (void*).sizeof; 197 case DW_EH_PE_udata2: return 2; 198 case DW_EH_PE_udata4: return 4; 199 case DW_EH_PE_udata8: return 8; 200 201 default: fatalerror("Unrecognized fixed-size DWARF value encoding"); 202 } 203 } 204 205 // Actual value readers below: read a value from the given ubyte* into the 206 // output parameter and return the pointer incremented past the value. 207 208 // Like read_encoded_with_base but gets the base from the given context 209 private ubyte* read_encoded(_Unwind_Context_Ptr context, ubyte encoding, ubyte* p, out size_t val) 210 { 211 return read_encoded_with_base(encoding, base_of_encoded(context, encoding), p, val); 212 } 213 214 private ubyte* read_encoded_with_base(ubyte encoding, size_t base, ubyte* p, out size_t val) 215 { 216 if (encoding == DW_EH_PE_aligned) 217 { 218 auto a = cast(size_t)p; 219 a = (a + (void*).sizeof - 1) & -(void*).sizeof; 220 val = *cast(size_t*)a; 221 return cast(ubyte*)(a + (void*).sizeof); 222 } 223 224 union U 225 { 226 size_t ptr; 227 ushort udata2; 228 uint udata4; 229 ulong udata8; 230 short sdata2; 231 int sdata4; 232 long sdata8; 233 } 234 235 auto u = cast(U*)p; 236 237 size_t result; 238 239 switch (encoding & 0x0f) 240 { 241 case DW_EH_PE_absptr: 242 result = u.ptr; 243 p += (void*).sizeof; 244 break; 245 246 case DW_EH_PE_uleb128: 247 { 248 p = get_uleb128(p, result); 249 break; 250 } 251 case DW_EH_PE_sleb128: 252 { 253 ptrdiff_t sleb128; 254 p = get_sleb128(p, sleb128); 255 result = cast(size_t)sleb128; 256 break; 257 } 258 259 case DW_EH_PE_udata2: result = cast(size_t)u.udata2; p += 2; break; 260 case DW_EH_PE_udata4: result = cast(size_t)u.udata4; p += 4; break; 261 case DW_EH_PE_udata8: result = cast(size_t)u.udata8; p += 8; break; 262 case DW_EH_PE_sdata2: result = cast(size_t)u.sdata2; p += 2; break; 263 case DW_EH_PE_sdata4: result = cast(size_t)u.sdata4; p += 4; break; 264 case DW_EH_PE_sdata8: result = cast(size_t)u.sdata8; p += 8; break; 265 266 default: fatalerror("Unrecognized DWARF value encoding format"); 267 } 268 if (result) 269 { 270 if ((encoding & 0x70) == DW_EH_PE_pcrel) 271 result += cast(size_t)u; 272 else 273 result += base; 274 275 if (encoding & DW_EH_PE_indirect) 276 result = *cast(size_t*)result; 277 } 278 val = result; 279 return p; 280 } 281 133 282 private ubyte* get_uleb128(ubyte* addr, ref size_t res) 134 283 { 135 284 res = 0; … … 137 286 138 287 // read as long as high bit is set 139 288 while(*addr & 0x80) { 140 res |= (*addr & 0x7f ) << bitsize;289 res |= (*addr & 0x7fU) << bitsize; 141 290 bitsize += 7; 142 291 addr += 1; 143 292 if(bitsize >= size_t.sizeof*8) … … 153 302 154 303 private ubyte* get_sleb128(ubyte* addr, ref ptrdiff_t res) 155 304 { 156 res = 0;305 size_t tres = 0; 157 306 size_t bitsize = 0; 158 307 159 308 // read as long as high bit is set 160 309 while(*addr & 0x80) { 161 res |= (*addr & 0x7f) << bitsize;310 tres |= (*addr & 0x7fU) << bitsize; 162 311 bitsize += 7; 163 312 addr += 1; 164 313 if(bitsize >= size_t.sizeof*8) … … 167 316 // read last 168 317 if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize) 169 318 fatalerror("tried to read sleb128 that exceeded size of size_t"); 170 res |= (*addr) << bitsize;319 tres |= (*addr) << bitsize; 171 320 172 321 // take care of sign 173 if(bitsize < size_t.sizeof*8 && ( (*addr) & 0x40))174 res |= cast(ptrdiff_t)(-1) ^ ((1 << (bitsize+7)) - 1);322 if(bitsize < size_t.sizeof*8 && (*addr & 0x40U) != 0) 323 tres |= cast(size_t)(-1) ^ ((1 << (bitsize+7)) - 1); 175 324 325 res = cast(ptrdiff_t)tres; 326 176 327 return addr + 1; 177 328 } 178 329 … … 190 341 191 342 // the 8-byte string identifying the type of exception 192 343 // the first 4 are for vendor, the second 4 for language 193 //TODO: This may be the wrong way around 194 const char[8] _d_exception_class = "LLDCD1\0\0"; 344 const char[8] _d_exception_class = "LDC_D_10"; 195 345 196 346 197 347 // … … 201 351 version(X86_UNWIND) 202 352 { 203 353 354 // Various stuff we need 355 struct Region 356 { 357 ubyte* callsite_table; 358 ubyte* action_table; 359 360 // Note: classinfo_table points past the end of the table 361 ubyte* classinfo_table; 362 363 size_t start; 364 size_t lpStart_base; // landing pad base 365 366 ubyte ttypeEnc; 367 size_t ttype_base; // typeinfo base 368 369 ubyte callSiteEnc; 370 } 371 204 372 // the personality routine gets called by the unwind handler and is responsible for 205 373 // reading the EH tables and deciding what to do 206 374 extern(C) _Unwind_Reason_Code _d_eh_personality(int ver, _Unwind_Action actions, ulong exception_class, _Unwind_Exception* exception_info, _Unwind_Context_Ptr context) 207 375 { 376 debug(EH_personality) printf("Entering personality routine, context=%p\n", context); 208 377 // check ver: the C++ Itanium ABI only allows ver == 1 209 378 if(ver != 1) 379 { 380 debug(EH_personality) printf("eh version mismatch\n"); 210 381 return _Unwind_Reason_Code.FATAL_PHASE1_ERROR; 382 } 211 383 212 384 // check exceptionClass 213 385 //TODO: Treat foreign exceptions with more respect 214 if((cast(char*)&exception_class)[0..8] != _d_exception_class) 386 auto wanted_ec = *cast(ulong*)_d_exception_class.ptr; 387 if(exception_class != wanted_ec) 388 { 389 debug(EH_personality) printf("exception class mismatch %p vs %p\n", exception_class, wanted_ec); 215 390 return _Unwind_Reason_Code.FATAL_PHASE1_ERROR; 391 } 216 392 217 393 // find call site table, action table and classinfo table 218 394 // Note: callsite and action tables do not contain static-length 219 395 // data and will be parsed as needed 220 // Note: classinfo_table points past the end of the table 221 ubyte* callsite_table; 222 ubyte* action_table; 223 ClassInfo* classinfo_table; 224 _d_getLanguageSpecificTables(context, callsite_table, action_table, classinfo_table); 225 if (!callsite_table) 396 397 Region region; 398 399 _d_getLanguageSpecificTables(context, region); 400 401 // workaround. this should not happen 402 if (!region.callsite_table) 403 { 404 debug(EH_personality) printf("callsite_table is null\n"); 226 405 return _Unwind_Reason_Code.CONTINUE_UNWIND; 406 } 227 407 408 debug(EH_personality) printf("yay, checking\n"); 409 debug(EH_personality) printf("region.start = %p\n", region.start); 410 228 411 /* 229 412 find landing pad and action table index belonging to ip by walking 230 413 the callsite_table 231 414 */ 232 ubyte* callsite_walker = callsite_table; 415 ubyte* callsite_walker = region.callsite_table; 416 debug(EH_personality) printf("callsite table at: %p\n", region.callsite_table); 417 debug(EH_personality) printf("action table at: %p\n", region.action_table); 418 debug(EH_personality) printf("rtti table at %p\n", region.classinfo_table); 233 419 234 420 // get the instruction pointer 235 421 // will be used to find the right entry in the callsite_table 236 422 // -1 because it will point past the last instruction 237 ptrdiff_t ip = _Unwind_GetIP(context) - 1; 423 debug(EH_personality) printf("check1\n"); 424 size_t ip = _Unwind_GetIP(context) - 1; 425 debug(EH_personality) printf("check2\n"); 238 426 239 // address block_start is relative to240 ptrdiff_t region_start = _Unwind_GetRegionStart(context);241 242 427 // table entries 243 uint block_start_offset, block_size; 244 ptrdiff_t landing_pad; 428 size_t landing_pad; 245 429 size_t action_offset; 246 430 247 431 while(true) { 248 432 // if we've gone through the list and found nothing... 249 if(callsite_walker >= action_table) 433 if(callsite_walker >= region.action_table) 434 { 435 debug(EH_personality) printf("found nothing\n"); 250 436 return _Unwind_Reason_Code.CONTINUE_UNWIND; 437 } 251 438 252 block_start_offset = *cast(uint*)callsite_walker; 253 block_size = *(cast(uint*)callsite_walker + 1); 254 landing_pad = *(cast(uint*)callsite_walker + 2); 255 if(landing_pad) 256 landing_pad += region_start; 257 callsite_walker = get_uleb128(callsite_walker + 3*uint.sizeof, action_offset); 439 size_t block_start, block_size; 258 440 259 debug(EH_personality_verbose) printf("ip=%llx %d %d %llx\n", ip, block_start_offset, block_size, landing_pad); 441 callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, block_start); 442 callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, block_size); 443 callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, landing_pad); 444 callsite_walker = get_uleb128(callsite_walker, action_offset); 260 445 446 debug(EH_personality) printf("*block start offset = %p\n", block_start); 447 debug(EH_personality) printf(" block size = %p\n", block_size); 448 debug(EH_personality) printf(" landing pad = %p\n", landing_pad); 449 debug(EH_personality) printf(" ip=%p %p %p %p\n", ip, block_start, block_size, landing_pad); 450 261 451 // since the list is sorted, as soon as we're past the ip 262 452 // there's no handler to be found 263 if(ip < region_start + block_start_offset) 453 if(ip < region.start + block_start) 454 { 455 debug(EH_personality) printf("found nothing2\n"); 264 456 return _Unwind_Reason_Code.CONTINUE_UNWIND; 457 } 265 458 459 if(landing_pad) 460 landing_pad += region.lpStart_base; 461 266 462 // if we've found our block, exit 267 if(ip < region _start + block_start_offset + block_size)463 if(ip < region.start + block_start + block_size) 268 464 break; 269 465 } 270 466 271 debug(EH_personality) printf("Found correct landing pad and actionOffset %d\n", action_offset);467 debug(EH_personality) printf("Found correct landing pad %p and actionOffset %p\n", landing_pad, action_offset); 272 468 273 469 // now we need the exception's classinfo to find a handler 274 470 // the exception_info is actually a member of a larger _d_exception struct 275 471 // the runtime allocated. get that now 276 _d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - _d_exception.unwind_info.offsetof);472 _d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - size_t.sizeof); //_d_exception.unwind_info.offsetof); 277 473 278 474 // if there's no action offset and no landing pad, continue unwinding 279 475 if(!action_offset && !landing_pad) 280 476 return _Unwind_Reason_Code.CONTINUE_UNWIND; 281 477 282 478 // if there's no action offset but a landing pad, this is a cleanup handler 283 else if(!action_offset && landing_pad) 284 return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context); 479 else if(!action_offset && landing_pad != 0) 480 { 481 debug(EH_personality) printf("installing finally context\n"); 482 return _d_eh_install_finally_context(actions, cast(ptrdiff_t)landing_pad, exception_struct, context); 483 } 285 484 286 485 /* 287 486 walk action table chain, comparing classinfos using _d_isbaseof 288 487 */ 289 ubyte* action_walker = action_table + action_offset - 1;488 ubyte* action_walker = region.action_table + action_offset - 1; 290 489 291 ptrdiff_t ti_offset, next_action_offset;292 490 while(true) { 491 ptrdiff_t ti_offset, next_action_offset; 492 293 493 action_walker = get_sleb128(action_walker, ti_offset); 294 494 // it is intentional that we not modify action_walker here 295 495 // next_action_offset is from current action_walker position 296 496 get_sleb128(action_walker, next_action_offset); 297 497 298 498 // negative are 'filters' which we don't use 299 if( !(ti_offset >= 0))499 if(ti_offset < 0) 300 500 fatalerror("Filter actions are unsupported"); 301 501 302 502 // zero means cleanup, which we require to be the last action 303 503 if(ti_offset == 0) { 304 if( !(next_action_offset == 0))504 if(next_action_offset != 0) 305 505 fatalerror("Cleanup action must be last in chain"); 306 return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context);506 return _d_eh_install_finally_context(actions, cast(ptrdiff_t)landing_pad, exception_struct, context); 307 507 } 308 508 309 509 // get classinfo for action and check if the one in the 310 510 // exception structure is a base 311 ClassInfo catch_ci = *(classinfo_table - ti_offset); 312 debug(EH_personality) printf("Comparing catch %s to exception %s\n", catch_ci.name.ptr, exception_struct.exception_object.classinfo.name.ptr); 313 if(_d_isbaseof(exception_struct.exception_object.classinfo, catch_ci)) 314 return _d_eh_install_catch_context(actions, ti_offset, landing_pad, exception_struct, context); 511 size_t typeinfo; 512 auto filter = cast(size_t)ti_offset * size_of_encoded(region.ttypeEnc); 513 read_encoded_with_base(region.ttypeEnc, region.ttype_base, region.classinfo_table - filter, typeinfo); 315 514 515 debug(EH_personality) 516 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); 517 518 auto catch_ci = *cast(ClassInfo*)&typeinfo; 519 if(_d_dynamic_cast(exception_struct.exception_object, catch_ci) !is null) 520 return _d_eh_install_catch_context(actions, ti_offset, cast(ptrdiff_t)landing_pad, exception_struct, context); 521 316 522 // we've walked through all actions and found nothing... 317 523 if(next_action_offset == 0) 318 524 return _Unwind_Reason_Code.CONTINUE_UNWIND; … … 356 562 } 357 563 358 564 fatalerror("reached unreachable"); 565 359 566 return _Unwind_Reason_Code.FATAL_PHASE2_ERROR; 360 567 } 361 568 … … 370 577 _Unwind_SetGR(context, eh_exception_regno, cast(ptrdiff_t)exception_struct); 371 578 _Unwind_SetGR(context, eh_selector_regno, 0); 372 579 _Unwind_SetIP(context, landing_pad); 580 373 581 return _Unwind_Reason_Code.INSTALL_CONTEXT; 374 582 } 375 583 376 private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte* callsite, ref ubyte* action, ref ClassInfo* ci)584 private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, out Region region) 377 585 { 378 ubyte* data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context); 586 auto data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context); 587 588 // workaround. this should not be 0... 379 589 if (!data) 380 590 { 381 callsite = null; 382 action = null; 383 ci = null; 384 return; 591 //printf("language specific data is null\n"); 592 return; 385 593 } 386 594 387 //TODO: Do proper DWARF reading here 388 if(*data++ != 0xff) 389 fatalerror("DWARF header has unexpected format 1"); 595 region.start = _Unwind_GetRegionStart(context); 390 596 391 if(*data++ != 0x00) 392 fatalerror("DWARF header has unexpected format 2"); 393 size_t cioffset; 394 data = get_uleb128(data, cioffset); 395 ci = cast(ClassInfo*)(data + cioffset); 597 // Read the C++-style LSDA: this is implementation-defined by GCC but LLVM 598 // outputs the same kind of table 396 599 397 if(*data++ != 0x03) 398 fatalerror("DWARF header has unexpected format 3"); 399 size_t callsitelength; 400 data = get_uleb128(data, callsitelength); 401 action = data + callsitelength; 600 // Get @LPStart: landing pad offsets are relative to it 601 auto lpStartEnc = *data++; 602 if (lpStartEnc == DW_EH_PE_omit) 603 region.lpStart_base = region.start; 604 else 605 data = read_encoded(context, lpStartEnc, data, region.lpStart_base); 402 606 403 callsite = data; 607 // Get @TType: the offset to the handler and typeinfo 608 region.ttypeEnc = *data++; 609 if (region.ttypeEnc == DW_EH_PE_omit) 610 // Not sure about this one... 611 fatalerror("@TType must not be omitted from DWARF header"); 612 613 size_t ciOffset; 614 data = get_uleb128(data, ciOffset); 615 region.classinfo_table = data + ciOffset; 616 617 region.ttype_base = base_of_encoded(context, region.ttypeEnc); 618 619 // Get encoding and length of the call site table, which precedes the action 620 // table. 621 region.callSiteEnc = *data++; 622 if (region.callSiteEnc == DW_EH_PE_omit) 623 fatalerror("Call site table encoding must not be omitted from DWARF header"); 624 625 size_t callSiteLength; 626 region.callsite_table = get_uleb128(data, callSiteLength); 627 region.action_table = region.callsite_table + callSiteLength; 404 628 } 405 629 406 630 } // end of x86 Linux specific implementation 407 631 408 409 extern(C) void _d_throw_exception(Object e) 632 // called to throw object 633 extern(C) 634 void _d_throw_exception(Object e) 410 635 { 636 //printf("throwing %p, rtti = %p\n", e, **cast(ClassRTTI***)e); 411 637 if (e !is null) 412 638 { 413 639 _d_exception* exc_struct = new _d_exception; 414 640 exc_struct.unwind_info.exception_class = *cast(ulong*)_d_exception_class.ptr; 415 641 exc_struct.exception_object = e; 416 642 _Unwind_Reason_Code ret = _Unwind_RaiseException(&exc_struct.unwind_info); 417 console("_Unwind_RaiseException failed with reason code: ")(ret)("\n"); 643 printf("Error: returned %d from raise exception.\n", ret); 644 //console("_Unwind_RaiseException failed with reason code: ")(ret)("\n"); 418 645 } 419 646 abort(); 420 647 } 421 648 422 extern(C) void _d_eh_resume_unwind(_d_exception* exception_struct) 649 // called to resume unwinding 650 extern(C) 651 void _d_eh_resume_unwind(void* exception_struct) 423 652 { 424 _Unwind_Resume(&exception_struct.unwind_info);653 _Unwind_Resume(&(cast(_d_exception*)exception_struct).unwind_info); 425 654 }
Note: See TracBrowser for help on using the browser.

