Changeset 73531 in vbox
- Timestamp:
- Aug 6, 2018 5:08:57 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 124160
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/dbg/dbgmoddwarf.cpp
r73494 r73531 350 350 /** @} */ 351 351 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 352 375 353 376 /********************************************************************************************************************************* … … 506 529 /** The number of bytes left to read in the current unit. */ 507 530 size_t cbUnitLeft; 508 /** The DWARF debug info reader instance. */531 /** The DWARF debug info reader instance. (Can be NULL for eh_frame.) */ 509 532 PRTDBGMODDWARF pDwarfMod; 510 533 /** Set if this is 64-bit DWARF, clear if 32-bit. */ … … 1515 1538 1516 1539 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 */ 1549 static 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 */ 1579 static 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 1517 1594 /* 1518 1595 * … … 1892 1969 1893 1970 /** 1894 * Reads a 1, 2, 4 or 8 byte uns gined value.1971 * Reads a 1, 2, 4 or 8 byte unsigned value. 1895 1972 * 1896 1973 * @returns 64-bit unsigned value. … … 2022 2099 return uErrValue; 2023 2100 } 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 */ 2112 static 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; 2024 2151 } 2025 2152 … … 2069 2196 static uint32_t rtDwarfCursor_CalcSectOffsetU32(PRTDWARFCURSOR pCursor) 2070 2197 { 2071 size_t off = pCursor->pb - (uint8_t const *)pCursor->pDwarfMod->aSections[pCursor->enmSect].pv;2198 size_t off = pCursor->pb - pCursor->pbStart; 2072 2199 uint32_t offRet = (uint32_t)off; 2073 2200 if (offRet != off) … … 2274 2401 2275 2402 /** 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 */ 2410 static 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 /** 2276 2430 * Deletes a section reader initialized by rtDwarfCursor_Init. 2277 2431 * … … 2292 2446 pCursor->rc = VERR_INTERNAL_ERROR_4; 2293 2447 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 */ 2462 typedef 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. */ 2507 typedef RTDWARFCIEINFO *PRTDWARFCIEINFO; 2508 /** Pointer to const CIE info. */ 2509 typedef 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 */ 2524 static 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 */ 2588 static 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 */ 2730 DECLHIDDEN(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 */ 2836 static 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 */ 2871 DECLHIDDEN(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); 2294 2878 } 2295 2879 … … 4528 5112 static DECLCALLBACK(int) rtDbgModDwarf_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState) 4529 5113 { 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 } 4531 5145 return VERR_DBG_NO_UNWIND_INFO; 4532 5146 } -
trunk/src/VBox/Runtime/common/ldr/ldrELF.cpp
r69437 r73531 35 35 #include <iprt/alloc.h> 36 36 #include <iprt/assert.h> 37 #include <iprt/dbg.h> 37 38 #include <iprt/string.h> 38 39 #include <iprt/log.h> … … 43 44 #include <iprt/formats/elf-amd64.h> 44 45 #include "internal/ldr.h" 46 #include "internal/dbgmod.h" 45 47 46 48 -
trunk/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h
r73494 r73531 130 130 /** Pointer to section header string table within RTLDRMODELF::pvBits. */ 131 131 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; 132 137 } RTLDRMODELF, *PRTLDRMODELF; 133 138 … … 1299 1304 1300 1305 1301 /** @copydoc RTLDROPS::pfnR vaToSegOffset. */1306 /** @copydoc RTLDROPS::pfnReadDbgInfo. */ 1302 1307 static DECLCALLBACK(int) RTLDRELF_NAME(ReadDbgInfo)(PRTLDRMODINTERNAL pMod, uint32_t iDbgInfo, RTFOFF off, 1303 1308 size_t cb, void *pvBuf) … … 1398 1403 return rc; 1399 1404 } 1405 1406 1407 /** 1408 * @interface_method_impl{RTLDROPS,pfnUnwindFrame} 1409 */ 1410 static DECLCALLBACK(int) 1411 RTLDRELF_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 1400 1486 1401 1487 … … 1431 1517 NULL /*pfnVerifySignature*/, 1432 1518 NULL /*pfnHashImage*/, 1433 NULL /*pfnUnwindFrame*/,1519 RTLDRELF_NAME(UnwindFrame), 1434 1520 42 1435 1521 }; … … 1783 1869 //pModElf->cbShStr = 0; 1784 1870 //pModElf->pShStr = NULL; 1871 //pModElf->iShEhFrame = 0; 1872 //pModElf->iShEhFrameHdr = 0; 1785 1873 1786 1874 /* -
trunk/src/VBox/Runtime/include/internal/dbgmod.h
r73494 r73531 708 708 DECLHIDDEN(int) rtDbgModLdrOpenFromHandle(PRTDBGMODINT pDbgMod, RTLDRMOD hLdrMod); 709 709 710 DECLHIDDEN(int) rtDwarfUnwind_EhData(void const *pvSection, size_t cbSection, RTDBGSEGIDX idxSeg, RTUINTPTR offSeg, 711 RTUINTPTR uRva, PRTDBGUNWINDSTATE pState, RTLDRARCH enmArch); 712 710 713 /** @} */ 711 714
Note:
See TracChangeset
for help on using the changeset viewer.