summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Lindqvist <anton@cvs.openbsd.org>2024-11-19 05:50:42 +0000
committerAnton Lindqvist <anton@cvs.openbsd.org>2024-11-19 05:50:42 +0000
commit635400b2c122ce6ba3b2c61e026fb6c592684804 (patch)
tree23a5939117bc48fb4f0a318b022cdff96cc4ceba
parent59ac9330d5a4cb5723c420f4117cae7aa3628cd8 (diff)
Add amd64 ddb regress suite allowing the disassembler to be tested from
userspace.
-rw-r--r--regress/sys/arch/amd64/ddb/Makefile26
-rw-r--r--regress/sys/arch/amd64/ddb/disasm.c68
-rw-r--r--regress/sys/arch/amd64/ddb/disasm.h22
-rw-r--r--regress/sys/arch/amd64/ddb/stubs.c94
4 files changed, 210 insertions, 0 deletions
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 <bsd.regress.mk>
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 <stddef.h> /* size_t */
+#include <stdio.h>
+#include <string.h>
+
+#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 <sys/types.h> /* vaddr_t */
+#include <stddef.h> /* size_t */
+#include <stdint.h>
+
+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 <err.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <machine/db_machdep.h>
+#include <machine/cpu_full.h>
+#include <ddb/db_access.h>
+#include <ddb/db_interface.h>
+#include <ddb/db_command.h>
+#include <ddb/db_output.h>
+#include <ddb/db_sym.h>
+
+#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;
+}