Merge "Add support for UnwinderFromPid object."
This commit is contained in:
commit
b94c2e52a6
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…
Add table
Reference in a new issue