Bug fix: JVM crashes when running with -Xdebug option

Shanyao Chen shanyao.chen at linaro.org
Thu Dec 31 10:35:44 UTC 2015


hi,all:
     There is a bug in jdk9 aarch32 when using jdb. And it is
described as belowing:

When running any case by the following command,
    java -Xdebug
-Xrunjdwp:transport=dt_socket,address=localhost:8787,server=y,suspend=y
test
the jvm throws an error message "registers must be different: a=" r2
", b=" r0", c=" r0""

This is because in TemplateTable::jvmti_post_field_mod(Register cache,
Register index, bool is_static),there is an
assertion,assert_different_registers(cache, index, r0),and in
TemplateTable::putfield_or_static(int byte_no, bool is_static),passes
r0 as the argument index when it calls jvmti_post_field_mod. However
index and r0 should be different.

/******************code start****************/
void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
    transition(vtos, vtos);
    const Register cache = r2;
    const Register index = r0;
    ...
    jvmti_post_field_mod(cache, index, is_static);
/******************code end******************/

To fix this problem, it's safe to use rscratch1 as the register index
here. Then the jvm can start with -Xdebug, however,there is another
problem when using jdb.

/****command start****/
$ jdb -attach 127.0.0.1:8787
$ stop in test.main
$ run
/*****command end*****/

Everything is ok until here, the test case stop in main correctly.
However, if you send "next" or "continue" from the breakpoint,then the
jvm will crash by SIGSEGV in TemplateTable::_breakpoint()

/******************code start****************/
void TemplateTable::_breakpoint() {
                 ...
    __ call_VM(noreg,
               CAST_FROM_FN_PTR(address,
InterpreterRuntime::get_original_bytecode_at),
               c_rarg1, rbcp);
    __ mov(r3, r0);

    // post the breakpoint event
    __ call_VM(noreg,
               CAST_FROM_FN_PTR(address, InterpreterRuntime::_breakpoint),
               rmethod, rbcp);

    // complete the execution of original bytecode
    __ mov(rscratch1, r3);
    __ dispatch_only_normal(vtos);
}
/******************code end******************/

After getting the unpatched byte code, r0 is saved to r3 by __ mov(r3,
r0), and is restored to rscratch1 before dispatching. However, r3 was
destroyed by InterpreterRuntime::_breakpoint. In aarch64,the value of
r0 is saved to x19, This is safe because that x19 is a callee-saved
register. In aarch32, there is no free callee-saved register can be
used like x19,then we save r0 to stack here.

Bug Patch:
/******************patch start****************/
diff -r f69a4ff3f0bb src/cpu/aarch32/vm/templateTable_aarch32.cpp
--- a/src/cpu/aarch32/vm/templateTable_aarch32.cpp      Wed Dec 23
12:21:32 2015 +0000
+++ b/src/cpu/aarch32/vm/templateTable_aarch32.cpp      Thu Dec 31
17:10:31 2015 +0800
@@ -2721,7 +2721,7 @@
  void TemplateTable::putfield_or_static(int byte_no, bool is_static,
RewriteControl rc) {
    transition(vtos, vtos);
    const Register cache = r2;
-  const Register index = r0;
+  const Register index = rscratch1;
    const Register obj   = r2;
    const Register off   = rscratch2;
    const Register flags = r14;
@@ -3752,7 +3752,7 @@
               CAST_FROM_FN_PTR(address,
                                InterpreterRuntime::get_original_bytecode_at),
               c_rarg1, rbcp);
-  __ mov(r3, r0);
+  __ push(r0);
      // post the breakpoint event
    __ call_VM(noreg,
@@ -3760,7 +3760,7 @@
               rmethod, rbcp);
      // complete the execution of original bytecode
-  __ mov(rscratch1, r3);
+  __ pop(rscratch1);
    __ dispatch_only_normal(vtos);
  }
/******************patch end******************/

best regards,
Shanyao Chen
-------------- next part --------------
diff -r f69a4ff3f0bb src/cpu/aarch32/vm/templateTable_aarch32.cpp
--- a/src/cpu/aarch32/vm/templateTable_aarch32.cpp	Wed Dec 23 12:21:32 2015 +0000
+++ b/src/cpu/aarch32/vm/templateTable_aarch32.cpp	Thu Dec 31 17:10:31 2015 +0800
@@ -2721,7 +2721,7 @@
 void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteControl rc) {
   transition(vtos, vtos);
   const Register cache = r2;
-  const Register index = r0;
+  const Register index = rscratch1;
   const Register obj   = r2;
   const Register off   = rscratch2;
   const Register flags = r14;
@@ -3752,7 +3752,7 @@
              CAST_FROM_FN_PTR(address,
                               InterpreterRuntime::get_original_bytecode_at),
              c_rarg1, rbcp);
-  __ mov(r3, r0);
+  __ push(r0);
 
   // post the breakpoint event
   __ call_VM(noreg,
@@ -3760,7 +3760,7 @@
              rmethod, rbcp);
 
   // complete the execution of original bytecode
-  __ mov(rscratch1, r3);
+  __ pop(rscratch1);
   __ dispatch_only_normal(vtos);
 }
 



More information about the aarch32-port-dev mailing list