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 #include <linux/user.h> 36 37 #include "utility.h" 38 39 #ifdef WITH_VFP 40 #ifdef WITH_VFP_D32 41 #define NUM_VFP_REGS 32 42 #else 43 #define NUM_VFP_REGS 16 44 #endif 45 #endif 46 47 /* Main entry point to get the backtrace from the crashing process */ 48 extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map, 49 unsigned int sp_list[], 50 int *frame0_pc_sane, 51 bool at_fault); 52 53 void dump_stack_and_code(int tfd, int pid, mapinfo *map, 54 int unwind_depth, unsigned int sp_list[], 55 bool at_fault) 56 { 57 unsigned int sp, pc, lr, p, end, data; 58 struct pt_regs r; 59 int sp_depth; 60 bool only_in_tombstone = !at_fault; 61 char code_buffer[80]; 62 63 if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return; 64 sp = r.ARM_sp; 65 pc = r.ARM_pc; 66 lr = r.ARM_lr; 67 68 _LOG(tfd, only_in_tombstone, "\ncode around pc:\n"); 69 70 p = pc & ~3; 71 p -= 32; 72 if (p > pc) 73 p = 0; 74 end = p + 80; 75 /* 'end - p' has to be multiples of 16 */ 76 while (end < p) 77 end -= 16; 78 79 /* Dump the code around PC as: 80 * addr contents 81 * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c 82 * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 83 */ 84 while (p < end) { 85 int i; 86 87 sprintf(code_buffer, "%08x ", p); 88 for (i = 0; i < 4; i++) { 89 data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); 90 sprintf(code_buffer + strlen(code_buffer), "%08x ", data); 91 p += 4; 92 } 93 _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); 94 } 95 96 if (lr != pc) { 97 _LOG(tfd, only_in_tombstone, "\ncode around lr:\n"); 98 99 p = lr & ~3; 100 p -= 32; 101 if (p > lr) 102 p = 0; 103 end = p + 80; 104 /* 'end - p' has to be multiples of 16 */ 105 while (end < p) 106 end -= 16; 107 108 /* Dump the code around LR as: 109 * addr contents 110 * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c 111 * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 112 */ 113 while (p < end) { 114 int i; 115 116 sprintf(code_buffer, "%08x ", p); 117 for (i = 0; i < 4; i++) { 118 data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); 119 sprintf(code_buffer + strlen(code_buffer), "%08x ", data); 120 p += 4; 121 } 122 _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); 123 } 124 } 125 126 p = sp - 64; 127 if (p > sp) 128 p = 0; 129 p &= ~3; 130 if (unwind_depth != 0) { 131 if (unwind_depth < STACK_CONTENT_DEPTH) { 132 end = sp_list[unwind_depth-1]; 133 } 134 else { 135 end = sp_list[STACK_CONTENT_DEPTH-1]; 136 } 137 } 138 else { 139 end = p + 256; 140 /* 'end - p' has to be multiples of 4 */ 141 if (end < p) 142 end = ~7; 143 } 144 145 _LOG(tfd, only_in_tombstone, "\nstack:\n"); 146 147 /* If the crash is due to PC == 0, there will be two frames that 148 * have identical SP value. 149 */ 150 if (sp_list[0] == sp_list[1]) { 151 sp_depth = 1; 152 } 153 else { 154 sp_depth = 0; 155 } 156 157 while (p <= end) { 158 char *prompt; 159 char level[16]; 160 data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); 161 if (p == sp_list[sp_depth]) { 162 sprintf(level, "#%02d", sp_depth++); 163 prompt = level; 164 } 165 else { 166 prompt = " "; 167 } 168 169 /* Print the stack content in the log for the first 3 frames. For the 170 * rest only print them in the tombstone file. 171 */ 172 _LOG(tfd, (sp_depth > 2) || only_in_tombstone, 173 "%s %08x %08x %s\n", prompt, p, data, 174 map_to_name(map, data, "")); 175 p += 4; 176 } 177 /* print another 64-byte of stack data after the last frame */ 178 179 end = p+64; 180 /* 'end - p' has to be multiples of 4 */ 181 if (end < p) 182 end = ~7; 183 184 while (p <= end) { 185 data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); 186 _LOG(tfd, (sp_depth > 2) || only_in_tombstone, 187 " %08x %08x %s\n", p, data, 188 map_to_name(map, data, "")); 189 p += 4; 190 } 191 } 192 193 void dump_pc_and_lr(int tfd, int pid, mapinfo *map, int unwound_level, 194 bool at_fault) 195 { 196 struct pt_regs r; 197 198 if(ptrace(PTRACE_GETREGS, pid, 0, &r)) { 199 _LOG(tfd, !at_fault, "tid %d not responding!\n", pid); 200 return; 201 } 202 203 if (unwound_level == 0) { 204 _LOG(tfd, !at_fault, " #%02d pc %08x %s\n", 0, r.ARM_pc, 205 map_to_name(map, r.ARM_pc, "<unknown>")); 206 } 207 _LOG(tfd, !at_fault, " #%02d lr %08x %s\n", 1, r.ARM_lr, 208 map_to_name(map, r.ARM_lr, "<unknown>")); 209 } 210 211 void dump_registers(int tfd, int pid, bool at_fault) 212 { 213 struct pt_regs r; 214 bool only_in_tombstone = !at_fault; 215 216 if(ptrace(PTRACE_GETREGS, pid, 0, &r)) { 217 _LOG(tfd, only_in_tombstone, 218 "cannot get registers: %s\n", strerror(errno)); 219 return; 220 } 221 222 _LOG(tfd, only_in_tombstone, " r0 %08x r1 %08x r2 %08x r3 %08x\n", 223 r.ARM_r0, r.ARM_r1, r.ARM_r2, r.ARM_r3); 224 _LOG(tfd, only_in_tombstone, " r4 %08x r5 %08x r6 %08x r7 %08x\n", 225 r.ARM_r4, r.ARM_r5, r.ARM_r6, r.ARM_r7); 226 _LOG(tfd, only_in_tombstone, " r8 %08x r9 %08x 10 %08x fp %08x\n", 227 r.ARM_r8, r.ARM_r9, r.ARM_r10, r.ARM_fp); 228 _LOG(tfd, only_in_tombstone, 229 " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n", 230 r.ARM_ip, r.ARM_sp, r.ARM_lr, r.ARM_pc, r.ARM_cpsr); 231 232 #ifdef WITH_VFP 233 struct user_vfp vfp_regs; 234 int i; 235 236 if(ptrace(PTRACE_GETVFPREGS, pid, 0, &vfp_regs)) { 237 _LOG(tfd, only_in_tombstone, 238 "cannot get registers: %s\n", strerror(errno)); 239 return; 240 } 241 242 for (i = 0; i < NUM_VFP_REGS; i += 2) { 243 _LOG(tfd, only_in_tombstone, 244 " d%-2d %016llx d%-2d %016llx\n", 245 i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]); 246 } 247 _LOG(tfd, only_in_tombstone, " scr %08lx\n\n", vfp_regs.fpscr); 248 #endif 249 } 250