我有两个包含IL代码的文本文件,例如,两个文本文件都包含100%相同的代码:
然而它们是未对齐/混乱的,因此我找不到任何差异,我正在寻找一种方法来获取这些文件并过滤掉相同的代码并仅显示不同的块。
有没有办法完成这样的任务?
答案 0 :(得分:0)
首先" TL; DR":正如你所说,这两个贴纸实际上是相同的,除了方法顺序的简单差异,以及非常小的格式问题。也就是说,每个反汇编列表中的中间方法的.method
行不会被两个空格缩进,就像同一文件中的其他两个.method
行一样。
我将这些文件复制到Ubuntu Linux系统,并且可以自由地手动修复这些文件中的轻微.method
格式问题。
然后我使用TXR语言编写了一些提取代码,其目的是规范化文件:它提取方法,识别每个方法的名称,然后打印重新格式化的反汇编版本。然后可以比较这些重新格式化的版本。
在重新格式化中,方法按名称排序。此外,指令上的IL_XXXX偏移被删除,因此,诸如插入指令序列之类的微小差异不会由于随后的偏移改变而导致巨大差异。但是,这没有用给定的数据证明,因为代码实际上是相同的。
以下是其中一个输入的重新格式化内容,手动缩写:
$ txr norm.txr disasm-a .method public hidebysig newslot virtual final instance bool IsRoomConnected() cil managed { // Code size 21 (0x15) .maxstack 8 ldarg.0 ldfld class [UnityEngine]UnityEngine.AndroidJavaObject GooglePlayGames.Android.AndroidRtmpClient::mRoom brfalse IL_0013 ldarg.0 [ ... snip ... ] ldc.i4.0 ret } // end of method AndroidRtmpClient::IsRoomConnected [ ... other methods ... ]
.method
素材被折叠成一行,IsRoomConnected
是第一行,因为其他两个函数分别以P
和O
开头,且偏移量已从说明。
比较重新格式化的版本可以在Linux环境中一步完成而无需临时文件,这要归功于Bash&#34;进程替换&#34; <(command ...)
语法。这种语法允许我们在文件名参数的位置使用产生输出的程序。被调用的程序认为它是一个文件:
$ diff -u <(txr norm.txr disasm-a) <(txr norm.txr disasm-b) # no output!
也就是说,当我们对两个反汇编列表的规范化版本进行区分时,没有输出:它们是字符对字符相同的!
norm.txr
的代码清单如下:
(collect) @ (freeform) .method @decl { @ (bind pieces @(tok-str decl #/\S+/)) @ (bind name @(find-if (op search-str @1 "(") pieces)) @ (collect) @ (cases) IL_@offset: @line @ (or) @line @ (end) @ (last) } // @eom @ (end) @(end) @(set (name decl line eom) @(multi-sort (list name decl line eom) [list less])) @(output) @ (repeat) .method @decl { @ (repeat) @line @ (end) } // @eom @ (end) @(end)