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

📄 gdbstub.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    ptr += 4;    env->LO = tswapl(*(uint32_t *)ptr);    ptr += 4;    env->HI = tswapl(*(uint32_t *)ptr);    ptr += 4;    env->CP0_BadVAddr = tswapl(*(uint32_t *)ptr);    ptr += 4;    env->CP0_Cause = tswapl(*(uint32_t *)ptr);    ptr += 4;    env->PC = tswapl(*(uint32_t *)ptr);    ptr += 4;}#elif defined (TARGET_SH4)static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf){  uint32_t *ptr = (uint32_t *)mem_buf;  int i;#define SAVE(x) *ptr++=tswapl(x)  for (i = 0; i < 16; i++) SAVE(env->gregs[i]);  SAVE (env->pc);  SAVE (env->pr);  SAVE (env->gbr);  SAVE (env->vbr);  SAVE (env->mach);  SAVE (env->macl);  SAVE (env->sr);  SAVE (0); /* TICKS */  SAVE (0); /* STALLS */  SAVE (0); /* CYCLES */  SAVE (0); /* INSTS */  SAVE (0); /* PLR */  return ((uint8_t *)ptr - mem_buf);}static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size){  uint32_t *ptr = (uint32_t *)mem_buf;  int i;#define LOAD(x) (x)=*ptr++;  for (i = 0; i < 16; i++) LOAD(env->gregs[i]);  LOAD (env->pc);  LOAD (env->pr);  LOAD (env->gbr);  LOAD (env->vbr);  LOAD (env->mach);  LOAD (env->macl);  LOAD (env->sr);}#elsestatic int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf){    return 0;}static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size){}#endifstatic int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf){    const char *p;    int ch, reg_size, type;    char buf[4096];    uint8_t mem_buf[2000];    uint32_t *registers;    uint32_t addr, len;    #ifdef DEBUG_GDB    printf("command='%s'\n", line_buf);#endif    p = line_buf;    ch = *p++;    switch(ch) {    case '?':        /* TODO: Make this return the correct value for user-mode.  */        snprintf(buf, sizeof(buf), "S%02x", SIGTRAP);        put_packet(s, buf);        break;    case 'c':        if (*p != '\0') {            addr = strtoul(p, (char **)&p, 16);#if defined(TARGET_I386)            env->eip = addr;#elif defined (TARGET_PPC)            env->nip = addr;#elif defined (TARGET_SPARC)            env->pc = addr;            env->npc = addr + 4;#elif defined (TARGET_ARM)            env->regs[15] = addr;#elif defined (TARGET_SH4)	    env->pc = addr;#endif        }#ifdef CONFIG_USER_ONLY        s->running_state = 1;#else        vm_start();#endif	return RS_IDLE;    case 's':        if (*p != '\0') {            addr = strtoul(p, (char **)&p, 16);#if defined(TARGET_I386)            env->eip = addr;#elif defined (TARGET_PPC)            env->nip = addr;#elif defined (TARGET_SPARC)            env->pc = addr;            env->npc = addr + 4;#elif defined (TARGET_ARM)            env->regs[15] = addr;#elif defined (TARGET_SH4)	    env->pc = addr;#endif        }        cpu_single_step(env, 1);#ifdef CONFIG_USER_ONLY        s->running_state = 1;#else        vm_start();#endif	return RS_IDLE;    case 'g':        reg_size = cpu_gdb_read_registers(env, mem_buf);        memtohex(buf, mem_buf, reg_size);        put_packet(s, buf);        break;    case 'G':        registers = (void *)mem_buf;        len = strlen(p) / 2;        hextomem((uint8_t *)registers, p, len);        cpu_gdb_write_registers(env, mem_buf, len);        put_packet(s, "OK");        break;    case 'm':        addr = strtoul(p, (char **)&p, 16);        if (*p == ',')            p++;        len = strtoul(p, NULL, 16);        if (cpu_memory_rw_debug(env, addr, mem_buf, len, 0) != 0) {            put_packet (s, "E14");        } else {            memtohex(buf, mem_buf, len);            put_packet(s, buf);        }        break;    case 'M':        addr = strtoul(p, (char **)&p, 16);        if (*p == ',')            p++;        len = strtoul(p, (char **)&p, 16);        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 = strtoul(p, (char **)&p, 16);        if (*p == ',')            p++;        len = strtoul(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 = strtoul(p, (char **)&p, 16);        if (*p == ',')            p++;        len = strtoul(p, (char **)&p, 16);        if (type == 0 || type == 1) {            cpu_breakpoint_remove(env, addr);            put_packet(s, "OK");        } else {            goto breakpoint_error;        }        break;    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;    /* 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);}#endifstatic void gdb_read_byte(GDBState *s, int ch){    CPUState *env = s->env;    int i, csum;    char reply[1];#ifndef CONFIG_USER_ONLY    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;        }    }}#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);}#elsestatic void gdb_read(void *opaque){    GDBState *s = opaque;    int i, size;    uint8_t buf[4096];    size = read(s->fd, buf, sizeof(buf));    if (size < 0)        return;    if (size == 0) {        /* end of connection */        qemu_del_vm_stop_handler(gdb_vm_stopped, s);        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);        qemu_free(s);        vm_start();    } else {        for(i = 0; i < size; i++)            gdb_read_byte(s, buf[i]);    }}#endifstatic 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, &val, sizeof(val));    #ifdef CONFIG_USER_ONLY    s = &gdbserver_state;    memset (s, 0, sizeof (GDBState));#else    s = qemu_mallocz(sizeof(GDBState));    if (!s) {        close(fd);        return;    }#endif    s->env = first_cpu; /* XXX: allow to change CPU */    s->fd = fd;    fcntl(fd, F_SETFL, O_NONBLOCK);#ifndef CONFIG_USER_ONLY    /* stop the VM */    vm_stop(EXCP_INTERRUPT);    /* start handling I/O */    qemu_set_fd_handler(s->fd, gdb_read, NULL, s);    /* when the VM is stopped, the following callback is called */    qemu_add_vm_stop_handler(gdb_vm_stopped, s);#endif}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, &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;    }#ifndef CONFIG_USER_ONLY    fcntl(fd, F_SETFL, O_NONBLOCK);#endif    return fd;}int gdbserver_start(int port){    gdbserver_fd = gdbserver_open(port);    if (gdbserver_fd < 0)        return -1;    /* accept connections */#ifdef CONFIG_USER_ONLY    gdb_accept (NULL);#else    qemu_set_fd_handler(gdbserver_fd, gdb_accept, NULL, NULL);#endif    return 0;}

⌨️ 快捷键说明

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