static void erl_first_process_otp(char* modname, void* code, unsigned size, int argc, char** argv) { int i; Eterm start_mod; Eterm args; Eterm* hp; Process parent; ErlSpawnOpts so; Eterm env; start_mod = am_atom_put(modname, sys_strlen(modname)); if (erts_find_function(start_mod, am_start, 2, erts_active_code_ix()) == NULL) { erl_exit(5, "No function %s:start/2\n", modname); } /* * We need a dummy parent process to be able to call erl_create_process(). */ erts_init_empty_process(&parent); erts_smp_proc_lock(&parent, ERTS_PROC_LOCK_MAIN); hp = HAlloc(&parent, argc*2 + 4); args = NIL; for (i = argc-1; i >= 0; i--) { int len = sys_strlen(argv[i]); args = CONS(hp, new_binary(&parent, (byte*)argv[i], len), args); hp += 2; } env = new_binary(&parent, code, size); args = CONS(hp, args, NIL); hp += 2; args = CONS(hp, env, args); so.flags = 0; (void) erl_create_process(&parent, start_mod, am_start, args, &so); erts_smp_proc_unlock(&parent, ERTS_PROC_LOCK_MAIN); erts_cleanup_empty_process(&parent); }
BIF_RETTYPE erts_debug_disassemble_1(BIF_ALIST_1) { Process* p = BIF_P; Eterm addr = BIF_ARG_1; erts_dsprintf_buf_t *dsbufp; Eterm* hp; Eterm* tp; Eterm bin; Eterm mfa; ErtsCodeMFA *cmfa = NULL; BeamCodeHeader* code_hdr; BeamInstr *code_ptr; BeamInstr instr; BeamInstr uaddr; Uint hsz; int i; if (term_to_UWord(addr, &uaddr)) { code_ptr = (BeamInstr *) uaddr; if ((cmfa = find_function_from_pc(code_ptr)) == NULL) { BIF_RET(am_false); } } else if (is_tuple(addr)) { ErtsCodeIndex code_ix; Module* modp; Eterm mod; Eterm name; Export* ep; Sint arity; int n; tp = tuple_val(addr); if (tp[0] != make_arityval(3)) { error: BIF_ERROR(p, BADARG); } mod = tp[1]; name = tp[2]; if (!is_atom(mod) || !is_atom(name) || !is_small(tp[3])) { goto error; } arity = signed_val(tp[3]); code_ix = erts_active_code_ix(); modp = erts_get_module(mod, code_ix); /* * Try the export entry first to allow disassembly of special functions * such as erts_debug:apply/4. Then search for it in the module. */ if ((ep = erts_find_function(mod, name, arity, code_ix)) != NULL) { /* XXX: add "&& ep->address != ep->code" condition? * Consider a traced function. * Its ep will have ep->address == ep->code. * erts_find_function() will return the non-NULL ep. * Below we'll try to derive a code_ptr from ep->address. * But this code_ptr will point to the start of the Export, * not the function's func_info instruction. BOOM !? */ cmfa = erts_code_to_codemfa(ep->addressv[code_ix]); } else if (modp == NULL || (code_hdr = modp->curr.code_hdr) == NULL) { BIF_RET(am_undef); } else { n = code_hdr->num_functions; for (i = 0; i < n; i++) { cmfa = &code_hdr->functions[i]->mfa; if (cmfa->function == name && cmfa->arity == arity) { break; } } if (i == n) { BIF_RET(am_undef); } } code_ptr = (BeamInstr*)erts_code_to_codeinfo(erts_codemfa_to_code(cmfa)); } else { goto error; } dsbufp = erts_create_tmp_dsbuf(0); erts_print(ERTS_PRINT_DSBUF, (void *) dsbufp, HEXF ": ", code_ptr); instr = (BeamInstr) code_ptr[0]; for (i = 0; i < NUM_SPECIFIC_OPS; i++) { if (BeamIsOpCode(instr, i) && opc[i].name[0] != '\0') { code_ptr += print_op(ERTS_PRINT_DSBUF, (void *) dsbufp, i, opc[i].sz-1, code_ptr) + 1; break; } } if (i >= NUM_SPECIFIC_OPS) { erts_print(ERTS_PRINT_DSBUF, (void *) dsbufp, "unknown " HEXF "\n", instr); code_ptr++; } bin = new_binary(p, (byte *) dsbufp->str, dsbufp->str_len); erts_destroy_tmp_dsbuf(dsbufp); hsz = 4+4; (void) erts_bld_uword(NULL, &hsz, (BeamInstr) code_ptr); hp = HAlloc(p, hsz); addr = erts_bld_uword(&hp, NULL, (BeamInstr) code_ptr); ASSERT(is_atom(cmfa->module) || is_nil(cmfa->module)); ASSERT(is_atom(cmfa->function) || is_nil(cmfa->function)); mfa = TUPLE3(hp, cmfa->module, cmfa->function, make_small(cmfa->arity)); hp += 4; return TUPLE3(hp, addr, bin, mfa); }