• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 #define _GNU_SOURCE 1
18 #include <stdint.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include <memory>
23 #include <set>
24 #include <string>
25 
26 #include <backtrace/Backtrace.h>
27 #include <demangle.h>
28 #include <unwindstack/Elf.h>
29 #include <unwindstack/MapInfo.h>
30 #include <unwindstack/Maps.h>
31 #include <unwindstack/Memory.h>
32 #include <unwindstack/Regs.h>
33 #include <unwindstack/RegsGetLocal.h>
34 
35 #if !defined(NO_LIBDEXFILE_SUPPORT)
36 #include <unwindstack/DexFiles.h>
37 #endif
38 #include <unwindstack/Unwinder.h>
39 
40 #include "BacktraceLog.h"
41 #include "UnwindStack.h"
42 #include "UnwindStackMap.h"
43 
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)44 bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
45                        std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames,
46                        std::vector<std::string>* skip_names, BacktraceUnwindError* error) {
47   UnwindStackMap* stack_map = reinterpret_cast<UnwindStackMap*>(back_map);
48   auto process_memory = stack_map->process_memory();
49   unwindstack::Unwinder unwinder(MAX_BACKTRACE_FRAMES + num_ignore_frames, stack_map->stack_maps(),
50                                  regs, stack_map->process_memory());
51   unwinder.SetResolveNames(stack_map->ResolveNames());
52   stack_map->SetArch(regs->Arch());
53   if (stack_map->GetJitDebug() != nullptr) {
54     unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch());
55   }
56 #if !defined(NO_LIBDEXFILE_SUPPORT)
57   if (stack_map->GetDexFiles() != nullptr) {
58     unwinder.SetDexFiles(stack_map->GetDexFiles(), regs->Arch());
59   }
60 #endif
61   unwinder.Unwind(skip_names, &stack_map->GetSuffixesToIgnore());
62   if (error != nullptr) {
63     switch (unwinder.LastErrorCode()) {
64       case unwindstack::ERROR_NONE:
65         error->error_code = BACKTRACE_UNWIND_NO_ERROR;
66         break;
67 
68       case unwindstack::ERROR_MEMORY_INVALID:
69         error->error_code = BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED;
70         error->error_info.addr = unwinder.LastErrorAddress();
71         break;
72 
73       case unwindstack::ERROR_UNWIND_INFO:
74         error->error_code = BACKTRACE_UNWIND_ERROR_UNWIND_INFO;
75         break;
76 
77       case unwindstack::ERROR_UNSUPPORTED:
78         error->error_code = BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION;
79         break;
80 
81       case unwindstack::ERROR_INVALID_MAP:
82         error->error_code = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
83         break;
84 
85       case unwindstack::ERROR_MAX_FRAMES_EXCEEDED:
86         error->error_code = BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT;
87         break;
88 
89       case unwindstack::ERROR_REPEATED_FRAME:
90         error->error_code = BACKTRACE_UNWIND_ERROR_REPEATED_FRAME;
91         break;
92 
93       case unwindstack::ERROR_INVALID_ELF:
94         error->error_code = BACKTRACE_UNWIND_ERROR_INVALID_ELF;
95         break;
96     }
97   }
98 
99   if (num_ignore_frames >= unwinder.NumFrames()) {
100     frames->resize(0);
101     return true;
102   }
103 
104   auto unwinder_frames = unwinder.frames();
105   frames->resize(unwinder.NumFrames() - num_ignore_frames);
106   size_t cur_frame = 0;
107   for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++) {
108     auto frame = &unwinder_frames[i];
109 
110     backtrace_frame_data_t* back_frame = &frames->at(cur_frame);
111 
112     back_frame->num = cur_frame++;
113 
114     back_frame->rel_pc = frame->rel_pc;
115     back_frame->pc = frame->pc;
116     back_frame->sp = frame->sp;
117 
118     back_frame->func_name = demangle(frame->function_name.c_str());
119     back_frame->func_offset = frame->function_offset;
120 
121     back_frame->map.name = frame->map_name;
122     back_frame->map.start = frame->map_start;
123     back_frame->map.end = frame->map_end;
124     back_frame->map.offset = frame->map_elf_start_offset;
125     back_frame->map.load_bias = frame->map_load_bias;
126     back_frame->map.flags = frame->map_flags;
127   }
128 
129   return true;
130 }
131 
UnwindOffline(unwindstack::Regs * regs,BacktraceMap * back_map,const backtrace_stackinfo_t & stack,std::vector<backtrace_frame_data_t> * frames,BacktraceUnwindError * error)132 bool Backtrace::UnwindOffline(unwindstack::Regs* regs, BacktraceMap* back_map,
133                               const backtrace_stackinfo_t& stack,
134                               std::vector<backtrace_frame_data_t>* frames,
135                               BacktraceUnwindError* error) {
136   UnwindStackOfflineMap* offline_map = reinterpret_cast<UnwindStackOfflineMap*>(back_map);
137   // Create the process memory from the stack data since this will almost
138   // always be different each unwind.
139   if (!offline_map->CreateProcessMemory(stack)) {
140     if (error != nullptr) {
141       error->error_code = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
142     }
143     return false;
144   }
145   return Backtrace::Unwind(regs, back_map, frames, 0U, nullptr, error);
146 }
147 
UnwindStackCurrent(pid_t pid,pid_t tid,BacktraceMap * map)148 UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map)
149     : BacktraceCurrent(pid, tid, map) {}
150 
GetFunctionNameRaw(uint64_t pc,uint64_t * offset)151 std::string UnwindStackCurrent::GetFunctionNameRaw(uint64_t pc, uint64_t* offset) {
152   return GetMap()->GetFunctionName(pc, offset);
153 }
154 
UnwindFromContext(size_t num_ignore_frames,void * ucontext)155 bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, void* ucontext) {
156   std::unique_ptr<unwindstack::Regs> regs;
157   if (ucontext == nullptr) {
158     regs.reset(unwindstack::Regs::CreateFromLocal());
159     // Fill in the registers from this function. Do it here to avoid
160     // one extra function call appearing in the unwind.
161     unwindstack::RegsGetLocal(regs.get());
162   } else {
163     regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext));
164   }
165 
166   std::vector<std::string> skip_names{"libunwindstack.so", "libbacktrace.so"};
167   if (!skip_frames_) {
168     skip_names.clear();
169   }
170   return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, &skip_names, &error_);
171 }
172 
UnwindStackPtrace(pid_t pid,pid_t tid,BacktraceMap * map)173 UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map)
174     : BacktracePtrace(pid, tid, map), memory_(pid) {}
175 
GetFunctionNameRaw(uint64_t pc,uint64_t * offset)176 std::string UnwindStackPtrace::GetFunctionNameRaw(uint64_t pc, uint64_t* offset) {
177   return GetMap()->GetFunctionName(pc, offset);
178 }
179 
Unwind(size_t num_ignore_frames,void * context)180 bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, void* context) {
181   std::unique_ptr<unwindstack::Regs> regs;
182   if (context == nullptr) {
183     regs.reset(unwindstack::Regs::RemoteGet(Tid()));
184   } else {
185     regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), context));
186   }
187 
188   return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, nullptr, &error_);
189 }
190 
Read(uint64_t addr,uint8_t * buffer,size_t bytes)191 size_t UnwindStackPtrace::Read(uint64_t addr, uint8_t* buffer, size_t bytes) {
192   return memory_.Read(addr, buffer, bytes);
193 }
194 
UnwindStackOffline(ArchEnum arch,pid_t pid,pid_t tid,BacktraceMap * map,bool map_shared)195 UnwindStackOffline::UnwindStackOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map,
196                                        bool map_shared)
197     : Backtrace(pid, tid, map), arch_(arch) {
198   map_shared_ = map_shared;
199 }
200 
Unwind(size_t num_ignore_frames,void * ucontext)201 bool UnwindStackOffline::Unwind(size_t num_ignore_frames, void* ucontext) {
202   if (ucontext == nullptr) {
203     return false;
204   }
205 
206   unwindstack::ArchEnum arch;
207   switch (arch_) {
208     case ARCH_ARM:
209       arch = unwindstack::ARCH_ARM;
210       break;
211     case ARCH_ARM64:
212       arch = unwindstack::ARCH_ARM64;
213       break;
214     case ARCH_X86:
215       arch = unwindstack::ARCH_X86;
216       break;
217     case ARCH_X86_64:
218       arch = unwindstack::ARCH_X86_64;
219       break;
220     default:
221       return false;
222   }
223 
224   std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromUcontext(arch, ucontext));
225 
226   return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, nullptr, &error_);
227 }
228 
GetFunctionNameRaw(uint64_t,uint64_t *)229 std::string UnwindStackOffline::GetFunctionNameRaw(uint64_t, uint64_t*) {
230   return "";
231 }
232 
Read(uint64_t,uint8_t *,size_t)233 size_t UnwindStackOffline::Read(uint64_t, uint8_t*, size_t) {
234   return 0;
235 }
236 
ReadWord(uint64_t,word_t *)237 bool UnwindStackOffline::ReadWord(uint64_t, word_t*) {
238   return false;
239 }
240 
CreateOffline(ArchEnum arch,pid_t pid,pid_t tid,const std::vector<backtrace_map_t> & maps,const backtrace_stackinfo_t & stack)241 Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid,
242                                     const std::vector<backtrace_map_t>& maps,
243                                     const backtrace_stackinfo_t& stack) {
244   std::unique_ptr<UnwindStackOfflineMap> map(
245       reinterpret_cast<UnwindStackOfflineMap*>(BacktraceMap::CreateOffline(pid, maps)));
246   if (map.get() == nullptr || !map->CreateProcessMemory(stack)) {
247     return nullptr;
248   }
249   return new UnwindStackOffline(arch, pid, tid, map.release(), false);
250 }
251 
CreateOffline(ArchEnum arch,pid_t pid,pid_t tid,BacktraceMap * map)252 Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map) {
253   if (map == nullptr) {
254     return nullptr;
255   }
256   return new UnwindStackOffline(arch, pid, tid, map, true);
257 }
258 
SetGlobalElfCache(bool enable)259 void Backtrace::SetGlobalElfCache(bool enable) {
260   unwindstack::Elf::SetCachingEnabled(enable);
261 }
262