Loading debuggerd/crasher/crasher.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,11 @@ noinline int do_action_on_thread(const char* arg) { return reinterpret_cast<uintptr_t>(result); } noinline int crash_null() { int (*null_func)() = nullptr; return null_func(); } noinline int crash3(int a) { *reinterpret_cast<int*>(0xdead) = a; return a*4; Loading Loading @@ -169,6 +174,7 @@ static int usage() { fprintf(stderr, " nostack crash with a NULL stack pointer\n"); fprintf(stderr, "\n"); fprintf(stderr, " heap-usage cause a libc abort by abusing a heap function\n"); fprintf(stderr, " call-null cause a crash by calling through a nullptr\n"); fprintf(stderr, " leak leak memory until we get OOM-killed\n"); fprintf(stderr, "\n"); fprintf(stderr, " abort call abort()\n"); Loading Loading @@ -239,6 +245,8 @@ noinline int do_action(const char* arg) { crashnostack(); } else if (!strcasecmp(arg, "exit")) { exit(1); } else if (!strcasecmp(arg, "call-null")) { return crash_null(); } else if (!strcasecmp(arg, "crash") || !strcmp(arg, "SIGSEGV")) { return crash(42); } else if (!strcasecmp(arg, "abort")) { Loading libbacktrace/UnwindStack.cpp +105 −53 Original line number Diff line number Diff line Loading @@ -68,6 +68,32 @@ static bool IsUnwindLibrary(const std::string& map_name) { return library == "libunwindstack.so" || library == "libbacktrace.so"; } static void SetFrameInfo(unwindstack::Regs* regs, unwindstack::MapInfo* map_info, uint64_t adjusted_rel_pc, backtrace_frame_data_t* frame) { // This will point to the adjusted absolute pc. regs->pc() is // unaltered. frame->pc = map_info->start + adjusted_rel_pc; frame->sp = regs->sp(); frame->rel_pc = adjusted_rel_pc; frame->stack_size = 0; frame->map.start = map_info->start; frame->map.end = map_info->end; frame->map.offset = map_info->offset; frame->map.flags = map_info->flags; frame->map.name = map_info->name; unwindstack::Elf* elf = map_info->elf; frame->map.load_bias = elf->GetLoadBias(); uint64_t func_offset = 0; if (elf->GetFunctionName(adjusted_rel_pc, &frame->func_name, &func_offset)) { frame->func_name = demangle(frame->func_name.c_str()); } else { frame->func_name = ""; } frame->func_offset = func_offset; } static bool Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames) { UnwindStackMap* stack_map = reinterpret_cast<UnwindStackMap*>(back_map); Loading @@ -75,70 +101,96 @@ static bool Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, bool adjust_rel_pc = false; size_t num_frames = 0; frames->clear(); bool return_address_attempted = false; auto process_memory = stack_map->process_memory(); while (num_frames < MAX_BACKTRACE_FRAMES) { if (regs->pc() == 0) { break; } unwindstack::MapInfo* map_info = maps->Find(regs->pc()); bool stepped; bool in_device_map = false; if (map_info == nullptr) { break; stepped = false; if (num_ignore_frames == 0) { frames->resize(num_frames + 1); backtrace_frame_data_t* frame = &frames->at(num_frames); frame->pc = regs->pc(); frame->sp = regs->sp(); frame->rel_pc = frame->pc; num_frames++; } else { num_ignore_frames--; } unwindstack::Elf* elf = map_info->GetElf(stack_map->process_memory(), true); } else { unwindstack::Elf* elf = map_info->GetElf(process_memory, true); uint64_t rel_pc = elf->GetRelPc(regs->pc(), map_info); bool skip_frame = num_frames == 0 && IsUnwindLibrary(map_info->name); if (num_ignore_frames == 0 && !skip_frame) { if (frames->size() != 0 || !IsUnwindLibrary(map_info->name)) { if (num_ignore_frames == 0) { uint64_t adjusted_rel_pc = rel_pc; if (adjust_rel_pc) { adjusted_rel_pc = regs->GetAdjustedPc(rel_pc, elf); } frames->resize(num_frames + 1); backtrace_frame_data_t* frame = &frames->at(num_frames); frame->num = num_frames; // This will point to the adjusted absolute pc. regs->pc() is // unaltered. frame->pc = map_info->start + adjusted_rel_pc; frame->sp = regs->sp(); frame->rel_pc = adjusted_rel_pc; frame->stack_size = 0; SetFrameInfo(regs, map_info, adjusted_rel_pc, frame); frame->map.start = map_info->start; frame->map.end = map_info->end; frame->map.offset = map_info->offset; frame->map.load_bias = elf->GetLoadBias(); frame->map.flags = map_info->flags; frame->map.name = map_info->name; uint64_t func_offset = 0; if (elf->GetFunctionName(adjusted_rel_pc, &frame->func_name, &func_offset)) { frame->func_name = demangle(frame->func_name.c_str()); } else { frame->func_name = ""; } frame->func_offset = func_offset; if (num_frames > 0) { // Set the stack size for the previous frame. backtrace_frame_data_t* prev = &frames->at(num_frames - 1); prev->stack_size = frame->sp - prev->sp; } num_frames++; } else if (!skip_frame && num_ignore_frames > 0) { } else { num_ignore_frames--; } adjust_rel_pc = true; } // Do not unwind through a device map. if (map_info->flags & PROT_DEVICE_MAP) { break; } // Do not stop here, fall through in case we are // in the speculative unwind path and need to remove // some of the speculative frames. stepped = false; in_device_map = true; } else { unwindstack::MapInfo* sp_info = maps->Find(regs->sp()); if (sp_info->flags & PROT_DEVICE_MAP) { // Do not stop here, fall through in case we are // in the speculative unwind path and need to remove // some of the speculative frames. stepped = false; in_device_map = true; } else { bool finished; stepped = elf->Step(rel_pc + map_info->elf_offset, regs, process_memory.get(), &finished); if (stepped && finished) { break; } } } } adjust_rel_pc = true; if (!elf->Step(rel_pc + map_info->elf_offset, regs, stack_map->process_memory().get())) { if (!stepped) { if (return_address_attempted) { // Remove the speculative frame. if (frames->size() > 0) { frames->pop_back(); } break; } else if (in_device_map) { // Do not attempt any other unwinding, pc or sp is in a device // map. break; } else { // Stepping didn't work, try this secondary method. if (!regs->SetPcFromReturnAddress(process_memory.get())) { break; } return_address_attempted = true; } } else { return_address_attempted = false; } } Loading libbacktrace/backtrace_test.cpp +34 −22 Original line number Diff line number Diff line Loading @@ -82,6 +82,14 @@ struct dump_thread_t { int32_t done; }; typedef Backtrace* (*create_func_t)(pid_t, pid_t, BacktraceMap*); typedef BacktraceMap* (*map_create_func_t)(pid_t, bool); static void VerifyLevelDump(Backtrace* backtrace, create_func_t create_func = nullptr, map_create_func_t map_func = nullptr); static void VerifyMaxDump(Backtrace* backtrace, create_func_t create_func = nullptr, map_create_func_t map_func = nullptr); static uint64_t NanoTime() { struct timespec t = { 0, 0 }; clock_gettime(CLOCK_MONOTONIC, &t); Loading Loading @@ -147,7 +155,7 @@ static bool ReadyLevelBacktrace(Backtrace* backtrace) { return found; } static void VerifyLevelDump(Backtrace* backtrace) { static void VerifyLevelDump(Backtrace* backtrace, create_func_t, map_create_func_t) { ASSERT_GT(backtrace->NumFrames(), static_cast<size_t>(0)) << DumpFrames(backtrace); ASSERT_LT(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES)) Loading Loading @@ -189,7 +197,7 @@ static bool ReadyMaxBacktrace(Backtrace* backtrace) { return (backtrace->NumFrames() == MAX_BACKTRACE_FRAMES); } static void VerifyMaxDump(Backtrace* backtrace) { static void VerifyMaxDump(Backtrace* backtrace, create_func_t, map_create_func_t) { ASSERT_EQ(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES)) << DumpFrames(backtrace); // Verify that the last frame is our recursive call. Loading Loading @@ -251,10 +259,14 @@ TEST(libbacktrace, local_trace) { static void VerifyIgnoreFrames(Backtrace* bt_all, Backtrace* bt_ign1, Backtrace* bt_ign2, const char* cur_proc) { EXPECT_EQ(bt_all->NumFrames(), bt_ign1->NumFrames() + 1) << "All backtrace:\n" << DumpFrames(bt_all) << "Ignore 1 backtrace:\n" << DumpFrames(bt_ign1); EXPECT_EQ(bt_all->NumFrames(), bt_ign2->NumFrames() + 2) << "All backtrace:\n" << DumpFrames(bt_all) << "Ignore 2 backtrace:\n" << DumpFrames(bt_ign2); ASSERT_EQ(bt_all->NumFrames(), bt_ign1->NumFrames() + 1) << "All backtrace:\n" << DumpFrames(bt_all) << "Ignore 1 backtrace:\n" << DumpFrames(bt_ign1); ASSERT_EQ(bt_all->NumFrames(), bt_ign2->NumFrames() + 2) << "All backtrace:\n" << DumpFrames(bt_all) << "Ignore 2 backtrace:\n" << DumpFrames(bt_ign2); // Check all of the frames are the same > the current frame. bool check = (cur_proc == nullptr); Loading Loading @@ -305,9 +317,8 @@ TEST(libbacktrace, local_max_trace) { } static void VerifyProcTest(pid_t pid, pid_t tid, bool (*ReadyFunc)(Backtrace*), void (*VerifyFunc)(Backtrace*), Backtrace* (*back_func)(pid_t, pid_t, BacktraceMap*), BacktraceMap* (*map_func)(pid_t, bool)) { void (*VerifyFunc)(Backtrace*, create_func_t, map_create_func_t), create_func_t create_func, map_create_func_t map_create_func) { pid_t ptrace_tid; if (tid < 0) { ptrace_tid = pid; Loading @@ -324,13 +335,13 @@ static void VerifyProcTest(pid_t pid, pid_t tid, bool (*ReadyFunc)(Backtrace*), WaitForStop(ptrace_tid); std::unique_ptr<BacktraceMap> map; map.reset(map_func(pid, false)); std::unique_ptr<Backtrace> backtrace(back_func(pid, tid, map.get())); map.reset(map_create_func(pid, false)); std::unique_ptr<Backtrace> backtrace(create_func(pid, tid, map.get())); ASSERT_TRUE(backtrace.get() != nullptr); ASSERT_TRUE(backtrace->Unwind(0)); ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError()); if (ReadyFunc(backtrace.get())) { VerifyFunc(backtrace.get()); VerifyFunc(backtrace.get(), create_func, map_create_func); verified = true; } else { last_dump = DumpFrames(backtrace.get()); Loading Loading @@ -399,13 +410,15 @@ TEST(libbacktrace, ptrace_max_trace_new) { ASSERT_EQ(waitpid(pid, &status, 0), pid); } static void VerifyProcessIgnoreFrames(Backtrace* bt_all) { std::unique_ptr<Backtrace> ign1(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD)); static void VerifyProcessIgnoreFrames(Backtrace* bt_all, create_func_t create_func, map_create_func_t map_create_func) { std::unique_ptr<BacktraceMap> map(map_create_func(bt_all->Pid(), false)); std::unique_ptr<Backtrace> ign1(create_func(bt_all->Pid(), BACKTRACE_CURRENT_THREAD, map.get())); ASSERT_TRUE(ign1.get() != nullptr); ASSERT_TRUE(ign1->Unwind(1)); ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, ign1->GetError()); std::unique_ptr<Backtrace> ign2(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD)); std::unique_ptr<Backtrace> ign2(create_func(bt_all->Pid(), BACKTRACE_CURRENT_THREAD, map.get())); ASSERT_TRUE(ign2.get() != nullptr); ASSERT_TRUE(ign2->Unwind(2)); ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, ign2->GetError()); Loading Loading @@ -1702,9 +1715,8 @@ static void SetValueAndLoop(void* data) { ; } static void UnwindThroughSignal(bool use_action, Backtrace* (*back_func)(pid_t, pid_t, BacktraceMap*), BacktraceMap* (*map_func)(pid_t, bool)) { static void UnwindThroughSignal(bool use_action, create_func_t create_func, map_create_func_t map_create_func) { volatile int value = 0; pid_t pid; if ((pid = fork()) == 0) { Loading @@ -1730,8 +1742,8 @@ static void UnwindThroughSignal(bool use_action, WaitForStop(pid); std::unique_ptr<BacktraceMap> map(map_func(pid, false)); std::unique_ptr<Backtrace> backtrace(back_func(pid, pid, map.get())); std::unique_ptr<BacktraceMap> map(map_create_func(pid, false)); std::unique_ptr<Backtrace> backtrace(create_func(pid, pid, map.get())); size_t bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(const_cast<int*>(&value)), reinterpret_cast<uint8_t*>(&read_value), sizeof(read_value)); Loading @@ -1758,9 +1770,9 @@ static void UnwindThroughSignal(bool use_action, WaitForStop(pid); map.reset(map_func(pid, false)); map.reset(map_create_func(pid, false)); ASSERT_TRUE(map.get() != nullptr); backtrace.reset(back_func(pid, pid, map.get())); backtrace.reset(create_func(pid, pid, map.get())); ASSERT_TRUE(backtrace->Unwind(0)); bool found = false; for (frame_iter = backtrace->begin(); frame_iter != backtrace->end(); ++frame_iter) { Loading libunwindstack/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ cc_library { "Maps.cpp", "Memory.cpp", "Regs.cpp", "Unwinder.cpp", "Symbols.cpp", ], Loading libunwindstack/DwarfSection.cpp +8 −5 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) { return nullptr; } bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory) { bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) { last_error_ = DWARF_ERROR_NONE; const DwarfFde* fde = GetFdeFromPc(pc); if (fde == nullptr || fde->cie == nullptr) { Loading @@ -62,7 +62,7 @@ bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory) { } // Now eval the actual registers. return Eval(fde->cie, process_memory, loc_regs, regs); return Eval(fde->cie, process_memory, loc_regs, regs, finished); } template <typename AddressType> Loading Loading @@ -92,7 +92,8 @@ bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, uin template <typename AddressType> bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs, Regs* regs) { const dwarf_loc_regs_t& loc_regs, Regs* regs, bool* finished) { RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs); if (cie->return_address_register >= cur_regs->total_regs()) { last_error_ = DWARF_ERROR_ILLEGAL_VALUE; Loading Loading @@ -224,12 +225,14 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me // Find the return address location. if (return_address_undefined) { cur_regs->set_pc(0); *finished = true; } else { cur_regs->set_pc((*cur_regs)[cie->return_address_register]); *finished = false; } cur_regs->set_sp(cfa); // Stop if the cfa and pc are the same. return prev_cfa != cfa || prev_pc != cur_regs->pc(); // Return false if the unwind is not finished or the cfa and pc didn't change. return *finished || prev_cfa != cfa || prev_pc != cur_regs->pc(); } template <typename AddressType> Loading Loading
debuggerd/crasher/crasher.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,11 @@ noinline int do_action_on_thread(const char* arg) { return reinterpret_cast<uintptr_t>(result); } noinline int crash_null() { int (*null_func)() = nullptr; return null_func(); } noinline int crash3(int a) { *reinterpret_cast<int*>(0xdead) = a; return a*4; Loading Loading @@ -169,6 +174,7 @@ static int usage() { fprintf(stderr, " nostack crash with a NULL stack pointer\n"); fprintf(stderr, "\n"); fprintf(stderr, " heap-usage cause a libc abort by abusing a heap function\n"); fprintf(stderr, " call-null cause a crash by calling through a nullptr\n"); fprintf(stderr, " leak leak memory until we get OOM-killed\n"); fprintf(stderr, "\n"); fprintf(stderr, " abort call abort()\n"); Loading Loading @@ -239,6 +245,8 @@ noinline int do_action(const char* arg) { crashnostack(); } else if (!strcasecmp(arg, "exit")) { exit(1); } else if (!strcasecmp(arg, "call-null")) { return crash_null(); } else if (!strcasecmp(arg, "crash") || !strcmp(arg, "SIGSEGV")) { return crash(42); } else if (!strcasecmp(arg, "abort")) { Loading
libbacktrace/UnwindStack.cpp +105 −53 Original line number Diff line number Diff line Loading @@ -68,6 +68,32 @@ static bool IsUnwindLibrary(const std::string& map_name) { return library == "libunwindstack.so" || library == "libbacktrace.so"; } static void SetFrameInfo(unwindstack::Regs* regs, unwindstack::MapInfo* map_info, uint64_t adjusted_rel_pc, backtrace_frame_data_t* frame) { // This will point to the adjusted absolute pc. regs->pc() is // unaltered. frame->pc = map_info->start + adjusted_rel_pc; frame->sp = regs->sp(); frame->rel_pc = adjusted_rel_pc; frame->stack_size = 0; frame->map.start = map_info->start; frame->map.end = map_info->end; frame->map.offset = map_info->offset; frame->map.flags = map_info->flags; frame->map.name = map_info->name; unwindstack::Elf* elf = map_info->elf; frame->map.load_bias = elf->GetLoadBias(); uint64_t func_offset = 0; if (elf->GetFunctionName(adjusted_rel_pc, &frame->func_name, &func_offset)) { frame->func_name = demangle(frame->func_name.c_str()); } else { frame->func_name = ""; } frame->func_offset = func_offset; } static bool Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames) { UnwindStackMap* stack_map = reinterpret_cast<UnwindStackMap*>(back_map); Loading @@ -75,70 +101,96 @@ static bool Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, bool adjust_rel_pc = false; size_t num_frames = 0; frames->clear(); bool return_address_attempted = false; auto process_memory = stack_map->process_memory(); while (num_frames < MAX_BACKTRACE_FRAMES) { if (regs->pc() == 0) { break; } unwindstack::MapInfo* map_info = maps->Find(regs->pc()); bool stepped; bool in_device_map = false; if (map_info == nullptr) { break; stepped = false; if (num_ignore_frames == 0) { frames->resize(num_frames + 1); backtrace_frame_data_t* frame = &frames->at(num_frames); frame->pc = regs->pc(); frame->sp = regs->sp(); frame->rel_pc = frame->pc; num_frames++; } else { num_ignore_frames--; } unwindstack::Elf* elf = map_info->GetElf(stack_map->process_memory(), true); } else { unwindstack::Elf* elf = map_info->GetElf(process_memory, true); uint64_t rel_pc = elf->GetRelPc(regs->pc(), map_info); bool skip_frame = num_frames == 0 && IsUnwindLibrary(map_info->name); if (num_ignore_frames == 0 && !skip_frame) { if (frames->size() != 0 || !IsUnwindLibrary(map_info->name)) { if (num_ignore_frames == 0) { uint64_t adjusted_rel_pc = rel_pc; if (adjust_rel_pc) { adjusted_rel_pc = regs->GetAdjustedPc(rel_pc, elf); } frames->resize(num_frames + 1); backtrace_frame_data_t* frame = &frames->at(num_frames); frame->num = num_frames; // This will point to the adjusted absolute pc. regs->pc() is // unaltered. frame->pc = map_info->start + adjusted_rel_pc; frame->sp = regs->sp(); frame->rel_pc = adjusted_rel_pc; frame->stack_size = 0; SetFrameInfo(regs, map_info, adjusted_rel_pc, frame); frame->map.start = map_info->start; frame->map.end = map_info->end; frame->map.offset = map_info->offset; frame->map.load_bias = elf->GetLoadBias(); frame->map.flags = map_info->flags; frame->map.name = map_info->name; uint64_t func_offset = 0; if (elf->GetFunctionName(adjusted_rel_pc, &frame->func_name, &func_offset)) { frame->func_name = demangle(frame->func_name.c_str()); } else { frame->func_name = ""; } frame->func_offset = func_offset; if (num_frames > 0) { // Set the stack size for the previous frame. backtrace_frame_data_t* prev = &frames->at(num_frames - 1); prev->stack_size = frame->sp - prev->sp; } num_frames++; } else if (!skip_frame && num_ignore_frames > 0) { } else { num_ignore_frames--; } adjust_rel_pc = true; } // Do not unwind through a device map. if (map_info->flags & PROT_DEVICE_MAP) { break; } // Do not stop here, fall through in case we are // in the speculative unwind path and need to remove // some of the speculative frames. stepped = false; in_device_map = true; } else { unwindstack::MapInfo* sp_info = maps->Find(regs->sp()); if (sp_info->flags & PROT_DEVICE_MAP) { // Do not stop here, fall through in case we are // in the speculative unwind path and need to remove // some of the speculative frames. stepped = false; in_device_map = true; } else { bool finished; stepped = elf->Step(rel_pc + map_info->elf_offset, regs, process_memory.get(), &finished); if (stepped && finished) { break; } } } } adjust_rel_pc = true; if (!elf->Step(rel_pc + map_info->elf_offset, regs, stack_map->process_memory().get())) { if (!stepped) { if (return_address_attempted) { // Remove the speculative frame. if (frames->size() > 0) { frames->pop_back(); } break; } else if (in_device_map) { // Do not attempt any other unwinding, pc or sp is in a device // map. break; } else { // Stepping didn't work, try this secondary method. if (!regs->SetPcFromReturnAddress(process_memory.get())) { break; } return_address_attempted = true; } } else { return_address_attempted = false; } } Loading
libbacktrace/backtrace_test.cpp +34 −22 Original line number Diff line number Diff line Loading @@ -82,6 +82,14 @@ struct dump_thread_t { int32_t done; }; typedef Backtrace* (*create_func_t)(pid_t, pid_t, BacktraceMap*); typedef BacktraceMap* (*map_create_func_t)(pid_t, bool); static void VerifyLevelDump(Backtrace* backtrace, create_func_t create_func = nullptr, map_create_func_t map_func = nullptr); static void VerifyMaxDump(Backtrace* backtrace, create_func_t create_func = nullptr, map_create_func_t map_func = nullptr); static uint64_t NanoTime() { struct timespec t = { 0, 0 }; clock_gettime(CLOCK_MONOTONIC, &t); Loading Loading @@ -147,7 +155,7 @@ static bool ReadyLevelBacktrace(Backtrace* backtrace) { return found; } static void VerifyLevelDump(Backtrace* backtrace) { static void VerifyLevelDump(Backtrace* backtrace, create_func_t, map_create_func_t) { ASSERT_GT(backtrace->NumFrames(), static_cast<size_t>(0)) << DumpFrames(backtrace); ASSERT_LT(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES)) Loading Loading @@ -189,7 +197,7 @@ static bool ReadyMaxBacktrace(Backtrace* backtrace) { return (backtrace->NumFrames() == MAX_BACKTRACE_FRAMES); } static void VerifyMaxDump(Backtrace* backtrace) { static void VerifyMaxDump(Backtrace* backtrace, create_func_t, map_create_func_t) { ASSERT_EQ(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES)) << DumpFrames(backtrace); // Verify that the last frame is our recursive call. Loading Loading @@ -251,10 +259,14 @@ TEST(libbacktrace, local_trace) { static void VerifyIgnoreFrames(Backtrace* bt_all, Backtrace* bt_ign1, Backtrace* bt_ign2, const char* cur_proc) { EXPECT_EQ(bt_all->NumFrames(), bt_ign1->NumFrames() + 1) << "All backtrace:\n" << DumpFrames(bt_all) << "Ignore 1 backtrace:\n" << DumpFrames(bt_ign1); EXPECT_EQ(bt_all->NumFrames(), bt_ign2->NumFrames() + 2) << "All backtrace:\n" << DumpFrames(bt_all) << "Ignore 2 backtrace:\n" << DumpFrames(bt_ign2); ASSERT_EQ(bt_all->NumFrames(), bt_ign1->NumFrames() + 1) << "All backtrace:\n" << DumpFrames(bt_all) << "Ignore 1 backtrace:\n" << DumpFrames(bt_ign1); ASSERT_EQ(bt_all->NumFrames(), bt_ign2->NumFrames() + 2) << "All backtrace:\n" << DumpFrames(bt_all) << "Ignore 2 backtrace:\n" << DumpFrames(bt_ign2); // Check all of the frames are the same > the current frame. bool check = (cur_proc == nullptr); Loading Loading @@ -305,9 +317,8 @@ TEST(libbacktrace, local_max_trace) { } static void VerifyProcTest(pid_t pid, pid_t tid, bool (*ReadyFunc)(Backtrace*), void (*VerifyFunc)(Backtrace*), Backtrace* (*back_func)(pid_t, pid_t, BacktraceMap*), BacktraceMap* (*map_func)(pid_t, bool)) { void (*VerifyFunc)(Backtrace*, create_func_t, map_create_func_t), create_func_t create_func, map_create_func_t map_create_func) { pid_t ptrace_tid; if (tid < 0) { ptrace_tid = pid; Loading @@ -324,13 +335,13 @@ static void VerifyProcTest(pid_t pid, pid_t tid, bool (*ReadyFunc)(Backtrace*), WaitForStop(ptrace_tid); std::unique_ptr<BacktraceMap> map; map.reset(map_func(pid, false)); std::unique_ptr<Backtrace> backtrace(back_func(pid, tid, map.get())); map.reset(map_create_func(pid, false)); std::unique_ptr<Backtrace> backtrace(create_func(pid, tid, map.get())); ASSERT_TRUE(backtrace.get() != nullptr); ASSERT_TRUE(backtrace->Unwind(0)); ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError()); if (ReadyFunc(backtrace.get())) { VerifyFunc(backtrace.get()); VerifyFunc(backtrace.get(), create_func, map_create_func); verified = true; } else { last_dump = DumpFrames(backtrace.get()); Loading Loading @@ -399,13 +410,15 @@ TEST(libbacktrace, ptrace_max_trace_new) { ASSERT_EQ(waitpid(pid, &status, 0), pid); } static void VerifyProcessIgnoreFrames(Backtrace* bt_all) { std::unique_ptr<Backtrace> ign1(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD)); static void VerifyProcessIgnoreFrames(Backtrace* bt_all, create_func_t create_func, map_create_func_t map_create_func) { std::unique_ptr<BacktraceMap> map(map_create_func(bt_all->Pid(), false)); std::unique_ptr<Backtrace> ign1(create_func(bt_all->Pid(), BACKTRACE_CURRENT_THREAD, map.get())); ASSERT_TRUE(ign1.get() != nullptr); ASSERT_TRUE(ign1->Unwind(1)); ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, ign1->GetError()); std::unique_ptr<Backtrace> ign2(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD)); std::unique_ptr<Backtrace> ign2(create_func(bt_all->Pid(), BACKTRACE_CURRENT_THREAD, map.get())); ASSERT_TRUE(ign2.get() != nullptr); ASSERT_TRUE(ign2->Unwind(2)); ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, ign2->GetError()); Loading Loading @@ -1702,9 +1715,8 @@ static void SetValueAndLoop(void* data) { ; } static void UnwindThroughSignal(bool use_action, Backtrace* (*back_func)(pid_t, pid_t, BacktraceMap*), BacktraceMap* (*map_func)(pid_t, bool)) { static void UnwindThroughSignal(bool use_action, create_func_t create_func, map_create_func_t map_create_func) { volatile int value = 0; pid_t pid; if ((pid = fork()) == 0) { Loading @@ -1730,8 +1742,8 @@ static void UnwindThroughSignal(bool use_action, WaitForStop(pid); std::unique_ptr<BacktraceMap> map(map_func(pid, false)); std::unique_ptr<Backtrace> backtrace(back_func(pid, pid, map.get())); std::unique_ptr<BacktraceMap> map(map_create_func(pid, false)); std::unique_ptr<Backtrace> backtrace(create_func(pid, pid, map.get())); size_t bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(const_cast<int*>(&value)), reinterpret_cast<uint8_t*>(&read_value), sizeof(read_value)); Loading @@ -1758,9 +1770,9 @@ static void UnwindThroughSignal(bool use_action, WaitForStop(pid); map.reset(map_func(pid, false)); map.reset(map_create_func(pid, false)); ASSERT_TRUE(map.get() != nullptr); backtrace.reset(back_func(pid, pid, map.get())); backtrace.reset(create_func(pid, pid, map.get())); ASSERT_TRUE(backtrace->Unwind(0)); bool found = false; for (frame_iter = backtrace->begin(); frame_iter != backtrace->end(); ++frame_iter) { Loading
libunwindstack/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ cc_library { "Maps.cpp", "Memory.cpp", "Regs.cpp", "Unwinder.cpp", "Symbols.cpp", ], Loading
libunwindstack/DwarfSection.cpp +8 −5 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) { return nullptr; } bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory) { bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) { last_error_ = DWARF_ERROR_NONE; const DwarfFde* fde = GetFdeFromPc(pc); if (fde == nullptr || fde->cie == nullptr) { Loading @@ -62,7 +62,7 @@ bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory) { } // Now eval the actual registers. return Eval(fde->cie, process_memory, loc_regs, regs); return Eval(fde->cie, process_memory, loc_regs, regs, finished); } template <typename AddressType> Loading Loading @@ -92,7 +92,8 @@ bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, uin template <typename AddressType> bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs, Regs* regs) { const dwarf_loc_regs_t& loc_regs, Regs* regs, bool* finished) { RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs); if (cie->return_address_register >= cur_regs->total_regs()) { last_error_ = DWARF_ERROR_ILLEGAL_VALUE; Loading Loading @@ -224,12 +225,14 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me // Find the return address location. if (return_address_undefined) { cur_regs->set_pc(0); *finished = true; } else { cur_regs->set_pc((*cur_regs)[cie->return_address_register]); *finished = false; } cur_regs->set_sp(cfa); // Stop if the cfa and pc are the same. return prev_cfa != cfa || prev_pc != cur_regs->pc(); // Return false if the unwind is not finished or the cfa and pc didn't change. return *finished || prev_cfa != cfa || prev_pc != cur_regs->pc(); } template <typename AddressType> Loading