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