diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp index e267f5864..73dc92167 100644 --- a/libunwindstack/Android.bp +++ b/libunwindstack/Android.bp @@ -127,6 +127,10 @@ cc_library { }, }, + whole_static_libs: [ + "libdemangle" + ], + static_libs: [ "libprocinfo", ], @@ -189,6 +193,7 @@ cc_test { "tests/MapInfoCreateMemoryTest.cpp", "tests/MapInfoGetElfTest.cpp", "tests/MapInfoGetLoadBiasTest.cpp", + "tests/MapInfoTest.cpp", "tests/MapsTest.cpp", "tests/MemoryBufferTest.cpp", "tests/MemoryCacheTest.cpp", diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp index 39a09cf41..b9d8b3db7 100644 --- a/libunwindstack/MapInfo.cpp +++ b/libunwindstack/MapInfo.cpp @@ -221,6 +221,19 @@ Elf* MapInfo::GetElf(const std::shared_ptr& process_memory, ArchEnum exp return elf.get(); } +bool MapInfo::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) { + { + // Make sure no other thread is trying to update this elf object. + std::lock_guard guard(mutex_); + if (elf == nullptr) { + return false; + } + } + // No longer need the lock, once the elf object is created, it is not deleted + // until this object is deleted. + return elf->GetFunctionName(addr, name, func_offset); +} + uint64_t MapInfo::GetLoadBias(const std::shared_ptr& process_memory) { uint64_t cur_load_bias = load_bias.load(); if (cur_load_bias != static_cast(-1)) { diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp index 813363905..57207de21 100644 --- a/libunwindstack/Unwinder.cpp +++ b/libunwindstack/Unwinder.cpp @@ -26,10 +26,13 @@ #include +#include + #include #include #include #include +#include #include #if !defined(NO_LIBDEXFILE_SUPPORT) @@ -306,7 +309,7 @@ std::string Unwinder::FormatFrame(const FrameData& frame, bool is32bit) { } if (!frame.function_name.empty()) { - data += " (" + frame.function_name; + data += " (" + demangle(frame.function_name.c_str()); if (frame.function_offset != 0) { data += android::base::StringPrintf("+%" PRId64, frame.function_offset); } @@ -327,4 +330,29 @@ void Unwinder::SetDexFiles(DexFiles* dex_files, ArchEnum arch) { } #endif +bool UnwinderFromPid::Init(ArchEnum arch) { + if (pid_ == getpid()) { + maps_ptr_.reset(new LocalMaps()); + } else { + maps_ptr_.reset(new RemoteMaps(pid_)); + } + if (!maps_ptr_->Parse()) { + return false; + } + maps_ = maps_ptr_.get(); + + process_memory_ = Memory::CreateProcessMemoryCached(pid_); + + jit_debug_ptr_.reset(new JitDebug(process_memory_)); + jit_debug_ = jit_debug_ptr_.get(); + SetJitDebug(jit_debug_, arch); +#if !defined(NO_LIBDEXFILE_SUPPORT) + dex_files_ptr_.reset(new DexFiles(process_memory_)); + dex_files_ = dex_files_ptr_.get(); + SetDexFiles(dex_files_, arch); +#endif + + return true; +} + } // namespace unwindstack diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h index 5e3d6f607..a9febd17d 100644 --- a/libunwindstack/include/unwindstack/MapInfo.h +++ b/libunwindstack/include/unwindstack/MapInfo.h @@ -75,6 +75,8 @@ struct MapInfo { Memory* CreateMemory(const std::shared_ptr& process_memory); + bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset); + private: MapInfo(const MapInfo&) = delete; void operator=(const MapInfo&) = delete; diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h index d7bbd9d3d..ab239c1f1 100644 --- a/libunwindstack/include/unwindstack/Unwinder.h +++ b/libunwindstack/include/unwindstack/Unwinder.h @@ -24,7 +24,9 @@ #include #include +#include #include +#include #include #include #include @@ -32,9 +34,7 @@ namespace unwindstack { // Forward declarations. -class DexFiles; class Elf; -class JitDebug; enum ArchEnum : uint8_t; struct FrameData { @@ -67,6 +67,11 @@ class Unwinder { : max_frames_(max_frames), maps_(maps), regs_(regs), process_memory_(process_memory) { frames_.reserve(max_frames); } + Unwinder(size_t max_frames, Maps* maps, std::shared_ptr process_memory) + : max_frames_(max_frames), maps_(maps), process_memory_(process_memory) { + frames_.reserve(max_frames); + } + ~Unwinder() = default; void Unwind(const std::vector* initial_map_names_to_skip = nullptr, @@ -81,6 +86,10 @@ class Unwinder { void SetJitDebug(JitDebug* jit_debug, ArchEnum arch); + void SetRegs(Regs* regs) { regs_ = regs; } + Maps* GetMaps() { return maps_; } + std::shared_ptr& GetProcessMemory() { return process_memory_; } + // Disabling the resolving of names results in the function name being // set to an empty string and the function offset being set to zero. void SetResolveNames(bool resolve) { resolve_names_ = resolve; } @@ -92,7 +101,9 @@ class Unwinder { ErrorCode LastErrorCode() { return last_error_.code; } uint64_t LastErrorAddress() { return last_error_.address; } - private: + protected: + Unwinder(size_t max_frames) : max_frames_(max_frames) { frames_.reserve(max_frames); } + void FillInDexFrame(); void FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t func_pc, uint64_t pc_adjustment); @@ -110,6 +121,22 @@ class Unwinder { ErrorData last_error_; }; +class UnwinderFromPid : public Unwinder { + public: + UnwinderFromPid(size_t max_frames, pid_t pid) : Unwinder(max_frames), pid_(pid) {} + ~UnwinderFromPid() = default; + + bool Init(ArchEnum arch); + + private: + pid_t pid_; + std::unique_ptr maps_ptr_; + std::unique_ptr jit_debug_ptr_; +#if !defined(NO_LIBDEXFILE_SUPPORT) + std::unique_ptr dex_files_ptr_; +#endif +}; + } // namespace unwindstack #endif // _LIBUNWINDSTACK_UNWINDER_H diff --git a/libunwindstack/tests/MapInfoTest.cpp b/libunwindstack/tests/MapInfoTest.cpp new file mode 100644 index 000000000..e2cbb9812 --- /dev/null +++ b/libunwindstack/tests/MapInfoTest.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include +#include + +#include "ElfFake.h" + +namespace unwindstack { + +TEST(MapInfoTest, maps_constructor_const_char) { + MapInfo prev_map(nullptr, 0, 0, 0, 0, ""); + MapInfo map_info(&prev_map, 1, 2, 3, 4, "map"); + + EXPECT_EQ(&prev_map, map_info.prev_map); + EXPECT_EQ(1UL, map_info.start); + EXPECT_EQ(2UL, map_info.end); + EXPECT_EQ(3UL, map_info.offset); + EXPECT_EQ(4UL, map_info.flags); + EXPECT_EQ("map", map_info.name); + EXPECT_EQ(static_cast(-1), map_info.load_bias); + EXPECT_EQ(0UL, map_info.elf_offset); + EXPECT_TRUE(map_info.elf.get() == nullptr); +} + +TEST(MapInfoTest, maps_constructor_string) { + std::string name("string_map"); + MapInfo prev_map(nullptr, 0, 0, 0, 0, ""); + MapInfo map_info(&prev_map, 1, 2, 3, 4, name); + + EXPECT_EQ(&prev_map, map_info.prev_map); + EXPECT_EQ(1UL, map_info.start); + EXPECT_EQ(2UL, map_info.end); + EXPECT_EQ(3UL, map_info.offset); + EXPECT_EQ(4UL, map_info.flags); + EXPECT_EQ("string_map", map_info.name); + EXPECT_EQ(static_cast(-1), map_info.load_bias); + EXPECT_EQ(0UL, map_info.elf_offset); + EXPECT_TRUE(map_info.elf.get() == nullptr); +} + +TEST(MapInfoTest, get_function_name) { + ElfFake* elf = new ElfFake(nullptr); + ElfInterfaceFake* interface = new ElfInterfaceFake(nullptr); + elf->FakeSetInterface(interface); + interface->FakePushFunctionData(FunctionData("function", 1000)); + + MapInfo map_info(nullptr, 1, 2, 3, 4, ""); + map_info.elf.reset(elf); + + std::string name; + uint64_t offset; + ASSERT_TRUE(map_info.GetFunctionName(1000, &name, &offset)); + EXPECT_EQ("function", name); + EXPECT_EQ(1000UL, offset); +} + +} // namespace unwindstack diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp index aab9ec20d..0588a8444 100644 --- a/libunwindstack/tests/UnwindOfflineTest.cpp +++ b/libunwindstack/tests/UnwindOfflineTest.cpp @@ -210,8 +210,8 @@ TEST_F(UnwindOfflineTest, pc_straddle_arm) { ASSERT_EQ(4U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; EXPECT_EQ( " #00 pc 0001a9f8 libc.so (abort+64)\n" - " #01 pc 00006a1b libbase.so (_ZN7android4base14DefaultAborterEPKc+6)\n" - " #02 pc 00007441 libbase.so (_ZN7android4base10LogMessageD2Ev+748)\n" + " #01 pc 00006a1b libbase.so (android::base::DefaultAborter(char const*)+6)\n" + " #02 pc 00007441 libbase.so (android::base::LogMessage::~LogMessage()+748)\n" " #03 pc 00015147 /does/not/exist/libhidlbase.so\n", frame_info); EXPECT_EQ(0xf31ea9f8U, unwinder.frames()[0].pc); @@ -234,9 +234,10 @@ TEST_F(UnwindOfflineTest, pc_in_gnu_debugdata_arm) { ASSERT_EQ(2U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; EXPECT_EQ( " #00 pc 0006dc49 libandroid_runtime.so " - "(_ZN7android14AndroidRuntime15javaThreadShellEPv+80)\n" + "(android::AndroidRuntime::javaThreadShell(void*)+80)\n" " #01 pc 0006dce5 libandroid_runtime.so " - "(_ZN7android14AndroidRuntime19javaCreateThreadEtcEPFiPvES1_PKcijPS1_)\n", + "(android::AndroidRuntime::javaCreateThreadEtc(int (*)(void*), void*, char const*, int, " + "unsigned int, void**))\n", frame_info); EXPECT_EQ(0xf1f6dc49U, unwinder.frames()[0].pc); EXPECT_EQ(0xd8fe6930U, unwinder.frames()[0].sp); @@ -257,10 +258,10 @@ TEST_F(UnwindOfflineTest, pc_straddle_arm64) { " #01 pc 000000000042a078 libunwindstack_test (SignalMiddleFunction+8)\n" " #02 pc 000000000042a08c libunwindstack_test (SignalOuterFunction+8)\n" " #03 pc 000000000042d8fc libunwindstack_test " - "(_ZN11unwindstackL19RemoteThroughSignalEij+20)\n" + "(unwindstack::RemoteThroughSignal(int, unsigned int)+20)\n" " #04 pc 000000000042d8d8 libunwindstack_test " - "(_ZN11unwindstack37UnwindTest_remote_through_signal_Test8TestBodyEv+32)\n" - " #05 pc 0000000000455d70 libunwindstack_test (_ZN7testing4Test3RunEv+392)\n", + "(unwindstack::UnwindTest_remote_through_signal_Test::TestBody()+32)\n" + " #05 pc 0000000000455d70 libunwindstack_test (testing::Test::Run()+392)\n", frame_info); EXPECT_EQ(0x64d09d4fd8U, unwinder.frames()[0].pc); EXPECT_EQ(0x7fe0d84040U, unwinder.frames()[0].sp); @@ -296,54 +297,57 @@ TEST_F(UnwindOfflineTest, jit_debug_x86) { std::string frame_info(DumpFrames(unwinder)); ASSERT_EQ(69U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; EXPECT_EQ( - " #00 pc 00068fb8 libarttestd.so (_ZN3artL13CauseSegfaultEv+72)\n" + " #00 pc 00068fb8 libarttestd.so (art::CauseSegfault()+72)\n" " #01 pc 00067f00 libarttestd.so (Java_Main_unwindInProcess+10032)\n" " #02 pc 000021a8 137-cfi.odex (offset 0x2000) (boolean Main.unwindInProcess(boolean, int, " "boolean)+136)\n" " #03 pc 0000fe80 anonymous:ee74c000 (boolean Main.bar(boolean)+64)\n" " #04 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n" " #05 pc 00146ab5 libartd.so " - "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+885)\n" " #06 pc 0039cf0d libartd.so " - "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_" - "11ShadowFrameEtPNS_6JValueE+653)\n" + "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " + "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n" " #07 pc 00392552 libartd.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+354)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+354)\n" " #08 pc 0039399a libartd.so " - "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n" + "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " + "const&, art::ShadowFrame*)+234)\n" " #09 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n" " #10 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n" " #11 pc 0000fe03 anonymous:ee74c000 (int Main.compare(Main, Main)+51)\n" " #12 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n" " #13 pc 00146ab5 libartd.so " - "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+885)\n" " #14 pc 0039cf0d libartd.so " - "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_" - "11ShadowFrameEtPNS_6JValueE+653)\n" + "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " + "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n" " #15 pc 00392552 libartd.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+354)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+354)\n" " #16 pc 0039399a libartd.so " - "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n" + "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " + "const&, art::ShadowFrame*)+234)\n" " #17 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n" " #18 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n" " #19 pc 0000fd3b anonymous:ee74c000 (int Main.compare(java.lang.Object, " "java.lang.Object)+107)\n" " #20 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n" " #21 pc 00146ab5 libartd.so " - "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+885)\n" " #22 pc 0039cf0d libartd.so " - "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_" - "11ShadowFrameEtPNS_6JValueE+653)\n" + "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " + "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n" " #23 pc 00392552 libartd.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+354)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+354)\n" " #24 pc 0039399a libartd.so " - "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n" + "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " + "const&, art::ShadowFrame*)+234)\n" " #25 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n" " #26 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n" " #27 pc 0000fbdb anonymous:ee74c000 (int " @@ -351,81 +355,86 @@ TEST_F(UnwindOfflineTest, jit_debug_x86) { "java.util.Comparator)+331)\n" " #28 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n" " #29 pc 00146acb libartd.so " - "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+907)\n" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+907)\n" " #30 pc 0039cf0d libartd.so " - "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_" - "11ShadowFrameEtPNS_6JValueE+653)\n" + "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " + "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n" " #31 pc 00392552 libartd.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+354)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+354)\n" " #32 pc 0039399a libartd.so " - "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n" + "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " + "const&, art::ShadowFrame*)+234)\n" " #33 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n" " #34 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n" " #35 pc 0000f624 anonymous:ee74c000 (boolean Main.foo()+164)\n" " #36 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n" " #37 pc 00146ab5 libartd.so " - "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+885)\n" " #38 pc 0039cf0d libartd.so " - "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_" - "11ShadowFrameEtPNS_6JValueE+653)\n" + "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " + "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n" " #39 pc 00392552 libartd.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+354)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+354)\n" " #40 pc 0039399a libartd.so " - "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n" + "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " + "const&, art::ShadowFrame*)+234)\n" " #41 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n" " #42 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n" " #43 pc 0000eedb anonymous:ee74c000 (void Main.runPrimary()+59)\n" " #44 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n" " #45 pc 00146ab5 libartd.so " - "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+885)\n" " #46 pc 0039cf0d libartd.so " - "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_" - "11ShadowFrameEtPNS_6JValueE+653)\n" + "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " + "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n" " #47 pc 00392552 libartd.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+354)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+354)\n" " #48 pc 0039399a libartd.so " - "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n" + "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " + "const&, art::ShadowFrame*)+234)\n" " #49 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n" " #50 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n" " #51 pc 0000ac21 anonymous:ee74c000 (void Main.main(java.lang.String[])+97)\n" " #52 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n" " #53 pc 00146acb libartd.so " - "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+907)\n" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+907)\n" " #54 pc 0039cf0d libartd.so " - "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_" - "11ShadowFrameEtPNS_6JValueE+653)\n" + "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " + "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n" " #55 pc 00392552 libartd.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+354)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+354)\n" " #56 pc 0039399a libartd.so " - "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n" + "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " + "const&, art::ShadowFrame*)+234)\n" " #57 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n" " #58 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n" " #59 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n" " #60 pc 00146acb libartd.so " - "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+907)\n" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+907)\n" " #61 pc 005aac95 libartd.so " - "(_ZN3artL18InvokeWithArgArrayERKNS_33ScopedObjectAccessAlreadyRunnableEPNS_9ArtMethodEPNS_" - "8ArgArrayEPNS_6JValueEPKc+85)\n" + "(art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, " + "art::ArgArray*, art::JValue*, char const*)+85)\n" " #62 pc 005aab5a libartd.so " - "(_ZN3art17InvokeWithVarArgsERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectP10_" - "jmethodIDPc+362)\n" + "(art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, " + "_jmethodID*, char*)+362)\n" " #63 pc 0048a3dd libartd.so " - "(_ZN3art3JNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDPc+125)\n" + "(art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, char*)+125)\n" " #64 pc 0018448c libartd.so " - "(_ZN3art8CheckJNI11CallMethodVEPKcP7_JNIEnvP8_jobjectP7_jclassP10_jmethodIDPcNS_" - "9Primitive4TypeENS_10InvokeTypeE+1964)\n" + "(art::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, char*, " + "art::Primitive::Type, art::InvokeType)+1964)\n" " #65 pc 0017cf06 libartd.so " - "(_ZN3art8CheckJNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDPc+70)\n" + "(art::CheckJNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, char*)+70)\n" " #66 pc 00001d8c dalvikvm32 " - "(_ZN7_JNIEnv20CallStaticVoidMethodEP7_jclassP10_jmethodIDz+60)\n" + "(_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+60)\n" " #67 pc 00001a80 dalvikvm32 (main+1312)\n" " #68 pc 00018275 libc.so\n", frame_info); @@ -597,32 +606,34 @@ TEST_F(UnwindOfflineTest, jit_debug_arm) { " #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" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+864)\n" " #06 pc 00247833 libartd.so " - "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_" - "11ShadowFrameEtPNS_6JValueE+382)\n" + "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " + "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n" " #07 pc 0022e935 libartd.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+244)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+244)\n" " #08 pc 0022f71d libartd.so " - "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n" + "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " + "const&, art::ShadowFrame*)+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" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+864)\n" " #15 pc 00247833 libartd.so " - "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_" - "11ShadowFrameEtPNS_6JValueE+382)\n" + "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " + "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n" " #16 pc 0022e935 libartd.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+244)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+244)\n" " #17 pc 0022f71d libartd.so " - "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n" + "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " + "const&, art::ShadowFrame*)+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, " @@ -630,16 +641,17 @@ TEST_F(UnwindOfflineTest, jit_debug_arm) { " #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" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+864)\n" " #24 pc 00247833 libartd.so " - "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_" - "11ShadowFrameEtPNS_6JValueE+382)\n" + "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " + "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n" " #25 pc 0022e935 libartd.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+244)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+244)\n" " #26 pc 0022f71d libartd.so " - "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n" + "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " + "const&, art::ShadowFrame*)+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 " @@ -648,85 +660,90 @@ TEST_F(UnwindOfflineTest, jit_debug_arm) { " #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" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+882)\n" " #33 pc 00247833 libartd.so " - "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_" - "11ShadowFrameEtPNS_6JValueE+382)\n" + "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " + "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n" " #34 pc 0022e935 libartd.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+244)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+244)\n" " #35 pc 0022f71d libartd.so " - "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n" + "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " + "const&, art::ShadowFrame*)+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" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+864)\n" " #42 pc 00247833 libartd.so " - "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_" - "11ShadowFrameEtPNS_6JValueE+382)\n" + "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " + "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n" " #43 pc 0022e935 libartd.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+244)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+244)\n" " #44 pc 0022f71d libartd.so " - "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n" + "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " + "const&, art::ShadowFrame*)+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" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+864)\n" " #51 pc 00247833 libartd.so " - "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_" - "11ShadowFrameEtPNS_6JValueE+382)\n" + "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " + "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n" " #52 pc 0022e935 libartd.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+244)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+244)\n" " #53 pc 0022f71d libartd.so " - "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n" + "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " + "const&, art::ShadowFrame*)+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" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+882)\n" " #60 pc 00247833 libartd.so " - "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_" - "11ShadowFrameEtPNS_6JValueE+382)\n" + "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " + "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n" " #61 pc 0022e935 libartd.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+244)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+244)\n" " #62 pc 0022f71d libartd.so " - "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n" + "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " + "const&, art::ShadowFrame*)+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" + "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " + "const*)+882)\n" " #68 pc 003b292d libartd.so " - "(_ZN3artL18InvokeWithArgArrayERKNS_33ScopedObjectAccessAlreadyRunnableEPNS_9ArtMethodEPNS_" - "8ArgArrayEPNS_6JValueEPKc+52)\n" + "(art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, " + "art::ArgArray*, art::JValue*, char const*)+52)\n" " #69 pc 003b26c3 libartd.so " - "(_ZN3art17InvokeWithVarArgsERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectP10_" - "jmethodIDSt9__va_list+210)\n" + "(art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, " + "_jmethodID*, std::__va_list)+210)\n" " #70 pc 00308411 libartd.so " - "(_ZN3art3JNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDSt9__va_list+76)\n" + "(art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+76)\n" " #71 pc 000e6a9f libartd.so " - "(_ZN3art8CheckJNI11CallMethodVEPKcP7_JNIEnvP8_jobjectP7_jclassP10_jmethodIDSt9__va_listNS_" - "9Primitive4TypeENS_10InvokeTypeE+1486)\n" + "(art::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, " + "std::__va_list, art::Primitive::Type, art::InvokeType)+1486)\n" " #72 pc 000e19b9 libartd.so " - "(_ZN3art8CheckJNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDSt9__va_list+40)\n" + "(art::CheckJNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+40)\n" " #73 pc 0000159f dalvikvm32 " - "(_ZN7_JNIEnv20CallStaticVoidMethodEP7_jclassP10_jmethodIDz+30)\n" + "(_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+30)\n" " #74 pc 00001349 dalvikvm32 (main+896)\n" " #75 pc 000850c9 libc.so\n", frame_info); @@ -997,41 +1014,44 @@ TEST_F(UnwindOfflineTest, art_quick_osr_stub_arm) { "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n" " #02 pc 004135bb libart.so (art_quick_osr_stub+42)\n" " #03 pc 002657a5 libart.so " - "(_ZN3art3jit3Jit25MaybeDoOnStackReplacementEPNS_6ThreadEPNS_9ArtMethodEjiPNS_6JValueE+876)\n" + "(art::jit::Jit::MaybeDoOnStackReplacement(art::Thread*, art::ArtMethod*, unsigned int, int, " + "art::JValue*)+876)\n" " #04 pc 004021a7 libart.so (MterpMaybeDoOnStackReplacement+86)\n" " #05 pc 00412474 libart.so (ExecuteMterpImpl+66164)\n" " #06 pc cd8365b0 \n" // symbol in dex file " #07 pc 001d7f1b libart.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+374)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+374)\n" " #08 pc 001dc593 libart.so " - "(_ZN3art11interpreter33ArtInterpreterToInterpreterBridgeEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameEPNS_6JValueE+154)\n" + "(art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, " + "art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*)+154)\n" " #09 pc 001f4d01 libart.so " - "(_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_" - "11InstructionEtPNS_6JValueE+732)\n" + "(bool art::interpreter::DoCall(art::ArtMethod*, art::Thread*, " + "art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+732)\n" " #10 pc 003fe427 libart.so (MterpInvokeInterface+1354)\n" " #11 pc 00405b94 libart.so (ExecuteMterpImpl+14740)\n" " #12 pc 7004873e \n" // symbol in dex file " #13 pc 001d7f1b libart.so " - "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_" - "6JValueEb+374)\n" + "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " + "art::ShadowFrame&, art::JValue, bool)+374)\n" " #14 pc 001dc4d5 libart.so " - "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_" - "20CodeItemDataAccessorEPNS_11ShadowFrameE+92)\n" + "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " + "const&, art::ShadowFrame*)+92)\n" " #15 pc 003f25ab libart.so (artQuickToInterpreterBridge+970)\n" " #16 pc 00417aff libart.so (art_quick_to_interpreter_bridge+30)\n" " #17 pc 00413575 libart.so (art_quick_invoke_stub_internal+68)\n" " #18 pc 00418531 libart.so (art_quick_invoke_stub+236)\n" - " #19 pc 000b468d libart.so (_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+136)\n" + " #19 pc 000b468d libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned " + "int, art::JValue*, char const*)+136)\n" " #20 pc 00362f49 libart.so " - "(_ZN3art12_GLOBAL__N_118InvokeWithArgArrayERKNS_33ScopedObjectAccessAlreadyRunnableEPNS_" - "9ArtMethodEPNS0_8ArgArrayEPNS_6JValueEPKc+52)\n" + "(art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable " + "const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char " + "const*)+52)\n" " #21 pc 00363cd9 libart.so " - "(_ZN3art35InvokeVirtualOrInterfaceWithJValuesERKNS_33ScopedObjectAccessAlreadyRunnableEP8_" - "jobjectP10_jmethodIDP6jvalue+332)\n" - " #22 pc 003851dd libart.so (_ZN3art6Thread14CreateCallbackEPv+868)\n" - " #23 pc 00062925 libc.so (_ZL15__pthread_startPv+22)\n" + "(art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, " + "_jobject*, _jmethodID*, jvalue*)+332)\n" + " #22 pc 003851dd libart.so (art::Thread::CreateCallback(void*)+868)\n" + " #23 pc 00062925 libc.so (__pthread_start(void*)+22)\n" " #24 pc 0001de39 libc.so (__start_thread+24)\n", frame_info); EXPECT_EQ(0xd025c788U, unwinder.frames()[0].pc); @@ -1107,8 +1127,8 @@ TEST_F(UnwindOfflineTest, jit_map_arm) { "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n" " #02 pc 004135bb libart.so (art_quick_osr_stub+42)\n" - " #03 pc 003851dd libart.so (_ZN3art6Thread14CreateCallbackEPv+868)\n" - " #04 pc 00062925 libc.so (_ZL15__pthread_startPv+22)\n" + " #03 pc 003851dd libart.so (art::Thread::CreateCallback(void*)+868)\n" + " #04 pc 00062925 libc.so (__pthread_start(void*)+22)\n" " #05 pc 0001de39 libc.so (__start_thread+24)\n", frame_info); @@ -1139,22 +1159,22 @@ TEST_F(UnwindOfflineTest, offset_arm) { " #01 pc 0032bfeb libunwindstack_test (SignalMiddleFunction+2)\n" " #02 pc 0032bff3 libunwindstack_test (SignalOuterFunction+2)\n" " #03 pc 0032fed3 libunwindstack_test " - "(_ZN11unwindstackL19SignalCallerHandlerEiP7siginfoPv+26)\n" + "(unwindstack::SignalCallerHandler(int, siginfo*, void*)+26)\n" " #04 pc 00026528 libc.so\n" " #05 pc 00000000 \n" " #06 pc 0032c2d9 libunwindstack_test (InnerFunction+736)\n" " #07 pc 0032cc4f libunwindstack_test (MiddleFunction+42)\n" " #08 pc 0032cc81 libunwindstack_test (OuterFunction+42)\n" " #09 pc 0032e547 libunwindstack_test " - "(_ZN11unwindstackL19RemoteThroughSignalEij+270)\n" + "(unwindstack::RemoteThroughSignal(int, unsigned int)+270)\n" " #10 pc 0032ed99 libunwindstack_test " - "(_ZN11unwindstack55UnwindTest_remote_through_signal_with_invalid_func_Test8TestBodyEv+16)\n" - " #11 pc 00354453 libunwindstack_test (_ZN7testing4Test3RunEv+154)\n" - " #12 pc 00354de7 libunwindstack_test (_ZN7testing8TestInfo3RunEv+194)\n" - " #13 pc 00355105 libunwindstack_test (_ZN7testing8TestCase3RunEv+180)\n" + "(unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+16)\n" + " #11 pc 00354453 libunwindstack_test (testing::Test::Run()+154)\n" + " #12 pc 00354de7 libunwindstack_test (testing::TestInfo::Run()+194)\n" + " #13 pc 00355105 libunwindstack_test (testing::TestCase::Run()+180)\n" " #14 pc 0035a215 libunwindstack_test " - "(_ZN7testing8internal12UnitTestImpl11RunAllTestsEv+664)\n" - " #15 pc 00359f4f libunwindstack_test (_ZN7testing8UnitTest3RunEv+110)\n" + "(testing::internal::UnitTestImpl::RunAllTests()+664)\n" + " #15 pc 00359f4f libunwindstack_test (testing::UnitTest::Run()+110)\n" " #16 pc 0034d3db libunwindstack_test (main+38)\n" " #17 pc 00092c0d libc.so (__libc_init+48)\n" " #18 pc 0004202f libunwindstack_test (_start_main+38)\n", @@ -1213,9 +1233,9 @@ TEST_F(UnwindOfflineTest, debug_frame_load_bias_arm) { EXPECT_EQ( " #00 pc 0005138c libc.so (__ioctl+8)\n" " #01 pc 0002140f libc.so (ioctl+30)\n" - " #02 pc 00039535 libbinder.so (_ZN7android14IPCThreadState14talkWithDriverEb+204)\n" - " #03 pc 00039633 libbinder.so (_ZN7android14IPCThreadState20getAndExecuteCommandEv+10)\n" - " #04 pc 00039b57 libbinder.so (_ZN7android14IPCThreadState14joinThreadPoolEb+38)\n" + " #02 pc 00039535 libbinder.so (android::IPCThreadState::talkWithDriver(bool)+204)\n" + " #03 pc 00039633 libbinder.so (android::IPCThreadState::getAndExecuteCommand()+10)\n" + " #04 pc 00039b57 libbinder.so (android::IPCThreadState::joinThreadPool(bool)+38)\n" " #05 pc 00000c21 mediaserver (main+104)\n" " #06 pc 00084b89 libc.so (__libc_init+48)\n" " #07 pc 00000b77 mediaserver (_start_main+38)\n", diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp index ea992c790..a91bd9506 100644 --- a/libunwindstack/tests/UnwindTest.cpp +++ b/libunwindstack/tests/UnwindTest.cpp @@ -44,6 +44,13 @@ namespace unwindstack { +enum TestTypeEnum : uint8_t { + TEST_TYPE_LOCAL_UNWINDER = 0, + TEST_TYPE_LOCAL_UNWINDER_FROM_PID, + TEST_TYPE_REMOTE, + TEST_TYPE_REMOTE_WITH_INVALID_CALL, +}; + static std::atomic_bool g_ready; static volatile bool g_ready_for_remote; static volatile bool g_signal_ready_for_remote; @@ -88,10 +95,10 @@ static void SignalCallerHandler(int, siginfo_t*, void*) { SignalOuterFunction(); } -static std::string ErrorMsg(const std::vector& function_names, Unwinder& unwinder) { +static std::string ErrorMsg(const std::vector& function_names, Unwinder* unwinder) { std::string unwind; - for (size_t i = 0; i < unwinder.NumFrames(); i++) { - unwind += unwinder.FormatFrame(i) + '\n'; + for (size_t i = 0; i < unwinder->NumFrames(); i++) { + unwind += unwinder->FormatFrame(i) + '\n'; } return std::string( @@ -100,14 +107,10 @@ static std::string ErrorMsg(const std::vector& function_names, Unwi function_names.front() + "\n" + "Unwind data:\n" + unwind; } -static void VerifyUnwind(pid_t pid, Maps* maps, Regs* regs, - std::vector expected_function_names) { - auto process_memory(Memory::CreateProcessMemory(pid)); +static void VerifyUnwind(Unwinder* unwinder, std::vector expected_function_names) { + unwinder->Unwind(); - Unwinder unwinder(512, maps, regs, process_memory); - unwinder.Unwind(); - - for (auto& frame : unwinder.frames()) { + for (auto& frame : unwinder->frames()) { if (frame.function_name == expected_function_names.back()) { expected_function_names.pop_back(); if (expected_function_names.empty()) { @@ -119,35 +122,55 @@ static void VerifyUnwind(pid_t pid, Maps* maps, Regs* regs, ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, unwinder); } +static void VerifyUnwind(pid_t pid, Maps* maps, Regs* regs, + std::vector expected_function_names) { + auto process_memory(Memory::CreateProcessMemory(pid)); + + Unwinder unwinder(512, maps, regs, process_memory); + VerifyUnwind(&unwinder, expected_function_names); +} + // This test assumes that this code is compiled with optimizations turned // off. If this doesn't happen, then all of the calls will be optimized // away. -extern "C" void InnerFunction(bool local, bool trigger_invalid_call) { - if (local) { - LocalMaps maps; - ASSERT_TRUE(maps.Parse()); - std::unique_ptr regs(Regs::CreateFromLocal()); - RegsGetLocal(regs.get()); - - VerifyUnwind(getpid(), &maps, regs.get(), kFunctionOrder); - } else { +extern "C" void InnerFunction(TestTypeEnum test_type) { + if (test_type == TEST_TYPE_REMOTE || test_type == TEST_TYPE_REMOTE_WITH_INVALID_CALL) { g_ready_for_remote = true; g_ready = true; - if (trigger_invalid_call) { + if (test_type == TEST_TYPE_REMOTE_WITH_INVALID_CALL) { void (*crash_func)() = nullptr; crash_func(); } while (!g_finish.load()) { } + return; } + + std::unique_ptr unwinder; + std::unique_ptr regs(Regs::CreateFromLocal()); + RegsGetLocal(regs.get()); + std::unique_ptr maps; + + if (test_type == TEST_TYPE_LOCAL_UNWINDER) { + maps.reset(new LocalMaps()); + ASSERT_TRUE(maps->Parse()); + auto process_memory(Memory::CreateProcessMemory(getpid())); + unwinder.reset(new Unwinder(512, maps.get(), regs.get(), process_memory)); + } else { + UnwinderFromPid* unwinder_from_pid = new UnwinderFromPid(512, getpid()); + ASSERT_TRUE(unwinder_from_pid->Init(regs->Arch())); + unwinder_from_pid->SetRegs(regs.get()); + unwinder.reset(unwinder_from_pid); + } + VerifyUnwind(unwinder.get(), kFunctionOrder); } -extern "C" void MiddleFunction(bool local, bool trigger_invalid_call) { - InnerFunction(local, trigger_invalid_call); +extern "C" void MiddleFunction(TestTypeEnum test_type) { + InnerFunction(test_type); } -extern "C" void OuterFunction(bool local, bool trigger_invalid_call) { - MiddleFunction(local, trigger_invalid_call); +extern "C" void OuterFunction(TestTypeEnum test_type) { + MiddleFunction(test_type); } class UnwindTest : public ::testing::Test { @@ -156,7 +179,11 @@ class UnwindTest : public ::testing::Test { }; TEST_F(UnwindTest, local) { - OuterFunction(true, false); + OuterFunction(TEST_TYPE_LOCAL_UNWINDER); +} + +TEST_F(UnwindTest, local_use_from_pid) { + OuterFunction(TEST_TYPE_LOCAL_UNWINDER_FROM_PID); } void WaitForRemote(pid_t pid, uint64_t addr, bool leave_attached, bool* completed) { @@ -191,7 +218,7 @@ void WaitForRemote(pid_t pid, uint64_t addr, bool leave_attached, bool* complete TEST_F(UnwindTest, remote) { pid_t pid; if ((pid = fork()) == 0) { - OuterFunction(false, false); + OuterFunction(TEST_TYPE_REMOTE); exit(0); } ASSERT_NE(-1, pid); @@ -212,11 +239,39 @@ TEST_F(UnwindTest, remote) { << "ptrace detach failed with unexpected error: " << strerror(errno); } +TEST_F(UnwindTest, unwind_from_pid_remote) { + pid_t pid; + if ((pid = fork()) == 0) { + OuterFunction(TEST_TYPE_REMOTE); + exit(0); + } + ASSERT_NE(-1, pid); + TestScopedPidReaper reap(pid); + + bool completed; + WaitForRemote(pid, reinterpret_cast(&g_ready_for_remote), true, &completed); + ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready."; + + std::unique_ptr regs(Regs::RemoteGet(pid)); + ASSERT_TRUE(regs.get() != nullptr); + + UnwinderFromPid unwinder(512, pid); + ASSERT_TRUE(unwinder.Init(regs->Arch())); + unwinder.SetRegs(regs.get()); + + VerifyUnwind(&unwinder, kFunctionOrder); + + // Verify that calling the same object works again. + + ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0)) + << "ptrace detach failed with unexpected error: " << strerror(errno); +} + TEST_F(UnwindTest, from_context) { std::atomic_int tid(0); std::thread thread([&]() { tid = syscall(__NR_gettid); - OuterFunction(false, false); + OuterFunction(TEST_TYPE_REMOTE); }); struct sigaction act, oldact; @@ -266,7 +321,7 @@ static void RemoteThroughSignal(int signal, unsigned int sa_flags) { act.sa_flags = SA_RESTART | SA_ONSTACK | sa_flags; ASSERT_EQ(0, sigaction(signal, &act, &oldact)); - OuterFunction(false, signal == SIGSEGV); + OuterFunction(signal != SIGSEGV ? TEST_TYPE_REMOTE : TEST_TYPE_REMOTE_WITH_INVALID_CALL); exit(0); } ASSERT_NE(-1, pid); diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp index 1fdeee566..49aeeb378 100644 --- a/libunwindstack/tests/UnwinderTest.cpp +++ b/libunwindstack/tests/UnwinderTest.cpp @@ -1080,6 +1080,12 @@ TEST_F(UnwinderTest, format_frame_static) { Unwinder::FormatFrame(frame, false)); EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function)", Unwinder::FormatFrame(frame, true)); + // Verify the function name is demangled. + frame.function_name = "_ZN4funcEv"; + EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (func())", + Unwinder::FormatFrame(frame, false)); + EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (func())", Unwinder::FormatFrame(frame, true)); + frame.function_name = ""; EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so", Unwinder::FormatFrame(frame, false)); EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so", Unwinder::FormatFrame(frame, true)); diff --git a/libunwindstack/tools/unwind.cpp b/libunwindstack/tools/unwind.cpp index e72945321..1812e5037 100644 --- a/libunwindstack/tools/unwind.cpp +++ b/libunwindstack/tools/unwind.cpp @@ -57,12 +57,6 @@ static bool Attach(pid_t pid) { } void DoUnwind(pid_t pid) { - unwindstack::RemoteMaps remote_maps(pid); - if (!remote_maps.Parse()) { - printf("Failed to parse map data.\n"); - return; - } - unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid); if (regs == nullptr) { printf("Unable to get remote reg data\n"); @@ -95,15 +89,13 @@ void DoUnwind(pid_t pid) { } printf("\n"); - auto process_memory = unwindstack::Memory::CreateProcessMemory(pid); - unwindstack::Unwinder unwinder(128, &remote_maps, regs, process_memory); - - unwindstack::JitDebug jit_debug(process_memory); - unwinder.SetJitDebug(&jit_debug, regs->Arch()); - - unwindstack::DexFiles dex_files(process_memory); - unwinder.SetDexFiles(&dex_files, regs->Arch()); + unwindstack::UnwinderFromPid unwinder(1024, pid); + if (!unwinder.Init(regs->Arch())) { + printf("Failed to init unwinder object.\n"); + return; + } + unwinder.SetRegs(regs); unwinder.Unwind(); // Print the frames. diff --git a/libunwindstack/tools/unwind_for_offline.cpp b/libunwindstack/tools/unwind_for_offline.cpp index 5ae887458..4f67d679f 100644 --- a/libunwindstack/tools/unwind_for_offline.cpp +++ b/libunwindstack/tools/unwind_for_offline.cpp @@ -240,12 +240,6 @@ int SaveData(pid_t pid) { return 1; } - unwindstack::RemoteMaps maps(pid); - if (!maps.Parse()) { - printf("Unable to parse maps.\n"); - return 1; - } - // Save the current state of the registers. if (!SaveRegs(regs)) { return 1; @@ -253,35 +247,38 @@ int SaveData(pid_t pid) { // Do an unwind so we know how much of the stack to save, and what // elf files are involved. + unwindstack::UnwinderFromPid unwinder(1024, pid); + if (!unwinder.Init(regs->Arch())) { + printf("Unable to init unwinder object.\n"); + return 1; + } + unwinder.SetRegs(regs); uint64_t sp = regs->sp(); - auto process_memory = unwindstack::Memory::CreateProcessMemory(pid); - unwindstack::JitDebug jit_debug(process_memory); - unwindstack::Unwinder unwinder(1024, &maps, regs, process_memory); - unwinder.SetJitDebug(&jit_debug, regs->Arch()); unwinder.Unwind(); std::unordered_map maps_by_start; std::vector> stacks; + unwindstack::Maps* maps = unwinder.GetMaps(); uint64_t sp_map_start = 0; - unwindstack::MapInfo* map_info = maps.Find(sp); + unwindstack::MapInfo* map_info = maps->Find(sp); if (map_info != nullptr) { stacks.emplace_back(std::make_pair(sp, map_info->end)); sp_map_start = map_info->start; } for (const auto& frame : unwinder.frames()) { - map_info = maps.Find(frame.sp); + map_info = maps->Find(frame.sp); if (map_info != nullptr && sp_map_start != map_info->start) { stacks.emplace_back(std::make_pair(frame.sp, map_info->end)); sp_map_start = map_info->start; } if (maps_by_start.count(frame.map_start) == 0) { - map_info = maps.Find(frame.map_start); + map_info = maps->Find(frame.map_start); auto info = FillInAndGetMapInfo(maps_by_start, map_info); bool file_copied = false; - SaveMapInformation(process_memory, info, &file_copied); + SaveMapInformation(unwinder.GetProcessMemory(), info, &file_copied); // If you are using a a linker that creates two maps (one read-only, one // read-executable), it's necessary to capture the previous map @@ -291,7 +288,7 @@ int SaveData(pid_t pid) { prev_map->flags == PROT_READ && map_info->name == prev_map->name && maps_by_start.count(prev_map->start) == 0) { info = FillInAndGetMapInfo(maps_by_start, prev_map); - SaveMapInformation(process_memory, info, &file_copied); + SaveMapInformation(unwinder.GetProcessMemory(), info, &file_copied); } } }