The distinction between the two is artificial. Following patches will rearrange the functions involved to make it easier for dumping of the trace file.
Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- Makefile | 2 +- risu.h | 28 +--------- reginfo.c | 151 ------------------------------------------------------ risu.c | 129 ++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 126 insertions(+), 184 deletions(-) delete mode 100644 reginfo.c diff --git a/Makefile b/Makefile index 6ab014a..ad7f879 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ CFLAGS ?= -g ALL_CFLAGS = -Wall -D_GNU_SOURCE -DARCH=$(ARCH) -U$(ARCH) $(BUILD_INC) $(CFLAGS) $(EXTRA_CFLAGS) PROG=risu -SRCS=risu.c comms.c reginfo.c risu_$(ARCH).c risu_reginfo_$(ARCH).c +SRCS=risu.c comms.c risu_$(ARCH).c risu_reginfo_$(ARCH).c HDRS=risu.h risu_reginfo_$(ARCH).h BINS=test_$(ARCH).bin diff --git a/risu.h b/risu.h index 77d6128..dd9fda5 100644 --- a/risu.h +++ b/risu.h @@ -35,7 +35,6 @@ void process_arch_opt(int opt, const char *arg); #include REGINFO_HEADER(ARCH) extern uintptr_t image_start_address; -extern void *memblock; /* Ops code under test can request from risu: */ typedef enum { @@ -83,34 +82,9 @@ void send_response_byte(int sock, int resp); /* Functions operating on reginfo */ -/* Function prototypes for read/write helper functions. */ -RisuResult write_buffer(void *ptr, size_t bytes); -RisuResult read_buffer(void *ptr, size_t bytes); -void respond(RisuResult response); - -/* - * Send the register information from the struct ucontext down the socket. - * NB: called from a signal handler. - */ -RisuResult send_register_info(void *uc); - -/* - * Read register info from the socket and compare it with that from the - * ucontext. - * NB: called from a signal handler. - */ -RisuResult recv_and_compare_register_info(void *uc); - -/* - * Print a useful report on the status of the last reg comparison - * done in recv_and_compare_register_info(). - */ -void report_mismatch_reg(void); - /* Interface provided by CPU-specific code: */ -/* Move the PC past this faulting insn by adjusting ucontext - */ +/* Move the PC past this faulting insn by adjusting ucontext. */ void advance_pc(void *uc); /* Set the parameter register in a ucontext_t to the specified value. diff --git a/reginfo.c b/reginfo.c deleted file mode 100644 index a007f16..0000000 --- a/reginfo.c +++ /dev/null @@ -1,151 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2017 Linaro Limited - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Peter Maydell (Linaro) - initial implementation - *****************************************************************************/ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include "risu.h" - -static struct reginfo master_ri, apprentice_ri; -static uint8_t master_memblock[MEMBLOCKLEN]; - -RisuResult send_register_info(void *uc) -{ - struct reginfo ri; - trace_header_t header; - RisuResult res; - RisuOp op; - - reginfo_init(&ri, uc); - op = get_risuop(&ri); - - /* Write a header with PC/op to keep in sync */ - header.pc = get_pc(&ri); - header.risu_op = op; - res = write_buffer(&header, sizeof(header)); - if (res != RES_OK) { - return res; - } - - switch (op) { - case OP_COMPARE: - case OP_TESTEND: - case OP_SIGILL: - /* - * Do a simple register compare on (a) explicit request - * (b) end of test (c) a non-risuop UNDEF - */ - res = write_buffer(&ri, reginfo_size()); - /* For OP_TEST_END, force exit. */ - if (res == RES_OK && op == OP_TESTEND) { - res = RES_END; - } - break; - case OP_SETMEMBLOCK: - memblock = (void *)(uintptr_t)get_reginfo_paramreg(&ri); - break; - case OP_GETMEMBLOCK: - set_ucontext_paramreg(uc, - get_reginfo_paramreg(&ri) + (uintptr_t)memblock); - break; - case OP_COMPAREMEM: - return write_buffer(memblock, MEMBLOCKLEN); - default: - abort(); - } - return res; -} - -/* Read register info from the socket and compare it with that from the - * ucontext. Return 0 for match, 1 for end-of-test, 2 for mismatch. - * NB: called from a signal handler. - * - * We don't have any kind of identifying info in the incoming data - * that says whether it is register or memory data, so if the two - * sides get out of sync then we will fail obscurely. - */ -RisuResult recv_and_compare_register_info(void *uc) -{ - RisuResult res; - trace_header_t header; - RisuOp op; - - reginfo_init(&apprentice_ri, uc); - op = get_risuop(&apprentice_ri); - - res = read_buffer(&header, sizeof(header)); - if (res != RES_OK) { - return res; - } - - if (header.risu_op != op) { - /* We are out of sync. Tell master to exit. */ - respond(RES_END); - return RES_BAD_IO; - } - - /* send OK for the header */ - respond(RES_OK); - - switch (op) { - case OP_COMPARE: - case OP_TESTEND: - case OP_SIGILL: - /* Do a simple register compare on (a) explicit request - * (b) end of test (c) a non-risuop UNDEF - */ - res = read_buffer(&master_ri, reginfo_size()); - if (res != RES_OK) { - /* fail */ - } else if (!reginfo_is_eq(&master_ri, &apprentice_ri)) { - /* register mismatch */ - res = RES_MISMATCH_REG; - } else if (op == OP_TESTEND) { - res = RES_END; - } - respond(res == RES_OK ? RES_OK : RES_END); - break; - case OP_SETMEMBLOCK: - memblock = (void *)(uintptr_t)get_reginfo_paramreg(&apprentice_ri); - break; - case OP_GETMEMBLOCK: - set_ucontext_paramreg(uc, get_reginfo_paramreg(&apprentice_ri) + - (uintptr_t)memblock); - break; - case OP_COMPAREMEM: - res = read_buffer(master_memblock, MEMBLOCKLEN); - if (res != RES_OK) { - /* fail */ - } else if (memcmp(memblock, master_memblock, MEMBLOCKLEN) != 0) { - /* memory mismatch */ - res = RES_MISMATCH_MEM; - } - respond(res == RES_OK ? RES_OK : RES_END); - break; - default: - abort(); - } - - return res; -} - -/* - * Print a useful report on the status of the last reg comparison - * done in recv_and_compare_register_info(). - */ -void report_mismatch_reg(void) -{ - fprintf(stderr, "master reginfo:\n"); - reginfo_dump(&master_ri, stderr); - fprintf(stderr, "apprentice reginfo:\n"); - reginfo_dump(&apprentice_ri, stderr); - reginfo_dump_mismatch(&master_ri, &apprentice_ri, stderr); -} diff --git a/risu.c b/risu.c index d6c2deb..a0e20d5 100644 --- a/risu.c +++ b/risu.c @@ -28,7 +28,10 @@ #include "config.h" #include "risu.h" -void *memblock; +static void *memblock; +static struct reginfo master_ri, apprentice_ri; +static uint8_t master_memblock[MEMBLOCKLEN]; + static int comm_fd; static bool trace; @@ -48,7 +51,7 @@ static sigjmp_buf jmpbuf; /* I/O functions */ -RisuResult read_buffer(void *ptr, size_t bytes) +static RisuResult read_buffer(void *ptr, size_t bytes) { size_t res; @@ -69,7 +72,7 @@ RisuResult read_buffer(void *ptr, size_t bytes) return res == bytes ? RES_OK : RES_BAD_IO; } -RisuResult write_buffer(void *ptr, size_t bytes) +static RisuResult write_buffer(void *ptr, size_t bytes) { size_t res; @@ -90,13 +93,60 @@ RisuResult write_buffer(void *ptr, size_t bytes) return res == bytes ? RES_OK : RES_BAD_IO; } -void respond(RisuResult r) +static void respond(RisuResult r) { if (!trace) { send_response_byte(comm_fd, r); } } +static RisuResult send_register_info(void *uc) +{ + struct reginfo ri; + trace_header_t header; + RisuResult res; + RisuOp op; + + reginfo_init(&ri, uc); + op = get_risuop(&ri); + + /* Write a header with PC/op to keep in sync */ + header.pc = get_pc(&ri); + header.risu_op = op; + res = write_buffer(&header, sizeof(header)); + if (res != RES_OK) { + return res; + } + + switch (op) { + case OP_COMPARE: + case OP_TESTEND: + case OP_SIGILL: + /* + * Do a simple register compare on (a) explicit request + * (b) end of test (c) a non-risuop UNDEF + */ + res = write_buffer(&ri, reginfo_size()); + /* For OP_TEST_END, force exit. */ + if (res == RES_OK && op == OP_TESTEND) { + res = RES_END; + } + break; + case OP_SETMEMBLOCK: + memblock = (void *)(uintptr_t)get_reginfo_paramreg(&ri); + break; + case OP_GETMEMBLOCK: + set_ucontext_paramreg(uc, + get_reginfo_paramreg(&ri) + (uintptr_t)memblock); + break; + case OP_COMPAREMEM: + return write_buffer(memblock, MEMBLOCKLEN); + default: + abort(); + } + return res; +} + static void master_sigill(int sig, siginfo_t *si, void *uc) { RisuResult r; @@ -110,6 +160,71 @@ static void master_sigill(int sig, siginfo_t *si, void *uc) } } +static RisuResult recv_and_compare_register_info(void *uc) +{ + RisuResult res; + trace_header_t header; + RisuOp op; + + reginfo_init(&apprentice_ri, uc); + op = get_risuop(&apprentice_ri); + + res = read_buffer(&header, sizeof(header)); + if (res != RES_OK) { + return res; + } + + if (header.risu_op != op) { + /* We are out of sync. Tell master to exit. */ + respond(RES_END); + return RES_BAD_IO; + } + + /* send OK for the header */ + respond(RES_OK); + + switch (op) { + case OP_COMPARE: + case OP_TESTEND: + case OP_SIGILL: + /* Do a simple register compare on (a) explicit request + * (b) end of test (c) a non-risuop UNDEF + */ + res = read_buffer(&master_ri, reginfo_size()); + if (res != RES_OK) { + /* fail */ + } else if (!reginfo_is_eq(&master_ri, &apprentice_ri)) { + /* register mismatch */ + res = RES_MISMATCH_REG; + } else if (op == OP_TESTEND) { + res = RES_END; + } + respond(res == RES_OK ? RES_OK : RES_END); + break; + case OP_SETMEMBLOCK: + memblock = (void *)(uintptr_t)get_reginfo_paramreg(&apprentice_ri); + break; + case OP_GETMEMBLOCK: + set_ucontext_paramreg(uc, get_reginfo_paramreg(&apprentice_ri) + + (uintptr_t)memblock); + break; + case OP_COMPAREMEM: + res = read_buffer(master_memblock, MEMBLOCKLEN); + if (res != RES_OK) { + /* fail */ + } else if (memcmp(memblock, master_memblock, MEMBLOCKLEN) != 0) { + /* memory mismatch */ + res = RES_MISMATCH_MEM; + } + respond(res == RES_OK ? RES_OK : RES_END); + break; + default: + abort(); + } + + return res; +} + static void apprentice_sigill(int sig, siginfo_t *si, void *uc) { RisuResult r; @@ -226,7 +341,11 @@ static int apprentice(void) case RES_MISMATCH_REG: fprintf(stderr, "mismatch reg after %zd checkpoints\n", signal_count); - report_mismatch_reg(); + fprintf(stderr, "master reginfo:\n"); + reginfo_dump(&master_ri, stderr); + fprintf(stderr, "apprentice reginfo:\n"); + reginfo_dump(&apprentice_ri, stderr); + reginfo_dump_mismatch(&master_ri, &apprentice_ri, stderr); return EXIT_FAILURE; case RES_MISMATCH_MEM: -- 2.34.1