machine.c revision f2eae5a860ebdf0dd47669c9bf58b8824b57728c
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 39f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden/* enable to dump memory pointed to by every register */ 40f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden#define DUMP_MEM_FOR_ALL_REGS 0 41f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden 42849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#ifdef WITH_VFP 43849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#ifdef WITH_VFP_D32 44849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#define NUM_VFP_REGS 32 45849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#else 46849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#define NUM_VFP_REGS 16 47849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#endif 48849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#endif 49849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 50849249064cae9c1bb23b0204b5d35b832567801eBruce Beare/* Main entry point to get the backtrace from the crashing process */ 51849249064cae9c1bb23b0204b5d35b832567801eBruce Beareextern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map, 52849249064cae9c1bb23b0204b5d35b832567801eBruce Beare unsigned int sp_list[], 53849249064cae9c1bb23b0204b5d35b832567801eBruce Beare int *frame0_pc_sane, 54849249064cae9c1bb23b0204b5d35b832567801eBruce Beare bool at_fault); 55849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 56136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden/* 57136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden * If this isn't clearly a null pointer dereference, dump the 58136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden * /proc/maps entries near the fault address. 59136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden */ 60136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFaddenstatic void show_nearby_maps(int tfd, int pid, mapinfo *map) 61136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden{ 62136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden siginfo_t si; 63136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 64136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden memset(&si, 0, sizeof(si)); 65136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si)) { 66136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "cannot get siginfo: %s\n", strerror(errno)); 67136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden return; 68136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } 69136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden if (!signal_has_address(si.si_signo)) 70136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden return; 71136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 72136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden uintptr_t addr = (uintptr_t) si.si_addr; 73136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden addr &= ~0xfff; /* round to 4K page boundary */ 74136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden if (addr == 0) /* null-pointer deref */ 75136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden return; 76136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 77136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "\nmemory map around addr %08x:\n", si.si_addr); 78136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 79136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden /* 80136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden * Search for a match, or for a hole where the match would be. The list 81136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden * is backward from the file content, so it starts at high addresses. 82136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden */ 83136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden bool found = false; 84136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden mapinfo *next = NULL; 85136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden mapinfo *prev = NULL; 86136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden while (map != NULL) { 87136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden if (addr >= map->start && addr < map->end) { 88136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden found = true; 89136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden next = map->next; 90136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden break; 91136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } else if (addr >= map->end) { 92136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden /* map would be between "prev" and this entry */ 93136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden next = map; 94136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden map = NULL; 95136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden break; 96136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } 97136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 98136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden prev = map; 99136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden map = map->next; 100136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } 101136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 102136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden /* 103136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden * Show "next" then "match" then "prev" so that the addresses appear in 104136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden * ascending order (like /proc/pid/maps). 105136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden */ 106136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden if (next != NULL) { 107136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "%08x-%08x %s\n", next->start, next->end, next->name); 108136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } else { 109136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "(no map below)\n"); 110136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } 111136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden if (map != NULL) { 112136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "%08x-%08x %s\n", map->start, map->end, map->name); 113136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } else { 114136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "(no map for address)\n"); 115136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } 116136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden if (prev != NULL) { 117136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "%08x-%08x %s\n", prev->start, prev->end, prev->name); 118136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } else { 119136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "(no map above)\n"); 120136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } 121136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden} 122136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 123f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden/* 124f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * Dumps a few bytes of memory, starting a bit before and ending a bit 125f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * after the specified address. 126f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden */ 127f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFaddenstatic void dump_memory(int tfd, int pid, uintptr_t addr, 128f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden bool only_in_tombstone) 129849249064cae9c1bb23b0204b5d35b832567801eBruce Beare{ 130f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden char code_buffer[64]; /* actual 8+1+((8+1)*4) + 1 == 45 */ 131f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden char ascii_buffer[32]; /* actual 16 + 1 == 17 */ 132f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden uintptr_t p, end; 133849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 134f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden p = addr & ~3; 135849249064cae9c1bb23b0204b5d35b832567801eBruce Beare p -= 32; 136f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden if (p > addr) { 137f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden /* catch underflow */ 1383227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham p = 0; 139f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden } 140dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng end = p + 80; 141f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden /* catch overflow; 'end - p' has to be multiples of 16 */ 142dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng while (end < p) 143dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng end -= 16; 144849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 145849249064cae9c1bb23b0204b5d35b832567801eBruce Beare /* Dump the code around PC as: 146f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * addr contents ascii 147f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * 00008d34 ef000000 e8bd0090 e1b00000 512fff1e ............../Q 148f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * 00008d44 ea00b1f9 e92d0090 e3a070fc ef000000 ......-..p...... 149849249064cae9c1bb23b0204b5d35b832567801eBruce Beare */ 150f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden while (p < end) { 151f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden char* asc_out = ascii_buffer; 152849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 153849249064cae9c1bb23b0204b5d35b832567801eBruce Beare sprintf(code_buffer, "%08x ", p); 154f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden 155f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden int i; 156849249064cae9c1bb23b0204b5d35b832567801eBruce Beare for (i = 0; i < 4; i++) { 157f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden /* 158f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * If we see (data == -1 && errno != 0), we know that the ptrace 159f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * call failed, probably because we're dumping memory in an 160f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * unmapped or inaccessible page. I don't know if there's 161f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * value in making that explicit in the output -- it likely 162f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * just complicates parsing and clarifies nothing for the 163f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * enlightened reader. 164f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden */ 165f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden long data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); 166f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden sprintf(code_buffer + strlen(code_buffer), "%08lx ", data); 167f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden 168f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden int j; 169f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden for (j = 0; j < 4; j++) { 170f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden /* 171f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * Our isprint() allows high-ASCII characters that display 172f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * differently (often badly) in different viewers, so we 173f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * just use a simpler test. 174f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden */ 175f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden char val = (data >> (j*8)) & 0xff; 176f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden if (val >= 0x20 && val < 0x7f) { 177f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden *asc_out++ = val; 178f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden } else { 179f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden *asc_out++ = '.'; 180f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden } 181f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden } 182849249064cae9c1bb23b0204b5d35b832567801eBruce Beare p += 4; 183849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 184f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden *asc_out = '\0'; 185f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden _LOG(tfd, only_in_tombstone, "%s %s\n", code_buffer, ascii_buffer); 186849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 187849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 188f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden} 189f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden 190f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFaddenvoid dump_stack_and_code(int tfd, int pid, mapinfo *map, 191f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden int unwind_depth, unsigned int sp_list[], 192f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden bool at_fault) 193f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden{ 194f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden struct pt_regs r; 195f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden int sp_depth; 196f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden bool only_in_tombstone = !at_fault; 197f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden 198f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return; 199f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden 200f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden if (DUMP_MEM_FOR_ALL_REGS && at_fault) { 201f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden /* 202f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * If configured to do so, dump memory around *all* registers 203f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * for the crashing thread. 204f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * 205f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * TODO: remove duplicates. 206849249064cae9c1bb23b0204b5d35b832567801eBruce Beare */ 207f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden static const char REG_NAMES[] = "R0R1R2R3R4R5R6R7R8R9SLFPIPSPLRPC"; 208f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden 209f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden int reg; 210f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden for (reg = 0; reg < 16; reg++) { 211f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden /* this may not be a valid way to access, but it'll do for now */ 212f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden uintptr_t addr = r.uregs[reg]; 213f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden 214f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden /* 215f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * Don't bother if it looks like a small int or ~= null, or if 216f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden * it's in the kernel area. 217f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden */ 218f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden if (addr < 4096 || addr >= 0xc0000000) { 219f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden continue; 220849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 221f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden 222f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden _LOG(tfd, only_in_tombstone, "\nmem near %.2s:\n", 223f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden ®_NAMES[reg*2]); 224f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden dump_memory(tfd, pid, addr, false); 225f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden } 226f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden } else { 227f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden unsigned int pc, lr; 228f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden pc = r.ARM_pc; 229f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden lr = r.ARM_lr; 230f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden 231f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden _LOG(tfd, only_in_tombstone, "\ncode around pc:\n"); 232f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden dump_memory(tfd, pid, (uintptr_t) pc, only_in_tombstone); 233f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden 234f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden if (lr != pc) { 235f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden _LOG(tfd, only_in_tombstone, "\ncode around lr:\n"); 236f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden dump_memory(tfd, pid, (uintptr_t) lr, only_in_tombstone); 237849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 238849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 239849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 240136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden show_nearby_maps(tfd, pid, map); 241136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden 242f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden unsigned int p, end; 243f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden unsigned int sp = r.ARM_sp; 244f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden 245849249064cae9c1bb23b0204b5d35b832567801eBruce Beare p = sp - 64; 2463227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham if (p > sp) 2473227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham p = 0; 248849249064cae9c1bb23b0204b5d35b832567801eBruce Beare p &= ~3; 249849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if (unwind_depth != 0) { 250849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if (unwind_depth < STACK_CONTENT_DEPTH) { 251849249064cae9c1bb23b0204b5d35b832567801eBruce Beare end = sp_list[unwind_depth-1]; 252849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 253849249064cae9c1bb23b0204b5d35b832567801eBruce Beare else { 254849249064cae9c1bb23b0204b5d35b832567801eBruce Beare end = sp_list[STACK_CONTENT_DEPTH-1]; 255849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 256849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 257849249064cae9c1bb23b0204b5d35b832567801eBruce Beare else { 258dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng end = p + 256; 259dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng /* 'end - p' has to be multiples of 4 */ 260dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng if (end < p) 261dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng end = ~7; 262849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 263849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 264849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, "\nstack:\n"); 265849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 266849249064cae9c1bb23b0204b5d35b832567801eBruce Beare /* If the crash is due to PC == 0, there will be two frames that 267849249064cae9c1bb23b0204b5d35b832567801eBruce Beare * have identical SP value. 268849249064cae9c1bb23b0204b5d35b832567801eBruce Beare */ 269849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if (sp_list[0] == sp_list[1]) { 270849249064cae9c1bb23b0204b5d35b832567801eBruce Beare sp_depth = 1; 271849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 272849249064cae9c1bb23b0204b5d35b832567801eBruce Beare else { 273849249064cae9c1bb23b0204b5d35b832567801eBruce Beare sp_depth = 0; 274849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 275849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 276849249064cae9c1bb23b0204b5d35b832567801eBruce Beare while (p <= end) { 277849249064cae9c1bb23b0204b5d35b832567801eBruce Beare char *prompt; 278849249064cae9c1bb23b0204b5d35b832567801eBruce Beare char level[16]; 279f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden long data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); 280849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if (p == sp_list[sp_depth]) { 281849249064cae9c1bb23b0204b5d35b832567801eBruce Beare sprintf(level, "#%02d", sp_depth++); 282849249064cae9c1bb23b0204b5d35b832567801eBruce Beare prompt = level; 283849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 284849249064cae9c1bb23b0204b5d35b832567801eBruce Beare else { 285849249064cae9c1bb23b0204b5d35b832567801eBruce Beare prompt = " "; 286849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 287849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 288849249064cae9c1bb23b0204b5d35b832567801eBruce Beare /* Print the stack content in the log for the first 3 frames. For the 289849249064cae9c1bb23b0204b5d35b832567801eBruce Beare * rest only print them in the tombstone file. 290849249064cae9c1bb23b0204b5d35b832567801eBruce Beare */ 291849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, (sp_depth > 2) || only_in_tombstone, 292849249064cae9c1bb23b0204b5d35b832567801eBruce Beare "%s %08x %08x %s\n", prompt, p, data, 293849249064cae9c1bb23b0204b5d35b832567801eBruce Beare map_to_name(map, data, "")); 294849249064cae9c1bb23b0204b5d35b832567801eBruce Beare p += 4; 295849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 296849249064cae9c1bb23b0204b5d35b832567801eBruce Beare /* print another 64-byte of stack data after the last frame */ 297849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 298849249064cae9c1bb23b0204b5d35b832567801eBruce Beare end = p+64; 299dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng /* 'end - p' has to be multiples of 4 */ 3003227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham if (end < p) 301dce4d06b5c92f375bcf2efcb5b2d87d7566d04f2Ben Cheng end = ~7; 3023227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham 303849249064cae9c1bb23b0204b5d35b832567801eBruce Beare while (p <= end) { 304f2eae5a860ebdf0dd47669c9bf58b8824b57728cAndy McFadden long data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); 305849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, (sp_depth > 2) || only_in_tombstone, 306849249064cae9c1bb23b0204b5d35b832567801eBruce Beare " %08x %08x %s\n", p, data, 307849249064cae9c1bb23b0204b5d35b832567801eBruce Beare map_to_name(map, data, "")); 308849249064cae9c1bb23b0204b5d35b832567801eBruce Beare p += 4; 309849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 310849249064cae9c1bb23b0204b5d35b832567801eBruce Beare} 311849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 312849249064cae9c1bb23b0204b5d35b832567801eBruce Bearevoid dump_pc_and_lr(int tfd, int pid, mapinfo *map, int unwound_level, 313849249064cae9c1bb23b0204b5d35b832567801eBruce Beare bool at_fault) 314849249064cae9c1bb23b0204b5d35b832567801eBruce Beare{ 315849249064cae9c1bb23b0204b5d35b832567801eBruce Beare struct pt_regs r; 316849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 317849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if(ptrace(PTRACE_GETREGS, pid, 0, &r)) { 318849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, !at_fault, "tid %d not responding!\n", pid); 319849249064cae9c1bb23b0204b5d35b832567801eBruce Beare return; 320849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 321849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 322849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if (unwound_level == 0) { 323849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, !at_fault, " #%02d pc %08x %s\n", 0, r.ARM_pc, 324849249064cae9c1bb23b0204b5d35b832567801eBruce Beare map_to_name(map, r.ARM_pc, "<unknown>")); 325849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 326849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, !at_fault, " #%02d lr %08x %s\n", 1, r.ARM_lr, 327849249064cae9c1bb23b0204b5d35b832567801eBruce Beare map_to_name(map, r.ARM_lr, "<unknown>")); 328849249064cae9c1bb23b0204b5d35b832567801eBruce Beare} 329849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 330849249064cae9c1bb23b0204b5d35b832567801eBruce Bearevoid dump_registers(int tfd, int pid, bool at_fault) 331849249064cae9c1bb23b0204b5d35b832567801eBruce Beare{ 332849249064cae9c1bb23b0204b5d35b832567801eBruce Beare struct pt_regs r; 333849249064cae9c1bb23b0204b5d35b832567801eBruce Beare bool only_in_tombstone = !at_fault; 334849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 335849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if(ptrace(PTRACE_GETREGS, pid, 0, &r)) { 336849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, 337849249064cae9c1bb23b0204b5d35b832567801eBruce Beare "cannot get registers: %s\n", strerror(errno)); 338849249064cae9c1bb23b0204b5d35b832567801eBruce Beare return; 339849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 340849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 341849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, " r0 %08x r1 %08x r2 %08x r3 %08x\n", 342849249064cae9c1bb23b0204b5d35b832567801eBruce Beare r.ARM_r0, r.ARM_r1, r.ARM_r2, r.ARM_r3); 343849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, " r4 %08x r5 %08x r6 %08x r7 %08x\n", 344849249064cae9c1bb23b0204b5d35b832567801eBruce Beare r.ARM_r4, r.ARM_r5, r.ARM_r6, r.ARM_r7); 345849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, " r8 %08x r9 %08x 10 %08x fp %08x\n", 346849249064cae9c1bb23b0204b5d35b832567801eBruce Beare r.ARM_r8, r.ARM_r9, r.ARM_r10, r.ARM_fp); 347849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, 348849249064cae9c1bb23b0204b5d35b832567801eBruce Beare " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n", 349849249064cae9c1bb23b0204b5d35b832567801eBruce Beare r.ARM_ip, r.ARM_sp, r.ARM_lr, r.ARM_pc, r.ARM_cpsr); 350849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 351849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#ifdef WITH_VFP 352849249064cae9c1bb23b0204b5d35b832567801eBruce Beare struct user_vfp vfp_regs; 353849249064cae9c1bb23b0204b5d35b832567801eBruce Beare int i; 354849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 355849249064cae9c1bb23b0204b5d35b832567801eBruce Beare if(ptrace(PTRACE_GETVFPREGS, pid, 0, &vfp_regs)) { 356849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, 357849249064cae9c1bb23b0204b5d35b832567801eBruce Beare "cannot get registers: %s\n", strerror(errno)); 358849249064cae9c1bb23b0204b5d35b832567801eBruce Beare return; 359849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 360849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 361849249064cae9c1bb23b0204b5d35b832567801eBruce Beare for (i = 0; i < NUM_VFP_REGS; i += 2) { 362849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, 363849249064cae9c1bb23b0204b5d35b832567801eBruce Beare " d%-2d %016llx d%-2d %016llx\n", 364849249064cae9c1bb23b0204b5d35b832567801eBruce Beare i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]); 365849249064cae9c1bb23b0204b5d35b832567801eBruce Beare } 366849249064cae9c1bb23b0204b5d35b832567801eBruce Beare _LOG(tfd, only_in_tombstone, " scr %08lx\n\n", vfp_regs.fpscr); 367849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#endif 368849249064cae9c1bb23b0204b5d35b832567801eBruce Beare} 369