summaryrefslogtreecommitdiffstats
path: root/pigeonhole/src/lib-sieve/sieve-binary-debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'pigeonhole/src/lib-sieve/sieve-binary-debug.c')
-rw-r--r--pigeonhole/src/lib-sieve/sieve-binary-debug.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/pigeonhole/src/lib-sieve/sieve-binary-debug.c b/pigeonhole/src/lib-sieve/sieve-binary-debug.c
new file mode 100644
index 0000000..5e8b13a
--- /dev/null
+++ b/pigeonhole/src/lib-sieve/sieve-binary-debug.c
@@ -0,0 +1,276 @@
+/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
+ */
+
+#include "lib.h"
+#include "str.h"
+
+#include "sieve-common.h"
+#include "sieve-error.h"
+#include "sieve-code.h"
+
+#include "sieve-binary-private.h"
+
+/* Quick 'n dirty debug */
+#if 0
+#define debug_printf(...) printf ("lineinfo: " __VA_ARGS__)
+#else
+#define debug_printf(...)
+#endif
+
+/*
+ * Opcodes
+ */
+
+enum {
+ LINPROG_OP_COPY,
+ LINPROG_OP_ADVANCE_PC,
+ LINPROG_OP_ADVANCE_LINE,
+ LINPROG_OP_SET_COLUMN,
+ LINPROG_OP_SPECIAL_BASE
+};
+
+#define LINPROG_LINE_BASE 0
+#define LINPROG_LINE_RANGE 4
+
+/*
+ * Lineinfo writer
+ */
+
+struct sieve_binary_debug_writer {
+ struct sieve_binary_block *sblock;
+
+ sieve_size_t address;
+ unsigned int line;
+ unsigned int column;
+};
+
+struct sieve_binary_debug_writer *
+sieve_binary_debug_writer_init(struct sieve_binary_block *sblock)
+{
+ struct sieve_binary_debug_writer *dwriter;
+
+ dwriter = i_new(struct sieve_binary_debug_writer, 1);
+ dwriter->sblock = sblock;
+
+ return dwriter;
+}
+
+void sieve_binary_debug_writer_deinit(
+ struct sieve_binary_debug_writer **dwriter)
+{
+ i_free(*dwriter);
+ *dwriter = NULL;
+}
+
+void sieve_binary_debug_emit(struct sieve_binary_debug_writer *dwriter,
+ sieve_size_t code_address, unsigned int code_line,
+ unsigned int code_column)
+{
+ i_assert(code_address >= dwriter->address);
+
+ struct sieve_binary_block *sblock = dwriter->sblock;
+ sieve_size_t address_inc = code_address - dwriter->address;
+ int line_inc = (code_line > dwriter->line ?
+ (int)(code_line - dwriter->line) :
+ -(int)(dwriter->line - code_line));
+ unsigned int sp_opcode = 0;
+
+ /* Check for applicability of special opcode */
+ if (line_inc > 0 &&
+ (LINPROG_LINE_BASE + LINPROG_LINE_RANGE - 1) >= line_inc) {
+ sp_opcode = LINPROG_OP_SPECIAL_BASE +
+ (line_inc - LINPROG_LINE_BASE) +
+ (LINPROG_LINE_RANGE * address_inc);
+
+ if (sp_opcode > 255)
+ sp_opcode = 0;
+ }
+
+ /* Update line and address */
+ if (sp_opcode == 0) {
+ if (line_inc != 0) {
+ (void)sieve_binary_emit_byte(sblock,
+ LINPROG_OP_ADVANCE_LINE);
+ (void)sieve_binary_emit_unsigned(
+ sblock, (unsigned int)line_inc);
+ }
+
+ if (address_inc > 0) {
+ (void)sieve_binary_emit_byte(sblock,
+ LINPROG_OP_ADVANCE_PC);
+ (void)sieve_binary_emit_unsigned(sblock, address_inc);
+ }
+ } else {
+ (void)sieve_binary_emit_byte(sblock, sp_opcode);
+ }
+
+ /* Set column */
+ if (dwriter->column != code_column) {
+ (void)sieve_binary_emit_byte(sblock, LINPROG_OP_SET_COLUMN);
+ (void)sieve_binary_emit_unsigned(sblock, code_column);
+ }
+
+ /* Generate matrix row */
+ (void)sieve_binary_emit_byte(sblock, LINPROG_OP_COPY);
+
+ dwriter->address = code_address;
+ dwriter->line = code_line;
+ dwriter->column = code_column;
+}
+
+/*
+ * Debug reader
+ */
+
+struct sieve_binary_debug_reader {
+ struct sieve_binary_block *sblock;
+
+ sieve_size_t address, last_address;
+ unsigned int line, last_line;
+
+ unsigned int column;
+
+ sieve_size_t state;
+};
+
+struct sieve_binary_debug_reader *
+sieve_binary_debug_reader_init(struct sieve_binary_block *sblock)
+{
+ struct sieve_binary_debug_reader *dreader;
+
+ dreader = i_new(struct sieve_binary_debug_reader, 1);
+ dreader->sblock = sblock;
+
+ return dreader;
+}
+
+void sieve_binary_debug_reader_deinit(
+ struct sieve_binary_debug_reader **dreader)
+{
+ i_free(*dreader);
+ *dreader = NULL;
+}
+
+void sieve_binary_debug_reader_reset(struct sieve_binary_debug_reader *dreader)
+{
+ dreader->address = 0;
+ dreader->line = 0;
+ dreader->column = 0;
+ dreader->state = 0;
+}
+
+unsigned int
+sieve_binary_debug_read_line(struct sieve_binary_debug_reader *dreader,
+ sieve_size_t code_address)
+{
+ size_t linprog_size;
+ sieve_size_t address;
+ unsigned int line;
+
+ if (code_address < dreader->last_address)
+ sieve_binary_debug_reader_reset(dreader);
+
+ if (code_address >= dreader->last_address &&
+ code_address < dreader->address) {
+ debug_printf("%08llx: NOOP [%08llx]\n",
+ (unsigned long long)dreader->state,
+ (unsigned long long)code_address);
+ return dreader->last_line;
+ }
+
+ address = dreader->address;
+ line = dreader->line;
+
+ debug_printf("%08llx: READ [%08llx]\n",
+ (unsigned long long)dreader->state,
+ (unsigned long long)code_address);
+
+ linprog_size = sieve_binary_block_get_size(dreader->sblock);
+ while (dreader->state < linprog_size) {
+ unsigned int opcode;
+ unsigned int value;
+ int line_inc;
+
+ if (sieve_binary_read_byte(dreader->sblock,
+ &dreader->state, &opcode)) {
+ switch (opcode) {
+ case LINPROG_OP_COPY:
+ debug_printf("%08llx: COPY ==> %08llx: %ld\n",
+ (unsigned long long)dreader->state,
+ (unsigned long long)address, line);
+
+ dreader->last_address = dreader->address;
+ dreader->last_line = dreader->line;
+
+ dreader->address = address;
+ dreader->line = line;
+
+ if (code_address < address)
+ return dreader->last_line;
+ else if (code_address == address)
+ return dreader->line;
+ break;
+ case LINPROG_OP_ADVANCE_PC:
+ debug_printf("%08llx: ADV_PC\n",
+ (unsigned long long)dreader->state);
+ if (!sieve_binary_read_unsigned(
+ dreader->sblock, &dreader->state,
+ &value)) {
+ sieve_binary_debug_reader_reset(dreader);
+ return 0;
+ }
+ debug_printf(" : + %d\n", value);
+ address += value;
+ break;
+ case LINPROG_OP_ADVANCE_LINE:
+ debug_printf("%08llx: ADV_LINE\n",
+ (unsigned long long)dreader->state);
+ if (!sieve_binary_read_unsigned(
+ dreader->sblock, &dreader->state,
+ &value)) {
+ sieve_binary_debug_reader_reset(dreader);
+ return 0;
+ }
+ line_inc = (int)value;
+ debug_printf(" : + %d\n", line_inc);
+ line = (line_inc > 0 ?
+ line + (unsigned int)line_inc :
+ line - (unsigned int)-line_inc);
+ break;
+ case LINPROG_OP_SET_COLUMN:
+ debug_printf("%08llx: SET_COL\n",
+ (unsigned long long)dreader->state);
+ if (!sieve_binary_read_unsigned(
+ dreader->sblock, &dreader->state,
+ &value)) {
+ sieve_binary_debug_reader_reset(dreader);
+ return 0;
+ }
+ debug_printf(" : = %d\n", value);
+ dreader->column = value;
+ break;
+ default:
+ opcode -= LINPROG_OP_SPECIAL_BASE;
+
+ address += (opcode / LINPROG_LINE_RANGE);
+ line += LINPROG_LINE_BASE +
+ (opcode % LINPROG_LINE_RANGE);
+
+ debug_printf("%08llx: SPECIAL\n",
+ (unsigned long long)dreader->state);
+ debug_printf(" : +A %d +L %d\n",
+ (opcode / LINPROG_LINE_RANGE),
+ LINPROG_LINE_BASE +
+ (opcode % LINPROG_LINE_RANGE));
+ break;
+ }
+ } else {
+ debug_printf("OPCODE READ FAILED\n");
+ sieve_binary_debug_reader_reset(dreader);
+ return 0;
+ }
+ }
+
+ return dreader->line;
+}
+