Home | History | Annotate | Download | only in libbacktrace
      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 
     53 void Space::Clear() {
     54   start = 0;
     55   end = 0;
     56   data = nullptr;
     57 }
     58 
     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 
     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 
     75 static void PutUnwindInfo(unw_addr_space_t, unw_proc_info_t*, void*) {
     76 }
     77 
     78 static int GetDynInfoListAddr(unw_addr_space_t, unw_word_t*, void*) {
     79   return -UNW_ENOINFO;
     80 }
     81 
     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 
     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 
    109 static int AccessFpReg(unw_addr_space_t, unw_regnum_t, unw_fpreg_t*, int, void*) {
    110   return -UNW_EINVAL;
    111 }
    112 
    113 static int Resume(unw_addr_space_t, unw_cursor_t*, void*) {
    114   return -UNW_EINVAL;
    115 }
    116 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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>
    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 
    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 
    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:
    668   ScopedZiparchiveHandle(ZipArchiveHandle handle) : handle_(handle) {
    669   }
    670 
    671   ~ScopedZiparchiveHandle() {
    672     CloseArchive(handle_);
    673   }
    674 
    675  private:
    676   ZipArchiveHandle handle_;
    677 };
    678 
    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 
    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 
    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