summaryrefslogtreecommitdiff
path: root/yjit/yjit.mk
diff options
context:
space:
mode:
authorAlan Wu <XrXr@users.noreply.github.com>2023-01-18 15:58:35 -0500
committerAlan Wu <XrXr@users.noreply.github.com>2023-01-27 12:28:09 -0500
commit7d4395cb690c4b6be41bc51b25a8a5cda6210a81 (patch)
treeb09030cd55b1534f68ae09470c59ab6bbd273839 /yjit/yjit.mk
parente7e48e8a667614c8264993c746ad84b92de997fd (diff)
downloadruby-7d4395cb690c4b6be41bc51b25a8a5cda6210a81.tar.gz
YJIT: Fix shared/static library symbol leaks
Rust 1.58.0 unfortunately doesn't provide facilities to control symbol visibility/presence, but we care about controlling the list of symbols exported from libruby-static.a and libruby.so. This commit uses `ld -r` to make a single object out of rustc's staticlib output, libyjit.a. This moves libyjit.a out of MAINLIBS and adds libyjit.o into COMMONOBJS, which obviates the code for merging libyjit.a into libruby-static.a. The odd appearance of libyjit.a in SOLIBS is also gone. To filter out symbols we do not want to export on ELF platforms, we use objcopy after the partial link. On darwin, we supply a symbol list to the linker which takes care of hiding unprefixed symbols. [Bug #19255] Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
Diffstat (limited to 'yjit/yjit.mk')
-rw-r--r--yjit/yjit.mk34
1 files changed, 32 insertions, 2 deletions
diff --git a/yjit/yjit.mk b/yjit/yjit.mk
index bcfe902be7..6cd12c4bf3 100644
--- a/yjit/yjit.mk
+++ b/yjit/yjit.mk
@@ -40,8 +40,38 @@ $(YJIT_LIBS): $(YJIT_SRC_FILES)
else
endif
-# Put this here instead of in common.mk to avoid breaking nmake builds
-miniruby$(EXEEXT): $(YJIT_LIBS)
+yjit-libobj: $(YJIT_LIBOBJ)
+
+# Note, BSD handling is in yjit/not_gmake.mk
+YJIT_LIB_SYMBOLS = $(YJIT_LIBS:.a=).symbols
+$(YJIT_LIBOBJ): $(YJIT_LIBS)
+ $(ECHO) 'partial linking $(YJIT_LIBS) into $@'
+ifneq ($(findstring linux,$(target_os)),)
+ $(Q) $(LD) -r -o $@ --whole-archive $(YJIT_LIBS)
+ -$(Q) $(OBJCOPY) --wildcard --keep-global-symbol='$(SYMBOL_PREFIX)rb_*' $(@)
+else ifneq ($(findstring darwin,$(target_os)),)
+ $(Q) $(CC) -nodefaultlibs -r -o $@ -exported_symbols_list $(YJIT_LIB_SYMBOLS) $(YJIT_LIBS)
+else
+ false
+endif
+
+# For Darwin only: a list of symbols that we want the glommed Rust static lib to export.
+# Unfortunately, using wildcard like '_rb_*' with -exported-symbol does not work, at least
+# not on version 820.1. Assume llvm-nm, so XCode 8.0 (from 2016) or newer.
+#
+# The -exported_symbols_list pulls out the right archive members. Symbols not listed
+# in the list are made private extern, which are in turn made local as we're using `ld -r`.
+# Note, section about -keep_private_externs in ld's man page hints at this behavior on which
+# we rely.
+ifneq ($(findstring darwin,$(target_os)),)
+$(YJIT_LIB_SYMBOLS): $(YJIT_LIBS)
+ $(Q) $(NM) --no-llvm-bc --defined-only --extern-only $(YJIT_LIBS) | \
+ sed -n -e 's/.* //' -e '/^$(SYMBOL_PREFIX)rb_/p' \
+ -e '/^$(SYMBOL_PREFIX)rust_eh_personality/p' \
+ > $@
+
+$(YJIT_LIBOBJ): $(YJIT_LIB_SYMBOLS)
+endif
# By using YJIT_BENCH_OPTS instead of RUN_OPTS, you can skip passing the options to `make install`
YJIT_BENCH_OPTS = $(RUN_OPTS) --enable-gems