Browse Source

Enable gdbserver to launch program on startup attach and stop immediately
- also fix gdbserver when it program runs to completion

Signed-off-by: Graham MacDonald <grahamamacdonald@gmail.com>

Graham MacDonald 4 years ago
parent
commit
7304b3b94f
2 changed files with 68 additions and 19 deletions
  1. 67 18
      sys/src/cmd/gdbserver/gdbserver.c
  2. 1 1
      sys/src/libmach/executable.c

+ 67 - 18
sys/src/cmd/gdbserver/gdbserver.c

@@ -240,6 +240,7 @@ getstatus(int pid)
 		return nil;
 	}
 
+	syslog(0, "gdbserver", "pid %d status %s", pid, argv[2]);
 	return argv[2];
 }
 
@@ -329,7 +330,8 @@ get_packet(char *buffer)
 		if (ch == '#') {
 			xmitcsum = hex_to_bin(gdbstub_read_wait()) << 4;
 			xmitcsum += hex_to_bin(gdbstub_read_wait());
-if (checksum != xmitcsum) syslog(0, "gdbserver", "BAD CSUM Computed 0x%x want 0x%x", xmitcsum, checksum);
+		if (checksum != xmitcsum)
+			syslog(0, "gdbserver", "BAD CSUM Computed 0x%x want 0x%x", xmitcsum, checksum);
 			if (checksum != xmitcsum)
 				/* failed checksum */
 				write_char('-');
@@ -947,8 +949,8 @@ gdb_cmd_exception_pass(GdbState *ks)
 
 	} else {
 		gdbstub_msg_write("KGDB only knows signal 9 (pass)"
-						  " and 15 (pass and disconnect)\n"
-						  "Executing a continue without signal passing\n", 0);
+			" and 15 (pass and disconnect)\n"
+			"Executing a continue without signal passing\n", 0);
 		remcom_in_buffer[0] = 'c';
 	}
 
@@ -971,12 +973,20 @@ gdb_cmd_continue(GdbState *ks)
 	// Block for the process to stop or receive a note
 	sendctl(ks->threadid, "startstop");
 
-	// Remove the breakpoint note so the process
-	// doesn't suicide
+	// Remove the breakpoint note so the process doesn't suicide
 	remove_note();
 
-	// Send code indicating we've hit a breakpoint
-	strcpy((char *)remcom_out_buffer, "S05");
+	// Check whether it's ended or stopped
+	const char *status = getstatus(ks->threadid);
+	if (status == nil) {
+		// Let's assume for now this means the program has ended
+		// Send code indicating process ended normally
+		strcpy((char *)remcom_out_buffer, "W00");
+	} else {
+		// Let's assume for now this means the program has hit a breakpoint
+		// Send code indicating we've hit a breakpoint
+		strcpy((char *)remcom_out_buffer, "S05");
+	}
 }
 
 static void
@@ -1263,15 +1273,15 @@ wmem(uint64_t dest, int pid, void *addr, int size)
 static void
 usage(void)
 {
-	fprint(2, "usage: gdbserver [-p pid] [-l port] [-d]\n");
+	fprint(2, "usage: gdbserver [-p pid] [-l port] [-d] [exe] [args...]\n");
 	exits("usage");
 }
 
 void
 main(int argc, char **argv)
 {
-	char* pid = nil;
-	char* port = "1666";
+	char *pid = nil;
+	char *port = "1666";
 
 	ARGBEGIN {
 	case 'l':
@@ -1293,20 +1303,59 @@ main(int argc, char **argv)
 		fprint(2, " badflag('%c')", ARGC());
 	} ARGEND
 
-	if (pid == nil) {
+	if (pid == nil && argc == 0) {
 		usage();
 	}
 
-	ks.threadid = atoi(pid);
-	// Set to 0 if we eventually support creating a new process
-	attached_to_existing_pid = 1;
+	if (argc > 0) {
+		// Load process 'exe', then attach
+		ks.threadid = fork();
+
+		switch (ks.threadid) {
+		case -1:
+			syslog(0, "gdbserver", "fork failed");
+			werrstr("fork failed %r");
+			return;
+		case 0:
+		{
+			// In child process
+
+			// hang the new proc before exec
+			sendctl(getpid(), "hang");
+
+			close(0);
+			close(1);
+			close(2);
+
+			open("/dev/cons", OREAD);
+			open("/dev/cons", OWRITE);
+			open("/dev/cons", OWRITE);
+			exec(argv[0], argv);
+			werrstr("exec failed %r");
+			return;
+		}
+		default:
+			// Fork succeeded, back in gdbserver
 
-	print("Stopping process %d...\n", ks.threadid);
-	sendctl(ks.threadid, "stop");
-	print("Process stopped.  Waiting for remote gdb connection...\n");
+			// Set to 0 if we eventually support creating a new
+			// process - really?
+			attached_to_existing_pid = 0;
+			print("Process %d launched.  Waiting for remote gdb connection...\n", ks.threadid);
+			break;
+		}
+	} else if (pid != nil) {
+		// Attach to running process
+		ks.threadid = atoi(pid);
+		// Set to 0 if we eventually support creating a new process
+		attached_to_existing_pid = 1;
+
+		print("Stopping process %d...\n", ks.threadid);
+		sendctl(ks.threadid, "stop");
+		print("Process stopped.  Waiting for remote gdb connection...\n");
+	}
 
+	// Used in both attach and launch exe cases
 	gdb_init_regs();
 	attach_to_process(ks.threadid);
-
 	gdb_serial_stub(&ks, atoi(port));
 }

+ 1 - 1
sys/src/libmach/executable.c

@@ -310,7 +310,7 @@ elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
 		int idbg_line = -1;
 		for (int i = 0; i < ep->shnum; i++) {
 			const char *secname = &shstrtab[sh[i].name];
-			print("secname[%d] = %s\n", i, secname);
+			//print("secname[%d] = %s\n", i, secname);
 			if (sh[i].type == SHT_PROGBITS
 				&& !strcmp(".debug_line", secname)
 				&& idbg_line == -1) {