1 /*
2  * Copyright (C) 2015 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 "BacktraceOffline.h"
18 
19 extern "C" {
20 #define UNW_REMOTE_ONLY
21 #include <dwarf.h>
22 }
23 
24 #include <pthread.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <ucontext.h>
31 #include <unistd.h>
32 
33 #include <memory>
34 #include <mutex>
35 #include <string>
36 #include <vector>
37 
38 #include <android-base/file.h>
39 #include <android-base/macros.h>
40 #include <backtrace/Backtrace.h>
41 #include <backtrace/BacktraceMap.h>
42 #include <ziparchive/zip_archive.h>
43 
44 #pragma clang diagnostic push
45 #pragma clang diagnostic ignored "-Wunused-parameter"
46 
47 #include <llvm/ADT/StringRef.h>
48 #include <llvm/Object/Binary.h>
49 #include <llvm/Object/ELFObjectFile.h>
50 #include <llvm/Object/ObjectFile.h>
51 
52 #pragma clang diagnostic pop
53 
54 #include "BacktraceLog.h"
55 
56 struct EhFrame {
57   uint64_t hdr_vaddr;
58   uint64_t vaddr;
59   uint64_t fde_table_offset;
60   uintptr_t min_func_vaddr;
61   std::vector<uint8_t> hdr_data;
62   std::vector<uint8_t> data;
63 };
64 
65 struct ArmIdxEntry {
66   uint32_t func_offset;
67   uint32_t value;
68 };
69 
70 struct ArmExidx {
71   uint64_t exidx_vaddr;
72   uint64_t extab_vaddr;
73   std::vector<ArmIdxEntry> exidx_data;
74   std::vector<uint8_t> extab_data;
75   // There is a one-to-one map from exidx_data.func_offset to func_vaddr_array.
76   std::vector<uint32_t> func_vaddr_array;
77 };
78 
79 struct DebugFrameInfo {
80   bool has_arm_exidx;
81   bool has_eh_frame;
82   bool has_debug_frame;
83   bool has_gnu_debugdata;
84 
85   EhFrame eh_frame;
86   ArmExidx arm_exidx;
87 
88   uint64_t min_vaddr;
89   uint64_t text_end_vaddr;
90 
DebugFrameInfoDebugFrameInfo91   DebugFrameInfo() : has_arm_exidx(false), has_eh_frame(false),
92       has_debug_frame(false), has_gnu_debugdata(false) { }
93 };
94 
Clear()95 void Space::Clear() {
96   start = 0;
97   end = 0;
98   data = nullptr;
99 }
100 
Read(uint64_t addr,uint8_t * buffer,size_t size)101 size_t Space::Read(uint64_t addr, uint8_t* buffer, size_t size) {
102   if (addr >= start && addr < end) {
103     size_t read_size = std::min(size, static_cast<size_t>(end - addr));
104     memcpy(buffer, data + (addr - start), read_size);
105     return read_size;
106   }
107   return 0;
108 }
109 
FindProcInfo(unw_addr_space_t addr_space,unw_word_t ip,unw_proc_info * proc_info,int need_unwind_info,void * arg)110 static int FindProcInfo(unw_addr_space_t addr_space, unw_word_t ip, unw_proc_info* proc_info,
111                         int need_unwind_info, void* arg) {
112   BacktraceOffline* backtrace = reinterpret_cast<BacktraceOffline*>(arg);
113   bool result = backtrace->FindProcInfo(addr_space, ip, proc_info, need_unwind_info);
114   return result ? 0 : -UNW_EINVAL;
115 }
116 
PutUnwindInfo(unw_addr_space_t,unw_proc_info_t *,void *)117 static void PutUnwindInfo(unw_addr_space_t, unw_proc_info_t*, void*) {
118 }
119 
GetDynInfoListAddr(unw_addr_space_t,unw_word_t *,void *)120 static int GetDynInfoListAddr(unw_addr_space_t, unw_word_t*, void*) {
121   return -UNW_ENOINFO;
122 }
123 
AccessMem(unw_addr_space_t,unw_word_t addr,unw_word_t * value,int write,void * arg)124 static int AccessMem(unw_addr_space_t, unw_word_t addr, unw_word_t* value, int write, void* arg) {
125   if (write == 1) {
126     return -UNW_EINVAL;
127   }
128   BacktraceOffline* backtrace = reinterpret_cast<BacktraceOffline*>(arg);
129   *value = 0;
130   size_t read_size = backtrace->Read(addr, reinterpret_cast<uint8_t*>(value), sizeof(unw_word_t));
131   // Strictly we should check if read_size matches sizeof(unw_word_t), but it is possible in
132   // .eh_frame_hdr that the section can end at a position not aligned in sizeof(unw_word_t), and
133   // we should permit the read at the end of the section.
134   return (read_size > 0u ? 0 : -UNW_EINVAL);
135 }
136 
AccessReg(unw_addr_space_t,unw_regnum_t unwind_reg,unw_word_t * value,int write,void * arg)137 static int AccessReg(unw_addr_space_t, unw_regnum_t unwind_reg, unw_word_t* value, int write,
138                      void* arg) {
139   if (write == 1) {
140     return -UNW_EINVAL;
141   }
142   BacktraceOffline* backtrace = reinterpret_cast<BacktraceOffline*>(arg);
143   uint64_t reg_value;
144   bool result = backtrace->ReadReg(unwind_reg, &reg_value);
145   if (result) {
146     *value = static_cast<unw_word_t>(reg_value);
147   }
148   return result ? 0 : -UNW_EINVAL;
149 }
150 
AccessFpReg(unw_addr_space_t,unw_regnum_t,unw_fpreg_t *,int,void *)151 static int AccessFpReg(unw_addr_space_t, unw_regnum_t, unw_fpreg_t*, int, void*) {
152   return -UNW_EINVAL;
153 }
154 
Resume(unw_addr_space_t,unw_cursor_t *,void *)155 static int Resume(unw_addr_space_t, unw_cursor_t*, void*) {
156   return -UNW_EINVAL;
157 }
158 
GetProcName(unw_addr_space_t,unw_word_t,char *,size_t,unw_word_t *,void *)159 static int GetProcName(unw_addr_space_t, unw_word_t, char*, size_t, unw_word_t*, void*) {
160   return -UNW_EINVAL;
161 }
162 
163 static unw_accessors_t accessors = {
164     .find_proc_info = FindProcInfo,
165     .put_unwind_info = PutUnwindInfo,
166     .get_dyn_info_list_addr = GetDynInfoListAddr,
167     .access_mem = AccessMem,
168     .access_reg = AccessReg,
169     .access_fpreg = AccessFpReg,
170     .resume = Resume,
171     .get_proc_name = GetProcName,
172 };
173 
Unwind(size_t num_ignore_frames,ucontext_t * context)174 bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) {
175   if (context == nullptr) {
176     BACK_LOGW("The context is needed for offline backtracing.");
177     error_ = BACKTRACE_UNWIND_ERROR_NO_CONTEXT;
178     return false;
179   }
180   context_ = context;
181   error_ = BACKTRACE_UNWIND_NO_ERROR;
182 
183   unw_addr_space_t addr_space = unw_create_addr_space(&accessors, 0);
184   unw_cursor_t cursor;
185   int ret = unw_init_remote(&cursor, addr_space, this);
186   if (ret != 0) {
187     BACK_LOGW("unw_init_remote failed %d", ret);
188     unw_destroy_addr_space(addr_space);
189     error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
190     return false;
191   }
192   size_t num_frames = 0;
193   do {
194     unw_word_t pc;
195     ret = unw_get_reg(&cursor, UNW_REG_IP, &pc);
196     if (ret < 0) {
197       BACK_LOGW("Failed to read IP %d", ret);
198       break;
199     }
200     unw_word_t sp;
201     ret = unw_get_reg(&cursor, UNW_REG_SP, &sp);
202     if (ret < 0) {
203       BACK_LOGW("Failed to read SP %d", ret);
204       break;
205     }
206 
207     if (num_ignore_frames == 0) {
208       frames_.resize(num_frames + 1);
209       backtrace_frame_data_t* frame = &frames_[num_frames];
210       frame->num = num_frames;
211       frame->pc = static_cast<uintptr_t>(pc);
212       frame->sp = static_cast<uintptr_t>(sp);
213       frame->stack_size = 0;
214 
215       if (num_frames > 0) {
216         backtrace_frame_data_t* prev = &frames_[num_frames - 1];
217         prev->stack_size = frame->sp - prev->sp;
218       }
219       frame->func_name = GetFunctionName(frame->pc, &frame->func_offset);
220       FillInMap(frame->pc, &frame->map);
221       num_frames++;
222     } else {
223       num_ignore_frames--;
224     }
225     ret = unw_step(&cursor);
226   } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES);
227 
228   unw_destroy_addr_space(addr_space);
229   context_ = nullptr;
230   return true;
231 }
232 
ReadWord(uintptr_t ptr,word_t * out_value)233 bool BacktraceOffline::ReadWord(uintptr_t ptr, word_t* out_value) {
234   size_t bytes_read = Read(ptr, reinterpret_cast<uint8_t*>(out_value), sizeof(word_t));
235   return bytes_read == sizeof(word_t);
236 }
237 
Read(uintptr_t addr,uint8_t * buffer,size_t bytes)238 size_t BacktraceOffline::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
239   // Normally, libunwind needs stack information and call frame information to do remote unwinding.
240   // If call frame information is stored in .debug_frame, libunwind can read it from file
241   // by itself. If call frame information is stored in .eh_frame, we need to provide data in
242   // .eh_frame/.eh_frame_hdr sections.
243   // The order of readings below doesn't matter, as the spaces don't overlap with each other.
244   size_t read_size = eh_frame_hdr_space_.Read(addr, buffer, bytes);
245   if (read_size != 0) {
246     return read_size;
247   }
248   read_size = eh_frame_space_.Read(addr, buffer, bytes);
249   if (read_size != 0) {
250     return read_size;
251   }
252   read_size = arm_exidx_space_.Read(addr, buffer, bytes);
253   if (read_size != 0) {
254     return read_size;
255   }
256   read_size = arm_extab_space_.Read(addr, buffer, bytes);
257   if (read_size != 0) {
258     return read_size;
259   }
260   read_size = stack_space_.Read(addr, buffer, bytes);
261   return read_size;
262 }
263 
FindProcInfo(unw_addr_space_t addr_space,uint64_t ip,unw_proc_info_t * proc_info,int need_unwind_info)264 bool BacktraceOffline::FindProcInfo(unw_addr_space_t addr_space, uint64_t ip,
265                                     unw_proc_info_t* proc_info, int need_unwind_info) {
266   backtrace_map_t map;
267   FillInMap(ip, &map);
268   if (!BacktraceMap::IsValid(map)) {
269     return false;
270   }
271   const std::string& filename = map.name;
272   DebugFrameInfo* debug_frame = GetDebugFrameInFile(filename);
273   if (debug_frame == nullptr) {
274     return false;
275   }
276 
277   eh_frame_hdr_space_.Clear();
278   eh_frame_space_.Clear();
279   arm_exidx_space_.Clear();
280   arm_extab_space_.Clear();
281 
282   // vaddr in the elf file.
283   uint64_t ip_vaddr = ip - map.start + debug_frame->min_vaddr;
284 
285   // The unwind info can come from .ARM.exidx or .eh_frame, or .debug_frame/.gnu_debugdata.
286   // First check .eh_frame/.debug_frame, then check .ARM.exidx. Because .eh_frame/.debug_frame has
287   // function range for each entry, by matching ip address with the function range, we know exactly
288   // whether the ip address hits an entry. But .ARM.exidx doesn't have function range for each
289   // entry, it thinks that an ip address hits an entry when (entry.addr <= ip < next_entry.addr).
290   // To prevent ip addresses hit in .eh_frame/.debug_frame being regarded as addresses hit in
291   // .ARM.exidx, we need to check .eh_frame/.debug_frame first.
292   if (debug_frame->has_eh_frame) {
293     if (ip_vaddr >= debug_frame->eh_frame.min_func_vaddr &&
294         ip_vaddr < debug_frame->text_end_vaddr) {
295       // Prepare eh_frame_hdr space and eh_frame space.
296       eh_frame_hdr_space_.start = ip - ip_vaddr + debug_frame->eh_frame.hdr_vaddr;
297       eh_frame_hdr_space_.end =
298           eh_frame_hdr_space_.start + debug_frame->eh_frame.hdr_data.size();
299       eh_frame_hdr_space_.data = debug_frame->eh_frame.hdr_data.data();
300       eh_frame_space_.start = ip - ip_vaddr + debug_frame->eh_frame.vaddr;
301       eh_frame_space_.end = eh_frame_space_.start + debug_frame->eh_frame.data.size();
302       eh_frame_space_.data = debug_frame->eh_frame.data.data();
303 
304       unw_dyn_info di;
305       memset(&di, '\0', sizeof(di));
306       di.start_ip = map.start;
307       di.end_ip = map.end;
308       di.format = UNW_INFO_FORMAT_REMOTE_TABLE;
309       di.u.rti.name_ptr = 0;
310       di.u.rti.segbase = eh_frame_hdr_space_.start;
311       di.u.rti.table_data =
312           eh_frame_hdr_space_.start + debug_frame->eh_frame.fde_table_offset;
313       di.u.rti.table_len = (eh_frame_hdr_space_.end - di.u.rti.table_data) / sizeof(unw_word_t);
314       // TODO: Do it ourselves is more efficient than calling this function.
315       int ret = dwarf_search_unwind_table(addr_space, ip, &di, proc_info, need_unwind_info, this);
316       if (ret == 0) {
317         return true;
318       }
319     }
320   }
321   if (debug_frame->has_debug_frame || debug_frame->has_gnu_debugdata) {
322     unw_dyn_info_t di;
323     unw_word_t segbase = map.start - map.offset;
324     // TODO: http://b/32916571
325     // TODO: Do it ourselves is more efficient than calling libunwind functions.
326     int found = dwarf_find_debug_frame(0, &di, ip, segbase, filename.c_str(), map.start, map.end);
327     if (found == 1) {
328       int ret = dwarf_search_unwind_table(addr_space, ip, &di, proc_info, need_unwind_info, this);
329       if (ret == 0) {
330         return true;
331       }
332     }
333   }
334 
335   if (debug_frame->has_arm_exidx) {
336     auto& func_vaddrs = debug_frame->arm_exidx.func_vaddr_array;
337     if (ip_vaddr >= func_vaddrs[0] && ip_vaddr < debug_frame->text_end_vaddr) {
338       // Use binary search to find the correct function.
339       auto it = std::upper_bound(func_vaddrs.begin(), func_vaddrs.end(),
340                                  static_cast<uint32_t>(ip_vaddr));
341       if (it != func_vaddrs.begin()) {
342         --it;
343         // Found the exidx entry.
344         size_t index = it - func_vaddrs.begin();
345         proc_info->start_ip = *it;
346         proc_info->format = UNW_INFO_FORMAT_ARM_EXIDX;
347         proc_info->unwind_info = reinterpret_cast<void*>(
348             static_cast<uintptr_t>(index * sizeof(ArmIdxEntry) +
349                                    debug_frame->arm_exidx.exidx_vaddr +
350                                    debug_frame->min_vaddr));
351         eh_frame_hdr_space_.Clear();
352         eh_frame_space_.Clear();
353         // Prepare arm_exidx space and arm_extab space.
354         arm_exidx_space_.start = debug_frame->min_vaddr + debug_frame->arm_exidx.exidx_vaddr;
355         arm_exidx_space_.end = arm_exidx_space_.start +
356             debug_frame->arm_exidx.exidx_data.size() * sizeof(ArmIdxEntry);
357         arm_exidx_space_.data = reinterpret_cast<const uint8_t*>(
358             debug_frame->arm_exidx.exidx_data.data());
359 
360         arm_extab_space_.start = debug_frame->min_vaddr + debug_frame->arm_exidx.extab_vaddr;
361         arm_extab_space_.end = arm_extab_space_.start +
362             debug_frame->arm_exidx.extab_data.size();
363         arm_extab_space_.data = debug_frame->arm_exidx.extab_data.data();
364         return true;
365       }
366     }
367   }
368   return false;
369 }
370 
ReadReg(size_t reg,uint64_t * value)371 bool BacktraceOffline::ReadReg(size_t reg, uint64_t* value) {
372   bool result = true;
373 #if defined(__arm__)
374   switch (reg) {
375     case UNW_ARM_R0:
376       *value = context_->uc_mcontext.arm_r0;
377       break;
378     case UNW_ARM_R1:
379       *value = context_->uc_mcontext.arm_r1;
380       break;
381     case UNW_ARM_R2:
382       *value = context_->uc_mcontext.arm_r2;
383       break;
384     case UNW_ARM_R3:
385       *value = context_->uc_mcontext.arm_r3;
386       break;
387     case UNW_ARM_R4:
388       *value = context_->uc_mcontext.arm_r4;
389       break;
390     case UNW_ARM_R5:
391       *value = context_->uc_mcontext.arm_r5;
392       break;
393     case UNW_ARM_R6:
394       *value = context_->uc_mcontext.arm_r6;
395       break;
396     case UNW_ARM_R7:
397       *value = context_->uc_mcontext.arm_r7;
398       break;
399     case UNW_ARM_R8:
400       *value = context_->uc_mcontext.arm_r8;
401       break;
402     case UNW_ARM_R9:
403       *value = context_->uc_mcontext.arm_r9;
404       break;
405     case UNW_ARM_R10:
406       *value = context_->uc_mcontext.arm_r10;
407       break;
408     case UNW_ARM_R11:
409       *value = context_->uc_mcontext.arm_fp;
410       break;
411     case UNW_ARM_R12:
412       *value = context_->uc_mcontext.arm_ip;
413       break;
414     case UNW_ARM_R13:
415       *value = context_->uc_mcontext.arm_sp;
416       break;
417     case UNW_ARM_R14:
418       *value = context_->uc_mcontext.arm_lr;
419       break;
420     case UNW_ARM_R15:
421       *value = context_->uc_mcontext.arm_pc;
422       break;
423     default:
424       result = false;
425   }
426 #elif defined(__aarch64__)
427   if (reg <= UNW_AARCH64_PC) {
428     *value = context_->uc_mcontext.regs[reg];
429   } else {
430     result = false;
431   }
432 #elif defined(__x86_64__)
433   switch (reg) {
434     case UNW_X86_64_R8:
435       *value = context_->uc_mcontext.gregs[REG_R8];
436       break;
437     case UNW_X86_64_R9:
438       *value = context_->uc_mcontext.gregs[REG_R9];
439       break;
440     case UNW_X86_64_R10:
441       *value = context_->uc_mcontext.gregs[REG_R10];
442       break;
443     case UNW_X86_64_R11:
444       *value = context_->uc_mcontext.gregs[REG_R11];
445       break;
446     case UNW_X86_64_R12:
447       *value = context_->uc_mcontext.gregs[REG_R12];
448       break;
449     case UNW_X86_64_R13:
450       *value = context_->uc_mcontext.gregs[REG_R13];
451       break;
452     case UNW_X86_64_R14:
453       *value = context_->uc_mcontext.gregs[REG_R14];
454       break;
455     case UNW_X86_64_R15:
456       *value = context_->uc_mcontext.gregs[REG_R15];
457       break;
458     case UNW_X86_64_RDI:
459       *value = context_->uc_mcontext.gregs[REG_RDI];
460       break;
461     case UNW_X86_64_RSI:
462       *value = context_->uc_mcontext.gregs[REG_RSI];
463       break;
464     case UNW_X86_64_RBP:
465       *value = context_->uc_mcontext.gregs[REG_RBP];
466       break;
467     case UNW_X86_64_RBX:
468       *value = context_->uc_mcontext.gregs[REG_RBX];
469       break;
470     case UNW_X86_64_RDX:
471       *value = context_->uc_mcontext.gregs[REG_RDX];
472       break;
473     case UNW_X86_64_RAX:
474       *value = context_->uc_mcontext.gregs[REG_RAX];
475       break;
476     case UNW_X86_64_RCX:
477       *value = context_->uc_mcontext.gregs[REG_RCX];
478       break;
479     case UNW_X86_64_RSP:
480       *value = context_->uc_mcontext.gregs[REG_RSP];
481       break;
482     case UNW_X86_64_RIP:
483       *value = context_->uc_mcontext.gregs[REG_RIP];
484       break;
485     default:
486       result = false;
487   }
488 #elif defined(__i386__)
489   switch (reg) {
490     case UNW_X86_GS:
491       *value = context_->uc_mcontext.gregs[REG_GS];
492       break;
493     case UNW_X86_FS:
494       *value = context_->uc_mcontext.gregs[REG_FS];
495       break;
496     case UNW_X86_ES:
497       *value = context_->uc_mcontext.gregs[REG_ES];
498       break;
499     case UNW_X86_DS:
500       *value = context_->uc_mcontext.gregs[REG_DS];
501       break;
502     case UNW_X86_EAX:
503       *value = context_->uc_mcontext.gregs[REG_EAX];
504       break;
505     case UNW_X86_EBX:
506       *value = context_->uc_mcontext.gregs[REG_EBX];
507       break;
508     case UNW_X86_ECX:
509       *value = context_->uc_mcontext.gregs[REG_ECX];
510       break;
511     case UNW_X86_EDX:
512       *value = context_->uc_mcontext.gregs[REG_EDX];
513       break;
514     case UNW_X86_ESI:
515       *value = context_->uc_mcontext.gregs[REG_ESI];
516       break;
517     case UNW_X86_EDI:
518       *value = context_->uc_mcontext.gregs[REG_EDI];
519       break;
520     case UNW_X86_EBP:
521       *value = context_->uc_mcontext.gregs[REG_EBP];
522       break;
523     case UNW_X86_EIP:
524       *value = context_->uc_mcontext.gregs[REG_EIP];
525       break;
526     case UNW_X86_ESP:
527       *value = context_->uc_mcontext.gregs[REG_ESP];
528       break;
529     case UNW_X86_TRAPNO:
530       *value = context_->uc_mcontext.gregs[REG_TRAPNO];
531       break;
532     case UNW_X86_CS:
533       *value = context_->uc_mcontext.gregs[REG_CS];
534       break;
535     case UNW_X86_EFLAGS:
536       *value = context_->uc_mcontext.gregs[REG_EFL];
537       break;
538     case UNW_X86_SS:
539       *value = context_->uc_mcontext.gregs[REG_SS];
540       break;
541     default:
542       result = false;
543   }
544 #else
545   UNUSED(reg);
546   UNUSED(value);
547   result = false;
548 #endif
549   return result;
550 }
551 
GetFunctionNameRaw(uintptr_t,uintptr_t * offset)552 std::string BacktraceOffline::GetFunctionNameRaw(uintptr_t, uintptr_t* offset) {
553   // We don't have enough information to support this. And it is expensive.
554   *offset = 0;
555   return "";
556 }
557 
558 static std::mutex g_lock;
559 static std::unordered_map<std::string, std::unique_ptr<DebugFrameInfo>>* g_debug_frames = nullptr;
560 
561 static DebugFrameInfo* ReadDebugFrameFromFile(const std::string& filename);
562 
GetDebugFrameInFile(const std::string & filename)563 DebugFrameInfo* BacktraceOffline::GetDebugFrameInFile(const std::string& filename) {
564   if (cache_file_) {
565     std::lock_guard<std::mutex> lock(g_lock);
566     if (g_debug_frames != nullptr) {
567       auto it = g_debug_frames->find(filename);
568       if (it != g_debug_frames->end()) {
569         return it->second.get();
570       }
571     }
572   }
573   DebugFrameInfo* debug_frame = ReadDebugFrameFromFile(filename);
574   if (cache_file_) {
575     std::lock_guard<std::mutex> lock(g_lock);
576     if (g_debug_frames == nullptr) {
577       g_debug_frames = new std::unordered_map<std::string, std::unique_ptr<DebugFrameInfo>>;
578     }
579     auto pair = g_debug_frames->emplace(filename, std::unique_ptr<DebugFrameInfo>(debug_frame));
580     if (!pair.second) {
581       debug_frame = pair.first->second.get();
582     }
583   }
584   return debug_frame;
585 }
586 
OmitEncodedValue(uint8_t encode,const uint8_t * & p)587 static bool OmitEncodedValue(uint8_t encode, const uint8_t*& p) {
588   if (encode == DW_EH_PE_omit) {
589     return 0;
590   }
591   uint8_t format = encode & 0x0f;
592   switch (format) {
593     case DW_EH_PE_ptr:
594       p += sizeof(unw_word_t);
595       break;
596     case DW_EH_PE_uleb128:
597     case DW_EH_PE_sleb128:
598       while ((*p & 0x80) != 0) {
599         ++p;
600       }
601       ++p;
602       break;
603     case DW_EH_PE_udata2:
604     case DW_EH_PE_sdata2:
605       p += 2;
606       break;
607     case DW_EH_PE_udata4:
608     case DW_EH_PE_sdata4:
609       p += 4;
610       break;
611     case DW_EH_PE_udata8:
612     case DW_EH_PE_sdata8:
613       p += 8;
614       break;
615     default:
616       return false;
617   }
618   return true;
619 }
620 
GetFdeTableOffsetInEhFrameHdr(const std::vector<uint8_t> & data,uint64_t * table_offset_in_eh_frame_hdr)621 static bool GetFdeTableOffsetInEhFrameHdr(const std::vector<uint8_t>& data,
622                                           uint64_t* table_offset_in_eh_frame_hdr) {
623   const uint8_t* p = data.data();
624   const uint8_t* end = p + data.size();
625   if (p + 4 > end) {
626     return false;
627   }
628   uint8_t version = *p++;
629   if (version != 1) {
630     return false;
631   }
632   uint8_t eh_frame_ptr_encode = *p++;
633   uint8_t fde_count_encode = *p++;
634   uint8_t fde_table_encode = *p++;
635 
636   if (fde_table_encode != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) {
637     return false;
638   }
639 
640   if (!OmitEncodedValue(eh_frame_ptr_encode, p) || !OmitEncodedValue(fde_count_encode, p)) {
641     return false;
642   }
643   if (p >= end) {
644     return false;
645   }
646   *table_offset_in_eh_frame_hdr = p - data.data();
647   return true;
648 }
649 
650 template <class ELFT>
ReadDebugFrameFromELFFile(const llvm::object::ELFFile<ELFT> * elf)651 DebugFrameInfo* ReadDebugFrameFromELFFile(const llvm::object::ELFFile<ELFT>* elf) {
652   DebugFrameInfo* result = new DebugFrameInfo;
653   result->text_end_vaddr = std::numeric_limits<uint64_t>::max();
654 
655   bool has_eh_frame_hdr = false;
656   bool has_eh_frame = false;
657 
658   for (auto it = elf->section_begin(); it != elf->section_end(); ++it) {
659     llvm::ErrorOr<llvm::StringRef> name = elf->getSectionName(&*it);
660     if (name) {
661       std::string s = name.get();
662       if (s == ".debug_frame") {
663         result->has_debug_frame = true;
664       } else if (s == ".gnu_debugdata") {
665         result->has_gnu_debugdata = true;
666       } else if (s == ".eh_frame_hdr") {
667         result->eh_frame.hdr_vaddr = it->sh_addr;
668         llvm::ErrorOr<llvm::ArrayRef<uint8_t>> data = elf->getSectionContents(&*it);
669         if (data) {
670           result->eh_frame.hdr_data.insert(result->eh_frame.hdr_data.end(),
671               data->data(), data->data() + data->size());
672 
673           uint64_t fde_table_offset;
674           if (GetFdeTableOffsetInEhFrameHdr(result->eh_frame.hdr_data,
675                                              &fde_table_offset)) {
676             result->eh_frame.fde_table_offset = fde_table_offset;
677             // Make sure we have at least one entry in fde_table.
678             if (fde_table_offset + 2 * sizeof(int32_t) <= data->size()) {
679               intptr_t eh_frame_hdr_vaddr = it->sh_addr;
680               int32_t sdata;
681               uint8_t* p = result->eh_frame.hdr_data.data() + fde_table_offset;
682               memcpy(&sdata, p, sizeof(sdata));
683               result->eh_frame.min_func_vaddr = eh_frame_hdr_vaddr + sdata;
684               has_eh_frame_hdr = true;
685             }
686           }
687         }
688       } else if (s == ".eh_frame") {
689         result->eh_frame.vaddr = it->sh_addr;
690         llvm::ErrorOr<llvm::ArrayRef<uint8_t>> data = elf->getSectionContents(&*it);
691         if (data) {
692           result->eh_frame.data.insert(result->eh_frame.data.end(),
693                                                 data->data(), data->data() + data->size());
694           has_eh_frame = true;
695         }
696       } else if (s == ".ARM.exidx") {
697         result->arm_exidx.exidx_vaddr = it->sh_addr;
698         llvm::ErrorOr<llvm::ArrayRef<uint8_t>> data = elf->getSectionContents(&*it);
699         if (data) {
700           size_t entry_count = data->size() / sizeof(ArmIdxEntry);
701           result->arm_exidx.exidx_data.resize(entry_count);
702           memcpy(result->arm_exidx.exidx_data.data(), data->data(),
703                  entry_count * sizeof(ArmIdxEntry));
704           if (entry_count > 0u) {
705             // Change IdxEntry.func_offset into vaddr.
706             result->arm_exidx.func_vaddr_array.reserve(entry_count);
707             uint32_t vaddr = it->sh_addr;
708             for (auto& entry : result->arm_exidx.exidx_data) {
709               uint32_t func_offset = entry.func_offset + vaddr;
710               // Clear bit 31 for the prel31 offset.
711               // Arm sets bit 0 to mark it as thumb code, remove the flag.
712               result->arm_exidx.func_vaddr_array.push_back(
713                   func_offset & 0x7ffffffe);
714               vaddr += 8;
715             }
716             result->has_arm_exidx = true;
717           }
718         }
719       } else if (s == ".ARM.extab") {
720         result->arm_exidx.extab_vaddr = it->sh_addr;
721         llvm::ErrorOr<llvm::ArrayRef<uint8_t>> data = elf->getSectionContents(&*it);
722         if (data) {
723           result->arm_exidx.extab_data.insert(result->arm_exidx.extab_data.end(),
724                                               data->data(), data->data() + data->size());
725         }
726       } else if (s == ".text") {
727         result->text_end_vaddr = it->sh_addr + it->sh_size;
728       }
729     }
730   }
731 
732   if (has_eh_frame_hdr && has_eh_frame) {
733     result->has_eh_frame = true;
734   }
735 
736   result->min_vaddr = std::numeric_limits<uint64_t>::max();
737   for (auto it = elf->program_header_begin(); it != elf->program_header_end(); ++it) {
738     if ((it->p_type == llvm::ELF::PT_LOAD) && (it->p_flags & llvm::ELF::PF_X)) {
739       if (it->p_vaddr < result->min_vaddr) {
740         result->min_vaddr = it->p_vaddr;
741       }
742     }
743   }
744   if (!result->has_eh_frame && !result->has_arm_exidx && !result->has_debug_frame &&
745       !result->has_gnu_debugdata) {
746     delete result;
747     return nullptr;
748   }
749   return result;
750 }
751 
IsValidElfPath(const std::string & filename)752 static bool IsValidElfPath(const std::string& filename) {
753   static const char elf_magic[] = {0x7f, 'E', 'L', 'F'};
754 
755   struct stat st;
756   if (stat(filename.c_str(), &st) != 0 || !S_ISREG(st.st_mode)) {
757     return false;
758   }
759   FILE* fp = fopen(filename.c_str(), "reb");
760   if (fp == nullptr) {
761     return false;
762   }
763   char buf[4];
764   if (fread(buf, 4, 1, fp) != 1) {
765     fclose(fp);
766     return false;
767   }
768   fclose(fp);
769   return memcmp(buf, elf_magic, 4) == 0;
770 }
771 
IsValidApkPath(const std::string & apk_path)772 static bool IsValidApkPath(const std::string& apk_path) {
773   static const char zip_preamble[] = {0x50, 0x4b, 0x03, 0x04};
774   struct stat st;
775   if (stat(apk_path.c_str(), &st) != 0 || !S_ISREG(st.st_mode)) {
776     return false;
777   }
778   FILE* fp = fopen(apk_path.c_str(), "reb");
779   if (fp == nullptr) {
780     return false;
781   }
782   char buf[4];
783   if (fread(buf, 4, 1, fp) != 1) {
784     fclose(fp);
785     return false;
786   }
787   fclose(fp);
788   return memcmp(buf, zip_preamble, 4) == 0;
789 }
790 
791 class ScopedZiparchiveHandle {
792  public:
ScopedZiparchiveHandle(ZipArchiveHandle handle)793   explicit ScopedZiparchiveHandle(ZipArchiveHandle handle) : handle_(handle) {
794   }
795 
~ScopedZiparchiveHandle()796   ~ScopedZiparchiveHandle() {
797     CloseArchive(handle_);
798   }
799 
800  private:
801   ZipArchiveHandle handle_;
802 };
803 
OpenEmbeddedElfFile(const std::string & filename)804 llvm::object::OwningBinary<llvm::object::Binary> OpenEmbeddedElfFile(const std::string& filename) {
805   llvm::object::OwningBinary<llvm::object::Binary> nothing;
806   size_t pos = filename.find("!/");
807   if (pos == std::string::npos) {
808     return nothing;
809   }
810   std::string apk_file = filename.substr(0, pos);
811   std::string elf_file = filename.substr(pos + 2);
812   if (!IsValidApkPath(apk_file)) {
813     BACK_LOGW("%s is not a valid apk file", apk_file.c_str());
814     return nothing;
815   }
816   ZipArchiveHandle handle;
817   int32_t ret_code = OpenArchive(apk_file.c_str(), &handle);
818   if (ret_code != 0) {
819     CloseArchive(handle);
820     BACK_LOGW("failed to open archive %s: %s", apk_file.c_str(), ErrorCodeString(ret_code));
821     return nothing;
822   }
823   ScopedZiparchiveHandle scoped_handle(handle);
824   ZipEntry zentry;
825   ret_code = FindEntry(handle, ZipString(elf_file.c_str()), &zentry);
826   if (ret_code != 0) {
827     BACK_LOGW("failed to find %s in %s: %s", elf_file.c_str(), apk_file.c_str(),
828               ErrorCodeString(ret_code));
829     return nothing;
830   }
831   if (zentry.method != kCompressStored || zentry.compressed_length != zentry.uncompressed_length) {
832     BACK_LOGW("%s is compressed in %s, which doesn't support running directly", elf_file.c_str(),
833               apk_file.c_str());
834     return nothing;
835   }
836   auto buffer_or_err = llvm::MemoryBuffer::getOpenFileSlice(GetFileDescriptor(handle), apk_file,
837                                                             zentry.uncompressed_length,
838                                                             zentry.offset);
839   if (!buffer_or_err) {
840     BACK_LOGW("failed to read %s in %s: %s", elf_file.c_str(), apk_file.c_str(),
841               buffer_or_err.getError().message().c_str());
842     return nothing;
843   }
844   auto binary_or_err = llvm::object::createBinary(buffer_or_err.get()->getMemBufferRef());
845   if (!binary_or_err) {
846     BACK_LOGW("failed to create binary for %s in %s: %s", elf_file.c_str(), apk_file.c_str(),
847               llvm::toString(binary_or_err.takeError()).c_str());
848     return nothing;
849   }
850   return llvm::object::OwningBinary<llvm::object::Binary>(std::move(binary_or_err.get()),
851                                                           std::move(buffer_or_err.get()));
852 }
853 
ReadDebugFrameFromFile(const std::string & filename)854 static DebugFrameInfo* ReadDebugFrameFromFile(const std::string& filename) {
855   llvm::object::OwningBinary<llvm::object::Binary> owning_binary;
856   if (filename.find("!/") != std::string::npos) {
857     owning_binary = OpenEmbeddedElfFile(filename);
858   } else {
859     if (!IsValidElfPath(filename)) {
860       return nullptr;
861     }
862     auto binary_or_err = llvm::object::createBinary(llvm::StringRef(filename));
863     if (!binary_or_err) {
864       return nullptr;
865     }
866     owning_binary = std::move(binary_or_err.get());
867   }
868   llvm::object::Binary* binary = owning_binary.getBinary();
869   auto obj = llvm::dyn_cast<llvm::object::ObjectFile>(binary);
870   if (obj == nullptr) {
871     return nullptr;
872   }
873   if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(obj)) {
874     return ReadDebugFrameFromELFFile(elf->getELFFile());
875   }
876   if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(obj)) {
877     return ReadDebugFrameFromELFFile(elf->getELFFile());
878   }
879   return nullptr;
880 }
881 
CreateOffline(pid_t pid,pid_t tid,BacktraceMap * map,const backtrace_stackinfo_t & stack,bool cache_file)882 Backtrace* Backtrace::CreateOffline(pid_t pid, pid_t tid, BacktraceMap* map,
883                                     const backtrace_stackinfo_t& stack, bool cache_file) {
884   return new BacktraceOffline(pid, tid, map, stack, cache_file);
885 }
886