objdumpのdiffをいい感じに取る方法のメモ
たとえば、次のような二つのC言語コードを考える。
/* test1.c */ #include <stdio.h> double divide(long x, long y) { return x/(double)y; } int main() { divide(1, 2); divide(1, 0); return 0; }
/* test2.c */ #include <stdio.h> #include <stdlib.h> double divide(long x, long y) { if (!y) { exit(1); } return x/(double)y; } int main() { divide(1, 2); divide(1, 0); return 0; }
二つ目のコードは、被除数が0かどうかのチェックを加えたものである。 これらをそれぞれコンパイルし、objdumpで逆アセンブルしたもののdiffを取ると次のようになる。
$ make test1 test2 cc test1.c -o test1 cc test2.c -o test2 $ diff -u <(objdump -d test1) <(objdump -d test2) --- /dev/fd/63 2016-04-30 07:28:59.852032082 +0900 +++ /dev/fd/62 2016-04-30 07:28:59.852032082 +0900 @@ -1,193 +1,202 @@ -test1: file format elf64-x86-64 +test2: file format elf64-x86-64 Disassembly of section .init: -00000000004003a8 <_init>: - 4003a8: 48 83 ec 08 sub rsp,0x8 - 4003ac: 48 8b 05 45 0c 20 00 mov rax,QWORD PTR [rip+0x200c45] # 600ff8 <_DYNAMIC+0x1d0> - 4003b3: 48 85 c0 test rax,rax - 4003b6: 74 05 je 4003bd <_init+0x15> - 4003b8: e8 33 00 00 00 call 4003f0 <__gmon_start__@plt> - 4003bd: 48 83 c4 08 add rsp,0x8 - 4003c1: c3 ret +00000000004003e0 <_init>: + 4003e0: 48 83 ec 08 sub rsp,0x8 + 4003e4: 48 8b 05 0d 0c 20 00 mov rax,QWORD PTR [rip+0x200c0d] # 600ff8 <_DYNAMIC+0x1d0> + 4003eb: 48 85 c0 test rax,rax + 4003ee: 74 05 je 4003f5 <_init+0x15> + 4003f0: e8 2b 00 00 00 call 400420 <__gmon_start__@plt> + 4003f5: 48 83 c4 08 add rsp,0x8 + 4003f9: c3 ret Disassembly of section .plt: -00000000004003d0 <__libc_start_main@plt-0x10>: - 4003d0: ff 35 32 0c 20 00 push QWORD PTR [rip+0x200c32] # 601008 <_GLOBAL_OFFSET_TABLE_+0x8> - 4003d6: ff 25 34 0c 20 00 jmp QWORD PTR [rip+0x200c34] # 601010 <_GLOBAL_OFFSET_TABLE_+0x10> - 4003dc: 0f 1f 40 00 nop DWORD PTR [rax+0x0] - (snip)
主にアドレス部分のずれにより、まったくdiffが取れていないことがわかる。
このような場合、次のようなコマンドを打つとよい。
$ diff -u1 -F '>:$' -I '[0-9a-f]\{6,\}' <(objdump -d test1 | cut -f2-) <(objdump -d test2 | cut -f2-) --- /dev/fd/63 2016-04-30 07:40:28.072016196 +0900 +++ /dev/fd/62 2016-04-30 07:40:28.072016196 +0900 @@ -1,3 +1,3 @@ -test1: file format elf64-x86-64 +test2: file format elf64-x86-64 @@ -30,3 +30,8 @@ 00000000004003f0 <__gmon_start__@plt>: 68 01 00 00 00 push 0x1 -e9 d0 ff ff ff jmp 4003d0 <_init+0x28> +e9 d0 ff ff ff jmp 400400 <_init+0x20> + +0000000000400430 <exit@plt>: +ff 25 f2 0b 20 00 jmp QWORD PTR [rip+0x200bf2] # 601028 <_GLOBAL_OFFSET_TABLE_+0x28> +68 02 00 00 00 push 0x2 +e9 c0 ff ff ff jmp 400400 <_init+0x20> @@ -118,4 +123,9 @@ 00000000004004ed <divide>: 48 89 e5 mov rbp,rsp +48 83 ec 20 sub rsp,0x20 48 89 7d f8 mov QWORD PTR [rbp-0x8],rdi 48 89 75 f0 mov QWORD PTR [rbp-0x10],rsi +48 83 7d f0 00 cmp QWORD PTR [rbp-0x10],0x0 +75 0a jne 40054e <divide+0x21> +bf 01 00 00 00 mov edi,0x1 +e8 e2 fe ff ff call 400430 <exit@plt> f2 48 0f 2a 45 f8 cvtsi2sd xmm0,QWORD PTR [rbp-0x8] @@ -127,3 +137,3 @@ 00000000004004ed <divide>: f2 0f 10 45 e8 movsd xmm0,QWORD PTR [rbp-0x18] -5d pop rbp +c9 leave c3 ret @@ -142,4 +152,3 @@ 000000000040051d <main>: c3 ret -66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0] -00 00 00 +0f 1f 44 00 00 nop DWORD PTR [rax+rax*1+0x0]
-u1
は差分の前後1行のみを表示させるオプション、-F
は正規表現にマッチする行をセクション見出しとして扱うオプション、-I
は正規表現にマッチする行のみの差分を除外するオプションである。