Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Changeset 5393

Show
Ignore:
Timestamp:
03/01/10 16:17:41 (2 years ago)
Author:
Deewiant
Message:

Oops; undo commit to release branch.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • tags/releases/0.99.9/tango/core/rt/compiler/ldc/rt/eh.d

    r5392 r5393  
    7575version(HP_LIBUNWIND) 
    7676{ 
    77     // Haven't checked whether and how it has _Unwind_Get{Text,Data}RelBase 
    78     pragma (msg, "HP_LIBUNWIND interface is out of date and untested"); 
    79  
    8077    void __libunwind_Unwind_Resume(_Unwind_Exception *); 
    8178    _Unwind_Reason_Code __libunwind_Unwind_RaiseException(_Unwind_Exception *); 
     
    9895    alias __libunwind_Unwind_GetRegionStart _Unwind_GetRegionStart; 
    9996} 
    100 else version(X86_UNWIND) 
     97else version(X86_UNWIND)  
    10198{ 
    10299    void _Unwind_Resume(_Unwind_Exception*); 
     
    108105            ptrdiff_t new_value); 
    109106    ptrdiff_t _Unwind_GetRegionStart(_Unwind_Context_Ptr context); 
    110  
    111     size_t _Unwind_GetTextRelBase(_Unwind_Context_Ptr); 
    112     size_t _Unwind_GetDataRelBase(_Unwind_Context_Ptr); 
    113107} 
    114108else 
     
    136130 
    137131 
    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  
     132// helpers for reading certain DWARF data 
    282133private ubyte* get_uleb128(ubyte* addr, ref size_t res) 
    283134{ 
     
    351202{ 
    352203 
    353 // Various stuff we need 
    354 struct Region 
    355 { 
    356   ubyte* callsite_table; 
    357   ubyte* action_table; 
    358  
    359   // Note: classinfo_table points past the end of the table 
    360   ubyte* classinfo_table; 
    361  
    362   ptrdiff_t start; 
    363   size_t lpStart_base; // landing pad base 
    364  
    365   ubyte ttypeEnc; 
    366   size_t ttype_base; // typeinfo base 
    367  
    368   ubyte callSiteEnc; 
    369 } 
    370  
    371204// the personality routine gets called by the unwind handler and is responsible for 
    372205// reading the EH tables and deciding what to do 
     
    385218  // Note: callsite and action tables do not contain static-length 
    386219  // data and will be parsed as needed 
    387  
    388   Region region; 
    389  
    390   _d_getLanguageSpecificTables(context, region); 
    391   if (!region.callsite_table) 
     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) 
    392226    return _Unwind_Reason_Code.CONTINUE_UNWIND; 
    393227 
     
    396230    the callsite_table 
    397231  */ 
    398   ubyte* callsite_walker = region.callsite_table; 
     232  ubyte* callsite_walker = callsite_table; 
    399233 
    400234  // get the instruction pointer 
     
    403237  ptrdiff_t ip = _Unwind_GetIP(context) - 1; 
    404238 
     239  // address block_start is relative to 
     240  ptrdiff_t region_start = _Unwind_GetRegionStart(context); 
     241 
    405242  // table entries 
    406   size_t landing_pad; 
     243  uint block_start_offset, block_size; 
     244  ptrdiff_t landing_pad; 
    407245  size_t action_offset; 
    408246 
    409247  while(true) { 
    410248    // if we've gone through the list and found nothing... 
    411     if(callsite_walker >= region.action_table) 
     249    if(callsite_walker >= action_table) 
    412250      return _Unwind_Reason_Code.CONTINUE_UNWIND; 
    413251 
    414     size_t block_start, block_size
    415  
    416     callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, block_start); 
    417     callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, block_size); 
    418     callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, landing_pad)
    419     callsite_walker = get_uleb128(callsite_walker, action_offset); 
    420  
    421     debug(EH_personality_verbose) printf("ip=%zx %d %d %zx\n", ip, block_start, block_size, landing_pad); 
     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); 
     258 
     259    debug(EH_personality_verbose) printf("ip=%llx %d %d %llx\n", ip, block_start_offset, block_size, landing_pad); 
    422260 
    423261    // since the list is sorted, as soon as we're past the ip 
    424262    // there's no handler to be found 
    425     if(ip < region.start + block_start) 
     263    if(ip < region_start + block_start_offset) 
    426264      return _Unwind_Reason_Code.CONTINUE_UNWIND; 
    427265 
    428     if(landing_pad) 
    429       landing_pad += region.lpStart_base; 
    430  
    431266    // if we've found our block, exit 
    432     if(ip < region.start + block_start + block_size) 
     267    if(ip < region_start + block_start_offset + block_size) 
    433268      break; 
    434269  } 
    435270 
    436   debug(EH_personality) printf("Found correct landing pad %zx and actionOffset %zx\n", landing_pad, action_offset); 
     271  debug(EH_personality) printf("Found correct landing pad and actionOffset %d\n", action_offset); 
    437272 
    438273  // now we need the exception's classinfo to find a handler 
     
    447282  // if there's no action offset but a landing pad, this is a cleanup handler 
    448283  else if(!action_offset && landing_pad) 
    449     return _d_eh_install_finally_context(actions, cast(ptrdiff_t)landing_pad, exception_struct, context); 
     284    return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context); 
    450285 
    451286  /* 
    452287   walk action table chain, comparing classinfos using _d_isbaseof 
    453288  */ 
    454   ubyte* action_walker = region.action_table + action_offset - 1; 
    455  
     289  ubyte* action_walker = action_table + action_offset - 1; 
     290 
     291  ptrdiff_t ti_offset, next_action_offset; 
    456292  while(true) { 
    457     ptrdiff_t ti_offset, next_action_offset; 
    458  
    459293    action_walker = get_sleb128(action_walker, ti_offset); 
    460294    // it is intentional that we not modify action_walker here 
     
    463297 
    464298    // negative are 'filters' which we don't use 
    465     if(ti_offset < 0
     299    if(!(ti_offset >= 0)
    466300      fatalerror("Filter actions are unsupported"); 
    467301 
    468302    // zero means cleanup, which we require to be the last action 
    469303    if(ti_offset == 0) { 
    470       if(next_action_offset != 0
     304      if(!(next_action_offset == 0)
    471305        fatalerror("Cleanup action must be last in chain"); 
    472       return _d_eh_install_finally_context(actions, cast(ptrdiff_t)landing_pad, exception_struct, context); 
     306      return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context); 
    473307    } 
    474308 
    475309    // get classinfo for action and check if the one in the 
    476310    // exception structure is a base 
    477     size_t typeinfo; 
    478     auto filter = ti_offset * size_of_encoded(region.ttypeEnc); 
    479     read_encoded_with_base(region.ttypeEnc, region.ttype_base, region.classinfo_table - filter, typeinfo); 
    480  
    481     debug(EH_personality_verbose) 
    482       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); 
    483  
    484     auto catch_ci = *cast(ClassInfo*)&typeinfo; 
    485  
     311    ClassInfo catch_ci = *(classinfo_table - ti_offset); 
    486312    debug(EH_personality) printf("Comparing catch %s to exception %s\n", catch_ci.name.ptr, exception_struct.exception_object.classinfo.name.ptr); 
    487313    if(_d_isbaseof(exception_struct.exception_object.classinfo, catch_ci)) 
    488       return _d_eh_install_catch_context(actions, ti_offset, cast(ptrdiff_t)landing_pad, exception_struct, context); 
     314      return _d_eh_install_catch_context(actions, ti_offset, landing_pad, exception_struct, context); 
    489315 
    490316    // we've walked through all actions and found nothing... 
     
    548374} 
    549375 
    550 private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, out Region region
    551 { 
    552   auto data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context); 
     376private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte* callsite, ref ubyte* action, ref ClassInfo* ci
     377{ 
     378  ubyte* data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context); 
    553379  if (!data) 
     380  { 
     381    callsite = null; 
     382    action = null; 
     383    ci = null; 
    554384    return; 
    555  
    556   region.start = _Unwind_GetRegionStart(context); 
    557  
    558   // Read the C++-style LSDA: this is implementation-defined by GCC but LLVM 
    559   // outputs the same kind of table 
    560  
    561   // Get @LPStart: landing pad offsets are relative to it 
    562   auto lpStartEnc = *data++; 
    563   if (lpStartEnc == DW_EH_PE_omit) 
    564     region.lpStart_base = region.start; 
    565   else 
    566     data = read_encoded(context, lpStartEnc, data, region.lpStart_base); 
    567  
    568   // Get @TType: the offset to the handler and typeinfo 
    569   region.ttypeEnc = *data++; 
    570   if (region.ttypeEnc == DW_EH_PE_omit) 
    571     // Not sure about this one... 
    572     fatalerror("@TType must not be omitted from DWARF header"); 
    573  
    574   size_t ciOffset; 
    575   data = get_uleb128(data, ciOffset); 
    576   region.classinfo_table = data + ciOffset; 
    577  
    578   region.ttype_base = base_of_encoded(context, region.ttypeEnc); 
    579  
    580   // Get encoding and length of the call site table, which precedes the action 
    581   // table. 
    582   region.callSiteEnc = *data++; 
    583   if (region.callSiteEnc == DW_EH_PE_omit) 
    584     fatalerror("Call site table encoding must not be omitted from DWARF header"); 
    585  
    586   size_t callSiteLength; 
    587   region.callsite_table = get_uleb128(data, callSiteLength); 
    588   region.action_table = region.callsite_table + callSiteLength; 
     385  } 
     386 
     387  //TODO: Do proper DWARF reading here 
     388  if(*data++ != 0xff) 
     389    fatalerror("DWARF header has unexpected format 1"); 
     390 
     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); 
     396 
     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; 
     402 
     403  callsite = data; 
    589404} 
    590405