diff options
Diffstat (limited to 'gdb/gdbserver/server.c')
-rw-r--r-- | gdb/gdbserver/server.c | 195 |
1 files changed, 187 insertions, 8 deletions
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 81fde5b7f73..93e3ea431bb 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -1,5 +1,5 @@ /* Main code for remote server for GDB. - Copyright 1989, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2002 + Copyright 1989, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GDB. @@ -70,6 +70,8 @@ attach_inferior (int pid, char *statusptr, unsigned char *sigptr) if (myattach (pid) != 0) return -1; + fprintf (stderr, "Attached; pid = %d\n", pid); + /* FIXME - It may be that we should get the SIGNAL_PID from the attach function, so that it can be the main thread instead of whichever we were told to attach to. */ @@ -104,7 +106,7 @@ handle_query (char *own_buf) thread_ptr = thread_ptr->next; return; } - + if (strcmp ("qsThreadInfo", own_buf) == 0) { if (thread_ptr != NULL) @@ -119,10 +121,180 @@ handle_query (char *own_buf) return; } } - + + if (the_target->read_auxv != NULL + && strncmp ("qPart:auxv:read::", own_buf, 17) == 0) + { + char data[(PBUFSIZ - 1) / 2]; + CORE_ADDR ofs; + unsigned int len; + int n; + decode_m_packet (&own_buf[17], &ofs, &len); /* "OFS,LEN" */ + if (len > sizeof data) + len = sizeof data; + n = (*the_target->read_auxv) (ofs, data, len); + if (n == 0) + write_ok (own_buf); + else if (n < 0) + write_enn (own_buf); + else + convert_int_to_ascii (data, own_buf, n); + return; + } + + /* Otherwise we didn't know what packet it was. Say we didn't + understand it. */ + own_buf[0] = 0; +} + +/* Parse vCont packets. */ +void +handle_v_cont (char *own_buf, char *status, unsigned char *signal) +{ + char *p, *q; + int n = 0, i = 0; + struct thread_resume *resume_info, default_action; + + /* Count the number of semicolons in the packet. There should be one + for every action. */ + p = &own_buf[5]; + while (p) + { + n++; + p++; + p = strchr (p, ';'); + } + /* Allocate room for one extra action, for the default remain-stopped + behavior; if no default action is in the list, we'll need the extra + slot. */ + resume_info = malloc ((n + 1) * sizeof (resume_info[0])); + + default_action.thread = -1; + default_action.leave_stopped = 1; + default_action.step = 0; + default_action.sig = 0; + + p = &own_buf[5]; + i = 0; + while (*p) + { + p++; + + resume_info[i].leave_stopped = 0; + + if (p[0] == 's' || p[0] == 'S') + resume_info[i].step = 1; + else if (p[0] == 'c' || p[0] == 'C') + resume_info[i].step = 0; + else + goto err; + + if (p[0] == 'S' || p[0] == 'C') + { + int sig; + sig = strtol (p + 1, &q, 16); + if (p == q) + goto err; + p = q; + + if (!target_signal_to_host_p (sig)) + goto err; + resume_info[i].sig = target_signal_to_host (sig); + } + else + { + resume_info[i].sig = 0; + p = p + 1; + } + + if (p[0] == 0) + { + resume_info[i].thread = -1; + default_action = resume_info[i]; + + /* Note: we don't increment i here, we'll overwrite this entry + the next time through. */ + } + else if (p[0] == ':') + { + resume_info[i].thread = strtol (p + 1, &q, 16); + if (p == q) + goto err; + p = q; + if (p[0] != ';' && p[0] != 0) + goto err; + + i++; + } + } + + resume_info[i] = default_action; + + /* Still used in occasional places in the backend. */ + if (n == 1 && resume_info[0].thread != -1) + cont_thread = resume_info[0].thread; + else + cont_thread = -1; + set_desired_inferior (0); + + (*the_target->resume) (resume_info); + + free (resume_info); + + *signal = mywait (status, 1); + prepare_resume_reply (own_buf, *status, *signal); + return; + +err: + /* No other way to report an error... */ + strcpy (own_buf, ""); + free (resume_info); + return; +} + +/* Handle all of the extended 'v' packets. */ +void +handle_v_requests (char *own_buf, char *status, unsigned char *signal) +{ + if (strncmp (own_buf, "vCont;", 6) == 0) + { + handle_v_cont (own_buf, status, signal); + return; + } + + if (strncmp (own_buf, "vCont?", 6) == 0) + { + strcpy (own_buf, "vCont;c;C;s;S"); + return; + } + /* Otherwise we didn't know what packet it was. Say we didn't understand it. */ own_buf[0] = 0; + return; +} + +void +myresume (int step, int sig) +{ + struct thread_resume resume_info[2]; + int n = 0; + + if (step || sig || cont_thread > 0) + { + resume_info[0].thread + = ((struct inferior_list_entry *) current_inferior)->id; + resume_info[0].step = step; + resume_info[0].sig = sig; + resume_info[0].leave_stopped = 0; + n++; + } + resume_info[n].thread = -1; + resume_info[n].step = 0; + resume_info[n].sig = 0; + resume_info[n].leave_stopped = (cont_thread > 0); + + (*the_target->resume) (resume_info); } static int attached; @@ -222,7 +394,7 @@ main (int argc, char *argv[]) detach_inferior (); write_ok (own_buf); putpkt (own_buf); - remote_close (); + remote_close (); /* If we are attached, then we can exit. Otherwise, we need to hang around doing nothing, until the child is gone. */ @@ -290,8 +462,10 @@ main (int argc, char *argv[]) break; case 'm': decode_m_packet (&own_buf[1], &mem_addr, &len); - read_inferior_memory (mem_addr, mem_buf, len); - convert_int_to_ascii (mem_buf, own_buf, len); + if (read_inferior_memory (mem_addr, mem_buf, len) == 0) + convert_int_to_ascii (mem_buf, own_buf, len); + else + write_enn (own_buf); break; case 'M': decode_M_packet (&own_buf[1], &mem_addr, &len, mem_buf); @@ -383,6 +557,10 @@ main (int argc, char *argv[]) own_buf[0] = '\0'; break; } + case 'v': + /* Extended (long) request. */ + handle_v_requests (own_buf, &status, &signal); + break; default: /* It is a request we don't understand. Respond with an empty packet so that gdb knows that we don't support this @@ -395,9 +573,10 @@ main (int argc, char *argv[]) if (status == 'W') fprintf (stderr, - "\nChild exited with status %d\n", sig); + "\nChild exited with status %d\n", signal); if (status == 'X') - fprintf (stderr, "\nChild terminated with signal = 0x%x\n", sig); + fprintf (stderr, "\nChild terminated with signal = 0x%x\n", + signal); if (status == 'W' || status == 'X') { if (extended_protocol) |