diff options
author | Ben Cheng <bccheng@android.com> | 2010-03-16 16:20:43 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2010-03-16 16:20:43 -0700 |
commit | b4d15c644926761756c0785a9afde1ccdfe4c5c7 (patch) | |
tree | 4c82efd88ad54298ebe9f82e77929e1c1e430a4a | |
parent | ac19bd45c2dc987f2ab8bb74e3682324580b013c (diff) | |
parent | 79cea5c97267e0b3e35e0c2b70e2662aa533f200 (diff) | |
download | android_dalvik-b4d15c644926761756c0785a9afde1ccdfe4c5c7.tar.gz android_dalvik-b4d15c644926761756c0785a9afde1ccdfe4c5c7.tar.bz2 android_dalvik-b4d15c644926761756c0785a9afde1ccdfe4c5c7.zip |
am 79cea5c9: Merge "Implement signature-based breakpoint for the JIT compiler."
Merge commit '79cea5c97267e0b3e35e0c2b70e2662aa533f200' into dalvik-dev
* commit '79cea5c97267e0b3e35e0c2b70e2662aa533f200':
Implement signature-based breakpoint for the JIT compiler.
-rw-r--r-- | vm/Globals.h | 6 | ||||
-rw-r--r-- | vm/compiler/Compiler.c | 100 | ||||
-rw-r--r-- | vm/compiler/Compiler.h | 5 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/Assemble.c | 35 |
4 files changed, 146 insertions, 0 deletions
diff --git a/vm/Globals.h b/vm/Globals.h index b3886af46..681076a13 100644 --- a/vm/Globals.h +++ b/vm/Globals.h @@ -798,6 +798,12 @@ struct DvmJitGlobals { /* Framework requests to disable the JIT for good */ bool disableJit; +#if defined(SIGNATURE_BREAKPOINT) + /* Signature breakpoint */ + u4 signatureBreakpointSize; // # of words + u4 *signatureBreakpoint; // Signature content +#endif + /* Place arrays at the end to ease the display in gdb sessions */ /* Work order queue for compilations */ diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c index bd12e5689..2256c474e 100644 --- a/vm/compiler/Compiler.c +++ b/vm/compiler/Compiler.c @@ -391,6 +391,106 @@ bool compilerThreadStartup(void) /* Signal running threads to refresh their cached pJitTable pointers */ dvmSuspendAllThreads(SUSPEND_FOR_REFRESH); dvmResumeAllThreads(SUSPEND_FOR_REFRESH); + + /* Enable signature breakpoints by customizing the following code */ +#if defined(SIGNATURE_BREAKPOINT) + /* + * Suppose one sees the following native crash in the bugreport: + * I/DEBUG ( 1638): Build fingerprint: 'unknown' + * I/DEBUG ( 1638): pid: 2468, tid: 2507 >>> com.google.android.gallery3d + * I/DEBUG ( 1638): signal 11 (SIGSEGV), fault addr 00001400 + * I/DEBUG ( 1638): r0 44ea7190 r1 44e4f7b8 r2 44ebc710 r3 00000000 + * I/DEBUG ( 1638): r4 00000a00 r5 41862dec r6 4710dc10 r7 00000280 + * I/DEBUG ( 1638): r8 ad010f40 r9 46a37a12 10 001116b0 fp 42a78208 + * I/DEBUG ( 1638): ip 00000090 sp 4710dbc8 lr ad060e67 pc 46b90682 + * cpsr 00000030 + * I/DEBUG ( 1638): #00 pc 46b90682 /dev/ashmem/dalvik-jit-code-cache + * I/DEBUG ( 1638): #01 pc 00060e62 /system/lib/libdvm.so + * + * I/DEBUG ( 1638): code around pc: + * I/DEBUG ( 1638): 46b90660 6888d01c 34091dcc d2174287 4a186b68 + * I/DEBUG ( 1638): 46b90670 d0052800 68006809 28004790 6b68d00e + * I/DEBUG ( 1638): 46b90680 512000bc 37016eaf 6ea866af 6f696028 + * I/DEBUG ( 1638): 46b90690 682a6069 429a686b e003da08 6df1480b + * I/DEBUG ( 1638): 46b906a0 1c2d4788 47806d70 46a378fa 47806d70 + * + * Clearly it is a JIT bug. To find out which translation contains the + * offending code, the content of the memory dump around the faulting PC + * can be pasted into the gDvmJit.signatureBreakpoint[] array and next time + * when a similar compilation is being created, the JIT compiler replay the + * trace in the verbose mode and one can investigate the instruction + * sequence in details. + * + * The length of the signature may need additional experiments to determine. + * The rule of thumb is don't include PC-relative instructions in the + * signature since it may be affected by the alignment of the compiled code. + * However, a signature that's too short might increase the chance of false + * positive matches. Using gdbjithelper to disassembly the memory content + * first might be a good companion approach. + * + * For example, if the next 4 words starting from 46b90680 is pasted into + * the data structure: + */ + + gDvmJit.signatureBreakpointSize = 4; + gDvmJit.signatureBreakpoint = + malloc(sizeof(u4) * gDvmJit.signatureBreakpointSize); + gDvmJit.signatureBreakpoint[0] = 0x512000bc; + gDvmJit.signatureBreakpoint[1] = 0x37016eaf; + gDvmJit.signatureBreakpoint[2] = 0x6ea866af; + gDvmJit.signatureBreakpoint[3] = 0x6f696028; + + /* + * The following log will be printed when a match is found in subsequent + * testings: + * + * D/dalvikvm( 2468): Signature match starting from offset 0x34 (4 words) + * D/dalvikvm( 2468): -------- + * D/dalvikvm( 2468): Compiler: Building trace for computeVisibleItems, + * offset 0x1f7 + * D/dalvikvm( 2468): 0x46a37a12: 0x0090 add-int v42, v5, v26 + * D/dalvikvm( 2468): 0x46a37a16: 0x004d aput-object v13, v14, v42 + * D/dalvikvm( 2468): 0x46a37a1a: 0x0028 goto, (#0), (#0) + * D/dalvikvm( 2468): 0x46a3794e: 0x00d8 add-int/lit8 v26, v26, (#1) + * D/dalvikvm( 2468): 0x46a37952: 0x0028 goto, (#0), (#0) + * D/dalvikvm( 2468): 0x46a378ee: 0x0002 move/from16 v0, v26, (#0) + * D/dalvikvm( 2468): 0x46a378f2: 0x0002 move/from16 v1, v29, (#0) + * D/dalvikvm( 2468): 0x46a378f6: 0x0035 if-ge v0, v1, (#10) + * D/dalvikvm( 2468): TRACEINFO (554): 0x46a37624 + * Lcom/cooliris/media/GridLayer;computeVisibleItems 0x1f7 14 of 934, 8 + * blocks + * : + * : + * D/dalvikvm( 2468): 0x20 (0020): ldr r0, [r5, #52] + * D/dalvikvm( 2468): 0x22 (0022): ldr r2, [pc, #96] + * D/dalvikvm( 2468): 0x24 (0024): cmp r0, #0 + * D/dalvikvm( 2468): 0x26 (0026): beq 0x00000034 + * D/dalvikvm( 2468): 0x28 (0028): ldr r1, [r1, #0] + * D/dalvikvm( 2468): 0x2a (002a): ldr r0, [r0, #0] + * D/dalvikvm( 2468): 0x2c (002c): blx r2 + * D/dalvikvm( 2468): 0x2e (002e): cmp r0, #0 + * D/dalvikvm( 2468): 0x30 (0030): beq 0x00000050 + * D/dalvikvm( 2468): 0x32 (0032): ldr r0, [r5, #52] + * D/dalvikvm( 2468): 0x34 (0034): lsls r4, r7, #2 + * D/dalvikvm( 2468): 0x36 (0036): str r0, [r4, r4] + * D/dalvikvm( 2468): -------- dalvik offset: 0x01fb @ goto, (#0), (#0) + * D/dalvikvm( 2468): L0x0195: + * D/dalvikvm( 2468): -------- dalvik offset: 0x0195 @ add-int/lit8 v26, + * v26, (#1) + * D/dalvikvm( 2468): 0x38 (0038): ldr r7, [r5, #104] + * D/dalvikvm( 2468): 0x3a (003a): adds r7, r7, #1 + * D/dalvikvm( 2468): 0x3c (003c): str r7, [r5, #104] + * D/dalvikvm( 2468): -------- dalvik offset: 0x0197 @ goto, (#0), (#0) + * D/dalvikvm( 2468): L0x0165: + * D/dalvikvm( 2468): -------- dalvik offset: 0x0165 @ move/from16 v0, v26, + * (#0) + * D/dalvikvm( 2468): 0x3e (003e): ldr r0, [r5, #104] + * D/dalvikvm( 2468): 0x40 (0040): str r0, [r5, #0] + * + * The "str r0, [r4, r4]" is indeed the culprit of the native crash. + */ +#endif + return true; fail: diff --git a/vm/compiler/Compiler.h b/vm/compiler/Compiler.h index f264c5b16..7ac9ab71d 100644 --- a/vm/compiler/Compiler.h +++ b/vm/compiler/Compiler.h @@ -20,6 +20,11 @@ #ifndef _DALVIK_VM_COMPILER #define _DALVIK_VM_COMPILER +/* + * Uncomment the following to enable JIT signature breakpoint + * #define SIGNATURE_BREAKPOINT + */ + #define MAX_JIT_RUN_LEN 64 #define COMPILER_WORK_QUEUE_SIZE 100 #define COMPILER_IC_PATCH_QUEUE_SIZE 64 diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c index 0d7895f23..e642c5c16 100644 --- a/vm/compiler/codegen/arm/Assemble.c +++ b/vm/compiler/codegen/arm/Assemble.c @@ -1105,6 +1105,34 @@ static bool assembleInstructions(CompilationUnit *cUnit, intptr_t startAddr) return false; } +/* Inspect the assembled instruction stream to find potential matches */ +static void matchSignatureBreakpoint(const CompilationUnit *cUnit, + unsigned int size) +{ + unsigned int i, j; + u4 *ptr = (u4 *) cUnit->codeBuffer; + + for (i = 0; i < size - gDvmJit.signatureBreakpointSize + 1; i++) { + if (ptr[i] == gDvmJit.signatureBreakpoint[0]) { + for (j = 1; j < gDvmJit.signatureBreakpointSize; j++) { + if (ptr[i+j] != gDvmJit.signatureBreakpoint[j]) { + break; + } + } + if (j == gDvmJit.signatureBreakpointSize) { + LOGD("Signature match starting from offset %#x (%d words)", + i*4, gDvmJit.signatureBreakpointSize); + int descSize = jitTraceDescriptionSize(cUnit->traceDesc); + JitTraceDescription *newCopy = + (JitTraceDescription *) malloc(descSize); + memcpy(newCopy, cUnit->traceDesc, descSize); + dvmCompilerWorkEnqueue(NULL, kWorkOrderTraceDebug, newCopy); + break; + } + } + } +} + /* * Translation layout in the code cache. Note that the codeAddress pointer * in JitTable will point directly to the code body (field codeAddress). The @@ -1243,6 +1271,13 @@ void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info) return; } +#if defined(SIGNATURE_BREAKPOINT) + if (info->discardResult == false && gDvmJit.signatureBreakpoint != NULL && + chainCellOffset/4 >= gDvmJit.signatureBreakpointSize) { + matchSignatureBreakpoint(cUnit, chainCellOffset/4); + } +#endif + /* Don't go all the way if the goal is just to get the verbose output */ if (info->discardResult) return; |