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