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

📄 gdbstub.c

📁 qemu性能直逼VMware的仿真器QEMU 的模擬速度約為實機的 25%;約為 Bochs 的 60 倍。Plex86、User-Mode-Linux、VMware 和 Virtual PC 則比
💻 C
📖 第 1 页 / 共 3 页
字号:
        if (*p == ':')            p++;        hextomem(mem_buf, p, len);        if (cpu_memory_rw_debug(env, addr, mem_buf, len, 1) != 0)            put_packet(s, "E14");        else            put_packet(s, "OK");        break;    case 'Z':        type = strtoul(p, (char **)&p, 16);        if (*p == ',')            p++;        addr = strtoull(p, (char **)&p, 16);        if (*p == ',')            p++;        len = strtoull(p, (char **)&p, 16);        if (type == 0 || type == 1) {            if (cpu_breakpoint_insert(env, addr) < 0)                goto breakpoint_error;            put_packet(s, "OK");        } else {        breakpoint_error:            put_packet(s, "E22");        }        break;    case 'z':        type = strtoul(p, (char **)&p, 16);        if (*p == ',')            p++;        addr = strtoull(p, (char **)&p, 16);        if (*p == ',')            p++;        len = strtoull(p, (char **)&p, 16);        if (type == 0 || type == 1) {            cpu_breakpoint_remove(env, addr);            put_packet(s, "OK");        } else {            goto breakpoint_error;        }        break;#ifdef CONFIG_LINUX_USER    case 'q':        if (strncmp(p, "Offsets", 7) == 0) {            TaskState *ts = env->opaque;            sprintf(buf, "Text=%x;Data=%x;Bss=%x", ts->info->code_offset,                ts->info->data_offset, ts->info->data_offset);            put_packet(s, buf);            break;        }        /* Fall through.  */#endif    default:        //        unknown_command:        /* put empty packet */        buf[0] = '\0';        put_packet(s, buf);        break;    }    return RS_IDLE;}extern void tb_flush(CPUState *env);#ifndef CONFIG_USER_ONLYstatic void gdb_vm_stopped(void *opaque, int reason){    GDBState *s = opaque;    char buf[256];    int ret;    if (s->state == RS_SYSCALL)        return;    /* disable single step if it was enable */    cpu_single_step(s->env, 0);    if (reason == EXCP_DEBUG) {	tb_flush(s->env);        ret = SIGTRAP;    } else if (reason == EXCP_INTERRUPT) {        ret = SIGINT;    } else {        ret = 0;    }    snprintf(buf, sizeof(buf), "S%02x", ret);    put_packet(s, buf);}#endif/* Send a gdb syscall request.   This accepts limited printf-style format specifiers, specifically:    %x - target_ulong argument printed in hex.    %s - string pointer (target_ulong) and length (int) pair.  */void gdb_do_syscall(gdb_syscall_complete_cb cb, char *fmt, ...){    va_list va;    char buf[256];    char *p;    target_ulong addr;    GDBState *s;    s = gdb_syscall_state;    if (!s)        return;    gdb_current_syscall_cb = cb;    s->state = RS_SYSCALL;#ifndef CONFIG_USER_ONLY    vm_stop(EXCP_DEBUG);#endif    s->state = RS_IDLE;    va_start(va, fmt);    p = buf;    *(p++) = 'F';    while (*fmt) {        if (*fmt == '%') {            fmt++;            switch (*fmt++) {            case 'x':                addr = va_arg(va, target_ulong);                p += sprintf(p, TARGET_FMT_lx, addr);                break;            case 's':                addr = va_arg(va, target_ulong);                p += sprintf(p, TARGET_FMT_lx "/%x", addr, va_arg(va, int));                break;            default:                fprintf(stderr, "gdbstub: Bad syscall format string '%s'\n",                        fmt - 1);                break;            }        } else {            *(p++) = *(fmt++);        }    }    va_end(va);    put_packet(s, buf);#ifdef CONFIG_USER_ONLY    gdb_handlesig(s->env, 0);#else    cpu_interrupt(s->env, CPU_INTERRUPT_EXIT);#endif}static void gdb_read_byte(GDBState *s, int ch){    CPUState *env = s->env;    int i, csum;    char reply[1];#ifndef CONFIG_USER_ONLY    if (s->last_packet_len) {        /* Waiting for a response to the last packet.  If we see the start           of a new command then abandon the previous response.  */        if (ch == '-') {#ifdef DEBUG_GDB            printf("Got NACK, retransmitting\n");#endif            put_buffer(s, s->last_packet, s->last_packet_len);        }#ifdef DEBUG_GDB        else if (ch == '+')            printf("Got ACK\n");        else            printf("Got '%c' when expecting ACK/NACK\n", ch);#endif        if (ch == '+' || ch == '$')            s->last_packet_len = 0;        if (ch != '$')            return;    }    if (vm_running) {        /* when the CPU is running, we cannot do anything except stop           it when receiving a char */        vm_stop(EXCP_INTERRUPT);    } else #endif    {        switch(s->state) {        case RS_IDLE:            if (ch == '$') {                s->line_buf_index = 0;                s->state = RS_GETLINE;            }            break;        case RS_GETLINE:            if (ch == '#') {            s->state = RS_CHKSUM1;            } else if (s->line_buf_index >= sizeof(s->line_buf) - 1) {                s->state = RS_IDLE;            } else {            s->line_buf[s->line_buf_index++] = ch;            }            break;        case RS_CHKSUM1:            s->line_buf[s->line_buf_index] = '\0';            s->line_csum = fromhex(ch) << 4;            s->state = RS_CHKSUM2;            break;        case RS_CHKSUM2:            s->line_csum |= fromhex(ch);            csum = 0;            for(i = 0; i < s->line_buf_index; i++) {                csum += s->line_buf[i];            }            if (s->line_csum != (csum & 0xff)) {                reply[0] = '-';                put_buffer(s, reply, 1);                s->state = RS_IDLE;            } else {                reply[0] = '+';                put_buffer(s, reply, 1);                s->state = gdb_handle_packet(s, env, s->line_buf);            }            break;        default:            abort();        }    }}#ifdef CONFIG_USER_ONLYintgdb_handlesig (CPUState *env, int sig){  GDBState *s;  char buf[256];  int n;  if (gdbserver_fd < 0)    return sig;  s = &gdbserver_state;  /* disable single step if it was enabled */  cpu_single_step(env, 0);  tb_flush(env);  if (sig != 0)    {      snprintf(buf, sizeof(buf), "S%02x", sig);      put_packet(s, buf);    }  sig = 0;  s->state = RS_IDLE;  s->running_state = 0;  while (s->running_state == 0) {      n = read (s->fd, buf, 256);      if (n > 0)        {          int i;          for (i = 0; i < n; i++)            gdb_read_byte (s, buf[i]);        }      else if (n == 0 || errno != EAGAIN)        {          /* XXX: Connection closed.  Should probably wait for annother             connection before continuing.  */          return sig;        }  }  return sig;}/* Tell the remote gdb that the process has exited.  */void gdb_exit(CPUState *env, int code){  GDBState *s;  char buf[4];  if (gdbserver_fd < 0)    return;  s = &gdbserver_state;  snprintf(buf, sizeof(buf), "W%02x", code);  put_packet(s, buf);}static void gdb_accept(void *opaque){    GDBState *s;    struct sockaddr_in sockaddr;    socklen_t len;    int val, fd;    for(;;) {        len = sizeof(sockaddr);        fd = accept(gdbserver_fd, (struct sockaddr *)&sockaddr, &len);        if (fd < 0 && errno != EINTR) {            perror("accept");            return;        } else if (fd >= 0) {            break;        }    }    /* set short latency */    val = 1;    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));        s = &gdbserver_state;    memset (s, 0, sizeof (GDBState));    s->env = first_cpu; /* XXX: allow to change CPU */    s->fd = fd;    gdb_syscall_state = s;    fcntl(fd, F_SETFL, O_NONBLOCK);}static int gdbserver_open(int port){    struct sockaddr_in sockaddr;    int fd, val, ret;    fd = socket(PF_INET, SOCK_STREAM, 0);    if (fd < 0) {        perror("socket");        return -1;    }    /* allow fast reuse */    val = 1;    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));    sockaddr.sin_family = AF_INET;    sockaddr.sin_port = htons(port);    sockaddr.sin_addr.s_addr = 0;    ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));    if (ret < 0) {        perror("bind");        return -1;    }    ret = listen(fd, 0);    if (ret < 0) {        perror("listen");        return -1;    }    return fd;}int gdbserver_start(int port){    gdbserver_fd = gdbserver_open(port);    if (gdbserver_fd < 0)        return -1;    /* accept connections */    gdb_accept (NULL);    return 0;}#elsestatic int gdb_chr_can_recieve(void *opaque){  return 1;}static void gdb_chr_recieve(void *opaque, const uint8_t *buf, int size){    GDBState *s = opaque;    int i;    for (i = 0; i < size; i++) {        gdb_read_byte(s, buf[i]);    }}static void gdb_chr_event(void *opaque, int event){    switch (event) {    case CHR_EVENT_RESET:        vm_stop(EXCP_INTERRUPT);        gdb_syscall_state = opaque;        break;    default:        break;    }}int gdbserver_start(CharDriverState *chr){    GDBState *s;    if (!chr)        return -1;    s = qemu_mallocz(sizeof(GDBState));    if (!s) {        return -1;    }    s->env = first_cpu; /* XXX: allow to change CPU */    s->chr = chr;    qemu_chr_add_handlers(chr, gdb_chr_can_recieve, gdb_chr_recieve,                          gdb_chr_event, s);    qemu_add_vm_stop_handler(gdb_vm_stopped, s);    return 0;}int gdbserver_start_port(int port){    CharDriverState *chr;    char gdbstub_port_name[128];    snprintf(gdbstub_port_name, sizeof(gdbstub_port_name),             "tcp::%d,nowait,nodelay,server", port);    chr = qemu_chr_open(gdbstub_port_name);    if (!chr)         return -EIO;    return gdbserver_start(chr);}#endif

⌨️ 快捷键说明

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