VirtualBox

Changeset 73397 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jul 30, 2018 3:25:28 PM (6 years ago)
Author:
vboxsync
Message:

DBGF: Unwinding PE/AMD64, considered sketches for generic unwinding using unwind info.

Location:
trunk/src/VBox/VMM/VMMR3
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/DBGFAddrSpace.cpp

    r70948 r73397  
    544544
    545545    /*
    546      * Make sure the handle has is already in the database.
     546     * Make sure the handle is already in the database.
    547547     */
    548548    int rc = VERR_NOT_FOUND;
     
    559559        rc = VINF_SUCCESS;
    560560    }
     561    else
     562        RTDbgAsRelease(hRealAliasFor);
    561563    DBGF_AS_DB_UNLOCK_WRITE(pUVM);
    562564
     
    12111213    }
    12121214
     1215    RTDbgAsRelease(hRealAS);
    12131216    return rc;
    12141217}
     
    12971300    }
    12981301
     1302    RTDbgAsRelease(hRealAS);
    12991303    return rc;
    13001304}
     
    13341338     * Do the lookup.
    13351339     */
    1336     return RTDbgAsLineByAddr(hRealAS, pAddress->FlatPtr, poffDisp, pLine, phMod);
     1340    int rc = RTDbgAsLineByAddr(hRealAS, pAddress->FlatPtr, poffDisp, pLine, phMod);
     1341
     1342    RTDbgAsRelease(hRealAS);
     1343    return rc;
    13371344}
    13381345
  • trunk/src/VBox/VMM/VMMR3/DBGFStack.cpp

    r73388 r73397  
    5252    VMCPUID     m_idCpu;
    5353    RTDBGAS     m_hAs;
     54
     55    uint64_t    m_auRegs[16];
    5456    uint64_t    m_uPc;
    55     uint64_t    m_aGprs[16];
     57    uint64_t    m_uRFlags;
     58    uint16_t    m_uCs;
     59    uint16_t    m_uSs;
    5660
    5761    RTDBGMOD    m_hCached;
     
    7074        if (pInitialCtx)
    7175        {
    72             m_aGprs[X86_GREG_xAX] = pInitialCtx->rax;
    73             m_aGprs[X86_GREG_xCX] = pInitialCtx->rcx;
    74             m_aGprs[X86_GREG_xDX] = pInitialCtx->rdx;
    75             m_aGprs[X86_GREG_xBX] = pInitialCtx->rbx;
    76             m_aGprs[X86_GREG_xSP] = pInitialCtx->rsp;
    77             m_aGprs[X86_GREG_xBP] = pInitialCtx->rbp;
    78             m_aGprs[X86_GREG_xSI] = pInitialCtx->rsi;
    79             m_aGprs[X86_GREG_xDI] = pInitialCtx->rdi;
    80             m_aGprs[X86_GREG_x8 ] = pInitialCtx->r8;
    81             m_aGprs[X86_GREG_x9 ] = pInitialCtx->r9;
    82             m_aGprs[X86_GREG_x10] = pInitialCtx->r10;
    83             m_aGprs[X86_GREG_x11] = pInitialCtx->r11;
    84             m_aGprs[X86_GREG_x12] = pInitialCtx->r12;
    85             m_aGprs[X86_GREG_x13] = pInitialCtx->r13;
    86             m_aGprs[X86_GREG_x14] = pInitialCtx->r14;
    87             m_aGprs[X86_GREG_x15] = pInitialCtx->r15;
    88             m_uPc                 = pInitialCtx->rip;
     76            m_auRegs[X86_GREG_xAX] = pInitialCtx->rax;
     77            m_auRegs[X86_GREG_xCX] = pInitialCtx->rcx;
     78            m_auRegs[X86_GREG_xDX] = pInitialCtx->rdx;
     79            m_auRegs[X86_GREG_xBX] = pInitialCtx->rbx;
     80            m_auRegs[X86_GREG_xSP] = pInitialCtx->rsp;
     81            m_auRegs[X86_GREG_xBP] = pInitialCtx->rbp;
     82            m_auRegs[X86_GREG_xSI] = pInitialCtx->rsi;
     83            m_auRegs[X86_GREG_xDI] = pInitialCtx->rdi;
     84            m_auRegs[X86_GREG_x8 ] = pInitialCtx->r8;
     85            m_auRegs[X86_GREG_x9 ] = pInitialCtx->r9;
     86            m_auRegs[X86_GREG_x10] = pInitialCtx->r10;
     87            m_auRegs[X86_GREG_x11] = pInitialCtx->r11;
     88            m_auRegs[X86_GREG_x12] = pInitialCtx->r12;
     89            m_auRegs[X86_GREG_x13] = pInitialCtx->r13;
     90            m_auRegs[X86_GREG_x14] = pInitialCtx->r14;
     91            m_auRegs[X86_GREG_x15] = pInitialCtx->r15;
     92            m_uPc                  = pInitialCtx->rip;
     93            m_uCs                  = pInitialCtx->cs.Sel;
     94            m_uSs                  = pInitialCtx->ss.Sel;
     95            m_uRFlags              = pInitialCtx->rflags.u;
    8996        }
    9097        else
    9198        {
    92             RT_BZERO(m_aGprs, sizeof(m_aGprs));
    93             m_uPc = 0;
    94         }
     99            RT_BZERO(m_auRegs, sizeof(m_auRegs));
     100            m_uPc                  = 0;
     101            m_uCs                  = 0;
     102            m_uSs                  = 0;
     103            m_uRFlags              = 0;
     104        }
     105
    95106        m_pUVM            = pUVM;
    96107        m_idCpu           = idCpu;
    97         m_hAs             = hAs;
     108        m_hAs             = DBGFR3AsResolveAndRetain(pUVM, hAs);
    98109
    99110        m_hCached         = NIL_RTDBGMOD;
     
    134145{
    135146    dbgfR3UnwindCtxFlushCache(this);
    136 }
    137 
    138 
     147    if (m_hAs != NIL_RTDBGAS)
     148    {
     149        RTDbgAsRelease(m_hAs);
     150        m_hAs = NIL_RTDBGAS;
     151    }
     152}
     153
     154
     155/**
     156 * Sets PC and SP.
     157 *
     158 * @returns true.
     159 * @param   pUnwindCtx          The unwind context.
     160 * @param   pAddrPC             The program counter (PC) value to set.
     161 * @param   pAddrStack          The stack pointer (SP) value to set.
     162 */
    139163static bool dbgfR3UnwindCtxSetPcAndSp(PDBGFUNWINDCTX pUnwindCtx, PCDBGFADDRESS pAddrPC, PCDBGFADDRESS pAddrStack)
    140164{
    141     pUnwindCtx->m_uPc                 = pAddrPC->FlatPtr;
    142     pUnwindCtx->m_aGprs[X86_GREG_xSP] = pAddrStack->FlatPtr;
     165    if (!DBGFADDRESS_IS_FAR(pAddrPC))
     166        pUnwindCtx->m_uPc = pAddrPC->FlatPtr;
     167    else
     168    {
     169        pUnwindCtx->m_uPc = pAddrPC->off;
     170        pUnwindCtx->m_uCs = pAddrPC->Sel;
     171    }
     172    if (!DBGFADDRESS_IS_FAR(pAddrStack))
     173        pUnwindCtx->m_auRegs[X86_GREG_xSP] = pAddrStack->FlatPtr;
     174    else
     175    {
     176        pUnwindCtx->m_auRegs[X86_GREG_xSP] = pAddrStack->off;
     177        pUnwindCtx->m_uSs                  = pAddrStack->Sel;
     178    }
    143179    return true;
     180}
     181
     182
     183/**
     184 * Try read a 16-bit value off the stack.
     185 *
     186 * @param   pUnwindCtx      The unwind context.
     187 * @param   uSrcAddr        The stack address.
     188 * @param   puDst           The read destination.
     189 */
     190static void dbgfR3UnwindCtxLoadU16(PDBGFUNWINDCTX pUnwindCtx, uint64_t uSrcAddr, uint16_t *puDst)
     191{
     192    DBGFADDRESS SrcAddr;
     193    DBGFR3MemRead(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu,
     194                  DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, &SrcAddr, uSrcAddr),
     195                  puDst, sizeof(*puDst));
    144196}
    145197
     
    188240
    189241
    190 static bool dbgfR3UnwindCtxDoOneFrameCached(PDBGFUNWINDCTX pUnwindCtx, uint32_t uRvaRip, PDBGFADDRESS pAddrFrame)
     242/**
     243 * Processes an IRET frame.
     244 *
     245 * @returns true.
     246 * @param   pUnwindCtx      The unwind context.
     247 * @param   fErrCd          Non-zero if there is an error code on the stack.
     248 * @param   pAddrFrame      Where to return the frame pointer.
     249 * @param   penmRetType     Where to return the return type.
     250 */
     251static bool dbgfR3UnwindCtxDoOneIRet(PDBGFUNWINDCTX pUnwindCtx, uint8_t fErrCd,
     252                                     PDBGFADDRESS pAddrFrame, DBGFRETURNTYPE *penmRetType)
     253{
     254    Assert(fErrCd <= 1);
     255    if (fErrCd)
     256        pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8; /* error code */
     257
     258    *penmRetType = DBGFRETURNTYPE_IRET64;
     259    DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, pAddrFrame,
     260                       pUnwindCtx->m_auRegs[X86_GREG_xSP] - /* pretend rbp is pushed on the stack */ 8);
     261
     262    dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP], &pUnwindCtx->m_uPc);
     263    pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8; /* RIP */
     264
     265    dbgfR3UnwindCtxLoadU16(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP], &pUnwindCtx->m_uCs);
     266    pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8; /* CS */
     267
     268    dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP], &pUnwindCtx->m_uRFlags);
     269    pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8; /* EFLAGS */
     270
     271    uint64_t uNewRsp = (pUnwindCtx->m_auRegs[X86_GREG_xSP] - 8) & ~(uint64_t)15;
     272    dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP], &uNewRsp);
     273    pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8; /* RSP */
     274
     275    dbgfR3UnwindCtxLoadU16(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP], &pUnwindCtx->m_uSs);
     276    pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8; /* SS */
     277
     278    pUnwindCtx->m_auRegs[X86_GREG_xSP] = uNewRsp;
     279    return true;
     280}
     281
     282
     283/**
     284 * Unwinds one frame using cached module info.
     285 *
     286 * @returns true on success, false on failure.
     287 * @param   pUnwindCtx      The unwind context.
     288 * @param   uRvaRip         The RVA of the RIP.
     289 * @param   pAddrFrame      Where to return the frame pointer.
     290 * @param   penmRetType     Where to return the return type.
     291 */
     292static bool dbgfR3UnwindCtxDoOneFrameCached(PDBGFUNWINDCTX pUnwindCtx, uint32_t uRvaRip,
     293                                            PDBGFADDRESS pAddrFrame, DBGFRETURNTYPE *penmRetType)
    191294{
    192295    /*
     
    197300    if (pEntry)
    198301    {
     302        IMAGE_RUNTIME_FUNCTION_ENTRY ChainedEntry;
    199303        unsigned iFrameReg   = ~0U;
    200304        unsigned offFrameReg = 0;
    201305
    202         for (;;)
     306        int      fInEpilog = -1; /* -1: not-determined-assume-false;  0: false;  1: true. */
     307        uint8_t  cbEpilog  = 0;
     308        uint8_t  offEpilog = UINT8_MAX;
     309        for (unsigned cChainLoops = 0; ; cChainLoops++)
    203310        {
    204311            /*
     
    225332            PCIMAGE_UNWIND_INFO pInfo = (PCIMAGE_UNWIND_INFO)&uBuf;
    226333
    227             if (pInfo->Version != 1)
     334            if (pInfo->Version != 1 && pInfo->Version != 2)
    228335                return false;
    229336
     
    234341            unsigned       iOpcode  = 0;
    235342
    236             /* First, skip opcodes that doesn't apply to us if we're the prolog. */
    237             uint32_t offPc = uRvaRip - pEntry->BeginAddress;
    238             if (offPc < pInfo->SizeOfProlog)
    239                 while (iOpcode < cOpcodes && pInfo->aOpcodes[iOpcode].u.CodeOffset > offPc)
     343            /*
     344             * Check for epilog opcodes at the start and see if we're in an epilog.
     345             */
     346            if (   pInfo->Version >= 2
     347                && iOpcode < cOpcodes
     348                && pInfo->aOpcodes[iOpcode].u.UnwindOp == IMAGE_AMD64_UWOP_EPILOG)
     349            {
     350                if (fInEpilog == -1)
     351                {
     352                    cbEpilog = pInfo->aOpcodes[iOpcode].u.CodeOffset;
     353                    Assert(cbEpilog > 0);
     354
     355                    uint32_t uRvaEpilog = pEntry->EndAddress - cbEpilog;
    240356                    iOpcode++;
    241 
    242             /* Execute. */
    243             if (pInfo->FrameRegister != 0)
    244             {
    245                 iFrameReg   = pInfo->FrameRegister;
    246                 offFrameReg = pInfo->FrameOffset * 16;
    247             }
    248             while (iOpcode < cOpcodes)
    249             {
    250                 Assert(pInfo->aOpcodes[iOpcode].u.CodeOffset <= offPc);
    251                 switch (pInfo->aOpcodes[iOpcode].u.UnwindOp)
    252                 {
    253                     case IMAGE_AMD64_UWOP_PUSH_NONVOL:
    254                         pUnwindCtx->m_aGprs[X86_GREG_xSP] -= 8;
    255                         dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_aGprs[X86_GREG_xSP],
    256                                                &pUnwindCtx->m_aGprs[pInfo->aOpcodes[iOpcode].u.OpInfo]);
    257                         iOpcode++;
    258                         break;
    259 
    260                     case IMAGE_AMD64_UWOP_ALLOC_LARGE:
    261                         iOpcode += 3;
    262                         AssertBreak(iOpcode <= cOpcodes);
    263                         pUnwindCtx->m_aGprs[X86_GREG_xSP] -= *(uint32_t const *)&pInfo->aOpcodes[iOpcode - 2];
    264                         break;
    265 
    266                     case IMAGE_AMD64_UWOP_ALLOC_SMALL:
    267                         AssertBreak(iOpcode <= cOpcodes);
    268                         pUnwindCtx->m_aGprs[X86_GREG_xSP] -= pInfo->aOpcodes[iOpcode].u.OpInfo * 8 + 8;
    269                         iOpcode++;
    270                         break;
    271 
    272                     case IMAGE_AMD64_UWOP_SET_FPREG:
    273                         iFrameReg = pInfo->aOpcodes[iOpcode].u.OpInfo;
    274                         offFrameReg = pInfo->FrameOffset * 16;
    275                         break;
    276 
    277                     case IMAGE_AMD64_UWOP_SAVE_NONVOL:
    278                     case IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR:
     357                    if (   (pInfo->aOpcodes[iOpcode - 1].u.OpInfo & 1)
     358                        && uRvaRip >= uRvaEpilog)
    279359                    {
    280                         bool const     fFar  = pInfo->aOpcodes[iOpcode].u.UnwindOp == IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR;
    281                         unsigned const iGreg = pInfo->aOpcodes[iOpcode].u.OpInfo;
    282                         uint32_t       off   = 0;
    283                         iOpcode++;
    284                         if (iOpcode < cOpcodes)
     360                        offEpilog = uRvaRip - uRvaEpilog;
     361                        fInEpilog = 1;
     362                    }
     363                    else
     364                    {
     365                        fInEpilog = 0;
     366                        while (iOpcode < cOpcodes && pInfo->aOpcodes[iOpcode].u.UnwindOp == IMAGE_AMD64_UWOP_EPILOG)
    285367                        {
    286                             off = pInfo->aOpcodes[iOpcode].FrameOffset;
     368                            uRvaEpilog = pEntry->EndAddress
     369                                       - (pInfo->aOpcodes[iOpcode].u.CodeOffset + (pInfo->aOpcodes[iOpcode].u.OpInfo << 8));
    287370                            iOpcode++;
    288                             if (fFar && iOpcode < cOpcodes)
     371                            if (uRvaRip - uRvaEpilog < cbEpilog)
    289372                            {
    290                                 off |= (uint32_t)pInfo->aOpcodes[iOpcode].FrameOffset << 16;
    291                                 iOpcode++;
     373                                offEpilog = uRvaRip - uRvaEpilog;
     374                                fInEpilog = 1;
     375                                break;
    292376                            }
    293377                        }
    294                         off *= 8;
    295                         dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_aGprs[X86_GREG_xSP] + off, &pUnwindCtx->m_aGprs[iGreg]);
    296                         break;
    297378                    }
    298 
    299                     case IMAGE_AMD64_UWOP_SAVE_XMM128:
    300                         iOpcode += 2;
    301                         break;
    302 
    303                     case IMAGE_AMD64_UWOP_SAVE_XMM128_FAR:
    304                         iOpcode += 3;
    305                         break;
    306 
    307                     case IMAGE_AMD64_UWOP_PUSH_MACHFRAME:
     379                }
     380                while (iOpcode < cOpcodes && pInfo->aOpcodes[iOpcode].u.UnwindOp == IMAGE_AMD64_UWOP_EPILOG)
     381                    iOpcode++;
     382            }
     383            if (fInEpilog != 1)
     384            {
     385                /*
     386                 * Skip opcodes that doesn't apply to us if we're in the prolog.
     387                 */
     388                uint32_t offPc = uRvaRip - pEntry->BeginAddress;
     389                if (offPc < pInfo->SizeOfProlog)
     390                    while (iOpcode < cOpcodes && pInfo->aOpcodes[iOpcode].u.CodeOffset > offPc)
     391                        iOpcode++;
     392
     393                /*
     394                 * Execute the opcodes.
     395                 */
     396                if (pInfo->FrameRegister != 0)
     397                {
     398                    iFrameReg   = pInfo->FrameRegister;
     399                    offFrameReg = pInfo->FrameOffset * 16;
     400                }
     401                while (iOpcode < cOpcodes)
     402                {
     403                    Assert(pInfo->aOpcodes[iOpcode].u.CodeOffset <= offPc);
     404                    switch (pInfo->aOpcodes[iOpcode].u.UnwindOp)
    308405                    {
    309                         Assert(pInfo->aOpcodes[iOpcode].u.OpInfo <= 1);
    310                         if (pInfo->aOpcodes[iOpcode].u.OpInfo)
    311                             pUnwindCtx->m_aGprs[X86_GREG_xSP] -= 8; /* error code */
    312 
    313                         pUnwindCtx->m_aGprs[X86_GREG_xSP] -= 8; /* RIP */
    314                         dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_aGprs[X86_GREG_xSP], &pUnwindCtx->m_uPc);
    315 
    316                         pUnwindCtx->m_aGprs[X86_GREG_xSP] -= 8; /* CS */
    317                         //dbgfR3UnwindCtxLoadU16(pUnwindCtx, pUnwindCtx->m_aGprs[X86_GREG_xSP], &pUnwindCtx->m_uCs);
    318 
    319                         pUnwindCtx->m_aGprs[X86_GREG_xSP] -= 8; /* EFLAGS */
    320                         //dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_aGprs[X86_GREG_xSP], &pUnwindCtx->m_uRFlags);
    321 
    322                         pUnwindCtx->m_aGprs[X86_GREG_xSP] -= 8; /* RSP */
    323                         uint64_t uNewRsp = (pUnwindCtx->m_aGprs[X86_GREG_xSP] - 8) & ~(uint64_t)15;
    324                         dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_aGprs[X86_GREG_xSP], &uNewRsp);
    325 
    326                         pUnwindCtx->m_aGprs[X86_GREG_xSP] -= 8; /* SS */
    327                         //dbgfR3UnwindCtxLoadU16(pUnwindCtx, pUnwindCtx->m_aGprs[X86_GREG_xSP], &pUnwindCtx->m_uSs);
    328 
    329                         pUnwindCtx->m_aGprs[X86_GREG_xSP] = uNewRsp;
    330                         return true;
     406                        case IMAGE_AMD64_UWOP_PUSH_NONVOL:
     407                            pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8;
     408                            dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP],
     409                                                   &pUnwindCtx->m_auRegs[pInfo->aOpcodes[iOpcode].u.OpInfo]);
     410                            iOpcode++;
     411                            break;
     412
     413                        case IMAGE_AMD64_UWOP_ALLOC_LARGE:
     414                            if (pInfo->aOpcodes[iOpcode].u.OpInfo == 0)
     415                            {
     416                                iOpcode += 2;
     417                                AssertBreak(iOpcode <= cOpcodes);
     418                                pUnwindCtx->m_auRegs[X86_GREG_xSP] += pInfo->aOpcodes[iOpcode - 1].FrameOffset * 8;
     419                            }
     420                            else
     421                            {
     422                                iOpcode += 3;
     423                                AssertBreak(iOpcode <= cOpcodes);
     424                                pUnwindCtx->m_auRegs[X86_GREG_xSP] += RT_MAKE_U32(pInfo->aOpcodes[iOpcode - 2].FrameOffset,
     425                                                                                  pInfo->aOpcodes[iOpcode - 1].FrameOffset);
     426                            }
     427                            break;
     428
     429                        case IMAGE_AMD64_UWOP_ALLOC_SMALL:
     430                            AssertBreak(iOpcode <= cOpcodes);
     431                            pUnwindCtx->m_auRegs[X86_GREG_xSP] += pInfo->aOpcodes[iOpcode].u.OpInfo * 8 + 8;
     432                            iOpcode++;
     433                            break;
     434
     435                        case IMAGE_AMD64_UWOP_SET_FPREG:
     436                            iFrameReg = pInfo->aOpcodes[iOpcode].u.OpInfo;
     437                            offFrameReg = pInfo->FrameOffset * 16;
     438                            iOpcode++;
     439                            break;
     440
     441                        case IMAGE_AMD64_UWOP_SAVE_NONVOL:
     442                        case IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR:
     443                        {
     444                            bool const     fFar  = pInfo->aOpcodes[iOpcode].u.UnwindOp == IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR;
     445                            unsigned const iGreg = pInfo->aOpcodes[iOpcode].u.OpInfo;
     446                            uint32_t       off   = 0;
     447                            iOpcode++;
     448                            if (iOpcode < cOpcodes)
     449                            {
     450                                off = pInfo->aOpcodes[iOpcode].FrameOffset;
     451                                iOpcode++;
     452                                if (fFar && iOpcode < cOpcodes)
     453                                {
     454                                    off |= (uint32_t)pInfo->aOpcodes[iOpcode].FrameOffset << 16;
     455                                    iOpcode++;
     456                                }
     457                            }
     458                            off *= 8;
     459                            dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP] + off, &pUnwindCtx->m_auRegs[iGreg]);
     460                            break;
     461                        }
     462
     463                        case IMAGE_AMD64_UWOP_SAVE_XMM128:
     464                            iOpcode += 2;
     465                            break;
     466
     467                        case IMAGE_AMD64_UWOP_SAVE_XMM128_FAR:
     468                            iOpcode += 3;
     469                            break;
     470
     471                        case IMAGE_AMD64_UWOP_PUSH_MACHFRAME:
     472                            return dbgfR3UnwindCtxDoOneIRet(pUnwindCtx, pInfo->aOpcodes[iOpcode].u.OpInfo, pAddrFrame, penmRetType);
     473
     474                        case IMAGE_AMD64_UWOP_EPILOG:
     475                            iOpcode += 1;
     476                            break;
     477
     478                        case IMAGE_AMD64_UWOP_RESERVED_7:
     479                            AssertFailedReturn(false);
     480
     481                        default:
     482                            AssertMsgFailedReturn(("%u\n", pInfo->aOpcodes[iOpcode].u.UnwindOp), false);
    331483                    }
    332 
    333                     case IMAGE_AMD64_UWOP_RESERVED_6:
    334                         AssertFailedReturn(false);
    335 
    336                     case IMAGE_AMD64_UWOP_RESERVED_7:
    337                         AssertFailedReturn(false);
    338 
    339                     default:
    340                         AssertMsgFailedReturn(("%u\n", pInfo->aOpcodes[iOpcode].u.UnwindOp), false);
     484                }
     485            }
     486            else
     487            {
     488                /*
     489                 * We're in the POP sequence of an epilog.  The POP sequence should
     490                 * mirror the PUSH sequence exactly.
     491                 *
     492                 * Note! We should only end up here for the initial frame (just consider
     493                 *       RSP, stack allocations, non-volatile register restores, ++).
     494                 */
     495                while (iOpcode < cOpcodes)
     496                {
     497                    switch (pInfo->aOpcodes[iOpcode].u.UnwindOp)
     498                    {
     499                        case IMAGE_AMD64_UWOP_PUSH_NONVOL:
     500                            pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8;
     501                            if (offEpilog == 0)
     502                                dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP],
     503                                                       &pUnwindCtx->m_auRegs[pInfo->aOpcodes[iOpcode].u.OpInfo]);
     504                            else
     505                            {
     506                                /* Decrement offEpilog by estimated POP instruction length. */
     507                                offEpilog -= 1;
     508                                if (offEpilog > 0 && pInfo->aOpcodes[iOpcode].u.OpInfo >= 8)
     509                                    offEpilog -= 1;
     510                            }
     511                            iOpcode++;
     512                            break;
     513
     514                        case IMAGE_AMD64_UWOP_PUSH_MACHFRAME: /* Must terminate an epilog, so always execute this. */
     515                            return dbgfR3UnwindCtxDoOneIRet(pUnwindCtx, pInfo->aOpcodes[iOpcode].u.OpInfo, pAddrFrame, penmRetType);
     516
     517                        case IMAGE_AMD64_UWOP_ALLOC_SMALL:
     518                        case IMAGE_AMD64_UWOP_SET_FPREG:
     519                        case IMAGE_AMD64_UWOP_EPILOG:
     520                            iOpcode++;
     521                            break;
     522                        case IMAGE_AMD64_UWOP_SAVE_NONVOL:
     523                        case IMAGE_AMD64_UWOP_SAVE_XMM128:
     524                            iOpcode += 2;
     525                            break;
     526                        case IMAGE_AMD64_UWOP_ALLOC_LARGE:
     527                        case IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR:
     528                        case IMAGE_AMD64_UWOP_SAVE_XMM128_FAR:
     529                            iOpcode += 3;
     530                            break;
     531
     532                        default:
     533                            AssertMsgFailedReturn(("%u\n", pInfo->aOpcodes[iOpcode].u.UnwindOp), false);
     534                    }
    341535                }
    342536            }
     
    347541            if (!(pInfo->Flags & IMAGE_UNW_FLAGS_CHAININFO))
    348542                break;
    349             /** @todo impl chains.   */
    350             break;
    351         }
    352 
    353         /** @todo do post processing. */
     543            ChainedEntry = *(PCIMAGE_RUNTIME_FUNCTION_ENTRY)&pInfo->aOpcodes[(cOpcodes + 1) & ~1];
     544            pEntry = &ChainedEntry;
     545            AssertReturn(cChainLoops < 32, false);
     546        }
     547
     548        /*
     549         * RSP should now give us the return address, so perform a RET.
     550         */
     551        *penmRetType = DBGFRETURNTYPE_NEAR64;
     552        DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, pAddrFrame,
     553                           pUnwindCtx->m_auRegs[X86_GREG_xSP] - /* pretend rbp is pushed on the stack */ 8);
     554
     555        dbgfR3UnwindCtxLoadU64(pUnwindCtx, pUnwindCtx->m_auRegs[X86_GREG_xSP], &pUnwindCtx->m_uPc);
     556        pUnwindCtx->m_auRegs[X86_GREG_xSP] += 8;
     557        return true;
    354558    }
    355559
     
    359563
    360564
    361 static bool dbgfR3UnwindCtxDoOneFrame(PDBGFUNWINDCTX pUnwindCtx, PDBGFADDRESS pAddrFrame)
     565/**
     566 * Tries to unwind one frame using unwind info.
     567 *
     568 * @returns true on success, false on failure.
     569 * @param   pUnwindCtx      The unwind context.
     570 * @param   pAddrFrame      Where to return the frame pointer.
     571 * @param   penmRetType     Where to return the return type.
     572 */
     573static bool dbgfR3UnwindCtxDoOneFrame(PDBGFUNWINDCTX pUnwindCtx, PDBGFADDRESS pAddrFrame, DBGFRETURNTYPE *penmRetType)
    362574{
    363575    /*
     
    366578    RTUINTPTR offCache = pUnwindCtx->m_uPc - pUnwindCtx->m_uCachedMapping;
    367579    if (offCache < pUnwindCtx->m_cbCachedMapping)
    368         return dbgfR3UnwindCtxDoOneFrameCached(pUnwindCtx, offCache, pAddrFrame);
     580        return dbgfR3UnwindCtxDoOneFrameCached(pUnwindCtx, offCache, pAddrFrame, penmRetType);
    369581
    370582    /*
     
    381593        pUnwindCtx->m_hCached         = hDbgMod;
    382594        pUnwindCtx->m_uCachedMapping  = uBase;
    383         pUnwindCtx->m_cbCachedMapping = RTDbgModSegmentSize(hDbgMod, idxSeg);
     595        pUnwindCtx->m_cbCachedMapping = idxSeg == NIL_RTDBGSEGIDX ? RTDbgModImageSize(hDbgMod)
     596                                      : RTDbgModSegmentSize(hDbgMod, idxSeg);
    384597
    385598        /* Play simple for now. */
    386599        if (   idxSeg == NIL_RTDBGSEGIDX
    387             && RTDbgModImageGetFormat(hDbgMod) == RTLDRFMT_32BIT_HACK /// @todo RTLDRFMT_PE (disabled code)
     600            && RTDbgModImageGetFormat(hDbgMod) == RTLDRFMT_PE
    388601            && RTDbgModImageGetArch(hDbgMod)   == RTLDRARCH_AMD64)
    389602        {
     
    391604             * Try query the unwind data.
    392605             */
     606            uint32_t uDummy;
    393607            size_t cbNeeded = 0;
    394             rc = RTDbgModImageQueryProp(hDbgMod, RTLDRPROP_UNWIND_TABLE, NULL, 0, &cbNeeded);
     608            rc = RTDbgModImageQueryProp(hDbgMod, RTLDRPROP_UNWIND_TABLE, &uDummy, 0, &cbNeeded);
    395609            if (   rc == VERR_BUFFER_OVERFLOW
    396610                && cbNeeded >= sizeof(*pUnwindCtx->m_paFunctions)
     
    400614                if (pvBuf)
    401615                {
    402                     rc = RTDbgModImageQueryProp(hDbgMod, RTLDRPROP_UNWIND_TABLE, pUnwindCtx->m_pbCachedInfo, cbNeeded, &cbNeeded);
     616                    rc = RTDbgModImageQueryProp(hDbgMod, RTLDRPROP_UNWIND_TABLE, pvBuf, cbNeeded + 32, &cbNeeded);
    403617                    if (RT_SUCCESS(rc))
    404618                    {
     
    409623
    410624                        return dbgfR3UnwindCtxDoOneFrameCached(pUnwindCtx, pUnwindCtx->m_uPc - pUnwindCtx->m_uCachedMapping,
    411                                                                pAddrFrame);
     625                                                               pAddrFrame, penmRetType);
    412626                    }
    413627                    RTMemFree(pvBuf);
     
    458672 *      4  return address
    459673 *      0  old ebp; current ebp points here
    460  *
    461  * @todo Add AMD64 support (needs teaming up with the module management for
    462  *       unwind tables).
    463  */
    464 DECL_NO_INLINE(static, int) dbgfR3StackWalk(PUVM pUVM, VMCPUID idCpu, RTDBGAS hAs, PDBGFSTACKFRAME pFrame)
     674 */
     675DECL_NO_INLINE(static, int) dbgfR3StackWalk(PDBGFUNWINDCTX pUnwindCtx, PDBGFSTACKFRAME pFrame, bool fFirst)
    465676{
    466677    /*
     
    471682
    472683    /*
    473      * Read the raw frame data.
    474      * We double cbRetAddr in case we find we have a far return.
    475      */
    476     const DBGFADDRESS   AddrOldPC = pFrame->AddrPC;
    477     unsigned            cbRetAddr = DBGFReturnTypeSize(pFrame->enmReturnType);
    478     unsigned            cbStackItem;
    479     switch (AddrOldPC.fFlags & DBGFADDRESS_FLAGS_TYPE_MASK)
     684     * Advance the frame (except for the first).
     685     */
     686    if (!fFirst) /** @todo we can probably eliminate this fFirst business... */
     687    {
     688        /* frame, pc and stack is taken from the existing frames return members. */
     689        pFrame->AddrFrame = pFrame->AddrReturnFrame;
     690        pFrame->AddrPC    = pFrame->AddrReturnPC;
     691        pFrame->pSymPC    = pFrame->pSymReturnPC;
     692        pFrame->pLinePC   = pFrame->pLineReturnPC;
     693
     694        /* increment the frame number. */
     695        pFrame->iFrame++;
     696
     697        /* UNWIND_INFO_RET -> USED_UNWIND; return type */
     698        if (!(pFrame->fFlags & DBGFSTACKFRAME_FLAGS_UNWIND_INFO_RET))
     699            pFrame->fFlags &= ~DBGFSTACKFRAME_FLAGS_USED_UNWIND_INFO;
     700        else
     701        {
     702            pFrame->fFlags |= DBGFSTACKFRAME_FLAGS_USED_UNWIND_INFO;
     703            pFrame->fFlags &= ~DBGFSTACKFRAME_FLAGS_UNWIND_INFO_RET;
     704            if (pFrame->enmReturnFrameReturnType != DBGFRETURNTYPE_INVALID)
     705            {
     706                pFrame->enmReturnType = pFrame->enmReturnFrameReturnType;
     707                pFrame->enmReturnFrameReturnType = DBGFRETURNTYPE_INVALID;
     708            }
     709        }
     710    }
     711
     712    /*
     713     * Figure the return address size and use the old PC to guess stack item size.
     714     */
     715    /** @todo this is bogus... */
     716    unsigned cbRetAddr = DBGFReturnTypeSize(pFrame->enmReturnType);
     717    unsigned cbStackItem;
     718    switch (pFrame->AddrPC.fFlags & DBGFADDRESS_FLAGS_TYPE_MASK)
    480719    {
    481720        case DBGFADDRESS_FLAGS_FAR16: cbStackItem = 2; break;
     
    507746    }
    508747
     748    /*
     749     * Read the raw frame data.
     750     * We double cbRetAddr in case we have a far return.
     751     */
    509752    union
    510753    {
     
    522765
    523766    Assert(DBGFADDRESS_IS_VALID(&pFrame->AddrFrame));
    524     int rc = dbgfR3StackRead(pUVM, idCpu, u.pv,
    525                              pFrame->fFlags & DBGFSTACKFRAME_FLAGS_ALL_VALID
    526                              ? &pFrame->AddrReturnFrame
    527                              : &pFrame->AddrFrame,
    528                              cbRead, &cbRead);
    529     if (    RT_FAILURE(rc)
    530         ||  cbRead < cbRetAddr + cbStackItem)
     767    int rc = dbgfR3StackRead(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, u.pv, &pFrame->AddrFrame, cbRead, &cbRead);
     768    if (   RT_FAILURE(rc)
     769        || cbRead < cbRetAddr + cbStackItem)
    531770        pFrame->fFlags |= DBGFSTACKFRAME_FLAGS_LAST;
    532771
    533772    /*
    534      * The first step is taken in a different way than the others.
    535      */
    536     if (!(pFrame->fFlags & DBGFSTACKFRAME_FLAGS_ALL_VALID))
    537     {
    538         pFrame->fFlags |= DBGFSTACKFRAME_FLAGS_ALL_VALID;
    539         pFrame->iFrame = 0;
    540 
    541         /* Current PC - set by caller, just find symbol & line. */
    542         if (DBGFADDRESS_IS_VALID(&pFrame->AddrPC))
    543         {
    544             pFrame->pSymPC  = DBGFR3AsSymbolByAddrA(pUVM, hAs, &pFrame->AddrPC,
    545                                                     RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL | RTDBGSYMADDR_FLAGS_SKIP_ABS_IN_DEFERRED,
    546                                                     NULL /*poffDisp*/, NULL /*phMod*/);
    547             pFrame->pLinePC = DBGFR3AsLineByAddrA(pUVM, hAs, &pFrame->AddrPC, NULL /*poffDisp*/, NULL /*phMod*/);
    548         }
    549     }
    550     else /* 2nd and subsequent steps */
    551     {
    552         /* frame, pc and stack is taken from the existing frames return members. */
    553         pFrame->AddrFrame = pFrame->AddrReturnFrame;
    554         pFrame->AddrPC    = pFrame->AddrReturnPC;
    555         pFrame->pSymPC    = pFrame->pSymReturnPC;
    556         pFrame->pLinePC   = pFrame->pLineReturnPC;
    557 
    558         /* increment the frame number. */
    559         pFrame->iFrame++;
    560     }
    561 
    562     /*
    563773     * Return Frame address.
     774     *
     775     * If we used unwind info to get here, the unwind register context will be
     776     * positioned after the return instruction has been executed.  We start by
     777     * picking up the rBP register here for return frame and will try improve
     778     * on it further down by using unwind info.
    564779     */
    565780    pFrame->AddrReturnFrame = pFrame->AddrFrame;
    566     switch (cbStackItem)
    567     {
    568         case 2:    pFrame->AddrReturnFrame.off = *uBp.pu16; break;
    569         case 4:    pFrame->AddrReturnFrame.off = *uBp.pu32; break;
    570         case 8:    pFrame->AddrReturnFrame.off = *uBp.pu64; break;
    571         default:    AssertMsgFailedReturn(("cbStackItem=%d\n", cbStackItem), VERR_DBGF_STACK_IPE_1);
    572     }
    573 
    574     /* Watcom tries to keep the frame pointer odd for far returns. */
    575     if (cbStackItem <= 4)
    576     {
    577         if (pFrame->AddrReturnFrame.off & 1)
    578         {
    579             pFrame->AddrReturnFrame.off &= ~(RTGCUINTPTR)1;
    580             if (pFrame->enmReturnType == DBGFRETURNTYPE_NEAR16)
    581             {
    582                 pFrame->fFlags       |= DBGFSTACKFRAME_FLAGS_USED_ODD_EVEN;
    583                 pFrame->enmReturnType = DBGFRETURNTYPE_FAR16;
    584                 cbRetAddr = 4;
     781    if (pFrame->fFlags & DBGFSTACKFRAME_FLAGS_USED_UNWIND_INFO)
     782    {
     783        if (   pFrame->enmReturnType == DBGFRETURNTYPE_IRET32_PRIV
     784            && pFrame->enmReturnType == DBGFRETURNTYPE_IRET64)
     785            DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &pFrame->AddrReturnFrame,
     786                                 pUnwindCtx->m_uSs, pUnwindCtx->m_auRegs[X86_GREG_xBP]);
     787        else if (pFrame->enmReturnType == DBGFRETURNTYPE_IRET32_V86)
     788            DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, &pFrame->AddrReturnFrame,
     789                               ((uint32_t)pUnwindCtx->m_uSs << 4) + pUnwindCtx->m_auRegs[X86_GREG_xBP]);
     790        else
     791        {
     792            pFrame->AddrReturnFrame.off      = pUnwindCtx->m_auRegs[X86_GREG_xBP];
     793            pFrame->AddrReturnFrame.FlatPtr += pFrame->AddrReturnFrame.off - pFrame->AddrFrame.off;
     794        }
     795    }
     796    else
     797    {
     798        switch (cbStackItem)
     799        {
     800            case 2:     pFrame->AddrReturnFrame.off = *uBp.pu16; break;
     801            case 4:     pFrame->AddrReturnFrame.off = *uBp.pu32; break;
     802            case 8:     pFrame->AddrReturnFrame.off = *uBp.pu64; break;
     803            default:    AssertMsgFailedReturn(("cbStackItem=%d\n", cbStackItem), VERR_DBGF_STACK_IPE_1);
     804        }
     805
     806        /* Watcom tries to keep the frame pointer odd for far returns. */
     807        if (   cbStackItem <= 4
     808            && !(pFrame->fFlags & DBGFSTACKFRAME_FLAGS_USED_UNWIND_INFO))
     809        {
     810            if (pFrame->AddrReturnFrame.off & 1)
     811            {
     812                pFrame->AddrReturnFrame.off &= ~(RTGCUINTPTR)1;
     813                if (pFrame->enmReturnType == DBGFRETURNTYPE_NEAR16)
     814                {
     815                    pFrame->fFlags       |= DBGFSTACKFRAME_FLAGS_USED_ODD_EVEN;
     816                    pFrame->enmReturnType = DBGFRETURNTYPE_FAR16;
     817                    cbRetAddr = 4;
     818                }
     819                else if (pFrame->enmReturnType == DBGFRETURNTYPE_NEAR32)
     820                {
     821                    pFrame->fFlags       |= DBGFSTACKFRAME_FLAGS_USED_ODD_EVEN;
     822                    pFrame->enmReturnType = DBGFRETURNTYPE_FAR32;
     823                    cbRetAddr = 8;
     824                }
    585825            }
    586             else if (pFrame->enmReturnType == DBGFRETURNTYPE_NEAR32)
    587             {
    588                 pFrame->fFlags       |= DBGFSTACKFRAME_FLAGS_USED_ODD_EVEN;
    589                 pFrame->enmReturnType = DBGFRETURNTYPE_FAR32;
    590                 cbRetAddr = 8;
     826            else if (pFrame->fFlags & DBGFSTACKFRAME_FLAGS_USED_ODD_EVEN)
     827            {
     828                if (pFrame->enmReturnType == DBGFRETURNTYPE_FAR16)
     829                {
     830                    pFrame->enmReturnType = DBGFRETURNTYPE_NEAR16;
     831                    cbRetAddr = 2;
     832                }
     833                else if (pFrame->enmReturnType == DBGFRETURNTYPE_NEAR32)
     834                {
     835                    pFrame->enmReturnType = DBGFRETURNTYPE_FAR32;
     836                    cbRetAddr = 4;
     837                }
     838                pFrame->fFlags &= ~DBGFSTACKFRAME_FLAGS_USED_ODD_EVEN;
    591839            }
    592         }
    593         else if (pFrame->fFlags & DBGFSTACKFRAME_FLAGS_USED_ODD_EVEN)
    594         {
    595             if (pFrame->enmReturnType == DBGFRETURNTYPE_FAR16)
    596             {
    597                 pFrame->enmReturnType = DBGFRETURNTYPE_NEAR16;
    598                 cbRetAddr = 2;
    599             }
    600             else if (pFrame->enmReturnType == DBGFRETURNTYPE_NEAR32)
    601             {
    602                 pFrame->enmReturnType = DBGFRETURNTYPE_FAR32;
    603                 cbRetAddr = 4;
    604             }
    605             pFrame->fFlags &= ~DBGFSTACKFRAME_FLAGS_USED_ODD_EVEN;
    606         }
    607         uArgs.pb = u.pb + cbStackItem + cbRetAddr;
    608     }
    609 
    610     pFrame->AddrReturnFrame.FlatPtr += pFrame->AddrReturnFrame.off - pFrame->AddrFrame.off;
    611 
    612     /*
    613      * Return PC and Stack Addresses.
    614      */
    615     /** @todo AddrReturnStack is not correct for stdcall and pascal. (requires scope info) */
    616     pFrame->AddrReturnStack          = pFrame->AddrFrame;
    617     pFrame->AddrReturnStack.off     += cbStackItem + cbRetAddr;
    618     pFrame->AddrReturnStack.FlatPtr += cbStackItem + cbRetAddr;
    619 
    620     pFrame->AddrReturnPC             = pFrame->AddrPC;
    621     switch (pFrame->enmReturnType)
    622     {
    623         case DBGFRETURNTYPE_NEAR16:
    624             if (DBGFADDRESS_IS_VALID(&pFrame->AddrReturnPC))
    625             {
    626                 pFrame->AddrReturnPC.FlatPtr += *uRet.pu16 - pFrame->AddrReturnPC.off;
    627                 pFrame->AddrReturnPC.off      = *uRet.pu16;
    628             }
    629             else
    630                 DBGFR3AddrFromFlat(pUVM, &pFrame->AddrReturnPC, *uRet.pu16);
    631             break;
    632         case DBGFRETURNTYPE_NEAR32:
    633             if (DBGFADDRESS_IS_VALID(&pFrame->AddrReturnPC))
    634             {
    635                 pFrame->AddrReturnPC.FlatPtr += *uRet.pu32 - pFrame->AddrReturnPC.off;
    636                 pFrame->AddrReturnPC.off      = *uRet.pu32;
    637             }
    638             else
    639                 DBGFR3AddrFromFlat(pUVM, &pFrame->AddrReturnPC, *uRet.pu32);
    640             break;
    641         case DBGFRETURNTYPE_NEAR64:
    642             if (DBGFADDRESS_IS_VALID(&pFrame->AddrReturnPC))
    643             {
    644                 pFrame->AddrReturnPC.FlatPtr += *uRet.pu64 - pFrame->AddrReturnPC.off;
    645                 pFrame->AddrReturnPC.off      = *uRet.pu64;
    646             }
    647             else
    648                 DBGFR3AddrFromFlat(pUVM, &pFrame->AddrReturnPC, *uRet.pu64);
    649             break;
    650         case DBGFRETURNTYPE_FAR16:
    651             DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[1], uRet.pu16[0]);
    652             break;
    653         case DBGFRETURNTYPE_FAR32:
    654             DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]);
    655             break;
    656         case DBGFRETURNTYPE_FAR64:
    657             DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[4], uRet.pu64[0]);
    658             break;
    659         case DBGFRETURNTYPE_IRET16:
    660             DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[1], uRet.pu16[0]);
    661             break;
    662         case DBGFRETURNTYPE_IRET32:
    663             DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]);
    664             break;
    665         case DBGFRETURNTYPE_IRET32_PRIV:
    666             DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]);
    667             break;
    668         case DBGFRETURNTYPE_IRET32_V86:
    669             DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]);
    670             break;
    671         case DBGFRETURNTYPE_IRET64:
    672             DBGFR3AddrFromSelOff(pUVM, idCpu, &pFrame->AddrReturnPC, uRet.pu16[4], uRet.pu64[0]);
    673             break;
    674         default:
    675             AssertMsgFailed(("enmReturnType=%d\n", pFrame->enmReturnType));
    676             return VERR_INVALID_PARAMETER;
    677     }
    678 
    679     pFrame->pSymReturnPC  = DBGFR3AsSymbolByAddrA(pUVM, hAs, &pFrame->AddrReturnPC,
     840            uArgs.pb = u.pb + cbStackItem + cbRetAddr;
     841        }
     842
     843        pFrame->AddrReturnFrame.FlatPtr += pFrame->AddrReturnFrame.off - pFrame->AddrFrame.off;
     844    }
     845
     846    /*
     847     * Return Stack Address.
     848     */
     849    pFrame->AddrReturnStack = pFrame->AddrReturnFrame;
     850    if (pFrame->fFlags & DBGFSTACKFRAME_FLAGS_USED_UNWIND_INFO)
     851    {
     852        if (   pFrame->enmReturnType == DBGFRETURNTYPE_IRET32_PRIV
     853            && pFrame->enmReturnType == DBGFRETURNTYPE_IRET64)
     854            DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &pFrame->AddrReturnStack,
     855                                 pUnwindCtx->m_uSs, pUnwindCtx->m_auRegs[X86_GREG_xSP]);
     856        else if (pFrame->enmReturnType == DBGFRETURNTYPE_IRET32_V86)
     857            DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, &pFrame->AddrReturnStack,
     858                               ((uint32_t)pUnwindCtx->m_uSs << 4) + pUnwindCtx->m_auRegs[X86_GREG_xSP]);
     859        else
     860        {
     861            pFrame->AddrReturnStack.off      = pUnwindCtx->m_auRegs[X86_GREG_xSP];
     862            pFrame->AddrReturnStack.FlatPtr += pFrame->AddrReturnStack.off - pFrame->AddrStack.off;
     863        }
     864    }
     865    else
     866    {
     867        pFrame->AddrReturnStack.off     += cbStackItem + cbRetAddr;
     868        pFrame->AddrReturnStack.FlatPtr += cbStackItem + cbRetAddr;
     869    }
     870
     871    /*
     872     * Return PC.
     873     */
     874    pFrame->AddrReturnPC = pFrame->AddrPC;
     875    if (pFrame->fFlags & DBGFSTACKFRAME_FLAGS_USED_UNWIND_INFO)
     876    {
     877        if (DBGFReturnTypeIsNear(pFrame->enmReturnType))
     878        {
     879            pFrame->AddrReturnPC.off      = pUnwindCtx->m_uPc;
     880            pFrame->AddrReturnPC.FlatPtr += pFrame->AddrReturnPC.off - pFrame->AddrPC.off;
     881        }
     882        else
     883            DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &pFrame->AddrReturnPC,
     884                                 pUnwindCtx->m_uCs, pUnwindCtx->m_uPc);
     885    }
     886    else
     887        switch (pFrame->enmReturnType)
     888        {
     889            case DBGFRETURNTYPE_NEAR16:
     890                if (DBGFADDRESS_IS_VALID(&pFrame->AddrReturnPC))
     891                {
     892                    pFrame->AddrReturnPC.FlatPtr += *uRet.pu16 - pFrame->AddrReturnPC.off;
     893                    pFrame->AddrReturnPC.off      = *uRet.pu16;
     894                }
     895                else
     896                    DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, &pFrame->AddrReturnPC, *uRet.pu16);
     897                break;
     898            case DBGFRETURNTYPE_NEAR32:
     899                if (DBGFADDRESS_IS_VALID(&pFrame->AddrReturnPC))
     900                {
     901                    pFrame->AddrReturnPC.FlatPtr += *uRet.pu32 - pFrame->AddrReturnPC.off;
     902                    pFrame->AddrReturnPC.off      = *uRet.pu32;
     903                }
     904                else
     905                    DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, &pFrame->AddrReturnPC, *uRet.pu32);
     906                break;
     907            case DBGFRETURNTYPE_NEAR64:
     908                if (DBGFADDRESS_IS_VALID(&pFrame->AddrReturnPC))
     909                {
     910                    pFrame->AddrReturnPC.FlatPtr += *uRet.pu64 - pFrame->AddrReturnPC.off;
     911                    pFrame->AddrReturnPC.off      = *uRet.pu64;
     912                }
     913                else
     914                    DBGFR3AddrFromFlat(pUnwindCtx->m_pUVM, &pFrame->AddrReturnPC, *uRet.pu64);
     915                break;
     916            case DBGFRETURNTYPE_FAR16:
     917                DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &pFrame->AddrReturnPC, uRet.pu16[1], uRet.pu16[0]);
     918                break;
     919            case DBGFRETURNTYPE_FAR32:
     920                DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]);
     921                break;
     922            case DBGFRETURNTYPE_FAR64:
     923                DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &pFrame->AddrReturnPC, uRet.pu16[4], uRet.pu64[0]);
     924                break;
     925            case DBGFRETURNTYPE_IRET16:
     926                DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &pFrame->AddrReturnPC, uRet.pu16[1], uRet.pu16[0]);
     927                break;
     928            case DBGFRETURNTYPE_IRET32:
     929                DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]);
     930                break;
     931            case DBGFRETURNTYPE_IRET32_PRIV:
     932                DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]);
     933                break;
     934            case DBGFRETURNTYPE_IRET32_V86:
     935                DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &pFrame->AddrReturnPC, uRet.pu16[2], uRet.pu32[0]);
     936                break;
     937            case DBGFRETURNTYPE_IRET64:
     938                DBGFR3AddrFromSelOff(pUnwindCtx->m_pUVM, pUnwindCtx->m_idCpu, &pFrame->AddrReturnPC, uRet.pu16[4], uRet.pu64[0]);
     939                break;
     940            default:
     941                AssertMsgFailed(("enmReturnType=%d\n", pFrame->enmReturnType));
     942                return VERR_INVALID_PARAMETER;
     943        }
     944
     945
     946    pFrame->pSymReturnPC  = DBGFR3AsSymbolByAddrA(pUnwindCtx->m_pUVM, pUnwindCtx->m_hAs, &pFrame->AddrReturnPC,
    680947                                                  RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL | RTDBGSYMADDR_FLAGS_SKIP_ABS_IN_DEFERRED,
    681948                                                  NULL /*poffDisp*/, NULL /*phMod*/);
    682     pFrame->pLineReturnPC = DBGFR3AsLineByAddrA(pUVM, hAs, &pFrame->AddrReturnPC, NULL /*poffDisp*/, NULL /*phMod*/);
     949    pFrame->pLineReturnPC = DBGFR3AsLineByAddrA(pUnwindCtx->m_pUVM, pUnwindCtx->m_hAs, &pFrame->AddrReturnPC,
     950                                                NULL /*poffDisp*/, NULL /*phMod*/);
    683951
    684952    /*
    685953     * Frame bitness flag.
    686954     */
     955    /** @todo use previous return type for this? */
     956    pFrame->fFlags &= ~(DBGFSTACKFRAME_FLAGS_16BIT | DBGFSTACKFRAME_FLAGS_32BIT | DBGFSTACKFRAME_FLAGS_64BIT);
    687957    switch (cbStackItem)
    688958    {
     
    697967     */
    698968    memcpy(&pFrame->Args, uArgs.pv, sizeof(pFrame->Args));
     969
     970    /*
     971     * Try use unwind information to locate the return frame pointer (for the
     972     * next loop iteration).
     973     */
     974    Assert(!(pFrame->fFlags & DBGFSTACKFRAME_FLAGS_UNWIND_INFO_RET));
     975    pFrame->enmReturnFrameReturnType = DBGFRETURNTYPE_INVALID;
     976    if (!(pFrame->fFlags & DBGFSTACKFRAME_FLAGS_LAST))
     977    {
     978        /* Set PC and SP if we didn't unwind our way here (context will then point
     979           and the return PC and SP already). */
     980        if (!(pFrame->fFlags & DBGFSTACKFRAME_FLAGS_USED_UNWIND_INFO))
     981        {
     982            dbgfR3UnwindCtxSetPcAndSp(pUnwindCtx, &pFrame->AddrReturnPC, &pFrame->AddrReturnStack);
     983        }
     984        /** @todo Reevaluate CS if the previous frame return type isn't near. */
     985
     986        DBGFADDRESS    AddrReturnFrame = pFrame->AddrReturnFrame;
     987        DBGFRETURNTYPE enmReturnType   = pFrame->enmReturnType;
     988        if (dbgfR3UnwindCtxDoOneFrame(pUnwindCtx, &AddrReturnFrame, &enmReturnType))
     989        {
     990            pFrame->fFlags                  |= DBGFSTACKFRAME_FLAGS_UNWIND_INFO_RET;
     991            pFrame->AddrReturnFrame          = AddrReturnFrame;
     992            pFrame->enmReturnFrameReturnType = enmReturnType;
     993        }
     994    }
    699995
    700996    return VINF_SUCCESS;
     
    7931089            rc = DBGFR3AddrFromSelOff(pUVM, idCpu, &pCur->AddrStack, pCtx->ss.Sel, pCtx->rsp & fAddrMask);
    7941090
     1091        Assert(!(pCur->fFlags & DBGFSTACKFRAME_FLAGS_USED_UNWIND_INFO));
    7951092        if (pAddrFrame)
    7961093            pCur->AddrFrame = *pAddrFrame;
    797         else
    798         {
    799             if (   RT_SUCCESS(rc)
    800                 && dbgfR3UnwindCtxSetPcAndSp(&UnwindCtx, &pCur->AddrPC, &pCur->AddrStack)
    801                 && dbgfR3UnwindCtxDoOneFrame(&UnwindCtx, &pCur->AddrFrame))
    802             { }
    803             else if (enmCodeType != DBGFCODETYPE_GUEST)
    804                 DBGFR3AddrFromFlat(pUVM, &pCur->AddrFrame, pCtx->rbp & fAddrMask);
    805             else if (RT_SUCCESS(rc))
    806                 rc = DBGFR3AddrFromSelOff(pUVM, idCpu, &pCur->AddrFrame, pCtx->ss.Sel, pCtx->rbp & fAddrMask);
     1094        else if (   RT_SUCCESS(rc)
     1095                 && dbgfR3UnwindCtxSetPcAndSp(&UnwindCtx, &pCur->AddrPC, &pCur->AddrStack)
     1096                 && dbgfR3UnwindCtxDoOneFrame(&UnwindCtx, &pCur->AddrFrame, &pCur->enmReturnType))
     1097        {
     1098            pCur->fFlags |= DBGFSTACKFRAME_FLAGS_USED_UNWIND_INFO;
     1099        }
     1100        else if (enmCodeType != DBGFCODETYPE_GUEST)
     1101            DBGFR3AddrFromFlat(pUVM, &pCur->AddrFrame, pCtx->rbp & fAddrMask);
     1102        else if (RT_SUCCESS(rc))
     1103            rc = DBGFR3AddrFromSelOff(pUVM, idCpu, &pCur->AddrFrame, pCtx->ss.Sel, pCtx->rbp & fAddrMask);
     1104
     1105        /*
     1106         * The first frame.
     1107         */
     1108        if (RT_SUCCESS(rc))
     1109        {
     1110            if (DBGFADDRESS_IS_VALID(&pCur->AddrPC))
     1111            {
     1112                pCur->pSymPC  = DBGFR3AsSymbolByAddrA(pUVM, hAs, &pCur->AddrPC,
     1113                                                      RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL | RTDBGSYMADDR_FLAGS_SKIP_ABS_IN_DEFERRED,
     1114                                                      NULL /*poffDisp*/, NULL /*phMod*/);
     1115                pCur->pLinePC = DBGFR3AsLineByAddrA(pUVM, hAs, &pCur->AddrPC, NULL /*poffDisp*/, NULL /*phMod*/);
     1116            }
     1117
     1118            rc = dbgfR3StackWalk(&UnwindCtx, pCur, true /*fFirst*/);
    8071119        }
    8081120    }
    8091121    else
    8101122        pCur->enmReturnType = enmReturnType;
    811 
    812     /*
    813      * The first frame.
    814      */
    815     if (RT_SUCCESS(rc))
    816         rc = dbgfR3StackWalk(pUVM, idCpu, hAs, pCur);
    8171123    if (RT_FAILURE(rc))
    8181124    {
     
    8281134    {
    8291135        /* try walk. */
    830         rc = dbgfR3StackWalk(pUVM, idCpu, hAs, &Next);
     1136        rc = dbgfR3StackWalk(&UnwindCtx, &Next, false /*fFirst*/);
    8311137        if (RT_FAILURE(rc))
    8321138            break;
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