带有 Ghidra 的 SuperH 反汇编中的奇怪 jsr 目标

逆向工程 固件 吉德拉 超级
2021-07-09 04:25:39

我是从使用 Hitachi SuperH-3 7706 处理器的旧采样器/groovebox 逆向工程固件,取得了很大进步。在 8M 左右的代码中,一切看起来和排列正确。然而,在一些地方我看到一些让我挠头的东西,我不确定发生了什么......

这个函数看起来很像另一个区域中的另一个函数,它最终调用 memcpy()。它的这个版本在函数的中间创建了一个 jsr (0x8C010D20),并且考虑到被填充到函数参数寄存器中的内容并没有多大意义(请参阅 0x80018e82 了解实际的 jsr)。而 0x400B 绝对是一个 jsr r0。

这里是调用者和被调用者的反汇编。我在这里错过了什么?

-- Caller --
                     **************************************************************
                     *                          FUNCTION                          *
                     **************************************************************
                     undefined __stdcall rom_copy_to_ram_maybe(int param_1)
     undefined         r0:1           <RETURN>
     int               r4:4           param_1
     undefined4        Stack[-0x4]:4  local_4                                 XREF[1]:     80018e70(*)
     undefined4        Stack[-0x8]:4  local_8                                 XREF[2]:     80018e72(*),
                                                                                           80018e88(*)
                     rom_copy_to_ram_maybe
80018e70 2f e6           mov.l      r14,@-r15=>local_4
80018e72 4f 22           sts.l      pr,@-r15=>local_8
80018e74 24 48           tst        param_1,param_1
80018e76 d5 06           mov.l      @(DAT_80018e90,pc),r5=>DAT_a0400000              = A0400000h
80018e78 8f 01           bf/s       LAB_80018e7e
80018e7a 6e f3           _mov       r15,r14
80018e7c d5 05           mov.l      @(DAT_80018e94,pc),r5=>SUB_a0000000              = A0000000h
                     LAB_80018e7e                                    XREF[1]:     80018e78(j)
80018e7e d0 06           mov.l      @(->FUN_8c010d20,pc),r0                          = 8c010d20
80018e80 d4 06           mov.l      @(PTR_DAT_80018e9c,pc),param_1=>DAT_8d800000     = 8d800000
80018e82 40 0b           jsr        @r0=>FUN_8c010d20                                TODO: this makes no sense... it'
80018e84 00 09           _nop
80018e86 6f e3           mov        r14,r15
80018e88 4f 26           lds.l      @r15=>local_8+,pr
80018e8a 00 0b           rts
80018e8c 6e f6           _mov.l     @r15+,r14
80018e8e 00 09           nop
                     DAT_80018e90                                    XREF[2]:     rom_copy_to_ram_maybe:80018e76(R
                                                                                  rom_copy_to_ram_maybe:80018e76(R
80018e90 a0 40 00 00     undefined4 A0400000h
                     DAT_80018e94                                    XREF[2]:     rom_copy_to_ram_maybe:80018e7c(R
                                                                                  rom_copy_to_ram_maybe:80018e7c(R
80018e94 a0 00 00 00     undefined4 A0000000h
                     PTR_FUN_80018e98                                XREF[2]:     rom_copy_to_ram_maybe:80018e7e(R
                                                                                  rom_copy_to_ram_maybe:80018e7e(R
80018e98 8c 01 0d 20     addr       FUN_8c010d20
                     PTR_DAT_80018e9c                                XREF[2]:     rom_copy_to_ram_maybe:80018e80(R
                                                                                  rom_copy_to_ram_maybe:80018e80(R
80018e9c 8d 80 00 00     addr       DAT_8d800000

-- Callee --
                     **************************************************************
                     *                          FUNCTION                          *
                     **************************************************************
                     uint __stdcall FUN_8c010d10(char param_1)
     uint              r0:4           <RETURN>
     char              r4:1           param_1
     undefined4        Stack[-0x4]:4  local_4                                 XREF[1]:     8c010d10(*)
                     FUN_8c010d10                                    XREF[4]:     8c010a82(c), 8c010b14(*),
                                                                                  8c010cec(c), 8c010d08(*)
8c010d10 2f e6           mov.l      r14,@-r15=>local_4
8c010d12 74 bf           add        -0x41,param_1
8c010d14 64 4c           extu.b     param_1,param_1
8c010d16 e1 19           mov        #0x19,r1
8c010d18 34 16           cmp/hi     r1,param_1
8c010d1a 8f 02           bf/s       LAB_8c010d22
8c010d1c 6e f3           _mov       r15,r14
8c010d1e a0 01           bra        LAB_8c010d24
                     **************************************************************
                     *                          FUNCTION                          *
                     **************************************************************
                     undefined FUN_8c010d20()
     undefined         r0:1           <RETURN>
                     FUN_8c010d20                                    XREF[2]:     rom_copy_to_ram_maybe:80018e82(c
                                                                                  80018e98(*)
8c010d20 e0 00           _mov       #0x0,r0
                     LAB_8c010d22                                    XREF[1]:     FUN_8c010d10:8c010d1a(j)
8c010d22 e0 01           mov        #0x1,r0
                     LAB_8c010d24                                    XREF[1]:     FUN_8c010d10:8c010d1e(j)
8c010d24 6f e3           mov        r14,r15
8c010d26 00 0b           rts
8c010d28 6e f6           _mov.l     @r15+,r14
8c010d2a 00 09           nop
8c010d2c 00 09           nop
8c010d2e 00 09           nop```
1个回答

我不是 100% 确定我读对了,但它似乎FUN_8c010d20执行了结语处理的一部分:

  1. 复制r14(帧指针)到r15(堆栈指针)
  2. r14从堆栈中弹出(保存?)并返回。

我不确定为什么这是在单独的函数而不是内联函数中完成的,但我怀疑这可能是由过度激进的“共享代码”优化(有时也称为反向内联)引起的,当编译器(或更常见的链接器)扫描时公共代码序列(尤其是在函数末尾)的二进制文件,并通过调用公共函数来替换它们以减少总代码大小。这可以节省大量的代码大小,但在这种情况下,它基本上用一个函数调用代替了两条指令,该函数调用本身占用更多空间(特别是如果我们添加 4 字节函数地址文字)。