private ObjectNode.ObjectData EncodeEHInfo() { var builder = new ObjectDataBuilder(); builder.RequireInitialAlignment(1); int totalClauses = _ehClauses.Length; // Count the number of special markers that will be needed for (int i = 1; i < _ehClauses.Length; i++) { ref CORINFO_EH_CLAUSE clause = ref _ehClauses[i]; ref CORINFO_EH_CLAUSE previousClause = ref _ehClauses[i - 1];
protected CORINFO_EH_CLAUSE[] GetAllExceptionHandlers(void *pICorJitInfo, CorMethodInfo methodInfo) { CORINFO_EH_CLAUSE[] clauses; if (methodInfo.ExceptionHandlerCount == 0) { return(null); } clauses = new CORINFO_EH_CLAUSE[methodInfo.ExceptionHandlerCount]; for (uint i = 0; i < clauses.Length; i++) { GetEHInfo(pICorJitInfo, methodInfo.MethodHandle, i, out clauses[i]); } return(clauses); }
private ObjectNode.ObjectData EncodeEHInfo() { int totalClauses = _ehClauses.Length; byte[] ehInfoData = new byte[(int)EHInfoFields.Length * sizeof(uint) * totalClauses]; for (int i = 0; i < totalClauses; i++) { ref CORINFO_EH_CLAUSE clause = ref _ehClauses[i]; int clauseOffset = (int)EHInfoFields.Length * sizeof(uint) * i; Array.Copy(BitConverter.GetBytes((uint)clause.Flags), 0, ehInfoData, clauseOffset + (int)EHInfoFields.Flags * sizeof(uint), sizeof(uint)); Array.Copy(BitConverter.GetBytes((uint)clause.TryOffset), 0, ehInfoData, clauseOffset + (int)EHInfoFields.TryOffset * sizeof(uint), sizeof(uint)); // JIT in fact returns the end offset in the length field Array.Copy(BitConverter.GetBytes((uint)(clause.TryLength)), 0, ehInfoData, clauseOffset + (int)EHInfoFields.TryEnd * sizeof(uint), sizeof(uint)); Array.Copy(BitConverter.GetBytes((uint)clause.HandlerOffset), 0, ehInfoData, clauseOffset + (int)EHInfoFields.HandlerOffset * sizeof(uint), sizeof(uint)); Array.Copy(BitConverter.GetBytes((uint)(clause.HandlerLength)), 0, ehInfoData, clauseOffset + (int)EHInfoFields.HandlerEnd * sizeof(uint), sizeof(uint)); Array.Copy(BitConverter.GetBytes((uint)clause.ClassTokenOrOffset), 0, ehInfoData, clauseOffset + (int)EHInfoFields.ClassTokenOrOffset * sizeof(uint), sizeof(uint)); }
void hookEHInfo(IntPtr self, IntPtr ftn, uint EHnumber, CORINFO_EH_CLAUSE* clause) { if (ftn == this.ftn) { *clause = clauses[EHnumber]; } else { o_getEHinfo(self, ftn, EHnumber, clause); } }
public static CorMethodInfoHook Hook(ICorJitInfo* comp, IntPtr ftn, CORINFO_EH_CLAUSE[] clauses) { ICorMethodInfo* mtdInfo = ICorStaticInfo.ICorMethodInfo(ICorDynamicInfo.ICorStaticInfo(ICorJitInfo.ICorDynamicInfo(comp))); IntPtr* vfTbl = mtdInfo->vfptr; const int SLOT_NUM = 0x1B; IntPtr* newVfTbl = (IntPtr*)Marshal.AllocHGlobal(SLOT_NUM * IntPtr.Size); for (int i = 0; i < SLOT_NUM; i++) newVfTbl[i] = vfTbl[i]; if (ehNum == -1) for (int i = 0; i < SLOT_NUM; i++) { bool isEh = true; for (byte* func = (byte*)vfTbl[i]; *func != 0xe9; func++) if (IntPtr.Size == 8 ? (*func == 0x48 && *(func + 1) == 0x81 && *(func + 2) == 0xe9) : (*func == 0x83 && *(func + 1) == 0xe9)) { isEh = false; break; } if (isEh) { ehNum = i; break; } } CorMethodInfoHook ret = new CorMethodInfoHook() { ftn = ftn, info = mtdInfo, comp = comp, clauses = clauses, newVfTbl = newVfTbl, oriVfTbl = vfTbl }; ret.n_getEHinfo = new getEHinfo(ret.hookEHInfo); ret.o_getEHinfo = Marshal.GetDelegateForFunctionPointer(vfTbl[ehNum], typeof(getEHinfo)) as getEHinfo; newVfTbl[ehNum] = Marshal.GetFunctionPointerForDelegate(ret.n_getEHinfo); mtdInfo->vfptr = newVfTbl; return ret; }
//static unsafe void Parse(byte* body, CORINFO_METHOD_INFO* info, ICorJitInfo* comp, out CORINFO_EH_CLAUSE[] ehs) //{ // //Refer to SSCLI // if ((*body & 0x3) == 0x2) // { // if (ver) // { // *((uint*)(info + 1) + 0) = 8; //maxstack // *((uint*)(info + 1) + 1) = 0; //ehcount // } // else // { // *((ushort*)(info + 1) + 0) = 8; // *((ushort*)(info + 1) + 1) = 0; // } // info->ILCode = body + 1; // info->ILCodeSize = (uint)(*body >> 2); // ehs = null; // return; // } // else // { // ushort flags = *(ushort*)body; // if (ver) //maxstack // *((uint*)(info + 1) + 0) = *(ushort*)(body + 2); // else // *((ushort*)(info + 1) + 0) = *(ushort*)(body + 2); // info->ILCodeSize = *(uint*)(body + 4); // var localVarTok = *(uint*)(body + 8); // if ((flags & 0x10) != 0) // { // if (ver) //options // *((uint*)(info + 1) + 2) |= (uint)CorInfoOptions.OPT_INIT_LOCALS; // else // *((uint*)(info + 1) + 1) |= (ushort)CorInfoOptions.OPT_INIT_LOCALS; // } // info->ILCode = body + 12; // if (localVarTok != 0) // ParseLocalVars(info, comp, localVarTok); // if ((flags & 0x8) != 0) // { // body = body + 12 + info->ILCodeSize; // var list = new ArrayList(); // byte f; // do // { // body = (byte*)(((uint)body + 3) & ~3); // f = *body; // uint count; // bool isSmall = (f & 0x40) == 0; // if (isSmall) // count = *(body + 1) / 12u; // else // count = (*(uint*)body >> 8) / 24; // body += 4; // for (int i = 0; i < count; i++) // { // var clause = new CORINFO_EH_CLAUSE(); // clause.Flags = (CORINFO_EH_CLAUSE_FLAGS)(*body & 0x7); // body += isSmall ? 2 : 4; // clause.TryOffset = isSmall ? *(ushort*)body : *(uint*)body; // body += isSmall ? 2 : 4; // clause.TryLength = isSmall ? *(byte*)body : *(uint*)body; // body += isSmall ? 1 : 4; // clause.HandlerOffset = isSmall ? *(ushort*)body : *(uint*)body; // body += isSmall ? 2 : 4; // clause.HandlerLength = isSmall ? *(byte*)body : *(uint*)body; // body += isSmall ? 1 : 4; // clause.ClassTokenOrFilterOffset = *(uint*)body; // body += 4; // if ((clause.ClassTokenOrFilterOffset & 0xff000000) == 0x1b000000) // { // if (ver) //options // *((uint*)(info + 1) + 2) |= (uint)CorInfoOptions.GENERICS_CTXT_KEEP_ALIVE; // else // *((uint*)(info + 1) + 1) |= (ushort)CorInfoOptions.GENERICS_CTXT_KEEP_ALIVE; // } // list.Add(clause); // } // } // while ((f & 0x80) != 0); // ehs = new CORINFO_EH_CLAUSE[list.Count]; // for (int i = 0; i < ehs.Length; i++) // ehs[i] = (CORINFO_EH_CLAUSE)list[i]; // if (ver) //ehcount // *((uint*)(info + 1) + 1) = (ushort)ehs.Length; // else // *((ushort*)(info + 1) + 1) = (ushort)ehs.Length; // } // else // { // ehs = null; // if (ver) //ehcount // *((uint*)(info + 1) + 1) = 0; // else // *((ushort*)(info + 1) + 1) = 0; // } // } //} static unsafe uint Interop(IntPtr self, ICorJitInfo* comp, CORINFO_METHOD_INFO* info, uint flags, byte** nativeEntry, uint* nativeSizeOfCode) { if (self == IntPtr.Zero) return 0; if (info != null && (ulong)info->ILCode > s && (ulong)info->ILCode < s + l && info->ILCodeSize == 0x11 && info->ILCode[0] == 0x21 && info->ILCode[9] == 0x20 && info->ILCode[14] == 0x26) { ulong num = *(ulong*)(info->ILCode + 1); uint key = (uint)(num >> 32); uint ptr = (uint)(num & 0xFFFFFFFF) ^ key; uint len = ~*(uint*)(info->ILCode + 10) ^ key; byte[] buff = new byte[len]; fixed (byte* arr = buff) { Marshal.Copy(data, (int)ptr, (IntPtr)arr, (int)len); uint k = key * (uint)Mutation.Key4I; for (uint i = 0; i < buff.Length; i++) { arr[i] ^= (byte)(k & 0xff); k = (k * arr[i] + key) % 0xff; } MethodData* dat = (MethodData*)arr; info->ILCodeSize = dat->ILCodeSize; if (ver) { *((uint*)(info + 1) + 0) = dat->MaxStack; *((uint*)(info + 1) + 1) = dat->EHCount; *((uint*)(info + 1) + 2) = dat->Options & 0xff; } else { *((ushort*)(info + 1) + 0) = (ushort)dat->MaxStack; *((ushort*)(info + 1) + 1) = (ushort)dat->EHCount; *((uint*)(info + 1) + 1) = dat->Options & 0xff; } if (dat->LocalVars != 0) ParseLocalVars(info, comp, dat->LocalVars); CORINFO_EH_CLAUSE[] ehs; byte* body = (byte*)(dat + 1); if ((dat->Options >> 8) == 0) { info->ILCode = body; body += info->ILCodeSize; ehs = new CORINFO_EH_CLAUSE[dat->EHCount]; CORINFO_EH_CLAUSE* ehPtr = (CORINFO_EH_CLAUSE*)body; for (int i = 0; i < dat->EHCount; i++) { ehs[i] = *ehPtr; *ehPtr = new CORINFO_EH_CLAUSE(); ehPtr++; } } else { ehs = new CORINFO_EH_CLAUSE[dat->EHCount]; CORINFO_EH_CLAUSE* ehPtr = (CORINFO_EH_CLAUSE*)body; for (int i = 0; i < dat->EHCount; i++) { ehs[i] = *ehPtr; *ehPtr = new CORINFO_EH_CLAUSE(); ehPtr++; } info->ILCode = (byte*)ehPtr; } *((ulong*)dat) = 0; *((ulong*)dat + 1) = 0; *((uint*)dat + 4) = 0; var hook1 = CorMethodInfoHook.Hook(comp, info->ftn, ehs); var hook2 = CorDynamicInfoHook.Hook(comp); uint ret = originalDelegate(self, comp, info, flags, nativeEntry, nativeSizeOfCode); hook2.Dispose(); hook1.Dispose(); return ret; } } else return originalDelegate(self, comp, info, flags, nativeEntry, nativeSizeOfCode); }
public static CorJitInfoHook Hook(ICorJitInfo* comp, IntPtr ftn, CORINFO_EH_CLAUSE* clauses) { const int slotNum = 8; IntPtr* vfTbl = comp->vfptr; const int SLOT_NUM = 0x9E; var newVfTbl = (IntPtr*)Marshal.AllocHGlobal(SLOT_NUM * IntPtr.Size); for (int i = 0; i < SLOT_NUM; i++) newVfTbl[i] = vfTbl[i]; var ret = new CorJitInfoHook { ftn = ftn, info = comp, clauses = clauses, newVfTbl = newVfTbl, oldVfTbl = vfTbl }; ret.n_getEHinfo = ret.hookEHInfo; ret.o_getEHinfo = (getEHinfo)Marshal.GetDelegateForFunctionPointer(vfTbl[slotNum], typeof(getEHinfo)); newVfTbl[slotNum] = Marshal.GetFunctionPointerForDelegate(ret.n_getEHinfo); comp->vfptr = newVfTbl; return ret; }
protected virtual void GetEHInfo(void *pICorJitInfo, void *methodHandle, uint ehIndex, out CORINFO_EH_CLAUSE clause) { _getEHInfo(VTableHelpers.AdjustThis_GetEHInfo(pICorJitInfo), methodHandle, ehIndex, out clause); }
//static unsafe void Parse(byte* body, CORINFO_METHOD_INFO* info, ICorJitInfo* comp, out CORINFO_EH_CLAUSE[] ehs) //{ // //Refer to SSCLI // if ((*body & 0x3) == 0x2) // { // if (ver) // { // *((uint*)(info + 1) + 0) = 8; //maxstack // *((uint*)(info + 1) + 1) = 0; //ehcount // } // else // { // *((ushort*)(info + 1) + 0) = 8; // *((ushort*)(info + 1) + 1) = 0; // } // info->ILCode = body + 1; // info->ILCodeSize = (uint)(*body >> 2); // ehs = null; // return; // } // else // { // ushort flags = *(ushort*)body; // if (ver) //maxstack // *((uint*)(info + 1) + 0) = *(ushort*)(body + 2); // else // *((ushort*)(info + 1) + 0) = *(ushort*)(body + 2); // info->ILCodeSize = *(uint*)(body + 4); // var localVarTok = *(uint*)(body + 8); // if ((flags & 0x10) != 0) // { // if (ver) //options // *((uint*)(info + 1) + 2) |= (uint)CorInfoOptions.OPT_INIT_LOCALS; // else // *((uint*)(info + 1) + 1) |= (ushort)CorInfoOptions.OPT_INIT_LOCALS; // } // info->ILCode = body + 12; // if (localVarTok != 0) // ParseLocalVars(info, comp, localVarTok); // if ((flags & 0x8) != 0) // { // body = body + 12 + info->ILCodeSize; // var list = new ArrayList(); // byte f; // do // { // body = (byte*)(((uint)body + 3) & ~3); // f = *body; // uint count; // bool isSmall = (f & 0x40) == 0; // if (isSmall) // count = *(body + 1) / 12u; // else // count = (*(uint*)body >> 8) / 24; // body += 4; // for (int i = 0; i < count; i++) // { // var clause = new CORINFO_EH_CLAUSE(); // clause.Flags = (CORINFO_EH_CLAUSE_FLAGS)(*body & 0x7); // body += isSmall ? 2 : 4; // clause.TryOffset = isSmall ? *(ushort*)body : *(uint*)body; // body += isSmall ? 2 : 4; // clause.TryLength = isSmall ? *(byte*)body : *(uint*)body; // body += isSmall ? 1 : 4; // clause.HandlerOffset = isSmall ? *(ushort*)body : *(uint*)body; // body += isSmall ? 2 : 4; // clause.HandlerLength = isSmall ? *(byte*)body : *(uint*)body; // body += isSmall ? 1 : 4; // clause.ClassTokenOrFilterOffset = *(uint*)body; // body += 4; // if ((clause.ClassTokenOrFilterOffset & 0xff000000) == 0x1b000000) // { // if (ver) //options // *((uint*)(info + 1) + 2) |= (uint)CorInfoOptions.GENERICS_CTXT_KEEP_ALIVE; // else // *((uint*)(info + 1) + 1) |= (ushort)CorInfoOptions.GENERICS_CTXT_KEEP_ALIVE; // } // list.Add(clause); // } // } // while ((f & 0x80) != 0); // ehs = new CORINFO_EH_CLAUSE[list.Count]; // for (int i = 0; i < ehs.Length; i++) // ehs[i] = (CORINFO_EH_CLAUSE)list[i]; // if (ver) //ehcount // *((uint*)(info + 1) + 1) = (ushort)ehs.Length; // else // *((ushort*)(info + 1) + 1) = (ushort)ehs.Length; // } // else // { // ehs = null; // if (ver) //ehcount // *((uint*)(info + 1) + 1) = 0; // else // *((ushort*)(info + 1) + 1) = 0; // } // } //} static unsafe uint Interop(IntPtr self, ICorJitInfo *comp, CORINFO_METHOD_INFO *info, uint flags, byte **nativeEntry, uint *nativeSizeOfCode) { if (self == IntPtr.Zero) { return(0); } if (info != null && (ulong)info->ILCode > s && (ulong)info->ILCode < s + l && info->ILCodeSize == 0x11 && info->ILCode[0] == 0x21 && info->ILCode[9] == 0x20 && info->ILCode[14] == 0x26) { ulong num = *(ulong *)(info->ILCode + 1); uint key = (uint)(num >> 32); uint ptr = (uint)(num & 0xFFFFFFFF) ^ key; uint len = ~*(uint *)(info->ILCode + 10) ^ key; byte[] buff = new byte[len]; fixed(byte *arr = buff) { Marshal.Copy(data, (int)ptr, (IntPtr)arr, (int)len); uint k = key * (uint)Mutation.Key4I; for (uint i = 0; i < buff.Length; i++) { arr[i] ^= (byte)(k & 0xff); k = (k * arr[i] + key) % 0xff; } MethodData *dat = (MethodData *)arr; info->ILCodeSize = dat->ILCodeSize; if (ver) { *((uint *)(info + 1) + 0) = dat->MaxStack; *((uint *)(info + 1) + 1) = dat->EHCount; *((uint *)(info + 1) + 2) = dat->Options & 0xff; } else { *((ushort *)(info + 1) + 0) = (ushort)dat->MaxStack; *((ushort *)(info + 1) + 1) = (ushort)dat->EHCount; *((uint *)(info + 1) + 1) = dat->Options & 0xff; } if (dat->LocalVars != 0) { ParseLocalVars(info, comp, dat->LocalVars); } CORINFO_EH_CLAUSE[] ehs; byte *body = (byte *)(dat + 1); if ((dat->Options >> 8) == 0) { info->ILCode = body; body += info->ILCodeSize; ehs = new CORINFO_EH_CLAUSE[dat->EHCount]; CORINFO_EH_CLAUSE *ehPtr = (CORINFO_EH_CLAUSE *)body; for (int i = 0; i < dat->EHCount; i++) { ehs[i] = *ehPtr; *ehPtr = new CORINFO_EH_CLAUSE(); ehPtr++; } } else { ehs = new CORINFO_EH_CLAUSE[dat->EHCount]; CORINFO_EH_CLAUSE *ehPtr = (CORINFO_EH_CLAUSE *)body; for (int i = 0; i < dat->EHCount; i++) { ehs[i] = *ehPtr; *ehPtr = new CORINFO_EH_CLAUSE(); ehPtr++; } info->ILCode = (byte *)ehPtr; } *((ulong *)dat) = 0; *((ulong *)dat + 1) = 0; *((uint *)dat + 4) = 0; var hook1 = CorMethodInfoHook.Hook(comp, info->ftn, ehs); var hook2 = CorDynamicInfoHook.Hook(comp); uint ret = originalDelegate(self, comp, info, flags, nativeEntry, nativeSizeOfCode); hook2.Dispose(); hook1.Dispose(); return(ret); } } else { return(originalDelegate(self, comp, info, flags, nativeEntry, nativeSizeOfCode)); } }