Find first non-zero jit debug entry.
Sometimes a process will have multiple shared libraries loaded
that have defined __jit_debug_descriptor. Specifically, art testing
will load libart.so and libartd.so, which would have broken unwinding
through jit'd code for art testing if libart.so winds up being found first.
In order to avoid duplicating the code for the linker to figure out
which one is live, change the algorithm to find the first non-zero
first_entry_ set in __jit_debug_descriptor.
Bug: 68396769
Test: Passes unit tests.
Test: Verified this can unwind 137-cfi on arm/arm64.
Change-Id: Ic4d403065d2c6f22476ef0171e7add17cd1464cd
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index 9216204..582ac18 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -406,4 +406,223 @@
frame_info);
}
+TEST(UnwindOfflineTest, jit_debug_arm32) {
+ std::string dir(TestGetFileDirectory() + "offline/jit_debug_arm32/");
+
+ MemoryOfflineParts* memory = new MemoryOfflineParts;
+ AddMemory(dir + "descriptor.data", memory);
+ AddMemory(dir + "descriptor1.data", memory);
+ AddMemory(dir + "stack.data", memory);
+ for (size_t i = 0; i < 7; i++) {
+ AddMemory(dir + "entry" + std::to_string(i) + ".data", memory);
+ AddMemory(dir + "jit" + std::to_string(i) + ".data", memory);
+ }
+
+ FILE* fp = fopen((dir + "regs.txt").c_str(), "r");
+ ASSERT_TRUE(fp != nullptr);
+ RegsArm regs;
+ uint64_t reg_value;
+ ASSERT_EQ(1, fscanf(fp, "r0: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_R0] = reg_value;
+ ASSERT_EQ(1, fscanf(fp, "r1: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_R1] = reg_value;
+ ASSERT_EQ(1, fscanf(fp, "r2: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_R2] = reg_value;
+ ASSERT_EQ(1, fscanf(fp, "r3: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_R3] = reg_value;
+ ASSERT_EQ(1, fscanf(fp, "r4: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_R4] = reg_value;
+ ASSERT_EQ(1, fscanf(fp, "r5: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_R5] = reg_value;
+ ASSERT_EQ(1, fscanf(fp, "r6: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_R6] = reg_value;
+ ASSERT_EQ(1, fscanf(fp, "r7: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_R7] = reg_value;
+ ASSERT_EQ(1, fscanf(fp, "r8: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_R8] = reg_value;
+ ASSERT_EQ(1, fscanf(fp, "r9: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_R9] = reg_value;
+ ASSERT_EQ(1, fscanf(fp, "r10: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_R10] = reg_value;
+ ASSERT_EQ(1, fscanf(fp, "r11: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_R11] = reg_value;
+ ASSERT_EQ(1, fscanf(fp, "ip: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_R12] = reg_value;
+ ASSERT_EQ(1, fscanf(fp, "sp: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_SP] = reg_value;
+ ASSERT_EQ(1, fscanf(fp, "lr: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_LR] = reg_value;
+ ASSERT_EQ(1, fscanf(fp, "pc: %" SCNx64 "\n", ®_value));
+ regs[ARM_REG_PC] = reg_value;
+ regs.SetFromRaw();
+ fclose(fp);
+
+ fp = fopen((dir + "maps.txt").c_str(), "r");
+ ASSERT_TRUE(fp != nullptr);
+ // The file is guaranteed to be less than 4096 bytes.
+ std::vector<char> buffer(4096);
+ ASSERT_NE(0U, fread(buffer.data(), 1, buffer.size(), fp));
+ fclose(fp);
+
+ BufferMaps maps(buffer.data());
+ ASSERT_TRUE(maps.Parse());
+
+ ASSERT_EQ(ARCH_ARM, regs.Arch());
+
+ std::shared_ptr<Memory> process_memory(memory);
+
+ char* cwd = getcwd(nullptr, 0);
+ ASSERT_EQ(0, chdir(dir.c_str()));
+ JitDebug jit_debug(process_memory);
+ Unwinder unwinder(128, &maps, ®s, process_memory);
+ unwinder.SetJitDebug(&jit_debug, regs.Arch());
+ unwinder.Unwind();
+ ASSERT_EQ(0, chdir(cwd));
+ free(cwd);
+
+ std::string frame_info(DumpFrames(unwinder));
+ ASSERT_EQ(76U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+ EXPECT_EQ(
+ " #00 pc 00018a5e libarttestd.so (Java_Main_unwindInProcess+865)\n"
+ " #01 pc 0000212d (offset 0x2000) 137-cfi.odex (boolean Main.unwindInProcess(boolean, int, "
+ "boolean)+92)\n"
+ " #02 pc 00011cb1 anonymous:e2796000 (boolean Main.bar(boolean)+72)\n"
+ " #03 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
+ " #04 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
+ " #05 pc 000bf7a9 libartd.so "
+ "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
+ " #06 pc 00247833 libartd.so "
+ "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
+ "11ShadowFrameEtPNS_6JValueE+382)\n"
+ " #07 pc 0022e935 libartd.so "
+ "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
+ "6JValueEb+244)\n"
+ " #08 pc 0022f71d libartd.so "
+ "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
+ "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ " #09 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
+ " #10 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
+ " #11 pc 00011c31 anonymous:e2796000 (int Main.compare(Main, Main)+64)\n"
+ " #12 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
+ " #13 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
+ " #14 pc 000bf7a9 libartd.so "
+ "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
+ " #15 pc 00247833 libartd.so "
+ "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
+ "11ShadowFrameEtPNS_6JValueE+382)\n"
+ " #16 pc 0022e935 libartd.so "
+ "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
+ "6JValueEb+244)\n"
+ " #17 pc 0022f71d libartd.so "
+ "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
+ "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ " #18 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
+ " #19 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
+ " #20 pc 00011b77 anonymous:e2796000 (int Main.compare(java.lang.Object, "
+ "java.lang.Object)+118)\n"
+ " #21 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
+ " #22 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
+ " #23 pc 000bf7a9 libartd.so "
+ "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
+ " #24 pc 00247833 libartd.so "
+ "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
+ "11ShadowFrameEtPNS_6JValueE+382)\n"
+ " #25 pc 0022e935 libartd.so "
+ "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
+ "6JValueEb+244)\n"
+ " #26 pc 0022f71d libartd.so "
+ "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
+ "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ " #27 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
+ " #28 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
+ " #29 pc 00011a29 anonymous:e2796000 (int "
+ "java.util.Arrays.binarySearch0(java.lang.Object[], int, int, java.lang.Object, "
+ "java.util.Comparator)+304)\n"
+ " #30 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
+ " #31 pc 0046722f libartd.so (art_quick_invoke_static_stub+226)\n"
+ " #32 pc 000bf7bb libartd.so "
+ "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+882)\n"
+ " #33 pc 00247833 libartd.so "
+ "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
+ "11ShadowFrameEtPNS_6JValueE+382)\n"
+ " #34 pc 0022e935 libartd.so "
+ "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
+ "6JValueEb+244)\n"
+ " #35 pc 0022f71d libartd.so "
+ "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
+ "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ " #36 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
+ " #37 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
+ " #38 pc 0001139b anonymous:e2796000 (boolean Main.foo()+178)\n"
+ " #39 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
+ " #40 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
+ " #41 pc 000bf7a9 libartd.so "
+ "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
+ " #42 pc 00247833 libartd.so "
+ "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
+ "11ShadowFrameEtPNS_6JValueE+382)\n"
+ " #43 pc 0022e935 libartd.so "
+ "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
+ "6JValueEb+244)\n"
+ " #44 pc 0022f71d libartd.so "
+ "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
+ "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ " #45 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
+ " #46 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
+ " #47 pc 00010aa7 anonymous:e2796000 (void Main.runPrimary()+70)\n"
+ " #48 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
+ " #49 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
+ " #50 pc 000bf7a9 libartd.so "
+ "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
+ " #51 pc 00247833 libartd.so "
+ "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
+ "11ShadowFrameEtPNS_6JValueE+382)\n"
+ " #52 pc 0022e935 libartd.so "
+ "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
+ "6JValueEb+244)\n"
+ " #53 pc 0022f71d libartd.so "
+ "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
+ "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ " #54 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
+ " #55 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
+ " #56 pc 0000ba99 anonymous:e2796000 (void Main.main(java.lang.String[])+144)\n"
+ " #57 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
+ " #58 pc 0046722f libartd.so (art_quick_invoke_static_stub+226)\n"
+ " #59 pc 000bf7bb libartd.so "
+ "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+882)\n"
+ " #60 pc 00247833 libartd.so "
+ "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
+ "11ShadowFrameEtPNS_6JValueE+382)\n"
+ " #61 pc 0022e935 libartd.so "
+ "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
+ "6JValueEb+244)\n"
+ " #62 pc 0022f71d libartd.so "
+ "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
+ "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ " #63 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
+ " #64 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
+ " #65 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
+ " #66 pc 0046722f libartd.so (art_quick_invoke_static_stub+226)\n"
+ " #67 pc 000bf7bb libartd.so "
+ "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+882)\n"
+ " #68 pc 003b292d libartd.so "
+ "(_ZN3artL18InvokeWithArgArrayERKNS_33ScopedObjectAccessAlreadyRunnableEPNS_9ArtMethodEPNS_"
+ "8ArgArrayEPNS_6JValueEPKc+52)\n"
+ " #69 pc 003b26c3 libartd.so "
+ "(_ZN3art17InvokeWithVarArgsERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectP10_"
+ "jmethodIDSt9__va_list+210)\n"
+ " #70 pc 00308411 libartd.so "
+ "(_ZN3art3JNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDSt9__va_list+76)\n"
+ " #71 pc 000e6a9f libartd.so "
+ "(_ZN3art8CheckJNI11CallMethodVEPKcP7_JNIEnvP8_jobjectP7_jclassP10_jmethodIDSt9__va_listNS_"
+ "9Primitive4TypeENS_10InvokeTypeE+1486)\n"
+ " #72 pc 000e19b9 libartd.so "
+ "(_ZN3art8CheckJNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDSt9__va_list+40)\n"
+ " #73 pc 0000159f dalvikvm32 "
+ "(_ZN7_JNIEnv20CallStaticVoidMethodEP7_jclassP10_jmethodIDz+30)\n"
+ " #74 pc 00001349 dalvikvm32 (main+896)\n"
+ " #75 pc 000850c9 libc.so\n",
+ frame_info);
+}
+
} // namespace unwindstack