⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 debuggerd.c

📁 Android 一些工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* system/debuggerd/debuggerd.c**** Copyright 2006, The Android Open Source Project**** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ****     http://www.apache.org/licenses/LICENSE-2.0 **** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License.*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <signal.h>#include <pthread.h>#include <stdarg.h>#include <fcntl.h>#include <sys/types.h>#include <dirent.h>#include <sys/ptrace.h>#include <sys/wait.h>#include <sys/exec_elf.h>#include <sys/stat.h>#include <cutils/sockets.h>#include <cutils/logd.h>#include <cutils/sockets.h>#include <cutils/properties.h>#include <linux/input.h>#include <private/android_filesystem_config.h>#include "utility.h"/* Main entry point to get the backtrace from the crashing process */extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map,                                        unsigned int sp_list[],                                        int *frame0_pc_sane,                                        bool at_fault);static char **process_name_ptr;static int logsocket = -1;#define ANDROID_LOG_INFO 4/* Log information onto the tombstone */void _LOG(int tfd, bool in_tombstone_only, const char *fmt, ...){    char buf[128];        va_list ap;    va_start(ap, fmt);    if (tfd >= 0) {        int len;        vsnprintf(buf, sizeof(buf), fmt, ap);        len = strlen(buf);        if(tfd >= 0) write(tfd, buf, len);    }    if (!in_tombstone_only)        __android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap);}#define LOG(fmt...) _LOG(-1, 0, fmt)#if 0#define XLOG(fmt...) _LOG(-1, 0, fmt)#else#define XLOG(fmt...) do {} while(0)#endif// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419   /system/lib/libcomposer.so// 012345678901234567890123456789012345678901234567890123456789// 0         1         2         3         4         5mapinfo *parse_maps_line(char *line){    mapinfo *mi;    int len = strlen(line);    if(len < 1) return 0;    line[--len] = 0;        if(len < 50) return 0;    if(line[20] != 'x') return 0;    mi = malloc(sizeof(mapinfo) + (len - 47));    if(mi == 0) return 0;        mi->start = strtoul(line, 0, 16);    mi->end = strtoul(line + 9, 0, 16);    /* To be filled in parse_exidx_info if the mapped section starts with      * elf_header     */    mi->exidx_start = mi->exidx_end = 0;    mi->next = 0;    strcpy(mi->name, line + 49);    return mi;}void dump_build_info(int tfd){    char fingerprint[PROPERTY_VALUE_MAX];    property_get("ro.build.fingerprint", fingerprint, "unknown");    _LOG(tfd, false, "Build fingerprint: '%s'\n", fingerprint);}void dump_stack_and_code(int tfd, int pid, mapinfo *map,                          int unwind_depth, unsigned int sp_list[],                         int frame0_pc_sane, bool at_fault){    unsigned int sp, pc, p, end, data;    struct pt_regs r;    int sp_depth;    bool only_in_tombstone = !at_fault;    if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return;    sp = r.ARM_sp;    pc = r.ARM_pc;    /* Died because calling the weeds - dump     * the code around the PC in the next frame instead.     */    if (frame0_pc_sane == 0) {        pc = r.ARM_lr;    }    _LOG(tfd, true, "code%s:\n", frame0_pc_sane ? "" : " (around frame #01)");    end = p = pc & ~3;    p -= 16;    /* Dump the code as:     *  PC         contents     *  00008d34   fffffcd0 4c0eb530 b0934a0e 1c05447c     *  00008d44   f7ff18a0 490ced94 68035860 d0012b00     */    while (p <= end) {        int i;        _LOG(tfd, true, " %08x  ", p);        for (i = 0; i < 4; i++) {            data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);            _LOG(tfd, true, " %08x", data);            p += 4;        }        _LOG(tfd, true, "\n", p);    }    p = sp - 64;    p &= ~3;    if (unwind_depth != 0) {        if (unwind_depth < STACK_CONTENT_DEPTH) {            end = sp_list[unwind_depth-1];        }        else {            end = sp_list[STACK_CONTENT_DEPTH-1];        }    }    else {        end = sp | 0x000000ff;        end += 0xff;    }    _LOG(tfd, only_in_tombstone, "stack:\n");    /* If the crash is due to PC == 0, there will be two frames that     * have identical SP value.     */    if (sp_list[0] == sp_list[1]) {        sp_depth = 1;    }    else {        sp_depth = 0;    }    while (p <= end) {         char *prompt;          char level[16];         data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);         if (p == sp_list[sp_depth]) {             sprintf(level, "#%02d", sp_depth++);             prompt = level;         }         else {             prompt = "   ";         }                  /* Print the stack content in the log for the first 3 frames. For the          * rest only print them in the tombstone file.          */         _LOG(tfd, (sp_depth > 2) || only_in_tombstone,               "%s %08x  %08x  %s\n", prompt, p, data,               map_to_name(map, data, ""));         p += 4;    }    /* print another 64-byte of stack data after the last frame */    end = p+64;    while (p <= end) {         data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);         _LOG(tfd, (sp_depth > 2) || only_in_tombstone,               "    %08x  %08x  %s\n", p, data,               map_to_name(map, data, ""));         p += 4;    }}void dump_pc_and_lr(int tfd, int pid, mapinfo *map, int unwound_level,                     bool at_fault){    struct pt_regs r;    if(ptrace(PTRACE_GETREGS, pid, 0, &r)) {        _LOG(tfd, !at_fault, "tid %d not responding!\n", pid);        return;    }    if (unwound_level == 0) {        _LOG(tfd, !at_fault, "         #%02d  pc %08x  %s\n", 0, r.ARM_pc,             map_to_name(map, r.ARM_pc, "<unknown>"));    }    _LOG(tfd, !at_fault, "         #%02d  lr %08x  %s\n", 1, r.ARM_lr,            map_to_name(map, r.ARM_lr, "<unknown>"));}void dump_registers(int tfd, int pid, bool at_fault) {    struct pt_regs r;    bool only_in_tombstone = !at_fault;    if(ptrace(PTRACE_GETREGS, pid, 0, &r)) {        _LOG(tfd, only_in_tombstone,              "cannot get registers: %s\n", strerror(errno));        return;    }        _LOG(tfd, only_in_tombstone, " r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",         r.ARM_r0, r.ARM_r1, r.ARM_r2, r.ARM_r3);    _LOG(tfd, only_in_tombstone, " r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",         r.ARM_r4, r.ARM_r5, r.ARM_r6, r.ARM_r7);    _LOG(tfd, only_in_tombstone, " r8 %08x  r9 %08x  10 %08x  fp %08x\n",         r.ARM_r8, r.ARM_r9, r.ARM_r10, r.ARM_fp);    _LOG(tfd, only_in_tombstone,          " ip %08x  sp %08x  lr %08x  pc %08x  cpsr %08x\n",         r.ARM_ip, r.ARM_sp, r.ARM_lr, r.ARM_pc, r.ARM_cpsr);  }const char *get_signame(int sig){    switch(sig) {    case SIGILL:     return "SIGILL";    case SIGABRT:    return "SIGABRT";    case SIGBUS:     return "SIGBUS";    case SIGFPE:     return "SIGFPE";    case SIGSEGV:    return "SIGSEGV";    case SIGSTKFLT:  return "SIGSTKFLT";    default:         return "?";    }}void dump_fault_addr(int tfd, int pid, int sig){    siginfo_t si;        memset(&si, 0, sizeof(si));    if(ptrace(PTRACE_GETSIGINFO, pid, 0, &si)){        _LOG(tfd, false, "cannot get siginfo: %s\n", strerror(errno));    } else {        _LOG(tfd, false, "signal %d (%s), fault addr %08x\n",            sig, get_signame(sig), si.si_addr);    }}void dump_crash_banner(int tfd, unsigned pid, unsigned tid, int sig){    char data[1024];    char *x = 0;    FILE *fp;        sprintf(data, "/proc/%d/cmdline", pid);    fp = fopen(data, "r");    if(fp) {        x = fgets(data, 1024, fp);        fclose(fp);    }        _LOG(tfd, false,         "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");    dump_build_info(tfd);    _LOG(tfd, false, "pid: %d, tid: %d  >>> %s <<<\n",         pid, tid, x ? x : "UNKNOWN");        if(sig) dump_fault_addr(tfd, tid, sig);}static void parse_exidx_info(mapinfo *milist, pid_t pid){    mapinfo *mi;    for (mi = milist; mi != NULL; mi = mi->next) {        Elf32_Ehdr ehdr;        memset(&ehdr, 0, sizeof(Elf32_Ehdr));        /* Read in sizeof(Elf32_Ehdr) worth of data from the beginning of          * mapped section.         */        get_remote_struct(pid, (void *) (mi->start), &ehdr,                           sizeof(Elf32_Ehdr));        /* Check if it has the matching magic words */        if (IS_ELF(ehdr)) {            Elf32_Phdr phdr;            Elf32_Phdr *ptr;            int i;            ptr = (Elf32_Phdr *) (mi->start + ehdr.e_phoff);            for (i = 0; i < ehdr.e_phnum; i++) {                /* Parse the program header */                get_remote_struct(pid, (void *) ptr+i, &phdr,                                   sizeof(Elf32_Phdr));                /* Found a EXIDX segment? */                if (phdr.p_type == PT_ARM_EXIDX) {                    mi->exidx_start = mi->start + phdr.p_offset;                    mi->exidx_end = mi->exidx_start + phdr.p_filesz;                    break;                }            }        }    }}void dump_crash_report(int tfd, unsigned pid, unsigned tid, bool at_fault){    char data[1024];    FILE *fp;    mapinfo *milist = 0;    unsigned int sp_list[STACK_CONTENT_DEPTH];    int stack_depth;    int frame0_pc_sane = 1;        if (!at_fault) {        _LOG(tfd, true,         "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");        _LOG(tfd, true, "pid: %d, tid: %d\n", pid, tid);    }    dump_registers(tfd, tid, at_fault);        /* Clear stack pointer records */    memset(sp_list, 0, sizeof(sp_list));    sprintf(data, "/proc/%d/maps", pid);    fp = fopen(data, "r");    if(fp) {        while(fgets(data, 1024, fp)) {            mapinfo *mi = parse_maps_line(data);            if(mi) {                mi->next = milist;                milist = mi;            }        }        fclose(fp);    }    parse_exidx_info(milist, tid);    /* If stack unwinder fails, use the default solution to dump the stack     * content.     */    stack_depth = unwind_backtrace_with_ptrace(tfd, tid, milist, sp_list,                                               &frame0_pc_sane, at_fault);    /* The stack unwinder should at least unwind two levels of stack. If less     * level is seen we make sure at lease pc and lr are dumped.     */    if (stack_depth < 2) {        dump_pc_and_lr(tfd, tid, milist, stack_depth, at_fault);    }    dump_stack_and_code(tfd, tid, milist, stack_depth, sp_list, frame0_pc_sane,                        at_fault);    while(milist) {        mapinfo *next = milist->next;        free(milist);        milist = next;    }}/* FIXME: unused: use it or lose it*/#if 0staticvoid start_gdbserver_vs(int pid, int port){    pid_t p;    char *args[5];    char commspec[16];    char pidspec[16];        p = fork();    if(p < 0) {        LOG("could not fork()\n");        return;    }    if(p == 0) {        sprintf(commspec, ":%d", port);        sprintf(pidspec, "%d", pid);        args[0] = "/system/bin/gdbserver";        args[1] = commspec;        args[2] = "--attach";        args[3] = pidspec;        args[4] = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -