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