Use different method to mark DEX PC in the interpreter's CFI.
gdb handles unknown register numbers very ungracefully, so
we have to find a different way to insert the information.
Test: testrunner.py -j40 --host --cdex-fast -t 137
Change-Id: Ie4f8abb45e1b4ade32a510ac09413c6ee72edf2c
diff --git a/runtime/interpreter/mterp/arm/entry.S b/runtime/interpreter/mterp/arm/entry.S
index df4bcc6..7c7c527 100644
--- a/runtime/interpreter/mterp/arm/entry.S
+++ b/runtime/interpreter/mterp/arm/entry.S
@@ -56,7 +56,7 @@
VREG_INDEX_TO_ADDR rREFS, r0 @ point to reference array in shadow frame
ldr r0, [r2, #SHADOWFRAME_DEX_PC_OFFSET] @ Get starting dex_pc.
add rPC, r1, r0, lsl #1 @ Create direct pointer to 1st dex opcode
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/arm/header.S b/runtime/interpreter/mterp/arm/header.S
index 64ab9ef..1f15f87 100644
--- a/runtime/interpreter/mterp/arm/header.S
+++ b/runtime/interpreter/mterp/arm/header.S
@@ -93,6 +93,8 @@
/* During bringup, we'll use the shadow frame model instead of rFP */
/* single-purpose registers, given names for clarity */
#define rPC r4
+#define CFI_DEX 4 // DWARF register number of the register holding dex-pc (xPC).
+#define CFI_TMP 0 // DWARF register number of the first argument register (r0).
#define rFP r5
#define rSELF r6
#define rINST r7
diff --git a/runtime/interpreter/mterp/arm64/entry.S b/runtime/interpreter/mterp/arm64/entry.S
index 8d61210..cf38a29 100644
--- a/runtime/interpreter/mterp/arm64/entry.S
+++ b/runtime/interpreter/mterp/arm64/entry.S
@@ -46,7 +46,7 @@
add xREFS, xFP, w0, lsl #2 // point to reference array in shadow frame
ldr w0, [x2, #SHADOWFRAME_DEX_PC_OFFSET] // Get starting dex_pc.
add xPC, x1, w0, lsl #1 // Create direct pointer to 1st dex opcode
- .cfi_register DPC_PSEUDO_REG, xPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/arm64/header.S b/runtime/interpreter/mterp/arm64/header.S
index 9261b77..f0bf8ca 100644
--- a/runtime/interpreter/mterp/arm64/header.S
+++ b/runtime/interpreter/mterp/arm64/header.S
@@ -95,6 +95,8 @@
/* During bringup, we'll use the shadow frame model instead of xFP */
/* single-purpose registers, given names for clarity */
#define xPC x20
+#define CFI_DEX 20 // DWARF register number of the register holding dex-pc (xPC).
+#define CFI_TMP 0 // DWARF register number of the first argument register (r0).
#define xFP x21
#define xSELF x22
#define xINST x23
diff --git a/runtime/interpreter/mterp/cfi_asm_support.h b/runtime/interpreter/mterp/cfi_asm_support.h
index a97e153..0df4eb4 100644
--- a/runtime/interpreter/mterp/cfi_asm_support.h
+++ b/runtime/interpreter/mterp/cfi_asm_support.h
@@ -18,14 +18,30 @@
#define ART_RUNTIME_INTERPRETER_MTERP_CFI_ASM_SUPPORT_H_
/*
- * To keep track of the Dalvik PC, give assign it a magic register number that
- * won't be confused with a pysical register. Then, standard .cfi directives
- * will track the location of it so that it may be extracted during a stack
- * unwind.
+ * Define the DEX PC (memory address of the currently interpreted bytecode)
+ * within the CFI stream of the current function (stored in .eh_frame).
+ * This allows libunwind to detect that the frame is in the interpreter,
+ * and to resolve the memory address into human readable Java method name.
+ * The CFI instruction is recognised by the magic bytes in the expression
+ * (we push magic "DEX1" constant on the DWARF stack and drop it again).
*
- * The Dalvik PC will be in either a physical registor, or the frame.
- * Encoded from the ASCII string " DEX" -> 0x20 0x44 0x45 0x58
+ * As with any other CFI opcode, the expression needs to be associated with
+ * a register. Any caller-save register will do as those are unused in CFI.
+ * Better solution would be to store the expression in Android-specific
+ * DWARF register (CFI registers don't have to correspond to real hardware
+ * registers), however, gdb handles any unknown registers very poorly.
+ * Similarly, we could also use some of the user-defined opcodes defined
+ * in the DWARF specification, but gdb doesn't support those either.
+ *
+ * The DEX PC is generally advanced in the middle of the bytecode handler,
+ * which will result in the reported DEX PC to be off by an instruction.
+ * Therefore the macro allows adding/subtracting an offset to compensate.
+ * TODO: Add the offsets to handlers to get line-accurate DEX PC reporting.
*/
-#define DPC_PSEUDO_REG 0x20444558
+#define CFI_DEFINE_DEX_PC_WITH_OFFSET(tmpReg, dexReg, dexOffset) .cfi_escape \
+ 0x16 /* DW_CFA_val_expression */, tmpReg, 0x09 /* size */, \
+ 0x0c /* DW_OP_const4u */, 0x44, 0x45, 0x58, 0x31, /* magic = "DEX1" */ \
+ 0x13 /* DW_OP_drop */, \
+ 0x92 /* DW_OP_bregx */, dexReg, (dexOffset & 0x7F) /* 1-byte SLEB128 */
#endif // ART_RUNTIME_INTERPRETER_MTERP_CFI_ASM_SUPPORT_H_
diff --git a/runtime/interpreter/mterp/gen_mterp.py b/runtime/interpreter/mterp/gen_mterp.py
index 1c9af30..40d99df 100755
--- a/runtime/interpreter/mterp/gen_mterp.py
+++ b/runtime/interpreter/mterp/gen_mterp.py
@@ -22,7 +22,7 @@
import sys, string, re, time
from string import Template
-interp_defs_file = "../../dex_instruction_list.h" # need opcode list
+interp_defs_file = "../../dex/dex_instruction_list.h" # need opcode list
kNumPackedOpcodes = 256
splitops = False
diff --git a/runtime/interpreter/mterp/mips/entry.S b/runtime/interpreter/mterp/mips/entry.S
index 41b5d56..d342354 100644
--- a/runtime/interpreter/mterp/mips/entry.S
+++ b/runtime/interpreter/mterp/mips/entry.S
@@ -54,7 +54,7 @@
EAS2(rREFS, rFP, a0) # point to reference array in shadow frame
lw a0, SHADOWFRAME_DEX_PC_OFFSET(a2) # Get starting dex_pc
EAS1(rPC, a1, a0) # Create direct pointer to 1st dex opcode
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC()
diff --git a/runtime/interpreter/mterp/mips/header.S b/runtime/interpreter/mterp/mips/header.S
index 0f7a6f1..014628f 100644
--- a/runtime/interpreter/mterp/mips/header.S
+++ b/runtime/interpreter/mterp/mips/header.S
@@ -61,6 +61,8 @@
/* single-purpose registers, given names for clarity */
#define rPC s0
+#define CFI_DEX 16 // DWARF register number of the register holding dex-pc (s0).
+#define CFI_TMP 4 // DWARF register number of the first argument register (a0).
#define rFP s1
#define rSELF s2
#define rIBASE s3
diff --git a/runtime/interpreter/mterp/mips64/entry.S b/runtime/interpreter/mterp/mips64/entry.S
index 841a817..ed965aa 100644
--- a/runtime/interpreter/mterp/mips64/entry.S
+++ b/runtime/interpreter/mterp/mips64/entry.S
@@ -73,7 +73,7 @@
dlsa rREFS, v0, rFP, 2
lw v0, SHADOWFRAME_DEX_PC_OFFSET(a2)
dlsa rPC, v0, a1, 1
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/mips64/header.S b/runtime/interpreter/mterp/mips64/header.S
index 2b550cb..4947aff 100644
--- a/runtime/interpreter/mterp/mips64/header.S
+++ b/runtime/interpreter/mterp/mips64/header.S
@@ -90,6 +90,8 @@
/* During bringup, we'll use the shadow frame model instead of rFP */
/* single-purpose registers, given names for clarity */
#define rPC s0
+#define CFI_DEX 16 // DWARF register number of the register holding dex-pc (s0).
+#define CFI_TMP 4 // DWARF register number of the first argument register (a0).
#define rFP s1
#define rSELF s2
#define rINST s3
diff --git a/runtime/interpreter/mterp/out/mterp_arm.S b/runtime/interpreter/mterp/out/mterp_arm.S
index f3c1124..5c1a13b 100644
--- a/runtime/interpreter/mterp/out/mterp_arm.S
+++ b/runtime/interpreter/mterp/out/mterp_arm.S
@@ -100,6 +100,8 @@
/* During bringup, we'll use the shadow frame model instead of rFP */
/* single-purpose registers, given names for clarity */
#define rPC r4
+#define CFI_DEX 4 // DWARF register number of the register holding dex-pc (xPC).
+#define CFI_TMP 0 // DWARF register number of the first argument register (r0).
#define rFP r5
#define rSELF r6
#define rINST r7
@@ -375,7 +377,7 @@
VREG_INDEX_TO_ADDR rREFS, r0 @ point to reference array in shadow frame
ldr r0, [r2, #SHADOWFRAME_DEX_PC_OFFSET] @ Get starting dex_pc.
add rPC, r1, r0, lsl #1 @ Create direct pointer to 1st dex opcode
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/out/mterp_arm64.S b/runtime/interpreter/mterp/out/mterp_arm64.S
index 347d54f..72446ba 100644
--- a/runtime/interpreter/mterp/out/mterp_arm64.S
+++ b/runtime/interpreter/mterp/out/mterp_arm64.S
@@ -102,6 +102,8 @@
/* During bringup, we'll use the shadow frame model instead of xFP */
/* single-purpose registers, given names for clarity */
#define xPC x20
+#define CFI_DEX 20 // DWARF register number of the register holding dex-pc (xPC).
+#define CFI_TMP 0 // DWARF register number of the first argument register (r0).
#define xFP x21
#define xSELF x22
#define xINST x23
@@ -405,7 +407,7 @@
add xREFS, xFP, w0, lsl #2 // point to reference array in shadow frame
ldr w0, [x2, #SHADOWFRAME_DEX_PC_OFFSET] // Get starting dex_pc.
add xPC, x1, w0, lsl #1 // Create direct pointer to 1st dex opcode
- .cfi_register DPC_PSEUDO_REG, xPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/out/mterp_mips.S b/runtime/interpreter/mterp/out/mterp_mips.S
index 1687afa..d5861b2 100644
--- a/runtime/interpreter/mterp/out/mterp_mips.S
+++ b/runtime/interpreter/mterp/out/mterp_mips.S
@@ -68,6 +68,8 @@
/* single-purpose registers, given names for clarity */
#define rPC s0
+#define CFI_DEX 16 // DWARF register number of the register holding dex-pc (s0).
+#define CFI_TMP 4 // DWARF register number of the first argument register (a0).
#define rFP s1
#define rSELF s2
#define rIBASE s3
@@ -788,7 +790,7 @@
EAS2(rREFS, rFP, a0) # point to reference array in shadow frame
lw a0, SHADOWFRAME_DEX_PC_OFFSET(a2) # Get starting dex_pc
EAS1(rPC, a1, a0) # Create direct pointer to 1st dex opcode
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC()
diff --git a/runtime/interpreter/mterp/out/mterp_mips64.S b/runtime/interpreter/mterp/out/mterp_mips64.S
index 559c72b..5224df9 100644
--- a/runtime/interpreter/mterp/out/mterp_mips64.S
+++ b/runtime/interpreter/mterp/out/mterp_mips64.S
@@ -97,6 +97,8 @@
/* During bringup, we'll use the shadow frame model instead of rFP */
/* single-purpose registers, given names for clarity */
#define rPC s0
+#define CFI_DEX 16 // DWARF register number of the register holding dex-pc (s0).
+#define CFI_TMP 4 // DWARF register number of the first argument register (a0).
#define rFP s1
#define rSELF s2
#define rINST s3
@@ -408,7 +410,7 @@
dlsa rREFS, v0, rFP, 2
lw v0, SHADOWFRAME_DEX_PC_OFFSET(a2)
dlsa rPC, v0, a1, 1
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/out/mterp_x86.S b/runtime/interpreter/mterp/out/mterp_x86.S
index 0613c9d..f98fa5b 100644
--- a/runtime/interpreter/mterp/out/mterp_x86.S
+++ b/runtime/interpreter/mterp/out/mterp_x86.S
@@ -164,6 +164,8 @@
/* single-purpose registers, given names for clarity */
#define rSELF IN_ARG0(%esp)
#define rPC %esi
+#define CFI_DEX 6 // DWARF register number of the register holding dex-pc (esi).
+#define CFI_TMP 0 // DWARF register number of the first argument register (eax).
#define rFP %edi
#define rINST %ebx
#define rINSTw %bx
@@ -380,7 +382,7 @@
leal (rFP, %eax, 4), rREFS
movl SHADOWFRAME_DEX_PC_OFFSET(%edx), %eax
lea (%ecx, %eax, 2), rPC
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Set up for backwards branches & osr profiling */
diff --git a/runtime/interpreter/mterp/out/mterp_x86_64.S b/runtime/interpreter/mterp/out/mterp_x86_64.S
index aa91db3..d82a2d2 100644
--- a/runtime/interpreter/mterp/out/mterp_x86_64.S
+++ b/runtime/interpreter/mterp/out/mterp_x86_64.S
@@ -164,6 +164,8 @@
/* single-purpose registers, given names for clarity */
#define rSELF SELF_SPILL(%rsp)
#define rPC %r12
+#define CFI_DEX 12 // DWARF register number of the register holding dex-pc (rPC).
+#define CFI_TMP 5 // DWARF register number of the first argument register (rdi).
#define rFP %r13
#define rINST %ebx
#define rINSTq %rbx
@@ -363,7 +365,7 @@
leaq (rFP, %rax, 4), rREFS
movl SHADOWFRAME_DEX_PC_OFFSET(IN_ARG2), %eax
leaq (IN_ARG1, %rax, 2), rPC
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/x86/entry.S b/runtime/interpreter/mterp/x86/entry.S
index 10ca836..324637b 100644
--- a/runtime/interpreter/mterp/x86/entry.S
+++ b/runtime/interpreter/mterp/x86/entry.S
@@ -61,7 +61,7 @@
leal (rFP, %eax, 4), rREFS
movl SHADOWFRAME_DEX_PC_OFFSET(%edx), %eax
lea (%ecx, %eax, 2), rPC
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Set up for backwards branches & osr profiling */
diff --git a/runtime/interpreter/mterp/x86/header.S b/runtime/interpreter/mterp/x86/header.S
index 0e585e8..2e3bbdf 100644
--- a/runtime/interpreter/mterp/x86/header.S
+++ b/runtime/interpreter/mterp/x86/header.S
@@ -157,6 +157,8 @@
/* single-purpose registers, given names for clarity */
#define rSELF IN_ARG0(%esp)
#define rPC %esi
+#define CFI_DEX 6 // DWARF register number of the register holding dex-pc (esi).
+#define CFI_TMP 0 // DWARF register number of the first argument register (eax).
#define rFP %edi
#define rINST %ebx
#define rINSTw %bx
diff --git a/runtime/interpreter/mterp/x86_64/entry.S b/runtime/interpreter/mterp/x86_64/entry.S
index d85ef7f..2f69226 100644
--- a/runtime/interpreter/mterp/x86_64/entry.S
+++ b/runtime/interpreter/mterp/x86_64/entry.S
@@ -58,7 +58,7 @@
leaq (rFP, %rax, 4), rREFS
movl SHADOWFRAME_DEX_PC_OFFSET(IN_ARG2), %eax
leaq (IN_ARG1, %rax, 2), rPC
- .cfi_register DPC_PSEUDO_REG, rPC
+ CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
EXPORT_PC
/* Starting ibase */
diff --git a/runtime/interpreter/mterp/x86_64/header.S b/runtime/interpreter/mterp/x86_64/header.S
index a3ef895..eabaade 100644
--- a/runtime/interpreter/mterp/x86_64/header.S
+++ b/runtime/interpreter/mterp/x86_64/header.S
@@ -157,6 +157,8 @@
/* single-purpose registers, given names for clarity */
#define rSELF SELF_SPILL(%rsp)
#define rPC %r12
+#define CFI_DEX 12 // DWARF register number of the register holding dex-pc (rPC).
+#define CFI_TMP 5 // DWARF register number of the first argument register (rdi).
#define rFP %r13
#define rINST %ebx
#define rINSTq %rbx