@@ -30,7 +30,9 @@
void *memblock;
-int apprentice_socket, master_socket;
+int apprentice_fd, master_fd;
+int trace;
+size_t signal_count;
sigjmp_buf jmpbuf;
@@ -41,24 +43,60 @@ int test_fp_exc;
int read_sock(void *ptr, size_t bytes)
{
- return recv_data_pkt(master_socket, ptr, bytes);
+ return recv_data_pkt(master_fd, ptr, bytes);
+}
+
+int write_trace(void *ptr, size_t bytes)
+{
+ size_t res = write(master_fd, ptr, bytes);
+ return (res == bytes) ? 0 : 1;
}
void respond_sock(int r)
{
- send_response_byte(master_socket, r);
+ send_response_byte(master_fd, r);
}
/* Apprentice function */
int write_sock(void *ptr, size_t bytes)
{
- return send_data_pkt(apprentice_socket, ptr, bytes);
+ return send_data_pkt(apprentice_fd, ptr, bytes);
+}
+
+int read_trace(void *ptr, size_t bytes)
+{
+ size_t res = read(apprentice_fd, ptr, bytes);
+ return (res == bytes) ? 0 : 1;
+}
+
+void respond_trace(int r)
+{
+ switch (r) {
+ case 0: /* test ok */
+ case 1: /* end of test */
+ break;
+ default:
+ /* mismatch - if tracing we need to report, otherwise barf */
+ if (!trace) {
+ abort();
+ }
+ break;
+ }
}
void master_sigill(int sig, siginfo_t *si, void *uc)
{
- switch (recv_and_compare_register_info(read_sock, respond_sock, uc)) {
+ int r;
+ signal_count++;
+
+ if (trace) {
+ r = send_register_info(write_trace, uc);
+ } else {
+ r = recv_and_compare_register_info(read_sock, respond_sock, uc);
+ }
+
+ switch (r) {
case 0:
/* match OK */
advance_pc(uc);
@@ -71,7 +109,16 @@ void master_sigill(int sig, siginfo_t *si, void *uc)
void apprentice_sigill(int sig, siginfo_t *si, void *uc)
{
- switch (send_register_info(write_sock, uc)) {
+ int r;
+ signal_count++;
+
+ if (trace) {
+ r = recv_and_compare_register_info(read_trace, respond_trace, uc);
+ } else {
+ r = send_register_info(write_sock, uc);
+ }
+
+ switch (r) {
case 0:
/* match OK */
advance_pc(uc);
@@ -81,6 +128,9 @@ void apprentice_sigill(int sig, siginfo_t *si, void *uc)
exit(0);
default:
/* mismatch */
+ if (trace) {
+ siglongjmp(jmpbuf, 1);
+ }
exit(1);
}
}
@@ -136,12 +186,17 @@ void load_image(const char *imgfile)
image_start_address = (uintptr_t) addr;
}
-int master(int sock)
+int master(void)
{
if (sigsetjmp(jmpbuf, 1)) {
- return report_match_status();
+ close(master_fd);
+ if (trace) {
+ fprintf(stderr, "trace complete after %zd checkpoints\n", signal_count);
+ return 0;
+ } else {
+ return report_match_status();
+ }
}
- master_socket = sock;
set_sigill_handler(&master_sigill);
fprintf(stderr, "starting master image at 0x%"PRIxPTR"\n",
image_start_address);
@@ -151,9 +206,13 @@ int master(int sock)
exit(1);
}
-int apprentice(int sock)
+int apprentice(void)
{
- apprentice_socket = sock;
+ if (sigsetjmp(jmpbuf, 1)) {
+ close(apprentice_fd);
+ fprintf(stderr, "finished early after %zd checkpoints\n", signal_count);
+ return report_match_status();
+ }
set_sigill_handler(&apprentice_sigill);
fprintf(stderr, "starting apprentice image at 0x%"PRIxPTR"\n",
image_start_address);
@@ -175,6 +234,7 @@ void usage(void)
fprintf(stderr, "between master and apprentice risu processes.\n\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, " --master Be the master (server)\n");
+ fprintf(stderr, " -t, --trace=FILE Record/playback trace file\n");
fprintf(stderr,
" -h, --host=HOST Specify master host machine (apprentice only)"
"\n");
@@ -189,7 +249,7 @@ int main(int argc, char **argv)
uint16_t port = 9191;
char *hostname = "localhost";
char *imgfile;
- int sock;
+ char *trace_fn = NULL;
/* TODO clean this up later */
@@ -203,7 +263,7 @@ int main(int argc, char **argv)
{0, 0, 0, 0}
};
int optidx = 0;
- int c = getopt_long(argc, argv, "h:p:", longopts, &optidx);
+ int c = getopt_long(argc, argv, "h:p:t:", longopts, &optidx);
if (c == -1) {
break;
}
@@ -214,6 +274,12 @@ int main(int argc, char **argv)
/* flag set by getopt_long, do nothing */
break;
}
+ case 't':
+ {
+ trace_fn = optarg;
+ trace = 1;
+ break;
+ }
case 'h':
{
hostname = optarg;
@@ -245,12 +311,20 @@ int main(int argc, char **argv)
load_image(imgfile);
if (ismaster) {
- fprintf(stderr, "master port %d\n", port);
- sock = master_connect(port);
- return master(sock);
+ if (trace) {
+ master_fd = open(trace_fn, O_WRONLY|O_CREAT, S_IRWXU);
+ } else {
+ fprintf(stderr, "master port %d\n", port);
+ master_fd = master_connect(port);
+ }
+ return master();
} else {
- fprintf(stderr, "apprentice host %s port %d\n", hostname, port);
- sock = apprentice_connect(hostname, port);
- return apprentice(sock);
+ if (trace) {
+ apprentice_fd = open(trace_fn, O_RDONLY);
+ } else {
+ fprintf(stderr, "apprentice host %s port %d\n", hostname, port);
+ apprentice_fd = apprentice_connect(hostname, port);
+ }
+ return apprentice();
}
}