字节码的编译执行的调试"/>
15 HelloWorld的字节码的编译执行的调试
前言
字节码里面隐藏了多少秘密, 呵呵 我们这里来以一个极简单的例子 来探索一下, 探索一下 基于解释执行的 相关细节
lldb 汇编调试的部分需要感谢朋友 "新加坡买买提", 去年 12 月份的时候花了一下午的时间不佞帮助我, 呵呵 本文的例子也是那个时候 编写的以及调试的, 不过 当时是 clion 里面也能进行 lldb 的调试, 命令行中也可以, 现在 clion 里面的 lldb 不知道为啥不能调试了 ...
测试用例
package com.hx.test02;/*** TemplateInterpreter** @author Jerry.X.He <970655147@qq>* @version 1.0* @date 2019-12-08 13:36*/
public class Test23TemplateInterpreter {public static void main(String[] args) {// System.gc();int x = 1;}}
对应的字节码的相关信息如下, 一下可能会用于参照
master:classes jerry$ javap -c com/hx/test02/Test23TemplateInterpreter.class
Compiled from "Test23TemplateInterpreter.java"
public class com.hx.test02.Test23TemplateInterpreter {public com.hx.test02.Test23TemplateInterpreter();Code:0: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnpublic static void main(java.lang.String[]);Code:0: iconst_11: istore_12: return
}
基于 lldb 的调试
(lldb) p _active_table._table[9][4]
(address) $1 = 0x0000000105830e1f "?\x01"
(lldb) p _active_table._table[9][60]
(address) $2 = 0x0000000105833aa0 "\x8b\x04$H\x83\U00000088A\x89F?A\x0f?]\x01I??I?p?0\x04\x01"
(lldb) b 0x0000000105830e1f
Breakpoint 3: address = 0x0000000105830e1f
(lldb) b 0x0000000105833aa0
Breakpoint 4: address = 0x0000000105833aa0
// iconst_1
(lldb) c
Process 3086 resuming
Process 3086 stopped
* thread #5, stop reason = breakpoint 3.1frame #0: 0x0000000105830e1f
-> 0x105830e1f: movl $0x1, %eax0x105830e24: movzbl 0x1(%r13), %ebx0x105830e29: incq %r130x105830e2c: movabsq $0x104308a70, %r10 ; imm = 0x104308A70
Target 0: (java) stopped.
(lldb) stepi
Process 3086 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105830e24
-> 0x105830e24: movzbl 0x1(%r13), %ebx0x105830e29: incq %r130x105830e2c: movabsq $0x104308a70, %r10 ; imm = 0x104308A70 0x105830e36: jmpq *(%r10,%rbx,8)
Target 0: (java) stopped.
(lldb) stepi
Process 3086 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105830e29
-> 0x105830e29: incq %r130x105830e2c: movabsq $0x104308a70, %r10 ; imm = 0x104308A70 0x105830e36: jmpq *(%r10,%rbx,8)0x105830e3a: nop
Target 0: (java) stopped.
(lldb) stepi
Process 3086 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105830e2c
-> 0x105830e2c: movabsq $0x104308a70, %r10 ; imm = 0x104308A70 0x105830e36: jmpq *(%r10,%rbx,8)0x105830e3a: nop 0x105830e3b: nop
Target 0: (java) stopped.
(lldb) stepi
Process 3086 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105830e36
-> 0x105830e36: jmpq *(%r10,%rbx,8)0x105830e3a: nop 0x105830e3b: nop 0x105830e3c: nop
Target 0: (java) stopped.// istore_1
(lldb) c
Process 3086 resuming
Process 3086 stopped
* thread #5, stop reason = breakpoint 4.1frame #0: 0x0000000105833aa0
-> 0x105833aa0: movl (%rsp), %eax0x105833aa3: addq $0x8, %rsp0x105833aa7: movl %eax, -0x8(%r14)0x105833aab: movzbl 0x1(%r13), %ebx
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:rax = 0x0000000000000000rbx = 0x000000000000003crcx = 0x0000000000006a00rdx = 0x0000000000006a00rdi = 0x0000000105005000rsi = 0x0000000000000008rbp = 0x0000700009d05690rsp = 0x0000700009d05640r8 = 0x0000000000000000r9 = 0x0000000100611890r10 = 0x0000000104306270 libjvm.dylib`TemplateInterpreter::_normal_table + 18432r11 = 0x000000010061188cr12 = 0x0000000000000000r13 = 0x000000011c7ede61r14 = 0x0000700009d056a8r15 = 0x0000000105005000rip = 0x0000000105833aa0rflags = 0x0000000000000246cs = 0x000000000000002bfs = 0x0000000000000000gs = 0x0000000000000000(lldb) stepi
Process 3086 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105833aa3
-> 0x105833aa3: addq $0x8, %rsp0x105833aa7: movl %eax, -0x8(%r14)0x105833aab: movzbl 0x1(%r13), %ebx0x105833ab0: incq %r13
Target 0: (java) stopped.
(lldb) re r
General Purpose Registers:rax = 0x0000000000000001rbx = 0x000000000000003crcx = 0x0000000000006a00rdx = 0x0000000000006a00rdi = 0x0000000105005000rsi = 0x0000000000000008rbp = 0x0000700009d05690rsp = 0x0000700009d05640r8 = 0x0000000000000000r9 = 0x0000000100611890r10 = 0x0000000104306270 libjvm.dylib`TemplateInterpreter::_normal_table + 18432r11 = 0x000000010061188cr12 = 0x0000000000000000r13 = 0x000000011c7ede61r14 = 0x0000700009d056a8r15 = 0x0000000105005000rip = 0x0000000105833aa3rflags = 0x0000000000000246cs = 0x000000000000002bfs = 0x0000000000000000gs = 0x0000000000000000(lldb) stepi
Process 3086 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105833aa7
-> 0x105833aa7: movl %eax, -0x8(%r14)0x105833aab: movzbl 0x1(%r13), %ebx0x105833ab0: incq %r130x105833ab3: movabsq $0x10430b270, %r10 ; imm = 0x10430B270
Target 0: (java) stopped.
(lldb) x 0x0000700009d05640 -c 0x100
0x700009d05640: 01 00 00 00 00 00 00 00 48 56 d0 09 00 70 00 00 ........HV?..p..
0x700009d05650: 61 de 7e 1c 01 00 00 00 a8 56 d0 09 00 70 00 00 a?~.....?V?..p..
0x700009d05660: e0 de 7e 1c 01 00 00 00 00 00 00 00 00 00 00 00 ??~.............
0x700009d05670: d0 7f bb 47 07 00 00 00 88 de 7e 1c 01 00 00 00 ?.?G.....?~.....
0x700009d05680: 00 00 00 00 00 00 00 00 a8 56 d0 09 00 70 00 00 ........?V?..p..
0x700009d05690: 10 57 d0 09 00 70 00 00 f1 09 80 05 01 00 00 00 .W?..p..?.......
0x700009d056a0: 00 00 00 00 00 00 00 00 88 83 bb 47 07 00 00 00 ..........?G....
0x700009d056b0: a0 1f 00 00 03 00 00 00 00 00 00 00 00 00 00 00 ?...............
0x700009d056c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x700009d056d0: 00 00 00 00 00 00 00 00 00 60 d0 09 00 70 00 00 .........`?..p..
0x700009d056e0: 20 58 d0 09 00 70 00 00 50 5d d0 09 00 70 00 00 X?..p..P]?..p..
0x700009d056f0: 0a 00 00 00 00 70 00 00 88 de 7e 1c 01 00 00 00 .....p...?~.....
0x700009d05700: 00 a7 82 05 01 00 00 00 a0 5a d0 09 00 70 00 00 .?......?Z?..p..
0x700009d05710: e0 58 d0 09 00 70 00 00 1d bb 8e 03 01 00 00 00 ?X?..p...?......
0x700009d05720: 01 00 00 00 00 70 00 00 00 50 00 05 01 00 00 00 .....p...P......
0x700009d05730: 50 57 d0 09 00 70 00 00 15 95 28 03 01 00 00 00 PW?..p....(.....
(lldb) stepi
Process 3086 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105833aab
-> 0x105833aab: movzbl 0x1(%r13), %ebx0x105833ab0: incq %r130x105833ab3: movabsq $0x10430b270, %r10 ; imm = 0x10430B270 0x105833abd: jmpq *(%r10,%rbx,8)
Target 0: (java) stopped.
(lldb) x 0x0000700009d05640 -c 0x100
0x700009d05640: 01 00 00 00 00 00 00 00 48 56 d0 09 00 70 00 00 ........HV?..p..
0x700009d05650: 61 de 7e 1c 01 00 00 00 a8 56 d0 09 00 70 00 00 a?~.....?V?..p..
0x700009d05660: e0 de 7e 1c 01 00 00 00 00 00 00 00 00 00 00 00 ??~.............
0x700009d05670: d0 7f bb 47 07 00 00 00 88 de 7e 1c 01 00 00 00 ?.?G.....?~.....
0x700009d05680: 00 00 00 00 00 00 00 00 a8 56 d0 09 00 70 00 00 ........?V?..p..
0x700009d05690: 10 57 d0 09 00 70 00 00 f1 09 80 05 01 00 00 00 .W?..p..?.......
0x700009d056a0: 01 00 00 00 00 00 00 00 88 83 bb 47 07 00 00 00 ..........?G....
0x700009d056b0: a0 1f 00 00 03 00 00 00 00 00 00 00 00 00 00 00 ?...............
0x700009d056c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x700009d056d0: 00 00 00 00 00 00 00 00 00 60 d0 09 00 70 00 00 .........`?..p..
0x700009d056e0: 20 58 d0 09 00 70 00 00 50 5d d0 09 00 70 00 00 X?..p..P]?..p..
0x700009d056f0: 0a 00 00 00 00 70 00 00 88 de 7e 1c 01 00 00 00 .....p...?~.....
0x700009d05700: 00 a7 82 05 01 00 00 00 a0 5a d0 09 00 70 00 00 .?......?Z?..p..
0x700009d05710: e0 58 d0 09 00 70 00 00 1d bb 8e 03 01 00 00 00 ?X?..p...?......
0x700009d05720: 01 00 00 00 00 70 00 00 00 50 00 05 01 00 00 00 .....p...P......
0x700009d05730: 50 57 d0 09 00 70 00 00 15 95 28 03 01 00 00 00 PW?..p....(.....
(lldb) stepi
Process 3086 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105833ab0
-> 0x105833ab0: incq %r130x105833ab3: movabsq $0x10430b270, %r10 ; imm = 0x10430B270 0x105833abd: jmpq *(%r10,%rbx,8)0x105833ac1: nop
Target 0: (java) stopped.
(lldb) stepi
Process 3086 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105833ab3
-> 0x105833ab3: movabsq $0x10430b270, %r10 ; imm = 0x10430B270 0x105833abd: jmpq *(%r10,%rbx,8)0x105833ac1: nop 0x105833ac2: nop
Target 0: (java) stopped.
(lldb) stepi
Process 3086 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105833abd
-> 0x105833abd: jmpq *(%r10,%rbx,8)0x105833ac1: nop 0x105833ac2: nop 0x105833ac3: nop
Target 0: (java) stopped.
(lldb)
其中 0x700009d056a0 对应的数据对应的是 slot1[变量x]
可以看到这里的 iconst_1, istore_1 的大致的流程, 然后 如何存放到 slot1 里面的
这里有一个问题就是 0x105833aa0 的地方直接使用了 栈顶的数据 放到 rax 然后进行之后的业务操作
但是 在 iconst_1 的相关代码里面么有看到 将 rax 存入 stack 的过程(这个 push rax 在后面)
字节码执行之间中插的代码?
在 iconst_1 和 istore_1 之间, 还执行了如下一段代码, 呵呵 有些地方看的明白, 大部分地方看不明白, 先放在这里吧, 后面 有一定的了解之后再来解惑
(lldb) dis -s 0x105825f24 -c 200// push rax, 将1入表达式栈(这里的场景)0x105825f24: pushq %rax// MacroAssembler::call_VM_helper0x105825f25: callq 0x105825f2f0x105825f2a: jmp 0x1058261850x105825f2f: leaq 0x8(%rsp), %rax// save_bcp0x105825f34: movq %r13, -0x40(%rbp)// cmpptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD)0x105825f38: cmpq $0x0, -0x10(%rbp)0x105825f40: je 0x105825fbd// ignore MacroAssembler::debug64// 擦 这里对应的是哪里 0x105825fbd: pushq %r100x105825fbf: cmpq -0x150f9d6(%rip), %r12 ; Universe::_narrow_ptrs_base0x105825fc6: je 0x105826043// ignore MacroAssembler::debug640x105826043: popq %r10// LP64_ONLY(mov(c_rarg0, r15_thread))0x105826045: movq %r15, %rdi// set_last_Java_frame(java_thread, last_java_sp, rbp, NULL);0x105826048: movq %rbp, 0x218(%r15)0x10582604f: movq %rax, 0x208(%r15)// MacroAssembler::call_VM_leaf_base(entry_point, number_of_arguments); 0x105826056: testl $0xf, %esp0x10582605c: je 0x1058260740x105826062: subq $0x8, %rsp0x105826066: callq 0x1038d5ac0 ; InterpreterRuntime::at_safepoint at interpreterRuntime.cpp:10500x10582606b: addq $0x8, %rsp0x10582606f: jmp 0x1058260790x105826074: callq 0x1038d5ac0 ; InterpreterRuntime::at_safepoint at interpreterRuntime.cpp:1050// get_thread(java_thread);0x105826079: pushq %rax0x10582607a: pushq %rdi0x10582607b: pushq %rsi0x10582607c: pushq %rdx0x10582607d: pushq %rcx0x10582607e: pushq %r80x105826080: pushq %r90x105826082: pushq %r100x105826084: pushq %r110x105826086: testl $0xf, %esp0x10582608c: je 0x1058260a40x105826092: subq $0x8, %rsp0x105826096: callq 0x103003ae0 ; Thread::current at thread.hpp:6600x10582609b: addq $0x8, %rsp0x10582609f: jmp 0x1058260a90x1058260a4: callq 0x103003ae0 ; Thread::current at thread.hpp:6600x1058260a9: popq %r110x1058260ab: popq %r100x1058260ad: popq %r90x1058260af: popq %r80x1058260b1: popq %rcx0x1058260b2: popq %rdx0x1058260b3: popq %rsi0x1058260b4: popq %rdi0x1058260b5: cmpq %rax, %r150x1058260b8: je 0x105826135// ignore MacroAssembler::debug640x105826135: popq %rax// reset_last_Java_frame(java_thread, true);0x105826136: movabsq $0x0, %r100x105826140: movq %r10, 0x208(%r15)0x105826147: movabsq $0x0, %r100x105826151: movq %r10, 0x218(%r15)0x105826158: movabsq $0x0, %r100x105826162: movq %r10, 0x210(%r15)// check_exceptions0x105826169: cmpq $0x0, 0x8(%r15)0x105826171: je 0x10582617c0x105826177: jmp 0x1058007a0// restore_bcp();0x10582617c: movq -0x40(%rbp), %r13// restore_locals();0x105826180: movq -0x38(%rbp), %r140x105826184: retq// dispatch 下一条指令 0x105826185: movzbl (%r13), %ebx0x10582618a: movabsq $0x104306270, %r10 ; imm = 0x1043062700x105826194: jmpq *(%r10,%rbx,8)
这块代码 主要的目的是调用 InterpreterRuntime::at_safepoint
生成上面这段汇编的核心代码 似乎是来自于这里, 传入的 entry_point 是 InterpreterRuntime::at_safepoint 的 entry_point
呵呵 先留在这里不求甚解吧
另外还有一个现象是, 这断代码 核心调用的是 InterpreterRuntime::at_safepoint 在 lldb 命令行里面调试的时候, 你会清楚的看到 会执行这段代码, 但是 在 clion 里面调试的时候 打上一个断点, 却不会执行, 这个是和 什么时候调试 有一定的关系么 ?
这部分中插代码再记录 add at 2020.06.06
======================= add at 2020.06.06 =======================
今天又重新调试了一下 这个例子, 呵呵 发现了一点 之前调试记录的不同的东西
呵呵, 有些时候 没有去 调用 InterpreterRuntime::at_safepoint
直接按照 字节码模板 的调度过程去进行执行了, 直接以 ax 作为媒介来传递了数据
(lldb) p _active_table._table[9][4]
(address) $1 = 0x0000000105830e1f "?\x01"
(lldb) b 0x0000000105830e1f
Breakpoint 3: address = 0x0000000105830e1f// iconst_1
(lldb) c
Process 3326 resuming
Process 3326 stopped
* thread #5, stop reason = breakpoint 3.1frame #0: 0x0000000105830e1f
-> 0x105830e1f: movl $0x1, %eax0x105830e24: movzbl 0x1(%r13), %ebx0x105830e29: incq %r130x105830e2c: movabsq $0x103b08a70, %r10 ; imm = 0x103B08A70
Target 0: (java) stopped.
(lldb) stepi
Process 3326 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105830e24
-> 0x105830e24: movzbl 0x1(%r13), %ebx0x105830e29: incq %r130x105830e2c: movabsq $0x103b08a70, %r10 ; imm = 0x103B08A700x105830e36: jmpq *(%r10,%rbx,8)
Target 0: (java) stopped.
(lldb) stepi
Process 3326 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105830e29
-> 0x105830e29: incq %r130x105830e2c: movabsq $0x103b08a70, %r10 ; imm = 0x103B08A700x105830e36: jmpq *(%r10,%rbx,8)0x105830e3a: nop
Target 0: (java) stopped.
(lldb) stepi
Process 3326 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105830e2c
-> 0x105830e2c: movabsq $0x103b08a70, %r10 ; imm = 0x103B08A700x105830e36: jmpq *(%r10,%rbx,8)0x105830e3a: nop0x105830e3b: nop
Target 0: (java) stopped.
(lldb) stepi
Process 3326 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105830e36
-> 0x105830e36: jmpq *(%r10,%rbx,8)0x105830e3a: nop0x105830e3b: nop0x105830e3c: nop
Target 0: (java) stopped.// istore_1
(lldb) stepi
Process 3326 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105833aa7
-> 0x105833aa7: movl %eax, -0x8(%r14)0x105833aab: movzbl 0x1(%r13), %ebx0x105833ab0: incq %r130x105833ab3: movabsq $0x103b0b270, %r10 ; imm = 0x103B0B270
Target 0: (java) stopped.
(lldb) stepi
Process 3326 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105833aab
-> 0x105833aab: movzbl 0x1(%r13), %ebx0x105833ab0: incq %r130x105833ab3: movabsq $0x103b0b270, %r10 ; imm = 0x103B0B2700x105833abd: jmpq *(%r10,%rbx,8)
Target 0: (java) stopped.
(lldb) stepi
Process 3326 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105833ab0
-> 0x105833ab0: incq %r130x105833ab3: movabsq $0x103b0b270, %r10 ; imm = 0x103B0B2700x105833abd: jmpq *(%r10,%rbx,8)0x105833ac1: nop
Target 0: (java) stopped.
(lldb) stepi
Process 3326 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105833ab3
-> 0x105833ab3: movabsq $0x103b0b270, %r10 ; imm = 0x103B0B2700x105833abd: jmpq *(%r10,%rbx,8)0x105833ac1: nop0x105833ac2: nop
Target 0: (java) stopped.
(lldb) stepi
Process 3326 stopped
* thread #5, stop reason = instruction step intoframe #0: 0x0000000105833abd
-> 0x105833abd: jmpq *(%r10,%rbx,8)0x105833ac1: nop0x105833ac2: nop0x105833ac3: nop
Target 0: (java) stopped.
呵呵 上面的 字节码执行之间中插的代码 来自于
以上两种情况对应于 active_table 为 normal_table 或者 切换为 safept_table 的情况, 呵呵 但是什么情况下切换, 目前我还不明白
active_table 为 normal_table 的场景
(lldb) p _active_table._table[9][194]
(address) $0 = 0x000000010604f980 "XH;"
(lldb) p _active_table._table[0][0]
(address) $1 = 0x0000000106030b9e "PA\x0f\xb6]\x01I??I\xbap\xb2\xb0\x03\x01"
(lldb) p _normal_table._table[0][0]
(address) $2 = 0x0000000106030b9e "PA\x0f\xb6]\x01I??I\xbap\xb2\xb0\x03\x01"
(lldb) p _safept_table._table[0][0]
(address) $3 = 0x00000001060252e0 "P?
(lldb) p _active_table._table[9][4]
(address) $4 = 0x0000000106030e1f "\xb8\x01"
(lldb) b 0x0000000106030e1f
Breakpoint 3: address = 0x0000000106030e1f
(lldb) c
Process 3783 resuming
Process 3783 stopped
* thread #5, stop reason = breakpoint 3.1frame #0: 0x0000000106030e1f
-> 0x106030e1f: movl $0x1, %eax0x106030e24: movzbl 0x1(%r13), %ebx0x106030e29: incq %r130x106030e2c: movabsq $0x103b08a70, %r10 ; imm = 0x103B08A70
Target 0: (java) stopped.
(lldb) p _active_table._table[0][0]
(address) $5 = 0x0000000106030b9e "PA\x0f?]\x01I??I?p??\x03\x01"
active_table 为 safept_table 的场景
(lldb) p _active_table._table[9][194]
(address) $0 = 0x000000010584f980 "XH;"
(lldb) p _active_table._table[0][0]
(address) $1 = 0x0000000105830b9e "PA\x0f\xb6]\x01I??I\xbap\xb20\x04\x01"
(lldb) p _normal_table._table[0][0]
(address) $2 = 0x0000000105830b9e "PA\x0f\xb6]\x01I??I\xbap\xb20\x04\x01"
(lldb) p _safept_table._table[0][0]
(address) $3 = 0x00000001058252e0 "P?
(lldb) p _active_table._table[9][4]
(address) $4 = 0x0000000105830e1f "?\x01"
(lldb) b 0x0000000105830e1f
Breakpoint 3: address = 0x0000000105830e1f
(lldb) c
Process 3646 resuming
Process 3646 stopped
* thread #5, stop reason = breakpoint 3.1frame #0: 0x0000000105830e1f
-> 0x105830e1f: movl $0x1, %eax0x105830e24: movzbl 0x1(%r13), %ebx0x105830e29: incq %r130x105830e2c: movabsq $0x104308a70, %r10 ; imm = 0x104308A70
Target 0: (java) stopped.
(lldb) p _active_table._table[0][0]
(address) $5 = 0x00000001058252e0 "P?
完
更多推荐
15 HelloWorld的字节码的编译执行的调试
发布评论