>例如,我有两个包含IL代码的文本文件,两个文本文件都包含100%相同的代码:
http://pastebin.com/iDvbu1tD
http://pastebin.com/u5fi9NMh
然而,它们未对齐/混乱,因此我无法找到任何差异,我正在寻找一种方法来获取此类文件并过滤掉相同的代码,并且只显示不同的块。
有没有办法完成这样的任务?
首先是"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 { 代码大小 21 (0x15) .maxstack 8 ldarg.0 ldfld class [UnityEngine]UnityEngine.AndroidJavaObject GooglePlayGames.Android.AndroidRtmpClient::mRoom 布莱夫IL_0013 ldarg.0[ ...狙...... ] LDC.i4.0 雷特 }//end of method AndroidRtmpClient::IsRoomConnected[ ...其他方法... ]
.method
材料折叠成一行,IsRoomConnected
首先,因为其他两个函数分别以 P
和 O
开头,并且偏移量从指令中消失。
由于 Bash "进程替换"<(command ...)
语法,可以在 Linux 环境中一步完成比较重新格式化的版本,而无需临时文件。 此语法允许我们使用生成输出的程序代替文件名参数。 被调用的程序认为它是一个文件:
$ diff -u <(txr norm.txr disasm-a) <(txr norm.txr disasm-b)# 无输出!
也就是说,当我们比较两个反汇编列表的规范化版本时,没有输出:它们是字符对字符相同的!
norm.txr
的代码清单如下:
(收集)@(自由格式) .方法 @decl {@ (bind pieces @(tok-str decl #/\S+/))@ (绑定名称 @(find-if (op search-str @1 "(") 片段))@ (收集)@(案例) IL_@offset:@line@ (或) @line@ (完)@ (最后) }//@eom@ (完)@(完)@(设置(名称十进制行 EOM) @(多排序(列表名称十进制行 EOM) [列表更少]))@(输出)@(重复) .方法@decl {@(重复) @line@ (完) }//@eom@ (完)@(完)