diff options
author | Sergei Trofimovich <[email protected]> | 2019-03-28 08:38:56 +0000 |
---|---|---|
committer | Sergei Trofimovich <[email protected]> | 2019-03-29 23:24:11 +0000 |
commit | ed751968d8dc4c0b58210247e94409a8a52cc501 (patch) | |
tree | ba0cb7d8abee69288e3c2b64d5bf9d51b195df0f /erts/emulator | |
parent | 1892e8580d2815a7804954b0e7fa8642d0be4a44 (diff) | |
download | otp-ed751968d8dc4c0b58210247e94409a8a52cc501.tar.gz otp-ed751968d8dc4c0b58210247e94409a8a52cc501.tar.bz2 otp-ed751968d8dc4c0b58210247e94409a8a52cc501.zip |
stdlib: fix re:replace on LTO builds
Fabio Coatti reported elixir build failure in https://bugs.gentoo.org/681778.
The minimal reproducer looks like that (from otp git tree):
$ ./configure CFLAGS='-O2 -flto' LDFLAGS='-O2 -flto=8'
$ make
$ ERL_TOP=$PWD \
PATH=$ERL_TOP/bin:$PATH \
\
bin/erl \
\
-noshell -eval 're:replace("a","b","c",[{return,list}]).' \
-s erlang halt
{"init terminating in do_boot",{badarg,[{re,replace,["a","b","c",[{return,list}]],
[{file,"re.erl"},{line,362}]},
{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,680}]},
{init,start_it,1,[]},
{init,start_em,1,[]},
{init,do_boot,3,[]}]}}
init terminating in do_boot ({badarg,[{re,replace,[[_],[_],[_],[_]],[{_},{_}]},
{erl_eval,do_apply,6,[{_},{_}]},{init,start_it,1,[]},{init,start_em,1,[]},{init,do_boot,3,[]}]})
Crash dump is being written to: erl_crash.dump...done
The failure happens in libpcre2 where stack overflow is mis-identified
at function entry of
erts_pcre_compile2()
compile_regex()
if (PUBL(stack_guard) != NULL && PUBL(stack_guard)())
{
*errorcodeptr= ERR85;
return FALSE;
}
The stack "overflow" detection happens in
thr_wrapper()
ethr_set_stacklimit__()
because the stack usage code relies on the fact that ethr_set_stacklimit__()
and similar functions don't get inlined into callers for stack growth
measurement.
Before the change inlining avoidance was achieved by putting functions
into standalone translation units. LTO makes this technique inefficient.
The change marks functions explicitly as __attribute__((__noinline__)) on gcc.
Reported-by: Fabio Coatti
Bug: https://bugs.gentoo.org/681778
Signed-off-by: Sergei Trofimovich <[email protected]>
Diffstat (limited to 'erts/emulator')
-rw-r--r-- | erts/emulator/beam/global.h | 9 | ||||
-rw-r--r-- | erts/emulator/beam/sys.h | 10 |
2 files changed, 15 insertions, 4 deletions
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index f9bbe4167f..4c8d3d3dbe 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -1216,10 +1216,11 @@ Uint64 erts_timestamp_millis(void); Export* erts_find_function(Eterm, Eterm, unsigned int, ErtsCodeIndex); -void *erts_calc_stacklimit(char *prev_c, UWord stacksize); -int erts_check_below_limit(char *ptr, char *limit); -int erts_check_above_limit(char *ptr, char *limit); -void *erts_ptr_id(void *ptr); +/* ERTS_NOINLINE prevents link-time optimization across modules */ +void *erts_calc_stacklimit(char *prev_c, UWord stacksize) ERTS_NOINLINE; +int erts_check_below_limit(char *ptr, char *limit) ERTS_NOINLINE; +int erts_check_above_limit(char *ptr, char *limit) ERTS_NOINLINE; +void *erts_ptr_id(void *ptr) ERTS_NOINLINE; Eterm store_external_or_ref_in_proc_(Process *, Eterm); Eterm store_external_or_ref_(Uint **, ErlOffHeap*, Eterm); diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index a6312293cc..24b6738e08 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -63,6 +63,16 @@ # endif #endif +#ifndef ERTS_NOINLINE +# if ERTS_AT_LEAST_GCC_VSN__(3,1,1) +# define ERTS_NOINLINE __attribute__((__noinline__)) +# elif defined(__WIN32__) +# define ERTS_NOINLINE __declspec(noinline) +# else +# define ERTS_NOINLINE +# endif +#endif + #if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK) # undef ERTS_CAN_INLINE # define ERTS_CAN_INLINE 0 |