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 #define _GNU_SOURCE 1 18 #include <errno.h> 19 #include <inttypes.h> 20 #include <signal.h> 21 #include <stdint.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <sys/ptrace.h> 26 #include <sys/types.h> 27 #include <unistd.h> 28 29 #include <algorithm> 30 #include <memory> 31 #include <string> 32 #include <unordered_map> 33 #include <utility> 34 #include <vector> 35 36 #include <unwindstack/Elf.h> 37 #include <unwindstack/JitDebug.h> 38 #include <unwindstack/Maps.h> 39 #include <unwindstack/Memory.h> 40 #include <unwindstack/Regs.h> 41 #include <unwindstack/Unwinder.h> 42 43 #include <android-base/stringprintf.h> 44 45 struct map_info_t { 46 uint64_t start; 47 uint64_t end; 48 uint64_t offset; 49 std::string name; 50 }; 51 52 static bool Attach(pid_t pid) { 53 if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) { 54 return false; 55 } 56 57 // Allow at least 1 second to attach properly. 58 for (size_t i = 0; i < 1000; i++) { 59 siginfo_t si; 60 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) { 61 return true; 62 } 63 usleep(1000); 64 } 65 printf("%d: Failed to stop.\n", pid); 66 return false; 67 } 68 69 bool SaveRegs(unwindstack::Regs* regs) { 70 std::unique_ptr<FILE, decltype(&fclose)> fp(fopen("regs.txt", "w+"), &fclose); 71 if (fp == nullptr) { 72 printf("Failed to create file regs.txt.\n"); 73 return false; 74 } 75 regs->IterateRegisters([&fp](const char* name, uint64_t value) { 76 fprintf(fp.get(), "%s: %" PRIx64 "\n", name, value); 77 }); 78 79 return true; 80 } 81 82 bool SaveStack(pid_t pid, const std::vector<std::pair<uint64_t, uint64_t>>& stacks) { 83 for (size_t i = 0; i < stacks.size(); i++) { 84 std::string file_name; 85 if (stacks.size() != 1) { 86 file_name = "stack" + std::to_string(i) + ".data"; 87 } else { 88 file_name = "stack.data"; 89 } 90 91 // Do this first, so if it fails, we don't create the file. 92 uint64_t sp_start = stacks[i].first; 93 uint64_t sp_end = stacks[i].second; 94 std::vector<uint8_t> buffer(sp_end - sp_start); 95 auto process_memory = unwindstack::Memory::CreateProcessMemory(pid); 96 if (!process_memory->Read(sp_start, buffer.data(), buffer.size())) { 97 printf("Unable to read stack data.\n"); 98 return false; 99 } 100 101 printf("Saving the stack 0x%" PRIx64 "-0x%" PRIx64 "\n", sp_start, sp_end); 102 103 std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file_name.c_str(), "w+"), &fclose); 104 if (fp == nullptr) { 105 printf("Failed to create stack.data.\n"); 106 return false; 107 } 108 109 size_t bytes = fwrite(&sp_start, 1, sizeof(sp_start), fp.get()); 110 if (bytes != sizeof(sp_start)) { 111 perror("Failed to write all data."); 112 return false; 113 } 114 115 bytes = fwrite(buffer.data(), 1, buffer.size(), fp.get()); 116 if (bytes != buffer.size()) { 117 printf("Failed to write all stack data: stack size %zu, written %zu\n", buffer.size(), bytes); 118 return false; 119 } 120 } 121 122 return true; 123 } 124 125 bool CreateElfFromMemory(std::shared_ptr<unwindstack::Memory>& memory, map_info_t* info) { 126 std::string cur_name; 127 if (info->name.empty()) { 128 cur_name = android::base::StringPrintf("anonymous_%" PRIx64, info->start); 129 } else { 130 cur_name = android::base::StringPrintf("%s_%" PRIx64, basename(info->name.c_str()), info->start); 131 } 132 133 std::vector<uint8_t> buffer(info->end - info->start); 134 // If this is a mapped in file, it might not be possible to read the entire 135 // map, so read all that is readable. 136 size_t bytes = memory->Read(info->start, buffer.data(), buffer.size()); 137 if (bytes == 0) { 138 printf("Cannot read data from address %" PRIx64 " length %zu\n", info->start, buffer.size()); 139 return false; 140 } 141 142 std::unique_ptr<FILE, decltype(&fclose)> output(fopen(cur_name.c_str(), "w+"), &fclose); 143 if (output == nullptr) { 144 printf("Cannot create %s\n", cur_name.c_str()); 145 return false; 146 } 147 148 size_t bytes_written = fwrite(buffer.data(), 1, bytes, output.get()); 149 if (bytes_written != bytes) { 150 printf("Failed to write all data to file: bytes read %zu, written %zu\n", bytes, bytes_written); 151 return false; 152 } 153 154 // Replace the name with the new name. 155 info->name = cur_name; 156 157 return true; 158 } 159 160 bool CopyElfFromFile(map_info_t* info) { 161 std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(info->name.c_str(), "r"), &fclose); 162 if (fp == nullptr) { 163 return false; 164 } 165 166 std::string cur_name = basename(info->name.c_str()); 167 std::unique_ptr<FILE, decltype(&fclose)> output(fopen(cur_name.c_str(), "w+"), &fclose); 168 if (output == nullptr) { 169 printf("Cannot create file %s\n", cur_name.c_str()); 170 return false; 171 } 172 std::vector<uint8_t> buffer(10000); 173 size_t bytes; 174 while ((bytes = fread(buffer.data(), 1, buffer.size(), fp.get())) > 0) { 175 size_t bytes_written = fwrite(buffer.data(), 1, bytes, output.get()); 176 if (bytes_written != bytes) { 177 printf("Bytes written doesn't match bytes read: read %zu, written %zu\n", bytes, 178 bytes_written); 179 return false; 180 } 181 } 182 183 // Replace the name with the new name. 184 info->name = cur_name; 185 186 return true; 187 } 188 189 int SaveData(pid_t pid) { 190 unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid); 191 if (regs == nullptr) { 192 printf("Unable to get remote reg data.\n"); 193 return 1; 194 } 195 196 unwindstack::RemoteMaps maps(pid); 197 if (!maps.Parse()) { 198 printf("Unable to parse maps.\n"); 199 return 1; 200 } 201 202 // Save the current state of the registers. 203 if (!SaveRegs(regs)) { 204 return 1; 205 } 206 207 // Do an unwind so we know how much of the stack to save, and what 208 // elf files are involved. 209 uint64_t sp = regs->sp(); 210 auto process_memory = unwindstack::Memory::CreateProcessMemory(pid); 211 unwindstack::JitDebug jit_debug(process_memory); 212 unwindstack::Unwinder unwinder(1024, &maps, regs, process_memory); 213 unwinder.SetJitDebug(&jit_debug, regs->Arch()); 214 unwinder.Unwind(); 215 216 std::unordered_map<uint64_t, map_info_t> maps_by_start; 217 std::vector<std::pair<uint64_t, uint64_t>> stacks; 218 uint64_t sp_map_start = 0; 219 unwindstack::MapInfo* map_info = maps.Find(sp); 220 if (map_info != nullptr) { 221 stacks.emplace_back(std::make_pair(sp, map_info->end)); 222 sp_map_start = map_info->start; 223 } 224 225 for (auto frame : unwinder.frames()) { 226 map_info = maps.Find(frame.sp); 227 if (map_info != nullptr && sp_map_start != map_info->start) { 228 stacks.emplace_back(std::make_pair(frame.sp, map_info->end)); 229 sp_map_start = map_info->start; 230 } 231 232 if (maps_by_start.count(frame.map_start) == 0) { 233 auto info = &maps_by_start[frame.map_start]; 234 info->start = frame.map_start; 235 info->end = frame.map_end; 236 info->offset = frame.map_offset; 237 info->name = frame.map_name; 238 if (!CopyElfFromFile(info)) { 239 // Try to create the elf from memory, this will handle cases where 240 // the data only exists in memory such as vdso data on x86. 241 if (!CreateElfFromMemory(process_memory, info)) { 242 printf("Ignoring map "); 243 if (!info->name.empty()) { 244 printf("%s\n", info->name.c_str()); 245 } else { 246 printf("anonymous:%" PRIx64 "\n", info->start); 247 } 248 } 249 } 250 } 251 } 252 253 for (size_t i = 0; i < unwinder.NumFrames(); i++) { 254 printf("%s\n", unwinder.FormatFrame(i).c_str()); 255 } 256 257 if (!SaveStack(pid, stacks)) { 258 return 1; 259 } 260 261 std::vector<std::pair<uint64_t, map_info_t>> sorted_maps(maps_by_start.begin(), 262 maps_by_start.end()); 263 std::sort(sorted_maps.begin(), sorted_maps.end(), 264 [](auto& a, auto& b) { return a.first < b.first; }); 265 266 std::unique_ptr<FILE, decltype(&fclose)> fp(fopen("maps.txt", "w+"), &fclose); 267 if (fp == nullptr) { 268 printf("Failed to create maps.txt.\n"); 269 return false; 270 } 271 272 for (auto& element : sorted_maps) { 273 map_info_t& map = element.second; 274 fprintf(fp.get(), "%" PRIx64 "-%" PRIx64 " r-xp %" PRIx64 " 00:00 0", map.start, map.end, 275 map.offset); 276 if (!map.name.empty()) { 277 fprintf(fp.get(), " %s", map.name.c_str()); 278 } 279 fprintf(fp.get(), "\n"); 280 } 281 282 return 0; 283 } 284 285 int main(int argc, char** argv) { 286 if (argc != 2) { 287 printf("Usage: unwind_for_offline <PID>\n"); 288 return 1; 289 } 290 291 pid_t pid = atoi(argv[1]); 292 if (!Attach(pid)) { 293 printf("Failed to attach to pid %d: %s\n", pid, strerror(errno)); 294 return 1; 295 } 296 297 int return_code = SaveData(pid); 298 299 ptrace(PTRACE_DETACH, pid, 0, 0); 300 301 return return_code; 302 } 303