Add support for UnwinderFromPid object.
This object is able to be easily used from other code and can be used to replace the libbacktrace calls in other parts of the platform. Also, demangle the function names when calling FormatFrame. Bug: 120606663 Test: Unit tests pass, debuggerd using this code directly passes unit Test: tests. Change-Id: Ifd8cf9bdd89174c1736810711d20e9f37f29b1bf
This commit is contained in:
parent
61f4ceb55a
commit
eb0772ff4a
11 changed files with 438 additions and 218 deletions
|
@ -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",
|
||||
|
|
|
@ -221,6 +221,19 @@ Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& 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<std::mutex> 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<Memory>& process_memory) {
|
||||
uint64_t cur_load_bias = load_bias.load();
|
||||
if (cur_load_bias != static_cast<uint64_t>(-1)) {
|
||||
|
|
|
@ -26,10 +26,13 @@
|
|||
|
||||
#include <android-base/stringprintf.h>
|
||||
|
||||
#include <demangle.h>
|
||||
|
||||
#include <unwindstack/Elf.h>
|
||||
#include <unwindstack/JitDebug.h>
|
||||
#include <unwindstack/MapInfo.h>
|
||||
#include <unwindstack/Maps.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
#include <unwindstack/Unwinder.h>
|
||||
|
||||
#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
|
||||
|
|
|
@ -75,6 +75,8 @@ struct MapInfo {
|
|||
|
||||
Memory* CreateMemory(const std::shared_ptr<Memory>& process_memory);
|
||||
|
||||
bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset);
|
||||
|
||||
private:
|
||||
MapInfo(const MapInfo&) = delete;
|
||||
void operator=(const MapInfo&) = delete;
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <unwindstack/DexFiles.h>
|
||||
#include <unwindstack/Error.h>
|
||||
#include <unwindstack/JitDebug.h>
|
||||
#include <unwindstack/Maps.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
#include <unwindstack/Regs.h>
|
||||
|
@ -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<Memory> process_memory)
|
||||
: max_frames_(max_frames), maps_(maps), process_memory_(process_memory) {
|
||||
frames_.reserve(max_frames);
|
||||
}
|
||||
|
||||
~Unwinder() = default;
|
||||
|
||||
void Unwind(const std::vector<std::string>* 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<Memory>& 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> maps_ptr_;
|
||||
std::unique_ptr<JitDebug> jit_debug_ptr_;
|
||||
#if !defined(NO_LIBDEXFILE_SUPPORT)
|
||||
std::unique_ptr<DexFiles> dex_files_ptr_;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
||||
#endif // _LIBUNWINDSTACK_UNWINDER_H
|
||||
|
|
75
libunwindstack/tests/MapInfoTest.cpp
Normal file
75
libunwindstack/tests/MapInfoTest.cpp
Normal file
|
@ -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 <stdint.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <unwindstack/MapInfo.h>
|
||||
#include <unwindstack/Maps.h>
|
||||
|
||||
#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<uint64_t>(-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<uint64_t>(-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
|
|
@ -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 <unknown>\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<false, false>(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 <unknown>\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 <unknown>\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",
|
||||
|
|
|
@ -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<const char*>& function_names, Unwinder& unwinder) {
|
||||
static std::string ErrorMsg(const std::vector<const char*>& 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<const char*>& function_names, Unwi
|
|||
function_names.front() + "\n" + "Unwind data:\n" + unwind;
|
||||
}
|
||||
|
||||
static void VerifyUnwind(pid_t pid, Maps* maps, Regs* regs,
|
||||
std::vector<const char*> expected_function_names) {
|
||||
auto process_memory(Memory::CreateProcessMemory(pid));
|
||||
static void VerifyUnwind(Unwinder* unwinder, std::vector<const char*> 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<const char*> 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(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> unwinder;
|
||||
std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
|
||||
RegsGetLocal(regs.get());
|
||||
std::unique_ptr<Maps> 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<uint64_t>(&g_ready_for_remote), true, &completed);
|
||||
ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
|
||||
|
||||
std::unique_ptr<Regs> 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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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<uint64_t, map_info_t> maps_by_start;
|
||||
std::vector<std::pair<uint64_t, uint64_t>> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue