logo

overlay

My own overlay for experimentations, use with caution, no support is provided git clone https://hacktivis.me/git/overlay.git

erlang-21.3-lto.patch (5277B)


  1. https://github.com/erlang/otp/pull/2194
  2. https://bugs.gentoo.org/681778
  3. From ed751968d8dc4c0b58210247e94409a8a52cc501 Mon Sep 17 00:00:00 2001
  4. From: Sergei Trofimovich <slyfox@gentoo.org>
  5. Date: Thu, 28 Mar 2019 08:38:56 +0000
  6. Subject: [PATCH] stdlib: fix re:replace on LTO builds
  7. Fabio Coatti reported elixir build failure in https://bugs.gentoo.org/681778.
  8. The minimal reproducer looks like that (from otp git tree):
  9. $ ./configure CFLAGS='-O2 -flto' LDFLAGS='-O2 -flto=8'
  10. $ make
  11. $ ERL_TOP=$PWD \
  12. PATH=$ERL_TOP/bin:$PATH \
  13. \
  14. bin/erl \
  15. \
  16. -noshell -eval 're:replace("a","b","c",[{return,list}]).' \
  17. -s erlang halt
  18. {"init terminating in do_boot",{badarg,[{re,replace,["a","b","c",[{return,list}]],
  19. [{file,"re.erl"},{line,362}]},
  20. {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,680}]},
  21. {init,start_it,1,[]},
  22. {init,start_em,1,[]},
  23. {init,do_boot,3,[]}]}}
  24. init terminating in do_boot ({badarg,[{re,replace,[[_],[_],[_],[_]],[{_},{_}]},
  25. {erl_eval,do_apply,6,[{_},{_}]},{init,start_it,1,[]},{init,start_em,1,[]},{init,do_boot,3,[]}]})
  26. Crash dump is being written to: erl_crash.dump...done
  27. The failure happens in libpcre2 where stack overflow is mis-identified
  28. at function entry of
  29. erts_pcre_compile2()
  30. compile_regex()
  31. if (PUBL(stack_guard) != NULL && PUBL(stack_guard)())
  32. {
  33. *errorcodeptr= ERR85;
  34. return FALSE;
  35. }
  36. The stack "overflow" detection happens in
  37. thr_wrapper()
  38. ethr_set_stacklimit__()
  39. because the stack usage code relies on the fact that ethr_set_stacklimit__()
  40. and similar functions don't get inlined into callers for stack growth
  41. measurement.
  42. Before the change inlining avoidance was achieved by putting functions
  43. into standalone translation units. LTO makes this technique inefficient.
  44. The change marks functions explicitly as __attribute__((__noinline__)) on gcc.
  45. Reported-by: Fabio Coatti
  46. Bug: https://bugs.gentoo.org/681778
  47. Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
  48. ---
  49. erts/emulator/beam/global.h | 9 +++++----
  50. erts/emulator/beam/sys.h | 10 ++++++++++
  51. erts/include/internal/ethr_internal.h | 2 +-
  52. erts/include/internal/ethread_inline.h | 3 +++
  53. 4 files changed, 19 insertions(+), 5 deletions(-)
  54. diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
  55. index f9bbe4167f9..4c8d3d3dbe6 100644
  56. --- a/erts/emulator/beam/global.h
  57. +++ b/erts/emulator/beam/global.h
  58. @@ -1216,10 +1216,11 @@ Uint64 erts_timestamp_millis(void);
  59. Export* erts_find_function(Eterm, Eterm, unsigned int, ErtsCodeIndex);
  60. -void *erts_calc_stacklimit(char *prev_c, UWord stacksize);
  61. -int erts_check_below_limit(char *ptr, char *limit);
  62. -int erts_check_above_limit(char *ptr, char *limit);
  63. -void *erts_ptr_id(void *ptr);
  64. +/* ERTS_NOINLINE prevents link-time optimization across modules */
  65. +void *erts_calc_stacklimit(char *prev_c, UWord stacksize) ERTS_NOINLINE;
  66. +int erts_check_below_limit(char *ptr, char *limit) ERTS_NOINLINE;
  67. +int erts_check_above_limit(char *ptr, char *limit) ERTS_NOINLINE;
  68. +void *erts_ptr_id(void *ptr) ERTS_NOINLINE;
  69. Eterm store_external_or_ref_in_proc_(Process *, Eterm);
  70. Eterm store_external_or_ref_(Uint **, ErlOffHeap*, Eterm);
  71. diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
  72. index a6312293cc8..24b6738e082 100644
  73. --- a/erts/emulator/beam/sys.h
  74. +++ b/erts/emulator/beam/sys.h
  75. @@ -63,6 +63,16 @@
  76. # endif
  77. #endif
  78. +#ifndef ERTS_NOINLINE
  79. +# if ERTS_AT_LEAST_GCC_VSN__(3,1,1)
  80. +# define ERTS_NOINLINE __attribute__((__noinline__))
  81. +# elif defined(__WIN32__)
  82. +# define ERTS_NOINLINE __declspec(noinline)
  83. +# else
  84. +# define ERTS_NOINLINE
  85. +# endif
  86. +#endif
  87. +
  88. #if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
  89. # undef ERTS_CAN_INLINE
  90. # define ERTS_CAN_INLINE 0
  91. diff --git a/erts/include/internal/ethr_internal.h b/erts/include/internal/ethr_internal.h
  92. index ac27ff2ed09..17ec84c52b6 100644
  93. --- a/erts/include/internal/ethr_internal.h
  94. +++ b/erts/include/internal/ethr_internal.h
  95. @@ -90,7 +90,7 @@ int ethr_init_common__(ethr_init_data *id);
  96. int ethr_late_init_common__(ethr_late_init_data *lid);
  97. void ethr_run_exit_handlers__(void);
  98. void ethr_ts_event_destructor__(void *vtsep);
  99. -void ethr_set_stacklimit__(char *prev_c, size_t stacksize);
  100. +void ethr_set_stacklimit__(char *prev_c, size_t stacksize) ETHR_NOINLINE;
  101. #if defined(ETHR_X86_RUNTIME_CONF__)
  102. void ethr_x86_cpuid__(int *eax, int *ebx, int *ecx, int *edx);
  103. diff --git a/erts/include/internal/ethread_inline.h b/erts/include/internal/ethread_inline.h
  104. index 8e6bcfc4a8c..f25ba4ae721 100644
  105. --- a/erts/include/internal/ethread_inline.h
  106. +++ b/erts/include/internal/ethread_inline.h
  107. @@ -62,12 +62,15 @@
  108. # define ETHR_INLINE __inline__
  109. # if ETHR_AT_LEAST_GCC_VSN__(3, 1, 1)
  110. # define ETHR_FORCE_INLINE __inline__ __attribute__((__always_inline__))
  111. +# define ETHR_NOINLINE __attribute__((__noinline__))
  112. # else
  113. # define ETHR_FORCE_INLINE __inline__
  114. +# define ETHR_NOINLINE
  115. # endif
  116. #elif defined(__WIN32__)
  117. # define ETHR_INLINE __forceinline
  118. # define ETHR_FORCE_INLINE __forceinline
  119. +# define ETHR_NOINLINE __declspec(noinline)
  120. #endif
  121. #endif /* #ifndef ETHREAD_INLINE_H__ */