/** * @callback_method_impl{FNDBGCOPUNARY, Far address (unary).} */ static DECLCALLBACK(int) dbgcOpAddrFar(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult) { LogFlow(("dbgcOpAddrFar\n")); int rc; switch (pArg1->enmType) { case DBGCVAR_TYPE_SYMBOL: rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_NUMBER, pResult); if (RT_FAILURE(rc)) return rc; break; case DBGCVAR_TYPE_NUMBER: *pResult = *pArg1; break; default: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; } pResult->u.GCFar.sel = (RTSEL)pResult->u.u64Number; /* common code for the two types we support. */ switch (pArg2->enmType) { case DBGCVAR_TYPE_GC_FLAT: pResult->u.GCFar.off = pArg2->u.GCFlat; pResult->enmType = DBGCVAR_TYPE_GC_FAR; break; case DBGCVAR_TYPE_HC_FLAT: pResult->u.pvHCFlat = (void *)(uintptr_t)pArg2->u.GCFlat; pResult->enmType = DBGCVAR_TYPE_GC_FAR; break; case DBGCVAR_TYPE_NUMBER: pResult->u.GCFar.off = (RTGCPTR)pArg2->u.u64Number; pResult->enmType = DBGCVAR_TYPE_GC_FAR; break; case DBGCVAR_TYPE_SYMBOL: { DBGCVAR Var; rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var); if (RT_FAILURE(rc)) return rc; pResult->u.GCFar.off = (RTGCPTR)Var.u.u64Number; pResult->enmType = DBGCVAR_TYPE_GC_FAR; break; } default: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; } return VINF_SUCCESS; }
/** * Range to operator (binary). * * @returns VINF_SUCCESS on success. * @returns VBox evaluation / parsing error code on failure. * The caller does the bitching. * @param pDbgc Debugger console instance data. * @param pArg1 The first argument. * @param pArg2 The 2nd argument. * @param pResult Where to store the result. */ static DECLCALLBACK(int) dbgcOpRangeLength(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult) { LogFlow(("dbgcOpRangeLength\n")); if (pArg1->enmType == DBGCVAR_TYPE_STRING) return VERR_DBGC_PARSE_INVALID_OPERATION; /* * Make result. Symbols needs to be resolved. */ if (pArg1->enmType == DBGCVAR_TYPE_SYMBOL) { int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, pResult); if (RT_FAILURE(rc)) return rc; } else *pResult = *pArg1; /* * Convert 2nd argument to element count. */ pResult->enmRangeType = DBGCVAR_RANGE_ELEMENTS; switch (pArg2->enmType) { case DBGCVAR_TYPE_NUMBER: pResult->u64Range = pArg2->u.u64Number; break; case DBGCVAR_TYPE_SYMBOL: { int rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, pResult); if (RT_FAILURE(rc)) return rc; pResult->u64Range = pArg2->u.u64Number; break; } case DBGCVAR_TYPE_STRING: default: return VERR_DBGC_PARSE_INVALID_OPERATION; } return VINF_SUCCESS; }
/** * Converts an argument to a number value. * * @returns VBox status code. * @param pDbgc The DBGC instance. * @param pArg The argument to convert. * @param pu64Ret Where to return the value. */ static int dbgcOpHelperGetNumber(PDBGC pDbgc, PCDBGCVAR pArg, uint64_t *pu64Ret) { DBGCVAR Var = *pArg; switch (Var.enmType) { case DBGCVAR_TYPE_GC_FLAT: *pu64Ret = Var.u.GCFlat; break; case DBGCVAR_TYPE_GC_FAR: *pu64Ret = Var.u.GCFar.off; break; case DBGCVAR_TYPE_GC_PHYS: *pu64Ret = Var.u.GCPhys; break; case DBGCVAR_TYPE_HC_FLAT: *pu64Ret = (uintptr_t)Var.u.pvHCFlat; break; case DBGCVAR_TYPE_HC_PHYS: *pu64Ret = Var.u.HCPhys; break; case DBGCVAR_TYPE_NUMBER: *pu64Ret = Var.u.u64Number; break; case DBGCVAR_TYPE_SYMBOL: { int rc = dbgcSymbolGet(pDbgc, Var.u.pszString, DBGCVAR_TYPE_NUMBER, &Var); if (RT_FAILURE(rc)) return rc; /* fall thru */ } case DBGCVAR_TYPE_STRING: default: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; } return VINF_SUCCESS; }
/** * @interface_method_impl{DBGCCMDHLP,pfnVarConvert} */ static DECLCALLBACK(int) dbgcHlpVarConvert(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pInVar, DBGCVARTYPE enmToType, bool fConvSyms, PDBGCVAR pResult) { PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp); DBGCVAR const InVar = *pInVar; /* if pInVar == pResult */ PCDBGCVAR pArg = &InVar; /* lazy bird, clean up later */ DBGFADDRESS Address; int rc; Assert(pDbgc->pUVM); *pResult = InVar; switch (InVar.enmType) { case DBGCVAR_TYPE_GC_FLAT: switch (enmToType) { case DBGCVAR_TYPE_GC_FLAT: return VINF_SUCCESS; case DBGCVAR_TYPE_GC_FAR: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_PHYS: pResult->enmType = DBGCVAR_TYPE_GC_PHYS; rc = DBGFR3AddrToPhys(pDbgc->pUVM, pDbgc->idCpu, DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, pArg->u.GCFlat), &pResult->u.GCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_HC_FLAT: pResult->enmType = DBGCVAR_TYPE_HC_FLAT; rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pUVM, pDbgc->idCpu, DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, pArg->u.GCFlat), false /*fReadOnly */, &pResult->u.pvHCFlat); if (RT_SUCCESS(rc)) return VINF_SUCCESS; return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_HC_PHYS: pResult->enmType = DBGCVAR_TYPE_HC_PHYS; rc = DBGFR3AddrToHostPhys(pDbgc->pUVM, pDbgc->idCpu, DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, pArg->u.GCFlat), &pResult->u.GCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_NUMBER: pResult->enmType = enmToType; pResult->u.u64Number = InVar.u.GCFlat; return VINF_SUCCESS; case DBGCVAR_TYPE_STRING: case DBGCVAR_TYPE_SYMBOL: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } break; case DBGCVAR_TYPE_GC_FAR: switch (enmToType) { case DBGCVAR_TYPE_GC_FLAT: rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off); if (RT_SUCCESS(rc)) { pResult->enmType = DBGCVAR_TYPE_GC_FLAT; pResult->u.GCFlat = Address.FlatPtr; return VINF_SUCCESS; } return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_GC_FAR: return VINF_SUCCESS; case DBGCVAR_TYPE_GC_PHYS: rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off); if (RT_SUCCESS(rc)) { pResult->enmType = DBGCVAR_TYPE_GC_PHYS; rc = DBGFR3AddrToPhys(pDbgc->pUVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; } return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_HC_FLAT: rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off); if (RT_SUCCESS(rc)) { pResult->enmType = DBGCVAR_TYPE_HC_FLAT; rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pUVM, pDbgc->idCpu, &Address, false /*fReadOnly*/, &pResult->u.pvHCFlat); if (RT_SUCCESS(rc)) return VINF_SUCCESS; } return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_HC_PHYS: rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off); if (RT_SUCCESS(rc)) { pResult->enmType = DBGCVAR_TYPE_HC_PHYS; rc = DBGFR3AddrToHostPhys(pDbgc->pUVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; } return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_NUMBER: pResult->enmType = enmToType; pResult->u.u64Number = InVar.u.GCFar.off; return VINF_SUCCESS; case DBGCVAR_TYPE_STRING: case DBGCVAR_TYPE_SYMBOL: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } break; case DBGCVAR_TYPE_GC_PHYS: switch (enmToType) { case DBGCVAR_TYPE_GC_FLAT: //rc = MMR3PhysGCPhys2GCVirtEx(pDbgc->pVM, pResult->u.GCPhys, ..., &pResult->u.GCFlat); - yea, sure. return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_FAR: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_PHYS: return VINF_SUCCESS; case DBGCVAR_TYPE_HC_FLAT: pResult->enmType = DBGCVAR_TYPE_HC_FLAT; rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pUVM, pDbgc->idCpu, DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, pArg->u.GCPhys), false /*fReadOnly */, &pResult->u.pvHCFlat); if (RT_SUCCESS(rc)) return VINF_SUCCESS; return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_HC_PHYS: pResult->enmType = DBGCVAR_TYPE_HC_PHYS; rc = DBGFR3AddrToHostPhys(pDbgc->pUVM, pDbgc->idCpu, DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, pArg->u.GCPhys), &pResult->u.HCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_NUMBER: pResult->enmType = enmToType; pResult->u.u64Number = InVar.u.GCPhys; return VINF_SUCCESS; case DBGCVAR_TYPE_STRING: case DBGCVAR_TYPE_SYMBOL: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } break; case DBGCVAR_TYPE_HC_FLAT: switch (enmToType) { case DBGCVAR_TYPE_GC_FLAT: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_FAR: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_PHYS: pResult->enmType = DBGCVAR_TYPE_GC_PHYS; rc = PGMR3DbgR3Ptr2GCPhys(pDbgc->pUVM, pArg->u.pvHCFlat, &pResult->u.GCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; /** @todo more memory types! */ return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_HC_FLAT: return VINF_SUCCESS; case DBGCVAR_TYPE_HC_PHYS: pResult->enmType = DBGCVAR_TYPE_HC_PHYS; rc = PGMR3DbgR3Ptr2HCPhys(pDbgc->pUVM, pArg->u.pvHCFlat, &pResult->u.HCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; /** @todo more memory types! */ return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_NUMBER: pResult->enmType = enmToType; pResult->u.u64Number = (uintptr_t)InVar.u.pvHCFlat; return VINF_SUCCESS; case DBGCVAR_TYPE_STRING: case DBGCVAR_TYPE_SYMBOL: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } break; case DBGCVAR_TYPE_HC_PHYS: switch (enmToType) { case DBGCVAR_TYPE_GC_FLAT: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_FAR: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_PHYS: pResult->enmType = DBGCVAR_TYPE_GC_PHYS; rc = PGMR3DbgHCPhys2GCPhys(pDbgc->pUVM, pArg->u.HCPhys, &pResult->u.GCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_HC_FLAT: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_HC_PHYS: return VINF_SUCCESS; case DBGCVAR_TYPE_NUMBER: pResult->enmType = enmToType; pResult->u.u64Number = InVar.u.HCPhys; return VINF_SUCCESS; case DBGCVAR_TYPE_STRING: case DBGCVAR_TYPE_SYMBOL: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } break; case DBGCVAR_TYPE_NUMBER: switch (enmToType) { case DBGCVAR_TYPE_GC_FLAT: pResult->enmType = DBGCVAR_TYPE_GC_FLAT; pResult->u.GCFlat = (RTGCPTR)InVar.u.u64Number; return VINF_SUCCESS; case DBGCVAR_TYPE_GC_FAR: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_PHYS: pResult->enmType = DBGCVAR_TYPE_GC_PHYS; pResult->u.GCPhys = (RTGCPHYS)InVar.u.u64Number; return VINF_SUCCESS; case DBGCVAR_TYPE_HC_FLAT: pResult->enmType = DBGCVAR_TYPE_HC_FLAT; pResult->u.pvHCFlat = (void *)(uintptr_t)InVar.u.u64Number; return VINF_SUCCESS; case DBGCVAR_TYPE_HC_PHYS: pResult->enmType = DBGCVAR_TYPE_HC_PHYS; pResult->u.HCPhys = (RTHCPHYS)InVar.u.u64Number; return VINF_SUCCESS; case DBGCVAR_TYPE_NUMBER: return VINF_SUCCESS; case DBGCVAR_TYPE_STRING: case DBGCVAR_TYPE_SYMBOL: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } break; case DBGCVAR_TYPE_SYMBOL: case DBGCVAR_TYPE_STRING: switch (enmToType) { case DBGCVAR_TYPE_GC_FLAT: case DBGCVAR_TYPE_GC_FAR: case DBGCVAR_TYPE_GC_PHYS: case DBGCVAR_TYPE_HC_FLAT: case DBGCVAR_TYPE_HC_PHYS: case DBGCVAR_TYPE_NUMBER: if (fConvSyms) { rc = dbgcSymbolGet(pDbgc, InVar.u.pszString, enmToType, pResult); if (RT_SUCCESS(rc)) return VINF_SUCCESS; } return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_STRING: case DBGCVAR_TYPE_SYMBOL: pResult->enmType = enmToType; return VINF_SUCCESS; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } break; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } AssertMsgFailed(("f=%d t=%d\n", InVar.enmType, enmToType)); return VERR_INVALID_PARAMETER; }
/** * Subtraction operator (binary). * * @returns VINF_SUCCESS on success. * @returns VBox evaluation / parsing error code on failure. * The caller does the bitching. * @param pDbgc Debugger console instance data. * @param pArg1 The first argument. * @param pArg2 The 2nd argument. * @param pResult Where to store the result. */ static DECLCALLBACK(int) dbgcOpSub(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult) { LogFlow(("dbgcOpSub\n")); /* * An subtraction operation will return the left side type in the expression. * However, if the left hand side is a number and the right hand a pointer of * some kind we'll convert the left hand side to the same type as the right hand. * Any symbols will be resolved, strings will be rejected. */ DBGCVAR Sym1, Sym2; if ( pArg2->enmType == DBGCVAR_TYPE_SYMBOL && ( pArg1->enmType == DBGCVAR_TYPE_NUMBER || pArg1->enmType == DBGCVAR_TYPE_SYMBOL)) { int rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_ANY, &Sym2); if (RT_FAILURE(rc)) return rc; pArg2 = &Sym2; } if ( pArg1->enmType == DBGCVAR_TYPE_STRING || pArg2->enmType == DBGCVAR_TYPE_STRING) return VERR_DBGC_PARSE_INVALID_OPERATION; if (pArg1->enmType == DBGCVAR_TYPE_SYMBOL) { DBGCVARTYPE enmType; switch (pArg2->enmType) { case DBGCVAR_TYPE_NUMBER: enmType = DBGCVAR_TYPE_ANY; break; case DBGCVAR_TYPE_GC_FLAT: case DBGCVAR_TYPE_GC_PHYS: case DBGCVAR_TYPE_HC_FLAT: case DBGCVAR_TYPE_HC_PHYS: enmType = pArg2->enmType; break; case DBGCVAR_TYPE_GC_FAR: enmType = DBGCVAR_TYPE_GC_FLAT; break; default: AssertFailedReturn(VERR_DBGC_IPE); } if (enmType != DBGCVAR_TYPE_STRING) { int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, &Sym1); if (RT_FAILURE(rc)) return rc; pArg1 = &Sym1; } } else if (pArg1->enmType == DBGCVAR_TYPE_NUMBER) { PFNDBGCOPUNARY pOp = NULL; switch (pArg2->enmType) { case DBGCVAR_TYPE_GC_FAR: case DBGCVAR_TYPE_GC_FLAT: pOp = dbgcOpAddrFlat; break; case DBGCVAR_TYPE_GC_PHYS: pOp = dbgcOpAddrPhys; break; case DBGCVAR_TYPE_HC_FLAT: pOp = dbgcOpAddrHost; break; case DBGCVAR_TYPE_HC_PHYS: pOp = dbgcOpAddrHostPhys; break; case DBGCVAR_TYPE_NUMBER: break; default: AssertFailedReturn(VERR_DBGC_IPE); } if (pOp) { int rc = pOp(pDbgc, pArg1, DBGCVAR_CAT_ANY, &Sym1); if (RT_FAILURE(rc)) return rc; pArg1 = &Sym1; } } /* * Normal processing. */ int rc; DBGCVAR Var; DBGCVAR Var2; switch (pArg1->enmType) { /* * GC Flat */ case DBGCVAR_TYPE_GC_FLAT: switch (pArg2->enmType) { case DBGCVAR_TYPE_HC_FLAT: case DBGCVAR_TYPE_HC_PHYS: return VERR_DBGC_PARSE_INVALID_OPERATION; default: *pResult = *pArg1; rc = dbgcOpAddrFlat(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var); if (RT_FAILURE(rc)) return rc; pResult->u.GCFlat -= pArg2->u.GCFlat; break; } break; /* * GC Far */ case DBGCVAR_TYPE_GC_FAR: switch (pArg2->enmType) { case DBGCVAR_TYPE_HC_FLAT: case DBGCVAR_TYPE_HC_PHYS: return VERR_DBGC_PARSE_INVALID_OPERATION; case DBGCVAR_TYPE_NUMBER: *pResult = *pArg1; pResult->u.GCFar.off -= (RTGCPTR)pArg2->u.u64Number; break; default: rc = dbgcOpAddrFlat(pDbgc, pArg1, DBGCVAR_CAT_ANY, pResult); if (RT_FAILURE(rc)) return rc; rc = dbgcOpAddrFlat(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var); if (RT_FAILURE(rc)) return rc; pResult->u.GCFlat -= pArg2->u.GCFlat; break; } break; /* * GC Phys */ case DBGCVAR_TYPE_GC_PHYS: switch (pArg2->enmType) { case DBGCVAR_TYPE_HC_FLAT: case DBGCVAR_TYPE_HC_PHYS: return VERR_DBGC_PARSE_INVALID_OPERATION; default: *pResult = *pArg1; rc = dbgcOpAddrPhys(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var); if (RT_FAILURE(rc)) return rc; if (Var.enmType != DBGCVAR_TYPE_GC_PHYS) return VERR_DBGC_PARSE_INVALID_OPERATION; pResult->u.GCPhys -= Var.u.GCPhys; break; } break; /* * HC Flat */ case DBGCVAR_TYPE_HC_FLAT: *pResult = *pArg1; rc = dbgcOpAddrHost(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var2); if (RT_FAILURE(rc)) return rc; rc = dbgcOpAddrFlat(pDbgc, &Var2, DBGCVAR_CAT_ANY, &Var); if (RT_FAILURE(rc)) return rc; pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat - (uintptr_t)Var.u.pvHCFlat; break; /* * HC Phys */ case DBGCVAR_TYPE_HC_PHYS: *pResult = *pArg1; rc = dbgcOpAddrHostPhys(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var); if (RT_FAILURE(rc)) return rc; pResult->u.HCPhys -= Var.u.HCPhys; break; /* * Numbers (see start of function) */ case DBGCVAR_TYPE_NUMBER: *pResult = *pArg1; switch (pArg2->enmType) { case DBGCVAR_TYPE_SYMBOL: rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var); if (RT_FAILURE(rc)) return rc; case DBGCVAR_TYPE_NUMBER: pResult->u.u64Number -= pArg2->u.u64Number; break; default: return VERR_DBGC_PARSE_INVALID_OPERATION; } break; default: return VERR_DBGC_PARSE_INVALID_OPERATION; } return VINF_SUCCESS; }
/** * Addition operator (binary). * * @returns VINF_SUCCESS on success. * @returns VBox evaluation / parsing error code on failure. * The caller does the bitching. * @param pDbgc Debugger console instance data. * @param pArg1 The first argument. * @param pArg2 The 2nd argument. * @param pResult Where to store the result. */ static DECLCALLBACK(int) dbgcOpAdd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult) { LogFlow(("dbgcOpAdd\n")); /* * An addition operation will return (when possible) the left side type in the * expression. We make an omission for numbers, where we'll take the right side * type instead. An expression where only the left hand side is a symbol we'll * use the right hand type to try resolve it. */ if ( pArg1->enmType == DBGCVAR_TYPE_STRING || pArg2->enmType == DBGCVAR_TYPE_STRING) return VERR_DBGC_PARSE_INVALID_OPERATION; /** @todo string contactenation later. */ if ( (pArg1->enmType == DBGCVAR_TYPE_NUMBER && pArg2->enmType != DBGCVAR_TYPE_SYMBOL) || (pArg1->enmType == DBGCVAR_TYPE_SYMBOL && pArg2->enmType != DBGCVAR_TYPE_SYMBOL)) { PCDBGCVAR pTmp = pArg2; pArg2 = pArg1; pArg1 = pTmp; } DBGCVAR Sym1, Sym2; if (pArg1->enmType == DBGCVAR_TYPE_SYMBOL) { int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, &Sym1); if (RT_FAILURE(rc)) return rc; pArg1 = &Sym1; rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_ANY, &Sym2); if (RT_FAILURE(rc)) return rc; pArg2 = &Sym2; } int rc; DBGCVAR Var; DBGCVAR Var2; switch (pArg1->enmType) { /* * GC Flat */ case DBGCVAR_TYPE_GC_FLAT: switch (pArg2->enmType) { case DBGCVAR_TYPE_HC_FLAT: case DBGCVAR_TYPE_HC_PHYS: return VERR_DBGC_PARSE_INVALID_OPERATION; default: *pResult = *pArg1; rc = dbgcOpAddrFlat(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var); if (RT_FAILURE(rc)) return rc; pResult->u.GCFlat += pArg2->u.GCFlat; break; } break; /* * GC Far */ case DBGCVAR_TYPE_GC_FAR: switch (pArg2->enmType) { case DBGCVAR_TYPE_HC_FLAT: case DBGCVAR_TYPE_HC_PHYS: return VERR_DBGC_PARSE_INVALID_OPERATION; case DBGCVAR_TYPE_NUMBER: *pResult = *pArg1; pResult->u.GCFar.off += (RTGCPTR)pArg2->u.u64Number; break; default: rc = dbgcOpAddrFlat(pDbgc, pArg1, DBGCVAR_CAT_ANY, pResult); if (RT_FAILURE(rc)) return rc; rc = dbgcOpAddrFlat(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var); if (RT_FAILURE(rc)) return rc; pResult->u.GCFlat += pArg2->u.GCFlat; break; } break; /* * GC Phys */ case DBGCVAR_TYPE_GC_PHYS: switch (pArg2->enmType) { case DBGCVAR_TYPE_HC_FLAT: case DBGCVAR_TYPE_HC_PHYS: return VERR_DBGC_PARSE_INVALID_OPERATION; default: *pResult = *pArg1; rc = dbgcOpAddrPhys(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var); if (RT_FAILURE(rc)) return rc; if (Var.enmType != DBGCVAR_TYPE_GC_PHYS) return VERR_DBGC_PARSE_INVALID_OPERATION; pResult->u.GCPhys += Var.u.GCPhys; break; } break; /* * HC Flat */ case DBGCVAR_TYPE_HC_FLAT: *pResult = *pArg1; rc = dbgcOpAddrHost(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var2); if (RT_FAILURE(rc)) return rc; rc = dbgcOpAddrFlat(pDbgc, &Var2, DBGCVAR_CAT_ANY, &Var); if (RT_FAILURE(rc)) return rc; pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat + (uintptr_t)Var.u.pvHCFlat; break; /* * HC Phys */ case DBGCVAR_TYPE_HC_PHYS: *pResult = *pArg1; rc = dbgcOpAddrHostPhys(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var); if (RT_FAILURE(rc)) return rc; pResult->u.HCPhys += Var.u.HCPhys; break; /* * Numbers (see start of function) */ case DBGCVAR_TYPE_NUMBER: *pResult = *pArg1; switch (pArg2->enmType) { case DBGCVAR_TYPE_SYMBOL: rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var); if (RT_FAILURE(rc)) return rc; case DBGCVAR_TYPE_NUMBER: pResult->u.u64Number += pArg2->u.u64Number; break; default: return VERR_DBGC_PARSE_INVALID_OPERATION; } break; default: return VERR_DBGC_PARSE_INVALID_OPERATION; } return VINF_SUCCESS; }