通过JNI使用C和Java并进行SetObjectArrayElement调用,并运行一些测试来回答一些相关的gdb问题。
这是C语言中使用的JNI调用。
(*env)->SetObjectArrayElement(env, objArray, (jsize)i, obj1);
该代码导致了内核,并且在反汇编代码后显示mov命令失败。
Dump of assembler code for function jni_SetObjectArrayElement:
0x00002b514569f510 <+0>: push %rbp
0x00002b514569f511 <+1>: mov %rsp,%rbp
0x00002b514569f514 <+4>: push %r15
0x00002b514569f516 <+6>: mov %rsi,%r15
0x00002b514569f519 <+9>: push %r14
0x00002b514569f51b <+11>: mov %rdi,%r14
0x00002b514569f51e <+14>: push %r13
0x00002b514569f520 <+16>: mov %rcx,%r13
0x00002b514569f523 <+19>: push %r12
0x00002b514569f525 <+21>: mov %edx,%r12d
0x00002b514569f528 <+24>: push %rbx
0x00002b514569f529 <+25>: lea -0x258(%rdi),%rbx
0x00002b514569f530 <+32>: sub $0x48,%rsp
0x00002b514569f534 <+36>: mov %fs:0x28,%rax
0x00002b514569f53d <+45>: mov %rax,-0x38(%rbp)
0x00002b514569f541 <+49>: xor %eax,%eax
0x00002b514569f543 <+51>: mov 0x2e8(%rbx),%eax
0x00002b514569f549 <+57>: cmp $0xdeab,%eax
0x00002b514569f54e <+62>: je 0x2b514569f567 <jni_SetObjectArrayElement+87>
0x00002b514569f550 <+64>: mov 0x2e8(%rbx),%eax
0x00002b514569f556 <+70>: cmp $0xdeac,%eax
0x00002b514569f55b <+75>: je 0x2b514569f567 <jni_SetObjectArrayElement+87>
0x00002b514569f55d <+77>: mov %rbx,%rdi
0x00002b514569f560 <+80>: xor %ebx,%ebx
0x00002b514569f562 <+82>: callq 0x2b5145a740f0 <_ZN10JavaThread18block_if_vm_exitedEv>
0x00002b514569f567 <+87>: mov %rbx,%rdi
0x00002b514569f56a <+90>: callq 0x2b5145691bb0 <_ZN21ThreadStateTransition22transition_from_nativeEP10JavaThread15JavaThreadState.constprop.220>
0x00002b514569f56f <+95>: cmpq $0x0,0x8(%rbx)
0x00002b514569f574 <+100>: mov %rbx,-0x70(%rbp)
0x00002b514569f578 <+104>: movq $0x0,-0x68(%rbp)
0x00002b514569f580 <+112>: je 0x2b514569f58b <jni_SetObjectArrayElement+123>
0x00002b514569f582 <+114>: lea -0x70(%rbp),%rdi
0x00002b514569f586 <+118>: callq 0x2b514591bf90 <_ZN25WeakPreserveExceptionMark8preserveEv>
0x00002b514569f58b <+123>: nop
0x00002b514569f58c <+124>: test %r13,%r13
=> 0x00002b514569f58f <+127>: mov (%r15),%r14 <-----Fails here
0x00002b514569f592 <+130>: je 0x2b514569f700 <jni_SetObjectArrayElement+496>
0x00002b514569f598 <+136>: mov 0x0(%r13),%r13
0x00002b514569f59c <+140>: test %r12d,%r12d
0x00002b514569f59f <+143>: js 0x2b514569f638 <jni_SetObjectArrayElement+296>
0x00002b514569f5a5 <+149>: lea 0x928397(%rip),%rax # 0x2b5145fc7943
0x00002b514569f5ac <+156>: movzbl (%rax),%edx
“ info reg”命令将r15显示为NULL值。
(gdb) info reg
rax 0x2b5145afa808 47628061485064
rbx 0x2b54538d2800 47641179006976
rcx 0x2b5424000a30 47640381229616
rdx 0x2b5424018c30 47640381328432
rsi 0x0 0
rdi 0x2b54538d2800 47641179006976
rbp 0x2b51935ed890 0x2b51935ed890
rsp 0x2b51935ed820 0x2b51935ed820
r8 0xf497fc9c 4103601308
r9 0x2b51480606f8 47628100699896
r10 0x398 920
r11 0x206 518
r12 0x0 0
r13 0x2b5424000a30 47640381229616
r14 0x2b54538d2a58 47641179007576
r15 0x0 0 <---------NULL
rip 0x2b514569f58f 0x2b514569f58f <jni_SetObjectArrayElement+127>
eflags 0x206 [ PF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
仅根据提供的信息,如何确定哪个参数实际上为NULL?
“(* env)-> SetObjectArrayElement(env,objArray,(jsize)i,obj1)”调用返回一个空值并传入4个参数。
查看jni_SetObjectArrayElement的汇编代码,可以安全地假设前4个“ mov”命令将4个参数移动到寄存器中了吗?
另一个mov命令在做什么?
0x00002b514569f510 <+0>: push %rbp
0x00002b514569f511 <+1>: mov %rsp,%rbp <------Parameter env?
0x00002b514569f514 <+4>: push %r15
0x00002b514569f516 <+6>: mov %rsi,%r15 <------Parameter objArray?
0x00002b514569f519 <+9>: push %r14
0x00002b514569f51b <+11>: mov %rdi,%r14 <------Parameter i?
0x00002b514569f51e <+14>: push %r13
0x00002b514569f520 <+16>: mov %rcx,%r13 <------Parameter obj1?
0x00002b514569f523 <+19>: push %r12
0x00002b514569f525 <+21>: mov %edx,%r12d <----What is this one for?
0x00002b514569f528 <+24>: push %rbx
0x00002b514569f529 <+25>: lea -0x258(%rdi),%rbx
0x00002b514569f530 <+32>: sub $0x48,%rsp
我在另一种情况下运行了该代码,jni_SetObjectArrayElement的汇编代码实际上显示了以下4个mov命令,而不是上面显示的5个。为什么会这样?
Dump of assembler code for function jni_SetObjectArrayElement:
0x00002b1c85caa2d0 <+0>: push %rbp
0x00002b1c85caa2d1 <+1>: mov %rsp,%rbp
0x00002b1c85caa2d4 <+4>: push %r15
0x00002b1c85caa2d6 <+6>: mov %rsi,%r15
0x00002b1c85caa2d9 <+9>: push %r14
0x00002b1c85caa2db <+11>: mov %rdi,%r14
0x00002b1c85caa2de <+14>: push %r13
0x00002b1c85caa2e0 <+16>: mov %rcx,%r13
0x00002b1c85caa2e3 <+19>: push %r12
0x00002b1c85caa2e5 <+21>: movslq %edx,%r12
0x00002b1c85caa2e8 <+24>: push %rbx
基于以下评论,我相信这是正确的参考……也许。
0x00002b514569f510 <+0>: push %rbp
0x00002b514569f511 <+1>: mov %rsp,%rbp
0x00002b514569f514 <+4>: push %r15
0x00002b514569f516 <+6>: mov %rsi,%r15 <------Parameter env?
0x00002b514569f519 <+9>: push %r14
0x00002b514569f51b <+11>: mov %rdi,%r14 <------Parameter objArray?
0x00002b514569f51e <+14>: push %r13
0x00002b514569f520 <+16>: mov %rcx,%r13 <------Parameter i?
0x00002b514569f523 <+19>: push %r12
0x00002b514569f525 <+21>: mov %edx,%r12d <----Parameter obj1 (address in low order bytes)
0x00002b514569f528 <+24>: push %rbx
0x00002b514569f529 <+25>: lea -0x258(%rdi),%rbx
0x00002b514569f530 <+32>: sub $0x48,%rsp