VirtualBox

Changeset 75235 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
Nov 2, 2018 9:01:36 PM (6 years ago)
Author:
vboxsync
Message:

IPRT: Starting to get somewhere with DWARF unwinding. bugref:3897

Location:
trunk/src/VBox/Runtime/common
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/dbg/dbgmoddwarf.cpp

    r75163 r75235  
    4646#include <iprt/string.h>
    4747#include <iprt/strcache.h>
     48#include <iprt/x86.h>
    4849#include "internal/dbgmod.h"
    4950
     
    395396#define DW_CFA_offset_extended_sf   UINT8_C(0x11) /**< op1: ULEB128 register; op2: SLEB128 offset. */
    396397#define DW_CFA_restore              UINT8_C(0xc0) /**< low 6 bits: register. */
    397 #define DW_CFA_restore_extended     UINT8_C(0x06) /**< op1: ULEB128 register; op2: ULEB128 offset. */
     398#define DW_CFA_restore_extended     UINT8_C(0x06) /**< op1: ULEB128 register. */
    398399#define DW_CFA_undefined            UINT8_C(0x07) /**< op1: ULEB128 register. */
    399400#define DW_CFA_same_value           UINT8_C(0x08) /**< op1: ULEB128 register. */
     
    421422#define DW_CFA_GNU_negative_offset_extended UINT8_C(0x2f) /**< op1: ??; op2: ?? */
    422423#define DW_CFA_hi_user              UINT8_C(0x3f) /**< User defined operands. */
     424/** @} */
     425
     426
     427/** @name DWREG_X86_XXX - 386+ register number mappings.
     428 * @{  */
     429#define DWREG_X86_EAX       0
     430#define DWREG_X86_ECX       1
     431#define DWREG_X86_EDX       2
     432#define DWREG_X86_EBX       3
     433#define DWREG_X86_ESP       4
     434#define DWREG_X86_EBP       5
     435#define DWREG_X86_ESI       6
     436#define DWREG_X86_EDI       7
     437#define DWREG_X86_RA        8   /* return address (=EIP) */
     438#define DWREG_X86_EFLAGS    9
     439#define DWREG_X86_ST1       11
     440#define DWREG_X86_ST2       12
     441#define DWREG_X86_ST3       13
     442#define DWREG_X86_ST4       14
     443#define DWREG_X86_ST5       15
     444#define DWREG_X86_ST6       16
     445#define DWREG_X86_ST7       17
     446#define DWREG_X86_XMM0      21
     447#define DWREG_X86_XMM1      22
     448#define DWREG_X86_XMM2      23
     449#define DWREG_X86_XMM3      24
     450#define DWREG_X86_XMM4      25
     451#define DWREG_X86_XMM5      26
     452#define DWREG_X86_XMM6      27
     453#define DWREG_X86_XMM7      28
     454#define DWREG_X86_MM0       29
     455#define DWREG_X86_MM1       30
     456#define DWREG_X86_MM2       31
     457#define DWREG_X86_MM3       32
     458#define DWREG_X86_MM4       33
     459#define DWREG_X86_MM5       34
     460#define DWREG_X86_MM6       35
     461#define DWREG_X86_MM7       36
     462#define DWREG_X86_MXCSR     39
     463#define DWREG_X86_ES        40
     464#define DWREG_X86_CS        41
     465#define DWREG_X86_SS        42
     466#define DWREG_X86_DS        43
     467#define DWREG_X86_FS        44
     468#define DWREG_X86_GS        45
     469#define DWREG_X86_TR        48
     470#define DWREG_X86_LDTR      49
     471/** @} */
     472
     473
     474/** @name DWREG_AMD64_XXX - AMD64 register number mappings.
     475 * @note This for some braindead reason the first 8 GPR are in intel encoding
     476 *       order, unlike the DWREG_X86_XXX variant.  Utter stupidity.
     477 * @{ */
     478#define DWREG_AMD64_RAX     0
     479#define DWREG_AMD64_RDX     1
     480#define DWREG_AMD64_RCX     2
     481#define DWREG_AMD64_RBX     3
     482#define DWREG_AMD64_RSI     4
     483#define DWREG_AMD64_RDI     5
     484#define DWREG_AMD64_RBP     6
     485#define DWREG_AMD64_RSP     7
     486#define DWREG_AMD64_R8      8
     487#define DWREG_AMD64_R9      9
     488#define DWREG_AMD64_R10     10
     489#define DWREG_AMD64_R11     11
     490#define DWREG_AMD64_R12     12
     491#define DWREG_AMD64_R13     13
     492#define DWREG_AMD64_R14     14
     493#define DWREG_AMD64_R15     15
     494#define DWREG_AMD64_RA      16   /* return address (=RIP) */
     495#define DWREG_AMD64_XMM0    17
     496#define DWREG_AMD64_XMM1    18
     497#define DWREG_AMD64_XMM2    19
     498#define DWREG_AMD64_XMM3    20
     499#define DWREG_AMD64_XMM4    21
     500#define DWREG_AMD64_XMM5    22
     501#define DWREG_AMD64_XMM6    23
     502#define DWREG_AMD64_XMM7    24
     503#define DWREG_AMD64_XMM8    25
     504#define DWREG_AMD64_XMM9    26
     505#define DWREG_AMD64_XMM10   27
     506#define DWREG_AMD64_XMM11   28
     507#define DWREG_AMD64_XMM12   29
     508#define DWREG_AMD64_XMM13   30
     509#define DWREG_AMD64_XMM14   31
     510#define DWREG_AMD64_XMM15   32
     511#define DWREG_AMD64_ST0     33
     512#define DWREG_AMD64_ST1     34
     513#define DWREG_AMD64_ST2     35
     514#define DWREG_AMD64_ST3     36
     515#define DWREG_AMD64_ST4     37
     516#define DWREG_AMD64_ST5     38
     517#define DWREG_AMD64_ST6     39
     518#define DWREG_AMD64_ST7     40
     519#define DWREG_AMD64_MM0     41
     520#define DWREG_AMD64_MM1     42
     521#define DWREG_AMD64_MM2     43
     522#define DWREG_AMD64_MM3     44
     523#define DWREG_AMD64_MM4     45
     524#define DWREG_AMD64_MM5     46
     525#define DWREG_AMD64_MM6     47
     526#define DWREG_AMD64_MM7     48
     527#define DWREG_AMD64_RFLAGS  49
     528#define DWREG_AMD64_ES      50
     529#define DWREG_AMD64_CS      51
     530#define DWREG_AMD64_SS      52
     531#define DWREG_AMD64_DS      53
     532#define DWREG_AMD64_FS      54
     533#define DWREG_AMD64_GS      55
     534#define DWREG_AMD64_FS_BASE 58
     535#define DWREG_AMD64_GS_BASE 59
     536#define DWREG_AMD64_TR      62
     537#define DWREG_AMD64_LDTR    63
     538#define DWREG_AMD64_MXCSR   64
     539#define DWREG_AMD64_FCW     65
     540#define DWREG_AMD64_FSW     66
    423541/** @} */
    424542
     
    13201438
    13211439    /* The link address is 0 for all segments in a relocatable ELF image. */
    1322     RTLDRADDR cb = RT_MAX(pSeg->cb, pSeg->cbMapped);
     1440    RTLDRADDR cb = pSeg->cb;
     1441    if (   cb < pSeg->cbMapped
     1442        && RTLdrGetFormat(hLdrMod) != RTLDRFMT_LX /* for debugging our drivers; 64KB section align by linker, 4KB by loader. */
     1443       )
     1444        cb = pSeg->cbMapped;
    13231445    return RTDbgModSegmentAdd(pThis->hCnt, pSeg->RVA, cb, pSeg->pszName, 0 /*fFlags*/, NULL);
    13241446}
     
    13261448
    13271449/**
    1328  * Calls pfnSegmentAdd for each segment in the executable image.
     1450 * Calls rtDbgModDwarfAddSegmentsCallback for each segment in the executable
     1451 * image.
    13291452 *
    13301453 * @returns IPRT status code.
     
    15901713    if (pThis->fUseLinkAddress)
    15911714        return pThis->pImgMod->pImgVt->pfnLinkAddressToSegOffset(pThis->pImgMod, LinkAddress, piSeg, poffSeg);
     1715
     1716    /* If we have a non-zero segment number, assume it's correct for now.
     1717       This helps loading watcom linked LX drivers. */
     1718    if (uSegment > 0)
     1719    {
     1720        *piSeg   = uSegment - 1;
     1721        *poffSeg = LinkAddress;
     1722        return VINF_SUCCESS;
     1723    }
     1724
    15921725    return pThis->pImgMod->pImgVt->pfnRvaToSegOffset(pThis->pImgMod, LinkAddress, piSeg, poffSeg);
    15931726}
     
    22152348 * @param   pCursor             The cursor.
    22162349 */
    2217 static uint64_t rtDwarfCursor_GetInitalLength(PRTDWARFCURSOR pCursor)
     2350static uint64_t rtDwarfCursor_GetInitialLength(PRTDWARFCURSOR pCursor)
    22182351{
    22192352    /*
     
    25262659    /** The segment size (v4). */
    25272660    uint8_t         cbSegment;
     2661    /** The return register column.  UINT8_MAX if default register. */
     2662    uint8_t         bRetReg;
    25282663    /** The LSDA pointer encoding. */
    25292664    uint8_t         bLsdaPtrEnc;
     
    25652700typedef RTDWARFCIEINFO const *PCRTDWARFCIEINFO;
    25662701
    2567 #if 0
    2568 
    2569 typedef struct RTDWARFCFEXPR
    2570 {
    2571 
    2572 };
    2573 
    2574 /**
    2575  * Call frame engine state.
    2576  */
    2577 typedef struct RTDWARFCFSTATE
     2702
     2703/** Number of registers we care about.
     2704 * @note We're currently not expecting to be decoding ppc, arm, ia64 or such,
     2705 *       only x86 and x86_64.  We can easily increase the column count. */
     2706#define RTDWARFCF_MAX_REGISTERS         96
     2707
     2708
     2709/**
     2710 * Call frame state row.
     2711 */
     2712typedef struct RTDWARFCFROW
    25782713{
    25792714    /** Stack worked by DW_CFA_remember_state and DW_CFA_restore_state. */
    2580     struct RTDWARFCFSTATE      *pNextOnStack;
    2581 
    2582 
    2583 
    2584 } RTDWARFCFSTATE;
    2585 #endif
     2715    struct RTDWARFCFROW    *pNextOnStack;
     2716
     2717    /** @name CFA - Canonical frame address expression.
     2718     * Since there are partial CFA instructions, we cannot be lazy like with the
     2719     * register but keep register+offset around.  For DW_CFA_def_cfa_expression
     2720     * we just take down the program location, though.
     2721     * @{ */
     2722    /** Pointer to DW_CFA_def_cfa_expression instruction, NULL if reg+offset. */
     2723    uint8_t const          *pbCfaExprInstr;
     2724    /** The CFA register offset. */
     2725    int64_t                 offCfaReg;
     2726    /** The CFA base register number. */
     2727    uint16_t                uCfaBaseReg;
     2728    /** Set if we've got a valid CFA definition. */
     2729    bool                    fCfaDefined : 1;
     2730    /** @} */
     2731
     2732    /** Set if on the heap and needs freeing. */
     2733    bool                    fOnHeap : 1;
     2734    /** Pointer to the instructions bytes defining registers.
     2735     * NULL means  */
     2736    uint8_t const          *apbRegInstrs[RTDWARFCF_MAX_REGISTERS];
     2737} RTDWARFCFROW;
     2738typedef RTDWARFCFROW *PRTDWARFCFROW;
     2739typedef RTDWARFCFROW const *PCRTDWARFCFROW;
     2740
     2741/** Row program execution state. */
     2742typedef struct RTDWARFCFEXEC
     2743{
     2744    PRTDWARFCFROW       pRow;
     2745    /** Number of PC bytes left to advance before we get a hit. */
     2746    uint64_t            cbLeftToAdvance;
     2747    /** Number of pushed rows. */
     2748    uint32_t            cPushes;
     2749    /** Set if little endian, clear if big endian. */
     2750    bool                fLittleEndian;
     2751    /** The CIE.  */
     2752    PCRTDWARFCIEINFO    pCie;
     2753    /** The program counter value for the FDE.  Subjected to segment.
     2754     * Needed for DW_CFA_set_loc.  */
     2755    uint64_t            uPcBegin;
     2756    /** The offset relative to uPcBegin for which we're searching for a row.
     2757     * Needed for DW_CFA_set_loc.  */
     2758    uint64_t            offInRange;
     2759} RTDWARFCFEXEC;
     2760typedef RTDWARFCFEXEC *PRTDWARFCFEXEC;
     2761
     2762
     2763/* Set of macros for getting and skipping operands. */
     2764#define SKIP_ULEB128_OR_LEB128() \
     2765    do \
     2766    { \
     2767        AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
     2768    } while (pbInstr[offInstr++] & 0x80)
     2769
     2770#define GET_ULEB128_AS_U14(a_uDst) \
     2771    do \
     2772    { \
     2773        AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
     2774        uint8_t b = pbInstr[offInstr++]; \
     2775        (a_uDst) = b & 0x7f; \
     2776        if (b & 0x80) \
     2777        { \
     2778            AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
     2779            b = pbInstr[offInstr++]; \
     2780            AssertReturn(!(b & 0x80), VERR_DBG_MALFORMED_UNWIND_INFO); \
     2781            (a_uDst) |= (uint16_t)b << 7; \
     2782        } \
     2783    } while (0)
     2784#define GET_ULEB128_AS_U63(a_uDst) \
     2785    do \
     2786    { \
     2787        AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
     2788        uint8_t b = pbInstr[offInstr++]; \
     2789        (a_uDst) = b & 0x7f; \
     2790        if (b & 0x80) \
     2791        { \
     2792            unsigned cShift = 7; \
     2793            do \
     2794            { \
     2795                AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
     2796                AssertReturn(cShift < 63, VERR_DWARF_LEB_OVERFLOW); \
     2797                b = pbInstr[offInstr++]; \
     2798                (a_uDst) |= (uint16_t)(b & 0x7f) << cShift; \
     2799                cShift += 7; \
     2800            } while (b & 0x80); \
     2801        } \
     2802    } while (0)
     2803#define GET_LEB128_AS_I63(a_uDst) \
     2804    do \
     2805    { \
     2806        AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
     2807        uint8_t b = pbInstr[offInstr++]; \
     2808        if (!(b & 0x80)) \
     2809            (a_uDst) = !(b & 0x40) ? b : (int64_t)(int8_t)(b | 0x80); \
     2810        else \
     2811        { \
     2812            /* Read value into unsigned variable: */ \
     2813            unsigned cShift = 7; \
     2814            uint64_t uTmp   = b & 0x7f; \
     2815            do \
     2816            { \
     2817                AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
     2818                AssertReturn(cShift < 63, VERR_DWARF_LEB_OVERFLOW); \
     2819                b = pbInstr[offInstr++]; \
     2820                uTmp |= (uint16_t)(b & 0x7f) << cShift; \
     2821                cShift += 7; \
     2822            } while (b & 0x80); \
     2823            /* Sign extend before setting the destination value: */ \
     2824            cShift -= 7 + 1; \
     2825            if (uTmp & RT_BIT_64(cShift)) \
     2826                uTmp |= ~(RT_BIT_64(cShift) - 1); \
     2827            (a_uDst) = (int64_t)uTmp; \
     2828        } \
     2829    } while (0)
     2830
     2831#define SKIP_BLOCK() \
     2832    do \
     2833    { \
     2834        uint16_t cbBlock; \
     2835        GET_ULEB128_AS_U14(cbBlock); \
     2836        AssertReturn(offInstr + cbBlock <= cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
     2837        offInstr += cbBlock; \
     2838    } while (0)
     2839
     2840
     2841static int rtDwarfUnwind_Execute(PRTDWARFCFEXEC pExecState, uint8_t const *pbInstr, uint32_t cbInstr)
     2842{
     2843    PRTDWARFCFROW pRow = pExecState->pRow;
     2844    for (uint32_t offInstr = 0; offInstr < cbInstr;)
     2845    {
     2846        /*
     2847         * Instruction switches.
     2848         */
     2849        uint8_t const bInstr = pbInstr[offInstr++];
     2850        switch (bInstr & DW_CFA_high_bit_mask)
     2851        {
     2852            case DW_CFA_advance_loc:
     2853            {
     2854                uint8_t const cbAdvance = bInstr & ~DW_CFA_high_bit_mask;
     2855                if (cbAdvance > pExecState->cbLeftToAdvance)
     2856                    return VINF_SUCCESS;
     2857                pExecState->cbLeftToAdvance -= cbAdvance;
     2858                break;
     2859            }
     2860
     2861            case DW_CFA_offset:
     2862            {
     2863                uint8_t iReg = bInstr & ~DW_CFA_high_bit_mask;
     2864                if (iReg < RT_ELEMENTS(pRow->apbRegInstrs))
     2865                    pRow->apbRegInstrs[iReg] = &pbInstr[offInstr - 1];
     2866                SKIP_ULEB128_OR_LEB128();
     2867                break;
     2868            }
     2869
     2870            case 0:
     2871                switch (bInstr)
     2872                {
     2873                    case DW_CFA_nop:
     2874                        break;
     2875
     2876                    /*
     2877                     * Register instructions.
     2878                     */
     2879                    case DW_CFA_register:
     2880                    case DW_CFA_offset_extended:
     2881                    case DW_CFA_offset_extended_sf:
     2882                    case DW_CFA_val_offset:
     2883                    case DW_CFA_val_offset_sf:
     2884                    {
     2885                        uint8_t const * const pbCurInstr = &pbInstr[offInstr - 1];
     2886                        uint16_t              iReg;
     2887                        GET_ULEB128_AS_U14(iReg);
     2888                        if (iReg < RT_ELEMENTS(pRow->apbRegInstrs))
     2889                            pRow->apbRegInstrs[iReg] = pbCurInstr;
     2890                        SKIP_ULEB128_OR_LEB128();
     2891                        break;
     2892                    }
     2893
     2894                    case DW_CFA_expression:
     2895                    case DW_CFA_val_expression:
     2896                    {
     2897                        uint8_t const * const pbCurInstr = &pbInstr[offInstr - 1];
     2898                        uint16_t              iReg;
     2899                        GET_ULEB128_AS_U14(iReg);
     2900                        if (iReg < RT_ELEMENTS(pRow->apbRegInstrs))
     2901                            pRow->apbRegInstrs[iReg] = pbCurInstr;
     2902                        SKIP_BLOCK();
     2903                        break;
     2904                    }
     2905
     2906                    case DW_CFA_restore_extended:
     2907                    {
     2908                        uint8_t const * const pbCurInstr = &pbInstr[offInstr - 1];
     2909                        uint16_t              iReg;
     2910                        GET_ULEB128_AS_U14(iReg);
     2911                        if (iReg < RT_ELEMENTS(pRow->apbRegInstrs))
     2912                            pRow->apbRegInstrs[iReg] = pbCurInstr;
     2913                        break;
     2914                    }
     2915
     2916                    case DW_CFA_undefined:
     2917                    {
     2918                        uint16_t iReg;
     2919                        GET_ULEB128_AS_U14(iReg);
     2920                        if (iReg < RT_ELEMENTS(pRow->apbRegInstrs))
     2921                            pRow->apbRegInstrs[iReg] = NULL;
     2922                        break;
     2923                    }
     2924
     2925                    case DW_CFA_same_value:
     2926                    {
     2927                        uint8_t const * const pbCurInstr = &pbInstr[offInstr - 1];
     2928                        uint16_t              iReg;
     2929                        GET_ULEB128_AS_U14(iReg);
     2930                        if (iReg < RT_ELEMENTS(pRow->apbRegInstrs))
     2931                            pRow->apbRegInstrs[iReg] = pbCurInstr;
     2932                        break;
     2933                    }
     2934
     2935
     2936                    /*
     2937                     * CFA instructions.
     2938                     */
     2939                    case DW_CFA_def_cfa:
     2940                    {
     2941                        GET_ULEB128_AS_U14(pRow->uCfaBaseReg);
     2942                        uint64_t offCfaReg;
     2943                        GET_ULEB128_AS_U63(offCfaReg);
     2944                        pRow->offCfaReg        = offCfaReg;
     2945                        pRow->pbCfaExprInstr   = NULL;
     2946                        pRow->fCfaDefined      = true;
     2947                        break;
     2948                    }
     2949
     2950                    case DW_CFA_def_cfa_register:
     2951                    {
     2952                        GET_ULEB128_AS_U14(pRow->uCfaBaseReg);
     2953                        pRow->pbCfaExprInstr   = NULL;
     2954                        pRow->fCfaDefined      = true;
     2955                        /* Leaves offCfaReg as is. */
     2956                        break;
     2957                    }
     2958
     2959                    case DW_CFA_def_cfa_offset:
     2960                    {
     2961                        uint64_t offCfaReg;
     2962                        GET_ULEB128_AS_U63(offCfaReg);
     2963                        pRow->offCfaReg        = offCfaReg;
     2964                        pRow->pbCfaExprInstr   = NULL;
     2965                        pRow->fCfaDefined      = true;
     2966                        /* Leaves uCfaBaseReg as is. */
     2967                        break;
     2968                    }
     2969
     2970                    case DW_CFA_def_cfa_sf:
     2971                        GET_ULEB128_AS_U14(pRow->uCfaBaseReg);
     2972                        GET_LEB128_AS_I63(pRow->offCfaReg);
     2973                        pRow->pbCfaExprInstr   = NULL;
     2974                        pRow->fCfaDefined      = true;
     2975                        break;
     2976
     2977                    case DW_CFA_def_cfa_offset_sf:
     2978                        GET_LEB128_AS_I63(pRow->offCfaReg);
     2979                        pRow->pbCfaExprInstr   = NULL;
     2980                        pRow->fCfaDefined      = true;
     2981                        /* Leaves uCfaBaseReg as is. */
     2982                        break;
     2983
     2984                    case DW_CFA_def_cfa_expression:
     2985                        pRow->pbCfaExprInstr   = &pbInstr[offInstr - 1];
     2986                        pRow->fCfaDefined      = true;
     2987                        SKIP_BLOCK();
     2988                        break;
     2989
     2990                    /*
     2991                     * Less likely instructions:
     2992                     */
     2993                    case DW_CFA_advance_loc1:
     2994                    {
     2995                        AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
     2996                        uint8_t const cbAdvance = pbInstr[offInstr++];
     2997                        if (cbAdvance > pExecState->cbLeftToAdvance)
     2998                            return VINF_SUCCESS;
     2999                        pExecState->cbLeftToAdvance -= cbAdvance;
     3000                        break;
     3001                    }
     3002
     3003                    case DW_CFA_advance_loc2:
     3004                    {
     3005                        AssertReturn(offInstr + 1 < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
     3006                        uint16_t const cbAdvance = pExecState->fLittleEndian
     3007                                                 ? RT_MAKE_U16(pbInstr[offInstr], pbInstr[offInstr + 1])
     3008                                                 : RT_MAKE_U16(pbInstr[offInstr + 1], pbInstr[offInstr]);
     3009                        if (cbAdvance > pExecState->cbLeftToAdvance)
     3010                            return VINF_SUCCESS;
     3011                        pExecState->cbLeftToAdvance -= cbAdvance;
     3012                        offInstr += 2;
     3013                        break;
     3014                    }
     3015
     3016                    case DW_CFA_advance_loc4:
     3017                    {
     3018                        AssertReturn(offInstr + 3 < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
     3019                        uint32_t const cbAdvance = pExecState->fLittleEndian
     3020                                                 ? RT_MAKE_U32_FROM_U8(pbInstr[offInstr + 0], pbInstr[offInstr + 1],
     3021                                                                       pbInstr[offInstr + 2], pbInstr[offInstr + 3])
     3022                                                 : RT_MAKE_U32_FROM_U8(pbInstr[offInstr + 3], pbInstr[offInstr + 2],
     3023                                                                       pbInstr[offInstr + 1], pbInstr[offInstr + 0]);
     3024                        if (cbAdvance > pExecState->cbLeftToAdvance)
     3025                            return VINF_SUCCESS;
     3026                        pExecState->cbLeftToAdvance -= cbAdvance;
     3027                        offInstr += 4;
     3028                        break;
     3029                    }
     3030
     3031                    /*
     3032                     * This bugger is really annoying and probably never used.
     3033                     */
     3034                    case DW_CFA_set_loc:
     3035                    {
     3036                        /* Ignore the segment number. */
     3037                        if (pExecState->pCie->cbSegment)
     3038                        {
     3039                            offInstr += pExecState->pCie->cbSegment;
     3040                            AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
     3041                        }
     3042
     3043                        /* Retrieve the address. sigh. */
     3044                        uint64_t uAddress;
     3045                        switch (pExecState->pCie->bAddressPtrEnc & (DW_EH_PE_FORMAT_MASK | DW_EH_PE_indirect))
     3046                        {
     3047                            case DW_EH_PE_udata2:
     3048                                AssertReturn(offInstr + 1 < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
     3049                                if (pExecState->fLittleEndian)
     3050                                    uAddress = RT_MAKE_U16(pbInstr[offInstr], pbInstr[offInstr + 1]);
     3051                                else
     3052                                    uAddress = RT_MAKE_U16(pbInstr[offInstr + 1], pbInstr[offInstr]);
     3053                                offInstr += 2;
     3054                                break;
     3055                            case DW_EH_PE_sdata2:
     3056                                AssertReturn(offInstr + 1 < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
     3057                                if (pExecState->fLittleEndian)
     3058                                    uAddress = (int64_t)(int16_t)RT_MAKE_U16(pbInstr[offInstr], pbInstr[offInstr + 1]);
     3059                                else
     3060                                    uAddress = (int64_t)(int16_t)RT_MAKE_U16(pbInstr[offInstr + 1], pbInstr[offInstr]);
     3061                                offInstr += 2;
     3062                                break;
     3063                            case DW_EH_PE_udata4:
     3064                                AssertReturn(offInstr + 3 < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
     3065                                if (pExecState->fLittleEndian)
     3066                                    uAddress = RT_MAKE_U32_FROM_U8(pbInstr[offInstr + 0], pbInstr[offInstr + 1],
     3067                                                                   pbInstr[offInstr + 2], pbInstr[offInstr + 3]);
     3068                                else
     3069                                    uAddress = RT_MAKE_U32_FROM_U8(pbInstr[offInstr + 3], pbInstr[offInstr + 2],
     3070                                                                   pbInstr[offInstr + 1], pbInstr[offInstr + 0]);
     3071
     3072                                offInstr += 4;
     3073                                break;
     3074                            case DW_EH_PE_sdata4:
     3075                                AssertReturn(offInstr + 3 < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
     3076                                if (pExecState->fLittleEndian)
     3077                                    uAddress = (int64_t)(int32_t)RT_MAKE_U32_FROM_U8(pbInstr[offInstr + 0], pbInstr[offInstr + 1],
     3078                                                                                     pbInstr[offInstr + 2], pbInstr[offInstr + 3]);
     3079                                else
     3080                                    uAddress = (int64_t)(int32_t)RT_MAKE_U32_FROM_U8(pbInstr[offInstr + 3], pbInstr[offInstr + 2],
     3081                                                                                     pbInstr[offInstr + 1], pbInstr[offInstr + 0]);
     3082                                offInstr += 4;
     3083                                break;
     3084                            case DW_EH_PE_udata8:
     3085                            case DW_EH_PE_sdata8:
     3086                                AssertReturn(offInstr + 7 < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
     3087                                if (pExecState->fLittleEndian)
     3088                                    uAddress = RT_MAKE_U64_FROM_U8(pbInstr[offInstr + 0], pbInstr[offInstr + 1],
     3089                                                                   pbInstr[offInstr + 2], pbInstr[offInstr + 3],
     3090                                                                   pbInstr[offInstr + 4], pbInstr[offInstr + 5],
     3091                                                                   pbInstr[offInstr + 6], pbInstr[offInstr + 7]);
     3092                                else
     3093                                    uAddress = RT_MAKE_U64_FROM_U8(pbInstr[offInstr + 7], pbInstr[offInstr + 6],
     3094                                                                   pbInstr[offInstr + 5], pbInstr[offInstr + 4],
     3095                                                                   pbInstr[offInstr + 3], pbInstr[offInstr + 2],
     3096                                                                   pbInstr[offInstr + 1], pbInstr[offInstr + 0]);
     3097                                offInstr += 8;
     3098                                break;
     3099                            case DW_EH_PE_sleb128:
     3100                            case DW_EH_PE_uleb128:
     3101                            default:
     3102                                AssertMsgFailedReturn(("%#x\n", pExecState->pCie->bAddressPtrEnc), VERR_DWARF_TODO);
     3103                        }
     3104                        AssertReturn(uAddress >= pExecState->uPcBegin, VERR_DBG_MALFORMED_UNWIND_INFO);
     3105
     3106                        /* Did we advance past the desire address already? */
     3107                        if (uAddress > pExecState->uPcBegin + pExecState->offInRange)
     3108                            return VINF_SUCCESS;
     3109                        pExecState->cbLeftToAdvance = pExecState->uPcBegin + pExecState->offInRange - uAddress;
     3110                        break;
     3111
     3112
     3113                        /*
     3114                         * Row state push/pop instructions.
     3115                         */
     3116
     3117                        case DW_CFA_remember_state:
     3118                        {
     3119                            AssertReturn(pExecState->cPushes < 10, VERR_DBG_MALFORMED_UNWIND_INFO);
     3120                            PRTDWARFCFROW pNewRow = (PRTDWARFCFROW)RTMemTmpAlloc(sizeof(*pNewRow));
     3121                            AssertReturn(pNewRow, VERR_NO_TMP_MEMORY);
     3122                            memcpy(pNewRow, pRow, sizeof(*pNewRow));
     3123                            pNewRow->pNextOnStack = pRow;
     3124                            pNewRow->fOnHeap      = true;
     3125                            pExecState->pRow      = pNewRow;
     3126                            pExecState->cPushes  += 1;
     3127                            pRow = pNewRow;
     3128                            break;
     3129                        }
     3130
     3131                        case DW_CFA_restore_state:
     3132                            AssertReturn(pRow->pNextOnStack, VERR_DBG_MALFORMED_UNWIND_INFO);
     3133                            Assert(pRow->fOnHeap);
     3134                            Assert(pExecState->cPushes > 0);
     3135                            pExecState->cPushes -= 1;
     3136                            pExecState->pRow     = pRow->pNextOnStack;
     3137                            RTMemTmpFree(pRow);
     3138                            pRow = pExecState->pRow;
     3139                            break;
     3140                    }
     3141                }
     3142                break;
     3143
     3144            case DW_CFA_restore:
     3145            {
     3146                uint8_t const * const pbCurInstr = &pbInstr[offInstr - 1];
     3147                uint8_t const         iReg       = bInstr & ~DW_CFA_high_bit_mask;
     3148                if (iReg < RT_ELEMENTS(pRow->apbRegInstrs))
     3149                    pRow->apbRegInstrs[iReg] = pbCurInstr;
     3150                break;
     3151            }
     3152        }
     3153    }
     3154    return VINF_TRY_AGAIN;
     3155}
     3156
     3157
     3158/**
     3159 * Register getter for AMD64.
     3160 *
     3161 * @returns true if found, false if not.
     3162 * @param   pState              The unwind state to get the register from.
     3163 * @param   iReg                The dwarf register number.
     3164 * @param   puValue             Where to store the register value.
     3165 */
     3166static bool rtDwarfUnwind_Amd64GetRegFromState(PCRTDBGUNWINDSTATE pState, uint16_t iReg, uint64_t *puValue)
     3167{
     3168    switch (iReg)
     3169    {
     3170        case DWREG_AMD64_RAX:       *puValue = pState->u.x86.auRegs[X86_GREG_xAX];  return true;
     3171        case DWREG_AMD64_RDX:       *puValue = pState->u.x86.auRegs[X86_GREG_xDX];  return true;
     3172        case DWREG_AMD64_RCX:       *puValue = pState->u.x86.auRegs[X86_GREG_xCX];  return true;
     3173        case DWREG_AMD64_RBX:       *puValue = pState->u.x86.auRegs[X86_GREG_xBX];  return true;
     3174        case DWREG_AMD64_RSI:       *puValue = pState->u.x86.auRegs[X86_GREG_xSI];  return true;
     3175        case DWREG_AMD64_RDI:       *puValue = pState->u.x86.auRegs[X86_GREG_xDI];  return true;
     3176        case DWREG_AMD64_RBP:       *puValue = pState->u.x86.auRegs[X86_GREG_xBP];  return true;
     3177        case DWREG_AMD64_RSP:       *puValue = pState->u.x86.auRegs[X86_GREG_xSP];  return true;
     3178        case DWREG_AMD64_R8:        *puValue = pState->u.x86.auRegs[X86_GREG_x8];   return true;
     3179        case DWREG_AMD64_R9:        *puValue = pState->u.x86.auRegs[X86_GREG_x9];   return true;
     3180        case DWREG_AMD64_R10:       *puValue = pState->u.x86.auRegs[X86_GREG_x10];  return true;
     3181        case DWREG_AMD64_R11:       *puValue = pState->u.x86.auRegs[X86_GREG_x11];  return true;
     3182        case DWREG_AMD64_R12:       *puValue = pState->u.x86.auRegs[X86_GREG_x12];  return true;
     3183        case DWREG_AMD64_R13:       *puValue = pState->u.x86.auRegs[X86_GREG_x13];  return true;
     3184        case DWREG_AMD64_R14:       *puValue = pState->u.x86.auRegs[X86_GREG_x14];  return true;
     3185        case DWREG_AMD64_R15:       *puValue = pState->u.x86.auRegs[X86_GREG_x15];  return true;
     3186        case DWREG_AMD64_RFLAGS:    *puValue = pState->u.x86.uRFlags;               return true;
     3187        case DWREG_AMD64_ES:        *puValue = pState->u.x86.auSegs[X86_SREG_ES];   return true;
     3188        case DWREG_AMD64_CS:        *puValue = pState->u.x86.auSegs[X86_SREG_CS];   return true;
     3189        case DWREG_AMD64_SS:        *puValue = pState->u.x86.auSegs[X86_SREG_SS];   return true;
     3190        case DWREG_AMD64_DS:        *puValue = pState->u.x86.auSegs[X86_SREG_DS];   return true;
     3191        case DWREG_AMD64_FS:        *puValue = pState->u.x86.auSegs[X86_SREG_FS];   return true;
     3192        case DWREG_AMD64_GS:        *puValue = pState->u.x86.auSegs[X86_SREG_GS];   return true;
     3193    }
     3194    return false;
     3195}
     3196
     3197
     3198/**
     3199 * Register getter for 386+.
     3200 *
     3201 * @returns true if found, false if not.
     3202 * @param   pState              The unwind state to get the register from.
     3203 * @param   iReg                The dwarf register number.
     3204 * @param   puValue             Where to store the register value.
     3205 */
     3206static bool rtDwarfUnwind_X86GetRegFromState(PCRTDBGUNWINDSTATE pState, uint16_t iReg, uint64_t *puValue)
     3207{
     3208    switch (iReg)
     3209    {
     3210        case DWREG_X86_EAX:         *puValue = pState->u.x86.auRegs[X86_GREG_xAX];  return true;
     3211        case DWREG_X86_ECX:         *puValue = pState->u.x86.auRegs[X86_GREG_xCX];  return true;
     3212        case DWREG_X86_EDX:         *puValue = pState->u.x86.auRegs[X86_GREG_xDX];  return true;
     3213        case DWREG_X86_EBX:         *puValue = pState->u.x86.auRegs[X86_GREG_xBX];  return true;
     3214        case DWREG_X86_ESP:         *puValue = pState->u.x86.auRegs[X86_GREG_xSP];  return true;
     3215        case DWREG_X86_EBP:         *puValue = pState->u.x86.auRegs[X86_GREG_xBP];  return true;
     3216        case DWREG_X86_ESI:         *puValue = pState->u.x86.auRegs[X86_GREG_xSI];  return true;
     3217        case DWREG_X86_EDI:         *puValue = pState->u.x86.auRegs[X86_GREG_xDI];  return true;
     3218        case DWREG_X86_EFLAGS:      *puValue = pState->u.x86.uRFlags;               return true;
     3219        case DWREG_X86_ES:          *puValue = pState->u.x86.auSegs[X86_SREG_ES];   return true;
     3220        case DWREG_X86_CS:          *puValue = pState->u.x86.auSegs[X86_SREG_CS];   return true;
     3221        case DWREG_X86_SS:          *puValue = pState->u.x86.auSegs[X86_SREG_SS];   return true;
     3222        case DWREG_X86_DS:          *puValue = pState->u.x86.auSegs[X86_SREG_DS];   return true;
     3223        case DWREG_X86_FS:          *puValue = pState->u.x86.auSegs[X86_SREG_FS];   return true;
     3224        case DWREG_X86_GS:          *puValue = pState->u.x86.auSegs[X86_SREG_GS];   return true;
     3225    }
     3226    return false;
     3227}
     3228
     3229/** Register getter. */
     3230typedef bool FNDWARFUNWINDGEREGFROMSTATE(PCRTDBGUNWINDSTATE pState, uint16_t iReg, uint64_t *puValue);
     3231/** Pointer to a register getter. */
     3232typedef FNDWARFUNWINDGEREGFROMSTATE *PFNDWARFUNWINDGEREGFROMSTATE;
     3233
     3234
     3235
     3236/**
     3237 * Does the heavy work for figuring out the return value of a register.
     3238 *
     3239 * @returns IPRT status code.
     3240 * @retval  VERR_NOT_FOUND if register is undefined.
     3241 *
     3242 * @param   pRow        The DWARF unwind table "row" to use.
     3243 * @param   uReg        The DWARF register number.
     3244 * @param   pCie        The corresponding CIE.
     3245 * @param   uCfa        The canonical frame address to use.
     3246 * @param   pState      The unwind to use when reading stack.
     3247 * @param   pOldState   The unwind state to get register values from.
     3248 * @param   pfnGetReg   The register value getter.
     3249 * @param   puValue     Where to store the return value.
     3250 * @param   cbValue     The size this register would have on the stack.
     3251 */
     3252static int rtDwarfUnwind_CalcRegisterValue(PRTDWARFCFROW pRow, unsigned uReg, PCRTDWARFCIEINFO pCie, uint64_t uCfa,
     3253                                           PRTDBGUNWINDSTATE pState, PCRTDBGUNWINDSTATE pOldState,
     3254                                           PFNDWARFUNWINDGEREGFROMSTATE pfnGetReg, uint64_t *puValue, uint8_t cbValue)
     3255{
     3256    Assert(uReg < RT_ELEMENTS(pRow->apbRegInstrs));
     3257    uint8_t const *pbInstr = pRow->apbRegInstrs[uReg];
     3258    if (!pbInstr)
     3259        return VERR_NOT_FOUND;
     3260
     3261    uint32_t      cbInstr  = UINT32_MAX / 2;
     3262    uint32_t      offInstr = 1;
     3263    uint8_t const bInstr   = *pbInstr;
     3264    switch (bInstr)
     3265    {
     3266        default:
     3267            if ((bInstr & DW_CFA_high_bit_mask) == DW_CFA_offset)
     3268            {
     3269                uint64_t offCfa;
     3270                GET_ULEB128_AS_U63(offCfa);
     3271                int rc = pState->pfnReadStack(pState, uCfa + (int64_t)offCfa * pCie->iDataAlignFactor, cbValue, puValue);
     3272                Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_offset %#RX64: %Rrc, %#RX64\n", uReg, uCfa + (int64_t)offCfa * pCie->iDataAlignFactor, rc, *puValue));
     3273                return rc;
     3274            }
     3275            AssertReturn((bInstr & DW_CFA_high_bit_mask) == DW_CFA_restore, VERR_INTERNAL_ERROR);
     3276            RT_FALL_THRU();
     3277        case DW_CFA_restore_extended:
     3278            /* Need to search the CIE for the rule. */
     3279            Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_restore/extended:\n", uReg));
     3280            AssertFailedReturn(VERR_DWARF_TODO);
     3281
     3282        case DW_CFA_offset_extended:
     3283        {
     3284            SKIP_ULEB128_OR_LEB128();
     3285            uint64_t offCfa;
     3286            GET_ULEB128_AS_U63(offCfa);
     3287            int rc = pState->pfnReadStack(pState, uCfa + (int64_t)offCfa * pCie->iDataAlignFactor, cbValue, puValue);
     3288            Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_offset_extended %#RX64: %Rrc, %#RX64\n", uReg, uCfa + (int64_t)offCfa * pCie->iDataAlignFactor, rc, *puValue));
     3289            return rc;
     3290        }
     3291
     3292        case DW_CFA_offset_extended_sf:
     3293        {
     3294            SKIP_ULEB128_OR_LEB128();
     3295            int64_t offCfa;
     3296            GET_LEB128_AS_I63(offCfa);
     3297            int rc = pState->pfnReadStack(pState, uCfa + offCfa * pCie->iDataAlignFactor, cbValue, puValue);
     3298            Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_offset_extended_sf %#RX64: %Rrc, %#RX64\n", uReg, uCfa + offCfa * pCie->iDataAlignFactor, rc, *puValue));
     3299            return rc;
     3300        }
     3301
     3302        case DW_CFA_val_offset:
     3303        {
     3304            SKIP_ULEB128_OR_LEB128();
     3305            uint64_t offCfa;
     3306            GET_ULEB128_AS_U63(offCfa);
     3307            *puValue = uCfa + (int64_t)offCfa * pCie->iDataAlignFactor;
     3308            Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_val_offset: %#RX64\n", uReg, *puValue));
     3309            return VINF_SUCCESS;
     3310        }
     3311
     3312        case DW_CFA_val_offset_sf:
     3313        {
     3314            SKIP_ULEB128_OR_LEB128();
     3315            int64_t offCfa;
     3316            GET_LEB128_AS_I63(offCfa);
     3317            *puValue = uCfa + offCfa * pCie->iDataAlignFactor;
     3318            Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_val_offset_sf: %#RX64\n", uReg, *puValue));
     3319            return VINF_SUCCESS;
     3320        }
     3321
     3322        case DW_CFA_register:
     3323        {
     3324            SKIP_ULEB128_OR_LEB128();
     3325            uint16_t iSrcReg;
     3326            GET_ULEB128_AS_U14(iSrcReg);
     3327            if (pfnGetReg(pOldState, uReg, puValue))
     3328            {
     3329                Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_register: %#RX64\n", uReg, *puValue));
     3330                return VINF_SUCCESS;
     3331            }
     3332            Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_register: VERR_NOT_FOUND\n", uReg));
     3333            return VERR_NOT_FOUND;
     3334        }
     3335
     3336        case DW_CFA_expression:
     3337            Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_expression: TODO\n", uReg));
     3338            AssertFailedReturn(VERR_DWARF_TODO);
     3339
     3340        case DW_CFA_val_expression:
     3341            Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_val_expression: TODO\n", uReg));
     3342            AssertFailedReturn(VERR_DWARF_TODO);
     3343
     3344        case DW_CFA_undefined:
     3345            Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_undefined\n", uReg));
     3346            return VERR_NOT_FOUND;
     3347
     3348        case DW_CFA_same_value:
     3349            if (pfnGetReg(pOldState, uReg, puValue))
     3350            {
     3351                Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_same_value: %#RX64\n", uReg, *puValue));
     3352                return VINF_SUCCESS;
     3353            }
     3354            Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_same_value: VERR_NOT_FOUND\n", uReg));
     3355            return VERR_NOT_FOUND;
     3356    }
     3357}
     3358
     3359
     3360DECLINLINE(void) rtDwarfUnwind_UpdateX86GRegFromRow(PRTDBGUNWINDSTATE pState, PCRTDBGUNWINDSTATE pOldState, unsigned idxGReg,
     3361                                                    PRTDWARFCFROW pRow, unsigned idxDwReg, PCRTDWARFCIEINFO pCie,
     3362                                                    uint64_t uCfa, PFNDWARFUNWINDGEREGFROMSTATE pfnGetReg, uint8_t cbGReg)
     3363{
     3364    int rc = rtDwarfUnwind_CalcRegisterValue(pRow, idxDwReg, pCie, uCfa, pState, pOldState, pfnGetReg,
     3365                                             &pState->u.x86.auRegs[idxGReg], cbGReg);
     3366    if (RT_SUCCESS(rc))
     3367        pState->u.x86.Loaded.s.fRegs |= RT_BIT_32(idxGReg);
     3368}
     3369
     3370
     3371DECLINLINE(void) rtDwarfUnwind_UpdateX86SRegFromRow(PRTDBGUNWINDSTATE pState, PCRTDBGUNWINDSTATE pOldState, unsigned idxSReg,
     3372                                                    PRTDWARFCFROW pRow, unsigned idxDwReg, PCRTDWARFCIEINFO pCie,
     3373                                                    uint64_t uCfa, PFNDWARFUNWINDGEREGFROMSTATE pfnGetReg)
     3374{
     3375    uint64_t uValue = pState->u.x86.auSegs[idxSReg];
     3376    int rc = rtDwarfUnwind_CalcRegisterValue(pRow, idxDwReg, pCie, uCfa, pState, pOldState, pfnGetReg, &uValue, sizeof(uint16_t));
     3377    if (RT_SUCCESS(rc))
     3378    {
     3379        pState->u.x86.auSegs[idxSReg] = (uint16_t)uValue;
     3380        pState->u.x86.Loaded.s.fSegs |= RT_BIT_32(idxSReg);
     3381    }
     3382}
     3383
     3384
     3385DECLINLINE(void) rtDwarfUnwind_UpdateX86RFlagsFromRow(PRTDBGUNWINDSTATE pState, PCRTDBGUNWINDSTATE pOldState,
     3386                                                      PRTDWARFCFROW pRow, unsigned idxDwReg, PCRTDWARFCIEINFO pCie,
     3387                                                      uint64_t uCfa, PFNDWARFUNWINDGEREGFROMSTATE pfnGetReg)
     3388{
     3389    int rc = rtDwarfUnwind_CalcRegisterValue(pRow, idxDwReg, pCie, uCfa, pState, pOldState, pfnGetReg,
     3390                                             &pState->u.x86.uRFlags, sizeof(uint32_t));
     3391    if (RT_SUCCESS(rc))
     3392        pState->u.x86.Loaded.s.fRFlags = 1;
     3393}
     3394
     3395
     3396DECLINLINE(void) rtDwarfUnwind_UpdatePCFromRow(PRTDBGUNWINDSTATE pState, PCRTDBGUNWINDSTATE pOldState,
     3397                                               PRTDWARFCFROW pRow, unsigned idxDwReg, PCRTDWARFCIEINFO pCie,
     3398                                               uint64_t uCfa, PFNDWARFUNWINDGEREGFROMSTATE pfnGetReg, uint8_t cbPc)
     3399{
     3400    if (pCie->bRetReg != UINT8_MAX)
     3401        idxDwReg = pCie->bRetReg;
     3402    int rc = rtDwarfUnwind_CalcRegisterValue(pRow, idxDwReg, pCie, uCfa, pState, pOldState, pfnGetReg, &pState->uPc, cbPc);
     3403    if (RT_SUCCESS(rc))
     3404        pState->u.x86.Loaded.s.fPc = 1;
     3405    else
     3406    {
     3407        rc = pState->pfnReadStack(pState, uCfa - cbPc, cbPc, &pState->uPc);
     3408        if (RT_SUCCESS(rc))
     3409            pState->u.x86.Loaded.s.fPc = 1;
     3410    }
     3411}
     3412
     3413
     3414
     3415/**
     3416 * Updates @a pState with the rules found in @a pRow.
     3417 *
     3418 * @returns IPRT status code.
     3419 * @param   pState          The unwind state to update.
     3420 * @param   pRow            The "row" in the dwarf unwind table.
     3421 * @param   pCie            The CIE structure for the row.
     3422 */
     3423static int rtDwarfUnwind_UpdateStateFromRow(PRTDBGUNWINDSTATE pState, PRTDWARFCFROW pRow, PCRTDWARFCIEINFO pCie)
     3424{
     3425    /*
     3426     * We need to make a copy of the current state so we can get at the
     3427     * current register values while calculating the ones of the next frame.
     3428     */
     3429    RTDBGUNWINDSTATE const Old = *pState;
     3430
     3431    /*
     3432     * Get the register state getter.
     3433     */
     3434    PFNDWARFUNWINDGEREGFROMSTATE pfnGetReg;
     3435    switch (pState->enmArch)
     3436    {
     3437        case RTLDRARCH_AMD64:
     3438            pfnGetReg = rtDwarfUnwind_Amd64GetRegFromState;
     3439            break;
     3440        case RTLDRARCH_X86_32:
     3441        case RTLDRARCH_X86_16:
     3442            pfnGetReg = rtDwarfUnwind_X86GetRegFromState;
     3443            break;
     3444        default:
     3445            return VERR_NOT_SUPPORTED;
     3446    }
     3447
     3448    /*
     3449     * Calc the canonical frame address for the current row.
     3450     */
     3451    AssertReturn(pRow->fCfaDefined, VERR_DBG_MALFORMED_UNWIND_INFO);
     3452    uint64_t uCfa = 0;
     3453    if (!pRow->pbCfaExprInstr)
     3454    {
     3455        pfnGetReg(&Old, pRow->uCfaBaseReg, &uCfa);
     3456        uCfa += pRow->offCfaReg;
     3457    }
     3458    else
     3459    {
     3460        AssertFailed();
     3461        return VERR_DWARF_TODO;
     3462    }
     3463    Log8(("rtDwarfUnwind_UpdateStateFromRow: uCfa=%RX64\n", uCfa));
     3464
     3465    /*
     3466     * Do the architecture specific register updating.
     3467     */
     3468    switch (pState->enmArch)
     3469    {
     3470        case RTLDRARCH_AMD64:
     3471            pState->u.x86.FrameAddr.off       = uCfa - 8*2;
     3472            pState->u.x86.Loaded.fAll         = 0;
     3473            pState->u.x86.Loaded.s.fFrameAddr = 1;
     3474            rtDwarfUnwind_UpdatePCFromRow(pState, &Old,                    pRow, DWREG_AMD64_RA,  pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3475            rtDwarfUnwind_UpdateX86RFlagsFromRow(pState, &Old,             pRow, DWREG_AMD64_RFLAGS, pCie, uCfa, pfnGetReg);
     3476            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xAX, pRow, DWREG_AMD64_RAX, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3477            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xCX, pRow, DWREG_AMD64_RCX, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3478            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xDX, pRow, DWREG_AMD64_RDX, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3479            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xBX, pRow, DWREG_AMD64_RBX, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3480            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xSP, pRow, DWREG_AMD64_RSP, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3481            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xBP, pRow, DWREG_AMD64_RBP, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3482            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xSI, pRow, DWREG_AMD64_RSI, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3483            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xDI, pRow, DWREG_AMD64_RDI, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3484            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x8,  pRow, DWREG_AMD64_R8,  pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3485            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x9,  pRow, DWREG_AMD64_R9,  pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3486            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x10, pRow, DWREG_AMD64_R10, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3487            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x11, pRow, DWREG_AMD64_R11, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3488            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x12, pRow, DWREG_AMD64_R12, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3489            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x13, pRow, DWREG_AMD64_R13, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3490            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x14, pRow, DWREG_AMD64_R14, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3491            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x15, pRow, DWREG_AMD64_R15, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
     3492            rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_ES,  pRow, DWREG_AMD64_ES,  pCie, uCfa, pfnGetReg);
     3493            rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_CS,  pRow, DWREG_AMD64_CS,  pCie, uCfa, pfnGetReg);
     3494            rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_SS,  pRow, DWREG_AMD64_SS,  pCie, uCfa, pfnGetReg);
     3495            rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_DS,  pRow, DWREG_AMD64_DS,  pCie, uCfa, pfnGetReg);
     3496            rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_FS,  pRow, DWREG_AMD64_FS,  pCie, uCfa, pfnGetReg);
     3497            rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_GS,  pRow, DWREG_AMD64_GS,  pCie, uCfa, pfnGetReg);
     3498            break;
     3499
     3500        case RTLDRARCH_X86_32:
     3501        case RTLDRARCH_X86_16:
     3502            pState->u.x86.FrameAddr.off       = uCfa - 4*2;
     3503            pState->u.x86.Loaded.fAll         = 0;
     3504            pState->u.x86.Loaded.s.fFrameAddr = 1;
     3505            rtDwarfUnwind_UpdatePCFromRow(pState, &Old,                    pRow, DWREG_X86_RA,  pCie, uCfa, pfnGetReg, sizeof(uint32_t));
     3506            rtDwarfUnwind_UpdateX86RFlagsFromRow(pState, &Old,             pRow, DWREG_X86_EFLAGS, pCie, uCfa, pfnGetReg);
     3507            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xAX, pRow, DWREG_X86_EAX, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
     3508            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xCX, pRow, DWREG_X86_ECX, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
     3509            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xDX, pRow, DWREG_X86_EDX, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
     3510            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xBX, pRow, DWREG_X86_EBX, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
     3511            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xSP, pRow, DWREG_X86_ESP, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
     3512            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xBP, pRow, DWREG_X86_EBP, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
     3513            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xSI, pRow, DWREG_X86_ESI, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
     3514            rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xDI, pRow, DWREG_X86_EDI, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
     3515            rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_ES,  pRow, DWREG_X86_ES,  pCie, uCfa, pfnGetReg);
     3516            rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_CS,  pRow, DWREG_X86_CS,  pCie, uCfa, pfnGetReg);
     3517            rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_SS,  pRow, DWREG_X86_SS,  pCie, uCfa, pfnGetReg);
     3518            rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_DS,  pRow, DWREG_X86_DS,  pCie, uCfa, pfnGetReg);
     3519            rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_FS,  pRow, DWREG_X86_FS,  pCie, uCfa, pfnGetReg);
     3520            rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_GS,  pRow, DWREG_X86_GS,  pCie, uCfa, pfnGetReg);
     3521            break;
     3522
     3523        default:
     3524            AssertFailedReturn(VERR_NOT_SUPPORTED);
     3525    }
     3526
     3527    return VINF_SUCCESS;
     3528}
     3529
    25863530
    25873531/**
     
    26363580
    26373581    /*
    2638      * The crazy part.  Table program execution.
     3582     * Now "execute" the programs till we've constructed the desired row.
    26393583     */
    2640     if (pCie->cbInstructions > 0)
    2641     {
    2642         /** @todo continue here later.   */
    2643     }
     3584    RTDWARFCFROW            Row;
     3585    RTDWARFCFEXEC           ExecState = { &Row, offInRange, 0, true /** @todo byte-order*/, pCie, uPcBegin, offInRange };
     3586    RT_ZERO(Row);
     3587
     3588    int rc = rtDwarfUnwind_Execute(&ExecState, pCie->pbInstructions, (uint32_t)pCie->cbInstructions);
     3589    if (rc == VINF_TRY_AGAIN)
     3590        rc = rtDwarfUnwind_Execute(&ExecState, pCursor->pb, (uint32_t)pCursor->cbUnitLeft);
     3591
     3592    /* On success, extract whatever state we've got. */
     3593    if (RT_SUCCESS(rc))
     3594        rc = rtDwarfUnwind_UpdateStateFromRow(pState, &Row, pCie);
     3595
     3596    /*
     3597     * Clean up allocations in case of pushes.
     3598     */
     3599    if (ExecState.pRow == &Row)
     3600        Assert(!ExecState.pRow->fOnHeap);
     3601    else
     3602        do
     3603        {
     3604            PRTDWARFCFROW pPopped = ExecState.pRow;
     3605            ExecState.pRow = ExecState.pRow->pNextOnStack;
     3606            Assert(pPopped->fOnHeap);
     3607            RTMemTmpFree(pPopped);
     3608        } while (ExecState.pRow && ExecState.pRow != &Row);
    26443609
    26453610    RT_NOREF(pState, uPcBegin, cbPcRange, offInRange);
    2646     return VINF_SUCCESS;
    2647 }
    2648 
     3611    return rc;
     3612}
    26493613
    26503614
     
    26633627static int rtDwarfUnwind_LoadCie(PRTDWARFCURSOR pCursor, PRTDWARFCIEINFO pNewCie, uint64_t offUnit, uint8_t bDefaultPtrEnc)
    26643628{
     3629Log8(("%#08RX64: rtDwarfUnwind_LoadCie: %.*Rhxs\n", offUnit, pCursor->cbUnitLeft, pCursor->pb));
    26653630    /*
    26663631     * Initialize the CIE record and get the version.
     
    26733638    if (   pNewCie->uDwarfVer >= 1 /* Note! Some GCC versions may emit v1 here. */
    26743639        && pNewCie->uDwarfVer <= 5)
     3640    { /* likely */ }
     3641    else
     3642    {
     3643        Log(("rtDwarfUnwind_LoadCie(%RX64): uDwarfVer=%u: VERR_VERSION_MISMATCH\n", offUnit, pNewCie->uDwarfVer));
    26753644        return VERR_VERSION_MISMATCH;
     3645    }
    26763646
    26773647    /*
     
    27273697    pNewCie->uCodeAlignFactor = rtDwarfCursor_GetULeb128(pCursor, 1);
    27283698    pNewCie->iDataAlignFactor = rtDwarfCursor_GetSLeb128(pCursor, 1);
     3699    pNewCie->bRetReg          = rtDwarfCursor_GetU8(pCursor, UINT8_MAX);
    27293700
    27303701    /*
     
    27393710            uint64_t cbAugData = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX);
    27403711            if (RT_FAILURE(pCursor->rc))
     3712            {
     3713                Log(("rtDwarfUnwind_LoadCie(%#RX64): rtDwarfCursor_GetULeb128 -> %Rrc!\n", offUnit, pCursor->rc));
    27413714                return pCursor->rc;
     3715            }
    27423716            if (cbAugData > pCursor->cbUnitLeft)
     3717            {
     3718                Log(("rtDwarfUnwind_LoadCie(%#RX64): cbAugData=%#x pCursor->cbUnitLeft=%#x -> VERR_DBG_MALFORMED_UNWIND_INFO!\n", offUnit, cbAugData, pCursor->cbUnitLeft));
    27433719                return VERR_DBG_MALFORMED_UNWIND_INFO;
     3720            }
    27443721            cbInstr = pCursor->cbUnitLeft - cbAugData;
    27453722        }
    27463723        else if (pNewCie->fHasUnknowAugmentation)
     3724        {
     3725            Log(("rtDwarfUnwind_LoadCie(%#RX64): fHasUnknowAugmentation=%1 -> VERR_DBG_MALFORMED_UNWIND_INFO!\n", offUnit));
    27473726            return VERR_DBG_MALFORMED_UNWIND_INFO;
     3727        }
    27483728
    27493729        /* Parse the string. */
     
    27753755
    27763756    /*
    2777      * Determine the target address encoding.
     3757     * Determine the target address encoding.  Make sure we resolve DW_EH_PE_ptr.
    27783758     */
    27793759    if (pNewCie->bAddressPtrEnc == DW_EH_PE_omit)
     
    27853765            default:    pNewCie->bAddressPtrEnc = bDefaultPtrEnc;  break;
    27863766        }
     3767    else if ((pNewCie->bAddressPtrEnc & DW_EH_PE_FORMAT_MASK) == DW_EH_PE_ptr)
     3768        pNewCie->bAddressPtrEnc = bDefaultPtrEnc;
    27873769
    27883770    return VINF_SUCCESS;
     
    27953777 * @returns IPRT status code.
    27963778 * @param   pCursor         The cursor.
     3779 * @param   uRvaCursor      The RVA corrsponding to the cursor start location.
    27973780 * @param   idxSeg          The segment of the PC location.
    27983781 * @param   offSeg          The segment offset of the PC location.
     
    28033786 *                          with different CIE_pointer values.
    28043787 */
    2805 DECLHIDDEN(int) rtDwarfUnwind_Slow(PRTDWARFCURSOR pCursor, RTDBGSEGIDX idxSeg, RTUINTPTR offSeg, RTUINTPTR uRva,
     3788DECLHIDDEN(int) rtDwarfUnwind_Slow(PRTDWARFCURSOR pCursor, RTUINTPTR uRvaCursor,
     3789                                   RTDBGSEGIDX idxSeg, RTUINTPTR offSeg, RTUINTPTR uRva,
    28063790                                   PRTDBGUNWINDSTATE pState, uint8_t bDefaultPtrEnc, bool fIsEhFrame)
    28073791{
     3792    Log8(("rtDwarfUnwind_Slow: idxSeg=%#x offSeg=%RTptr uRva=%RTptr enmArch=%d PC=%#RX64\n", idxSeg, offSeg, uRva, pState->enmArch, pState->uPc));
     3793
    28083794    /*
    28093795     * CIE info we collect.
     
    28173803     */
    28183804    int rc = VERR_DBG_UNWIND_INFO_NOT_FOUND;
    2819     while (   !rtDwarfCursor_IsAtEnd(pCursor)
    2820            && RT_SUCCESS(rc))
     3805    while (!rtDwarfCursor_IsAtEnd(pCursor))
    28213806    {
    28223807        uint64_t const offUnit = rtDwarfCursor_CalcSectOffsetU32(pCursor);
    2823         if (rtDwarfCursor_GetInitalLength(pCursor) == 0)
     3808        if (rtDwarfCursor_GetInitialLength(pCursor) == 0)
    28243809            break;
     3810Log8(("%#08RX64: rtDwarfCursor_GetInitialLength -> %#x\n", offUnit, pCursor->cbUnitLeft));
    28253811
    28263812        uint64_t const offRelCie = rtDwarfCursor_GetUOff(pCursor, 0);
     
    28343820               in .eh_frame and section relative in .debug_frame. */
    28353821            PRTDWARFCIEINFO pCieForFde;
    2836             uint64_t offCie = fIsEhFrame ? offUnit - offRelCie : offRelCie;
     3822            uint64_t offCie = fIsEhFrame ? offUnit + 4 - offRelCie : offRelCie;
    28373823            if (pCieHint && pCieHint->offCie == offCie)
    28383824                pCieForFde = pCieHint;
     
    28503836            if (pCieForFde)
    28513837            {
    2852                 /* Read the PC range covered by this FDE (the fields are also
    2853                    known as initial_location & instructions). */
     3838                /* Read the PC range covered by this FDE (the fields are also known as initial_location). */
    28543839                RTDBGSEGIDX idxFdeSeg = RTDBGSEGIDX_RVA;
    28553840                if (pCieForFde->cbSegment)
    28563841                    idxFdeSeg = rtDwarfCursor_GetVarSizedU(pCursor, pCieForFde->cbSegment, RTDBGSEGIDX_RVA);
    2857                 uint64_t uPcBegin  = rtDwarfCursor_GetPtrEnc(pCursor, pCieForFde->bAddressPtrEnc, 0);
     3842                uint64_t uPcBegin;
     3843                switch (pCieForFde->bAddressPtrEnc & DW_EH_PE_APPL_MASK)
     3844                {
     3845                    default: AssertFailed();
     3846                        RT_FALL_THRU();
     3847                    case DW_EH_PE_absptr:
     3848                        uPcBegin = rtDwarfCursor_GetPtrEnc(pCursor, pCieForFde->bAddressPtrEnc, 0);
     3849                        break;
     3850                    case DW_EH_PE_pcrel:
     3851                    {
     3852                        uPcBegin = rtDwarfCursor_CalcSectOffsetU32(pCursor) + uRvaCursor;
     3853                        uPcBegin += rtDwarfCursor_GetPtrEnc(pCursor, pCieForFde->bAddressPtrEnc, 0);
     3854                        break;
     3855                    }
     3856                }
    28583857                uint64_t cbPcRange = rtDwarfCursor_GetPtrEnc(pCursor, pCieForFde->bAddressPtrEnc, 0);
    28593858
     
    28623861                            ? uRva - uPcBegin < cbPcRange
    28633862                            : idxSeg == idxFdeSeg && offSeg - uPcBegin < cbPcRange;
     3863                Log8(("%#08RX64: FDE pCie=%p idxFdeSeg=%#x uPcBegin=%#RX64 cbPcRange=%#x fMatch=%d\n",
     3864                      offUnit, pCieForFde, idxFdeSeg, uPcBegin, cbPcRange, fMatch));
    28643865                if (fMatch)
    28653866                {
     
    28703871                }
    28713872            }
     3873            else
     3874                Log8(("%#08RX64: FDE -  pCie=NULL!!  offCie=%#RX64 offRelCie=%#RX64 fIsEhFrame=%d\n", offUnit, offCie, offRelCie, fIsEhFrame));
    28723875        }
    28733876        else
     
    28873890                }
    28883891            }
     3892            Log8(("%#08RX64: CIE\n", offUnit));
    28893893            int rc2 = rtDwarfUnwind_LoadCie(pCursor, &paCies[cCies], offUnit, bDefaultPtrEnc);
    28903894            if (RT_SUCCESS(rc2))
     3895            {
     3896                Log8(("%#08RX64: CIE #%u: offCie=%#RX64\n", offUnit, cCies, paCies[cCies].offCie));
    28913897                cCies++;
     3898            }
    28923899        }
    28933900        rtDwarfCursor_SkipUnit(pCursor);
     
    28993906    if (paCies)
    29003907        RTMemFree(paCies);
     3908    Log8(("rtDwarfUnwind_Slow: returns %Rrc PC=%#RX64\n", rc, pState->uPc));
    29013909    return rc;
    29023910}
     
    29383946 * @param   pvSection       The '.eh_frame' section data.
    29393947 * @param   cbSection       The size of the '.eh_frame' section data.
     3948 * @param   uRvaSection     The RVA of the '.eh_frame' section.
    29403949 * @param   idxSeg          The segment of the PC location.
    29413950 * @param   offSeg          The segment offset of the PC location.
     
    29443953 * @param   enmArch         The image architecture.
    29453954 */
    2946 DECLHIDDEN(int) rtDwarfUnwind_EhData(void const *pvSection, size_t cbSection, RTDBGSEGIDX idxSeg, RTUINTPTR offSeg,
    2947                                      RTUINTPTR uRva, PRTDBGUNWINDSTATE pState, RTLDRARCH enmArch)
     3955DECLHIDDEN(int) rtDwarfUnwind_EhData(void const *pvSection, size_t cbSection, RTUINTPTR uRvaSection,
     3956                                     RTDBGSEGIDX idxSeg, RTUINTPTR offSeg, RTUINTPTR uRva,
     3957                                     PRTDBGUNWINDSTATE pState, RTLDRARCH enmArch)
    29483958{
    29493959    RTDWARFCURSOR Cursor;
    29503960    rtDwarfCursor_InitForMem(&Cursor, pvSection, cbSection);
    2951     int rc = rtDwarfUnwind_Slow(&Cursor, idxSeg, offSeg, uRva, pState, rtDwarfUnwind_ArchToPtrEnc(enmArch), true /*fIsEhFrame*/);
    2952     return rtDwarfCursor_Delete(&Cursor, rc);
     3961    int rc = rtDwarfUnwind_Slow(&Cursor, uRvaSection, idxSeg, offSeg, uRva, pState,
     3962                                rtDwarfUnwind_ArchToPtrEnc(enmArch), true /*fIsEhFrame*/);
     3963    LogFlow(("rtDwarfUnwind_EhData: rtDwarfUnwind_Slow -> %Rrc\n", rc));
     3964    rc = rtDwarfCursor_Delete(&Cursor, rc);
     3965    LogFlow(("rtDwarfUnwind_EhData: returns %Rrc\n", rc));
     3966    return rc;
    29533967}
    29543968
     
    33984412     * Parse the header.
    33994413     */
    3400     rtDwarfCursor_GetInitalLength(pCursor);
     4414    rtDwarfCursor_GetInitialLength(pCursor);
    34014415    LnState.Hdr.uVer           = rtDwarfCursor_GetUHalf(pCursor, 0);
    34024416    if (   LnState.Hdr.uVer < 2
     
    49535967     */
    49545968    uint64_t offUnit = rtDwarfCursor_CalcSectOffsetU32(pCursor);
    4955     uint64_t cbUnit  = rtDwarfCursor_GetInitalLength(pCursor);
     5969    uint64_t cbUnit  = rtDwarfCursor_GetInitialLength(pCursor);
    49565970    cbUnit += rtDwarfCursor_CalcSectOffsetU32(pCursor) - offUnit;
    49575971    uint16_t const uVer = rtDwarfCursor_GetUHalf(pCursor, 0);
     
    52436257
    52446258            /* Do the work */
    5245             rc = rtDwarfUnwind_Slow(&Cursor, iSeg, off, uRva, pState, bPtrEnc, false /*fIsEhFrame*/);
     6259            rc = rtDwarfUnwind_Slow(&Cursor, 0 /** @todo .debug_frame RVA*/, iSeg, off, uRva,
     6260                                    pState, bPtrEnc, false /*fIsEhFrame*/);
    52466261
    52476262            rc = rtDwarfCursor_Delete(&Cursor, rc);
  • trunk/src/VBox/Runtime/common/dbg/dbgstackdumpself-amd64-x86.asm

    r74255 r75235  
    8080        SEH64_PUSH_GREG xSI
    8181%ifdef RT_ARCH_AMD64
    82         mov     r10, [xBP + xCB * 2]        ; Caller RBP.
     82        mov     r10, [xBP]                  ; Caller RBP.
    8383        push    r10
    8484        lea     r10, [xBP + xCB * 2]        ; Caller RSP.
  • trunk/src/VBox/Runtime/common/dbg/dbgstackdumpself.cpp

    r74252 r75235  
    4747# include <iprt/param.h>
    4848# include <iprt/win/windows.h>
     49#elif defined(RT_OS_LINUX)
     50# include <dlfcn.h>
    4951#endif
    5052
     
    273275                RTMemFree(pMod);
    274276            }
     277        }
     278    }
     279#elif defined(RT_OS_LINUX)
     280    Dl_info Info = { NULL, NULL, NULL, NULL };
     281    int rc = dladdr((const void *)uPc, &Info);
     282    if (rc != 0)
     283    {
     284        pMod = (PRTDBGSTACKSELFMOD)RTMemAllocZ(sizeof(*pMod));
     285        if (pMod)
     286        {
     287            /** @todo better filename translation... */
     288            rc = RTStrCopy(pMod->szFilename, sizeof(pMod->szFilename), Info.dli_fname);
     289            if (RT_SUCCESS(rc))
     290            {
     291                RTStrPurgeEncoding(pMod->szFilename);
     292
     293                const char *pszFilename = RTPathFilename(pMod->szFilename);
     294                pMod->offName   = pszFilename ? pszFilename - &pMod->szFilename[0] : 0;
     295                pMod->uMapping  = (uintptr_t)Info.dli_fbase;
     296                pMod->cbMapping = 0;
     297                pMod->hLdrMod   = NIL_RTLDRMOD;
     298                pMod->hDbgMod   = NIL_RTDBGMOD;
     299
     300                rc = RTLdrOpen(pMod->szFilename, RTLDR_O_FOR_DEBUG, RTLdrGetHostArch(), &pMod->hLdrMod);
     301                if (RT_SUCCESS(rc))
     302                {
     303                    pMod->cbMapping = RTLdrSize(pMod->hLdrMod);
     304
     305                    /* Try open debug info for the module. */
     306                    //uint32_t uTimeDateStamp = 0;
     307                    //RTLdrQueryProp(pMod->hLdrMod, RTLDRPROP_TIMESTAMP_SECONDS, &uTimeDateStamp, sizeof(uTimeDateStamp));
     308                    //RTDbgModCreateFromImage()??
     309                    //rc = RTDbgModCreateFromPeImage(&pMod->hDbgMod, pMod->szFilename, &pMod->szFilename[pMod->offName],
     310                    //                               &pMod->hLdrMod, (uint32_t)pMod->cbMapping, uTimeDateStamp, NIL_RTDBGCFG);
     311
     312                    RTListPrepend(pCachedModules, &pMod->ListEntry);
     313                    return pMod;
     314                }
     315            }
     316            RTMemFree(pMod);
    275317        }
    276318    }
  • trunk/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h

    r73531 r75235  
    14191419    int rc;
    14201420    RTLDRADDR uRva = off;
    1421     if (iSeg == RTDBGSEGIDX_RVA)
     1421    if (iSeg == UINT32_MAX)
    14221422        rc = RTLDRELF_NAME(RvaToSegOffset)(pMod, uRva, &iSeg, &off);
    14231423    else
     
    14541454                && pszName[8] == 'e')
    14551455            {
    1456                 if (pszName[8] == '\0')
     1456                if (pszName[9] == '\0')
    14571457                    pThis->iShEhFrame = iShdr;
    1458                 else if (   pszName[8] == '_'
    1459                          && pszName[9] == 'h'
    1460                          && pszName[10] == 'd'
    1461                          && pszName[11] == 'r'
    1462                          && pszName[12] == '\0')
     1458                else if (   pszName[9] == '_'
     1459                         && pszName[10] == 'h'
     1460                         && pszName[11] == 'd'
     1461                         && pszName[12] == 'r'
     1462                         && pszName[13] == '\0')
    14631463                    pThis->iShEhFrameHdr = iShdr;
    14641464                else
     
    14791479        if (pThis->paShdrs[iShdr].sh_flags & SHF_ALLOC)
    14801480            return rtDwarfUnwind_EhData((uint8_t const *)pThis->pvBits + pThis->paShdrs[iShdr].sh_addr,
    1481                                         pThis->paShdrs[iShdr].sh_size, iSeg, off, uRva, pState, pThis->Core.enmArch);
     1481                                        pThis->paShdrs[iShdr].sh_size, pThis->paShdrs[iShdr].sh_addr,
     1482                                        iSeg, off, uRva, pState, pThis->Core.enmArch);
    14821483    }
    14831484    return VERR_DBG_NO_UNWIND_INFO;
    14841485}
    1485 
    1486 
    14871486
    14881487
     
    19801979                        rc = VERR_LDR_GENERAL_FAILURE;
    19811980                    }
     1981                    if (pModElf->Ehdr.e_type == ET_DYN && pModElf->LinkAddress < 0x1000)
     1982                        pModElf->LinkAddress = 0;
    19821983                }
    19831984
  • trunk/src/VBox/Runtime/common/misc/assert.cpp

    r74344 r75235  
    143143#ifdef IPRT_WITH_ASSERT_STACK
    144144        /* The stack dump. */
     145        static volatile bool s_fDumpingStackAlready = false; /* for simple recursion prevention */
    145146        char   szStack[sizeof(g_szRTAssertStack)];
    146147        size_t cchStack = 0;
     
    152153        bool   fStack = true;
    153154# endif
    154         if (fStack)
     155        szStack[0] = '\0';
     156        if (fStack && !s_fDumpingStackAlready)
     157        {
     158            s_fDumpingStackAlready = true;
    155159            cchStack = RTDbgStackDumpSelf(szStack, sizeof(szStack), 0);
    156         else
    157             szStack[0] = '\0';
     160            s_fDumpingStackAlready = false;
     161        }
    158162        memcpy(g_szRTAssertStack, szStack, cchStack + 1);
    159163#endif
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette