From 635400b2c122ce6ba3b2c61e026fb6c592684804 Mon Sep 17 00:00:00 2001 From: Anton Lindqvist Date: Tue, 19 Nov 2024 05:50:42 +0000 Subject: Add amd64 ddb regress suite allowing the disassembler to be tested from userspace. --- regress/sys/arch/amd64/ddb/Makefile | 26 ++++++++++ regress/sys/arch/amd64/ddb/disasm.c | 68 +++++++++++++++++++++++++++ regress/sys/arch/amd64/ddb/disasm.h | 22 +++++++++ regress/sys/arch/amd64/ddb/stubs.c | 94 +++++++++++++++++++++++++++++++++++++ 4 files changed, 210 insertions(+) create mode 100644 regress/sys/arch/amd64/ddb/Makefile create mode 100644 regress/sys/arch/amd64/ddb/disasm.c create mode 100644 regress/sys/arch/amd64/ddb/disasm.h create mode 100644 regress/sys/arch/amd64/ddb/stubs.c diff --git a/regress/sys/arch/amd64/ddb/Makefile b/regress/sys/arch/amd64/ddb/Makefile new file mode 100644 index 00000000000..483d24693fc --- /dev/null +++ b/regress/sys/arch/amd64/ddb/Makefile @@ -0,0 +1,26 @@ +# $OpenBSD: Makefile,v 1.1 2024/11/19 05:50:41 anton Exp $ + +.if "${MACHINE_ARCH}" == "amd64" + +SRCS+= disasm.c +SRCS+= stubs.c +SRCS+= db_disasm.c +SRCS+= db_output.c +SRCS+= db_sym.c +PROG= disasm + +CPPFLAGS+= -D_KERNEL +CPPFLAGS+= -I${.CURDIR}/../../../../../sys +WARNINGS= yes + +.PATH: ${.CURDIR}/../../../../../sys/arch/amd64/amd64 +.PATH: ${.CURDIR}/../../../../../sys/ddb + +.else + +regress: + @echo SKIPPED + +.endif + +.include diff --git a/regress/sys/arch/amd64/ddb/disasm.c b/regress/sys/arch/amd64/ddb/disasm.c new file mode 100644 index 00000000000..33d401191a4 --- /dev/null +++ b/regress/sys/arch/amd64/ddb/disasm.c @@ -0,0 +1,68 @@ +/* $OpenBSD: disasm.c,v 1.1 2024/11/19 05:50:41 anton Exp $ */ + +#include /* size_t */ +#include +#include + +#include "disasm.h" + +#define test(instr, exp) \ + test_impl((instr), sizeof(instr) - 1, \ + (exp), sizeof(exp) - 1, \ + __func__, __LINE__) + +struct db_disasm_context *ctx = NULL; + +static int +test_impl(const uint8_t *instr, size_t ninstr, const char *exp, size_t explen, + const char *fun, int lno) +{ + const char *act; + size_t actlen; + + static struct db_disasm_context c; + memset(&c, 0, sizeof(c)); + ctx = &c; + + ctx->raw.buf = instr; + ctx->raw.len = ninstr; + ctx->act.len = 0; + ctx->act.siz = sizeof(ctx->act.buf); + + db_disasm(0, 0); + + act = ctx->act.buf; + actlen = ctx->act.len; + /* Remove trailing whitespace from instructions w/o operands. */ + while (actlen > 0 && act[actlen - 1] == ' ') + actlen--; + + if (explen != actlen || strncmp(exp, act, actlen) != 0) { + fprintf(stderr, "%s:%d:\n", fun, lno); + fprintf(stderr, "exp: \"%.*s\"\n", (int)explen, exp); + fprintf(stderr, "act: \"%.*s\"\n", (int)actlen, act); + return 1; + } + + if (ctx->raw.len > 0) { + fprintf(stderr, "%s:%d: %zu byte(s) not consumed\n", fun, lno, + ctx->raw.len); + return 1; + } + + return 0; +} + +int +main(void) +{ + int error = 0; + + error |= test("\x90", "nop"); + error |= test("\x00", "addb %al,0(%rax)"); + error |= test("\xf2\x48\xa5", "repne movsq (%rsi),%es:(%rdi)"); + error |= test("\xf3\x48\xa5", "repe movsq (%rsi),%es:(%rdi)"); + error |= test("\xf3\x0f\x1e\xfa", "endbr64"); + + return error; +} diff --git a/regress/sys/arch/amd64/ddb/disasm.h b/regress/sys/arch/amd64/ddb/disasm.h new file mode 100644 index 00000000000..7130ef6d0df --- /dev/null +++ b/regress/sys/arch/amd64/ddb/disasm.h @@ -0,0 +1,22 @@ +/* $OpenBSD: disasm.h,v 1.1 2024/11/19 05:50:41 anton Exp $ */ + +#include /* vaddr_t */ +#include /* size_t */ +#include + +struct db_disasm_context { + struct { + const uint8_t *buf; + size_t len; + } raw; + + struct { + char buf[128]; + size_t siz; + size_t len; + } act; +}; + +vaddr_t db_disasm(vaddr_t, int); + +extern struct db_disasm_context *ctx; diff --git a/regress/sys/arch/amd64/ddb/stubs.c b/regress/sys/arch/amd64/ddb/stubs.c new file mode 100644 index 00000000000..4a8a2fa69e0 --- /dev/null +++ b/regress/sys/arch/amd64/ddb/stubs.c @@ -0,0 +1,94 @@ +/* $OpenBSD: stubs.c,v 1.1 2024/11/19 05:50:41 anton Exp $ */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "disasm.h" + +void (*cnputc)(int) = NULL; +int (*cngetc)(void) = NULL; +char *esym = NULL; +char *ssym = NULL; +struct cpu_info_full cpu_info_full_primary = {0}; + +int +db_elf_sym_init(int symsize, void *symtab, void *esymtab, const char *name) +{ + return 0; +} + +Elf_Sym * +db_elf_sym_search(vaddr_t off, db_strategy_t strategy, db_expr_t *diffp) +{ + return NULL; +} + +int +db_elf_line_at_pc(Elf_Sym *cursym, const char **filename, int *linenum, + db_expr_t off) +{ + return 0; +} + +void +db_error(char *s) +{ +} + +void +db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count, + char *modif, int (*pr)(const char *, ...)) +{ +} + +void +db_symbol_values(Elf_Sym *sym, const char **namep, db_expr_t *valuep) +{ +} + +db_expr_t +db_get_value(vaddr_t addr, size_t size, int is_signed) +{ + db_expr_t c; + + if (ctx->raw.len == 0) + return 0; + + c = ctx->raw.buf[0]; + ctx->raw.buf++; + ctx->raw.len--; + return c; +} + +int +db_printf(const char *fmt, ...) +{ + int n = 0; + + if (strcmp(fmt, "\n") == 0) { + /* nothing */ + } else if (strcmp(fmt, "\t") == 0) { + n = snprintf(&ctx->act.buf[ctx->act.len], ctx->act.siz, " "); + } else { + va_list ap; + + va_start(ap, fmt); + n = vsnprintf(&ctx->act.buf[ctx->act.len], ctx->act.siz, fmt, + ap); + va_end(ap); + } + if (n < 0 || (size_t)n >= ctx->act.siz) + errx(1, "buffer too small"); + ctx->act.len += n; + ctx->act.siz -= n; + return 0; +} -- cgit v1.2.3