1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <elf.h> 18#include <errno.h> 19#include <inttypes.h> 20#include <signal.h> 21#include <stdint.h> 22#include <stdio.h> 23#include <stdlib.h> 24#include <string.h> 25#include <sys/ptrace.h> 26#include <sys/types.h> 27#include <unistd.h> 28 29#include <unwindstack/DexFiles.h> 30#include <unwindstack/Elf.h> 31#include <unwindstack/JitDebug.h> 32#include <unwindstack/Maps.h> 33#include <unwindstack/Memory.h> 34#include <unwindstack/Regs.h> 35#include <unwindstack/Unwinder.h> 36 37static bool Attach(pid_t pid) { 38 if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) { 39 return false; 40 } 41 42 // Allow at least 1 second to attach properly. 43 for (size_t i = 0; i < 1000; i++) { 44 siginfo_t si; 45 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) { 46 return true; 47 } 48 usleep(1000); 49 } 50 printf("%d: Failed to stop.\n", pid); 51 return false; 52} 53 54void DoUnwind(pid_t pid) { 55 unwindstack::RemoteMaps remote_maps(pid); 56 if (!remote_maps.Parse()) { 57 printf("Failed to parse map data.\n"); 58 return; 59 } 60 61 unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid); 62 if (regs == nullptr) { 63 printf("Unable to get remote reg data\n"); 64 return; 65 } 66 67 printf("ABI: "); 68 switch (regs->Arch()) { 69 case unwindstack::ARCH_ARM: 70 printf("arm"); 71 break; 72 case unwindstack::ARCH_X86: 73 printf("x86"); 74 break; 75 case unwindstack::ARCH_ARM64: 76 printf("arm64"); 77 break; 78 case unwindstack::ARCH_X86_64: 79 printf("x86_64"); 80 break; 81 case unwindstack::ARCH_MIPS: 82 printf("mips"); 83 break; 84 case unwindstack::ARCH_MIPS64: 85 printf("mips64"); 86 break; 87 default: 88 printf("unknown\n"); 89 return; 90 } 91 printf("\n"); 92 93 auto process_memory = unwindstack::Memory::CreateProcessMemory(pid); 94 unwindstack::Unwinder unwinder(128, &remote_maps, regs, process_memory); 95 96 unwindstack::JitDebug jit_debug(process_memory); 97 unwinder.SetJitDebug(&jit_debug, regs->Arch()); 98 99 unwindstack::DexFiles dex_files(process_memory); 100 unwinder.SetDexFiles(&dex_files, regs->Arch()); 101 102 unwinder.Unwind(); 103 104 // Print the frames. 105 for (size_t i = 0; i < unwinder.NumFrames(); i++) { 106 printf("%s\n", unwinder.FormatFrame(i).c_str()); 107 } 108} 109 110int main(int argc, char** argv) { 111 if (argc != 2) { 112 printf("Usage: unwind <PID>\n"); 113 return 1; 114 } 115 116 pid_t pid = atoi(argv[1]); 117 if (!Attach(pid)) { 118 printf("Failed to attach to pid %d: %s\n", pid, strerror(errno)); 119 return 1; 120 } 121 122 DoUnwind(pid); 123 124 ptrace(PTRACE_DETACH, pid, 0, 0); 125 126 return 0; 127} 128