encounter / objdiff

A local diffing tool for decompilation projects
Apache License 2.0
124 stars 21 forks source link

objdiff-cli diff: allow writing diff to a file. #96

Closed roblabla closed 2 months ago

roblabla commented 3 months ago

It'd be awesome to use objdiff-cli diff as part of a CI pipeline to be able to display the diff between an implementation and the original.

I currently do this hackily by diffing some asm dumps manually (See https://github.com/happyhavoc/th06/actions/runs/10192215949#user-content-enemy____updateeffects), but this runs into all kind of issues that objdiff already solves.

Unfortunately, objdiff-cli diff seems to only support TUI operation, and cannot just output the diff to standard output.

encounter commented 2 months ago

This was implemented in v2.0.0-beta.4. The diff structures are defined with protobuf, and the diff command accepts options for output and format. Let me know if this fits your needs!

roblabla commented 2 months ago

This is great! I wrote a quick python script that's able to generate a "simili-patchfile", and github seems to accept it:

import json
import sys

with open(sys.argv[1]) as f:
    data = json.load(f)

left_sects = data['left']['sections']
right_sects = data['right']['sections']

left_fun = next((fun for sect in left_sects for fun in sect['functions'] if fun['symbol']['name'] == sys.argv[2]), None)
right_fun = next((fun for sect in right_sects for fun in sect['functions'] if fun['symbol']['name'] == sys.argv[2]), None)

for left_instr, right_instr in zip(left_fun['instructions'], right_fun['instructions']):
    if 'diff_kind' not in left_instr:
        print(' ' + left_instr['instruction']['formatted'])
    elif left_instr['diff_kind'] == 'DIFF_INSERT':
        print('+' + right_instr['instruction']['formatted'])
    elif left_instr['diff_kind'] == 'DIFF_DELETE':
        print('-' + left_instr['instruction']['formatted'])
    else:
        print('-' + left_instr['instruction']['formatted'])
        print('+' + right_instr['instruction']['formatted'])
Example output (click me): ```diff push ebp mov ebp, esp push ecx push esi push edi mov [ebp-4], ecx mov esi, [ebp+0Ch] mov eax, [ebp+8] imul eax, 38h mov edi, [ebp-4] add edi, eax mov ecx, 0Eh rep movsd [edi], [esi] mov ecx, [ebp+8] imul ecx, 38h mov edx, [ebp-4] mov eax, [ebp-4] mov eax, [eax+1C930h] mov [edx+ecx+34h], eax mov ecx, [ebp-4] mov edx, [ecx+1C930h] add edx, 1 mov eax, [ebp-4] mov [eax+1C930h], edx mov ecx, [ebp+8] imul ecx, 38h mov edx, [ebp+8] imul edx, 38h mov eax, [ebp-4] +mov esi, [ebp-4] -fld st, dword ptr [eax+edx+18h] +fld st, dword ptr [eax+ecx+4] -mov edx, [ebp-4] +fdiv st, dword ptr [esi+edx+18h] -fdivr st, dword ptr [edx+ecx+4] -mov eax, [ebp+8] +mov ecx, [ebp+8] -imul eax, 38h +imul ecx, 38h -mov ecx, [ebp-4] +mov edx, [ebp-4] -fstp dword ptr [ecx+eax+1Ch], st +fstp dword ptr [edx+ecx+1Ch], st -mov edx, [ebp+8] +mov eax, [ebp+8] -imul edx, 38h +imul eax, 38h -mov eax, [ebp+8] +mov ecx, [ebp+8] -imul eax, 38h +imul ecx, 38h -mov ecx, [ebp-4] +mov edx, [ebp-4] +mov esi, [ebp-4] -fld st, dword ptr [ecx+eax+18h] +fld st, dword ptr [edx+eax+0Ch] -mov eax, [ebp-4] +fdiv st, dword ptr [esi+ecx+18h] -fdivr st, dword ptr [eax+edx+0Ch] -mov ecx, [ebp+8] +mov eax, [ebp+8] -imul ecx, 38h +imul eax, 38h -mov edx, [ebp-4] +mov ecx, [ebp-4] -fstp dword ptr [edx+ecx+24h], st +fstp dword ptr [ecx+eax+24h], st -mov eax, [ebp+8] +mov edx, [ebp+8] -imul eax, 38h +imul edx, 38h -mov ecx, [ebp+8] +mov eax, [ebp+8] -imul ecx, 38h +imul eax, 38h -mov edx, [ebp-4] +mov ecx, [ebp-4] +mov esi, [ebp-4] -fld st, dword ptr [edx+ecx+14h] +fld st, dword ptr [ecx+edx+8] -mov ecx, [ebp-4] +fdiv st, dword ptr [esi+eax+14h] -fdivr st, dword ptr [ecx+eax+8] mov edx, [ebp+8] imul edx, 38h mov eax, [ebp-4] fstp dword ptr [eax+edx+20h], st mov ecx, [ebp+8] imul ecx, 38h mov edx, [ebp+8] imul edx, 38h mov eax, [ebp-4] +mov esi, [ebp-4] -fld st, dword ptr [eax+edx+14h] +fld st, dword ptr [eax+ecx+10h] -mov edx, [ebp-4] +fdiv st, dword ptr [esi+edx+14h] -fdivr st, dword ptr [edx+ecx+10h] -mov eax, [ebp+8] +mov ecx, [ebp+8] -imul eax, 38h +imul ecx, 38h -mov ecx, [ebp-4] +mov edx, [ebp-4] -fstp dword ptr [ecx+eax+28h], st +fstp dword ptr [edx+ecx+28h], st -mov edx, [ebp+8] +mov eax, [ebp+8] -imul edx, 38h +imul eax, 38h -mov eax, [ebp+8] +mov ecx, [ebp+8] -imul eax, 38h +imul ecx, 38h -mov ecx, [ebp-4] +mov edx, [ebp-4] mov esi, [ebp-4] -fld st, dword ptr [ecx+edx+0Ch] +fld st, dword ptr [edx+eax+0Ch] -fsub st, dword ptr [esi+eax+4] +fsub st, dword ptr [esi+ecx+4] -mov edx, [ebp+8] +mov eax, [ebp+8] -imul edx, 38h +imul eax, 38h -mov eax, [ebp-4] +mov ecx, [ebp-4] -fstp dword ptr [eax+edx+30h], st +fstp dword ptr [ecx+eax+30h], st -mov ecx, [ebp+8] +mov edx, [ebp+8] -imul ecx, 38h +imul edx, 38h -mov edx, [ebp+8] +mov eax, [ebp+8] -imul edx, 38h +imul eax, 38h -mov eax, [ebp-4] +mov ecx, [ebp-4] mov esi, [ebp-4] -fld st, dword ptr [eax+ecx+10h] +fld st, dword ptr [ecx+edx+10h] -fsub st, dword ptr [esi+edx+8] +fsub st, dword ptr [esi+eax+8] -mov ecx, [ebp+8] +mov edx, [ebp+8] -imul ecx, 38h +imul edx, 38h -mov edx, [ebp-4] +mov eax, [ebp-4] -fstp dword ptr [edx+ecx+2Ch], st +fstp dword ptr [eax+edx+2Ch], st pop edi pop esi mov esp, ebp pop ebp ret 8 ```
roblabla commented 2 months ago

One small question: My script will currently treat differing relocations as being a diff, while objdiff does not. I'm not sure how I'm supposed to detect this and treat them as a match.

encounter commented 2 months ago

It should, unless you pass --relax-reloc-diffs. So that's odd. Do you have an example?

roblabla commented 2 months ago

Ah, that fixed it. I had missed the --relax-reloc-diffs flag. With this, everything's working great!