static int verify_eterm(Process *p,Eterm element) { Eterm *ptr; ErlHeapFragment* mbuf; switch (primary_tag(element)) { case TAG_PRIMARY_LIST: ptr = list_val(element); break; case TAG_PRIMARY_BOXED: ptr = boxed_val(element); break; default: /* Immediate or header/cp */ return 1; } if (p) { if (IN_HEAP(p, ptr)) return 1; for (mbuf = p->mbuf; mbuf; mbuf = mbuf->next) { if (WITHIN(ptr, &mbuf->mem[0], &mbuf->mem[0] + mbuf->used_size)) { return 1; } } } return 0; }
void erts_check_stack(Process *p) { Eterm *elemp; Eterm *stack_start = p->heap + p->heap_sz; Eterm *stack_end = p->htop; if (p->stop > stack_start) erl_exit(1, "<%lu.%lu.%lu>: Stack underflow\n", internal_pid_channel_no(p->common.id), internal_pid_number(p->common.id), internal_pid_serial(p->common.id)); if (p->stop < stack_end) erl_exit(1, "<%lu.%lu.%lu>: Stack overflow\n", internal_pid_channel_no(p->common.id), internal_pid_number(p->common.id), internal_pid_serial(p->common.id)); for (elemp = p->stop; elemp < stack_start; elemp++) { int in_mbuf = 0; Eterm *ptr; ErlHeapFragment* mbuf; switch (primary_tag(*elemp)) { case TAG_PRIMARY_LIST: ptr = list_val(*elemp); break; case TAG_PRIMARY_BOXED: ptr = boxed_val(*elemp); break; default: /* Immediate or cp */ continue; } if (IN_HEAP(p, ptr)) continue; for (mbuf = p->mbuf; mbuf; mbuf = mbuf->next) if (WITHIN(ptr, &mbuf->mem[0], &mbuf->mem[0] + mbuf->used_size)) { in_mbuf = 1; break; } if (in_mbuf) continue; erl_exit(1, "<%lu.%lu.%lu>: Wild stack pointer\n", internal_pid_channel_no(p->common.id), internal_pid_number(p->common.id), internal_pid_serial(p->common.id)); } }
static int pdisplay1(fmtfn_t to, void *to_arg, Process* p, Eterm obj) { int i, k; Eterm* nobj; if (dcount-- <= 0) return(1); if (is_CP(obj)) { erts_print(to, to_arg, "<cp/header:%0*lX",PTR_SIZE,obj); return 0; } switch (tag_val_def(obj)) { case NIL_DEF: erts_print(to, to_arg, "[]"); break; case ATOM_DEF: erts_print(to, to_arg, "%T", obj); break; case SMALL_DEF: erts_print(to, to_arg, "%ld", signed_val(obj)); break; case BIG_DEF: nobj = big_val(obj); if (!IN_HEAP(p, nobj)) { erts_print(to, to_arg, "#<bad big %X>#", obj); return 1; } i = BIG_SIZE(nobj); if (BIG_SIGN(nobj)) erts_print(to, to_arg, "-#integer(%d) = {", i); else erts_print(to, to_arg, "#integer(%d) = {", i); erts_print(to, to_arg, "%d", BIG_DIGIT(nobj, 0)); for (k = 1; k < i; k++) erts_print(to, to_arg, ",%d", BIG_DIGIT(nobj, k)); erts_putc(to, to_arg, '}'); break; case REF_DEF: case EXTERNAL_REF_DEF: { Uint32 *ref_num; erts_print(to, to_arg, "#Ref<%lu", ref_channel_no(obj)); ref_num = ref_numbers(obj); for (i = ref_no_numbers(obj)-1; i >= 0; i--) erts_print(to, to_arg, ",%lu", ref_num[i]); erts_print(to, to_arg, ">"); break; } case PID_DEF: case EXTERNAL_PID_DEF: erts_print(to, to_arg, "<%lu.%lu.%lu>", pid_channel_no(obj), pid_number(obj), pid_serial(obj)); break; case PORT_DEF: case EXTERNAL_PORT_DEF: erts_print(to, to_arg, "#Port<%lu.%lu>", port_channel_no(obj), port_number(obj)); break; case LIST_DEF: erts_putc(to, to_arg, '['); nobj = list_val(obj); while (1) { if (!IN_HEAP(p, nobj)) { erts_print(to, to_arg, "#<bad list %X>", obj); return 1; } if (pdisplay1(to, to_arg, p, *nobj++) != 0) return(1); if (is_not_list(*nobj)) break; erts_putc(to, to_arg, ','); nobj = list_val(*nobj); } if (is_not_nil(*nobj)) { erts_putc(to, to_arg, '|'); if (pdisplay1(to, to_arg, p, *nobj) != 0) return(1); } erts_putc(to, to_arg, ']'); break; case TUPLE_DEF: nobj = tuple_val(obj); /* pointer to arity */ i = arityval(*nobj); /* arity */ erts_putc(to, to_arg, '{'); while (i--) { if (pdisplay1(to, to_arg, p, *++nobj) != 0) return(1); if (i >= 1) erts_putc(to, to_arg, ','); } erts_putc(to, to_arg, '}'); break; case FLOAT_DEF: { FloatDef ff; GET_DOUBLE(obj, ff); erts_print(to, to_arg, "%.20e", ff.fd); } break; case BINARY_DEF: erts_print(to, to_arg, "#Bin"); break; case MATCHSTATE_DEF: erts_print(to, to_arg, "#Matchstate"); break; default: erts_print(to, to_arg, "unknown object %x", obj); } return(0); }