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