diff --git a/lib/modules/Debug.pmod/module.pmod b/lib/modules/Debug.pmod/module.pmod index d986e994976d324c5808a4b5a1daedb2b981862f..81528332b921c85acc378b563acb6d415dfd82a5 100644 --- a/lib/modules/Debug.pmod/module.pmod +++ b/lib/modules/Debug.pmod/module.pmod @@ -11,6 +11,7 @@ constant describe_program = _describe_program; constant debug = _debug; constant optimizer_debug = _optimizer_debug; constant assembler_debug = _assembler_debug; +constant disassemble = Builtin._disassemble; constant dump_program_tables = _dump_program_tables; constant locate_references = _locate_references; constant describe = _describe; diff --git a/src/builtin.cmod b/src/builtin.cmod index ee5d1e7571544fae158e3a194941d6dc064a3e00..a833c767969944490c045c1ae09ec7c63f714ffe 100644 --- a/src/builtin.cmod +++ b/src/builtin.cmod @@ -30,6 +30,7 @@ #include "gc.h" #include "block_alloc.h" #include "pikecode.h" +#include "opcodes.h" #include <ctype.h> #include <errno.h> @@ -1687,6 +1688,66 @@ PIKEFUN void _putenv (string var, void|string val) #endif /* !USE_SETENV */ } +#if defined(PIKE_DEBUG) && defined(PIKE_PORTABLE_BYTECODE) + +/*! @decl void disassemble(function fun) + *! @belongs Debug + *! + *! Disassemble a Pike function to @[Stdio.stderr]. + *! + *! @note + *! This function is only available if the Pike runtime + *! has been compiled with debug enabled. + */ +PIKEFUN void _disassemble(function fun) +{ + if ((TYPEOF(*fun) != T_FUNCTION) || + (SUBTYPEOF(*fun) == FUNCTION_BUILTIN)) { + fprintf(stderr, + "Disassembly only supported for functions implemented in Pike.\n"); + } else if (!fun->u.object->prog) { + fprintf(stderr, "Function in destructed object.\n"); + } else { + int f = SUBTYPEOF(*fun); + struct reference *ptr = PTR_FROM_INT(fun->u.object->prog, f); + struct program *p = PROG_FROM_PTR(fun->u.object->prog, ptr); + struct identifier *id = p->identifiers + ptr->identifier_offset; + if (id->func.offset >= 0) { + struct pike_string *tripples = + p->strings[read_program_data(p->program + id->func.offset, -1)]; + switch(tripples->size_shift) { +#define CASE(SHIFT) \ + case SHIFT: \ + { \ + PIKE_CONCAT(p_wchar, SHIFT) *str = \ + PIKE_CONCAT(STR, SHIFT)(tripples); \ + int i=0; \ + while(i < tripples->len) { \ + fprintf(stderr, "@@@ %d: %s, %d, %d\n", \ + i/3, \ + instrs[*str - F_OFFSET]. \ + name, \ + str[1], str[2]); \ + str += 3; \ + i += 3; \ + } \ + } \ + break + CASE(0); + CASE(1); + CASE(2); +#undef CASE + } + } else { + fprintf(stderr, "Prototype.\n"); + } + } + pop_n_elems(args); + push_int(0); +} + +#endif /* PIKE_DEBUG && PIKE_PORTABLE_BYTECODE */ + /* * Backtrace handling. */