/***************************************************************************** * gsGSChecksInitCookie * Grabs the cookie for detecting overflow of unsafe buffers. */ void Compiler::gsGSChecksInitCookie() { var_types type = TYP_I_IMPL; lvaGSSecurityCookie = lvaGrabTemp(false DEBUGARG("GSSecurityCookie")); // Prevent cookie init/check from being optimized lvaSetVarAddrExposed(lvaGSSecurityCookie); lvaTable[lvaGSSecurityCookie].lvType = type; info.compCompHnd->getGSCookie(&gsGlobalSecurityCookieVal, &gsGlobalSecurityCookieAddr); }
/***************************************************************************** * gsParamsToShadows * Copy each vulnerable param ptr or buffer to a local shadow copy and replace * uses of the param by the shadow copy */ void Compiler::gsParamsToShadows() { // Cache old count since we'll add new variables, and // gsShadowVarInfo will not grow to accomodate the new ones. UINT lvaOldCount = lvaCount; // Create shadow copy for each param candidate for (UINT lclNum = 0; lclNum < lvaOldCount; lclNum++) { LclVarDsc *varDsc = &lvaTable[lclNum]; gsShadowVarInfo[lclNum].shadowCopy = NO_SHADOW_COPY; // Only care about params whose values are on the stack if (!ShadowParamVarInfo::mayNeedShadowCopy(varDsc)) { continue; } if (!varDsc->lvIsPtr && !varDsc->lvIsUnsafeBuffer) { continue; } int shadowVar = lvaGrabTemp(false DEBUGARG("shadowVar")); // Copy some info var_types type = varTypeIsSmall(varDsc->TypeGet()) ? TYP_INT : varDsc->TypeGet(); lvaTable[shadowVar].lvType = type; lvaTable[shadowVar].lvAddrExposed = varDsc->lvAddrExposed; lvaTable[shadowVar].lvDoNotEnregister = varDsc->lvDoNotEnregister; #ifdef DEBUG lvaTable[shadowVar].lvVMNeedsStackAddr = varDsc->lvVMNeedsStackAddr; lvaTable[shadowVar].lvLiveInOutOfHndlr = varDsc->lvLiveInOutOfHndlr; lvaTable[shadowVar].lvLclFieldExpr = varDsc->lvLclFieldExpr; lvaTable[shadowVar].lvLiveAcrossUCall = varDsc->lvLiveAcrossUCall; #endif lvaTable[shadowVar].lvVerTypeInfo = varDsc->lvVerTypeInfo; lvaTable[shadowVar].lvGcLayout = varDsc->lvGcLayout; lvaTable[shadowVar].lvIsUnsafeBuffer = varDsc->lvIsUnsafeBuffer; lvaTable[shadowVar].lvIsPtr = varDsc->lvIsPtr; #ifdef DEBUG if (verbose) { printf("Var V%02u is shadow param candidate. Shadow copy is V%02u.\n", lclNum, shadowVar); } #endif gsShadowVarInfo[lclNum].shadowCopy = shadowVar; } // Replace param uses with shadow copy fgWalkAllTreesPre(gsReplaceShadowParams, (void *)this); // Now insert code to copy the params to their shadow copy. for (UINT lclNum = 0; lclNum < lvaOldCount; lclNum++) { LclVarDsc *varDsc = &lvaTable[lclNum]; unsigned shadowVar = gsShadowVarInfo[lclNum].shadowCopy; if (shadowVar == NO_SHADOW_COPY) { continue; } var_types type = lvaTable[shadowVar].TypeGet(); GenTreePtr src = gtNewLclvNode(lclNum, varDsc->TypeGet()); GenTreePtr dst = gtNewLclvNode(shadowVar, type); src->gtFlags |= GTF_DONT_CSE; dst->gtFlags |= GTF_DONT_CSE; GenTreePtr opAssign = NULL; if (type == TYP_STRUCT) { CORINFO_CLASS_HANDLE clsHnd = varDsc->lvVerTypeInfo.GetClassHandle(); // We don't need unsafe value cls check here since we are copying the params and this flag // would have been set on the original param before reaching here. lvaSetStruct(shadowVar, clsHnd, false); src = gtNewOperNode(GT_ADDR, TYP_BYREF, src); dst = gtNewOperNode(GT_ADDR, TYP_BYREF, dst); opAssign = gtNewCpObjNode(dst, src, clsHnd, false); #if FEATURE_MULTIREG_ARGS_OR_RET lvaTable[shadowVar].lvIsMultiRegArgOrRet = lvaTable[lclNum].lvIsMultiRegArgOrRet; #endif // FEATURE_MULTIREG_ARGS_OR_RET } else { opAssign = gtNewAssignNode(dst, src); } fgEnsureFirstBBisScratch(); (void) fgInsertStmtAtBeg(fgFirstBB, fgMorphTree(opAssign)); } // If the method has "Jmp CalleeMethod", then we need to copy shadow params back to original // params before "jmp" to CalleeMethod. if (compJmpOpUsed) { // There could be more than one basic block ending with a "Jmp" type tail call. // We would have to insert assignments in all such blocks, just before GT_JMP stmnt. for (BasicBlock * block = fgFirstBB; block; block = block->bbNext) { if (block->bbJumpKind != BBJ_RETURN) { continue; } if ((block->bbFlags & BBF_HAS_JMP) == 0) { continue; } for (UINT lclNum = 0; lclNum < info.compArgsCount; lclNum++) { LclVarDsc *varDsc = &lvaTable[lclNum]; unsigned shadowVar = gsShadowVarInfo[lclNum].shadowCopy; if (shadowVar == NO_SHADOW_COPY) { continue; } GenTreePtr src = gtNewLclvNode(shadowVar, lvaTable[shadowVar].TypeGet()); GenTreePtr dst = gtNewLclvNode(lclNum, varDsc->TypeGet()); src->gtFlags |= GTF_DONT_CSE; dst->gtFlags |= GTF_DONT_CSE; GenTreePtr opAssign = nullptr; if (varDsc->TypeGet() == TYP_STRUCT) { CORINFO_CLASS_HANDLE clsHnd = varDsc->lvVerTypeInfo.GetClassHandle(); src = gtNewOperNode(GT_ADDR, TYP_BYREF, src); dst = gtNewOperNode(GT_ADDR, TYP_BYREF, dst); opAssign = gtNewCpObjNode(dst, src, clsHnd, false); } else { opAssign = gtNewAssignNode(dst, src); } (void) fgInsertStmtNearEnd(block, fgMorphTree(opAssign)); } } } }