dlls/ntdll/signal_x86_64.c
/***********************************************************************
 *           dwarf_virtual_unwind
 *
 * Equivalent of RtlVirtualUnwind for builtin modules.
 */
dwarf_virtual_unwind
Equivalent of RtlVirtualUnwind for builtin modules.
dwarf_virtual_unwind Equivalent of RtlVirtualUnwind for builtin modules .
static NTSTATUS dwarf_virtual_unwind( ULONG64 ip, ULONG64 *frame,CONTEXT *context,
                                      const struct dwarf_fde *fde, const struct dwarf_eh_bases *bases,
                                      PEXCEPTION_ROUTINE *handler, void **handler_data )
{
    const struct dwarf_cie *cie;
    const unsigned char *ptr, *augmentation, *end;
    ULONG_PTR len, code_end;
    struct frame_info info;
    struct frame_state state_stack[MAX_SAVED_STATES];
    int aug_z_format = 0;
    unsigned char lsda_encoding = DW_EH_PE_omit;
    memset( &info, 0, sizeof(info) );
    info.state_stack = state_stack;
    info.ip = (ULONG_PTR)bases->func;
    *handler = NULL;
    cie = (const struct dwarf_cie *)((const char *)&fde->cie_offset - fde->cie_offset);
    if (cie->version != 1)
    {
        FIXME( "unknown CIE version %u at %p\n", cie->version, cie );
        return STATUS_INVALID_DISPOSITION;
    }
    ptr = cie->augmentation + strlen((const char *)cie->augmentation) + 1;
    info.code_align = dwarf_get_uleb128( &ptr );
    info.data_align = dwarf_get_sleb128( &ptr );
    info.retaddr_reg = *ptr++;
    info.state.cfa_rule = RULE_CFA_OFFSET;
    TRACE( "function %lx base %p cie %p len %x id %x version %x aug '%s' code_align %lu data_align %ld retaddr %s\n",
           ip, bases->func, cie, cie->length, cie->id, cie->version, cie->augmentation,
           info.code_align, info.data_align, dwarf_reg_names[info.retaddr_reg] );
    end = NULL;
    for (augmentation = cie->augmentation; *augmentation; augmentation++)
    {
        switch (*augmentation)
        {
        case 'z':
            len = dwarf_get_uleb128( &ptr );
            end = ptr + len;
            aug_z_format = 1;
            continue;
        case 'L':
            lsda_encoding = *ptr++;
            continue;
        case 'P':
        {
            unsigned char encoding = *ptr++;
            *handler = (void *)dwarf_get_ptr( &ptr, encoding );
            continue;
        }
        case 'R':
            info.fde_encoding = *ptr++;
            continue;
        case 'S':
            info.signal_frame = 1;
            continue;
        }
        FIXME( "unknown augmentation '%c'\n", *augmentation );
        if (!end) return STATUS_INVALID_DISPOSITION;  
        break;
    }
    if (end) ptr = end;
    end = (const unsigned char *)(&cie->length + 1) + cie->length;
    execute_cfa_instructions( ptr, end, ip, &info );
    ptr = (const unsigned char *)(fde + 1);
    info.ip = dwarf_get_ptr( &ptr, info.fde_encoding );  
    code_end = info.ip + dwarf_get_ptr( &ptr, info.fde_encoding & 0x0f );  
    if (aug_z_format)  
    {
        len = dwarf_get_uleb128( &ptr );
        end = ptr + len;
    }
    else end = NULL;
    *handler_data = (void *)dwarf_get_ptr( &ptr, lsda_encoding );
    if (end) ptr = end;
    end = (const unsigned char *)(&fde->length + 1) + fde->length;
    TRACE( "fde %p len %x personality %p lsda %p code %lx-%lx\n",
           fde, fde->length, *handler, *handler_data, info.ip, code_end );
    execute_cfa_instructions( ptr, end, ip, &info );
    apply_frame_state( context, &info.state );
    *frame = context->Rsp;
    TRACE( "next function rip=%016lx\n", context->Rip );
    TRACE( "  rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n",
           context->Rax, context->Rbx, context->Rcx, context->Rdx );
    TRACE( "  rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n",
           context->Rsi, context->Rdi, context->Rbp, context->Rsp );
    TRACE( "   r8=%016lx  r9=%016lx r10=%016lx r11=%016lx\n",
           context->R8, context->R9, context->R10, context->R11 );
    TRACE( "  r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n",
           context->R12, context->R13, context->R14, context->R15 );
    return STATUS_SUCCESS;
}
static NTSTATUS dwarf_virtual_unwind ( ULONG64 ip , ULONG64 * frame , CONTEXT * context , const struct dwarf_fde * fde , const struct dwarf_eh_bases * bases , PEXCEPTION_ROUTINE * handler , void * * handler_data ) { const struct dwarf_cie * cie ; const unsigned char * ptr , * augmentation , * end ; ULONG_PTR len , code_end ; struct frame_info info ; struct frame_state state_stack [ MAX_SAVED_STATES ] ; int aug_z_format = 0 ; unsigned char lsda_encoding = DW_EH_PE_omit ; memset ( & info , 0 , sizeof ( info ) ) ; info . state_stack = state_stack ; info . ip = ( ULONG_PTR ) bases -> func ; * handler = NULL ; cie = ( const struct dwarf_cie * ) ( ( const char * ) & fde -> cie_offset - fde -> cie_offset ) ; if ( cie -> version != 1 ) { FIXME ( " \n " , cie -> version , cie ) ; return STATUS_INVALID_DISPOSITION ; } ptr = cie -> augmentation + strlen ( ( const char * ) cie -> augmentation ) + 1 ; info . code_align = dwarf_get_uleb128 ( & ptr ) ; info . data_align = dwarf_get_sleb128 ( & ptr ) ; info . retaddr_reg = * ptr ++ ; info . state . cfa_rule = RULE_CFA_OFFSET ; TRACE ( " \n " , ip , bases -> func , cie , cie -> length , cie -> id , cie -> version , cie -> augmentation , info . code_align , info . data_align , dwarf_reg_names [ info . retaddr_reg ] ) ; end = NULL ; for ( augmentation = cie -> augmentation ; * augmentation ; augmentation ++ ) { switch ( * augmentation ) { case ' ' : len = dwarf_get_uleb128 ( & ptr ) ; end = ptr + len ; aug_z_format = 1 ; continue ; case ' ' : lsda_encoding = * ptr ++ ; continue ; case ' ' : { unsigned char encoding = * ptr ++ ; * handler = ( void * ) dwarf_get_ptr ( & ptr , encoding ) ; continue ; } case ' ' : info . fde_encoding = * ptr ++ ; continue ; case ' ' : info . signal_frame = 1 ; continue ; } FIXME ( " \n " , * augmentation ) ; if ( ! end ) return STATUS_INVALID_DISPOSITION ; break ; } if ( end ) ptr = end ; end = ( const unsigned char * ) ( & cie -> length + 1 ) + cie -> length ; execute_cfa_instructions ( ptr , end , ip , & info ) ; ptr = ( const unsigned char * ) ( fde + 1 ) ; info . ip = dwarf_get_ptr ( & ptr , info . fde_encoding ) ; code_end = info . ip + dwarf_get_ptr ( & ptr , info . fde_encoding & 0x0f ) ; if ( aug_z_format ) { len = dwarf_get_uleb128 ( & ptr ) ; end = ptr + len ; } else end = NULL ; * handler_data = ( void * ) dwarf_get_ptr ( & ptr , lsda_encoding ) ; if ( end ) ptr = end ; end = ( const unsigned char * ) ( & fde -> length + 1 ) + fde -> length ; TRACE ( " \n " , fde , fde -> length , * handler , * handler_data , info . ip , code_end ) ; execute_cfa_instructions ( ptr , end , ip , & info ) ; apply_frame_state ( context , & info . state ) ; * frame = context -> Rsp ; TRACE ( " \n " , context -> Rip ) ; TRACE ( " \n " , context -> Rax , context -> Rbx , context -> Rcx , context -> Rdx ) ; TRACE ( " \n " , context -> Rsi , context -> Rdi , context -> Rbp , context -> Rsp ) ; TRACE ( " \n " , context -> R8 , context -> R9 , context -> R10 , context -> R11 ) ; TRACE ( " \n " , context -> R12 , context -> R13 , context -> R14 , context -> R15 ) ; return STATUS_SUCCESS ; }
dwarf_virtual_unwind
 Equivalent of RtlVirtualUnwind for builtin modules.
dwarf_virtual_unwind Equivalent of RtlVirtualUnwind for builtin modules .
/* parse the CIE first */ /* cannot continue */ /* fde code start */ /* fde code length */ /* get length of augmentation data */