Home | History | Annotate | Download | only in libbacktrace
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdint.h>
     18 #include <stdlib.h>
     19 #include <sys/types.h>
     20 
     21 #include <string>
     22 #include <vector>
     23 
     24 #include <backtrace/BacktraceMap.h>
     25 #include <unwindstack/Elf.h>
     26 #include <unwindstack/MapInfo.h>
     27 #include <unwindstack/Maps.h>
     28 
     29 #include "UnwindStackMap.h"
     30 
     31 //-------------------------------------------------------------------------
     32 UnwindStackMap::UnwindStackMap(pid_t pid) : BacktraceMap(pid) {}
     33 
     34 bool UnwindStackMap::Build() {
     35   if (pid_ == 0) {
     36     pid_ = getpid();
     37     stack_maps_.reset(new unwindstack::LocalMaps);
     38   } else {
     39     stack_maps_.reset(new unwindstack::RemoteMaps(pid_));
     40   }
     41 
     42   // Create the process memory object.
     43   process_memory_ = unwindstack::Memory::CreateProcessMemory(pid_);
     44 
     45   // Create a JitDebug object for getting jit unwind information.
     46   std::vector<std::string> search_libs_{"libart.so", "libartd.so"};
     47   jit_debug_.reset(new unwindstack::JitDebug(process_memory_, search_libs_));
     48 #if !defined(NO_LIBDEXFILE_SUPPORT)
     49   dex_files_.reset(new unwindstack::DexFiles(process_memory_, search_libs_));
     50 #endif
     51 
     52   if (!stack_maps_->Parse()) {
     53     return false;
     54   }
     55 
     56   // Iterate through the maps and fill in the backtrace_map_t structure.
     57   for (auto* map_info : *stack_maps_) {
     58     backtrace_map_t map;
     59     map.start = map_info->start;
     60     map.end = map_info->end;
     61     map.offset = map_info->offset;
     62     // Set to -1 so that it is demand loaded.
     63     map.load_bias = static_cast<uint64_t>(-1);
     64     map.flags = map_info->flags;
     65     map.name = map_info->name;
     66 
     67     maps_.push_back(map);
     68   }
     69 
     70   return true;
     71 }
     72 
     73 void UnwindStackMap::FillIn(uint64_t addr, backtrace_map_t* map) {
     74   BacktraceMap::FillIn(addr, map);
     75   if (map->load_bias != static_cast<uint64_t>(-1)) {
     76     return;
     77   }
     78 
     79   // Fill in the load_bias.
     80   unwindstack::MapInfo* map_info = stack_maps_->Find(addr);
     81   if (map_info == nullptr) {
     82     return;
     83   }
     84   map->load_bias = map_info->GetLoadBias(process_memory_);
     85 }
     86 
     87 uint64_t UnwindStackMap::GetLoadBias(size_t index) {
     88   if (index >= stack_maps_->Total()) {
     89     return 0;
     90   }
     91 
     92   unwindstack::MapInfo* map_info = stack_maps_->Get(index);
     93   if (map_info == nullptr) {
     94     return 0;
     95   }
     96   return map_info->GetLoadBias(process_memory_);
     97 }
     98 
     99 std::string UnwindStackMap::GetFunctionName(uint64_t pc, uint64_t* offset) {
    100   *offset = 0;
    101   unwindstack::Maps* maps = stack_maps();
    102 
    103   // Get the map for this
    104   unwindstack::MapInfo* map_info = maps->Find(pc);
    105   if (map_info == nullptr || map_info->flags & PROT_DEVICE_MAP) {
    106     return "";
    107   }
    108 
    109   unwindstack::Elf* elf = map_info->GetElf(process_memory(), true);
    110 
    111   std::string name;
    112   uint64_t func_offset;
    113   if (!elf->GetFunctionName(elf->GetRelPc(pc, map_info), &name, &func_offset)) {
    114     return "";
    115   }
    116   *offset = func_offset;
    117   return name;
    118 }
    119 
    120 std::shared_ptr<unwindstack::Memory> UnwindStackMap::GetProcessMemory() {
    121   return process_memory_;
    122 }
    123 
    124 UnwindStackOfflineMap::UnwindStackOfflineMap(pid_t pid) : UnwindStackMap(pid) {}
    125 
    126 bool UnwindStackOfflineMap::Build() {
    127   return false;
    128 }
    129 
    130 bool UnwindStackOfflineMap::Build(const std::vector<backtrace_map_t>& backtrace_maps) {
    131   for (const backtrace_map_t& map : backtrace_maps) {
    132     maps_.push_back(map);
    133   }
    134 
    135   std::sort(maps_.begin(), maps_.end(),
    136             [](const backtrace_map_t& a, const backtrace_map_t& b) { return a.start < b.start; });
    137 
    138   unwindstack::Maps* maps = new unwindstack::Maps;
    139   stack_maps_.reset(maps);
    140   for (const backtrace_map_t& map : maps_) {
    141     maps->Add(map.start, map.end, map.offset, map.flags, map.name, map.load_bias);
    142   }
    143   return true;
    144 }
    145 
    146 bool UnwindStackOfflineMap::CreateProcessMemory(const backtrace_stackinfo_t& stack) {
    147   if (stack.start >= stack.end) {
    148     return false;
    149   }
    150 
    151   // Create the process memory from the stack data.
    152   if (memory_ == nullptr) {
    153     memory_ = new unwindstack::MemoryOfflineBuffer(stack.data, stack.start, stack.end);
    154     process_memory_.reset(memory_);
    155   } else {
    156     memory_->Reset(stack.data, stack.start, stack.end);
    157   }
    158   return true;
    159 }
    160 
    161 //-------------------------------------------------------------------------
    162 // BacktraceMap create function.
    163 //-------------------------------------------------------------------------
    164 BacktraceMap* BacktraceMap::Create(pid_t pid, bool uncached) {
    165   BacktraceMap* map;
    166 
    167   if (uncached) {
    168     // Force use of the base class to parse the maps when this call is made.
    169     map = new BacktraceMap(pid);
    170   } else if (pid == getpid()) {
    171     map = new UnwindStackMap(0);
    172   } else {
    173     map = new UnwindStackMap(pid);
    174   }
    175   if (!map->Build()) {
    176     delete map;
    177     return nullptr;
    178   }
    179   return map;
    180 }
    181 
    182 //-------------------------------------------------------------------------
    183 // BacktraceMap create offline function.
    184 //-------------------------------------------------------------------------
    185 BacktraceMap* BacktraceMap::CreateOffline(pid_t pid, const std::vector<backtrace_map_t>& maps) {
    186   UnwindStackOfflineMap* map = new UnwindStackOfflineMap(pid);
    187   if (!map->Build(maps)) {
    188     delete map;
    189     return nullptr;
    190   }
    191   return map;
    192 }
    193