1 /*
2 * Copyright (C) 2020 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 <errno.h>
18 #include <signal.h>
19 #include <string.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22
23 #include <memory>
24 #include <mutex>
25 #include <string>
26 #include <vector>
27
28 #include <android-base/errno_restorer.h>
29 #include <android-base/threads.h>
30
31 #include <unwindstack/Log.h>
32 #include <unwindstack/Regs.h>
33 #include <unwindstack/Unwinder.h>
34
35 #include "ThreadEntry.h"
36
37 namespace unwindstack {
38
SignalLogOnly(int,siginfo_t *,void *)39 static void SignalLogOnly(int, siginfo_t*, void*) {
40 android::base::ErrnoRestorer restore;
41
42 Log::AsyncSafe("pid %d, tid %d: Received a spurious thread signal\n", getpid(),
43 static_cast<int>(android::base::GetThreadId()));
44 }
45
SignalHandler(int,siginfo_t *,void * sigcontext)46 static void SignalHandler(int, siginfo_t*, void* sigcontext) {
47 android::base::ErrnoRestorer restore;
48
49 ThreadEntry* entry = ThreadEntry::Get(android::base::GetThreadId(), false);
50 if (!entry) {
51 return;
52 }
53
54 entry->CopyUcontextFromSigcontext(sigcontext);
55
56 // Indicate the ucontext is now valid.
57 entry->Wake();
58 // Pause the thread until the unwind is complete. This avoids having
59 // the thread run ahead causing problems.
60 // The number indicates that we are waiting for the second Wake() call
61 // overall which is made by the thread requesting an unwind.
62 if (entry->Wait(WAIT_FOR_UNWIND_TO_COMPLETE)) {
63 // Do not remove the entry here because that can result in a deadlock
64 // if the code cannot properly send a signal to the thread under test.
65 entry->Wake();
66 }
67 // If the wait fails, the entry might have been freed, so only exit.
68 }
69
ThreadUnwinder(size_t max_frames,Maps * maps)70 ThreadUnwinder::ThreadUnwinder(size_t max_frames, Maps* maps)
71 : UnwinderFromPid(max_frames, getpid(), Regs::CurrentArch(), maps) {}
72
ThreadUnwinder(size_t max_frames,Maps * maps,std::shared_ptr<Memory> & process_memory)73 ThreadUnwinder::ThreadUnwinder(size_t max_frames, Maps* maps,
74 std::shared_ptr<Memory>& process_memory)
75 : UnwinderFromPid(max_frames, getpid(), Regs::CurrentArch(), maps, process_memory) {}
76
ThreadUnwinder(size_t max_frames,const ThreadUnwinder * unwinder)77 ThreadUnwinder::ThreadUnwinder(size_t max_frames, const ThreadUnwinder* unwinder)
78 : UnwinderFromPid(max_frames, getpid(), Regs::CurrentArch()) {
79 process_memory_ = unwinder->process_memory_;
80 maps_ = unwinder->maps_;
81 jit_debug_ = unwinder->jit_debug_;
82 dex_files_ = unwinder->dex_files_;
83 initted_ = unwinder->initted_;
84 }
85
SendSignalToThread(int signal,pid_t tid)86 ThreadEntry* ThreadUnwinder::SendSignalToThread(int signal, pid_t tid) {
87 static std::mutex action_mutex;
88 std::lock_guard<std::mutex> guard(action_mutex);
89
90 ThreadEntry* entry = ThreadEntry::Get(tid);
91 entry->Lock();
92 struct sigaction new_action = {.sa_sigaction = SignalHandler,
93 .sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK};
94 struct sigaction old_action = {};
95 sigemptyset(&new_action.sa_mask);
96 if (sigaction(signal, &new_action, &old_action) != 0) {
97 Log::AsyncSafe("sigaction failed: %s", strerror(errno));
98 ThreadEntry::Remove(entry);
99 last_error_.code = ERROR_SYSTEM_CALL;
100 return nullptr;
101 }
102
103 if (tgkill(getpid(), tid, signal) != 0) {
104 // Do not emit an error message, this might be expected. Set the
105 // error and let the caller decide.
106 if (errno == ESRCH) {
107 last_error_.code = ERROR_THREAD_DOES_NOT_EXIST;
108 } else {
109 last_error_.code = ERROR_SYSTEM_CALL;
110 }
111
112 sigaction(signal, &old_action, nullptr);
113 ThreadEntry::Remove(entry);
114 return nullptr;
115 }
116
117 // Wait for the thread to get the ucontext. The number indicates
118 // that we are waiting for the first Wake() call made by the thread.
119 bool wait_completed = entry->Wait(WAIT_FOR_UCONTEXT);
120 if (wait_completed) {
121 return entry;
122 }
123
124 if (old_action.sa_sigaction == nullptr) {
125 // If the wait failed, it could be that the signal could not be delivered
126 // within the timeout. Add a signal handler that's simply going to log
127 // something so that we don't crash if the signal eventually gets
128 // delivered. Only do this if there isn't already an action set up.
129 struct sigaction log_action = {.sa_sigaction = SignalLogOnly,
130 .sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK};
131 sigemptyset(&log_action.sa_mask);
132 sigaction(signal, &log_action, nullptr);
133 } else {
134 sigaction(signal, &old_action, nullptr);
135 }
136
137 // Check to see if the thread has disappeared.
138 if (tgkill(getpid(), tid, 0) == -1 && errno == ESRCH) {
139 last_error_.code = ERROR_THREAD_DOES_NOT_EXIST;
140 } else {
141 last_error_.code = ERROR_THREAD_TIMEOUT;
142 }
143
144 ThreadEntry::Remove(entry);
145
146 return nullptr;
147 }
148
UnwindWithSignal(int signal,pid_t tid,std::unique_ptr<Regs> * initial_regs,const std::vector<std::string> * initial_map_names_to_skip,const std::vector<std::string> * map_suffixes_to_ignore)149 void ThreadUnwinder::UnwindWithSignal(int signal, pid_t tid, std::unique_ptr<Regs>* initial_regs,
150 const std::vector<std::string>* initial_map_names_to_skip,
151 const std::vector<std::string>* map_suffixes_to_ignore) {
152 ClearErrors();
153 if (tid == static_cast<pid_t>(android::base::GetThreadId())) {
154 last_error_.code = ERROR_UNSUPPORTED;
155 return;
156 }
157
158 if (!Init()) {
159 return;
160 }
161
162 ThreadEntry* entry = SendSignalToThread(signal, tid);
163 if (entry == nullptr) {
164 return;
165 }
166
167 std::unique_ptr<Regs> regs(Regs::CreateFromUcontext(Regs::CurrentArch(), entry->GetUcontext()));
168 if (initial_regs != nullptr) {
169 initial_regs->reset(regs->Clone());
170 }
171 SetRegs(regs.get());
172 UnwinderFromPid::Unwind(initial_map_names_to_skip, map_suffixes_to_ignore);
173
174 // Tell the signal handler to exit and release the entry.
175 entry->Wake();
176
177 // Wait for the thread to indicate it is done with the ThreadEntry.
178 // If this fails, the Wait command will log an error message.
179 entry->Wait(WAIT_FOR_THREAD_TO_RESTART);
180
181 ThreadEntry::Remove(entry);
182 }
183
184 } // namespace unwindstack
185