替换.so文件中的函数

时间:2014-03-11 12:30:15

标签: android gcc java-native-interface arm shared-libraries

WHY: 我有一个三方Android共享库(没有源代码),libxyz.so,而dalvik vm说JNI_OnLoad returned bad version (-1) in filepath 。我假设vm是正确的,并且该函数确实返回了这个错误的值而不是有效的值。 (据我所知,直到现在这被忽略了,因为在AndroidManifest.xml中debuggable设置为true。)

我如何用另一个.so库中的函数替换.so库中的函数?

(不确定我是否必须调用旧函数,在一般情况下是的,在我的情况下可能没有,但是如何调用旧函数的建议也将受到赞赏。)

00023da0 <JNI_OnLoad>:
   23da0:   e52de004    push    {lr}        ; (str lr, [sp, #-4]!)
   23da4:   e59f3094    ldr r3, [pc, #148]  ; 23e40 <JNI_OnLoad+0xa0>
   23da8:   e24dd00c    sub sp, sp, #12
   23dac:   e28d1008    add r1, sp, #8
   23db0:   e3a02000    mov r2, #0
   23db4:   e5212004    str r2, [r1, #-4]!
   23db8:   e08f3003    add r3, pc, r3
   23dbc:   e3a02801    mov r2, #65536  ; 0x10000
   23dc0:   e583000c    str r0, [r3, #12]
   23dc4:   e2822004    add r2, r2, #4
   23dc8:   e5903000    ldr r3, [r0]
   23dcc:   e1a0e00f    mov lr, pc
   23dd0:   e593f018    ldr pc, [r3, #24]
   23dd4:   e3500000    cmp r0, #0
   23dd8:   0a000002    beq 23de8 <JNI_OnLoad+0x48>
   23ddc:   e3e00000    mvn r0, #0
   23de0:   e28dd00c    add sp, sp, #12
   23de4:   e8bd8000    pop {pc}
   23de8:   e59d3004    ldr r3, [sp, #4]
   23dec:   e59f2050    ldr r2, [pc, #80]   ; 23e44 <JNI_OnLoad+0xa4>
   23df0:   e1a00003    mov r0, r3
   23df4:   e79f1002    ldr r1, [pc, r2]
   23df8:   e5933000    ldr r3, [r3]
   23dfc:   e1a0e00f    mov lr, pc
   23e00:   e593f018    ldr pc, [r3, #24]
   23e04:   e2501000    subs    r1, r0, #0
   23e08:   0afffff3    beq 23ddc <JNI_OnLoad+0x3c>
   23e0c:   e59d3004    ldr r3, [sp, #4]
   23e10:   e59f2030    ldr r2, [pc, #48]   ; 23e48 <JNI_OnLoad+0xa8>
   23e14:   e1a00003    mov r0, r3
   23e18:   e593c000    ldr ip, [r3]
   23e1c:   e08f2002    add r2, pc, r2
   23e20:   e3a03033    mov r3, #51 ; 0x33
   23e24:   e1a0e00f    mov lr, pc
   23e28:   e59cf35c    ldr pc, [ip, #860]  ; 0x35c
   23e2c:   e3500000    cmp r0, #0
   23e30:   a3a00801    movge   r0, #65536  ; 0x10000
   23e34:   a2800004    addge   r0, r0, #4
   23e38:   aaffffe8    bge 23de0 <JNI_OnLoad+0x40>
   23e3c:   eaffffe6    b   23ddc <JNI_OnLoad+0x3c>
   23e40:   00103d6c    andseq  r3, r0, ip, ror #26
   23e44:   00103204    andseq  r3, r0, r4, lsl #4
   23e48:   00103a84    andseq  r3, r0, r4, lsl #21

2 个答案:

答案 0 :(得分:0)

它是什么:

由于 @auselen 绝对正确写入,该函数无法初始化,因此返回-1。也就是说,它需要通过名称访问包含本机函数的类的一些内部类。

我使用了以下proguard法术:

-keep public class com.xyz.abc.XYZ
-keepclassmembers class com.xyz.adc.XYZ { *; }
-keep class com.xyz.abc.XYZ$* { *; }

非常感谢 @auselen

编辑:同时,我再一次面临这样的问题。 objcopy--redefine-sym,但是为什么它对我不起作用。

答案 1 :(得分:0)

虽然在一个案例中我可以避免解决这个问题,但我再次面对它了。

这是我到目前为止所做的:

objcopy --rename-sym不适用于.so。 (至少现在是2014年。)

System.loadLibrary()调用System.load()JNI_OnLoad()也不起作用(这些库报告为已加载到日志中,但它们的符号未显示),我没有尝试修复它

但你可以 make two native shared libraries calling each other,所以你可以创建一个额外的库来定义感兴趣的函数,你(EDIT1 :)可以rename that function in the original binary library(你必须保留哈希函数值),但你必须加载() loadLibrary()来自Java的新库。

EDIT2:

现在,我们如何扩展调用库的依赖列表?我们没有。在调用库的导入列表中,您可以找到可以重新编译和扩展的库,并在该库中定义重命名函数的新版本。如果在依赖项列表中更改(就地)库名称,则无需关心哈希函数和存储桶。