aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/hipe/hipe_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/hipe/hipe_debug.c')
-rw-r--r--erts/emulator/hipe/hipe_debug.c242
1 files changed, 242 insertions, 0 deletions
diff --git a/erts/emulator/hipe/hipe_debug.c b/erts/emulator/hipe/hipe_debug.c
new file mode 100644
index 0000000000..548998b7b7
--- /dev/null
+++ b/erts/emulator/hipe/hipe_debug.c
@@ -0,0 +1,242 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2001-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+/* $Id$
+ * hipe_debug.c
+ *
+ * TODO:
+ * - detect mode-switch native return addresses (ARCH-specific)
+ * - map user-code native return addresses to symbolic names
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stddef.h> /* offsetof() */
+#include <stdio.h>
+#include "sys.h"
+#include "erl_vm.h"
+#include "global.h"
+#include "erl_process.h"
+#include "beam_catches.h"
+#include "beam_load.h"
+#include "hipe_mode_switch.h"
+#include "hipe_debug.h"
+
+static const char dashes[2*sizeof(long)+5] = {
+ [0 ... 2*sizeof(long)+3] = '-'
+};
+
+static const char dots[2*sizeof(long)+5] = {
+ [0 ... 2*sizeof(long)+3] = '.'
+};
+
+static const char stars[2*sizeof(long)+5] = {
+ [0 ... 2*sizeof(long)+3] = '*'
+};
+
+extern Uint beam_apply[];
+
+static void print_beam_pc(Uint *pc)
+{
+ if (pc == hipe_beam_pc_return) {
+ printf("return-to-native");
+ } else if (pc == hipe_beam_pc_throw) {
+ printf("throw-to-native");
+ } else if (pc == &beam_apply[1]) {
+ printf("normal-process-exit");
+ } else {
+ Eterm *mfa = find_function_from_pc(pc);
+ if (mfa)
+ erts_printf("%T:%T/%bpu + 0x%bpx",
+ mfa[0], mfa[1], mfa[2], pc - &mfa[3]);
+ else
+ printf("?");
+ }
+}
+
+static void catch_slot(Eterm *pos, Eterm val)
+{
+ Uint *pc = catch_pc(val);
+ printf(" | 0x%0*lx | 0x%0*lx | CATCH 0x%0*lx (BEAM ",
+ 2*(int)sizeof(long), (unsigned long)pos,
+ 2*(int)sizeof(long), (unsigned long)val,
+ 2*(int)sizeof(long), (unsigned long)pc);
+ print_beam_pc(pc);
+ printf(")\r\n");
+}
+
+static void print_beam_cp(Eterm *pos, Eterm val)
+{
+ printf(" |%s|%s| BEAM ACTIVATION RECORD\r\n", dashes, dashes);
+ printf(" | 0x%0*lx | 0x%0*lx | BEAM PC ",
+ 2*(int)sizeof(long), (unsigned long)pos,
+ 2*(int)sizeof(long), (unsigned long)val);
+ print_beam_pc(cp_val(val));
+ printf("\r\n");
+}
+
+static void print_catch(Eterm *pos, Eterm val)
+{
+ printf(" |%s|%s| BEAM CATCH FRAME\r\n", dots, dots);
+ catch_slot(pos, val);
+ printf(" |%s|%s|\r\n", stars, stars);
+}
+
+static void print_stack(Eterm *sp, Eterm *end)
+{
+ printf(" | %*s | %*s |\r\n",
+ 2+2*(int)sizeof(long), "Address",
+ 2+2*(int)sizeof(long), "Contents");
+ while (sp < end) {
+ Eterm val = sp[0];
+ if (is_CP(val))
+ print_beam_cp(sp, val);
+ else if (is_catch(val))
+ print_catch(sp, val);
+ else {
+ printf(" | 0x%0*lx | 0x%0*lx | ",
+ 2*(int)sizeof(long), (unsigned long)sp,
+ 2*(int)sizeof(long), (unsigned long)val);
+ erts_printf("%.30T", val);
+ printf("\r\n");
+ }
+ sp += 1;
+ }
+ printf(" |%s|%s|\r\n", dashes, dashes);
+}
+
+void hipe_print_estack(Process *p)
+{
+ printf(" | BEAM STACK |\r\n");
+ print_stack(p->stop, STACK_START(p));
+}
+
+static void print_heap(Eterm *pos, Eterm *end)
+{
+ printf("From: 0x%0*lx to 0x%0*lx\n\r",
+ 2*(int)sizeof(long), (unsigned long)pos,
+ 2*(int)sizeof(long), (unsigned long)end);
+ printf(" | H E A P |\r\n");
+ printf(" | %*s | %*s |\r\n",
+ 2+2*(int)sizeof(long), "Address",
+ 2+2*(int)sizeof(long), "Contents");
+ printf(" |%s|%s|\r\n", dashes, dashes);
+ while (pos < end) {
+ Eterm val = pos[0];
+ printf(" | 0x%0*lx | 0x%0*lx | ",
+ 2*(int)sizeof(long), (unsigned long)pos,
+ 2*(int)sizeof(long), (unsigned long)val);
+ ++pos;
+ if (is_arity_value(val))
+ printf("Arity(%lu)", arityval(val));
+ else if (is_thing(val)) {
+ unsigned int ari = thing_arityval(val);
+ printf("Thing Arity(%u) Tag(%lu)", ari, thing_subtag(val));
+ while (ari) {
+ printf("\r\n | 0x%0*lx | 0x%0*lx | THING",
+ 2*(int)sizeof(long), (unsigned long)pos,
+ 2*(int)sizeof(long), (unsigned long)*pos);
+ ++pos;
+ --ari;
+ }
+ } else
+ erts_printf("%.30T", val);
+ printf("\r\n");
+ }
+ printf(" |%s|%s|\r\n", dashes, dashes);
+}
+
+void hipe_print_heap(Process *p)
+{
+ print_heap(p->heap, p->htop);
+}
+
+void hipe_print_pcb(Process *p)
+{
+ printf("P: 0x%0*lx\r\n", 2*(int)sizeof(long), (unsigned long)p);
+ printf("-----------------------------------------------\r\n");
+ printf("Offset| Name | Value | *Value |\r\n");
+#define U(n,x) \
+ printf(" % 4d | %s | 0x%0*lx | |\r\n", (int)offsetof(Process,x), n, 2*(int)sizeof(long), (unsigned long)p->x)
+#define P(n,x) \
+ printf(" % 4d | %s | 0x%0*lx | 0x%0*lx |\r\n", (int)offsetof(Process,x), n, 2*(int)sizeof(long), (unsigned long)p->x, 2*(int)sizeof(long), p->x ? (unsigned long)*(p->x) : -1UL)
+
+ U("htop ", htop);
+ U("hend ", hend);
+ U("heap ", heap);
+ U("heap_sz ", heap_sz);
+ U("stop ", stop);
+ U("gen_gcs ", gen_gcs);
+ U("max_gen_gcs", max_gen_gcs);
+ U("high_water ", high_water);
+ U("old_hend ", old_hend);
+ U("old_htop ", old_htop);
+ U("old_head ", old_heap);
+ U("min_heap_..", min_heap_size);
+ U("status ", status);
+ U("rstatus ", rstatus);
+ U("rcount ", rcount);
+ U("id ", id);
+ U("prio ", prio);
+ U("reds ", reds);
+ U("tracer_pr..", tracer_proc);
+ U("trace_fla..", trace_flags);
+ U("group_lea..", group_leader);
+ U("flags ", flags);
+ U("fvalue ", fvalue);
+ U("freason ", freason);
+ U("fcalls ", fcalls);
+ /*XXX: ErlTimer tm; */
+ U("next ", next);
+ /*XXX: ErlOffHeap off_heap; */
+ U("reg ", reg);
+ U("nlinks ", nlinks);
+ /*XXX: ErlMessageQueue msg; */
+ U("mbuf ", mbuf);
+ U("mbuf_sz ", mbuf_sz);
+ U("dictionary ", dictionary);
+ U("seq..clock ", seq_trace_clock);
+ U("seq..astcnt", seq_trace_lastcnt);
+ U("seq..token ", seq_trace_token);
+ U("intial[0] ", initial[0]);
+ U("intial[1] ", initial[1]);
+ U("intial[2] ", initial[2]);
+ P("current ", current);
+ P("cp ", cp);
+ P("i ", i);
+ U("catches ", catches);
+ U("arity ", arity);
+ P("arg_reg ", arg_reg);
+ U("max_arg_reg", max_arg_reg);
+ U("def..reg[0]", def_arg_reg[0]);
+ U("def..reg[1]", def_arg_reg[1]);
+ U("def..reg[2]", def_arg_reg[2]);
+ U("def..reg[3]", def_arg_reg[3]);
+ U("def..reg[4]", def_arg_reg[4]);
+ U("def..reg[5]", def_arg_reg[5]);
+#ifdef HIPE
+ U("nsp ", hipe.nsp);
+ U("nstack ", hipe.nstack);
+ U("nstend ", hipe.nstend);
+ U("ncallee ", hipe.ncallee);
+ hipe_arch_print_pcb(&p->hipe);
+#endif /* HIPE */
+#undef U
+#undef P
+ printf("-----------------------------------------------\r\n");
+}