machine.c revision 136dcc5ce628a1ba600a6818e5cb24d5f15eb016
1849249064cae9c1bb23b0204b5d35b832567801eBruce Beare/* system/debuggerd/debuggerd.c 2849249064cae9c1bb23b0204b5d35b832567801eBruce Beare** 3849249064cae9c1bb23b0204b5d35b832567801eBruce Beare** Copyright 2006, The Android Open Source Project 4849249064cae9c1bb23b0204b5d35b832567801eBruce Beare** 5849249064cae9c1bb23b0204b5d35b832567801eBruce Beare** Licensed under the Apache License, Version 2.0 (the "License"); 6849249064cae9c1bb23b0204b5d35b832567801eBruce Beare** you may not use this file except in compliance with the License. 7849249064cae9c1bb23b0204b5d35b832567801eBruce Beare** You may obtain a copy of the License at 8849249064cae9c1bb23b0204b5d35b832567801eBruce Beare** 9849249064cae9c1bb23b0204b5d35b832567801eBruce Beare** http://www.apache.org/licenses/LICENSE-2.0 10849249064cae9c1bb23b0204b5d35b832567801eBruce Beare** 11849249064cae9c1bb23b0204b5d35b832567801eBruce Beare** Unless required by applicable law or agreed to in writing, software 12849249064cae9c1bb23b0204b5d35b832567801eBruce Beare** distributed under the License is distributed on an "AS IS" BASIS, 13849249064cae9c1bb23b0204b5d35b832567801eBruce Beare** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14849249064cae9c1bb23b0204b5d35b832567801eBruce Beare** See the License for the specific language governing permissions and 15849249064cae9c1bb23b0204b5d35b832567801eBruce Beare** limitations under the License. 16849249064cae9c1bb23b0204b5d35b832567801eBruce Beare*/ 17849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 18849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#include <stdio.h> 19849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#include <errno.h> 20849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#include <signal.h> 21849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#include <pthread.h> 22849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#include <fcntl.h> 23849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#include <sys/types.h> 24849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#include <dirent.h> 25849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 26849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#include <sys/ptrace.h> 27849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#include <sys/wait.h> 28849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#include <sys/exec_elf.h> 29849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#include <sys/stat.h> 30849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 31849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#include <cutils/sockets.h> 32849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#include <cutils/properties.h> 33849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 34849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#include <linux/input.h> 352c259914a0c5d49a3fcb525a75f4817a3a99a6c8David 'Digit' Turner#include <linux/user.h> 36849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 37849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#include "utility.h" 38849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 39849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#ifdef WITH_VFP 40849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#ifdef WITH_VFP_D32 41849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#define NUM_VFP_REGS 32 42849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#else 43849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#define NUM_VFP_REGS 16 44849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#endif 45849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#endif 46849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 47849249064cae9c1bb23b0204b5d35b832567801eBruce Beare/* Main entry point to get the backtrace from the crashing process */ 48849249064cae9c1bb23b0204b5d35b832567801eBruce Beareextern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map, 49849249064cae9c1bb23b0204b5d35b832567801eBruce Beare unsigned int sp_list[], 50849249064cae9c1bb23b0204b5d35b832567801eBruce Beare int *frame0_pc_sane, 51849249064cae9c1bb23b0204b5d35b832567801eBruce Beare bool at_fault); 52849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 53136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden/* 54136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden * If this isn't clearly a null pointer dereference, dump the 55136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden * /proc/maps entries near the fault address. 56136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden */ 57136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFaddenstatic void show_nearby_maps(int tfd, int pid, mapinfo *map) 58136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden{ 59136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden siginfo_t si; 60136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 61136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden memset(&si, 0, sizeof(si)); 62136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si)) { 63136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "cannot get siginfo: %s\n", strerror(errno)); 64136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden return; 65136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } 66136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden if (!signal_has_address(si.si_signo)) 67136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden return; 68136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 69136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden uintptr_t addr = (uintptr_t) si.si_addr; 70136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden addr &= ~0xfff; /* round to 4K page boundary */ 71136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden if (addr == 0) /* null-pointer deref */ 72136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden return; 73136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 74136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "\nmemory map around addr %08x:\n", si.si_addr); 75136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 76136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden /* 77136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden * Search for a match, or for a hole where the match would be. The list 78136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden * is backward from the file content, so it starts at high addresses. 79136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden */ 80136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden bool found = false; 81136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden mapinfo *next = NULL; 82136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden mapinfo *prev = NULL; 83136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden while (map != NULL) { 84136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden if (addr >= map->start && addr < map->end) { 85136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden found = true; 86136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden next = map->next; 87136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden break; 88136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } else if (addr >= map->end) { 89136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden /* map would be between "prev" and this entry */ 90136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden next = map; 91136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden map = NULL; 92136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden break; 93136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } 94136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 95136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden prev = map; 96136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden map = map->next; 97136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } 98136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 99136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden /* 100136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden * Show "next" then "match" then "prev" so that the addresses appear in 101136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden * ascending order (like /proc/pid/maps). 102136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden */ 103136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden if (next != NULL) { 104136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "%08x-%08x %s\n", next->start, next->end, next->name); 105136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } else { 106136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "(no map below)\n"); 107136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } 108136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden if (map != NULL) { 109136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "%08x-%08x %s\n", map->start, map->end, map->name); 110136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } else { 111136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "(no map for address)\n"); 112136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } 113136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden if (prev != NULL) { 114136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "%08x-%08x %s\n", prev->start, prev->end, prev->name); 115136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } else { 116136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "(no map above)\n"); 117136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } 118136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden} 119136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 120136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 121849249064cae9c1bb23b0204b5d35b832567801eBruce Bearevoid dump_stack_and_code(int tfd, int pid, mapinfo *map, 122849249064cae9c1bb23b0204b5d35b832567801eBruce Beare int unwind_depth, unsigned int sp_list[], 123849249064cae9c1bb23b0204b5d35b832567801eBruce Beare bool at_fault) 124849249064cae9c1bb23b0204b5d35b832567801eBruce Beare{ 125dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng unsigned int sp, pc, lr, p, end, data; 126849249064cae9c1bb23b0204b5d35b832567801eBruce Beare struct pt_regs r; 127849249064cae9c1bb23b0204b5d35b832567801eBruce Beare int sp_depth; 128849249064cae9c1bb23b0204b5d35b832567801eBruce Beare bool only_in_tombstone = !at_fault; 129849249064cae9c1bb23b0204b5d35b832567801eBruce Beare char code_buffer[80]; 130849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 131849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return; 132849249064cae9c1bb23b0204b5d35b832567801eBruce Beare sp = r.ARM_sp; 133849249064cae9c1bb23b0204b5d35b832567801eBruce Beare pc = r.ARM_pc; 134dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng lr = r.ARM_lr; 135849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 136849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, "\ncode around pc:\n"); 137849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 138dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng p = pc & ~3; 139849249064cae9c1bb23b0204b5d35b832567801eBruce Beare p -= 32; 140dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng if (p > pc) 1413227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham p = 0; 142dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng end = p + 80; 143dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng /* 'end - p' has to be multiples of 16 */ 144dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng while (end < p) 145dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng end -= 16; 146849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 147849249064cae9c1bb23b0204b5d35b832567801eBruce Beare /* Dump the code around PC as: 148849249064cae9c1bb23b0204b5d35b832567801eBruce Beare * addr contents 149849249064cae9c1bb23b0204b5d35b832567801eBruce Beare * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c 150849249064cae9c1bb23b0204b5d35b832567801eBruce Beare * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 151849249064cae9c1bb23b0204b5d35b832567801eBruce Beare */ 152dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng while (p < end) { 153849249064cae9c1bb23b0204b5d35b832567801eBruce Beare int i; 154849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 155849249064cae9c1bb23b0204b5d35b832567801eBruce Beare sprintf(code_buffer, "%08x ", p); 156849249064cae9c1bb23b0204b5d35b832567801eBruce Beare for (i = 0; i < 4; i++) { 157849249064cae9c1bb23b0204b5d35b832567801eBruce Beare data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); 158849249064cae9c1bb23b0204b5d35b832567801eBruce Beare sprintf(code_buffer + strlen(code_buffer), "%08x ", data); 159849249064cae9c1bb23b0204b5d35b832567801eBruce Beare p += 4; 160849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 161849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); 162849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 163849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 164dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng if (lr != pc) { 165849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, "\ncode around lr:\n"); 166849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 167dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng p = lr & ~3; 168849249064cae9c1bb23b0204b5d35b832567801eBruce Beare p -= 32; 169dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng if (p > lr) 1703227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham p = 0; 171dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng end = p + 80; 172dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng /* 'end - p' has to be multiples of 16 */ 173dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng while (end < p) 174dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng end -= 16; 175849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 176849249064cae9c1bb23b0204b5d35b832567801eBruce Beare /* Dump the code around LR as: 177849249064cae9c1bb23b0204b5d35b832567801eBruce Beare * addr contents 178849249064cae9c1bb23b0204b5d35b832567801eBruce Beare * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c 179849249064cae9c1bb23b0204b5d35b832567801eBruce Beare * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 180849249064cae9c1bb23b0204b5d35b832567801eBruce Beare */ 181dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng while (p < end) { 182849249064cae9c1bb23b0204b5d35b832567801eBruce Beare int i; 183849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 184849249064cae9c1bb23b0204b5d35b832567801eBruce Beare sprintf(code_buffer, "%08x ", p); 185849249064cae9c1bb23b0204b5d35b832567801eBruce Beare for (i = 0; i < 4; i++) { 186849249064cae9c1bb23b0204b5d35b832567801eBruce Beare data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); 187849249064cae9c1bb23b0204b5d35b832567801eBruce Beare sprintf(code_buffer + strlen(code_buffer), "%08x ", data); 188849249064cae9c1bb23b0204b5d35b832567801eBruce Beare p += 4; 189849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 190849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); 191849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 192849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 193849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 194136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden show_nearby_maps(tfd, pid, map); 195136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 196849249064cae9c1bb23b0204b5d35b832567801eBruce Beare p = sp - 64; 1973227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham if (p > sp) 1983227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham p = 0; 199849249064cae9c1bb23b0204b5d35b832567801eBruce Beare p &= ~3; 200849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if (unwind_depth != 0) { 201849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if (unwind_depth < STACK_CONTENT_DEPTH) { 202849249064cae9c1bb23b0204b5d35b832567801eBruce Beare end = sp_list[unwind_depth-1]; 203849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 204849249064cae9c1bb23b0204b5d35b832567801eBruce Beare else { 205849249064cae9c1bb23b0204b5d35b832567801eBruce Beare end = sp_list[STACK_CONTENT_DEPTH-1]; 206849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 207849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 208849249064cae9c1bb23b0204b5d35b832567801eBruce Beare else { 209dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng end = p + 256; 210dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng /* 'end - p' has to be multiples of 4 */ 211dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng if (end < p) 212dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng end = ~7; 213849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 214849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 215849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, "\nstack:\n"); 216849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 217849249064cae9c1bb23b0204b5d35b832567801eBruce Beare /* If the crash is due to PC == 0, there will be two frames that 218849249064cae9c1bb23b0204b5d35b832567801eBruce Beare * have identical SP value. 219849249064cae9c1bb23b0204b5d35b832567801eBruce Beare */ 220849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if (sp_list[0] == sp_list[1]) { 221849249064cae9c1bb23b0204b5d35b832567801eBruce Beare sp_depth = 1; 222849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 223849249064cae9c1bb23b0204b5d35b832567801eBruce Beare else { 224849249064cae9c1bb23b0204b5d35b832567801eBruce Beare sp_depth = 0; 225849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 226849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 227849249064cae9c1bb23b0204b5d35b832567801eBruce Beare while (p <= end) { 228849249064cae9c1bb23b0204b5d35b832567801eBruce Beare char *prompt; 229849249064cae9c1bb23b0204b5d35b832567801eBruce Beare char level[16]; 230849249064cae9c1bb23b0204b5d35b832567801eBruce Beare data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); 231849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if (p == sp_list[sp_depth]) { 232849249064cae9c1bb23b0204b5d35b832567801eBruce Beare sprintf(level, "#%02d", sp_depth++); 233849249064cae9c1bb23b0204b5d35b832567801eBruce Beare prompt = level; 234849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 235849249064cae9c1bb23b0204b5d35b832567801eBruce Beare else { 236849249064cae9c1bb23b0204b5d35b832567801eBruce Beare prompt = " "; 237849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 238849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 239849249064cae9c1bb23b0204b5d35b832567801eBruce Beare /* Print the stack content in the log for the first 3 frames. For the 240849249064cae9c1bb23b0204b5d35b832567801eBruce Beare * rest only print them in the tombstone file. 241849249064cae9c1bb23b0204b5d35b832567801eBruce Beare */ 242849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, (sp_depth > 2) || only_in_tombstone, 243849249064cae9c1bb23b0204b5d35b832567801eBruce Beare "%s %08x %08x %s\n", prompt, p, data, 244849249064cae9c1bb23b0204b5d35b832567801eBruce Beare map_to_name(map, data, "")); 245849249064cae9c1bb23b0204b5d35b832567801eBruce Beare p += 4; 246849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 247849249064cae9c1bb23b0204b5d35b832567801eBruce Beare /* print another 64-byte of stack data after the last frame */ 248849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 249849249064cae9c1bb23b0204b5d35b832567801eBruce Beare end = p+64; 250dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng /* 'end - p' has to be multiples of 4 */ 2513227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham if (end < p) 252dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng end = ~7; 2533227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham 254849249064cae9c1bb23b0204b5d35b832567801eBruce Beare while (p <= end) { 255849249064cae9c1bb23b0204b5d35b832567801eBruce Beare data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); 256849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, (sp_depth > 2) || only_in_tombstone, 257849249064cae9c1bb23b0204b5d35b832567801eBruce Beare " %08x %08x %s\n", p, data, 258849249064cae9c1bb23b0204b5d35b832567801eBruce Beare map_to_name(map, data, "")); 259849249064cae9c1bb23b0204b5d35b832567801eBruce Beare p += 4; 260849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 261849249064cae9c1bb23b0204b5d35b832567801eBruce Beare} 262849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 263849249064cae9c1bb23b0204b5d35b832567801eBruce Bearevoid dump_pc_and_lr(int tfd, int pid, mapinfo *map, int unwound_level, 264849249064cae9c1bb23b0204b5d35b832567801eBruce Beare bool at_fault) 265849249064cae9c1bb23b0204b5d35b832567801eBruce Beare{ 266849249064cae9c1bb23b0204b5d35b832567801eBruce Beare struct pt_regs r; 267849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 268849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if(ptrace(PTRACE_GETREGS, pid, 0, &r)) { 269849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, !at_fault, "tid %d not responding!\n", pid); 270849249064cae9c1bb23b0204b5d35b832567801eBruce Beare return; 271849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 272849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 273849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if (unwound_level == 0) { 274849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, !at_fault, " #%02d pc %08x %s\n", 0, r.ARM_pc, 275849249064cae9c1bb23b0204b5d35b832567801eBruce Beare map_to_name(map, r.ARM_pc, "<unknown>")); 276849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 277849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, !at_fault, " #%02d lr %08x %s\n", 1, r.ARM_lr, 278849249064cae9c1bb23b0204b5d35b832567801eBruce Beare map_to_name(map, r.ARM_lr, "<unknown>")); 279849249064cae9c1bb23b0204b5d35b832567801eBruce Beare} 280849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 281849249064cae9c1bb23b0204b5d35b832567801eBruce Bearevoid dump_registers(int tfd, int pid, bool at_fault) 282849249064cae9c1bb23b0204b5d35b832567801eBruce Beare{ 283849249064cae9c1bb23b0204b5d35b832567801eBruce Beare struct pt_regs r; 284849249064cae9c1bb23b0204b5d35b832567801eBruce Beare bool only_in_tombstone = !at_fault; 285849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 286849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if(ptrace(PTRACE_GETREGS, pid, 0, &r)) { 287849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, 288849249064cae9c1bb23b0204b5d35b832567801eBruce Beare "cannot get registers: %s\n", strerror(errno)); 289849249064cae9c1bb23b0204b5d35b832567801eBruce Beare return; 290849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 291849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 292849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, " r0 %08x r1 %08x r2 %08x r3 %08x\n", 293849249064cae9c1bb23b0204b5d35b832567801eBruce Beare r.ARM_r0, r.ARM_r1, r.ARM_r2, r.ARM_r3); 294849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, " r4 %08x r5 %08x r6 %08x r7 %08x\n", 295849249064cae9c1bb23b0204b5d35b832567801eBruce Beare r.ARM_r4, r.ARM_r5, r.ARM_r6, r.ARM_r7); 296849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, " r8 %08x r9 %08x 10 %08x fp %08x\n", 297849249064cae9c1bb23b0204b5d35b832567801eBruce Beare r.ARM_r8, r.ARM_r9, r.ARM_r10, r.ARM_fp); 298849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, 299849249064cae9c1bb23b0204b5d35b832567801eBruce Beare " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n", 300849249064cae9c1bb23b0204b5d35b832567801eBruce Beare r.ARM_ip, r.ARM_sp, r.ARM_lr, r.ARM_pc, r.ARM_cpsr); 301849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 302849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#ifdef WITH_VFP 303849249064cae9c1bb23b0204b5d35b832567801eBruce Beare struct user_vfp vfp_regs; 304849249064cae9c1bb23b0204b5d35b832567801eBruce Beare int i; 305849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 306849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if(ptrace(PTRACE_GETVFPREGS, pid, 0, &vfp_regs)) { 307849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, 308849249064cae9c1bb23b0204b5d35b832567801eBruce Beare "cannot get registers: %s\n", strerror(errno)); 309849249064cae9c1bb23b0204b5d35b832567801eBruce Beare return; 310849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 311849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 312849249064cae9c1bb23b0204b5d35b832567801eBruce Beare for (i = 0; i < NUM_VFP_REGS; i += 2) { 313849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, 314849249064cae9c1bb23b0204b5d35b832567801eBruce Beare " d%-2d %016llx d%-2d %016llx\n", 315849249064cae9c1bb23b0204b5d35b832567801eBruce Beare i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]); 316849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 317849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, " scr %08lx\n\n", vfp_regs.fpscr); 318849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#endif 319849249064cae9c1bb23b0204b5d35b832567801eBruce Beare} 320