VirtualBox

Changeset 73531 in vbox


Ignore:
Timestamp:
Aug 6, 2018 5:08:57 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
124160
Message:

IPRT: Some work on stack unwinding using dwarf info. bugref:3897

Location:
trunk/src/VBox/Runtime
Files:
4 edited

Legend:

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

    r73494 r73531  
    350350/** @} */
    351351
     352/** @name Exception Handler Pointer Encodings (GCC/LSB).
     353 * @{ */
     354#define DW_EH_PE_FORMAT_MASK    UINT8_C(0x0f) /**< Format mask. */
     355#define DW_EH_PE_APPL_MASK      UINT8_C(0x70) /**< Application mask. */
     356#define DW_EH_PE_indirect       UINT8_C(0x80) /**< Flag: Indirect pointer. */
     357#define DW_EH_PE_omit           UINT8_C(0xff) /**< Special value: Omitted. */
     358#define DW_EH_PE_ptr            UINT8_C(0x00) /**< Format: pointer sized, unsigned. */
     359#define DW_EH_PE_uleb128        UINT8_C(0x01) /**< Format: unsigned LEB128. */
     360#define DW_EH_PE_udata2         UINT8_C(0x02) /**< Format: unsigned 16-bit. */
     361#define DW_EH_PE_udata4         UINT8_C(0x03) /**< Format: unsigned 32-bit. */
     362#define DW_EH_PE_udata8         UINT8_C(0x04) /**< Format: unsigned 64-bit. */
     363#define DW_EH_PE_sleb128        UINT8_C(0x09) /**< Format: signed LEB128. */
     364#define DW_EH_PE_sdata2         UINT8_C(0x0a) /**< Format: signed 16-bit. */
     365#define DW_EH_PE_sdata4         UINT8_C(0x0b) /**< Format: signed 32-bit. */
     366#define DW_EH_PE_sdata8         UINT8_C(0x0c) /**< Format: signed 64-bit. */
     367#define DW_EH_PE_absptr         UINT8_C(0x00) /**< Application: Absolute */
     368#define DW_EH_PE_pcrel          UINT8_C(0x10) /**< Application: PC relative, i.e. relative pointer address. */
     369#define DW_EH_PE_textrel        UINT8_C(0x20) /**< Application: text section relative. */
     370#define DW_EH_PE_datarel        UINT8_C(0x30) /**< Application: data section relative. */
     371#define DW_EH_PE_funcrel        UINT8_C(0x40) /**< Application: relative to start of function. */
     372#define DW_EH_PE_aligned        UINT8_C(0x50) /**< Application: aligned pointer. */
     373/** @} */
     374
    352375
    353376/*********************************************************************************************************************************
     
    506529    /** The number of bytes left to read in the current unit. */
    507530    size_t                  cbUnitLeft;
    508     /** The DWARF debug info reader instance. */
     531    /** The DWARF debug info reader instance.  (Can be NULL for eh_frame.) */
    509532    PRTDBGMODDWARF          pDwarfMod;
    510533    /** Set if this is 64-bit DWARF, clear if 32-bit. */
     
    15151538
    15161539
     1540/**
     1541 * Converts a segment+offset address into an RVA.
     1542 *
     1543 * @returns IPRT status code.
     1544 * @param   pThis           The DWARF instance.
     1545 * @param   idxSegment      The segment index.
     1546 * @param   offSegment      The segment offset.
     1547 * @param   puRva           Where to return the calculated RVA.
     1548 */
     1549static int rtDbgModDwarfSegOffsetToRva(PRTDBGMODDWARF pThis, RTDBGSEGIDX idxSegment, uint64_t offSegment, PRTUINTPTR puRva)
     1550{
     1551    if (pThis->paSegs)
     1552    {
     1553        PRTDBGDWARFSEG pSeg = rtDbgModDwarfFindSegment(pThis, idxSegment);
     1554        if (pSeg)
     1555        {
     1556            *puRva = pSeg->uBaseAddr + offSegment;
     1557            return VINF_SUCCESS;
     1558        }
     1559    }
     1560
     1561    RTUINTPTR uRva = RTDbgModSegmentRva(pThis->pImgMod, idxSegment);
     1562    if (uRva != RTUINTPTR_MAX)
     1563    {
     1564        *puRva = uRva + offSegment;
     1565        return VINF_SUCCESS;
     1566    }
     1567    return VERR_INVALID_POINTER;
     1568}
     1569
     1570/**
     1571 * Converts a segment+offset address into an RVA.
     1572 *
     1573 * @returns IPRT status code.
     1574 * @param   pThis           The DWARF instance.
     1575 * @param   uRva            The RVA to convert.
     1576 * @param   pidxSegment     Where to return the segment index.
     1577 * @param   poffSegment     Where to return the segment offset.
     1578 */
     1579static int rtDbgModDwarfRvaToSegOffset(PRTDBGMODDWARF pThis, RTUINTPTR uRva, RTDBGSEGIDX *pidxSegment, uint64_t *poffSegment)
     1580{
     1581    RTUINTPTR   offSeg = 0;
     1582    RTDBGSEGIDX idxSeg = RTDbgModRvaToSegOff(pThis->pImgMod, uRva, &offSeg);
     1583    if (idxSeg != NIL_RTDBGSEGIDX)
     1584    {
     1585        *pidxSegment = idxSeg;
     1586        *poffSegment = offSeg;
     1587        return VINF_SUCCESS;
     1588    }
     1589    return VERR_INVALID_POINTER;
     1590}
     1591
     1592
     1593
    15171594/*
    15181595 *
     
    18921969
    18931970/**
    1894  * Reads a 1, 2, 4 or 8 byte unsgined value.
     1971 * Reads a 1, 2, 4 or 8 byte unsigned value.
    18951972 *
    18961973 * @returns 64-bit unsigned value.
     
    20222099            return uErrValue;
    20232100    }
     2101}
     2102
     2103
     2104/**
     2105 * Reads a 1, 2, 4 or 8 byte unsigned value.
     2106 *
     2107 * @returns 64-bit unsigned value.
     2108 * @param   pCursor             The cursor.
     2109 * @param   bPtrEnc             The pointer encoding.
     2110 * @param   uErrValue           The error value.
     2111 */
     2112static uint64_t rtDwarfCursor_GetPtrEnc(PRTDWARFCURSOR pCursor, uint8_t bPtrEnc, uint64_t uErrValue)
     2113{
     2114    uint64_t u64Ret;
     2115    switch (bPtrEnc & DW_EH_PE_FORMAT_MASK)
     2116    {
     2117        case DW_EH_PE_ptr:
     2118            u64Ret = rtDwarfCursor_GetNativeUOff(pCursor, uErrValue);
     2119            break;
     2120        case DW_EH_PE_uleb128:
     2121            u64Ret = rtDwarfCursor_GetULeb128(pCursor, uErrValue);
     2122            break;
     2123        case DW_EH_PE_udata2:
     2124            u64Ret = rtDwarfCursor_GetU16(pCursor, UINT16_MAX);
     2125            break;
     2126        case DW_EH_PE_udata4:
     2127            u64Ret = rtDwarfCursor_GetU32(pCursor, UINT32_MAX);
     2128            break;
     2129        case DW_EH_PE_udata8:
     2130            u64Ret = rtDwarfCursor_GetU64(pCursor, UINT64_MAX);
     2131            break;
     2132        case DW_EH_PE_sleb128:
     2133            u64Ret = rtDwarfCursor_GetSLeb128(pCursor, uErrValue);
     2134            break;
     2135        case DW_EH_PE_sdata2:
     2136            u64Ret = (int64_t)(int16_t)rtDwarfCursor_GetU16(pCursor, UINT16_MAX);
     2137            break;
     2138        case DW_EH_PE_sdata4:
     2139            u64Ret = (int64_t)(int32_t)rtDwarfCursor_GetU32(pCursor, UINT32_MAX);
     2140            break;
     2141        case DW_EH_PE_sdata8:
     2142            u64Ret = rtDwarfCursor_GetU64(pCursor, UINT64_MAX);
     2143            break;
     2144        default:
     2145            pCursor->rc = VERR_DWARF_BAD_INFO;
     2146            return uErrValue;
     2147    }
     2148    if (RT_FAILURE(pCursor->rc))
     2149        return uErrValue;
     2150    return u64Ret;
    20242151}
    20252152
     
    20692196static uint32_t rtDwarfCursor_CalcSectOffsetU32(PRTDWARFCURSOR pCursor)
    20702197{
    2071     size_t off = pCursor->pb - (uint8_t const *)pCursor->pDwarfMod->aSections[pCursor->enmSect].pv;
     2198    size_t off = pCursor->pb - pCursor->pbStart;
    20722199    uint32_t offRet = (uint32_t)off;
    20732200    if (offRet != off)
     
    22742401
    22752402/**
     2403 * Initialize a reader cursor for a memory block (eh_frame).
     2404 *
     2405 * @returns IPRT status code.
     2406 * @param   pCursor             The cursor.
     2407 * @param   pvMem               The memory block.
     2408 * @param   cbMem               The size of the memory block.
     2409 */
     2410static int rtDwarfCursor_InitForMem(PRTDWARFCURSOR pCursor, void const *pvMem, size_t cbMem)
     2411{
     2412    pCursor->enmSect          = krtDbgModDwarfSect_End;
     2413    pCursor->pbStart          = (uint8_t const *)pvMem;
     2414    pCursor->pb               = (uint8_t const *)pvMem;
     2415    pCursor->cbLeft           = cbMem;
     2416    pCursor->cbUnitLeft       = cbMem;
     2417    pCursor->pDwarfMod        = NULL;
     2418    pCursor->f64bitDwarf      = false;
     2419    /** @todo ask the image about the endian used as well as the address
     2420     *        width. */
     2421    pCursor->fNativEndian     = true;
     2422    pCursor->cbNativeAddr     = 4;
     2423    pCursor->rc               = VINF_SUCCESS;
     2424
     2425    return VINF_SUCCESS;
     2426}
     2427
     2428
     2429/**
    22762430 * Deletes a section reader initialized by rtDwarfCursor_Init.
    22772431 *
     
    22922446    pCursor->rc         = VERR_INTERNAL_ERROR_4;
    22932447    return rcOther;
     2448}
     2449
     2450
     2451/*
     2452 *
     2453 * DWARF Frame Unwind Information.
     2454 * DWARF Frame Unwind Information.
     2455 * DWARF Frame Unwind Information.
     2456 *
     2457 */
     2458
     2459/**
     2460 * Common information entry (CIE) information.
     2461 */
     2462typedef struct RTDWARFCIEINFO
     2463{
     2464    /** The segment location of the CIE. */
     2465    uint64_t        offCie;
     2466    /** The DWARF version. */
     2467    uint8_t         uDwarfVer;
     2468    /** The address pointer encoding. */
     2469    uint8_t         bAddressPtrEnc;
     2470    /** The segment size (v4). */
     2471    uint8_t         cbSegment;
     2472    /** The LSDA pointer encoding. */
     2473    uint8_t         bLsdaPtrEnc;
     2474
     2475    /** Set if the EH data field is present ('eh'). */
     2476    bool            fHasEhData : 1;
     2477    /** Set if there is an augmentation data size ('z'). */
     2478    bool            fHasAugmentationSize : 1;
     2479    /** Set if the augmentation data contains a LSDA (pointer size byte in CIE,
     2480     * pointer in FDA) ('L'). */
     2481    bool            fHasLanguageSpecificDataArea : 1;
     2482    /** Set if the augmentation data contains a personality routine
     2483     * (pointer size + pointer) ('P'). */
     2484    bool            fHasPersonalityRoutine : 1;
     2485    /** Set if the augmentation data contains the address encoding . */
     2486    bool            fHasAddressEnc : 1;
     2487    /** Set if signal frame. */
     2488    bool            fIsSignalFrame : 1;
     2489    /** Set if we've encountered unknown augmentation data.  This
     2490     * means the CIE is incomplete and cannot be used. */
     2491    bool            fHasUnknowAugmentation : 1;
     2492
     2493    /** Copy of the augmentation string. */
     2494    const char     *pszAugmentation;
     2495
     2496    /** Code alignment factor for the instruction. */
     2497    uint64_t        uCodeAlignFactor;
     2498    /** Data alignment factor for the instructions. */
     2499    int64_t         iDataAlignFactor;
     2500
     2501    /** Pointer to the instruction sequence. */
     2502    uint8_t const  *pbInstructions;
     2503    /** The length of the instruction sequence. */
     2504    size_t          cbInstructions;
     2505} RTDWARFCIEINFO;
     2506/** Pointer to CIE info. */
     2507typedef RTDWARFCIEINFO *PRTDWARFCIEINFO;
     2508/** Pointer to const CIE info. */
     2509typedef RTDWARFCIEINFO const *PCRTDWARFCIEINFO;
     2510
     2511
     2512/**
     2513 * Processes a FDE, taking over after the PC range field.
     2514 *
     2515 * @returns IPRT status code.
     2516 * @param   pCursor         The cursor.
     2517 * @param   pCie            Information about the corresponding CIE.
     2518 * @param   uPcBegin        The PC begin field value (sans segment).
     2519 * @param   cbPcRange       The PC range from @a uPcBegin.
     2520 * @param   offInRange      The offset into the range corresponding to
     2521 *                          pState->uPc.
     2522 * @param   pState          The unwind state to work.
     2523 */
     2524static int rtDwarfUnwind_ProcessFde(PRTDWARFCURSOR pCursor, PCRTDWARFCIEINFO pCie, uint64_t uPcBegin,
     2525                                    uint64_t cbPcRange, uint64_t offInRange, PRTDBGUNWINDSTATE pState)
     2526{
     2527    /*
     2528     * Deal with augmented data fields.
     2529     */
     2530    /* The size. */
     2531    size_t cbInstr = ~(size_t)0;
     2532    if (pCie->fHasAugmentationSize)
     2533    {
     2534        uint64_t cbAugData = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX);
     2535        if (RT_FAILURE(pCursor->rc))
     2536            return pCursor->rc;
     2537        if (cbAugData > pCursor->cbUnitLeft)
     2538            return VERR_DBG_MALFORMED_UNWIND_INFO;
     2539        cbInstr = pCursor->cbUnitLeft - cbAugData;
     2540    }
     2541    else if (pCie->fHasUnknowAugmentation)
     2542        return VERR_DBG_MALFORMED_UNWIND_INFO;
     2543
     2544    /* Parse the string and fetch FDE fields. */
     2545    if (!pCie->fHasEhData)
     2546        for (const char *pszAug = pCie->pszAugmentation; *pszAug != '\0'; pszAug++)
     2547            switch (*pszAug)
     2548            {
     2549                case 'L':
     2550                    if (pCie->bLsdaPtrEnc != DW_EH_PE_omit)
     2551                        rtDwarfCursor_GetPtrEnc(pCursor, pCie->bLsdaPtrEnc, 0);
     2552                    break;
     2553            }
     2554
     2555    /* Skip unconsumed bytes. */
     2556    if (   cbInstr != ~(size_t)0
     2557        && pCursor->cbUnitLeft > cbInstr)
     2558        rtDwarfCursor_SkipBytes(pCursor, pCursor->cbUnitLeft - cbInstr);
     2559    if (RT_FAILURE(pCursor->rc))
     2560        return pCursor->rc;
     2561
     2562    /*
     2563     * The crazy part.  Table program execution.
     2564     */
     2565    if (pCie->cbInstructions > 0)
     2566    {
     2567        /** @todo continue here later.   */
     2568    }
     2569
     2570    RT_NOREF(pState, uPcBegin, cbPcRange, offInRange);
     2571    return VINF_SUCCESS;
     2572}
     2573
     2574
     2575
     2576/**
     2577 * Load the information we need from a CIE.
     2578 *
     2579 * This starts after the initial length and CIE_pointer fields has
     2580 * been processed.
     2581 *
     2582 * @returns IPRT status code.
     2583 * @param   pCursor         The cursor.
     2584 * @param   pNewCie         The structure to populate with parsed CIE info.
     2585 * @param   offUnit         The unit offset.
     2586 * @param   bDefaultPtrEnc  The default pointer encoding.
     2587 */
     2588static int rtDwarfUnwind_LoadCie(PRTDWARFCURSOR pCursor, PRTDWARFCIEINFO pNewCie, uint64_t offUnit, uint8_t bDefaultPtrEnc)
     2589{
     2590    /*
     2591     * Initialize the CIE record and get the version.
     2592     */
     2593    RT_ZERO(*pNewCie);
     2594    pNewCie->offCie         = offUnit;
     2595    pNewCie->bLsdaPtrEnc    = DW_EH_PE_omit;
     2596    pNewCie->bAddressPtrEnc = DW_EH_PE_omit; /* set later */
     2597    pNewCie->uDwarfVer      = rtDwarfCursor_GetUByte(pCursor, 0);
     2598    if (   pNewCie->uDwarfVer >= 1 /* Note! Some GCC versions may emit v1 here. */
     2599        && pNewCie->uDwarfVer <= 5)
     2600        return VERR_VERSION_MISMATCH;
     2601
     2602    /*
     2603     * The augmentation string.
     2604     *
     2605     * First deal with special "eh" string from oldish GCC (dwarf2out.c about 1997), specified in LSB:
     2606     *     https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html
     2607     */
     2608    pNewCie->pszAugmentation = rtDwarfCursor_GetSZ(pCursor, "");
     2609    if (   pNewCie->pszAugmentation[0] == 'e'
     2610        && pNewCie->pszAugmentation[1] == 'h'
     2611        && pNewCie->pszAugmentation[2] == '\0')
     2612    {
     2613        pNewCie->fHasEhData = true;
     2614        rtDwarfCursor_GetPtrEnc(pCursor, bDefaultPtrEnc, 0);
     2615    }
     2616    else
     2617    {
     2618        /* Regular augmentation string. */
     2619        for (const char *pszAug = pNewCie->pszAugmentation; *pszAug != '\0'; pszAug++)
     2620            switch (*pszAug)
     2621            {
     2622                case 'z':
     2623                    pNewCie->fHasAugmentationSize = true;
     2624                    break;
     2625                case 'L':
     2626                    pNewCie->fHasLanguageSpecificDataArea = true;
     2627                    break;
     2628                case 'P':
     2629                    pNewCie->fHasPersonalityRoutine = true;
     2630                    break;
     2631                case 'R':
     2632                    pNewCie->fHasAddressEnc = true;
     2633                    break;
     2634                case 'S':
     2635                    pNewCie->fIsSignalFrame = true;
     2636                    break;
     2637                default:
     2638                    pNewCie->fHasUnknowAugmentation = true;
     2639                    break;
     2640            }
     2641    }
     2642
     2643    /*
     2644     * More standard fields
     2645     */
     2646    uint8_t cbAddress = 0;
     2647    if (pNewCie->uDwarfVer >= 4)
     2648    {
     2649        cbAddress = rtDwarfCursor_GetU8(pCursor, bDefaultPtrEnc == DW_EH_PE_udata8 ? 8 : 4);
     2650        pNewCie->cbSegment = rtDwarfCursor_GetU8(pCursor, 0);
     2651    }
     2652    pNewCie->uCodeAlignFactor = rtDwarfCursor_GetULeb128(pCursor, 1);
     2653    pNewCie->iDataAlignFactor = rtDwarfCursor_GetSLeb128(pCursor, 1);
     2654
     2655    /*
     2656     * Augmentation data.
     2657     */
     2658    if (!pNewCie->fHasEhData)
     2659    {
     2660        /* The size. */
     2661        size_t cbInstr = ~(size_t)0;
     2662        if (pNewCie->fHasAugmentationSize)
     2663        {
     2664            uint64_t cbAugData = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX);
     2665            if (RT_FAILURE(pCursor->rc))
     2666                return pCursor->rc;
     2667            if (cbAugData > pCursor->cbUnitLeft)
     2668                return VERR_DBG_MALFORMED_UNWIND_INFO;
     2669            cbInstr = pCursor->cbUnitLeft - cbAugData;
     2670        }
     2671        else if (pNewCie->fHasUnknowAugmentation)
     2672            return VERR_DBG_MALFORMED_UNWIND_INFO;
     2673
     2674        /* Parse the string. */
     2675        for (const char *pszAug = pNewCie->pszAugmentation; *pszAug != '\0'; pszAug++)
     2676            switch (*pszAug)
     2677            {
     2678                case 'L':
     2679                    pNewCie->bLsdaPtrEnc = rtDwarfCursor_GetU8(pCursor, DW_EH_PE_omit);
     2680                    break;
     2681                case 'P':
     2682                    rtDwarfCursor_GetPtrEnc(pCursor, rtDwarfCursor_GetU8(pCursor, DW_EH_PE_omit), 0);
     2683                    break;
     2684                case 'R':
     2685                    pNewCie->bAddressPtrEnc = rtDwarfCursor_GetU8(pCursor, DW_EH_PE_omit);
     2686                    break;
     2687            }
     2688
     2689        /* Skip unconsumed bytes. */
     2690        if (   cbInstr != ~(size_t)0
     2691            && pCursor->cbUnitLeft > cbInstr)
     2692            rtDwarfCursor_SkipBytes(pCursor, pCursor->cbUnitLeft - cbInstr);
     2693    }
     2694
     2695    /*
     2696     * Note down where the instructions are.
     2697     */
     2698    pNewCie->pbInstructions = pCursor->pb;
     2699    pNewCie->cbInstructions = pCursor->cbUnitLeft;
     2700
     2701    /*
     2702     * Determine the target address encoding.
     2703     */
     2704    if (pNewCie->bAddressPtrEnc == DW_EH_PE_omit)
     2705        switch (cbAddress)
     2706        {
     2707            case 2:     pNewCie->bAddressPtrEnc = DW_EH_PE_udata2; break;
     2708            case 4:     pNewCie->bAddressPtrEnc = DW_EH_PE_udata4; break;
     2709            case 8:     pNewCie->bAddressPtrEnc = DW_EH_PE_udata8; break;
     2710            default:    pNewCie->bAddressPtrEnc = bDefaultPtrEnc;  break;
     2711        }
     2712
     2713    return VINF_SUCCESS;
     2714}
     2715
     2716
     2717/**
     2718 * Does a slow unwind of a '.debug_frame' or '.eh_frame' section.
     2719 *
     2720 * @returns IPRT status code.
     2721 * @param   pCursor         The cursor.
     2722 * @param   idxSeg          The segment of the PC location.
     2723 * @param   offSeg          The segment offset of the PC location.
     2724 * @param   uRva            The RVA of the PC location.
     2725 * @param   pState          The unwind state to work.
     2726 * @param   bDefaultPtrEnc  The default pointer encoding.
     2727 * @param   fIsEhFrame      Set if this is a '.eh_frame'.  GCC generate these
     2728 *                          with different CIE_pointer values.
     2729 */
     2730DECLHIDDEN(int) rtDwarfUnwind_Slow(PRTDWARFCURSOR pCursor, RTDBGSEGIDX idxSeg, RTUINTPTR offSeg, RTUINTPTR uRva,
     2731                                   PRTDBGUNWINDSTATE pState, uint8_t bDefaultPtrEnc, bool fIsEhFrame)
     2732{
     2733    /*
     2734     * CIE info we collect.
     2735     */
     2736    PRTDWARFCIEINFO paCies   = NULL;
     2737    uint32_t        cCies    = 0;
     2738    PRTDWARFCIEINFO pCieHint = NULL;
     2739
     2740    /*
     2741     * Do the scanning.
     2742     */
     2743    int rc = VERR_DBG_UNWIND_INFO_NOT_FOUND;
     2744    while (   !rtDwarfCursor_IsAtEnd(pCursor)
     2745           && RT_SUCCESS(rc))
     2746    {
     2747        uint64_t const offUnit = rtDwarfCursor_CalcSectOffsetU32(pCursor);
     2748        if (rtDwarfCursor_GetInitalLength(pCursor) == 0)
     2749            break;
     2750
     2751        uint64_t const offRelCie = rtDwarfCursor_GetUOff(pCursor, 0);
     2752        if (   offRelCie != 0
     2753            && offRelCie != (pCursor->f64bitDwarf ? UINT64_MAX : UINT32_MAX))
     2754        {
     2755            /*
     2756             * Frame descriptor entry (FDE).
     2757             */
     2758            /* Locate the corresponding CIE.  The CIE pointer is self relative
     2759               in .eh_frame and section relative in .debug_frame. */
     2760            PRTDWARFCIEINFO pCieForFde;
     2761            uint64_t offCie = fIsEhFrame ? offUnit - offRelCie : offRelCie;
     2762            if (pCieHint && pCieHint->offCie == offCie)
     2763                pCieForFde = pCieHint;
     2764            else
     2765            {
     2766                pCieForFde = NULL;
     2767                uint32_t i = cCies;
     2768                while (i-- > 0)
     2769                    if (paCies[i].offCie == offCie)
     2770                    {
     2771                        pCieHint = pCieForFde = &paCies[i];
     2772                        break;
     2773                    }
     2774            }
     2775            if (pCieForFde)
     2776            {
     2777                /* Read the PC range covered by this FDE (the fields are also
     2778                   known as initial_location & instructions). */
     2779                RTDBGSEGIDX idxFdeSeg = RTDBGSEGIDX_RVA;
     2780                if (pCieForFde->cbSegment)
     2781                    idxFdeSeg = rtDwarfCursor_GetVarSizedU(pCursor, pCieForFde->cbSegment, RTDBGSEGIDX_RVA);
     2782                uint64_t uPcBegin  = rtDwarfCursor_GetPtrEnc(pCursor, pCieForFde->bAddressPtrEnc, 0);
     2783                uint64_t cbPcRange = rtDwarfCursor_GetPtrEnc(pCursor, pCieForFde->bAddressPtrEnc, 0);
     2784
     2785                /* Match it with what we're looking for. */
     2786                bool fMatch = idxFdeSeg == RTDBGSEGIDX_RVA
     2787                            ? uRva - uPcBegin < cbPcRange
     2788                            : idxSeg == idxFdeSeg && offSeg - uPcBegin < cbPcRange;
     2789                if (fMatch)
     2790                {
     2791                    rc = rtDwarfUnwind_ProcessFde(pCursor, pCieForFde, uPcBegin, cbPcRange,
     2792                                                  idxFdeSeg == RTDBGSEGIDX_RVA ? uRva - uPcBegin : offSeg - uPcBegin,
     2793                                                  pState);
     2794                    break;
     2795                }
     2796            }
     2797        }
     2798        else
     2799        {
     2800            /*
     2801             * Common information entry (CIE).  Record the info we need about it.
     2802             */
     2803            if ((cCies & 8) == 0)
     2804            {
     2805                void *pvNew = RTMemRealloc(paCies, sizeof(paCies[0]) * (cCies + 8));
     2806                if (pvNew)
     2807                    paCies = (PRTDWARFCIEINFO)pvNew;
     2808                else
     2809                {
     2810                    rc = VERR_NO_MEMORY;
     2811                    break;
     2812                }
     2813            }
     2814            int rc2 = rtDwarfUnwind_LoadCie(pCursor, &paCies[cCies], offUnit, bDefaultPtrEnc);
     2815            if (RT_SUCCESS(rc2))
     2816                cCies++;
     2817        }
     2818        rtDwarfCursor_SkipUnit(pCursor);
     2819    }
     2820
     2821    /*
     2822     * Cleanup.
     2823     */
     2824    if (paCies)
     2825        RTMemFree(paCies);
     2826    return rc;
     2827}
     2828
     2829
     2830/**
     2831 * Helper for translating a loader architecture value to a pointe encoding.
     2832 *
     2833 * @returns Pointer encoding.
     2834 * @param   enmLdrArch          The loader architecture value to convert.
     2835 */
     2836static uint8_t rtDwarfUnwind_ArchToPtrEnc(RTLDRARCH enmLdrArch)
     2837{
     2838    switch (enmLdrArch)
     2839    {
     2840        case RTLDRARCH_AMD64:
     2841        case RTLDRARCH_ARM64:
     2842            return DW_EH_PE_udata8;
     2843        case RTLDRARCH_X86_16:
     2844        case RTLDRARCH_X86_32:
     2845        case RTLDRARCH_ARM32:
     2846            return DW_EH_PE_udata4;
     2847        case RTLDRARCH_HOST:
     2848        case RTLDRARCH_WHATEVER:
     2849        case RTLDRARCH_INVALID:
     2850        case RTLDRARCH_END:
     2851        case RTLDRARCH_32BIT_HACK:
     2852            break;
     2853    }
     2854    AssertFailed();
     2855    return DW_EH_PE_udata4;
     2856}
     2857
     2858
     2859/**
     2860 * Interface for the loader code.
     2861 *
     2862 * @returns IPRT status.
     2863 * @param   pvSection       The '.eh_frame' section data.
     2864 * @param   cbSection       The size of the '.eh_frame' section data.
     2865 * @param   idxSeg          The segment of the PC location.
     2866 * @param   offSeg          The segment offset of the PC location.
     2867 * @param   uRva            The RVA of the PC location.
     2868 * @param   pState          The unwind state to work.
     2869 * @param   enmArch         The image architecture.
     2870 */
     2871DECLHIDDEN(int) rtDwarfUnwind_EhData(void const *pvSection, size_t cbSection, RTDBGSEGIDX idxSeg, RTUINTPTR offSeg,
     2872                                     RTUINTPTR uRva, PRTDBGUNWINDSTATE pState, RTLDRARCH enmArch)
     2873{
     2874    RTDWARFCURSOR Cursor;
     2875    rtDwarfCursor_InitForMem(&Cursor, pvSection, cbSection);
     2876    int rc = rtDwarfUnwind_Slow(&Cursor, idxSeg, offSeg, uRva, pState, rtDwarfUnwind_ArchToPtrEnc(enmArch), true /*fIsEhFrame*/);
     2877    return rtDwarfCursor_Delete(&Cursor, rc);
    22942878}
    22952879
     
    45285112static DECLCALLBACK(int) rtDbgModDwarf_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
    45295113{
    4530     RT_NOREF(pMod, iSeg, off, pState);
     5114    PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
     5115
     5116    /*
     5117     * Unwinding info is stored in the '.debug_frame' section, or altertively
     5118     * in the '.eh_frame' one in the image.  In the latter case the dbgmodldr.cpp
     5119     * part of the operation will take care of it.  Since the sections contain the
     5120     * same data, we just create a cursor and call a common function to do the job.
     5121     */
     5122    if (pThis->aSections[krtDbgModDwarfSect_frame].fPresent)
     5123    {
     5124        RTDWARFCURSOR Cursor;
     5125        int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_frame);
     5126        if (RT_SUCCESS(rc))
     5127        {
     5128            /* Figure default pointer encoding from image arch. */
     5129            uint8_t bPtrEnc = rtDwarfUnwind_ArchToPtrEnc(pMod->pImgVt->pfnGetArch(pMod));
     5130
     5131            /* Make sure we've got both seg:off and rva for the input address. */
     5132            RTUINTPTR uRva = off;
     5133            if (iSeg == RTDBGSEGIDX_RVA)
     5134                rtDbgModDwarfRvaToSegOffset(pThis, uRva, &iSeg, &off);
     5135            else
     5136                rtDbgModDwarfSegOffsetToRva(pThis, iSeg, off, &uRva);
     5137
     5138            /* Do the work */
     5139            rc = rtDwarfUnwind_Slow(&Cursor, iSeg, off, uRva, pState, bPtrEnc, false /*fIsEhFrame*/);
     5140
     5141            rc = rtDwarfCursor_Delete(&Cursor, rc);
     5142        }
     5143        return rc;
     5144    }
    45315145    return VERR_DBG_NO_UNWIND_INFO;
    45325146}
  • trunk/src/VBox/Runtime/common/ldr/ldrELF.cpp

    r69437 r73531  
    3535#include <iprt/alloc.h>
    3636#include <iprt/assert.h>
     37#include <iprt/dbg.h>
    3738#include <iprt/string.h>
    3839#include <iprt/log.h>
     
    4344#include <iprt/formats/elf-amd64.h>
    4445#include "internal/ldr.h"
     46#include "internal/dbgmod.h"
    4547
    4648
  • trunk/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h

    r73494 r73531  
    130130    /** Pointer to section header string table within RTLDRMODELF::pvBits. */
    131131    const char             *pShStr;
     132
     133    /** The '.eh_frame' section index.  Zero if not searched for, ~0U if not found. */
     134    unsigned                iShEhFrame;
     135    /** The '.eh_frame_hdr' section index.  Zero if not searched for, ~0U if not found. */
     136    unsigned                iShEhFrameHdr;
    132137} RTLDRMODELF, *PRTLDRMODELF;
    133138
     
    12991304
    13001305
    1301 /** @copydoc RTLDROPS::pfnRvaToSegOffset. */
     1306/** @copydoc RTLDROPS::pfnReadDbgInfo. */
    13021307static DECLCALLBACK(int) RTLDRELF_NAME(ReadDbgInfo)(PRTLDRMODINTERNAL pMod, uint32_t iDbgInfo, RTFOFF off,
    13031308                                                    size_t cb, void *pvBuf)
     
    13981403    return rc;
    13991404}
     1405
     1406
     1407/**
     1408 * @interface_method_impl{RTLDROPS,pfnUnwindFrame}
     1409 */
     1410static DECLCALLBACK(int)
     1411RTLDRELF_NAME(UnwindFrame)(PRTLDRMODINTERNAL pMod, void const *pvBits, uint32_t iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
     1412{
     1413    PRTLDRMODELF pThis = (PRTLDRMODELF)pMod;
     1414    LogFlow(("%s: iSeg=%#x off=%RTptr\n", __FUNCTION__, iSeg, off));
     1415
     1416    /*
     1417     * Process the input address, making us both RVA and proper seg:offset out of it.
     1418     */
     1419    int rc;
     1420    RTLDRADDR uRva = off;
     1421    if (iSeg == RTDBGSEGIDX_RVA)
     1422        rc = RTLDRELF_NAME(RvaToSegOffset)(pMod, uRva, &iSeg, &off);
     1423    else
     1424        rc = RTLDRELF_NAME(SegOffsetToRva)(pMod, iSeg, off, &uRva);
     1425    AssertRCReturn(rc, rc);
     1426
     1427    /*
     1428     * Map the image bits if not already done and setup pointer into it.
     1429     */
     1430    RT_NOREF(pvBits); /** @todo Try use passed in pvBits? */
     1431    rc = RTLDRELF_NAME(MapBits)(pThis, true);
     1432    if (RT_FAILURE(rc))
     1433        return rc;
     1434
     1435    /*
     1436     * Do we need to search for .eh_frame and .eh_frame_hdr?
     1437     */
     1438    if (pThis->iShEhFrame == 0)
     1439    {
     1440        pThis->iShEhFrame = ~0U;
     1441        pThis->iShEhFrameHdr = ~0U;
     1442        unsigned cLeft = 2;
     1443        for (unsigned iShdr = 1; iShdr < pThis->Ehdr.e_shnum; iShdr++)
     1444        {
     1445            const char *pszName = ELF_SH_STR(pThis, pThis->paShdrs[iShdr].sh_name);
     1446            if (   pszName[0] == '.'
     1447                && pszName[1] == 'e'
     1448                && pszName[2] == 'h'
     1449                && pszName[3] == '_'
     1450                && pszName[4] == 'f'
     1451                && pszName[5] == 'r'
     1452                && pszName[6] == 'a'
     1453                && pszName[7] == 'm'
     1454                && pszName[8] == 'e')
     1455            {
     1456                if (pszName[8] == '\0')
     1457                    pThis->iShEhFrame = iShdr;
     1458                else if (   pszName[8] == '_'
     1459                         && pszName[9] == 'h'
     1460                         && pszName[10] == 'd'
     1461                         && pszName[11] == 'r'
     1462                         && pszName[12] == '\0')
     1463                    pThis->iShEhFrameHdr = iShdr;
     1464                else
     1465                    continue;
     1466                if (--cLeft == 0)
     1467                    break;
     1468            }
     1469        }
     1470    }
     1471
     1472    /*
     1473     * Any info present?
     1474     */
     1475    unsigned iShdr = pThis->iShEhFrame;
     1476    if (   iShdr != ~0U
     1477        && pThis->paShdrs[iShdr].sh_size > 0)
     1478    {
     1479        if (pThis->paShdrs[iShdr].sh_flags & SHF_ALLOC)
     1480            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);
     1482    }
     1483    return VERR_DBG_NO_UNWIND_INFO;
     1484}
     1485
    14001486
    14011487
     
    14311517    NULL /*pfnVerifySignature*/,
    14321518    NULL /*pfnHashImage*/,
    1433     NULL /*pfnUnwindFrame*/,
     1519    RTLDRELF_NAME(UnwindFrame),
    14341520    42
    14351521};
     
    17831869    //pModElf->cbShStr        = 0;
    17841870    //pModElf->pShStr         = NULL;
     1871    //pModElf->iShEhFrame      = 0;
     1872    //pModElf->iShEhFrameHdr   = 0;
    17851873
    17861874    /*
  • trunk/src/VBox/Runtime/include/internal/dbgmod.h

    r73494 r73531  
    708708DECLHIDDEN(int) rtDbgModLdrOpenFromHandle(PRTDBGMODINT pDbgMod, RTLDRMOD hLdrMod);
    709709
     710DECLHIDDEN(int) rtDwarfUnwind_EhData(void const *pvSection, size_t cbSection, RTDBGSEGIDX idxSeg, RTUINTPTR offSeg,
     711                                     RTUINTPTR uRva, PRTDBGUNWINDSTATE pState, RTLDRARCH enmArch);
     712
    710713/** @} */
    711714
Note: See TracChangeset for help on using the changeset viewer.

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