/** * Get first symbol. * @returns NULL if no symbol by that name. */ static PDBGFSYM dbgfR3SymbolGetName(PVM pVM, const char *pszSymbol) { PDBGFSYMSPACE pName = (PDBGFSYMSPACE)RTStrSpaceGet(pVM->dbgf.s.pSymbolSpace, pszSymbol); if (pName) return pName->pSym; return NULL; }
/** * Query an address space by name. * * @returns Retained address space handle if found, NIL_RTDBGAS if not. * * @param pUVM The user mode VM handle. * @param pszName The name. */ VMMR3DECL(RTDBGAS) DBGFR3AsQueryByName(PUVM pUVM, const char *pszName) { /* * Validate the input. */ UVM_ASSERT_VALID_EXT_RETURN(pUVM, NIL_RTDBGAS); AssertPtrReturn(pszName, NIL_RTDBGAS); AssertReturn(*pszName, NIL_RTDBGAS); /* * Look it up in the string space and retain the result. */ RTDBGAS hDbgAs = NIL_RTDBGAS; DBGF_AS_DB_LOCK_READ(pUVM); PRTSTRSPACECORE pNode = RTStrSpaceGet(&pUVM->dbgf.s.AsNameSpace, pszName); if (pNode) { PDBGFASDBNODE pDbNode = RT_FROM_MEMBER(pNode, DBGFASDBNODE, NameCore); hDbgAs = (RTDBGAS)pDbNode->HandleCore.Key; uint32_t cRefs = RTDbgAsRetain(hDbgAs); if (RT_UNLIKELY(cRefs == UINT32_MAX)) hDbgAs = NIL_RTDBGAS; } DBGF_AS_DB_UNLOCK_READ(pUVM); return hDbgAs; }
/** * @callback_method_impl{FNRTSTRSPACECALLBACK, Prepare equals operation.} */ static DECLCALLBACK(int) rtManifestEntryCompare(PRTSTRSPACECORE pStr, void *pvUser) { PRTMANIFESTEQUALS pEquals = (PRTMANIFESTEQUALS)pvUser; PRTMANIFESTENTRY pEntry1 = RT_FROM_MEMBER(pStr, RTMANIFESTENTRY, StrCore); PRTMANIFESTENTRY pEntry2; /* * Ignore this entry. */ char const * const *ppsz = pEquals->papszIgnoreEntries; if (ppsz) { while (*ppsz) { if (!strcmp(*ppsz, pStr->pszString)) { pEntry2 = (PRTMANIFESTENTRY)RTStrSpaceGet(&pEquals->pThis2->Entries, pStr->pszString); if (pEntry2) { pEntry2->fVisited = true; pEquals->cIgnoredEntries2++; } pEntry1->fVisited = true; return 0; } ppsz++; } } /* * Try find the entry in the other manifest. */ pEntry2 = (PRTMANIFESTENTRY)RTStrSpaceGet(&pEquals->pThis2->Entries, pEntry1->StrCore.pszString); if (!pEntry2) { RTStrPrintf(pEquals->pszError, pEquals->cbError, "'%s' not found in the 2nd manifest", pEntry1->StrCore.pszString); return VERR_NOT_EQUAL; } Assert(!pEntry1->fVisited); Assert(!pEntry2->fVisited); pEntry1->fVisited = true; pEntry2->fVisited = true; pEquals->cEntries2++; return rtManifestEntryCompare2(pEquals, pEntry1, pEntry2); }
DECLHIDDEN(int) vdScriptCtxInterprete(PVDSCRIPTCTXINT pThis, const char *pszFn, PVDSCRIPTARG paArgs, unsigned cArgs, PVDSCRIPTARG pRet) { int rc = VINF_SUCCESS; VDSCRIPTINTERPCTX InterpCtx; PVDSCRIPTFN pFn = NULL; AssertPtrReturn(pThis, VERR_INVALID_POINTER); AssertPtrReturn(pszFn, VERR_INVALID_POINTER); AssertReturn( (!cArgs && !paArgs) || (cArgs && paArgs), VERR_INVALID_PARAMETER); InterpCtx.pScriptCtx = pThis; InterpCtx.pFnCallCurr = NULL; vdScriptStackInit(&InterpCtx.StackValues, sizeof(VDSCRIPTARG)); vdScriptStackInit(&InterpCtx.StackCtrl, sizeof(VDSCRIPTINTERPCTRL)); pFn = (PVDSCRIPTFN)RTStrSpaceGet(&pThis->hStrSpaceFn, pszFn); if (pFn) { if (cArgs == pFn->cArgs) { /* Push the arguments onto the stack. */ /** @todo: Check expected and given argument types. */ for (unsigned i = 0; i < cArgs; i++) { PVDSCRIPTARG pArg = (PVDSCRIPTARG)vdScriptStackGetUnused(&InterpCtx.StackValues); *pArg = paArgs[i]; vdScriptStackPush(&InterpCtx.StackValues); } if (RT_SUCCESS(rc)) { /* Setup function call frame and parameters. */ rc = vdScriptInterpreterFnCall(&InterpCtx, pFn); if (RT_SUCCESS(rc)) { /* Run the interpreter. */ rc = vdScriptInterpreterEvaluate(&InterpCtx); vdScriptStackDestroy(&InterpCtx.StackValues); vdScriptStackDestroy(&InterpCtx.StackCtrl); } } } else rc = vdScriptInterpreterError(&InterpCtx, VERR_INVALID_PARAMETER, RT_SRC_POS, "Invalid number of parameters, expected %d got %d", pFn->cArgs, cArgs); } else rc = vdScriptInterpreterError(&InterpCtx, VERR_NOT_FOUND, RT_SRC_POS, "Function with identifier \"%s\" not found", pszFn); return rc; }
/** * Gets an entry. * * @returns IPRT status code. * @param pThis The manifest to work with. * @param pszEntry The entry name. * @param fNeedNormalization Whether rtManifestValidateNameEntry said it * needed normalization. * @param cchEntry The length of the name. * @param ppEntry Where to return the entry pointer on success. */ static int rtManifestGetEntry(RTMANIFESTINT *pThis, const char *pszEntry, bool fNeedNormalization, size_t cchEntry, PRTMANIFESTENTRY *ppEntry) { PRTMANIFESTENTRY pEntry; AssertCompileMemberOffset(RTMANIFESTATTR, StrCore, 0); if (!fNeedNormalization) pEntry = (PRTMANIFESTENTRY)RTStrSpaceGet(&pThis->Entries, pszEntry); else { char *pszCopy = (char *)RTMemTmpAlloc(cchEntry + 1); if (RT_UNLIKELY(!pszCopy)) return VERR_NO_TMP_MEMORY; memcpy(pszCopy, pszEntry, cchEntry + 1); rtManifestNormalizeEntry(pszCopy); pEntry = (PRTMANIFESTENTRY)RTStrSpaceGet(&pThis->Entries, pszCopy); RTMemTmpFree(pszCopy); } *ppEntry = pEntry; return pEntry ? VINF_SUCCESS : VERR_NOT_FOUND; }
/** @copydoc RTDBGMODVTDBG::pfnSymbolByName */ static DECLCALLBACK(int) rtDbgModContainer_SymbolByName(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol, PRTDBGSYMBOL pSymInfo) { PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv; NOREF(cchSymbol); /* * Look it up in the name space. */ PRTSTRSPACECORE pStrCore = RTStrSpaceGet(&pThis->Names, pszSymbol); if (!pStrCore) return VERR_SYMBOL_NOT_FOUND; PCRTDBGMODCTNSYMBOL pMySym = RT_FROM_MEMBER(pStrCore, RTDBGMODCTNSYMBOL const, NameCore); return rtDbgModContainerReturnSymbol(pMySym, pSymInfo); }
/** * Get the content of the given variable identifier from the current or parent scope. */ static PVDSCRIPTINTERPVAR vdScriptInterpreterGetVar(PVDSCRIPTINTERPCTX pThis, const char *pszVar) { PVDSCRIPTINTERPSCOPE pScopeCurr = pThis->pFnCallCurr->pScopeCurr; PVDSCRIPTINTERPVAR pVar = NULL; while ( !pVar && pScopeCurr) { pVar = (PVDSCRIPTINTERPVAR)RTStrSpaceGet(&pScopeCurr->hStrSpaceVar, pszVar); if (pVar) break; pScopeCurr = pScopeCurr->pParent; } return pVar; }
/** * Worker common to RTManifestQueryAttr and RTManifestEntryQueryAttr. * * @returns IPRT status code. * @param pEntry The entry. * @param pszAttr The attribute name. If NULL, it will be * selected by @a fType alone. * @param fType The attribute types the entry should match. Pass * Pass RTMANIFEST_ATTR_ANY match any. If more * than one is given, the first matching one is * returned. * @param pszValue Where to return value. * @param cbValue The size of the buffer @a pszValue points to. * @param pfType Where to return the attribute type value. */ static int rtManifestQueryAttrWorker(PRTMANIFESTENTRY pEntry, const char *pszAttr, uint32_t fType, char *pszValue, size_t cbValue, uint32_t *pfType) { /* * Find the requested attribute. */ PRTMANIFESTATTR pAttr; if (pszAttr) { /* By name. */ pAttr = (PRTMANIFESTATTR)RTStrSpaceGet(&pEntry->Attributes, pszAttr); if (!pAttr) return VERR_MANIFEST_ATTR_NOT_FOUND; if (!(pAttr->fType & fType)) return VERR_MANIFEST_ATTR_TYPE_MISMATCH; } else { /* By type. */ RTMANIFESTQUERYATTRARGS Args; Args.fType = fType; Args.pAttr = NULL; int rc = RTStrSpaceEnumerate(&pEntry->Attributes, rtMainfestQueryAttrEnumCallback, &Args); AssertRCReturn(rc, rc); pAttr = Args.pAttr; if (!pAttr) return VERR_MANIFEST_ATTR_TYPE_NOT_FOUND; } /* * Set the return values. */ if (cbValue || pszValue) { size_t cbNeeded = strlen(pAttr->pszValue) + 1; if (cbNeeded > cbValue) return VERR_BUFFER_OVERFLOW; memcpy(pszValue, pAttr->pszValue, cbNeeded); } if (pfType) *pfType = pAttr->fType; return VINF_SUCCESS; }
/** * Worker common to RTManifestSetAttr and RTManifestEntrySetAttr. * * @returns IPRT status code. * @param pEntry Pointer to the entry. * @param pszAttr The name of the attribute to add. * @param pszValue The value string. * @param fType The attribute type type. */ static int rtManifestSetAttrWorker(PRTMANIFESTENTRY pEntry, const char *pszAttr, const char *pszValue, uint32_t fType) { char *pszValueCopy; int rc = RTStrDupEx(&pszValueCopy, pszValue); if (RT_FAILURE(rc)) return rc; /* * Does the attribute exist already? */ AssertCompileMemberOffset(RTMANIFESTATTR, StrCore, 0); PRTMANIFESTATTR pAttr = (PRTMANIFESTATTR)RTStrSpaceGet(&pEntry->Attributes, pszAttr); if (pAttr) { RTStrFree(pAttr->pszValue); pAttr->pszValue = pszValueCopy; pAttr->fType = fType; } else { size_t cbName = strlen(pszAttr) + 1; pAttr = (PRTMANIFESTATTR)RTMemAllocVar(RT_OFFSETOF(RTMANIFESTATTR, szName[cbName])); if (!pAttr) { RTStrFree(pszValueCopy); return VERR_NO_MEMORY; } memcpy(pAttr->szName, pszAttr, cbName); pAttr->StrCore.pszString = pAttr->szName; pAttr->StrCore.cchString = cbName - 1; pAttr->pszValue = pszValueCopy; pAttr->fType = fType; if (RT_UNLIKELY(!RTStrSpaceInsert(&pEntry->Attributes, &pAttr->StrCore))) { AssertFailed(); RTStrFree(pszValueCopy); RTMemFree(pAttr); return VERR_INTERNAL_ERROR_4; } pEntry->cAttributes++; } return VINF_SUCCESS; }
/** * @callback_method_impl{FNRTSTRSPACECALLBACK, Compares attributes.} */ static DECLCALLBACK(int) rtManifestAttributeCompare(PRTSTRSPACECORE pStr, void *pvUser) { PRTMANIFESTEQUALS pEquals = (PRTMANIFESTEQUALS)pvUser; PRTMANIFESTATTR pAttr1 = RT_FROM_MEMBER(pStr, RTMANIFESTATTR, StrCore); PRTMANIFESTATTR pAttr2; Assert(!pAttr1->fVisited); pAttr1->fVisited = true; /* * Ignore this entry? */ char const * const *ppsz = pEquals->papszIgnoreAttr; if (ppsz) { while (*ppsz) { if (!strcmp(*ppsz, pAttr1->szName)) { pAttr2 = (PRTMANIFESTATTR)RTStrSpaceGet(pEquals->pAttributes2, pAttr1->szName); if (pAttr2) { Assert(!pAttr2->fVisited); pAttr2->fVisited = true; pEquals->cIgnoredAttributes2++; } pEquals->cIgnoredAttributes1++; return 0; } ppsz++; } } /* * Find the matching attribute. */ pAttr2 = (PRTMANIFESTATTR)RTStrSpaceGet(pEquals->pAttributes2, pAttr1->szName); if (!pAttr2) { if (pEquals->fFlags & RTMANIFEST_EQUALS_IGN_MISSING_ATTRS) return 0; if (*pEquals->pszCurEntry) RTStrPrintf(pEquals->pszError, pEquals->cbError, "Attribute '%s' on '%s' was not found in the 2nd manifest", pAttr1->szName, pEquals->pszCurEntry); else RTStrPrintf(pEquals->pszError, pEquals->cbError, "Attribute '%s' was not found in the 2nd manifest", pAttr1->szName); return VERR_NOT_EQUAL; } Assert(!pAttr2->fVisited); pAttr2->fVisited = true; pEquals->cAttributes2++; /* * Compare them. */ if (strcmp(pAttr1->pszValue, pAttr2->pszValue)) { if (*pEquals->pszCurEntry) RTStrPrintf(pEquals->pszError, pEquals->cbError, "Attribute '%s' on '%s' does not match ('%s' vs. '%s')", pAttr1->szName, pEquals->pszCurEntry, pAttr1->pszValue, pAttr2->pszValue); else RTStrPrintf(pEquals->pszError, pEquals->cbError, "Attribute '%s' does not match ('%s' vs. '%s')", pAttr1->szName, pAttr1->pszValue, pAttr2->pszValue); return VERR_NOT_EQUAL; } return 0; }
/** * Gets a property. * * @returns Pointer to the property if found, NULL if not. * * @param pszName The name of the property to get. */ Property *getPropertyInternal(const char *pszName) { return (Property *)RTStrSpaceGet(&mhProperties, pszName); }
/** * Evaluate an expression. * * @returns VBox status code. * @param pThis The interpreter context. * @param pExpr The expression to evaluate. */ static int vdScriptInterpreterEvaluateExpression(PVDSCRIPTINTERPCTX pThis, PVDSCRIPTASTEXPR pExpr) { int rc = VINF_SUCCESS; switch (pExpr->enmType) { case VDSCRIPTEXPRTYPE_PRIMARY_NUMCONST: { /* Push the numerical constant on the value stack. */ VDSCRIPTARG NumConst; NumConst.enmType = VDSCRIPTTYPE_UINT64; NumConst.u64 = pExpr->u64; rc = vdScriptInterpreterPushValue(pThis, &NumConst); break; } case VDSCRIPTEXPRTYPE_PRIMARY_STRINGCONST: { /* Push the string literal on the value stack. */ VDSCRIPTARG StringConst; StringConst.enmType = VDSCRIPTTYPE_STRING; StringConst.psz = pExpr->pszStr; rc = vdScriptInterpreterPushValue(pThis, &StringConst); break; } case VDSCRIPTEXPRTYPE_PRIMARY_BOOLEAN: { VDSCRIPTARG BoolConst; BoolConst.enmType = VDSCRIPTTYPE_BOOL; BoolConst.f = pExpr->f; rc = vdScriptInterpreterPushValue(pThis, &BoolConst); break; } case VDSCRIPTEXPRTYPE_PRIMARY_IDENTIFIER: { /* Look it up and push the value onto the value stack. */ PVDSCRIPTINTERPVAR pVar = vdScriptInterpreterGetVar(pThis, pExpr->pIde->aszIde); AssertPtrReturn(pVar, VERR_IPE_UNINITIALIZED_STATUS); rc = vdScriptInterpreterPushValue(pThis, &pVar->Value); break; } case VDSCRIPTEXPRTYPE_POSTFIX_INCREMENT: case VDSCRIPTEXPRTYPE_POSTFIX_DECREMENT: AssertMsgFailed(("TODO\n")); case VDSCRIPTEXPRTYPE_POSTFIX_FNCALL: { PVDSCRIPTFN pFn = (PVDSCRIPTFN)RTStrSpaceGet(&pThis->pScriptCtx->hStrSpaceFn, pExpr->FnCall.pFnIde->pIde->aszIde); if (pFn) { /* Push a function call control entry on the stack. */ PVDSCRIPTINTERPCTRL pCtrlFn = (PVDSCRIPTINTERPCTRL)vdScriptStackGetUnused(&pThis->StackCtrl); if (pCtrlFn) { pCtrlFn->fEvalAst = false; pCtrlFn->Ctrl.enmCtrlType = VDSCRIPTINTERPCTRLTYPE_FN_CALL; pCtrlFn->Ctrl.FnCall.pFn = pFn; vdScriptStackPush(&pThis->StackCtrl); /* Push parameter expressions on the stack. */ PVDSCRIPTASTEXPR pArg = RTListGetFirst(&pExpr->FnCall.ListArgs, VDSCRIPTASTEXPR, Core.ListNode); while (pArg) { rc = vdScriptInterpreterPushAstEntry(pThis, &pArg->Core); if (RT_FAILURE(rc)) break; pArg = RTListGetNext(&pExpr->FnCall.ListArgs, pArg, VDSCRIPTASTEXPR, Core.ListNode); } } } else AssertMsgFailed(("Invalid program given, unknown function: %s\n", pExpr->FnCall.pFnIde->pIde->aszIde)); break; } case VDSCRIPTEXPRTYPE_UNARY_INCREMENT: case VDSCRIPTEXPRTYPE_UNARY_DECREMENT: case VDSCRIPTEXPRTYPE_UNARY_POSSIGN: case VDSCRIPTEXPRTYPE_UNARY_NEGSIGN: case VDSCRIPTEXPRTYPE_UNARY_INVERT: case VDSCRIPTEXPRTYPE_UNARY_NEGATE: case VDSCRIPTEXPRTYPE_MULTIPLICATION: case VDSCRIPTEXPRTYPE_DIVISION: case VDSCRIPTEXPRTYPE_MODULUS: case VDSCRIPTEXPRTYPE_ADDITION: case VDSCRIPTEXPRTYPE_SUBTRACTION: case VDSCRIPTEXPRTYPE_LSR: case VDSCRIPTEXPRTYPE_LSL: case VDSCRIPTEXPRTYPE_LOWER: case VDSCRIPTEXPRTYPE_HIGHER: case VDSCRIPTEXPRTYPE_LOWEREQUAL: case VDSCRIPTEXPRTYPE_HIGHEREQUAL: case VDSCRIPTEXPRTYPE_EQUAL: case VDSCRIPTEXPRTYPE_NOTEQUAL: case VDSCRIPTEXPRTYPE_BITWISE_AND: case VDSCRIPTEXPRTYPE_BITWISE_XOR: case VDSCRIPTEXPRTYPE_BITWISE_OR: case VDSCRIPTEXPRTYPE_LOGICAL_AND: case VDSCRIPTEXPRTYPE_LOGICAL_OR: case VDSCRIPTEXPRTYPE_ASSIGN: case VDSCRIPTEXPRTYPE_ASSIGN_MULT: case VDSCRIPTEXPRTYPE_ASSIGN_DIV: case VDSCRIPTEXPRTYPE_ASSIGN_MOD: case VDSCRIPTEXPRTYPE_ASSIGN_ADD: case VDSCRIPTEXPRTYPE_ASSIGN_SUB: case VDSCRIPTEXPRTYPE_ASSIGN_LSL: case VDSCRIPTEXPRTYPE_ASSIGN_LSR: case VDSCRIPTEXPRTYPE_ASSIGN_AND: case VDSCRIPTEXPRTYPE_ASSIGN_XOR: case VDSCRIPTEXPRTYPE_ASSIGN_OR: case VDSCRIPTEXPRTYPE_ASSIGNMENT_LIST: AssertMsgFailed(("TODO\n")); default: AssertMsgFailed(("Invalid expression type: %d\n", pExpr->enmType)); } return rc; }
/** * Insert a record into the symbol tree. */ static int dbgfR3SymbolInsert(PVM pVM, const char *pszName, RTGCPTR Address, size_t cb, PDBGFMOD pModule) { /* * Make the address space node. */ size_t cchName = strlen(pszName) + 1; PDBGFSYM pSym = (PDBGFSYM)MMR3HeapAlloc(pVM, MM_TAG_DBGF_SYMBOL, RT_OFFSETOF(DBGFSYM, szName[cchName])); if (pSym) { pSym->Core.Key = Address; pSym->Core.KeyLast = Address + cb; pSym->pModule = pModule; memcpy(pSym->szName, pszName, cchName); PDBGFSYM pOld = (PDBGFSYM)RTAvlrGCPtrRangeGet(&pVM->dbgf.s.SymbolTree, (RTGCPTR)Address); if (pOld) { pSym->Core.KeyLast = pOld->Core.KeyLast; if (pOld->Core.Key == pSym->Core.Key) { pOld = (PDBGFSYM)RTAvlrGCPtrRemove(&pVM->dbgf.s.SymbolTree, (RTGCPTR)Address); AssertRelease(pOld); MMR3HeapFree(pOld); } else pOld->Core.KeyLast = Address - 1; if (RTAvlrGCPtrInsert(&pVM->dbgf.s.SymbolTree, &pSym->Core)) { /* * Make the name space node. */ PDBGFSYMSPACE pName = (PDBGFSYMSPACE)RTStrSpaceGet(pVM->dbgf.s.pSymbolSpace, pszName); if (!pName) { /* make new symbol space node. */ pName = (PDBGFSYMSPACE)MMR3HeapAlloc(pVM, MM_TAG_DBGF_SYMBOL, sizeof(*pName) + cchName); if (pName) { pName->Core.pszString = (char *)memcpy(pName + 1, pszName, cchName); pName->pSym = pSym; if (RTStrSpaceInsert(pVM->dbgf.s.pSymbolSpace, &pName->Core)) return VINF_SUCCESS; } else return VINF_SUCCESS; } else { /* Add to existing symbol name. */ pSym->pNext = pName->pSym; pName->pSym = pSym; return VINF_SUCCESS; } } AssertReleaseMsgFailed(("Failed to insert %RGv-%RGv!\n", pSym->Core.Key, pSym->Core.KeyLast)); } else AssertMsgFailed(("pOld! %RGv %s\n", pSym->Core.Key, pszName)); return VERR_INTERNAL_ERROR; } return VERR_NO_MEMORY; }