.NET高级调试 | 通过JIT拦截无侵入调试 C# Emit 生成的动态代码

大家还记得上一篇的测试代码吗?我们用了:

Console.WriteLine("Function Pointer: 0x{0:x16}", Marshal.GetFunctionPointerForDelegate(addDelegate).ToInt64());

来获得 委托函数指针 地址,通过这个突破口最终实现了 动态代码 的调试,这种方式可以是可以,但很显然这是侵入式的,那有没有办法实现 非侵入 调试动态代码呢?在 .NET高级调试 这本书上还真给找到了,方法就是在  JIT 编译动态方法时进行拦截,获取其中的 方法描述符

为了方便讲解,先上测试代码:

class Program{private delegate int AddDelegate(int a, int b);static void Main(string[] args){var dynamicAdd = new DynamicMethod("Add", typeof(int), new[] { typeof(int), typeof(int) }, true);var il = dynamicAdd.GetILGenerator();il.Emit(OpCodes.Ldarg_0);il.Emit(OpCodes.Ldarg_1);il.Emit(OpCodes.Add);il.Emit(OpCodes.Ret);var addDelegate = (AddDelegate)dynamicAdd.CreateDelegate(typeof(AddDelegate));//Debugger.Break();//Console.WriteLine("Function Pointer: 0x{0:x16}", Marshal.GetFunctionPointerForDelegate(addDelegate).ToInt64());Console.WriteLine(addDelegate(10, 20));}}

可以看到,我把上面两行侵入式的代码给屏蔽掉了,接下来在 il.Emit(OpCodes.Ret); 处下断点,目的是为了在 clr 加载后寻找 JIT的 compileMethod 方法。

0:000> !mbp Program.cs 28
The CLR has not yet been initialized in the process.
Breakpoint resolution will be attempted when the CLR is initialized.
0:000> g
ModLoad: 76910000 7698a000   C:\Windows\SysWOW64\ADVAPI32.dll
...
ModLoad: 77190000 77226000   C:\Windows\SysWOW64\OLEAUT32.dll
Breakpoint: JIT notification received for method ConsoleApp1.Program.Main(System.String[]) in AppDomain 00783758.
Breakpoint set at ConsoleApp1.Program.Main(System.String[]) in AppDomain 00783758.
Breakpoint 1 hit
eax=00000001 ebx=0019f5ac ecx=023c3684 edx=ffffffff esi=023c230c edi=0019f4fc
eip=048a0a02 esp=0019f4ac ebp=0019f508 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
048a0a02 b901000000      mov     ecx,1

接下来可以用 x 命令模糊搜索 compileMethod 签名,找出签名是为了更好的下断点。

0:000> x *!*compileMethod*
...
61413700          clrjit!CILJit::compileMethod (class ICorJitInfo *, struct CORINFO_METHOD_INFO *, unsigned int, unsigned char **, unsigned long *)

可以看到 compileMethod 的完整签名是 clrjit!CILJit::compileMethod, 并且它的方法入口点地址是 61413700,有了它就可以对其下断点啦!

0:000> bp 61413700
0:000> g
Breakpoint 0 hit
eax=61494698 ebx=80000004 ecx=61413700 edx=00005c10 esi=6148b3fc edi=0019efa4
eip=61413700 esp=0019ede0 ebp=0019ee38 iopl=0         nv up ei ng nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000282
clrjit!CILJit::compileMethod:
61413700 55              push    ebp
0:000> kb# ChildEBP RetAddr      Args to Child              
00 0019ee38 62a4ccc3     61494698 0019efa4 0019ef1c clrjit!CILJit::compileMethod [f:\dd\ndp\clr\src\jit32\ee_il_dll.cpp @ 151] 
01 0019ee38 62a4cd9b     0019ef1c 0019f06c 0019f024 clr!invokeCompileMethodHelper+0x10b

很开心,成功命中,接下来提取 compileMethod 方法的第三个参数,它就是需要编译方法所指向的 方法描述符 地址,可以用 dp 给提取出来。

0:000> dp 0019ef1c L1
0019ef1c  0071537c
0:000> !dumpmd 0071537c
Method Name:  DynamicClass.Add(Int32, Int32)
Class:        007152e8
MethodTable:  0071533c
mdToken:      06000000
Module:       00714ea8
IsJitted:     no
CodeAddr:     ffffffff
Transparency: Transparent

方法描述符果然给调出来了,但这里的方法字节码是 CodeAddr: ffffffff ,说明此时动态方法还没有开始编译,为了能够使其编译,我们在 Console.WriteLine(addDelegate(10, 20)); 处再下一个断点,因为代码到此处时, JIT 肯定编译了该办法,自然就能看到编译后的 CodeAddr 地址。

0:000> !mbp Program.cs 35
Breakpoint set at ConsoleApp1.Program.Main(System.String[]) in AppDomain 00783758.
0:000> g
Breakpoint 3 hit
eax=023c5f88 ebx=0019f5ac ecx=023c5f3c edx=00008f17 esi=023c230c edi=0019f4fc
eip=048a0a9b esp=0019f4ac ebp=0019f508 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
048a0a9b 6a14            push    14h
0:000> !dumpmd 0071537c
Method Name:  DynamicClass.Add(Int32, Int32)
Class:        007152e8
MethodTable:  0071533c
mdToken:      06000000
Module:       00714ea8
IsJitted:     yes
CodeAddr:     04a00050
Transparency: Transparent

可以看到,此时的 CodeAddr: 04a00050 ,也就表明已经编译完成了,接下来继续 bp 。

0:000> bp 04a00050
0:000> g
Breakpoint 4 hit
eax=023c5f98 ebx=0019f5ac ecx=0000000a edx=00000014 esi=023c230c edi=0019f4fc
eip=04a00050 esp=0019f4a8 ebp=0019f508 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
04a00050 8bc1            mov     eax,ecx
24b348be52affede333cac09ebff780a.png

可以看到,全部搞定,非侵入式,🐂

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/289175.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用IAR开发CC2530遇到的两个问题

2019独角兽企业重金招聘Python工程师标准>>> 首先说明,IAR for 8051为7.51版本,操作系统为windows7 32位。 上手CC2530,在IDE的使用上就遇到了2个问题。 一个是用SmartRF Programmer Flash下载HEX文件不成功,提示说cou…

openssh登陆时提示服务器拒绝了密码

升级openssh7.5后,登陆报错按照网上的说法是不允许root用户登陆但是,/etc/ssh/sshd_config 已经写入PermitRootLogin yes解决方法:设置/etc/sysconfig/selinux 中的SELINUXdisabled然后重启就OK了转载于:https://blog.51cto.com/adamcrab/194…

Blazor University (10)组件 — 捕获意外参数

原文链接&#xff1a;https://blazor-university.com/components/capturing-unexpected-parameters/捕获意外参数源代码[1]之前我们已经看到了如何使用特定名称声明参数和级联参数。例如&#xff0c;一个将 <img> 元素包装在一些自定义 HTML 中的自定义组件。<div cla…

React Native之最构建对象通过构造方法传递值然后再获取值

1 问题 在一个文件构建一个对象,然后在另外一个文件里面new这个对象,通过构造方法传递参数,然后再获取这个参数 2 测试代码 Student.js文件如下 use strict;import React from reactimport {NativeModules, NativeEventEmitter, DeviceEventEmitter,Alert} from react-nativ…

.NET点滴:SpanT

昨天小桂问了一个问题&#xff0c;把一个数组的全部元素加1&#xff0c;有什么好办法&#xff0c;于是有了下面的分析&#xff1a;var arr new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; //方法一 foreach (var i in arr) {i; } //方法二 for (var i 0; i < arr.Length; i) {…

React Native之通过DeviceEventEmitter发送和接收事件

1 怎么实现发送和接收事件 理论上封装了Android原生广播的代码,需要注册和反注册,这里用DeviceEventEmitter实现 //增加监听 DeviceEventEmitter.addListener //取消监听 //this.emitter.remove(); 这里可也可以通过安卓原生向页面js发送消息,可以参考我的这篇博客 React Nat…

navicat循环执行上下两行相减sql语句_SQL太难?你离完全理解SQL就差这10步!

- 点击上方“中国统计网”设置⭐星标不迷路&#xff01;-很多程序员视 SQL 为洪水猛兽。SQL 是一种为数不多的声明性语言&#xff0c;它的运行方式完全不同于我们所熟知的命令行语言、面向对象的程序语言、甚至是函数语言(尽管有些人认为 SQL 语言也是一种函数式语言)。我们每天…

mysql游标书写_mysql中光标如何书写

mysql中光标书写的方法&#xff1a;首先声明光标&#xff1b;然后开启光标&#xff0c;代码为【OPEN cursor_name】&#xff1b;接着捕获光标&#xff1b;最后关闭光标&#xff0c;代码为【CLOSE cursor_name】。本教程操作环境&#xff1a;windows7系统、mysql5.8版&#xff0…

上海女白领吃火锅碰瓷,支付宝口碑居然真的要赔?

昨天中午&#xff0c;新闻晨报在微博上发出一条新闻&#xff1a;上海一位汪小姐吃火锅的时候&#xff0c;因用支付宝口碑扫码中了一个999元大红包&#xff0c;结果因为太激动手机不小心掉进油汤里&#xff0c;捞出来以后开不了机了。关键是这位小姐觉得这是口碑和商家活动导致的…

ASP.NETCore统一处理404错误都有哪些方式?

当未找到网页并且应用程序返回 404 错误时&#xff0c;ASP.NET Core MVC 仅呈现通用浏览器错误页面&#xff0c;如下图所示这不是很优雅&#xff0c;是吗&#xff1f;我们平时看到的404页面一般是这样的还有这样的试了下京东&#xff0c;地址不存在的时候是会重定向到首页下面就…

React Native之组件(Component)生命周期学习笔记

1、Component介绍 一般Component需要被其它类进行继承&#xff0c;Component和Android一样&#xff0c;也有生命周期 英文图片如下 2 具体说明 1)、挂载阶段 constructor() //构造函数,声明之前先调用super(props) componentWillMount()//因为它发生在render()方法前&…

基于junit4的关于个人所得税计算的等价类与边界值_《边界值分析》-有这篇就够了...

目录&#xff1a;定义&#xff08;What&#xff09;为什么使用该方法&#xff1f;&#xff08;Why&#xff09;如何选定边界值&#xff1f;&#xff08;How&#xff09;设计测试用例根据测试用例的完整性划分边界的分类使用场景实战演练边界值分析的优缺点特殊值测试边界值分析…

【Envi风暴】ENVI中求两幅遥感影像的相关性(相关系数)

相关性,是指两个变量的关联程度。一般地,从散点图上可以观察到两个变量有以下三种关系之一:两变量正相关、负相关、不相关。如果一个变量高的值对应于另一个变量高的值,相似地,低的值对应低的值,那么这两个变量正相关。在土壤中,孔隙率和渗透度就具有典型的正相关。反之…

(三) 一起学 Unix 环境高级编程 (APUE) 之 文件和目录

. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编程 (APUE) 之 文件和目录 (四) 一起学 Unix 环境高级编程 (APUE) 之 系统数据文件和信息 (五) 一起学 Unix 环境高级编程 (APUE)…

C# StreamReader类和StreamWriter类

先看看 StreamReader&#xff0c;将前面的示例转换为读取文件以使用 StreamReader。它现在看起来容易得多。StreamReader 的构造函数接收FileStream。使用 EndOfStream 属性可以检查文件的末尾&#xff0c;使用ReadLine 方法读取文本行&#xff1a;public static void ReadFile…

DIV+CSS列表式布局(同意图片的应用)

1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">2 <html xmlns"http://www.w3.org/1999/xhtml">3 <head>4 <!--gbk,gb2312 中文-->5 &…

斯皮尔曼等级相关

一、斯皮尔曼等级相关简介 斯皮尔曼等级相关(Spearman’s correlation coefficient for ranked data)主要用于解决称名数据和顺序数据相关的问题。适用于两列变量,而且具有等级变量性质具有线性关系的资料。由英国心理学家、统计学家斯皮尔曼根据积差相关的概念推到而来,一…

用php写一个可以抽取随机数的工具一次只抽四个怎么实现?_面试了一个32岁的程序员,场面一度很尴尬。...

招人背景首先说一下朋友的公司招人背景&#xff0c;公司招聘PHP高级岗位&#xff0c;负责公司的B2B项目研发、并发问题的处理和解决。领导给了他两个要求&#xff1a;&#xff08;接下来的讲述我会以朋友的第一人称来进行&#xff09;&#xff08;1&#xff09;技术比较好&…

React Native之导出

1 React Native里面一般导出函数或者常量或者组件 如果是默认组件或者类(export default修饰)的话,在另外一个地方导入的时候不需要加上{},格式如下 导出 export default class Student {} 导入 import Student from "./file"如果不是默认组件或类或则方法或则变量…

Windows 11 新版 22598 发布!引入 4K 聚焦壁纸,优化全新任务管理器和媒体播放器...

面向 Dev 和 Beta 频道的 Windows 预览体验成员&#xff0c;微软现已发布 Windows 11 预览版 Build 22598。主要变化1.微软宣布媒体播放器应用程序现已更新&#xff0c;进一步适配 Windows 11 的视觉设计。在播放视频时右键将看到全新的菜单&#xff0c;此外还提高了该应用的性…