- Timestamp:
- Apr 5, 2021 7:08:37 AM (4 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/dbgf.h
r87776 r88366 2918 2918 * @{ */ 2919 2919 /** The basic block is the entry into the owning control flow graph. */ 2920 #define DBGF_FLOW_BB_F_ENTRY RT_BIT_32(0)2920 #define DBGF_FLOW_BB_F_ENTRY RT_BIT_32(0) 2921 2921 /** The basic block was not populated because the limit was reached. */ 2922 #define DBGF_FLOW_BB_F_EMPTY RT_BIT_32(1)2922 #define DBGF_FLOW_BB_F_EMPTY RT_BIT_32(1) 2923 2923 /** The basic block is not complete because an error happened during disassembly. */ 2924 #define DBGF_FLOW_BB_F_INCOMPLETE_ERR RT_BIT_32(2)2924 #define DBGF_FLOW_BB_F_INCOMPLETE_ERR RT_BIT_32(2) 2925 2925 /** The basic block is reached through a branch table. */ 2926 #define DBGF_FLOW_BB_F_BRANCH_TABLE RT_BIT_32(3) 2926 #define DBGF_FLOW_BB_F_BRANCH_TABLE RT_BIT_32(3) 2927 /** The basic block consists only of a single call instruction because 2928 * DBGF_FLOW_CREATE_F_CALL_INSN_SEPARATE_BB was given. */ 2929 #define DBGF_FLOW_BB_F_CALL_INSN RT_BIT_32(4) 2930 /** The branch target of the call instruction could be deduced and can be queried with 2931 * DBGFR3FlowBbGetBranchAddress(). May only be available when DBGF_FLOW_BB_F_CALL_INSN 2932 * is set. */ 2933 #define DBGF_FLOW_BB_F_CALL_INSN_TARGET_KNOWN RT_BIT_32(5) 2927 2934 /** @} */ 2928 2935 … … 2930 2937 * @{ */ 2931 2938 /** Default options. */ 2932 #define DBGF_FLOW_CREATE_F_DEFAULT 02939 #define DBGF_FLOW_CREATE_F_DEFAULT 0 2933 2940 /** Tries to resolve indirect branches, useful for code using 2934 2941 * jump tables generated for large switch statements by some compilers. */ 2935 #define DBGF_FLOW_CREATE_F_TRY_RESOLVE_INDIRECT_BRANCHES RT_BIT_32(0) 2942 #define DBGF_FLOW_CREATE_F_TRY_RESOLVE_INDIRECT_BRANCHES RT_BIT_32(0) 2943 /** Call instructions are placed in a separate basic block. */ 2944 #define DBGF_FLOW_CREATE_F_CALL_INSN_SEPARATE_BB RT_BIT_32(1) 2936 2945 /** @} */ 2937 2946 … … 2994 3003 VMMR3DECL(uint32_t) DBGFR3FlowGetBbCount(DBGFFLOW hFlow); 2995 3004 VMMR3DECL(uint32_t) DBGFR3FlowGetBranchTblCount(DBGFFLOW hFlow); 3005 VMMR3DECL(uint32_t) DBGFR3FlowGetCallInsnCount(DBGFFLOW hFlow); 2996 3006 2997 3007 VMMR3DECL(uint32_t) DBGFR3FlowBbRetain(DBGFFLOWBB hFlowBb); -
trunk/src/VBox/VMM/VMMR3/DBGFR3Flow.cpp
r82968 r88366 68 68 /** Number of branch tables in this control flow graph. */ 69 69 uint32_t cBranchTbls; 70 /** Number of call instructions in this control flow graph. */ 71 uint32_t cCallInsns; 70 72 /** The lowest addres of a basic block. */ 71 73 DBGFADDRESS AddrLowest; … … 1148 1150 } 1149 1151 1150 pFlowBb->fFlags &= ~DBGF_FLOW_BB_F_EMPTY;1151 1152 1152 rc = dbgfR3DisasInstrStateEx(pUVM, idCpu, &AddrDisasm, fFlags, 1153 1153 &szOutput[0], sizeof(szOutput), &DisState); 1154 1154 if (RT_SUCCESS(rc)) 1155 1155 { 1156 if ( pThis->fFlags & DBGF_FLOW_CREATE_F_CALL_INSN_SEPARATE_BB 1157 && DisState.pCurInstr->uOpcode == OP_CALL 1158 && !(pFlowBb->fFlags & DBGF_FLOW_BB_F_EMPTY)) 1159 { 1160 /* 1161 * If the basic block is not empty, the basic block is terminated and the successor is added 1162 * which will contain the call instruction. 1163 */ 1164 pFlowBb->AddrTarget = AddrDisasm; 1165 pFlowBb->enmEndType = DBGFFLOWBBENDTYPE_UNCOND; 1166 rc = dbgfR3FlowBbSuccessorAdd(pThis, &AddrDisasm, 1167 (pFlowBb->fFlags & DBGF_FLOW_BB_F_BRANCH_TABLE), 1168 pFlowBb->pFlowBranchTbl); 1169 if (RT_FAILURE(rc)) 1170 dbgfR3FlowBbSetError(pFlowBb, rc, "Adding successor blocks failed with %Rrc", rc); 1171 break; 1172 } 1173 1174 pFlowBb->fFlags &= ~DBGF_FLOW_BB_F_EMPTY; 1156 1175 cbDisasmLeft -= DisState.cbInstr; 1157 1176 … … 1192 1211 { 1193 1212 uint16_t uOpc = DisState.pCurInstr->uOpcode; 1213 1214 if (uOpc == OP_CALL) 1215 pThis->cCallInsns++; 1194 1216 1195 1217 if ( uOpc == OP_RETN || uOpc == OP_RETF || uOpc == OP_IRET … … 1263 1285 } 1264 1286 } 1287 else if (pThis->fFlags & DBGF_FLOW_CREATE_F_CALL_INSN_SEPARATE_BB) 1288 { 1289 pFlowBb->enmEndType = DBGFFLOWBBENDTYPE_UNCOND; 1290 pFlowBb->fFlags |= DBGF_FLOW_BB_F_CALL_INSN; 1291 1292 /* Add new basic block coming after the call instruction. */ 1293 rc = dbgfR3FlowBbSuccessorAdd(pThis, &AddrDisasm, 1294 (pFlowBb->fFlags & DBGF_FLOW_BB_F_BRANCH_TABLE), 1295 pFlowBb->pFlowBranchTbl); 1296 if ( RT_SUCCESS(rc) 1297 && !dbgfR3FlowBranchTargetIsIndirect(&DisState.Param1)) 1298 { 1299 /* Resolve the branch target. */ 1300 rc = dbgfR3FlowQueryDirectBranchTarget(pUVM, idCpu, &DisState.Param1, &pInstr->AddrInstr, pInstr->cbInstr, 1301 RT_BOOL(DisState.pCurInstr->fOpType & DISOPTYPE_RELATIVE_CONTROLFLOW), 1302 &pFlowBb->AddrTarget); 1303 if (RT_SUCCESS(rc)) 1304 pFlowBb->fFlags |= DBGF_FLOW_BB_F_CALL_INSN_TARGET_KNOWN; 1305 } 1306 } 1265 1307 1266 1308 if (RT_FAILURE(rc)) … … 1268 1310 1269 1311 /* Quit disassembling. */ 1270 if ( uOpc != OP_CALL 1312 if ( ( uOpc != OP_CALL 1313 || (pThis->fFlags & DBGF_FLOW_CREATE_F_CALL_INSN_SEPARATE_BB)) 1271 1314 || RT_FAILURE(rc)) 1272 1315 break; … … 1290 1333 * @param idCpu CPU id for disassembling. 1291 1334 * @param pThis The control flow graph to populate. 1292 * @param pAddrStart The start address to disassemble at.1293 1335 * @param cbDisasmMax The maximum amount to disassemble. 1294 1336 * @param fFlags Combination of DBGF_DISAS_FLAGS_*. 1295 1337 */ 1296 static int dbgfR3FlowPopulate(PUVM pUVM, VMCPUID idCpu, PDBGFFLOWINT pThis, PDBGFADDRESS pAddrStart,1338 static int dbgfR3FlowPopulate(PUVM pUVM, VMCPUID idCpu, PDBGFFLOWINT pThis, 1297 1339 uint32_t cbDisasmMax, uint32_t fFlags) 1298 1340 { 1299 1341 int rc = VINF_SUCCESS; 1300 1342 PDBGFFLOWBBINT pFlowBb = dbgfR3FlowGetUnpopulatedBb(pThis); 1301 DBGFADDRESS AddrEnd = *pAddrStart;1302 DBGFR3AddrAdd(&AddrEnd, cbDisasmMax);1303 1343 1304 1344 while (VALID_PTR(pFlowBb)) … … 1350 1390 pThis->cBbs = 0; 1351 1391 pThis->cBranchTbls = 0; 1392 pThis->cCallInsns = 0; 1352 1393 pThis->fFlags = fFlagsFlow; 1353 1394 RTListInit(&pThis->LstFlowBb); … … 1359 1400 { 1360 1401 dbgfR3FlowLink(pThis, pFlowBb); 1361 rc = dbgfR3FlowPopulate(pUVM, idCpu, pThis, pAddressStart,cbDisasmMax, fFlagsDisasm);1402 rc = dbgfR3FlowPopulate(pUVM, idCpu, pThis, cbDisasmMax, fFlagsDisasm); 1362 1403 if (RT_SUCCESS(rc)) 1363 1404 { … … 1538 1579 1539 1580 /** 1581 * Returns the number of call instructions encountered in the given 1582 * control flow graph. 1583 * 1584 * @returns Number of call instructions. 1585 * @param hFlow The control flow graph handle. 1586 */ 1587 VMMR3DECL(uint32_t) DBGFR3FlowGetCallInsnCount(DBGFFLOW hFlow) 1588 { 1589 PDBGFFLOWINT pThis = hFlow; 1590 AssertPtrReturn(pThis, 0); 1591 1592 return pThis->cCallInsns; 1593 } 1594 1595 1596 /** 1540 1597 * Retains the basic block handle. 1541 1598 * … … 1613 1670 * @param pAddrTarget Where to store the branch address of the basic block. 1614 1671 * 1615 * @note This is only valid for unconditional or conditional branches and will assert 1616 * for every other basic block type. 1672 * @note This is only valid for unconditional or conditional branches, or for a basic block 1673 * containing only a call instruction when DBGF_FLOW_CREATE_F_CALL_INSN_SEPARATE_BB was given 1674 * during creation and the branch target could be deduced as indicated by the DBGF_FLOW_BB_F_CALL_INSN_TARGET_KNOWN 1675 * flag for the basic block. This method will assert for every other basic block type. 1617 1676 * @note For indirect unconditional branches using a branch table this will return the start address 1618 1677 * of the branch table. … … 1625 1684 AssertReturn( pFlowBb->enmEndType == DBGFFLOWBBENDTYPE_UNCOND_JMP 1626 1685 || pFlowBb->enmEndType == DBGFFLOWBBENDTYPE_COND 1627 || pFlowBb->enmEndType == DBGFFLOWBBENDTYPE_UNCOND_INDIRECT_JMP, 1686 || pFlowBb->enmEndType == DBGFFLOWBBENDTYPE_UNCOND_INDIRECT_JMP 1687 || ( pFlowBb->enmEndType == DBGFFLOWBBENDTYPE_UNCOND 1688 && (pFlowBb->fFlags & DBGF_FLOW_BB_F_CALL_INSN_TARGET_KNOWN)), 1628 1689 NULL); 1629 1690 -
trunk/src/VBox/VMM/VMMR3/VMMR3.def
r87787 r88366 163 163 DBGFR3FlowGetBbCount 164 164 DBGFR3FlowGetBranchTblCount 165 DBGFR3FlowGetCallInsnCount 165 166 DBGFR3FlowBbRetain 166 167 DBGFR3FlowBbRelease
Note:
See TracChangeset
for help on using the changeset viewer.