.Net RuntimeExplorer开发日志(五) IL to C# - 解析语法糖
最近诸事不顺,父母需要照顾,自己也病了一阵,时间太散了,没法静下心来思考,所以搁置了两个多月。言归正传,试着生成了一个debug版本,结果呵呵,大量的数组下标越界和空引用问题,显示出来的也驴唇不对马嘴,不过比较庆幸是对PE头和.net表及资源的解析没有大问题,只在格式上略有不足而已。
语法糖这个东西真的是无处不在吖,你以为只有lambda表达式是语法糖吗?当然不,++、--、+=、-=、?:、use、foreach等等都是。在已经解析好的基本表达式之上再度解析,代码又增加了,下面则记录一些特殊的处理。
数组元素的赋值有两种方式,举例说明:int[] ary = new int[1]; ary[1]=0; 与 int[] ary = new int[] {0}; 这两句在IL上是完全不同的表现,前者是两句表达式,后者是一句。当遇到params object[] objs 这个参数时,object数组不能再显示其类型和new关键字,只显示{}中的数组元素,如果是空数组则不显示任何。在这里代码的变复杂了,从SubBlock派生类了ListBlock,用以表示数组值,从SubBlockWriter派生了ArrayBlockWriter,用来单独处理数组的显示,还增加了修订的功能,意思是在最终显示或被拼接时再填充其内容,以此来动态处理数组中元素。
一些被隐藏调用的方法,例如string+string其实是string.concat(),typeof(type)其实是Type.GetTypeFromHandle(type),基础类型中一些操作符实际上是调用op_xxxx方法,还有扩展方法和属性事件的方法等等。这些都需要预处理,在目标进程中反射时就要单独标注出来,才能在生成表达式时特殊处理。
对每个IL语句的operand进行类型判定,以便在条件跳转语句上做出区别应对,例如brtrue这个IL语句,其上一句的operand是数字时译为if(xxx == 0){},上一句operand是对象时译为if(xxx == null){}等等列情况。
对于在方法末端的多个出口语句,将以inline的形式代替goto语句。
被遗忘的几个关键字。__arglist这目前还不知该如何处理,因为无法判断实际参数的数量,也许会在方法体被JIT后在前导和后导会有处理,但单从IL和元数据上无法得知,日后应该会简单的用代码猜测一下。__makeref,__reftype和__refvalue这三兄弟也着实让我费力了一番,原以为只是操作托管指针,但实际上不止如此,为此又重新改了一次构架,增加对指针型operand的支持,还有stackalloc基本上也没什么可说。
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号