summaryrefslogtreecommitdiff
path: root/erts
diff options
context:
space:
mode:
authorSverker Eriksson <sverker@erlang.org>2020-09-16 23:03:25 +0200
committerSverker Eriksson <sverker@erlang.org>2020-09-25 12:58:59 +0200
commitbf984876f69ad039b64f573baeef57a51c48f1e3 (patch)
treed8074f473709e54d1fa4bb52d84dde6bb6c6bc83 /erts
parent9303603b91f268181596a391c6af64248baba1a2 (diff)
downloaderlang-bf984876f69ad039b64f573baeef57a51c48f1e3.tar.gz
erts: Preserve instruction word arguments in call_nif_early
to fix race when a write of call_nif_early comes between instruction dispatch and a repeated read of arguments from I[0]. This is already done for tracing when writing i_generic_breakpoint instruction. Race seen provoked when compiled with NO_JUMP_TABLE.
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/beam/erl_nif.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 9b12c459fe..420826ea86 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -4604,6 +4604,7 @@ Eterm erts_load_nif(Process *c_p, BeamInstr *I, Eterm filename, Eterm args)
static void patch_call_nif_early(ErlNifEntry* entry,
struct erl_module_instance* this_mi)
{
+ const BeamInstr call_nif_early = BeamOpCodeAddr(op_call_nif_early);
int i;
ERTS_LC_ASSERT(erts_has_code_write_permission());
@@ -4626,13 +4627,13 @@ static void patch_call_nif_early(ErlNifEntry* entry,
* Code write permission protects against racing breakpoint writes.
*/
GenericBp* g = ci->u.gen_bp;
- g->orig_instr = BeamOpCodeAddr(op_call_nif_early);
+ g->orig_instr = BeamSetCodeAddr(g->orig_instr, call_nif_early);
if (BeamIsOpCode(code_ptr[0], op_i_generic_breakpoint))
continue;
}
else
ASSERT(!BeamIsOpCode(code_ptr[0], op_i_generic_breakpoint));
- code_ptr[0] = BeamOpCodeAddr(op_call_nif_early);
+ code_ptr[0] = BeamSetCodeAddr(code_ptr[0], call_nif_early);
}
}
@@ -4711,12 +4712,12 @@ static void load_nif_2nd_finisher(void* vlib)
* Function traced, patch the original instruction word
*/
GenericBp* g = ci->u.gen_bp;
- ASSERT(g->orig_instr == BeamOpCodeAddr(op_call_nif_early));
+ ASSERT(BeamIsOpCode(g->orig_instr, op_call_nif_early));
g->orig_instr = BeamOpCodeAddr(op_call_nif_WWW);
if (BeamIsOpCode(code_ptr[0], op_i_generic_breakpoint))
continue;
}
- ASSERT(code_ptr[0] == BeamOpCodeAddr(op_call_nif_early));
+ ASSERT(BeamIsOpCode(code_ptr[0], op_call_nif_early));
code_ptr[0] = BeamOpCodeAddr(op_call_nif_WWW);
}
}