[Tarantool-patches] [PATCH v2 2/2] cmake: remove dynamic-list linker option

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Sat Apr 18 02:48:43 MSK 2020


dynamic-list (exported_symbols_list on Mac) was used to forbid
export of all symbols of the tarantool executable except a given
list. Motivation of that was to avoid hacking the linker with
false usage of symbols needed to be exported. As a consequence,
symbols not listed in these options became invisible.

Before these options, when a symbol was defined, but not used in
the final executable, the linker could throw it away, even though
many symbols were used by Lua FFI, or should be visible for user's
dynamic modules. Where the linker, obviously, can't see if they
are needed.

To make the linker believe the symbols are actually needed there
was a hack with getting pointers at these functions and doing
something with them.

For example, assume we have 'test()' function in 'box' static
library:

    int
    test(void);

It is not used anywhere in the final executable. So to trick the
linker there is a function 'export_syms()' declared, which takes a
pointer at 'test()' and seemingly does something with it (or
actually does - it does not matter):

    void
    export_syms()
    {
        void *syms[] = {test};
        if (time(NULL) == 0) {
            syms[0]();
            syms[1]();
            ...
        }
    }

Some users want to use not documented but visible symbols, so the
patch removes the dynamic-list option, and returns the linker
hack back. But with 0 dependencies in the export file.

Closes #2971
---
 .gitignore                                  |   1 -
 extra/exports                               | 404 ----------------
 src/CMakeLists.txt                          |  50 +-
 src/exports.c                               | 511 ++++++++++++++++++++
 src/main.cc                                 |   5 +
 test/box/gh-2971-symbol-visibility.result   |  22 +
 test/box/gh-2971-symbol-visibility.test.lua |  14 +
 7 files changed, 555 insertions(+), 452 deletions(-)
 delete mode 100644 extra/exports
 create mode 100644 src/exports.c
 create mode 100644 test/box/gh-2971-symbol-visibility.result
 create mode 100644 test/box/gh-2971-symbol-visibility.test.lua

diff --git a/.gitignore b/.gitignore
index cda28d79f..a42c7db35 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,7 +57,6 @@ extra/dist/tarantool.logrotate
 extra/dist/tarantool at .service
 extra/dist/tarantool.tmpfiles.conf
 extra/dist/tarantool-generator
-extra/exports.*
 cmake_install.cmake
 config.mk
 config.guess
diff --git a/extra/exports b/extra/exports
deleted file mode 100644
index a9add2cc1..000000000
--- a/extra/exports
+++ /dev/null
@@ -1,404 +0,0 @@
-# Symbols exported by the main Tarantool executable
-
-# FFI
-
-password_prepare
-lbox_socket_local_resolve
-lbox_socket_nonblock
-base64_decode
-base64_encode
-base64_bufsize
-SHA1internal
-guava
-random_bytes
-fiber_time
-fiber_time64
-fiber_clock
-fiber_clock64
-tarantool_lua_slab_cache
-ibuf_create
-ibuf_reinit
-ibuf_destroy
-ibuf_reserve_slow
-port_destroy
-csv_create
-csv_destroy
-csv_setopt
-csv_iterator_create
-csv_next
-csv_feed
-csv_escape_field
-title_update
-title_get
-title_set_interpretor_name
-title_get_interpretor_name
-title_set_script_name
-title_get_script_name
-title_set_custom
-title_get_custom
-title_set_status
-title_get_status
-tnt_iconv_open
-tnt_iconv_close
-tnt_iconv
-exception_get_string
-exception_get_int
-console_get_output_format
-console_set_output_format
-
-tarantool_lua_ibuf
-uuid_nil
-tt_uuid_create
-tt_uuid_str
-tt_uuid_is_equal
-tt_uuid_is_nil
-tt_uuid_bswap
-tt_uuid_from_string
-log_level
-log_format
-uri_parse
-uri_format
-PMurHash32
-PMurHash32_Process
-PMurHash32_Result
-crc32_calc
-mp_encode_double
-mp_encode_float
-mp_encode_decimal
-mp_encode_uuid
-mp_decode_double
-mp_decode_float
-mp_decode_extl
-mp_sizeof_decimal
-mp_sizeof_uuid
-decimal_unpack
-uuid_unpack
-
-log_type
-say_set_log_level
-say_logrotate
-say_set_log_format
-tarantool_uptime
-tarantool_exit
-log_pid
-space_by_id
-space_run_triggers
-space_bsize
-box_schema_version
-
-crypto_EVP_MD_CTX_new
-crypto_EVP_MD_CTX_free
-crypto_HMAC_CTX_new
-crypto_HMAC_CTX_free
-crypto_stream_new
-crypto_stream_begin
-crypto_stream_append
-crypto_stream_commit
-crypto_stream_delete
-
-lua_static_aligned_alloc
-
-swim_is_configured
-swim_cfg
-swim_set_payload
-swim_set_codec
-swim_add_member
-swim_remove_member
-swim_probe_member
-swim_broadcast
-swim_size
-swim_quit
-swim_self
-swim_member_by_uuid
-swim_member_status
-swim_iterator_open
-swim_iterator_next
-swim_iterator_close
-swim_member_uri
-swim_member_uuid
-swim_member_incarnation
-swim_member_payload
-swim_member_ref
-swim_member_unref
-swim_member_is_dropped
-swim_member_is_payload_up_to_date
-
-# Module API
-
-_say
-fiber_attr_new
-fiber_attr_delete
-fiber_attr_setstacksize
-fiber_attr_getstacksize
-fiber_self
-fiber_new
-fiber_new_ex
-fiber_yield
-fiber_start
-fiber_wakeup
-fiber_cancel
-fiber_set_cancellable
-fiber_set_joinable
-fiber_join
-fiber_sleep
-fiber_is_cancelled
-fiber_time
-fiber_time64
-fiber_reschedule
-fiber_cond_new
-fiber_cond_delete
-fiber_cond_signal
-fiber_cond_broadcast
-fiber_cond_wait_timeout
-fiber_cond_wait
-cord_slab_cache
-coio_wait
-coio_close
-coio_call
-coio_getaddrinfo
-luaL_pushcdata
-luaL_checkcdata
-luaL_setcdatagc
-luaL_ctypeid
-luaL_cdef
-luaL_pushuint64
-luaL_pushint64
-luaL_checkuint64
-luaL_checkint64
-luaL_touint64
-luaL_toint64
-luaT_checktuple
-luaT_pushtuple
-luaT_istuple
-luaT_error
-luaT_call
-luaT_cpcall
-luaT_state
-luaT_tolstring
-luaL_iscallable
-box_txn
-box_txn_begin
-box_txn_commit
-box_txn_savepoint
-box_txn_rollback
-box_txn_rollback_to_savepoint
-box_txn_alloc
-box_txn_id
-box_key_def_new
-box_key_def_delete
-box_tuple_format_default
-box_tuple_new
-box_tuple_ref
-box_tuple_unref
-box_tuple_field_count
-box_tuple_bsize
-box_tuple_to_buf
-box_tuple_format
-box_tuple_format_new
-box_tuple_format_ref
-box_tuple_format_unref
-box_tuple_field
-box_tuple_iterator
-box_tuple_iterator_free
-box_tuple_position
-box_tuple_rewind
-box_tuple_seek
-box_tuple_next
-box_tuple_update
-box_tuple_upsert
-box_tuple_extract_key
-box_tuple_compare
-box_tuple_compare_with_key
-box_return_tuple
-box_space_id_by_name
-box_index_id_by_name
-box_select
-box_insert
-box_replace
-box_delete
-box_update
-box_upsert
-box_truncate
-box_sequence_next
-box_sequence_current
-box_sequence_set
-box_sequence_reset
-box_session_push
-box_index_iterator
-box_iterator_next
-box_iterator_free
-box_index_len
-box_index_bsize
-box_index_random
-box_index_get
-box_index_min
-box_index_max
-box_index_count
-box_error_type
-box_error_code
-box_error_message
-box_error_last
-box_error_clear
-box_error_set
-error_set_prev
-box_latch_new
-box_latch_delete
-box_latch_lock
-box_latch_trylock
-box_latch_unlock
-clock_realtime
-clock_monotonic
-clock_process
-clock_thread
-clock_realtime64
-clock_monotonic64
-clock_process64
-clock_thread64
-string_strip_helper
-
-# Lua / LuaJIT
-
-lua_newstate
-lua_close
-lua_newthread
-lua_atpanic
-lua_gettop
-lua_settop
-lua_pushvalue
-lua_remove
-lua_insert
-lua_replace
-lua_checkstack
-lua_xmove
-lua_isnumber
-lua_isstring
-lua_iscfunction
-lua_isuserdata
-lua_type
-lua_typename
-lua_equal
-lua_rawequal
-lua_lessthan
-lua_tonumber
-lua_tointeger
-lua_toboolean
-lua_tolstring
-lua_objlen
-lua_tocfunction
-lua_touserdata
-lua_tothread
-lua_topointer
-lua_pushnil
-lua_pushnumber
-lua_pushinteger
-lua_pushlstring
-lua_pushstring
-lua_pushvfstring
-lua_pushfstring
-lua_pushcclosure
-lua_pushboolean
-lua_pushlightuserdata
-lua_pushthread
-lua_gettable
-lua_getfield
-lua_rawget
-lua_rawgeti
-lua_createtable
-lua_newuserdata
-lua_getmetatable
-lua_getfenv
-lua_settable
-lua_setfield
-lua_rawset
-lua_rawseti
-lua_setmetatable
-lua_setfenv
-lua_call
-lua_pcall
-lua_cpcall
-lua_load
-lua_dump
-lua_yield
-lua_resume
-lua_status
-lua_gc
-lua_error
-lua_next
-lua_concat
-lua_getallocf
-lua_setallocf
-lua_getstack
-lua_getinfo
-lua_getlocal
-lua_setlocal
-lua_getupvalue
-lua_setupvalue
-lua_sethook
-lua_gethook
-lua_gethookmask
-lua_gethookcount
-lua_upvalueid
-lua_upvaluejoin
-lua_loadx
-
-luaopen_base
-luaopen_math
-luaopen_string
-luaopen_table
-luaopen_io
-luaopen_os
-luaopen_package
-luaopen_debug
-luaopen_bit
-luaopen_jit
-luaopen_ffi
-
-luaL_openlibs
-luaL_openlib
-luaL_register
-luaL_getmetafield
-luaL_callmeta
-luaL_typerror
-luaL_argerror
-luaL_checklstring
-luaL_optlstring
-luaL_checknumber
-luaL_optnumber
-luaL_checkinteger
-luaL_optinteger
-luaL_checkstack
-luaL_checktype
-luaL_checkany
-luaL_newmetatable
-luaL_checkudata
-luaL_where
-luaL_error
-luaL_checkoption
-luaL_ref
-luaL_unref
-luaL_loadfile
-luaL_loadbuffer
-luaL_loadstring
-luaL_newstate
-luaL_gsub
-luaL_findtable
-luaL_fileresult
-luaL_execresult
-luaL_loadfilex
-luaL_loadbufferx
-luaL_traceback
-luaL_setfuncs
-luaL_pushmodule
-luaL_testudata
-luaL_setmetatable
-luaL_buffinit
-luaL_prepbuffer
-luaL_addlstring
-luaL_addstring
-luaL_addvalue
-luaL_pushresult
-
-luaJIT_setmode
-luaJIT_profile_start
-luaJIT_profile_stop
-luaJIT_profile_dumpstack
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6c756f00f..ca978aa89 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -245,56 +245,12 @@ if(BUILD_STATIC)
     endif()
 endif()
 
-# Exports syntax is toolchain-dependent, preprocessing is necessary
-set(exports_file ${CMAKE_BINARY_DIR}/extra/exports.${CMAKE_SYSTEM_NAME})
-add_custom_target(preprocess_exports
-                  DEPENDS ${exports_file})
-add_custom_command(
-    OUTPUT  ${exports_file}
-    DEPENDS ${CMAKE_SOURCE_DIR}/extra/exports
-    COMMAND ${CMAKE_SOURCE_DIR}/extra/mkexports
-            ${CMAKE_SOURCE_DIR}/extra/exports
-            ${exports_file} ${CMAKE_SYSTEM_NAME}
-            ${EXPORT_LIST}
-)
-
 add_executable(
-    tarantool main.cc
+    tarantool main.cc exports.c
     ${LIBUTIL_FREEBSD_SRC}/flopen.c
     ${LIBUTIL_FREEBSD_SRC}/pidfile.c)
 
-add_dependencies(tarantool build_bundled_libs preprocess_exports sql)
-
-# Re-link if exports changed
-set_target_properties(tarantool PROPERTIES LINK_DEPENDS ${exports_file})
-
-# A note about linkers:
-# [GNU linker] When linking an *executable* visibility is ignored, and
-#              either nothing is exported (default), or any non-static
-#              symbol is exported (-rdynamic), or explicitly listed
-#              symbols are exported (--dynamic-list).
-#
-#              However, if a symbol listed lives in a static library it
-#              won't be automatically pulled, hence --whole-archive
-#              option.
-#
-# [Apple linker] One can provide an explicit export list; pulls symbols
-#                from static libraries.
-#
-if (TARGET_OS_DARWIN)
-    target_link_libraries(tarantool box ${common_libraries})
-    set_target_properties(tarantool PROPERTIES
-        LINK_FLAGS "-Wl,-exported_symbols_list,${exports_file}")
-else ()
-    target_link_libraries(tarantool
-                          -Wl,--whole-archive box ${reexport_libraries}
-                          salad -Wl,--no-whole-archive
-                          ${common_libraries}
-                          ${generic_libraries})
-    set_target_properties(tarantool PROPERTIES
-        LINK_FLAGS "-Wl,--dynamic-list,${exports_file}")
-    # get rid of -rdynamic
-    set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
-endif()
+add_dependencies(tarantool build_bundled_libs sql)
+target_link_libraries(tarantool box ${common_libraries})
 
 install (TARGETS tarantool DESTINATION bin)
diff --git a/src/exports.c b/src/exports.c
new file mode 100644
index 000000000..243fdde28
--- /dev/null
+++ b/src/exports.c
@@ -0,0 +1,511 @@
+/*
+ * Copyright 2010-2020, Tarantool AUTHORS, please see AUTHORS file.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/**
+ * The file is a hack to force the linker keep the needed symbols
+ * in the result tarantool executable file.
+ *
+ * Problem is that if a symbol is defined inside a static library,
+ * but never used in the final executable, the linker may throw it
+ * away. But many symbols are needed for Lua FFI and for the
+ * public C API used by dynamic modules.
+ *
+ * This file creates a 'false usage' of needed symbols. It stores
+ * pointers at them into a big array, and does something with
+ * them, so as the compiler and linker couldn't remove it.
+ *
+ * In reality the symbols are never touched here, but the compiler
+ * and the linker can't tell that.
+ *
+ * Below are some alternatives, which may replace the current
+ * solution in future. Both are better in being able to declare a
+ * symbol as exported right where it is defined. Or sometimes in
+ * another place if necessary. For example, when the needed
+ * symbol is defined somewhere in a third_party library.
+ *
+ * ** Solution 1 - user-defined ELF sections. **
+ *
+ * That way is similar to what is used by the Linux kernel. To
+ * implement it there is a macros, lets call it EXPORT_SYMBOL. The
+ * macros takes one parameter - symbol name. In its implementation
+ * the macros defines a global struct keeping pointer at that
+ * symbol, and stored in a special section. For example, .tntexp
+ * section. Later when all is complied into the final executable,
+ * there is a linker script, which takes all the symbols defined
+ * in that section, and creates a reference at them, which is then
+ * somehow used in the code.
+ *
+ * A pseudocode example of how can it look in theory:
+ *
+ * 	struct tnt_exported_symbol {
+ * 		void *sym;
+ * 	};
+ *
+ * 	#define EXPORT_SYMBOL(symbol) \
+ * 		__attribute__((section(".tntexp")))
+ * 		struct tnt_exported_symbol tnt_exported_##sym = { \
+ * 			.sym = (void *) symbol \
+ * 		};
+ *
+ * For more info see EXPORT_SYMBOL() macros in
+ * include/linux/export.h file in the kernel sources.
+ *
+ * ** Solution 2 - precompile script which would find all exported
+ *    functions and generate this file automatically. **
+ *
+ * Not much to explain. Introduce a macros EXPORT_SYMBOL, and walk
+ * all the source code, looking for it. When see a symbol marked
+ * so, remember it. Then generate the exports.c like it is defined
+ * below. But automatically.
+ */
+
+/**
+ * Symbol is just an address. No need to know its definition or
+ * even type to get that address. Even an integer global variable
+ * can be referenced as extern void(*)(void).
+ */
+#define EXPORT(symbol) do {							\
+	extern void *symbol(void);						\
+	syms[__COUNTER__ - index_base] = symbol;				\
+} while (0)
+
+void
+export_syms(void)
+{
+	/*
+	 * Compiler should think the exported symbols are
+	 * reachable. Volatile condition prevents their removal
+	 * during optimizations appliance.
+	 */
+	volatile int never_true = 0;
+	if (!never_true)
+		return;
+	const int index_base = __COUNTER__ + 1;
+	void **syms = (void **)&never_true;
+	/*
+	 * Keep the symbols sorted by name for search and addition
+	 * simplicity, to avoid duplicates. Makes no much sense to
+	 * split them into any sections. Anyway some symbols will
+	 * end-up belonging to several of them at once, and it
+	 * would require moving lines here when a symbol goes from
+	 * privately exported to the public C API.
+	 */
+	EXPORT(base64_bufsize);
+	EXPORT(base64_decode);
+	EXPORT(base64_encode);
+	EXPORT(box_delete);
+	EXPORT(box_error_clear);
+	EXPORT(box_error_code);
+	EXPORT(box_error_last);
+	EXPORT(box_error_message);
+	EXPORT(box_error_set);
+	EXPORT(box_error_type);
+	EXPORT(box_index_bsize);
+	EXPORT(box_index_count);
+	EXPORT(box_index_get);
+	EXPORT(box_index_id_by_name);
+	EXPORT(box_index_iterator);
+	EXPORT(box_index_len);
+	EXPORT(box_index_max);
+	EXPORT(box_index_min);
+	EXPORT(box_index_random);
+	EXPORT(box_insert);
+	EXPORT(box_iterator_free);
+	EXPORT(box_iterator_next);
+	EXPORT(box_key_def_delete);
+	EXPORT(box_key_def_new);
+	EXPORT(box_latch_delete);
+	EXPORT(box_latch_lock);
+	EXPORT(box_latch_new);
+	EXPORT(box_latch_trylock);
+	EXPORT(box_latch_unlock);
+	EXPORT(box_replace);
+	EXPORT(box_return_tuple);
+	EXPORT(box_schema_version);
+	EXPORT(box_select);
+	EXPORT(box_sequence_current);
+	EXPORT(box_sequence_next);
+	EXPORT(box_sequence_reset);
+	EXPORT(box_sequence_set);
+	EXPORT(box_session_push);
+	EXPORT(box_space_id_by_name);
+	EXPORT(box_truncate);
+	EXPORT(box_tuple_bsize);
+	EXPORT(box_tuple_compare);
+	EXPORT(box_tuple_compare_with_key);
+	EXPORT(box_tuple_extract_key);
+	EXPORT(box_tuple_field);
+	EXPORT(box_tuple_field_count);
+	EXPORT(box_tuple_format);
+	EXPORT(box_tuple_format_default);
+	EXPORT(box_tuple_format_new);
+	EXPORT(box_tuple_format_ref);
+	EXPORT(box_tuple_format_unref);
+	EXPORT(box_tuple_iterator);
+	EXPORT(box_tuple_iterator_free);
+	EXPORT(box_tuple_new);
+	EXPORT(box_tuple_next);
+	EXPORT(box_tuple_position);
+	EXPORT(box_tuple_ref);
+	EXPORT(box_tuple_rewind);
+	EXPORT(box_tuple_seek);
+	EXPORT(box_tuple_to_buf);
+	EXPORT(box_tuple_unref);
+	EXPORT(box_tuple_update);
+	EXPORT(box_tuple_upsert);
+	EXPORT(box_txn);
+	EXPORT(box_txn_alloc);
+	EXPORT(box_txn_begin);
+	EXPORT(box_txn_commit);
+	EXPORT(box_txn_id);
+	EXPORT(box_txn_rollback);
+	EXPORT(box_txn_rollback_to_savepoint);
+	EXPORT(box_txn_savepoint);
+	EXPORT(box_update);
+	EXPORT(box_upsert);
+	EXPORT(clock_monotonic64);
+	EXPORT(clock_monotonic);
+	EXPORT(clock_process64);
+	EXPORT(clock_process);
+	EXPORT(clock_realtime64);
+	EXPORT(clock_realtime);
+	EXPORT(clock_thread64);
+	EXPORT(clock_thread);
+	EXPORT(coio_call);
+	EXPORT(coio_close);
+	EXPORT(coio_getaddrinfo);
+	EXPORT(coio_wait);
+	EXPORT(console_get_output_format);
+	EXPORT(console_set_output_format);
+	EXPORT(cord_slab_cache);
+	EXPORT(crc32_calc);
+	EXPORT(crypto_EVP_MD_CTX_free);
+	EXPORT(crypto_EVP_MD_CTX_new);
+	EXPORT(crypto_HMAC_CTX_free);
+	EXPORT(crypto_HMAC_CTX_new);
+	EXPORT(crypto_stream_append);
+	EXPORT(crypto_stream_begin);
+	EXPORT(crypto_stream_commit);
+	EXPORT(crypto_stream_delete);
+	EXPORT(crypto_stream_new);
+	EXPORT(csv_create);
+	EXPORT(csv_destroy);
+	EXPORT(csv_escape_field);
+	EXPORT(csv_feed);
+	EXPORT(csv_iterator_create);
+	EXPORT(csv_next);
+	EXPORT(csv_setopt);
+	EXPORT(decimal_unpack);
+	EXPORT(error_set_prev);
+	EXPORT(exception_get_int);
+	EXPORT(exception_get_string);
+	EXPORT(fiber_attr_delete);
+	EXPORT(fiber_attr_getstacksize);
+	EXPORT(fiber_attr_new);
+	EXPORT(fiber_attr_setstacksize);
+	EXPORT(fiber_cancel);
+	EXPORT(fiber_clock64);
+	EXPORT(fiber_clock);
+	EXPORT(fiber_cond_broadcast);
+	EXPORT(fiber_cond_delete);
+	EXPORT(fiber_cond_new);
+	EXPORT(fiber_cond_signal);
+	EXPORT(fiber_cond_wait);
+	EXPORT(fiber_cond_wait_timeout);
+	EXPORT(fiber_is_cancelled);
+	EXPORT(fiber_join);
+	EXPORT(fiber_new);
+	EXPORT(fiber_new_ex);
+	EXPORT(fiber_reschedule);
+	EXPORT(fiber_self);
+	EXPORT(fiber_set_cancellable);
+	EXPORT(fiber_set_joinable);
+	EXPORT(fiber_sleep);
+	EXPORT(fiber_start);
+	EXPORT(fiber_time64);
+	EXPORT(fiber_time);
+	EXPORT(fiber_wakeup);
+	EXPORT(fiber_yield);
+	EXPORT(guava);
+	EXPORT(ibuf_create);
+	EXPORT(ibuf_destroy);
+	EXPORT(ibuf_reinit);
+	EXPORT(ibuf_reserve_slow);
+	EXPORT(lbox_socket_local_resolve);
+	EXPORT(lbox_socket_nonblock);
+	EXPORT(log_format);
+	EXPORT(log_level);
+	EXPORT(log_pid);
+	EXPORT(log_type);
+	EXPORT(lua_atpanic);
+	EXPORT(lua_call);
+	EXPORT(lua_checkstack);
+	EXPORT(lua_close);
+	EXPORT(lua_concat);
+	EXPORT(lua_cpcall);
+	EXPORT(lua_createtable);
+	EXPORT(lua_dump);
+	EXPORT(lua_equal);
+	EXPORT(lua_error);
+	EXPORT(lua_gc);
+	EXPORT(lua_getallocf);
+	EXPORT(lua_getfenv);
+	EXPORT(lua_getfield);
+	EXPORT(lua_gethook);
+	EXPORT(lua_gethookcount);
+	EXPORT(lua_gethookmask);
+	EXPORT(lua_getinfo);
+	EXPORT(lua_getlocal);
+	EXPORT(lua_getmetatable);
+	EXPORT(lua_getstack);
+	EXPORT(lua_gettable);
+	EXPORT(lua_gettop);
+	EXPORT(lua_getupvalue);
+	EXPORT(lua_insert);
+	EXPORT(lua_iscfunction);
+	EXPORT(lua_isnumber);
+	EXPORT(lua_isstring);
+	EXPORT(lua_isuserdata);
+	EXPORT(lua_lessthan);
+	EXPORT(lua_load);
+	EXPORT(lua_loadx);
+	EXPORT(lua_newstate);
+	EXPORT(lua_newthread);
+	EXPORT(lua_newuserdata);
+	EXPORT(lua_next);
+	EXPORT(lua_objlen);
+	EXPORT(lua_pcall);
+	EXPORT(lua_pushboolean);
+	EXPORT(lua_pushcclosure);
+	EXPORT(lua_pushfstring);
+	EXPORT(lua_pushinteger);
+	EXPORT(lua_pushlightuserdata);
+	EXPORT(lua_pushlstring);
+	EXPORT(lua_pushnil);
+	EXPORT(lua_pushnumber);
+	EXPORT(lua_pushstring);
+	EXPORT(lua_pushthread);
+	EXPORT(lua_pushvalue);
+	EXPORT(lua_pushvfstring);
+	EXPORT(lua_rawequal);
+	EXPORT(lua_rawget);
+	EXPORT(lua_rawgeti);
+	EXPORT(lua_rawset);
+	EXPORT(lua_rawseti);
+	EXPORT(lua_remove);
+	EXPORT(lua_replace);
+	EXPORT(lua_resume);
+	EXPORT(lua_setallocf);
+	EXPORT(lua_setfenv);
+	EXPORT(lua_setfield);
+	EXPORT(lua_sethook);
+	EXPORT(lua_setlocal);
+	EXPORT(lua_setmetatable);
+	EXPORT(lua_settable);
+	EXPORT(lua_settop);
+	EXPORT(lua_setupvalue);
+	EXPORT(lua_static_aligned_alloc);
+	EXPORT(lua_status);
+	EXPORT(lua_toboolean);
+	EXPORT(lua_tocfunction);
+	EXPORT(lua_tointeger);
+	EXPORT(lua_tolstring);
+	EXPORT(lua_tonumber);
+	EXPORT(lua_topointer);
+	EXPORT(lua_tothread);
+	EXPORT(lua_touserdata);
+	EXPORT(lua_type);
+	EXPORT(lua_typename);
+	EXPORT(lua_upvalueid);
+	EXPORT(lua_upvaluejoin);
+	EXPORT(lua_xmove);
+	EXPORT(lua_yield);
+	EXPORT(luaJIT_profile_dumpstack);
+	EXPORT(luaJIT_profile_start);
+	EXPORT(luaJIT_profile_stop);
+	EXPORT(luaJIT_setmode);
+	EXPORT(luaL_addlstring);
+	EXPORT(luaL_addstring);
+	EXPORT(luaL_addvalue);
+	EXPORT(luaL_argerror);
+	EXPORT(luaL_buffinit);
+	EXPORT(luaL_callmeta);
+	EXPORT(luaL_cdef);
+	EXPORT(luaL_checkany);
+	EXPORT(luaL_checkcdata);
+	EXPORT(luaL_checkint64);
+	EXPORT(luaL_checkinteger);
+	EXPORT(luaL_checklstring);
+	EXPORT(luaL_checknumber);
+	EXPORT(luaL_checkoption);
+	EXPORT(luaL_checkstack);
+	EXPORT(luaL_checktype);
+	EXPORT(luaL_checkudata);
+	EXPORT(luaL_checkuint64);
+	EXPORT(luaL_ctypeid);
+	EXPORT(luaL_error);
+	EXPORT(luaL_execresult);
+	EXPORT(luaL_fileresult);
+	EXPORT(luaL_findtable);
+	EXPORT(luaL_getmetafield);
+	EXPORT(luaL_gsub);
+	EXPORT(luaL_iscallable);
+	EXPORT(luaL_loadbuffer);
+	EXPORT(luaL_loadbufferx);
+	EXPORT(luaL_loadfile);
+	EXPORT(luaL_loadfilex);
+	EXPORT(luaL_loadstring);
+	EXPORT(luaL_newmetatable);
+	EXPORT(luaL_newstate);
+	EXPORT(luaL_openlib);
+	EXPORT(luaL_openlibs);
+	EXPORT(luaL_optinteger);
+	EXPORT(luaL_optlstring);
+	EXPORT(luaL_optnumber);
+	EXPORT(luaL_prepbuffer);
+	EXPORT(luaL_pushcdata);
+	EXPORT(luaL_pushint64);
+	EXPORT(luaL_pushmodule);
+	EXPORT(luaL_pushresult);
+	EXPORT(luaL_pushuint64);
+	EXPORT(luaL_ref);
+	EXPORT(luaL_register);
+	EXPORT(luaL_setcdatagc);
+	EXPORT(luaL_setfuncs);
+	EXPORT(luaL_setmetatable);
+	EXPORT(luaL_testudata);
+	EXPORT(luaL_toint64);
+	EXPORT(luaL_touint64);
+	EXPORT(luaL_traceback);
+	EXPORT(luaL_typerror);
+	EXPORT(luaL_unref);
+	EXPORT(luaL_where);
+	EXPORT(luaopen_base);
+	EXPORT(luaopen_bit);
+	EXPORT(luaopen_debug);
+	EXPORT(luaopen_ffi);
+	EXPORT(luaopen_io);
+	EXPORT(luaopen_jit);
+	EXPORT(luaopen_math);
+	EXPORT(luaopen_os);
+	EXPORT(luaopen_package);
+	EXPORT(luaopen_string);
+	EXPORT(luaopen_table);
+	EXPORT(luaT_call);
+	EXPORT(luaT_checktuple);
+	EXPORT(luaT_cpcall);
+	EXPORT(luaT_error);
+	EXPORT(luaT_istuple);
+	EXPORT(luaT_pushtuple);
+	EXPORT(luaT_state);
+	EXPORT(luaT_tolstring);
+	EXPORT(mp_decode_double);
+	EXPORT(mp_decode_extl);
+	EXPORT(mp_decode_float);
+	EXPORT(mp_encode_decimal);
+	EXPORT(mp_encode_double);
+	EXPORT(mp_encode_float);
+	EXPORT(mp_encode_uuid);
+	EXPORT(mp_sizeof_decimal);
+	EXPORT(mp_sizeof_uuid);
+	EXPORT(password_prepare);
+	EXPORT(PMurHash32);
+	EXPORT(PMurHash32_Process);
+	EXPORT(PMurHash32_Result);
+	EXPORT(port_destroy);
+	EXPORT(random_bytes);
+	EXPORT(_say);
+	EXPORT(say_logrotate);
+	EXPORT(say_set_log_format);
+	EXPORT(say_set_log_level);
+	EXPORT(SHA1internal);
+	EXPORT(space_bsize);
+	EXPORT(space_by_id);
+	EXPORT(space_run_triggers);
+	EXPORT(string_strip_helper);
+	EXPORT(swim_add_member);
+	EXPORT(swim_broadcast);
+	EXPORT(swim_cfg);
+	EXPORT(swim_is_configured);
+	EXPORT(swim_iterator_close);
+	EXPORT(swim_iterator_next);
+	EXPORT(swim_iterator_open);
+	EXPORT(swim_member_by_uuid);
+	EXPORT(swim_member_incarnation);
+	EXPORT(swim_member_is_dropped);
+	EXPORT(swim_member_is_payload_up_to_date);
+	EXPORT(swim_member_payload);
+	EXPORT(swim_member_ref);
+	EXPORT(swim_member_status);
+	EXPORT(swim_member_unref);
+	EXPORT(swim_member_uri);
+	EXPORT(swim_member_uuid);
+	EXPORT(swim_probe_member);
+	EXPORT(swim_quit);
+	EXPORT(swim_remove_member);
+	EXPORT(swim_self);
+	EXPORT(swim_set_codec);
+	EXPORT(swim_set_payload);
+	EXPORT(swim_size);
+	EXPORT(tarantool_exit);
+	EXPORT(tarantool_lua_ibuf);
+	EXPORT(tarantool_lua_slab_cache);
+	EXPORT(tarantool_uptime);
+	EXPORT(title_get);
+	EXPORT(title_get_custom);
+	EXPORT(title_get_interpretor_name);
+	EXPORT(title_get_script_name);
+	EXPORT(title_get_status);
+	EXPORT(title_set_custom);
+	EXPORT(title_set_interpretor_name);
+	EXPORT(title_set_script_name);
+	EXPORT(title_set_status);
+	EXPORT(title_update);
+	EXPORT(tnt_iconv);
+	EXPORT(tnt_iconv_close);
+	EXPORT(tnt_iconv_open);
+	EXPORT(tt_uuid_bswap);
+	EXPORT(tt_uuid_create);
+	EXPORT(tt_uuid_from_string);
+	EXPORT(tt_uuid_is_equal);
+	EXPORT(tt_uuid_is_nil);
+	EXPORT(tt_uuid_str);
+	EXPORT(uri_format);
+	EXPORT(uri_parse);
+	EXPORT(uuid_nil);
+	EXPORT(uuid_unpack);
+
+	const int func_count = __COUNTER__ - index_base;
+	for (int i = 0; i < func_count; ++i)
+		((void **(*)(void))syms[i])();
+}
+
+#undef EXPORT
diff --git a/src/main.cc b/src/main.cc
index bb0794dfe..712c70bc0 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -711,6 +711,9 @@ break_loop(struct trigger *, void *)
 	return 0;
 }
 
+extern "C" void
+export_syms(void);
+
 int
 main(int argc, char **argv)
 {
@@ -808,6 +811,8 @@ main(int argc, char **argv)
 		title_set_script_name(argv[0]);
 	}
 
+	export_syms();
+
 	random_init();
 
 	crc32_init();
diff --git a/test/box/gh-2971-symbol-visibility.result b/test/box/gh-2971-symbol-visibility.result
new file mode 100644
index 000000000..9f91a4edf
--- /dev/null
+++ b/test/box/gh-2971-symbol-visibility.result
@@ -0,0 +1,22 @@
+-- test-run result file version 2
+ffi = require('ffi')
+ | ---
+ | ...
+
+--
+-- gh-2971: Tarantool should not hide symbols. Even those which
+-- are not a part of the public API.
+--
+
+-- This symbol is not public, but should be defined.
+ffi.cdef[[                                                                      \
+bool                                                                            \
+box_is_configured(void);                                                        \
+]]
+ | ---
+ | ...
+
+ffi.C.box_is_configured()
+ | ---
+ | - true
+ | ...
diff --git a/test/box/gh-2971-symbol-visibility.test.lua b/test/box/gh-2971-symbol-visibility.test.lua
new file mode 100644
index 000000000..f19effeba
--- /dev/null
+++ b/test/box/gh-2971-symbol-visibility.test.lua
@@ -0,0 +1,14 @@
+ffi = require('ffi')
+
+--
+-- gh-2971: Tarantool should not hide symbols. Even those which
+-- are not a part of the public API.
+--
+
+-- This symbol is not public, but should be defined.
+ffi.cdef[[                                                                      \
+bool                                                                            \
+box_is_configured(void);                                                        \
+]]
+
+ffi.C.box_is_configured()
-- 
2.21.1 (Apple Git-122.3)



More information about the Tarantool-patches mailing list