machine.c revision 3227b5c25f17b19d65e1fe7ec27e62c5430bd258
1/* system/debuggerd/debuggerd.c 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#include <stdio.h> 19#include <errno.h> 20#include <signal.h> 21#include <pthread.h> 22#include <fcntl.h> 23#include <sys/types.h> 24#include <dirent.h> 25 26#include <sys/ptrace.h> 27#include <sys/wait.h> 28#include <sys/exec_elf.h> 29#include <sys/stat.h> 30 31#include <cutils/sockets.h> 32#include <cutils/properties.h> 33 34#include <linux/input.h> 35 36#include "utility.h" 37 38#ifdef WITH_VFP 39#ifdef WITH_VFP_D32 40#define NUM_VFP_REGS 32 41#else 42#define NUM_VFP_REGS 16 43#endif 44#endif 45 46/* Main entry point to get the backtrace from the crashing process */ 47extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map, 48 unsigned int sp_list[], 49 int *frame0_pc_sane, 50 bool at_fault); 51 52void dump_stack_and_code(int tfd, int pid, mapinfo *map, 53 int unwind_depth, unsigned int sp_list[], 54 bool at_fault) 55{ 56 unsigned int sp, pc, p, end, data; 57 struct pt_regs r; 58 int sp_depth; 59 bool only_in_tombstone = !at_fault; 60 char code_buffer[80]; 61 62 if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return; 63 sp = r.ARM_sp; 64 pc = r.ARM_pc; 65 66 _LOG(tfd, only_in_tombstone, "\ncode around pc:\n"); 67 68 end = p = pc & ~3; 69 p -= 32; 70 if (p > end) 71 p = 0; 72 end += 32; 73 if (end < p) 74 end = ~0; 75 76 /* Dump the code around PC as: 77 * addr contents 78 * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c 79 * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 80 */ 81 while (p <= end) { 82 int i; 83 84 sprintf(code_buffer, "%08x ", p); 85 for (i = 0; i < 4; i++) { 86 data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); 87 sprintf(code_buffer + strlen(code_buffer), "%08x ", data); 88 p += 4; 89 } 90 _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); 91 } 92 93 if ((unsigned) r.ARM_lr != pc) { 94 _LOG(tfd, only_in_tombstone, "\ncode around lr:\n"); 95 96 end = p = r.ARM_lr & ~3; 97 p -= 32; 98 if (p > end) 99 p = 0; 100 end += 32; 101 if (end < p) 102 end = ~0; 103 104 /* Dump the code around LR as: 105 * addr contents 106 * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c 107 * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 108 */ 109 while (p <= end) { 110 int i; 111 112 sprintf(code_buffer, "%08x ", p); 113 for (i = 0; i < 4; i++) { 114 data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); 115 sprintf(code_buffer + strlen(code_buffer), "%08x ", data); 116 p += 4; 117 } 118 _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); 119 } 120 } 121 122 p = sp - 64; 123 if (p > sp) 124 p = 0; 125 p &= ~3; 126 if (unwind_depth != 0) { 127 if (unwind_depth < STACK_CONTENT_DEPTH) { 128 end = sp_list[unwind_depth-1]; 129 } 130 else { 131 end = sp_list[STACK_CONTENT_DEPTH-1]; 132 } 133 } 134 else { 135 end = sp | 0x000000ff; 136 end += 0xff; 137 if (end < sp) 138 end = ~0; 139 } 140 141 _LOG(tfd, only_in_tombstone, "\nstack:\n"); 142 143 /* If the crash is due to PC == 0, there will be two frames that 144 * have identical SP value. 145 */ 146 if (sp_list[0] == sp_list[1]) { 147 sp_depth = 1; 148 } 149 else { 150 sp_depth = 0; 151 } 152 153 while (p <= end) { 154 char *prompt; 155 char level[16]; 156 data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); 157 if (p == sp_list[sp_depth]) { 158 sprintf(level, "#%02d", sp_depth++); 159 prompt = level; 160 } 161 else { 162 prompt = " "; 163 } 164 165 /* Print the stack content in the log for the first 3 frames. For the 166 * rest only print them in the tombstone file. 167 */ 168 _LOG(tfd, (sp_depth > 2) || only_in_tombstone, 169 "%s %08x %08x %s\n", prompt, p, data, 170 map_to_name(map, data, "")); 171 p += 4; 172 } 173 /* print another 64-byte of stack data after the last frame */ 174 175 end = p+64; 176 if (end < p) 177 end = ~0; 178 179 while (p <= end) { 180 data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); 181 _LOG(tfd, (sp_depth > 2) || only_in_tombstone, 182 " %08x %08x %s\n", p, data, 183 map_to_name(map, data, "")); 184 p += 4; 185 } 186} 187 188void dump_pc_and_lr(int tfd, int pid, mapinfo *map, int unwound_level, 189 bool at_fault) 190{ 191 struct pt_regs r; 192 193 if(ptrace(PTRACE_GETREGS, pid, 0, &r)) { 194 _LOG(tfd, !at_fault, "tid %d not responding!\n", pid); 195 return; 196 } 197 198 if (unwound_level == 0) { 199 _LOG(tfd, !at_fault, " #%02d pc %08x %s\n", 0, r.ARM_pc, 200 map_to_name(map, r.ARM_pc, "<unknown>")); 201 } 202 _LOG(tfd, !at_fault, " #%02d lr %08x %s\n", 1, r.ARM_lr, 203 map_to_name(map, r.ARM_lr, "<unknown>")); 204} 205 206void dump_registers(int tfd, int pid, bool at_fault) 207{ 208 struct pt_regs r; 209 bool only_in_tombstone = !at_fault; 210 211 if(ptrace(PTRACE_GETREGS, pid, 0, &r)) { 212 _LOG(tfd, only_in_tombstone, 213 "cannot get registers: %s\n", strerror(errno)); 214 return; 215 } 216 217 _LOG(tfd, only_in_tombstone, " r0 %08x r1 %08x r2 %08x r3 %08x\n", 218 r.ARM_r0, r.ARM_r1, r.ARM_r2, r.ARM_r3); 219 _LOG(tfd, only_in_tombstone, " r4 %08x r5 %08x r6 %08x r7 %08x\n", 220 r.ARM_r4, r.ARM_r5, r.ARM_r6, r.ARM_r7); 221 _LOG(tfd, only_in_tombstone, " r8 %08x r9 %08x 10 %08x fp %08x\n", 222 r.ARM_r8, r.ARM_r9, r.ARM_r10, r.ARM_fp); 223 _LOG(tfd, only_in_tombstone, 224 " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n", 225 r.ARM_ip, r.ARM_sp, r.ARM_lr, r.ARM_pc, r.ARM_cpsr); 226 227#ifdef WITH_VFP 228 struct user_vfp vfp_regs; 229 int i; 230 231 if(ptrace(PTRACE_GETVFPREGS, pid, 0, &vfp_regs)) { 232 _LOG(tfd, only_in_tombstone, 233 "cannot get registers: %s\n", strerror(errno)); 234 return; 235 } 236 237 for (i = 0; i < NUM_VFP_REGS; i += 2) { 238 _LOG(tfd, only_in_tombstone, 239 " d%-2d %016llx d%-2d %016llx\n", 240 i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]); 241 } 242 _LOG(tfd, only_in_tombstone, " scr %08lx\n\n", vfp_regs.fpscr); 243#endif 244} 245