Magic Lantern Firmware Wiki
Advertisement

An experimental decompiler for ARM ASM is implemented in ARM-console, module deco.

Theory: Static_analysis

Notations[]

  • arg0, arg1, arg2, arg3 => function arguments passed in r0, r1, r2, r3
  • sp0 => stack pointer at the beginning of the function
    • *(sp0), *(sp0+4), *(sp0+8) => arg4, arg5, arg6
    • *(sp0-4), *(sp0-8)... => local variables
  • !end => end of code path
  • EQ(x), NE(x): check some condition flags; e.g. EQ(x) is true if x == 0
  • EQ5(x) is true if x == 5 (these will appear when decompiling jump tables)

Forward (normal) decompilation[]

You decompile from the start of a function.

dec AJ_guess_get_DIGIC_time
return struct_0xc0242000.off_0x14 /*0xC0242014*/
!end
dec PrintRemconParam
*(-4 + sp0) = lr0
*(-8 + sp0) = unk_R4
TH_con_puts('\n[RemDriver] RemconParam\n', arg1, arg2, arg3) => ret_TH_con_puts_FF066D6C
TH_con_puts(' PulseWidthMin  : %4ld\n', remocon_struct.PulseWidthMin /*off_0x10, 0x2AA0*/, arg2, arg3) => ret_TH_con_puts_FF066D7C
TH_con_puts(' PulseWidthMax  : %4ld\n', remocon_struct.PulseWidthMax /*off_0x14, 0x2AA4*/, arg2, arg3) => ret_TH_con_puts_FF066D88
[...]
return 0
!end
dec RemOff_secret_mode_RemOn
*(-4 + sp0) = lr0
*(-8 + sp0) = unk_R4
RemOff() => ret_RemOff_FF07BF08
if arg0 != 0:
    if arg0 == 1:
        secret_mode(0x4, 0x14, 0x1, 0x2) => ret_secret_mode_FF07BF30
    
if arg0 == 0:
    secret_mode(0x4, 0x14, 0x1, 0x1) => ret_secret_mode_FF07BF30
RemOn() => ret_RemOn_FF07BF38
!end

Loops[]

The decompiler doesn't supoort loops, but it will usually handle the first iteration:

dec gui_main_task
*(-4 + sp0) = lr0
*(-8 + sp0) = unk_R5
*(-12 + sp0) = unk_R4
memcpy(-44 + sp0, GMT_FUNCTABLE, 0x20) => ret_memcpy_FF01FFA8
gui_init_end() => ret_gui_init_end_FF01FFAC
msg_queue_receive(gui_main_struct.msg_queue /*off_0x38, 0x1C3C*/, -48 + sp0, 0x0, arg3) => ret_msg_queue_receive_FF01FFC4
gui_main_struct.counter /*off_0x4, 0x1C08*/ = -1 + gui_main_struct.counter /*off_0x4, 0x1C08*/
[...]

Reverse decompilation[]

This is useful when normal decompilation fails (usually when you have to deal with huge monsters like IDLEHandler or AJ_CopyDataToStorage).

S PROP_SHUT

String references to ff2014d4 'PROP_SHUTTER_COUNTER [%d][%d]':

AJ_CopyDataToStorage+22892:
ff201390:	e28f2f4f 	add	r2, pc, #316	; *'PROP_SHUTTER_COUNTER [%d][%d]'
'PROP_SHUTTER_COUNTER [%d][%d]'

[...]
g ff201390
f201390:	e28f2f4f 	add	r2, pc, #316	; *'PROP_SHUTTER_COUNTER [%d][%d]'
ff201394:	e58d3000 	str	r3, [sp]
ff201398:	e5943004 	ldr	r3, [r4, #4]
ff20139c:	e3a01003 	mov	r1, #3
ff2013a0:	e3a00083 	mov	r0, #131	; 0x83
ff2013a4:	ebf99810 	bl	@DebugMsg	
[...]
bd ff2013a4
[...]
DebugMsg(132, 2, msg='copyDataToStorage eventID(%#x)Data(%d)size(%d)', *(arg0), arg0->off_0x8, arg3, unk_R4, unk_R5, ...)
if arg0 != 0:
    if *(arg0) <= 0x8005002D:
        if *(arg0) > 0x80030013:
            if *(arg0) <= 0x80040006:
                if *(arg0) <= PROP_HDMI_CHANGE:
                    if *(arg0) <= 0x80030029:
                        REGWRITE(PC, 4279483944 + 4**(arg0))
                        if EQ21(2147287020 + *(arg0)):
                            *(-40 + sp0) = arg0->off_0x8
                            DebugMsg(131, 3, msg='PROP_SHUTTER_COUNTER [%d][%d]', arg0->off_0x4, arg0->off_0x8, arg3, unk_R4, unk_R5, ...)
                            !!! Stack not restored !!!
                            !end
hex(21 - 2147287020)
'80030029'
#define PROP_SHUTTER_COUNTER 0x80030029 :)

Advanced use[]

cp = range(0xff31695c, 0xff316970+1, 4)
cp
[4281428316L, 4281428320L, 4281428324L, 4281428328L, 4281428332L, 4281428336L]
emusym.print_cp(cp)
CODE PATH:
ff31695c:	e5940008 	ldr	r0, [r4, #8]
ff316960:	e3500007 	cmp	r0, #7
ff316964:	83a020d3 	movhi	r2, #211	; 0xd3
ff316968:	828f1f55 	addhi	r1, pc, #340	; *'GUI\\ShootInfo\\DlgShootOlcAFFrame.c'
ff31696c:	828f0f5d 	addhi	r0, pc, #372	; 0xff316ae8: pointer to 0x30
ff316970:	8bf3f3a9 	blhi	@assert_0	
cp = emusym.add_branch_info(cp)
print deco.decompile(cp[0], [cp])
SEQ(IF(-7 + MEM(8 + unk_R4), IFB(HI, SEQ(CALL(4281428336, 4278269980, 4281428712, 4281428676, 211, arg3, arg4, arg5, arg6, arg7), !end))))
print emusym.P.doprint(deco.decompile(cp[0], [cp]))
if unk_R4->off_0x8 > 7:
    assert_0(0xff316ae8: pointer to 0x30, 'GUI\\ShootInfo\\DlgShootOlcAFFrame.c', 0xd3) => ret_assert_0_FF316970
    !end
Advertisement