size_t Call6(std::shared_ptr<unwindstack::Memory>& process_memory, unwindstack::Maps* maps) { std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal()); unwindstack::RegsGetLocal(regs.get()); unwindstack::Unwinder unwinder(32, maps, regs.get(), process_memory); unwinder.Unwind(); return unwinder.NumFrames(); }
void DoUnwind(pid_t pid) { unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid); if (regs == nullptr) { printf("Unable to get remote reg data\n"); return; } printf("ABI: "); switch (regs->Arch()) { case unwindstack::ARCH_ARM: printf("arm"); break; case unwindstack::ARCH_X86: printf("x86"); break; case unwindstack::ARCH_ARM64: printf("arm64"); break; case unwindstack::ARCH_X86_64: printf("x86_64"); break; case unwindstack::ARCH_MIPS: printf("mips"); break; case unwindstack::ARCH_MIPS64: printf("mips64"); break; default: printf("unknown\n"); return; } printf("\n"); 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. for (size_t i = 0; i < unwinder.NumFrames(); i++) { printf("%s\n", unwinder.FormatFrame(i).c_str()); } }
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"); return; } printf("ABI: "); switch (regs->MachineType()) { case EM_ARM: printf("arm"); break; case EM_386: printf("x86"); break; case EM_AARCH64: printf("arm64"); break; case EM_X86_64: printf("x86_64"); break; default: printf("unknown\n"); return; } printf("\n"); auto process_memory = unwindstack::Memory::CreateProcessMemory(pid); unwindstack::Unwinder unwinder(128, &remote_maps, regs, process_memory); unwinder.Unwind(); // Print the frames. for (size_t i = 0; i < unwinder.NumFrames(); i++) { printf("%s\n", unwinder.FormatFrame(i).c_str()); } }
int SaveData(pid_t pid) { unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid); if (regs == nullptr) { printf("Unable to get remote reg data.\n"); return 1; } // Save the current state of the registers. if (!SaveRegs(regs)) { return 1; } // 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(); 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); 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); 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); auto info = FillInAndGetMapInfo(maps_by_start, map_info); bool file_copied = false; 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 // information if needed. unwindstack::MapInfo* prev_map = map_info->prev_map; if (prev_map != nullptr && map_info->offset != 0 && prev_map->offset == 0 && 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(unwinder.GetProcessMemory(), info, &file_copied); } } } for (size_t i = 0; i < unwinder.NumFrames(); i++) { printf("%s\n", unwinder.FormatFrame(i).c_str()); } if (!SaveStack(pid, stacks)) { return 1; } std::vector<std::pair<uint64_t, map_info_t>> sorted_maps(maps_by_start.begin(), maps_by_start.end()); std::sort(sorted_maps.begin(), sorted_maps.end(), [](auto& a, auto& b) { return a.first < b.first; }); std::unique_ptr<FILE, decltype(&fclose)> fp(fopen("maps.txt", "w+"), &fclose); if (fp == nullptr) { perror("Failed to create maps.txt"); return false; } for (auto& element : sorted_maps) { char perms[5] = {"---p"}; map_info_t& map = element.second; if (map.flags & PROT_READ) { perms[0] = 'r'; } if (map.flags & PROT_WRITE) { perms[1] = 'w'; } if (map.flags & PROT_EXEC) { perms[2] = 'x'; } fprintf(fp.get(), "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " 00:00 0", map.start, map.end, perms, map.offset); if (!map.name.empty()) { fprintf(fp.get(), " %s", map.name.c_str()); } fprintf(fp.get(), "\n"); } return 0; }
bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames, std::vector<std::string>* skip_names, BacktraceUnwindError* error) { UnwindStackMap* stack_map = reinterpret_cast<UnwindStackMap*>(back_map); auto process_memory = stack_map->process_memory(); unwindstack::Unwinder unwinder(MAX_BACKTRACE_FRAMES + num_ignore_frames, stack_map->stack_maps(), regs, stack_map->process_memory()); unwinder.SetResolveNames(stack_map->ResolveNames()); stack_map->SetArch(regs->Arch()); if (stack_map->GetJitDebug() != nullptr) { unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch()); } #if !defined(NO_LIBDEXFILE_SUPPORT) if (stack_map->GetDexFiles() != nullptr) { unwinder.SetDexFiles(stack_map->GetDexFiles(), regs->Arch()); } #endif unwinder.Unwind(skip_names, &stack_map->GetSuffixesToIgnore()); if (error != nullptr) { switch (unwinder.LastErrorCode()) { case unwindstack::ERROR_NONE: error->error_code = BACKTRACE_UNWIND_NO_ERROR; break; case unwindstack::ERROR_MEMORY_INVALID: error->error_code = BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED; error->error_info.addr = unwinder.LastErrorAddress(); break; case unwindstack::ERROR_UNWIND_INFO: error->error_code = BACKTRACE_UNWIND_ERROR_UNWIND_INFO; break; case unwindstack::ERROR_UNSUPPORTED: error->error_code = BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION; break; case unwindstack::ERROR_INVALID_MAP: error->error_code = BACKTRACE_UNWIND_ERROR_MAP_MISSING; break; case unwindstack::ERROR_MAX_FRAMES_EXCEEDED: error->error_code = BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT; break; case unwindstack::ERROR_REPEATED_FRAME: error->error_code = BACKTRACE_UNWIND_ERROR_REPEATED_FRAME; break; case unwindstack::ERROR_INVALID_ELF: error->error_code = BACKTRACE_UNWIND_ERROR_INVALID_ELF; break; } } if (num_ignore_frames >= unwinder.NumFrames()) { frames->resize(0); return true; } auto unwinder_frames = unwinder.frames(); frames->resize(unwinder.NumFrames() - num_ignore_frames); size_t cur_frame = 0; for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++) { auto frame = &unwinder_frames[i]; backtrace_frame_data_t* back_frame = &frames->at(cur_frame); back_frame->num = cur_frame++; back_frame->rel_pc = frame->rel_pc; back_frame->pc = frame->pc; back_frame->sp = frame->sp; back_frame->func_name = demangle(frame->function_name.c_str()); back_frame->func_offset = frame->function_offset; back_frame->map.name = frame->map_name; back_frame->map.start = frame->map_start; back_frame->map.end = frame->map_end; back_frame->map.offset = frame->map_elf_start_offset; back_frame->map.load_bias = frame->map_load_bias; back_frame->map.flags = frame->map_flags; } return true; }