utility.c revision 13e715b491e876865e752a3a69dd6f347049a488
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* system/debuggerd/utility.c
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Copyright 2008, The Android Open Source Project
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** you may not use this file except in compliance with the License.
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** You may obtain a copy of the License at
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** See the License for the specific language governing permissions and
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** limitations under the License.
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
18136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden#include <signal.h>
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
2013e715b491e876865e752a3a69dd6f347049a488Jeff Brown#include <cutils/logd.h>
2113e715b491e876865e752a3a69dd6f347049a488Jeff Brown#include <sys/ptrace.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
2313e715b491e876865e752a3a69dd6f347049a488Jeff Brown#include <corkscrew/demangle.h>
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "utility.h"
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2713e715b491e876865e752a3a69dd6f347049a488Jeff Brown#define STACK_DEPTH 32
2813e715b491e876865e752a3a69dd6f347049a488Jeff Brown#define STACK_WORDS 16
2913e715b491e876865e752a3a69dd6f347049a488Jeff Brown
3013e715b491e876865e752a3a69dd6f347049a488Jeff Brownvoid _LOG(int tfd, bool in_tombstone_only, const char *fmt, ...) {
3113e715b491e876865e752a3a69dd6f347049a488Jeff Brown    char buf[512];
3213e715b491e876865e752a3a69dd6f347049a488Jeff Brown
3313e715b491e876865e752a3a69dd6f347049a488Jeff Brown    va_list ap;
3413e715b491e876865e752a3a69dd6f347049a488Jeff Brown    va_start(ap, fmt);
3513e715b491e876865e752a3a69dd6f347049a488Jeff Brown
3613e715b491e876865e752a3a69dd6f347049a488Jeff Brown    if (tfd >= 0) {
3713e715b491e876865e752a3a69dd6f347049a488Jeff Brown        int len;
3813e715b491e876865e752a3a69dd6f347049a488Jeff Brown        vsnprintf(buf, sizeof(buf), fmt, ap);
3913e715b491e876865e752a3a69dd6f347049a488Jeff Brown        len = strlen(buf);
4013e715b491e876865e752a3a69dd6f347049a488Jeff Brown        if(tfd >= 0) write(tfd, buf, len);
4113e715b491e876865e752a3a69dd6f347049a488Jeff Brown    }
4213e715b491e876865e752a3a69dd6f347049a488Jeff Brown
4313e715b491e876865e752a3a69dd6f347049a488Jeff Brown    if (!in_tombstone_only)
4413e715b491e876865e752a3a69dd6f347049a488Jeff Brown        __android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap);
4513e715b491e876865e752a3a69dd6f347049a488Jeff Brown    va_end(ap);
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4813e715b491e876865e752a3a69dd6f347049a488Jeff Brownbool signal_has_address(int sig) {
4913e715b491e876865e752a3a69dd6f347049a488Jeff Brown    switch (sig) {
5013e715b491e876865e752a3a69dd6f347049a488Jeff Brown        case SIGILL:
5113e715b491e876865e752a3a69dd6f347049a488Jeff Brown        case SIGFPE:
5213e715b491e876865e752a3a69dd6f347049a488Jeff Brown        case SIGSEGV:
5313e715b491e876865e752a3a69dd6f347049a488Jeff Brown        case SIGBUS:
5413e715b491e876865e752a3a69dd6f347049a488Jeff Brown            return true;
5513e715b491e876865e752a3a69dd6f347049a488Jeff Brown        default:
5613e715b491e876865e752a3a69dd6f347049a488Jeff Brown            return false;
5713e715b491e876865e752a3a69dd6f347049a488Jeff Brown    }
5813e715b491e876865e752a3a69dd6f347049a488Jeff Brown}
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
6013e715b491e876865e752a3a69dd6f347049a488Jeff Brownstatic void dump_backtrace(ptrace_context_t* context __attribute((unused)),
6113e715b491e876865e752a3a69dd6f347049a488Jeff Brown        int tfd, int pid __attribute((unused)), bool at_fault,
6213e715b491e876865e752a3a69dd6f347049a488Jeff Brown        const backtrace_frame_t* backtrace, size_t frames) {
6313e715b491e876865e752a3a69dd6f347049a488Jeff Brown    _LOG(tfd, !at_fault, "\nbacktrace:\n");
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
6513e715b491e876865e752a3a69dd6f347049a488Jeff Brown    backtrace_symbol_t backtrace_symbols[STACK_DEPTH];
6613e715b491e876865e752a3a69dd6f347049a488Jeff Brown    get_backtrace_symbols_ptrace(context, backtrace, frames, backtrace_symbols);
6713e715b491e876865e752a3a69dd6f347049a488Jeff Brown    for (size_t i = 0; i < frames; i++) {
6813e715b491e876865e752a3a69dd6f347049a488Jeff Brown        const backtrace_symbol_t* symbol = &backtrace_symbols[i];
6913e715b491e876865e752a3a69dd6f347049a488Jeff Brown        const char* map_name = symbol->map_info ? symbol->map_info->name : "<unknown>";
7013e715b491e876865e752a3a69dd6f347049a488Jeff Brown        const char* symbol_name = symbol->demangled_name ? symbol->demangled_name : symbol->name;
7113e715b491e876865e752a3a69dd6f347049a488Jeff Brown        if (symbol_name) {
7213e715b491e876865e752a3a69dd6f347049a488Jeff Brown            _LOG(tfd, !at_fault, "    #%02d  pc %08x  %s (%s)\n",
7313e715b491e876865e752a3a69dd6f347049a488Jeff Brown                    (int)i, symbol->relative_pc, map_name, symbol_name);
7413e715b491e876865e752a3a69dd6f347049a488Jeff Brown        } else {
7513e715b491e876865e752a3a69dd6f347049a488Jeff Brown            _LOG(tfd, !at_fault, "    #%02d  pc %08x  %s\n",
7613e715b491e876865e752a3a69dd6f347049a488Jeff Brown                    (int)i, symbol->relative_pc, map_name);
7713e715b491e876865e752a3a69dd6f347049a488Jeff Brown        }
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
7913e715b491e876865e752a3a69dd6f347049a488Jeff Brown    free_backtrace_symbols(backtrace_symbols, frames);
8013e715b491e876865e752a3a69dd6f347049a488Jeff Brown}
8113e715b491e876865e752a3a69dd6f347049a488Jeff Brown
8213e715b491e876865e752a3a69dd6f347049a488Jeff Brownstatic void dump_stack_segment(ptrace_context_t* context, int tfd, int pid,
8313e715b491e876865e752a3a69dd6f347049a488Jeff Brown        bool only_in_tombstone, uintptr_t* sp, size_t words, int label) {
8413e715b491e876865e752a3a69dd6f347049a488Jeff Brown    for (size_t i = 0; i < words; i++) {
8513e715b491e876865e752a3a69dd6f347049a488Jeff Brown        uint32_t stack_content;
8613e715b491e876865e752a3a69dd6f347049a488Jeff Brown        if (!try_get_word(pid, *sp, &stack_content)) {
8713e715b491e876865e752a3a69dd6f347049a488Jeff Brown            break;
8813e715b491e876865e752a3a69dd6f347049a488Jeff Brown        }
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
9013e715b491e876865e752a3a69dd6f347049a488Jeff Brown        const map_info_t* mi;
9113e715b491e876865e752a3a69dd6f347049a488Jeff Brown        const symbol_t* symbol;
9213e715b491e876865e752a3a69dd6f347049a488Jeff Brown        find_symbol_ptrace(context, stack_content, &mi, &symbol);
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
9413e715b491e876865e752a3a69dd6f347049a488Jeff Brown        if (symbol) {
9513e715b491e876865e752a3a69dd6f347049a488Jeff Brown            char* demangled_name = demangle_symbol_name(symbol->name);
9613e715b491e876865e752a3a69dd6f347049a488Jeff Brown            const char* symbol_name = demangled_name ? demangled_name : symbol->name;
9713e715b491e876865e752a3a69dd6f347049a488Jeff Brown            if (!i && label >= 0) {
9813e715b491e876865e752a3a69dd6f347049a488Jeff Brown                _LOG(tfd, only_in_tombstone, "    #%02d  %08x  %08x  %s (%s)\n",
9913e715b491e876865e752a3a69dd6f347049a488Jeff Brown                        label, *sp, stack_content, mi ? mi->name : "", symbol_name);
10013e715b491e876865e752a3a69dd6f347049a488Jeff Brown            } else {
10113e715b491e876865e752a3a69dd6f347049a488Jeff Brown                _LOG(tfd, only_in_tombstone, "         %08x  %08x  %s (%s)\n",
10213e715b491e876865e752a3a69dd6f347049a488Jeff Brown                        *sp, stack_content, mi ? mi->name : "", symbol_name);
10313e715b491e876865e752a3a69dd6f347049a488Jeff Brown            }
10413e715b491e876865e752a3a69dd6f347049a488Jeff Brown            free(demangled_name);
10513e715b491e876865e752a3a69dd6f347049a488Jeff Brown        } else {
10613e715b491e876865e752a3a69dd6f347049a488Jeff Brown            if (!i && label >= 0) {
10713e715b491e876865e752a3a69dd6f347049a488Jeff Brown                _LOG(tfd, only_in_tombstone, "    #%02d  %08x  %08x  %s\n",
10813e715b491e876865e752a3a69dd6f347049a488Jeff Brown                        label, *sp, stack_content, mi ? mi->name : "");
10913e715b491e876865e752a3a69dd6f347049a488Jeff Brown            } else {
11013e715b491e876865e752a3a69dd6f347049a488Jeff Brown                _LOG(tfd, only_in_tombstone, "         %08x  %08x  %s\n",
11113e715b491e876865e752a3a69dd6f347049a488Jeff Brown                        *sp, stack_content, mi ? mi->name : "");
11213e715b491e876865e752a3a69dd6f347049a488Jeff Brown            }
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
11413e715b491e876865e752a3a69dd6f347049a488Jeff Brown
11513e715b491e876865e752a3a69dd6f347049a488Jeff Brown        *sp += sizeof(uint32_t);
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
11913e715b491e876865e752a3a69dd6f347049a488Jeff Brownstatic void dump_stack(ptrace_context_t* context, int tfd, int pid, bool at_fault,
12013e715b491e876865e752a3a69dd6f347049a488Jeff Brown        const backtrace_frame_t* backtrace, size_t frames) {
12113e715b491e876865e752a3a69dd6f347049a488Jeff Brown    bool have_first = false;
12213e715b491e876865e752a3a69dd6f347049a488Jeff Brown    size_t first, last;
12313e715b491e876865e752a3a69dd6f347049a488Jeff Brown    for (size_t i = 0; i < frames; i++) {
12413e715b491e876865e752a3a69dd6f347049a488Jeff Brown        if (backtrace[i].stack_top) {
12513e715b491e876865e752a3a69dd6f347049a488Jeff Brown            if (!have_first) {
12613e715b491e876865e752a3a69dd6f347049a488Jeff Brown                have_first = true;
12713e715b491e876865e752a3a69dd6f347049a488Jeff Brown                first = i;
12813e715b491e876865e752a3a69dd6f347049a488Jeff Brown            }
12913e715b491e876865e752a3a69dd6f347049a488Jeff Brown            last = i;
13013e715b491e876865e752a3a69dd6f347049a488Jeff Brown        }
13113e715b491e876865e752a3a69dd6f347049a488Jeff Brown    }
13213e715b491e876865e752a3a69dd6f347049a488Jeff Brown    if (!have_first) {
13313e715b491e876865e752a3a69dd6f347049a488Jeff Brown        return;
13413e715b491e876865e752a3a69dd6f347049a488Jeff Brown    }
13513e715b491e876865e752a3a69dd6f347049a488Jeff Brown
13613e715b491e876865e752a3a69dd6f347049a488Jeff Brown    _LOG(tfd, !at_fault, "\nstack:\n");
13713e715b491e876865e752a3a69dd6f347049a488Jeff Brown
13813e715b491e876865e752a3a69dd6f347049a488Jeff Brown    // Dump a few words before the first frame.
13913e715b491e876865e752a3a69dd6f347049a488Jeff Brown    bool only_in_tombstone = !at_fault;
14013e715b491e876865e752a3a69dd6f347049a488Jeff Brown    uintptr_t sp = backtrace[first].stack_top - STACK_WORDS * sizeof(uint32_t);
14113e715b491e876865e752a3a69dd6f347049a488Jeff Brown    dump_stack_segment(context, tfd, pid, only_in_tombstone, &sp, STACK_WORDS, -1);
14213e715b491e876865e752a3a69dd6f347049a488Jeff Brown
14313e715b491e876865e752a3a69dd6f347049a488Jeff Brown    // Dump a few words from all successive frames.
14413e715b491e876865e752a3a69dd6f347049a488Jeff Brown    // Only log the first 3 frames, put the rest in the tombstone.
14513e715b491e876865e752a3a69dd6f347049a488Jeff Brown    for (size_t i = first; i <= last; i++) {
14613e715b491e876865e752a3a69dd6f347049a488Jeff Brown        const backtrace_frame_t* frame = &backtrace[i];
14713e715b491e876865e752a3a69dd6f347049a488Jeff Brown        if (sp != frame->stack_top) {
14813e715b491e876865e752a3a69dd6f347049a488Jeff Brown            _LOG(tfd, only_in_tombstone, "         ........  ........\n");
14913e715b491e876865e752a3a69dd6f347049a488Jeff Brown            sp = frame->stack_top;
15013e715b491e876865e752a3a69dd6f347049a488Jeff Brown        }
15113e715b491e876865e752a3a69dd6f347049a488Jeff Brown        if (i - first == 3) {
15213e715b491e876865e752a3a69dd6f347049a488Jeff Brown            only_in_tombstone = true;
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
15413e715b491e876865e752a3a69dd6f347049a488Jeff Brown        if (i == last) {
15513e715b491e876865e752a3a69dd6f347049a488Jeff Brown            dump_stack_segment(context, tfd, pid, only_in_tombstone, &sp, STACK_WORDS, i);
15613e715b491e876865e752a3a69dd6f347049a488Jeff Brown            if (sp < frame->stack_top + frame->stack_size) {
15713e715b491e876865e752a3a69dd6f347049a488Jeff Brown                _LOG(tfd, only_in_tombstone, "         ........  ........\n");
15813e715b491e876865e752a3a69dd6f347049a488Jeff Brown            }
15913e715b491e876865e752a3a69dd6f347049a488Jeff Brown        } else {
16013e715b491e876865e752a3a69dd6f347049a488Jeff Brown            size_t words = frame->stack_size / sizeof(uint32_t);
16113e715b491e876865e752a3a69dd6f347049a488Jeff Brown            if (words == 0) {
16213e715b491e876865e752a3a69dd6f347049a488Jeff Brown                words = 1;
16313e715b491e876865e752a3a69dd6f347049a488Jeff Brown            } else if (words > STACK_WORDS) {
16413e715b491e876865e752a3a69dd6f347049a488Jeff Brown                words = STACK_WORDS;
16513e715b491e876865e752a3a69dd6f347049a488Jeff Brown            }
16613e715b491e876865e752a3a69dd6f347049a488Jeff Brown            dump_stack_segment(context, tfd, pid, only_in_tombstone, &sp, words, i);
16713e715b491e876865e752a3a69dd6f347049a488Jeff Brown        }
16813e715b491e876865e752a3a69dd6f347049a488Jeff Brown    }
16913e715b491e876865e752a3a69dd6f347049a488Jeff Brown}
17013e715b491e876865e752a3a69dd6f347049a488Jeff Brown
17113e715b491e876865e752a3a69dd6f347049a488Jeff Brownvoid dump_backtrace_and_stack(ptrace_context_t* context, int tfd, pid_t tid, bool at_fault) {
17213e715b491e876865e752a3a69dd6f347049a488Jeff Brown    backtrace_frame_t backtrace[STACK_DEPTH];
17313e715b491e876865e752a3a69dd6f347049a488Jeff Brown    ssize_t frames = unwind_backtrace_ptrace(tid, context, backtrace, 0, STACK_DEPTH);
17413e715b491e876865e752a3a69dd6f347049a488Jeff Brown    if (frames > 0) {
17513e715b491e876865e752a3a69dd6f347049a488Jeff Brown        dump_backtrace(context, tfd, tid, at_fault, backtrace, frames);
17613e715b491e876865e752a3a69dd6f347049a488Jeff Brown        dump_stack(context, tfd, tid, at_fault, backtrace, frames);
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
18013e715b491e876865e752a3a69dd6f347049a488Jeff Brownvoid dump_memory(int tfd, pid_t tid, uintptr_t addr, bool at_fault) {
18113e715b491e876865e752a3a69dd6f347049a488Jeff Brown    char code_buffer[64];       /* actual 8+1+((8+1)*4) + 1 == 45 */
18213e715b491e876865e752a3a69dd6f347049a488Jeff Brown    char ascii_buffer[32];      /* actual 16 + 1 == 17 */
18313e715b491e876865e752a3a69dd6f347049a488Jeff Brown    uintptr_t p, end;
18413e715b491e876865e752a3a69dd6f347049a488Jeff Brown
18513e715b491e876865e752a3a69dd6f347049a488Jeff Brown    p = addr & ~3;
18613e715b491e876865e752a3a69dd6f347049a488Jeff Brown    p -= 32;
18713e715b491e876865e752a3a69dd6f347049a488Jeff Brown    if (p > addr) {
18813e715b491e876865e752a3a69dd6f347049a488Jeff Brown        /* catch underflow */
18913e715b491e876865e752a3a69dd6f347049a488Jeff Brown        p = 0;
19013e715b491e876865e752a3a69dd6f347049a488Jeff Brown    }
19113e715b491e876865e752a3a69dd6f347049a488Jeff Brown    end = p + 80;
19213e715b491e876865e752a3a69dd6f347049a488Jeff Brown    /* catch overflow; 'end - p' has to be multiples of 16 */
19313e715b491e876865e752a3a69dd6f347049a488Jeff Brown    while (end < p)
19413e715b491e876865e752a3a69dd6f347049a488Jeff Brown        end -= 16;
19513e715b491e876865e752a3a69dd6f347049a488Jeff Brown
19613e715b491e876865e752a3a69dd6f347049a488Jeff Brown    /* Dump the code around PC as:
19713e715b491e876865e752a3a69dd6f347049a488Jeff Brown     *  addr     contents                             ascii
19813e715b491e876865e752a3a69dd6f347049a488Jeff Brown     *  00008d34 ef000000 e8bd0090 e1b00000 512fff1e  ............../Q
19913e715b491e876865e752a3a69dd6f347049a488Jeff Brown     *  00008d44 ea00b1f9 e92d0090 e3a070fc ef000000  ......-..p......
20013e715b491e876865e752a3a69dd6f347049a488Jeff Brown     */
20113e715b491e876865e752a3a69dd6f347049a488Jeff Brown    while (p < end) {
20213e715b491e876865e752a3a69dd6f347049a488Jeff Brown        char* asc_out = ascii_buffer;
20313e715b491e876865e752a3a69dd6f347049a488Jeff Brown
20413e715b491e876865e752a3a69dd6f347049a488Jeff Brown        sprintf(code_buffer, "%08x ", p);
20513e715b491e876865e752a3a69dd6f347049a488Jeff Brown
20613e715b491e876865e752a3a69dd6f347049a488Jeff Brown        int i;
20713e715b491e876865e752a3a69dd6f347049a488Jeff Brown        for (i = 0; i < 4; i++) {
20813e715b491e876865e752a3a69dd6f347049a488Jeff Brown            /*
20913e715b491e876865e752a3a69dd6f347049a488Jeff Brown             * If we see (data == -1 && errno != 0), we know that the ptrace
21013e715b491e876865e752a3a69dd6f347049a488Jeff Brown             * call failed, probably because we're dumping memory in an
21113e715b491e876865e752a3a69dd6f347049a488Jeff Brown             * unmapped or inaccessible page.  I don't know if there's
21213e715b491e876865e752a3a69dd6f347049a488Jeff Brown             * value in making that explicit in the output -- it likely
21313e715b491e876865e752a3a69dd6f347049a488Jeff Brown             * just complicates parsing and clarifies nothing for the
21413e715b491e876865e752a3a69dd6f347049a488Jeff Brown             * enlightened reader.
21513e715b491e876865e752a3a69dd6f347049a488Jeff Brown             */
21613e715b491e876865e752a3a69dd6f347049a488Jeff Brown            long data = ptrace(PTRACE_PEEKTEXT, tid, (void*)p, NULL);
21713e715b491e876865e752a3a69dd6f347049a488Jeff Brown            sprintf(code_buffer + strlen(code_buffer), "%08lx ", data);
21813e715b491e876865e752a3a69dd6f347049a488Jeff Brown
21913e715b491e876865e752a3a69dd6f347049a488Jeff Brown            int j;
22013e715b491e876865e752a3a69dd6f347049a488Jeff Brown            for (j = 0; j < 4; j++) {
22113e715b491e876865e752a3a69dd6f347049a488Jeff Brown                /*
22213e715b491e876865e752a3a69dd6f347049a488Jeff Brown                 * Our isprint() allows high-ASCII characters that display
22313e715b491e876865e752a3a69dd6f347049a488Jeff Brown                 * differently (often badly) in different viewers, so we
22413e715b491e876865e752a3a69dd6f347049a488Jeff Brown                 * just use a simpler test.
22513e715b491e876865e752a3a69dd6f347049a488Jeff Brown                 */
22613e715b491e876865e752a3a69dd6f347049a488Jeff Brown                char val = (data >> (j*8)) & 0xff;
22713e715b491e876865e752a3a69dd6f347049a488Jeff Brown                if (val >= 0x20 && val < 0x7f) {
22813e715b491e876865e752a3a69dd6f347049a488Jeff Brown                    *asc_out++ = val;
22913e715b491e876865e752a3a69dd6f347049a488Jeff Brown                } else {
23013e715b491e876865e752a3a69dd6f347049a488Jeff Brown                    *asc_out++ = '.';
23113e715b491e876865e752a3a69dd6f347049a488Jeff Brown                }
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
23313e715b491e876865e752a3a69dd6f347049a488Jeff Brown            p += 4;
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
23513e715b491e876865e752a3a69dd6f347049a488Jeff Brown        *asc_out = '\0';
23613e715b491e876865e752a3a69dd6f347049a488Jeff Brown        _LOG(tfd, !at_fault, "    %s %s\n", code_buffer, ascii_buffer);
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
239136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden
24013e715b491e876865e752a3a69dd6f347049a488Jeff Brownvoid dump_nearby_maps(ptrace_context_t* context, int tfd, pid_t tid) {
24113e715b491e876865e752a3a69dd6f347049a488Jeff Brown    siginfo_t si;
24213e715b491e876865e752a3a69dd6f347049a488Jeff Brown    memset(&si, 0, sizeof(si));
24313e715b491e876865e752a3a69dd6f347049a488Jeff Brown    if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) {
24413e715b491e876865e752a3a69dd6f347049a488Jeff Brown        _LOG(tfd, false, "cannot get siginfo for %d: %s\n",
24513e715b491e876865e752a3a69dd6f347049a488Jeff Brown                tid, strerror(errno));
24613e715b491e876865e752a3a69dd6f347049a488Jeff Brown        return;
24713e715b491e876865e752a3a69dd6f347049a488Jeff Brown    }
24813e715b491e876865e752a3a69dd6f347049a488Jeff Brown    if (!signal_has_address(si.si_signo)) {
24913e715b491e876865e752a3a69dd6f347049a488Jeff Brown        return;
25013e715b491e876865e752a3a69dd6f347049a488Jeff Brown    }
25113e715b491e876865e752a3a69dd6f347049a488Jeff Brown
25213e715b491e876865e752a3a69dd6f347049a488Jeff Brown    uintptr_t addr = (uintptr_t) si.si_addr;
25313e715b491e876865e752a3a69dd6f347049a488Jeff Brown    addr &= ~0xfff;     /* round to 4K page boundary */
25413e715b491e876865e752a3a69dd6f347049a488Jeff Brown    if (addr == 0) {    /* null-pointer deref */
25513e715b491e876865e752a3a69dd6f347049a488Jeff Brown        return;
25613e715b491e876865e752a3a69dd6f347049a488Jeff Brown    }
25713e715b491e876865e752a3a69dd6f347049a488Jeff Brown
25813e715b491e876865e752a3a69dd6f347049a488Jeff Brown    _LOG(tfd, false, "\nmemory map around fault addr %08x:\n", (int)si.si_addr);
25913e715b491e876865e752a3a69dd6f347049a488Jeff Brown
26013e715b491e876865e752a3a69dd6f347049a488Jeff Brown    /*
26113e715b491e876865e752a3a69dd6f347049a488Jeff Brown     * Search for a match, or for a hole where the match would be.  The list
26213e715b491e876865e752a3a69dd6f347049a488Jeff Brown     * is backward from the file content, so it starts at high addresses.
26313e715b491e876865e752a3a69dd6f347049a488Jeff Brown     */
26413e715b491e876865e752a3a69dd6f347049a488Jeff Brown    bool found = false;
26513e715b491e876865e752a3a69dd6f347049a488Jeff Brown    map_info_t* map = context->map_info_list;
26613e715b491e876865e752a3a69dd6f347049a488Jeff Brown    map_info_t *next = NULL;
26713e715b491e876865e752a3a69dd6f347049a488Jeff Brown    map_info_t *prev = NULL;
26813e715b491e876865e752a3a69dd6f347049a488Jeff Brown    while (map != NULL) {
26913e715b491e876865e752a3a69dd6f347049a488Jeff Brown        if (addr >= map->start && addr < map->end) {
27013e715b491e876865e752a3a69dd6f347049a488Jeff Brown            found = true;
27113e715b491e876865e752a3a69dd6f347049a488Jeff Brown            next = map->next;
27213e715b491e876865e752a3a69dd6f347049a488Jeff Brown            break;
27313e715b491e876865e752a3a69dd6f347049a488Jeff Brown        } else if (addr >= map->end) {
27413e715b491e876865e752a3a69dd6f347049a488Jeff Brown            /* map would be between "prev" and this entry */
27513e715b491e876865e752a3a69dd6f347049a488Jeff Brown            next = map;
27613e715b491e876865e752a3a69dd6f347049a488Jeff Brown            map = NULL;
27713e715b491e876865e752a3a69dd6f347049a488Jeff Brown            break;
27813e715b491e876865e752a3a69dd6f347049a488Jeff Brown        }
27913e715b491e876865e752a3a69dd6f347049a488Jeff Brown
28013e715b491e876865e752a3a69dd6f347049a488Jeff Brown        prev = map;
28113e715b491e876865e752a3a69dd6f347049a488Jeff Brown        map = map->next;
28213e715b491e876865e752a3a69dd6f347049a488Jeff Brown    }
28313e715b491e876865e752a3a69dd6f347049a488Jeff Brown
28413e715b491e876865e752a3a69dd6f347049a488Jeff Brown    /*
28513e715b491e876865e752a3a69dd6f347049a488Jeff Brown     * Show "next" then "match" then "prev" so that the addresses appear in
28613e715b491e876865e752a3a69dd6f347049a488Jeff Brown     * ascending order (like /proc/pid/maps).
28713e715b491e876865e752a3a69dd6f347049a488Jeff Brown     */
28813e715b491e876865e752a3a69dd6f347049a488Jeff Brown    if (next != NULL) {
28913e715b491e876865e752a3a69dd6f347049a488Jeff Brown        _LOG(tfd, false, "    %08x-%08x %s\n", next->start, next->end, next->name);
29013e715b491e876865e752a3a69dd6f347049a488Jeff Brown    } else {
29113e715b491e876865e752a3a69dd6f347049a488Jeff Brown        _LOG(tfd, false, "    (no map below)\n");
29213e715b491e876865e752a3a69dd6f347049a488Jeff Brown    }
29313e715b491e876865e752a3a69dd6f347049a488Jeff Brown    if (map != NULL) {
29413e715b491e876865e752a3a69dd6f347049a488Jeff Brown        _LOG(tfd, false, "    %08x-%08x %s\n", map->start, map->end, map->name);
29513e715b491e876865e752a3a69dd6f347049a488Jeff Brown    } else {
29613e715b491e876865e752a3a69dd6f347049a488Jeff Brown        _LOG(tfd, false, "    (no map for address)\n");
29713e715b491e876865e752a3a69dd6f347049a488Jeff Brown    }
29813e715b491e876865e752a3a69dd6f347049a488Jeff Brown    if (prev != NULL) {
29913e715b491e876865e752a3a69dd6f347049a488Jeff Brown        _LOG(tfd, false, "    %08x-%08x %s\n", prev->start, prev->end, prev->name);
30013e715b491e876865e752a3a69dd6f347049a488Jeff Brown    } else {
30113e715b491e876865e752a3a69dd6f347049a488Jeff Brown        _LOG(tfd, false, "    (no map above)\n");
302136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden    }
303136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden}
304