machine.c revision 2c259914a0c5d49a3fcb525a75f4817a3a99a6c8
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
53849249064cae9c1bb23b0204b5d35b832567801eBruce Bearevoid dump_stack_and_code(int tfd, int pid, mapinfo *map,
54849249064cae9c1bb23b0204b5d35b832567801eBruce Beare                         int unwind_depth, unsigned int sp_list[],
55849249064cae9c1bb23b0204b5d35b832567801eBruce Beare                         bool at_fault)
56849249064cae9c1bb23b0204b5d35b832567801eBruce Beare{
57849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    unsigned int sp, pc, p, end, data;
58849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    struct pt_regs r;
59849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    int sp_depth;
60849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    bool only_in_tombstone = !at_fault;
61849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    char code_buffer[80];
62849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
63849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return;
64849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    sp = r.ARM_sp;
65849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    pc = r.ARM_pc;
66849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
67849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    _LOG(tfd, only_in_tombstone, "\ncode around pc:\n");
68849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
69849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    end = p = pc & ~3;
70849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    p -= 32;
713227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham    if (p > end)
723227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham        p = 0;
73849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    end += 32;
743227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham    if (end < p)
753227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham        end = ~0;
76849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
77849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    /* Dump the code around PC as:
78849249064cae9c1bb23b0204b5d35b832567801eBruce Beare     *  addr       contents
79849249064cae9c1bb23b0204b5d35b832567801eBruce Beare     *  00008d34   fffffcd0 4c0eb530 b0934a0e 1c05447c
80849249064cae9c1bb23b0204b5d35b832567801eBruce Beare     *  00008d44   f7ff18a0 490ced94 68035860 d0012b00
81849249064cae9c1bb23b0204b5d35b832567801eBruce Beare     */
82849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    while (p <= end) {
83849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        int i;
84849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
85849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        sprintf(code_buffer, "%08x ", p);
86849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        for (i = 0; i < 4; i++) {
87849249064cae9c1bb23b0204b5d35b832567801eBruce Beare            data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
88849249064cae9c1bb23b0204b5d35b832567801eBruce Beare            sprintf(code_buffer + strlen(code_buffer), "%08x ", data);
89849249064cae9c1bb23b0204b5d35b832567801eBruce Beare            p += 4;
90849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        }
91849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        _LOG(tfd, only_in_tombstone, "%s\n", code_buffer);
92849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    }
93849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
94849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    if ((unsigned) r.ARM_lr != pc) {
95849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        _LOG(tfd, only_in_tombstone, "\ncode around lr:\n");
96849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
97849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        end = p = r.ARM_lr & ~3;
98849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        p -= 32;
993227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham        if (p > end)
1003227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham            p = 0;
101849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        end += 32;
1023227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham        if (end < p)
1033227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham            end = ~0;
104849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
105849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        /* Dump the code around LR as:
106849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         *  addr       contents
107849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         *  00008d34   fffffcd0 4c0eb530 b0934a0e 1c05447c
108849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         *  00008d44   f7ff18a0 490ced94 68035860 d0012b00
109849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         */
110849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        while (p <= end) {
111849249064cae9c1bb23b0204b5d35b832567801eBruce Beare            int i;
112849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
113849249064cae9c1bb23b0204b5d35b832567801eBruce Beare            sprintf(code_buffer, "%08x ", p);
114849249064cae9c1bb23b0204b5d35b832567801eBruce Beare            for (i = 0; i < 4; i++) {
115849249064cae9c1bb23b0204b5d35b832567801eBruce Beare                data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
116849249064cae9c1bb23b0204b5d35b832567801eBruce Beare                sprintf(code_buffer + strlen(code_buffer), "%08x ", data);
117849249064cae9c1bb23b0204b5d35b832567801eBruce Beare                p += 4;
118849249064cae9c1bb23b0204b5d35b832567801eBruce Beare            }
119849249064cae9c1bb23b0204b5d35b832567801eBruce Beare            _LOG(tfd, only_in_tombstone, "%s\n", code_buffer);
120849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        }
121849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    }
122849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
123849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    p = sp - 64;
1243227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham    if (p > sp)
1253227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham        p = 0;
126849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    p &= ~3;
127849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    if (unwind_depth != 0) {
128849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        if (unwind_depth < STACK_CONTENT_DEPTH) {
129849249064cae9c1bb23b0204b5d35b832567801eBruce Beare            end = sp_list[unwind_depth-1];
130849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        }
131849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        else {
132849249064cae9c1bb23b0204b5d35b832567801eBruce Beare            end = sp_list[STACK_CONTENT_DEPTH-1];
133849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        }
134849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    }
135849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    else {
136849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        end = sp | 0x000000ff;
137849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        end += 0xff;
1383227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham        if (end < sp)
1393227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham            end = ~0;
140849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    }
141849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
142849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    _LOG(tfd, only_in_tombstone, "\nstack:\n");
143849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
144849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    /* If the crash is due to PC == 0, there will be two frames that
145849249064cae9c1bb23b0204b5d35b832567801eBruce Beare     * have identical SP value.
146849249064cae9c1bb23b0204b5d35b832567801eBruce Beare     */
147849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    if (sp_list[0] == sp_list[1]) {
148849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        sp_depth = 1;
149849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    }
150849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    else {
151849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        sp_depth = 0;
152849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    }
153849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
154849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    while (p <= end) {
155849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         char *prompt;
156849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         char level[16];
157849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
158849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         if (p == sp_list[sp_depth]) {
159849249064cae9c1bb23b0204b5d35b832567801eBruce Beare             sprintf(level, "#%02d", sp_depth++);
160849249064cae9c1bb23b0204b5d35b832567801eBruce Beare             prompt = level;
161849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         }
162849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         else {
163849249064cae9c1bb23b0204b5d35b832567801eBruce Beare             prompt = "   ";
164849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         }
165849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
166849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         /* Print the stack content in the log for the first 3 frames. For the
167849249064cae9c1bb23b0204b5d35b832567801eBruce Beare          * rest only print them in the tombstone file.
168849249064cae9c1bb23b0204b5d35b832567801eBruce Beare          */
169849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         _LOG(tfd, (sp_depth > 2) || only_in_tombstone,
170849249064cae9c1bb23b0204b5d35b832567801eBruce Beare              "%s %08x  %08x  %s\n", prompt, p, data,
171849249064cae9c1bb23b0204b5d35b832567801eBruce Beare              map_to_name(map, data, ""));
172849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         p += 4;
173849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    }
174849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    /* print another 64-byte of stack data after the last frame */
175849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
176849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    end = p+64;
1773227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham    if (end < p)
1783227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham        end = ~0;
1793227b5c25f17b19d65e1fe7ec27e62c5430bd258Paul Eastham
180849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    while (p <= end) {
181849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
182849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         _LOG(tfd, (sp_depth > 2) || only_in_tombstone,
183849249064cae9c1bb23b0204b5d35b832567801eBruce Beare              "    %08x  %08x  %s\n", p, data,
184849249064cae9c1bb23b0204b5d35b832567801eBruce Beare              map_to_name(map, data, ""));
185849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         p += 4;
186849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    }
187849249064cae9c1bb23b0204b5d35b832567801eBruce Beare}
188849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
189849249064cae9c1bb23b0204b5d35b832567801eBruce Bearevoid dump_pc_and_lr(int tfd, int pid, mapinfo *map, int unwound_level,
190849249064cae9c1bb23b0204b5d35b832567801eBruce Beare                    bool at_fault)
191849249064cae9c1bb23b0204b5d35b832567801eBruce Beare{
192849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    struct pt_regs r;
193849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
194849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    if(ptrace(PTRACE_GETREGS, pid, 0, &r)) {
195849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        _LOG(tfd, !at_fault, "tid %d not responding!\n", pid);
196849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        return;
197849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    }
198849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
199849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    if (unwound_level == 0) {
200849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        _LOG(tfd, !at_fault, "         #%02d  pc %08x  %s\n", 0, r.ARM_pc,
201849249064cae9c1bb23b0204b5d35b832567801eBruce Beare             map_to_name(map, r.ARM_pc, "<unknown>"));
202849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    }
203849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    _LOG(tfd, !at_fault, "         #%02d  lr %08x  %s\n", 1, r.ARM_lr,
204849249064cae9c1bb23b0204b5d35b832567801eBruce Beare            map_to_name(map, r.ARM_lr, "<unknown>"));
205849249064cae9c1bb23b0204b5d35b832567801eBruce Beare}
206849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
207849249064cae9c1bb23b0204b5d35b832567801eBruce Bearevoid dump_registers(int tfd, int pid, bool at_fault)
208849249064cae9c1bb23b0204b5d35b832567801eBruce Beare{
209849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    struct pt_regs r;
210849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    bool only_in_tombstone = !at_fault;
211849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
212849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    if(ptrace(PTRACE_GETREGS, pid, 0, &r)) {
213849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        _LOG(tfd, only_in_tombstone,
214849249064cae9c1bb23b0204b5d35b832567801eBruce Beare             "cannot get registers: %s\n", strerror(errno));
215849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        return;
216849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    }
217849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
218849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    _LOG(tfd, only_in_tombstone, " r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",
219849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         r.ARM_r0, r.ARM_r1, r.ARM_r2, r.ARM_r3);
220849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    _LOG(tfd, only_in_tombstone, " r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",
221849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         r.ARM_r4, r.ARM_r5, r.ARM_r6, r.ARM_r7);
222849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    _LOG(tfd, only_in_tombstone, " r8 %08x  r9 %08x  10 %08x  fp %08x\n",
223849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         r.ARM_r8, r.ARM_r9, r.ARM_r10, r.ARM_fp);
224849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    _LOG(tfd, only_in_tombstone,
225849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         " ip %08x  sp %08x  lr %08x  pc %08x  cpsr %08x\n",
226849249064cae9c1bb23b0204b5d35b832567801eBruce Beare         r.ARM_ip, r.ARM_sp, r.ARM_lr, r.ARM_pc, r.ARM_cpsr);
227849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
228849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#ifdef WITH_VFP
229849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    struct user_vfp vfp_regs;
230849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    int i;
231849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
232849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    if(ptrace(PTRACE_GETVFPREGS, pid, 0, &vfp_regs)) {
233849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        _LOG(tfd, only_in_tombstone,
234849249064cae9c1bb23b0204b5d35b832567801eBruce Beare             "cannot get registers: %s\n", strerror(errno));
235849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        return;
236849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    }
237849249064cae9c1bb23b0204b5d35b832567801eBruce Beare
238849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    for (i = 0; i < NUM_VFP_REGS; i += 2) {
239849249064cae9c1bb23b0204b5d35b832567801eBruce Beare        _LOG(tfd, only_in_tombstone,
240849249064cae9c1bb23b0204b5d35b832567801eBruce Beare             " d%-2d %016llx  d%-2d %016llx\n",
241849249064cae9c1bb23b0204b5d35b832567801eBruce Beare              i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]);
242849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    }
243849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    _LOG(tfd, only_in_tombstone, " scr %08lx\n\n", vfp_regs.fpscr);
244849249064cae9c1bb23b0204b5d35b832567801eBruce Beare#endif
245849249064cae9c1bb23b0204b5d35b832567801eBruce Beare}
246