Tarantool development patches archive
 help / color / mirror / Atom feed
* [Tarantool-patches] [PATCH v2 0/2] Unhide symbols
@ 2020-04-17 23:48 Vladislav Shpilevoy
  2020-04-17 23:48 ` [Tarantool-patches] [PATCH v2 1/2] cmake: remove double usage of some source files Vladislav Shpilevoy
                   ` (5 more replies)
  0 siblings, 6 replies; 16+ messages in thread
From: Vladislav Shpilevoy @ 2020-04-17 23:48 UTC (permalink / raw)
  To: tarantool-patches, tsafin

The patchset makes Tarantool stop hiding not explicitly exported
symbols.

It means, all FFI and public C API related symbols are still
always exported. All the other symbols may be exported, or may be
not.

That feature was requested solely by Mons.

To make the needed symbols visible the hack with function
addresses was returned back, like it was before
https://github.com/tarantool/tarantool/commit/4c4c1ccbe422e1420ce0c0b36194fc61bb857ed4,
but with 0 dependencies in the export file.

Branch: http://github.com/tarantool/tarantool/tree/gerold103/gh-2971-symbols-v2
Issue: https://github.com/tarantool/tarantool/issues/2971

@ChangeLog
- Symbols of tarantool executable are not masked anymore. Some
  private symbols may become visible and available for FFI and
  dlopen() + dlsym() (gh-2971).

Changes in v2:
- All exports are moved to one file for simplicity.

Vladislav Shpilevoy (2):
  cmake: remove double usage of some source files
  cmake: remove dynamic-list linker option

 .gitignore                                  |   1 -
 extra/exports                               | 404 ----------------
 src/CMakeLists.txt                          |  57 +--
 src/box/CMakeLists.txt                      |   7 +-
 src/exports.c                               | 511 ++++++++++++++++++++
 src/lib/small                               |   2 +-
 src/main.cc                                 |   5 +
 test/box/gh-2971-symbol-visibility.result   |  22 +
 test/box/gh-2971-symbol-visibility.test.lua |  14 +
 9 files changed, 563 insertions(+), 460 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

-- 
2.21.1 (Apple Git-122.3)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Tarantool-patches] [PATCH v2 1/2] cmake: remove double usage of some source files
  2020-04-17 23:48 [Tarantool-patches] [PATCH v2 0/2] Unhide symbols Vladislav Shpilevoy
@ 2020-04-17 23:48 ` Vladislav Shpilevoy
  2020-04-18  9:22   ` Timur Safin
  2020-04-17 23:48 ` [Tarantool-patches] [PATCH v2 2/2] cmake: remove dynamic-list linker option Vladislav Shpilevoy
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 16+ messages in thread
From: Vladislav Shpilevoy @ 2020-04-17 23:48 UTC (permalink / raw)
  To: tarantool-patches, tsafin

src/cpu_feature.c, src/box/error.cc and src/box/vclock.c were used
twice. As a result it could lead to duplicate symbols.
---
 src/CMakeLists.txt     | 7 ++++---
 src/box/CMakeLists.txt | 7 +++----
 src/lib/small          | 2 +-
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index de9680bcc..6c756f00f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -82,11 +82,13 @@ target_link_libraries(stat core)
 add_library(scramble STATIC scramble.c)
 target_link_libraries(scramble core misc)
 
+add_library(cpu_feature STATIC cpu_feature.c)
+
 add_library(crc32 STATIC
     crc32.c
-    cpu_feature.c
     ${PROJECT_SOURCE_DIR}/third_party/crc32.c
 )
+target_link_libraries(crc32 cpu_feature)
 
 set (server_sources
      find_path.c
@@ -94,7 +96,6 @@ set (server_sources
      httpc.c
      pickle.c
      cfg.c
-     cpu_feature.c
      title.c
      proc_title.c
      path_lock.c
@@ -170,7 +171,7 @@ set_source_files_compile_flags(${server_sources})
 add_library(server STATIC ${server_sources})
 add_dependencies(server build_bundled_libs)
 target_link_libraries(server core coll http_parser bit uri uuid swim swim_udp
-                      swim_ev crypto mpstream)
+                      swim_ev crypto mpstream crc32)
 
 # Rule of thumb: if exporting a symbol from a static library, list the
 # library here.
diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index 5ed7eaead..a232939ab 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
@@ -34,12 +34,12 @@ set_property(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${lua_sources})
 include_directories(${ZSTD_INCLUDE_DIRS})
 include_directories(${CMAKE_BINARY_DIR}/src/box/sql)
 
-add_library(box_error STATIC error.cc errcode.c vclock.c)
-target_link_libraries(box_error core stat)
-
 add_library(vclock STATIC vclock.c)
 target_link_libraries(vclock core)
 
+add_library(box_error STATIC error.cc errcode.c)
+target_link_libraries(box_error core stat vclock)
+
 add_library(xrow STATIC xrow.c iproto_constants.c)
 target_link_libraries(xrow server core small vclock misc box_error
                       scramble mpstream ${MSGPUCK_LIBRARIES})
@@ -73,7 +73,6 @@ target_link_libraries(xlog core box_error crc32 ${ZSTD_LIBRARIES})
 
 add_library(box STATIC
     iproto.cc
-    error.cc
     xrow_io.cc
     tuple_convert.c
     identifier.c
diff --git a/src/lib/small b/src/lib/small
index 3df505017..cebc40574 160000
--- a/src/lib/small
+++ b/src/lib/small
@@ -1 +1 @@
-Subproject commit 3df5050171d040bfe5717b4bddf57da3b312ffe4
+Subproject commit cebc40574cb68a21dac16c438371392db8f98f66
-- 
2.21.1 (Apple Git-122.3)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Tarantool-patches] [PATCH v2 2/2] cmake: remove dynamic-list linker option
  2020-04-17 23:48 [Tarantool-patches] [PATCH v2 0/2] Unhide symbols Vladislav Shpilevoy
  2020-04-17 23:48 ` [Tarantool-patches] [PATCH v2 1/2] cmake: remove double usage of some source files Vladislav Shpilevoy
@ 2020-04-17 23:48 ` Vladislav Shpilevoy
  2020-04-18 12:39   ` Timur Safin
  2020-04-22 22:08 ` [Tarantool-patches] [PATCH v2 0/2] Unhide symbols Vladislav Shpilevoy
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 16+ messages in thread
From: Vladislav Shpilevoy @ 2020-04-17 23:48 UTC (permalink / raw)
  To: tarantool-patches, tsafin

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@.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)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 1/2] cmake: remove double usage of some source files
  2020-04-17 23:48 ` [Tarantool-patches] [PATCH v2 1/2] cmake: remove double usage of some source files Vladislav Shpilevoy
@ 2020-04-18  9:22   ` Timur Safin
  2020-04-18 16:51     ` Vladislav Shpilevoy
  0 siblings, 1 reply; 16+ messages in thread
From: Timur Safin @ 2020-04-18  9:22 UTC (permalink / raw)
  To: 'Vladislav Shpilevoy', tarantool-patches

LGTM As trivial fix, but there is one question though...

: -----Original Message-----
: From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
: Sent: Saturday, April 18, 2020 2:49 AM
: To: tarantool-patches@dev.tarantool.org; tsafin@tarantool.org
: Subject: [PATCH v2 1/2] cmake: remove double usage of some source files
: 
: src/cpu_feature.c, src/box/error.cc and src/box/vclock.c were used
: twice. As a result it could lead to duplicate symbols.
: ---
:  src/CMakeLists.txt     | 7 ++++---
:  src/box/CMakeLists.txt | 7 +++----
:  src/lib/small          | 2 +-
:  3 files changed, 8 insertions(+), 8 deletions(-)
: 
: diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
: index de9680bcc..6c756f00f 100644
: --- a/src/CMakeLists.txt
: +++ b/src/CMakeLists.txt
: @@ -82,11 +82,13 @@ target_link_libraries(stat core)
:  add_library(scramble STATIC scramble.c)
:  target_link_libraries(scramble core misc)
: 
: +add_library(cpu_feature STATIC cpu_feature.c)
: +
:  add_library(crc32 STATIC
:      crc32.c
: -    cpu_feature.c
:      ${PROJECT_SOURCE_DIR}/third_party/crc32.c
:  )
: +target_link_libraries(crc32 cpu_feature)
: 
:  set (server_sources
:       find_path.c
: @@ -94,7 +96,6 @@ set (server_sources
:       httpc.c
:       pickle.c
:       cfg.c
: -     cpu_feature.c
:       title.c
:       proc_title.c
:       path_lock.c
: @@ -170,7 +171,7 @@ set_source_files_compile_flags(${server_sources})
:  add_library(server STATIC ${server_sources})
:  add_dependencies(server build_bundled_libs)
:  target_link_libraries(server core coll http_parser bit uri uuid swim
: swim_udp
: -                      swim_ev crypto mpstream)
: +                      swim_ev crypto mpstream crc32)
: 
:  # Rule of thumb: if exporting a symbol from a static library, list the
:  # library here.
: diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
: index 5ed7eaead..a232939ab 100644
: --- a/src/box/CMakeLists.txt
: +++ b/src/box/CMakeLists.txt
: @@ -34,12 +34,12 @@ set_property(DIRECTORY PROPERTY
: ADDITIONAL_MAKE_CLEAN_FILES ${lua_sources})
:  include_directories(${ZSTD_INCLUDE_DIRS})
:  include_directories(${CMAKE_BINARY_DIR}/src/box/sql)
: 
: -add_library(box_error STATIC error.cc errcode.c vclock.c)
: -target_link_libraries(box_error core stat)
: -
:  add_library(vclock STATIC vclock.c)
:  target_link_libraries(vclock core)
: 
: +add_library(box_error STATIC error.cc errcode.c)
: +target_link_libraries(box_error core stat vclock)
: +
:  add_library(xrow STATIC xrow.c iproto_constants.c)
:  target_link_libraries(xrow server core small vclock misc box_error
:                        scramble mpstream ${MSGPUCK_LIBRARIES})
: @@ -73,7 +73,6 @@ target_link_libraries(xlog core box_error crc32
: ${ZSTD_LIBRARIES})
: 
:  add_library(box STATIC
:      iproto.cc
: -    error.cc
:      xrow_io.cc
:      tuple_convert.c
:      identifier.c
: diff --git a/src/lib/small b/src/lib/small
: index 3df505017..cebc40574 160000
: --- a/src/lib/small
: +++ b/src/lib/small
: @@ -1 +1 @@
: -Subproject commit 3df5050171d040bfe5717b4bddf57da3b312ffe4
: +Subproject commit cebc40574cb68a21dac16c438371392db8f98f66

Have you intentionally moved small submodule? Is it necessary for this case?

Thanks,
Timur

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 2/2] cmake: remove dynamic-list linker option
  2020-04-17 23:48 ` [Tarantool-patches] [PATCH v2 2/2] cmake: remove dynamic-list linker option Vladislav Shpilevoy
@ 2020-04-18 12:39   ` Timur Safin
  2020-04-18 16:51     ` Vladislav Shpilevoy
  0 siblings, 1 reply; 16+ messages in thread
From: Timur Safin @ 2020-04-18 12:39 UTC (permalink / raw)
  To: 'Vladislav Shpilevoy', tarantool-patches

[-- Attachment #1: Type: text/plain, Size: 37735 bytes --]

There are some comments embedded and bonus patch at the end, please not miss it...

: From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
: 
...
: 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@.service
:  extra/dist/tarantool.tmpfiles.conf
:  extra/dist/tarantool-generator
: -extra/exports.*

Woohoo!

:  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
...
: -luaJIT_profile_stop
: -luaJIT_profile_dumpstack

Woohoo! (again)

: 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

Should we delete extra/mkexports as well? Which is apparently not needed anymore.

: -            ${CMAKE_SOURCE_DIR}/extra/exports
: -            ${exports_file} ${CMAKE_SYSTEM_NAME}
: -            ${EXPORT_LIST}
: -)
: -
...

: 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).

I'd emphasize here the C-symbol aspect, i.e.

"Non-decorated C symbol is just an address for the linker purposes...

: + */
: +#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(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

This is very cool! But I'm still confused though (and, eventually, any static checker would be even more confused) - why there is no simple static array or even blatant original ffi_syms[] array as in https://github.com/tarantool/tarantool/commit/4c4c1ccbe422e1420ce0c0b36194fc61bb857ed4#diff-0d537fbabe94394d24abfc403247c75eL67 which would be initialized with these declared symbols? 

Using volatile integer as and array looks very, very much confusing.  

Update - I've just looked into object code generated by compiler, and it's apparently just blatantly ignored all the tricks - leaving no references to all functions mentioned here:

(please see U type symbols for undefined, external functions)

tsafin@M1BOOK6319:~/tarantool1/build-symbols$ nm -a ./src/CMakeFiles/tarantool.dir/exports.c.o
0000000000000000 b .bss
0000000000000000 n .comment
0000000000000000 d .data
0000000000000000 N .debug_abbrev
0000000000000000 N .debug_aranges
0000000000000000 N .debug_info
0000000000000000 N .debug_line
0000000000000000 N .debug_loc
0000000000000000 N .debug_str
0000000000000000 r .eh_frame
0000000000000000 a exports.c
0000000000000000 T export_syms
0000000000000000 n .note.GNU-stack
0000000000000000 t .text

There is no undefined symbol to link them against :(

And here is the disassembly - please see all EXPORT(x) lines thrown out.

```
objdump -dtS -a ./src/CMakeFiles/tarantool.dir/exports.c.o
...
Disassembly of section .text:

0000000000000000 <export_syms>:
        syms[__COUNTER__ - index_base] = symbol;                                \
} while (0)

void
export_syms(void)
{
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   41 54                   push   %r12
   6:   53                      push   %rbx
   7:   48 83 ec 10             sub    $0x10,%rsp
        /*
         * Compiler should think the exported symbols are
         * reachable. Volatile condition prevents their removal
         * during optimizations appliance.
         */
        volatile int never_true = 0;
   b:   c7 45 ec 00 00 00 00    movl   $0x0,-0x14(%rbp)
        if (!never_true)
  12:   8b 45 ec                mov    -0x14(%rbp),%eax
  15:   85 c0                   test   %eax,%eax
  17:   74 18                   je     31 <export_syms+0x31>
  19:   31 db                   xor    %ebx,%ebx
  1b:   4c 8d 65 ec             lea    -0x14(%rbp),%r12
  1f:   90                      nop
        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])();
  20:   41 ff 14 dc             callq  *(%r12,%rbx,8)
  24:   48 83 c3 01             add    $0x1,%rbx
        for (int i = 0; i < func_count; ++i)
  28:   48 81 fb 80 01 00 00    cmp    $0x180,%rbx
  2f:   75 ef                   jne    20 <export_syms+0x20>
}
  31:   48 83 c4 10             add    $0x10,%rsp
  35:   5b                      pop    %rbx
  36:   41 5c                   pop    %r12
  38:   5d                      pop    %rbp
  39:   c3                      retq   
```

¯\_(ツ)_/¯



: 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();

Please find below the quick patch I've cooked here. It's using the simplest tricks possible, but still make compiler insert external references to the object file

```
tsafin@M1BOOK6319:~/tarantool1/build-symbols$ nm -a ./src/CMakeFiles/tarantool.dir/exports.c.o | grep 'U ' | head -10
                 U base64_bufsize
                 U base64_decode
                 U base64_encode
                 U box_delete
                 U box_error_clear
                 U box_error_code
                 U box_error_last
                 U box_error_message
                 U box_error_set
                 U box_error_type
```

Here is the patch inlined (just in case I've attached it)

diff --git a/src/export-symbols.h b/src/export-symbols.h
new file mode 100644
index 000000000..220eb988e
--- /dev/null
+++ b/src/export-symbols.h
@@ -0,0 +1,392 @@
+/*
+* 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_SYMBOL(base64_bufsize)
+EXPORT_SYMBOL(base64_decode)
+EXPORT_SYMBOL(base64_encode)
+EXPORT_SYMBOL(box_delete)
+EXPORT_SYMBOL(box_error_clear)
+EXPORT_SYMBOL(box_error_code)
+EXPORT_SYMBOL(box_error_last)
+EXPORT_SYMBOL(box_error_message)
+EXPORT_SYMBOL(box_error_set)
+EXPORT_SYMBOL(box_error_type)
+EXPORT_SYMBOL(box_index_bsize)
+EXPORT_SYMBOL(box_index_count)
+EXPORT_SYMBOL(box_index_get)
+EXPORT_SYMBOL(box_index_id_by_name)
+EXPORT_SYMBOL(box_index_iterator)
+EXPORT_SYMBOL(box_index_len)
+EXPORT_SYMBOL(box_index_max)
+EXPORT_SYMBOL(box_index_min)
+EXPORT_SYMBOL(box_index_random)
+EXPORT_SYMBOL(box_insert)
+EXPORT_SYMBOL(box_iterator_free)
+EXPORT_SYMBOL(box_iterator_next)
+EXPORT_SYMBOL(box_key_def_delete)
+EXPORT_SYMBOL(box_key_def_new)
+EXPORT_SYMBOL(box_latch_delete)
+EXPORT_SYMBOL(box_latch_lock)
+EXPORT_SYMBOL(box_latch_new)
+EXPORT_SYMBOL(box_latch_trylock)
+EXPORT_SYMBOL(box_latch_unlock)
+EXPORT_SYMBOL(box_replace)
+EXPORT_SYMBOL(box_return_tuple)
+EXPORT_SYMBOL(box_schema_version)
+EXPORT_SYMBOL(box_select)
+EXPORT_SYMBOL(box_sequence_current)
+EXPORT_SYMBOL(box_sequence_next)
+EXPORT_SYMBOL(box_sequence_reset)
+EXPORT_SYMBOL(box_sequence_set)
+EXPORT_SYMBOL(box_session_push)
+EXPORT_SYMBOL(box_space_id_by_name)
+EXPORT_SYMBOL(box_truncate)
+EXPORT_SYMBOL(box_tuple_bsize)
+EXPORT_SYMBOL(box_tuple_compare)
+EXPORT_SYMBOL(box_tuple_compare_with_key)
+EXPORT_SYMBOL(box_tuple_extract_key)
+EXPORT_SYMBOL(box_tuple_field)
+EXPORT_SYMBOL(box_tuple_field_count)
+EXPORT_SYMBOL(box_tuple_format)
+EXPORT_SYMBOL(box_tuple_format_default)
+EXPORT_SYMBOL(box_tuple_format_new)
+EXPORT_SYMBOL(box_tuple_format_ref)
+EXPORT_SYMBOL(box_tuple_format_unref)
+EXPORT_SYMBOL(box_tuple_iterator)
+EXPORT_SYMBOL(box_tuple_iterator_free)
+EXPORT_SYMBOL(box_tuple_new)
+EXPORT_SYMBOL(box_tuple_next)
+EXPORT_SYMBOL(box_tuple_position)
+EXPORT_SYMBOL(box_tuple_ref)
+EXPORT_SYMBOL(box_tuple_rewind)
+EXPORT_SYMBOL(box_tuple_seek)
+EXPORT_SYMBOL(box_tuple_to_buf)
+EXPORT_SYMBOL(box_tuple_unref)
+EXPORT_SYMBOL(box_tuple_update)
+EXPORT_SYMBOL(box_tuple_upsert)
+EXPORT_SYMBOL(box_txn)
+EXPORT_SYMBOL(box_txn_alloc)
+EXPORT_SYMBOL(box_txn_begin)
+EXPORT_SYMBOL(box_txn_commit)
+EXPORT_SYMBOL(box_txn_id)
+EXPORT_SYMBOL(box_txn_rollback)
+EXPORT_SYMBOL(box_txn_rollback_to_savepoint)
+EXPORT_SYMBOL(box_txn_savepoint)
+EXPORT_SYMBOL(box_update)
+EXPORT_SYMBOL(box_upsert)
+EXPORT_SYMBOL(clock_monotonic64)
+EXPORT_SYMBOL(clock_monotonic)
+EXPORT_SYMBOL(clock_process64)
+EXPORT_SYMBOL(clock_process)
+EXPORT_SYMBOL(clock_realtime64)
+EXPORT_SYMBOL(clock_realtime)
+EXPORT_SYMBOL(clock_thread64)
+EXPORT_SYMBOL(clock_thread)
+EXPORT_SYMBOL(coio_call)
+EXPORT_SYMBOL(coio_close)
+EXPORT_SYMBOL(coio_getaddrinfo)
+EXPORT_SYMBOL(coio_wait)
+EXPORT_SYMBOL(console_get_output_format)
+EXPORT_SYMBOL(console_set_output_format)
+EXPORT_SYMBOL(cord_slab_cache)
+EXPORT_SYMBOL(crc32_calc)
+EXPORT_SYMBOL(crypto_EVP_MD_CTX_free)
+EXPORT_SYMBOL(crypto_EVP_MD_CTX_new)
+EXPORT_SYMBOL(crypto_HMAC_CTX_free)
+EXPORT_SYMBOL(crypto_HMAC_CTX_new)
+EXPORT_SYMBOL(crypto_stream_append)
+EXPORT_SYMBOL(crypto_stream_begin)
+EXPORT_SYMBOL(crypto_stream_commit)
+EXPORT_SYMBOL(crypto_stream_delete)
+EXPORT_SYMBOL(crypto_stream_new)
+EXPORT_SYMBOL(csv_create)
+EXPORT_SYMBOL(csv_destroy)
+EXPORT_SYMBOL(csv_escape_field)
+EXPORT_SYMBOL(csv_feed)
+EXPORT_SYMBOL(csv_iterator_create)
+EXPORT_SYMBOL(csv_next)
+EXPORT_SYMBOL(csv_setopt)
+EXPORT_SYMBOL(decimal_unpack)
+EXPORT_SYMBOL(error_set_prev)
+EXPORT_SYMBOL(exception_get_int)
+EXPORT_SYMBOL(exception_get_string)
+EXPORT_SYMBOL(fiber_attr_delete)
+EXPORT_SYMBOL(fiber_attr_getstacksize)
+EXPORT_SYMBOL(fiber_attr_new)
+EXPORT_SYMBOL(fiber_attr_setstacksize)
+EXPORT_SYMBOL(fiber_cancel)
+EXPORT_SYMBOL(fiber_clock64)
+EXPORT_SYMBOL(fiber_clock)
+EXPORT_SYMBOL(fiber_cond_broadcast)
+EXPORT_SYMBOL(fiber_cond_delete)
+EXPORT_SYMBOL(fiber_cond_new)
+EXPORT_SYMBOL(fiber_cond_signal)
+EXPORT_SYMBOL(fiber_cond_wait)
+EXPORT_SYMBOL(fiber_cond_wait_timeout)
+EXPORT_SYMBOL(fiber_is_cancelled)
+EXPORT_SYMBOL(fiber_join)
+EXPORT_SYMBOL(fiber_new)
+EXPORT_SYMBOL(fiber_new_ex)
+EXPORT_SYMBOL(fiber_reschedule)
+EXPORT_SYMBOL(fiber_self)
+EXPORT_SYMBOL(fiber_set_cancellable)
+EXPORT_SYMBOL(fiber_set_joinable)
+EXPORT_SYMBOL(fiber_sleep)
+EXPORT_SYMBOL(fiber_start)
+EXPORT_SYMBOL(fiber_time64)
+EXPORT_SYMBOL(fiber_time)
+EXPORT_SYMBOL(fiber_wakeup)
+EXPORT_SYMBOL(fiber_yield)
+EXPORT_SYMBOL(guava)
+EXPORT_SYMBOL(ibuf_create)
+EXPORT_SYMBOL(ibuf_destroy)
+EXPORT_SYMBOL(ibuf_reinit)
+EXPORT_SYMBOL(ibuf_reserve_slow)
+EXPORT_SYMBOL(lbox_socket_local_resolve)
+EXPORT_SYMBOL(lbox_socket_nonblock)
+EXPORT_SYMBOL(log_format)
+EXPORT_SYMBOL(log_level)
+EXPORT_SYMBOL(log_pid)
+EXPORT_SYMBOL(log_type)
+EXPORT_SYMBOL(lua_atpanic)
+EXPORT_SYMBOL(lua_call)
+EXPORT_SYMBOL(lua_checkstack)
+EXPORT_SYMBOL(lua_close)
+EXPORT_SYMBOL(lua_concat)
+EXPORT_SYMBOL(lua_cpcall)
+EXPORT_SYMBOL(lua_createtable)
+EXPORT_SYMBOL(lua_dump)
+EXPORT_SYMBOL(lua_equal)
+EXPORT_SYMBOL(lua_error)
+EXPORT_SYMBOL(lua_gc)
+EXPORT_SYMBOL(lua_getallocf)
+EXPORT_SYMBOL(lua_getfenv)
+EXPORT_SYMBOL(lua_getfield)
+EXPORT_SYMBOL(lua_gethook)
+EXPORT_SYMBOL(lua_gethookcount)
+EXPORT_SYMBOL(lua_gethookmask)
+EXPORT_SYMBOL(lua_getinfo)
+EXPORT_SYMBOL(lua_getlocal)
+EXPORT_SYMBOL(lua_getmetatable)
+EXPORT_SYMBOL(lua_getstack)
+EXPORT_SYMBOL(lua_gettable)
+EXPORT_SYMBOL(lua_gettop)
+EXPORT_SYMBOL(lua_getupvalue)
+EXPORT_SYMBOL(lua_insert)
+EXPORT_SYMBOL(lua_iscfunction)
+EXPORT_SYMBOL(lua_isnumber)
+EXPORT_SYMBOL(lua_isstring)
+EXPORT_SYMBOL(lua_isuserdata)
+EXPORT_SYMBOL(lua_lessthan)
+EXPORT_SYMBOL(lua_load)
+EXPORT_SYMBOL(lua_loadx)
+EXPORT_SYMBOL(lua_newstate)
+EXPORT_SYMBOL(lua_newthread)
+EXPORT_SYMBOL(lua_newuserdata)
+EXPORT_SYMBOL(lua_next)
+EXPORT_SYMBOL(lua_objlen)
+EXPORT_SYMBOL(lua_pcall)
+EXPORT_SYMBOL(lua_pushboolean)
+EXPORT_SYMBOL(lua_pushcclosure)
+EXPORT_SYMBOL(lua_pushfstring)
+EXPORT_SYMBOL(lua_pushinteger)
+EXPORT_SYMBOL(lua_pushlightuserdata)
+EXPORT_SYMBOL(lua_pushlstring)
+EXPORT_SYMBOL(lua_pushnil)
+EXPORT_SYMBOL(lua_pushnumber)
+EXPORT_SYMBOL(lua_pushstring)
+EXPORT_SYMBOL(lua_pushthread)
+EXPORT_SYMBOL(lua_pushvalue)
+EXPORT_SYMBOL(lua_pushvfstring)
+EXPORT_SYMBOL(lua_rawequal)
+EXPORT_SYMBOL(lua_rawget)
+EXPORT_SYMBOL(lua_rawgeti)
+EXPORT_SYMBOL(lua_rawset)
+EXPORT_SYMBOL(lua_rawseti)
+EXPORT_SYMBOL(lua_remove)
+EXPORT_SYMBOL(lua_replace)
+EXPORT_SYMBOL(lua_resume)
+EXPORT_SYMBOL(lua_setallocf)
+EXPORT_SYMBOL(lua_setfenv)
+EXPORT_SYMBOL(lua_setfield)
+EXPORT_SYMBOL(lua_sethook)
+EXPORT_SYMBOL(lua_setlocal)
+EXPORT_SYMBOL(lua_setmetatable)
+EXPORT_SYMBOL(lua_settable)
+EXPORT_SYMBOL(lua_settop)
+EXPORT_SYMBOL(lua_setupvalue)
+EXPORT_SYMBOL(lua_static_aligned_alloc)
+EXPORT_SYMBOL(lua_status)
+EXPORT_SYMBOL(lua_toboolean)
+EXPORT_SYMBOL(lua_tocfunction)
+EXPORT_SYMBOL(lua_tointeger)
+EXPORT_SYMBOL(lua_tolstring)
+EXPORT_SYMBOL(lua_tonumber)
+EXPORT_SYMBOL(lua_topointer)
+EXPORT_SYMBOL(lua_tothread)
+EXPORT_SYMBOL(lua_touserdata)
+EXPORT_SYMBOL(lua_type)
+EXPORT_SYMBOL(lua_typename)
+EXPORT_SYMBOL(lua_upvalueid)
+EXPORT_SYMBOL(lua_upvaluejoin)
+EXPORT_SYMBOL(lua_xmove)
+EXPORT_SYMBOL(lua_yield)
+EXPORT_SYMBOL(luaJIT_profile_dumpstack)
+EXPORT_SYMBOL(luaJIT_profile_start)
+EXPORT_SYMBOL(luaJIT_profile_stop)
+EXPORT_SYMBOL(luaJIT_setmode)
+EXPORT_SYMBOL(luaL_addlstring)
+EXPORT_SYMBOL(luaL_addstring)
+EXPORT_SYMBOL(luaL_addvalue)
+EXPORT_SYMBOL(luaL_argerror)
+EXPORT_SYMBOL(luaL_buffinit)
+EXPORT_SYMBOL(luaL_callmeta)
+EXPORT_SYMBOL(luaL_cdef)
+EXPORT_SYMBOL(luaL_checkany)
+EXPORT_SYMBOL(luaL_checkcdata)
+EXPORT_SYMBOL(luaL_checkint64)
+EXPORT_SYMBOL(luaL_checkinteger)
+EXPORT_SYMBOL(luaL_checklstring)
+EXPORT_SYMBOL(luaL_checknumber)
+EXPORT_SYMBOL(luaL_checkoption)
+EXPORT_SYMBOL(luaL_checkstack)
+EXPORT_SYMBOL(luaL_checktype)
+EXPORT_SYMBOL(luaL_checkudata)
+EXPORT_SYMBOL(luaL_checkuint64)
+EXPORT_SYMBOL(luaL_ctypeid)
+EXPORT_SYMBOL(luaL_error)
+EXPORT_SYMBOL(luaL_execresult)
+EXPORT_SYMBOL(luaL_fileresult)
+EXPORT_SYMBOL(luaL_findtable)
+EXPORT_SYMBOL(luaL_getmetafield)
+EXPORT_SYMBOL(luaL_gsub)
+EXPORT_SYMBOL(luaL_iscallable)
+EXPORT_SYMBOL(luaL_loadbuffer)
+EXPORT_SYMBOL(luaL_loadbufferx)
+EXPORT_SYMBOL(luaL_loadfile)
+EXPORT_SYMBOL(luaL_loadfilex)
+EXPORT_SYMBOL(luaL_loadstring)
+EXPORT_SYMBOL(luaL_newmetatable)
+EXPORT_SYMBOL(luaL_newstate)
+EXPORT_SYMBOL(luaL_openlib)
+EXPORT_SYMBOL(luaL_openlibs)
+EXPORT_SYMBOL(luaL_optinteger)
+EXPORT_SYMBOL(luaL_optlstring)
+EXPORT_SYMBOL(luaL_optnumber)
+EXPORT_SYMBOL(luaL_prepbuffer)
+EXPORT_SYMBOL(luaL_pushcdata)
+EXPORT_SYMBOL(luaL_pushint64)
+EXPORT_SYMBOL(luaL_pushmodule)
+EXPORT_SYMBOL(luaL_pushresult)
+EXPORT_SYMBOL(luaL_pushuint64)
+EXPORT_SYMBOL(luaL_ref)
+EXPORT_SYMBOL(luaL_register)
+EXPORT_SYMBOL(luaL_setcdatagc)
+EXPORT_SYMBOL(luaL_setfuncs)
+EXPORT_SYMBOL(luaL_setmetatable)
+EXPORT_SYMBOL(luaL_testudata)
+EXPORT_SYMBOL(luaL_toint64)
+EXPORT_SYMBOL(luaL_touint64)
+EXPORT_SYMBOL(luaL_traceback)
+EXPORT_SYMBOL(luaL_typerror)
+EXPORT_SYMBOL(luaL_unref)
+EXPORT_SYMBOL(luaL_where)
+EXPORT_SYMBOL(luaopen_base)
+EXPORT_SYMBOL(luaopen_bit)
+EXPORT_SYMBOL(luaopen_debug)
+EXPORT_SYMBOL(luaopen_ffi)
+EXPORT_SYMBOL(luaopen_io)
+EXPORT_SYMBOL(luaopen_jit)
+EXPORT_SYMBOL(luaopen_math)
+EXPORT_SYMBOL(luaopen_os)
+EXPORT_SYMBOL(luaopen_package)
+EXPORT_SYMBOL(luaopen_string)
+EXPORT_SYMBOL(luaopen_table)
+EXPORT_SYMBOL(luaT_call)
+EXPORT_SYMBOL(luaT_checktuple)
+EXPORT_SYMBOL(luaT_cpcall)
+EXPORT_SYMBOL(luaT_error)
+EXPORT_SYMBOL(luaT_istuple)
+EXPORT_SYMBOL(luaT_pushtuple)
+EXPORT_SYMBOL(luaT_state)
+EXPORT_SYMBOL(luaT_tolstring)
+EXPORT_SYMBOL(mp_decode_double)
+EXPORT_SYMBOL(mp_decode_extl)
+EXPORT_SYMBOL(mp_decode_float)
+EXPORT_SYMBOL(mp_encode_decimal)
+EXPORT_SYMBOL(mp_encode_double)
+EXPORT_SYMBOL(mp_encode_float)
+EXPORT_SYMBOL(mp_encode_uuid)
+EXPORT_SYMBOL(mp_sizeof_decimal)
+EXPORT_SYMBOL(mp_sizeof_uuid)
+EXPORT_SYMBOL(password_prepare)
+EXPORT_SYMBOL(PMurHash32)
+EXPORT_SYMBOL(PMurHash32_Process)
+EXPORT_SYMBOL(PMurHash32_Result)
+EXPORT_SYMBOL(port_destroy)
+EXPORT_SYMBOL(random_bytes)
+EXPORT_SYMBOL(_say)
+EXPORT_SYMBOL(say_logrotate)
+EXPORT_SYMBOL(say_set_log_format)
+EXPORT_SYMBOL(say_set_log_level)
+EXPORT_SYMBOL(SHA1internal)
+EXPORT_SYMBOL(space_bsize)
+EXPORT_SYMBOL(space_by_id)
+EXPORT_SYMBOL(space_run_triggers)
+EXPORT_SYMBOL(string_strip_helper)
+EXPORT_SYMBOL(swim_add_member)
+EXPORT_SYMBOL(swim_broadcast)
+EXPORT_SYMBOL(swim_cfg)
+EXPORT_SYMBOL(swim_is_configured)
+EXPORT_SYMBOL(swim_iterator_close)
+EXPORT_SYMBOL(swim_iterator_next)
+EXPORT_SYMBOL(swim_iterator_open)
+EXPORT_SYMBOL(swim_member_by_uuid)
+EXPORT_SYMBOL(swim_member_incarnation)
+EXPORT_SYMBOL(swim_member_is_dropped)
+EXPORT_SYMBOL(swim_member_is_payload_up_to_date)
+EXPORT_SYMBOL(swim_member_payload)
+EXPORT_SYMBOL(swim_member_ref)
+EXPORT_SYMBOL(swim_member_status)
+EXPORT_SYMBOL(swim_member_unref)
+EXPORT_SYMBOL(swim_member_uri)
+EXPORT_SYMBOL(swim_member_uuid)
+EXPORT_SYMBOL(swim_probe_member)
+EXPORT_SYMBOL(swim_quit)
+EXPORT_SYMBOL(swim_remove_member)
+EXPORT_SYMBOL(swim_self)
+EXPORT_SYMBOL(swim_set_codec)
+EXPORT_SYMBOL(swim_set_payload)
+EXPORT_SYMBOL(swim_size)
+EXPORT_SYMBOL(tarantool_exit)
+EXPORT_SYMBOL(tarantool_lua_ibuf)
+EXPORT_SYMBOL(tarantool_lua_slab_cache)
+EXPORT_SYMBOL(tarantool_uptime)
+EXPORT_SYMBOL(title_get)
+EXPORT_SYMBOL(title_get_custom)
+EXPORT_SYMBOL(title_get_interpretor_name)
+EXPORT_SYMBOL(title_get_script_name)
+EXPORT_SYMBOL(title_get_status)
+EXPORT_SYMBOL(title_set_custom)
+EXPORT_SYMBOL(title_set_interpretor_name)
+EXPORT_SYMBOL(title_set_script_name)
+EXPORT_SYMBOL(title_set_status)
+EXPORT_SYMBOL(title_update)
+EXPORT_SYMBOL(tnt_iconv)
+EXPORT_SYMBOL(tnt_iconv_close)
+EXPORT_SYMBOL(tnt_iconv_open)
+EXPORT_SYMBOL(tt_uuid_bswap)
+EXPORT_SYMBOL(tt_uuid_create)
+EXPORT_SYMBOL(tt_uuid_from_string)
+EXPORT_SYMBOL(tt_uuid_is_equal)
+EXPORT_SYMBOL(tt_uuid_is_nil)
+EXPORT_SYMBOL(tt_uuid_str)
+EXPORT_SYMBOL(uri_format)
+EXPORT_SYMBOL(uri_parse)
+EXPORT_SYMBOL(uuid_nil)
+EXPORT_SYMBOL(uuid_unpack)
diff --git a/src/exports.c b/src/exports.c
index 243fdde28..54a4d9946 100644
--- a/src/exports.c
+++ b/src/exports.c
@@ -88,424 +88,25 @@
  */
 
 /**
- * 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).
+ * Non-decorated C symbol is just an address for the linker purposes.
+ * No need to know its definition or even type to get that address.
+ * Even an integer global variable can be referenced as simple
+ * extern void(*)(void).
  */
-#define EXPORT(symbol) do {							\
-	extern void *symbol(void);						\
-	syms[__COUNTER__ - index_base] = symbol;				\
-} while (0)
+#define EXPORT_SYMBOL(symbol)	extern void symbol();
+#include "export-symbols.h"
 
-void
+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);
+#undef EXPORT_SYMBOL
+#define EXPORT_SYMBOL(symbol)	(void*)symbol,
 
-	const int func_count = __COUNTER__ - index_base;
-	for (int i = 0; i < func_count; ++i)
-		((void **(*)(void))syms[i])();
+	static void* syms[] = {
+#include "export-symbols.h"
+	};
+
+	return (void*)syms;
 }
 
-#undef EXPORT
+#undef EXPORT_SYMBOL
diff --git a/src/main.cc b/src/main.cc
index 712c70bc0..15be71aee 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -711,7 +711,7 @@ break_loop(struct trigger *, void *)
 	return 0;
 }
 
-extern "C" void
+extern "C" void*
 export_syms(void);
 
 int

[-- Attachment #2: export-symbol-subpatch.patch --]
[-- Type: application/octet-stream, Size: 25527 bytes --]

diff --git a/src/export-symbols.h b/src/export-symbols.h
new file mode 100644
index 000000000..220eb988e
--- /dev/null
+++ b/src/export-symbols.h
@@ -0,0 +1,392 @@
+/*
+* 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_SYMBOL(base64_bufsize)
+EXPORT_SYMBOL(base64_decode)
+EXPORT_SYMBOL(base64_encode)
+EXPORT_SYMBOL(box_delete)
+EXPORT_SYMBOL(box_error_clear)
+EXPORT_SYMBOL(box_error_code)
+EXPORT_SYMBOL(box_error_last)
+EXPORT_SYMBOL(box_error_message)
+EXPORT_SYMBOL(box_error_set)
+EXPORT_SYMBOL(box_error_type)
+EXPORT_SYMBOL(box_index_bsize)
+EXPORT_SYMBOL(box_index_count)
+EXPORT_SYMBOL(box_index_get)
+EXPORT_SYMBOL(box_index_id_by_name)
+EXPORT_SYMBOL(box_index_iterator)
+EXPORT_SYMBOL(box_index_len)
+EXPORT_SYMBOL(box_index_max)
+EXPORT_SYMBOL(box_index_min)
+EXPORT_SYMBOL(box_index_random)
+EXPORT_SYMBOL(box_insert)
+EXPORT_SYMBOL(box_iterator_free)
+EXPORT_SYMBOL(box_iterator_next)
+EXPORT_SYMBOL(box_key_def_delete)
+EXPORT_SYMBOL(box_key_def_new)
+EXPORT_SYMBOL(box_latch_delete)
+EXPORT_SYMBOL(box_latch_lock)
+EXPORT_SYMBOL(box_latch_new)
+EXPORT_SYMBOL(box_latch_trylock)
+EXPORT_SYMBOL(box_latch_unlock)
+EXPORT_SYMBOL(box_replace)
+EXPORT_SYMBOL(box_return_tuple)
+EXPORT_SYMBOL(box_schema_version)
+EXPORT_SYMBOL(box_select)
+EXPORT_SYMBOL(box_sequence_current)
+EXPORT_SYMBOL(box_sequence_next)
+EXPORT_SYMBOL(box_sequence_reset)
+EXPORT_SYMBOL(box_sequence_set)
+EXPORT_SYMBOL(box_session_push)
+EXPORT_SYMBOL(box_space_id_by_name)
+EXPORT_SYMBOL(box_truncate)
+EXPORT_SYMBOL(box_tuple_bsize)
+EXPORT_SYMBOL(box_tuple_compare)
+EXPORT_SYMBOL(box_tuple_compare_with_key)
+EXPORT_SYMBOL(box_tuple_extract_key)
+EXPORT_SYMBOL(box_tuple_field)
+EXPORT_SYMBOL(box_tuple_field_count)
+EXPORT_SYMBOL(box_tuple_format)
+EXPORT_SYMBOL(box_tuple_format_default)
+EXPORT_SYMBOL(box_tuple_format_new)
+EXPORT_SYMBOL(box_tuple_format_ref)
+EXPORT_SYMBOL(box_tuple_format_unref)
+EXPORT_SYMBOL(box_tuple_iterator)
+EXPORT_SYMBOL(box_tuple_iterator_free)
+EXPORT_SYMBOL(box_tuple_new)
+EXPORT_SYMBOL(box_tuple_next)
+EXPORT_SYMBOL(box_tuple_position)
+EXPORT_SYMBOL(box_tuple_ref)
+EXPORT_SYMBOL(box_tuple_rewind)
+EXPORT_SYMBOL(box_tuple_seek)
+EXPORT_SYMBOL(box_tuple_to_buf)
+EXPORT_SYMBOL(box_tuple_unref)
+EXPORT_SYMBOL(box_tuple_update)
+EXPORT_SYMBOL(box_tuple_upsert)
+EXPORT_SYMBOL(box_txn)
+EXPORT_SYMBOL(box_txn_alloc)
+EXPORT_SYMBOL(box_txn_begin)
+EXPORT_SYMBOL(box_txn_commit)
+EXPORT_SYMBOL(box_txn_id)
+EXPORT_SYMBOL(box_txn_rollback)
+EXPORT_SYMBOL(box_txn_rollback_to_savepoint)
+EXPORT_SYMBOL(box_txn_savepoint)
+EXPORT_SYMBOL(box_update)
+EXPORT_SYMBOL(box_upsert)
+EXPORT_SYMBOL(clock_monotonic64)
+EXPORT_SYMBOL(clock_monotonic)
+EXPORT_SYMBOL(clock_process64)
+EXPORT_SYMBOL(clock_process)
+EXPORT_SYMBOL(clock_realtime64)
+EXPORT_SYMBOL(clock_realtime)
+EXPORT_SYMBOL(clock_thread64)
+EXPORT_SYMBOL(clock_thread)
+EXPORT_SYMBOL(coio_call)
+EXPORT_SYMBOL(coio_close)
+EXPORT_SYMBOL(coio_getaddrinfo)
+EXPORT_SYMBOL(coio_wait)
+EXPORT_SYMBOL(console_get_output_format)
+EXPORT_SYMBOL(console_set_output_format)
+EXPORT_SYMBOL(cord_slab_cache)
+EXPORT_SYMBOL(crc32_calc)
+EXPORT_SYMBOL(crypto_EVP_MD_CTX_free)
+EXPORT_SYMBOL(crypto_EVP_MD_CTX_new)
+EXPORT_SYMBOL(crypto_HMAC_CTX_free)
+EXPORT_SYMBOL(crypto_HMAC_CTX_new)
+EXPORT_SYMBOL(crypto_stream_append)
+EXPORT_SYMBOL(crypto_stream_begin)
+EXPORT_SYMBOL(crypto_stream_commit)
+EXPORT_SYMBOL(crypto_stream_delete)
+EXPORT_SYMBOL(crypto_stream_new)
+EXPORT_SYMBOL(csv_create)
+EXPORT_SYMBOL(csv_destroy)
+EXPORT_SYMBOL(csv_escape_field)
+EXPORT_SYMBOL(csv_feed)
+EXPORT_SYMBOL(csv_iterator_create)
+EXPORT_SYMBOL(csv_next)
+EXPORT_SYMBOL(csv_setopt)
+EXPORT_SYMBOL(decimal_unpack)
+EXPORT_SYMBOL(error_set_prev)
+EXPORT_SYMBOL(exception_get_int)
+EXPORT_SYMBOL(exception_get_string)
+EXPORT_SYMBOL(fiber_attr_delete)
+EXPORT_SYMBOL(fiber_attr_getstacksize)
+EXPORT_SYMBOL(fiber_attr_new)
+EXPORT_SYMBOL(fiber_attr_setstacksize)
+EXPORT_SYMBOL(fiber_cancel)
+EXPORT_SYMBOL(fiber_clock64)
+EXPORT_SYMBOL(fiber_clock)
+EXPORT_SYMBOL(fiber_cond_broadcast)
+EXPORT_SYMBOL(fiber_cond_delete)
+EXPORT_SYMBOL(fiber_cond_new)
+EXPORT_SYMBOL(fiber_cond_signal)
+EXPORT_SYMBOL(fiber_cond_wait)
+EXPORT_SYMBOL(fiber_cond_wait_timeout)
+EXPORT_SYMBOL(fiber_is_cancelled)
+EXPORT_SYMBOL(fiber_join)
+EXPORT_SYMBOL(fiber_new)
+EXPORT_SYMBOL(fiber_new_ex)
+EXPORT_SYMBOL(fiber_reschedule)
+EXPORT_SYMBOL(fiber_self)
+EXPORT_SYMBOL(fiber_set_cancellable)
+EXPORT_SYMBOL(fiber_set_joinable)
+EXPORT_SYMBOL(fiber_sleep)
+EXPORT_SYMBOL(fiber_start)
+EXPORT_SYMBOL(fiber_time64)
+EXPORT_SYMBOL(fiber_time)
+EXPORT_SYMBOL(fiber_wakeup)
+EXPORT_SYMBOL(fiber_yield)
+EXPORT_SYMBOL(guava)
+EXPORT_SYMBOL(ibuf_create)
+EXPORT_SYMBOL(ibuf_destroy)
+EXPORT_SYMBOL(ibuf_reinit)
+EXPORT_SYMBOL(ibuf_reserve_slow)
+EXPORT_SYMBOL(lbox_socket_local_resolve)
+EXPORT_SYMBOL(lbox_socket_nonblock)
+EXPORT_SYMBOL(log_format)
+EXPORT_SYMBOL(log_level)
+EXPORT_SYMBOL(log_pid)
+EXPORT_SYMBOL(log_type)
+EXPORT_SYMBOL(lua_atpanic)
+EXPORT_SYMBOL(lua_call)
+EXPORT_SYMBOL(lua_checkstack)
+EXPORT_SYMBOL(lua_close)
+EXPORT_SYMBOL(lua_concat)
+EXPORT_SYMBOL(lua_cpcall)
+EXPORT_SYMBOL(lua_createtable)
+EXPORT_SYMBOL(lua_dump)
+EXPORT_SYMBOL(lua_equal)
+EXPORT_SYMBOL(lua_error)
+EXPORT_SYMBOL(lua_gc)
+EXPORT_SYMBOL(lua_getallocf)
+EXPORT_SYMBOL(lua_getfenv)
+EXPORT_SYMBOL(lua_getfield)
+EXPORT_SYMBOL(lua_gethook)
+EXPORT_SYMBOL(lua_gethookcount)
+EXPORT_SYMBOL(lua_gethookmask)
+EXPORT_SYMBOL(lua_getinfo)
+EXPORT_SYMBOL(lua_getlocal)
+EXPORT_SYMBOL(lua_getmetatable)
+EXPORT_SYMBOL(lua_getstack)
+EXPORT_SYMBOL(lua_gettable)
+EXPORT_SYMBOL(lua_gettop)
+EXPORT_SYMBOL(lua_getupvalue)
+EXPORT_SYMBOL(lua_insert)
+EXPORT_SYMBOL(lua_iscfunction)
+EXPORT_SYMBOL(lua_isnumber)
+EXPORT_SYMBOL(lua_isstring)
+EXPORT_SYMBOL(lua_isuserdata)
+EXPORT_SYMBOL(lua_lessthan)
+EXPORT_SYMBOL(lua_load)
+EXPORT_SYMBOL(lua_loadx)
+EXPORT_SYMBOL(lua_newstate)
+EXPORT_SYMBOL(lua_newthread)
+EXPORT_SYMBOL(lua_newuserdata)
+EXPORT_SYMBOL(lua_next)
+EXPORT_SYMBOL(lua_objlen)
+EXPORT_SYMBOL(lua_pcall)
+EXPORT_SYMBOL(lua_pushboolean)
+EXPORT_SYMBOL(lua_pushcclosure)
+EXPORT_SYMBOL(lua_pushfstring)
+EXPORT_SYMBOL(lua_pushinteger)
+EXPORT_SYMBOL(lua_pushlightuserdata)
+EXPORT_SYMBOL(lua_pushlstring)
+EXPORT_SYMBOL(lua_pushnil)
+EXPORT_SYMBOL(lua_pushnumber)
+EXPORT_SYMBOL(lua_pushstring)
+EXPORT_SYMBOL(lua_pushthread)
+EXPORT_SYMBOL(lua_pushvalue)
+EXPORT_SYMBOL(lua_pushvfstring)
+EXPORT_SYMBOL(lua_rawequal)
+EXPORT_SYMBOL(lua_rawget)
+EXPORT_SYMBOL(lua_rawgeti)
+EXPORT_SYMBOL(lua_rawset)
+EXPORT_SYMBOL(lua_rawseti)
+EXPORT_SYMBOL(lua_remove)
+EXPORT_SYMBOL(lua_replace)
+EXPORT_SYMBOL(lua_resume)
+EXPORT_SYMBOL(lua_setallocf)
+EXPORT_SYMBOL(lua_setfenv)
+EXPORT_SYMBOL(lua_setfield)
+EXPORT_SYMBOL(lua_sethook)
+EXPORT_SYMBOL(lua_setlocal)
+EXPORT_SYMBOL(lua_setmetatable)
+EXPORT_SYMBOL(lua_settable)
+EXPORT_SYMBOL(lua_settop)
+EXPORT_SYMBOL(lua_setupvalue)
+EXPORT_SYMBOL(lua_static_aligned_alloc)
+EXPORT_SYMBOL(lua_status)
+EXPORT_SYMBOL(lua_toboolean)
+EXPORT_SYMBOL(lua_tocfunction)
+EXPORT_SYMBOL(lua_tointeger)
+EXPORT_SYMBOL(lua_tolstring)
+EXPORT_SYMBOL(lua_tonumber)
+EXPORT_SYMBOL(lua_topointer)
+EXPORT_SYMBOL(lua_tothread)
+EXPORT_SYMBOL(lua_touserdata)
+EXPORT_SYMBOL(lua_type)
+EXPORT_SYMBOL(lua_typename)
+EXPORT_SYMBOL(lua_upvalueid)
+EXPORT_SYMBOL(lua_upvaluejoin)
+EXPORT_SYMBOL(lua_xmove)
+EXPORT_SYMBOL(lua_yield)
+EXPORT_SYMBOL(luaJIT_profile_dumpstack)
+EXPORT_SYMBOL(luaJIT_profile_start)
+EXPORT_SYMBOL(luaJIT_profile_stop)
+EXPORT_SYMBOL(luaJIT_setmode)
+EXPORT_SYMBOL(luaL_addlstring)
+EXPORT_SYMBOL(luaL_addstring)
+EXPORT_SYMBOL(luaL_addvalue)
+EXPORT_SYMBOL(luaL_argerror)
+EXPORT_SYMBOL(luaL_buffinit)
+EXPORT_SYMBOL(luaL_callmeta)
+EXPORT_SYMBOL(luaL_cdef)
+EXPORT_SYMBOL(luaL_checkany)
+EXPORT_SYMBOL(luaL_checkcdata)
+EXPORT_SYMBOL(luaL_checkint64)
+EXPORT_SYMBOL(luaL_checkinteger)
+EXPORT_SYMBOL(luaL_checklstring)
+EXPORT_SYMBOL(luaL_checknumber)
+EXPORT_SYMBOL(luaL_checkoption)
+EXPORT_SYMBOL(luaL_checkstack)
+EXPORT_SYMBOL(luaL_checktype)
+EXPORT_SYMBOL(luaL_checkudata)
+EXPORT_SYMBOL(luaL_checkuint64)
+EXPORT_SYMBOL(luaL_ctypeid)
+EXPORT_SYMBOL(luaL_error)
+EXPORT_SYMBOL(luaL_execresult)
+EXPORT_SYMBOL(luaL_fileresult)
+EXPORT_SYMBOL(luaL_findtable)
+EXPORT_SYMBOL(luaL_getmetafield)
+EXPORT_SYMBOL(luaL_gsub)
+EXPORT_SYMBOL(luaL_iscallable)
+EXPORT_SYMBOL(luaL_loadbuffer)
+EXPORT_SYMBOL(luaL_loadbufferx)
+EXPORT_SYMBOL(luaL_loadfile)
+EXPORT_SYMBOL(luaL_loadfilex)
+EXPORT_SYMBOL(luaL_loadstring)
+EXPORT_SYMBOL(luaL_newmetatable)
+EXPORT_SYMBOL(luaL_newstate)
+EXPORT_SYMBOL(luaL_openlib)
+EXPORT_SYMBOL(luaL_openlibs)
+EXPORT_SYMBOL(luaL_optinteger)
+EXPORT_SYMBOL(luaL_optlstring)
+EXPORT_SYMBOL(luaL_optnumber)
+EXPORT_SYMBOL(luaL_prepbuffer)
+EXPORT_SYMBOL(luaL_pushcdata)
+EXPORT_SYMBOL(luaL_pushint64)
+EXPORT_SYMBOL(luaL_pushmodule)
+EXPORT_SYMBOL(luaL_pushresult)
+EXPORT_SYMBOL(luaL_pushuint64)
+EXPORT_SYMBOL(luaL_ref)
+EXPORT_SYMBOL(luaL_register)
+EXPORT_SYMBOL(luaL_setcdatagc)
+EXPORT_SYMBOL(luaL_setfuncs)
+EXPORT_SYMBOL(luaL_setmetatable)
+EXPORT_SYMBOL(luaL_testudata)
+EXPORT_SYMBOL(luaL_toint64)
+EXPORT_SYMBOL(luaL_touint64)
+EXPORT_SYMBOL(luaL_traceback)
+EXPORT_SYMBOL(luaL_typerror)
+EXPORT_SYMBOL(luaL_unref)
+EXPORT_SYMBOL(luaL_where)
+EXPORT_SYMBOL(luaopen_base)
+EXPORT_SYMBOL(luaopen_bit)
+EXPORT_SYMBOL(luaopen_debug)
+EXPORT_SYMBOL(luaopen_ffi)
+EXPORT_SYMBOL(luaopen_io)
+EXPORT_SYMBOL(luaopen_jit)
+EXPORT_SYMBOL(luaopen_math)
+EXPORT_SYMBOL(luaopen_os)
+EXPORT_SYMBOL(luaopen_package)
+EXPORT_SYMBOL(luaopen_string)
+EXPORT_SYMBOL(luaopen_table)
+EXPORT_SYMBOL(luaT_call)
+EXPORT_SYMBOL(luaT_checktuple)
+EXPORT_SYMBOL(luaT_cpcall)
+EXPORT_SYMBOL(luaT_error)
+EXPORT_SYMBOL(luaT_istuple)
+EXPORT_SYMBOL(luaT_pushtuple)
+EXPORT_SYMBOL(luaT_state)
+EXPORT_SYMBOL(luaT_tolstring)
+EXPORT_SYMBOL(mp_decode_double)
+EXPORT_SYMBOL(mp_decode_extl)
+EXPORT_SYMBOL(mp_decode_float)
+EXPORT_SYMBOL(mp_encode_decimal)
+EXPORT_SYMBOL(mp_encode_double)
+EXPORT_SYMBOL(mp_encode_float)
+EXPORT_SYMBOL(mp_encode_uuid)
+EXPORT_SYMBOL(mp_sizeof_decimal)
+EXPORT_SYMBOL(mp_sizeof_uuid)
+EXPORT_SYMBOL(password_prepare)
+EXPORT_SYMBOL(PMurHash32)
+EXPORT_SYMBOL(PMurHash32_Process)
+EXPORT_SYMBOL(PMurHash32_Result)
+EXPORT_SYMBOL(port_destroy)
+EXPORT_SYMBOL(random_bytes)
+EXPORT_SYMBOL(_say)
+EXPORT_SYMBOL(say_logrotate)
+EXPORT_SYMBOL(say_set_log_format)
+EXPORT_SYMBOL(say_set_log_level)
+EXPORT_SYMBOL(SHA1internal)
+EXPORT_SYMBOL(space_bsize)
+EXPORT_SYMBOL(space_by_id)
+EXPORT_SYMBOL(space_run_triggers)
+EXPORT_SYMBOL(string_strip_helper)
+EXPORT_SYMBOL(swim_add_member)
+EXPORT_SYMBOL(swim_broadcast)
+EXPORT_SYMBOL(swim_cfg)
+EXPORT_SYMBOL(swim_is_configured)
+EXPORT_SYMBOL(swim_iterator_close)
+EXPORT_SYMBOL(swim_iterator_next)
+EXPORT_SYMBOL(swim_iterator_open)
+EXPORT_SYMBOL(swim_member_by_uuid)
+EXPORT_SYMBOL(swim_member_incarnation)
+EXPORT_SYMBOL(swim_member_is_dropped)
+EXPORT_SYMBOL(swim_member_is_payload_up_to_date)
+EXPORT_SYMBOL(swim_member_payload)
+EXPORT_SYMBOL(swim_member_ref)
+EXPORT_SYMBOL(swim_member_status)
+EXPORT_SYMBOL(swim_member_unref)
+EXPORT_SYMBOL(swim_member_uri)
+EXPORT_SYMBOL(swim_member_uuid)
+EXPORT_SYMBOL(swim_probe_member)
+EXPORT_SYMBOL(swim_quit)
+EXPORT_SYMBOL(swim_remove_member)
+EXPORT_SYMBOL(swim_self)
+EXPORT_SYMBOL(swim_set_codec)
+EXPORT_SYMBOL(swim_set_payload)
+EXPORT_SYMBOL(swim_size)
+EXPORT_SYMBOL(tarantool_exit)
+EXPORT_SYMBOL(tarantool_lua_ibuf)
+EXPORT_SYMBOL(tarantool_lua_slab_cache)
+EXPORT_SYMBOL(tarantool_uptime)
+EXPORT_SYMBOL(title_get)
+EXPORT_SYMBOL(title_get_custom)
+EXPORT_SYMBOL(title_get_interpretor_name)
+EXPORT_SYMBOL(title_get_script_name)
+EXPORT_SYMBOL(title_get_status)
+EXPORT_SYMBOL(title_set_custom)
+EXPORT_SYMBOL(title_set_interpretor_name)
+EXPORT_SYMBOL(title_set_script_name)
+EXPORT_SYMBOL(title_set_status)
+EXPORT_SYMBOL(title_update)
+EXPORT_SYMBOL(tnt_iconv)
+EXPORT_SYMBOL(tnt_iconv_close)
+EXPORT_SYMBOL(tnt_iconv_open)
+EXPORT_SYMBOL(tt_uuid_bswap)
+EXPORT_SYMBOL(tt_uuid_create)
+EXPORT_SYMBOL(tt_uuid_from_string)
+EXPORT_SYMBOL(tt_uuid_is_equal)
+EXPORT_SYMBOL(tt_uuid_is_nil)
+EXPORT_SYMBOL(tt_uuid_str)
+EXPORT_SYMBOL(uri_format)
+EXPORT_SYMBOL(uri_parse)
+EXPORT_SYMBOL(uuid_nil)
+EXPORT_SYMBOL(uuid_unpack)
diff --git a/src/exports.c b/src/exports.c
index 243fdde28..54a4d9946 100644
--- a/src/exports.c
+++ b/src/exports.c
@@ -88,424 +88,25 @@
  */
 
 /**
- * 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).
+ * Non-decorated C symbol is just an address for the linker purposes.
+ * No need to know its definition or even type to get that address.
+ * Even an integer global variable can be referenced as simple
+ * extern void(*)(void).
  */
-#define EXPORT(symbol) do {							\
-	extern void *symbol(void);						\
-	syms[__COUNTER__ - index_base] = symbol;				\
-} while (0)
+#define EXPORT_SYMBOL(symbol)	extern void symbol();
+#include "export-symbols.h"
 
-void
+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);
+#undef EXPORT_SYMBOL
+#define EXPORT_SYMBOL(symbol)	(void*)symbol,
 
-	const int func_count = __COUNTER__ - index_base;
-	for (int i = 0; i < func_count; ++i)
-		((void **(*)(void))syms[i])();
+	static void* syms[] = {
+#include "export-symbols.h"
+	};
+
+	return (void*)syms;
 }
 
-#undef EXPORT
+#undef EXPORT_SYMBOL
diff --git a/src/main.cc b/src/main.cc
index 712c70bc0..15be71aee 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -711,7 +711,7 @@ break_loop(struct trigger *, void *)
 	return 0;
 }
 
-extern "C" void
+extern "C" void*
 export_syms(void);
 
 int

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 2/2] cmake: remove dynamic-list linker option
  2020-04-18 12:39   ` Timur Safin
@ 2020-04-18 16:51     ` Vladislav Shpilevoy
  2020-04-18 22:07       ` Timur Safin
  0 siblings, 1 reply; 16+ messages in thread
From: Vladislav Shpilevoy @ 2020-04-18 16:51 UTC (permalink / raw)
  To: Timur Safin, tarantool-patches

Thanks for the review and the patch!

> : 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
> 
> Should we delete extra/mkexports as well? Which is apparently not needed anymore.

Indeed. Removed:

====================
diff --git a/extra/mkexports b/extra/mkexports
deleted file mode 100755
index 145e5b8ce..000000000
--- a/extra/mkexports
+++ /dev/null
@@ -1,27 +0,0 @@
-#! /bin/sh
-# $1 - in  file
-# $2 - out file
-# $3 - os
-# $4 - export templates
-if [ "x$3x" = xDarwinx ]; then
-    # _func1
-    # _func2
-    sed -e 's/#.*//; /^[[:space:]]*$/d; s/^/_/;' $1 > $2
-else
-    # {
-    #   func1;
-    #   func2;
-    # };
-    echo "$4"
-    ( echo "{" && {
-      # combine static defined list of functions
-      cat $1 ;
-      # with list of exported functions of bundled libraries
-      for so in $4 ; do {
-        # exported names from shared object
-        nm -D $so ||
-        # or follow patch from shared object script
-        nm -D `cat $so | grep GROUP | awk '{print $3}'` ;
-      } | awk '{print $3}' ; done ;
-    } | sed '/^\s*$/d;s/$/;/;' && echo "};" ) > $2
-fi
====================

> : 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 @@
> : +/**
> : + * 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).
> 
> I'd emphasize here the C-symbol aspect, i.e.
> 
> "Non-decorated C symbol is just an address for the linker purposes...

But it is decorated. The decoration is fake, but it is still decorated.
Besides, I don't know about a way to reference a symbol without any
decoration. Nor what it has to do with C. From linker's point of view
there is no C anyway. We can even reference a symbol, which is
implemented not in C, but linked from some static or dynamic library.
It can be implemented in assembly. Or can be a symbol created in a linker
script, without having anything under it.

> : + */
> : +#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(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
> 
> This is very cool! But I'm still confused though (and, eventually, any static checker would be even more confused) - why there is no simple static array or even blatant original ffi_syms[] array as in https://github.com/tarantool/tarantool/commit/4c4c1ccbe422e1420ce0c0b36194fc61bb857ed4#diff-0d537fbabe94394d24abfc403247c75eL67 which would be initialized with these declared symbols? 
> 
> Using volatile integer as and array looks very, very much confusing.  

I didn't want the symbol in a global array. It would occupy memory in .data,
and a global array looks like it is really going to be accessed, even if it
is not.

Volatile variable is to avoid actual usage of the functions, and yet not
remove them. That was an attempt to avoid doing a fake condition of kind
'time(NULL) == 0', like it was done in the old exporting machinery.

> Update - I've just looked into object code generated by compiler, and it's apparently just blatantly ignored all the tricks - leaving no references to all functions mentioned here:

Yeah, I saw that in Travis. Looks like gcc on Linux is 'too smart' in
Release mode. All was fine on Mac, and with clang on Linux.

> (please see U type symbols for undefined, external functions)
> 
> tsafin@M1BOOK6319:~/tarantool1/build-symbols$ nm -a ./src/CMakeFiles/tarantool.dir/exports.c.o
> 0000000000000000 b .bss
> 0000000000000000 n .comment
> 0000000000000000 d .data
> 0000000000000000 N .debug_abbrev
> 0000000000000000 N .debug_aranges
> 0000000000000000 N .debug_info
> 0000000000000000 N .debug_line
> 0000000000000000 N .debug_loc
> 0000000000000000 N .debug_str
> 0000000000000000 r .eh_frame
> 0000000000000000 a exports.c
> 0000000000000000 T export_syms
> 0000000000000000 n .note.GNU-stack
> 0000000000000000 t .text
> 
> There is no undefined symbol to link them against :(
> 
> And here is the disassembly - please see all EXPORT(x) lines thrown out.
> 
> ```
> objdump -dtS -a ./src/CMakeFiles/tarantool.dir/exports.c.o
> ...
> Disassembly of section .text:
> 
> 0000000000000000 <export_syms>:
>         syms[__COUNTER__ - index_base] = symbol;                                \
> } while (0)
> 
> void
> export_syms(void)
> {
>    0:   55                      push   %rbp
>    1:   48 89 e5                mov    %rsp,%rbp
>    4:   41 54                   push   %r12
>    6:   53                      push   %rbx
>    7:   48 83 ec 10             sub    $0x10,%rsp
>         /*
>          * Compiler should think the exported symbols are
>          * reachable. Volatile condition prevents their removal
>          * during optimizations appliance.
>          */
>         volatile int never_true = 0;
>    b:   c7 45 ec 00 00 00 00    movl   $0x0,-0x14(%rbp)
>         if (!never_true)
>   12:   8b 45 ec                mov    -0x14(%rbp),%eax
>   15:   85 c0                   test   %eax,%eax
>   17:   74 18                   je     31 <export_syms+0x31>
>   19:   31 db                   xor    %ebx,%ebx
>   1b:   4c 8d 65 ec             lea    -0x14(%rbp),%r12
>   1f:   90                      nop
>         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])();
>   20:   41 ff 14 dc             callq  *(%r12,%rbx,8)
>   24:   48 83 c3 01             add    $0x1,%rbx
>         for (int i = 0; i < func_count; ++i)
>   28:   48 81 fb 80 01 00 00    cmp    $0x180,%rbx
>   2f:   75 ef                   jne    20 <export_syms+0x20>
> }
>   31:   48 83 c4 10             add    $0x10,%rsp
>   35:   5b                      pop    %rbx
>   36:   41 5c                   pop    %r12
>   38:   5d                      pop    %rbp
>   39:   c3                      retq   
> ```
I managed to fix it like this:

====================
diff --git a/src/exports.c b/src/exports.c
index 243fdde28..7c6b84ef0 100644
--- a/src/exports.c
+++ b/src/exports.c
@@ -93,8 +93,8 @@
  * can be referenced as extern void(*)(void).
  */
 #define EXPORT(symbol) do {							\
-	extern void *symbol(void);						\
-	syms[__COUNTER__ - index_base] = symbol;				\
+	extern void symbol(void);						\
+	symbol();								\
 } while (0)
 
 void
@@ -108,8 +108,6 @@ export_syms(void)
 	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
@@ -502,10 +500,6 @@ export_syms(void)
 	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

====================

But still don't understand why gcc decided that all the exports could
be removed. In the assembly I see that the cycle, calling all the
functions, is not removed. There are still 384 calls. But what does it
call, if all the exports were dropped?

> diff --git a/src/exports.c b/src/exports.c
> index 243fdde28..54a4d9946 100644
> --- a/src/exports.c
> +++ b/src/exports.c
> @@ -88,424 +88,25 @@
>   */
>  
>  /**
> - * 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).
> + * Non-decorated C symbol is just an address for the linker purposes.
> + * No need to know its definition or even type to get that address.
> + * Even an integer global variable can be referenced as simple
> + * extern void(*)(void).
>   */
> -#define EXPORT(symbol) do {							\
> -	extern void *symbol(void);						\
> -	syms[__COUNTER__ - index_base] = symbol;				\
> -} while (0)
> +#define EXPORT_SYMBOL(symbol)	extern void symbol();
> +#include "export-symbols.h"
>  
> -void
> +void*
>  export_syms(void)

The problem here is that the function's result is never used. I am
afraid some smart ass compiler may notice that, since exports.c and
main.cc are built together, and may optimize this call out.

Also return of a value assumes a caller needs to do something with it.
I didn't like that in the Nikolay's solution. I wanted to make a function,
which does all the work by itself.

However I like that all exports are in a separate file, not surrounded
by hacks of exports.c. So I applied your solution with some code
style problems fixed. Thanks for the help.

The patch diff is close to 100%, so below is the whole new patch,
without incremental diff.

====================

    cmake: remove dynamic-list linker option
    
    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

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@.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/extra/mkexports b/extra/mkexports
deleted file mode 100755
index 145e5b8ce..000000000
--- a/extra/mkexports
+++ /dev/null
@@ -1,27 +0,0 @@
-#! /bin/sh
-# $1 - in  file
-# $2 - out file
-# $3 - os
-# $4 - export templates
-if [ "x$3x" = xDarwinx ]; then
-    # _func1
-    # _func2
-    sed -e 's/#.*//; /^[[:space:]]*$/d; s/^/_/;' $1 > $2
-else
-    # {
-    #   func1;
-    #   func2;
-    # };
-    echo "$4"
-    ( echo "{" && {
-      # combine static defined list of functions
-      cat $1 ;
-      # with list of exported functions of bundled libraries
-      for so in $4 ; do {
-        # exported names from shared object
-        nm -D $so ||
-        # or follow patch from shared object script
-        nm -D `cat $so | grep GROUP | awk '{print $3}'` ;
-      } | awk '{print $3}' ; done ;
-    } | sed '/^\s*$/d;s/$/;/;' && echo "};" ) > $2
-fi
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..a3c27143e
--- /dev/null
+++ b/src/exports.c
@@ -0,0 +1,114 @@
+/*
+ * 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 returns it like if the
+ * caller will use them somehow. Call, write by their address, or
+ * anything else.
+ *
+ * In reality the symbols are never touched after export from
+ * 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) extern void symbol(void);
+#include "exports.h"
+#undef EXPORT
+
+void **
+export_syms(void)
+{
+	/*
+	 * Compiler should think the exported symbols are
+	 * reachable. When they are returned as an array, the
+	 * compiler can't assume anything, and can't remove them.
+	 */
+	#define EXPORT(symbol) ((void *)symbol),
+	static void *symbols[] = {
+		#include "exports.h"
+	};
+	#undef EXPORT
+	return symbols;
+}
diff --git a/src/exports.h b/src/exports.h
new file mode 100644
index 000000000..580ec19d2
--- /dev/null
+++ b/src/exports.h
@@ -0,0 +1,392 @@
+/*
+ * 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)
diff --git a/src/main.cc b/src/main.cc
index bb0794dfe..8321acc02 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()

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 1/2] cmake: remove double usage of some source files
  2020-04-18  9:22   ` Timur Safin
@ 2020-04-18 16:51     ` Vladislav Shpilevoy
  0 siblings, 0 replies; 16+ messages in thread
From: Vladislav Shpilevoy @ 2020-04-18 16:51 UTC (permalink / raw)
  To: Timur Safin, tarantool-patches

Hi! Thanks for the review!

> : diff --git a/src/lib/small b/src/lib/small
> : index 3df505017..cebc40574 160000
> : --- a/src/lib/small
> : +++ b/src/lib/small
> : @@ -1 +1 @@
> : -Subproject commit 3df5050171d040bfe5717b4bddf57da3b312ffe4
> : +Subproject commit cebc40574cb68a21dac16c438371392db8f98f66
> 
> Have you intentionally moved small submodule? Is it necessary for this case?

No, that was an accident. Reverted.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 2/2] cmake: remove dynamic-list linker option
  2020-04-18 16:51     ` Vladislav Shpilevoy
@ 2020-04-18 22:07       ` Timur Safin
  0 siblings, 0 replies; 16+ messages in thread
From: Timur Safin @ 2020-04-18 22:07 UTC (permalink / raw)
  To: 'Vladislav Shpilevoy', tarantool-patches

: From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
: Subject: Re: [PATCH v2 2/2] cmake: remove dynamic-list linker option
: 
: Thanks for the review and the patch!
: 
: 
...
: The problem here is that the function's result is never used. I am
: afraid some smart ass compiler may notice that, since exports.c and
: main.cc are built together, and may optimize this call out.

Yup, in theory, LTO should be able to proceed cross-function, intra-module optimizations and figure out that this chains of references is unnecessary. But I still hope that not all external symbols we injected would be deleted with LTO. We will need to recheck with LTO enabled.
 
: 
: Also return of a value assumes a caller needs to do something with it.
: I didn't like that in the Nikolay's solution. I wanted to make a function,
: which does all the work by itself.

Returning anything as value was a simple trick to make compiler think that unused array is used elsewhere. LTO should reveal the truth, unfortunately. 

: 
: However I like that all exports are in a separate file, not surrounded
: by hacks of exports.c. So I applied your solution with some code
: style problems fixed. Thanks for the help.
: 
: The patch diff is close to 100%, so below is the whole new patch,
: without incremental diff.
: 
: ====================
: 
:     cmake: remove dynamic-list linker option
: 
:     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
: 

Despite all the future LTO problems we may see, right now it's

LGTM

Regards,
Timur

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 0/2] Unhide symbols
  2020-04-17 23:48 [Tarantool-patches] [PATCH v2 0/2] Unhide symbols Vladislav Shpilevoy
  2020-04-17 23:48 ` [Tarantool-patches] [PATCH v2 1/2] cmake: remove double usage of some source files Vladislav Shpilevoy
  2020-04-17 23:48 ` [Tarantool-patches] [PATCH v2 2/2] cmake: remove dynamic-list linker option Vladislav Shpilevoy
@ 2020-04-22 22:08 ` Vladislav Shpilevoy
  2020-04-22 23:27   ` Timur Safin
  2020-04-27 10:44 ` Timur Safin
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 16+ messages in thread
From: Vladislav Shpilevoy @ 2020-04-22 22:08 UTC (permalink / raw)
  To: tarantool-patches, tsafin

What do we do now? When the issue is moved to a next milestone.
Do we proceed with this version?

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 0/2] Unhide symbols
  2020-04-22 22:08 ` [Tarantool-patches] [PATCH v2 0/2] Unhide symbols Vladislav Shpilevoy
@ 2020-04-22 23:27   ` Timur Safin
  2020-04-24  7:47     ` Kirill Yukhin
  0 siblings, 1 reply; 16+ messages in thread
From: Timur Safin @ 2020-04-22 23:27 UTC (permalink / raw)
  To: 'Vladislav Shpilevoy', tarantool-patches, Kirill Yukhin

I'd go with this version. Releases have been published - so we are ok to try to break something small in the next release. :)

Kirill?

Timur

: -----Original Message-----
: From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
: Sent: Thursday, April 23, 2020 1:08 AM
: To: tarantool-patches@dev.tarantool.org; tsafin@tarantool.org
: Subject: Re: [Tarantool-patches] [PATCH v2 0/2] Unhide symbols
: 
: What do we do now? When the issue is moved to a next milestone.
: Do we proceed with this version?

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 0/2] Unhide symbols
  2020-04-22 23:27   ` Timur Safin
@ 2020-04-24  7:47     ` Kirill Yukhin
  0 siblings, 0 replies; 16+ messages in thread
From: Kirill Yukhin @ 2020-04-24  7:47 UTC (permalink / raw)
  To: Timur Safin; +Cc: tarantool-patches, 'Vladislav Shpilevoy'

Hello,

On 23 апр 02:27, Timur Safin wrote:
> I'd go with this version. Releases have been published - so we are ok to try to break something small in the next release. :)

I think so.

--
Regards, Kirill Yukhin

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 0/2] Unhide symbols
  2020-04-17 23:48 [Tarantool-patches] [PATCH v2 0/2] Unhide symbols Vladislav Shpilevoy
                   ` (2 preceding siblings ...)
  2020-04-22 22:08 ` [Tarantool-patches] [PATCH v2 0/2] Unhide symbols Vladislav Shpilevoy
@ 2020-04-27 10:44 ` Timur Safin
  2020-04-27 21:38   ` Vladislav Shpilevoy
  2020-04-27 22:58   ` Vladislav Shpilevoy
  2020-05-18 21:32 ` Vladislav Shpilevoy
  2020-05-19  9:02 ` Kirill Yukhin
  5 siblings, 2 replies; 16+ messages in thread
From: Timur Safin @ 2020-04-27 10:44 UTC (permalink / raw)
  To: Vladislav Shpilevoy; +Cc: tarantool-patches

[-- Attachment #1: Type: text/plain, Size: 1989 bytes --]


FWIW — we may commit this patch, but it was failing CI testing some time ago  https://gitlab.com/tarantool/tarantool/pipelines/137481384  Do we have a procedure for rerunning it somehow easily?
 
Timur 
  
>Суббота, 18 апреля 2020, 2:48 +03:00 от Vladislav Shpilevoy <v.shpilevoy@tarantool.org>:
> 
>The patchset makes Tarantool stop hiding not explicitly exported
>symbols.
>
>It means, all FFI and public C API related symbols are still
>always exported. All the other symbols may be exported, or may be
>not.
>
>That feature was requested solely by Mons.
>
>To make the needed symbols visible the hack with function
>addresses was returned back, like it was before
>https://github.com/tarantool/tarantool/commit/4c4c1ccbe422e1420ce0c0b36194fc61bb857ed4 ,
>but with 0 dependencies in the export file.
>
>Branch:  http://github.com/tarantool/tarantool/tree/gerold103/gh-2971-symbols-v2
>Issue:  https://github.com/tarantool/tarantool/issues/2971
>
>@ChangeLog
>- Symbols of tarantool executable are not masked anymore. Some
>  private symbols may become visible and available for FFI and
>  dlopen() + dlsym() (gh-2971).
>
>Changes in v2:
>- All exports are moved to one file for simplicity.
>
>Vladislav Shpilevoy (2):
>  cmake: remove double usage of some source files
>  cmake: remove dynamic-list linker option
>
> .gitignore | 1 -
> extra/exports | 404 ----------------
> src/CMakeLists.txt | 57 +--
> src/box/CMakeLists.txt | 7 +-
> src/exports.c | 511 ++++++++++++++++++++
> src/lib/small | 2 +-
> src/main.cc | 5 +
> test/box/gh-2971-symbol-visibility.result | 22 +
> test/box/gh-2971-symbol-visibility.test.lua | 14 +
> 9 files changed, 563 insertions(+), 460 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
>
>--
>2.21.1 (Apple Git-122.3)
>  
 
 
--
Timur Safin
 

[-- Attachment #2: Type: text/html, Size: 3027 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 0/2] Unhide symbols
  2020-04-27 10:44 ` Timur Safin
@ 2020-04-27 21:38   ` Vladislav Shpilevoy
  2020-04-27 22:58   ` Vladislav Shpilevoy
  1 sibling, 0 replies; 16+ messages in thread
From: Vladislav Shpilevoy @ 2020-04-27 21:38 UTC (permalink / raw)
  To: Timur Safin; +Cc: tarantool-patches

On 27/04/2020 12:44, Timur Safin wrote:
> FWIW — we may commit this patch, but it was failing CI testing some time ago https://gitlab.com/tarantool/tarantool/pipelines/137481384 Do we have a procedure for rerunning it somehow easily?

Looks like we can't commit. The build fails on freebsd with some symbols
not exported. It means, the current patch does not work everywhere.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 0/2] Unhide symbols
  2020-04-27 10:44 ` Timur Safin
  2020-04-27 21:38   ` Vladislav Shpilevoy
@ 2020-04-27 22:58   ` Vladislav Shpilevoy
  1 sibling, 0 replies; 16+ messages in thread
From: Vladislav Shpilevoy @ 2020-04-27 22:58 UTC (permalink / raw)
  To: Timur Safin; +Cc: tarantool-patches

I managed to find a workaround. I took it from the old
version of the CMake file here:
https://github.com/tarantool/tarantool/commit/6a75d0b0c086dac7c0c46a9d80fcccd2f99958f0

Diff:

====================
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 64f0198db..7a718fde9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -254,4 +254,11 @@ add_executable(
 add_dependencies(tarantool build_bundled_libs sql)
 target_link_libraries(tarantool box ${common_libraries})
 
+if (TARGET_OS_FREEBSD AND NOT TARGET_OS_DEBIAN_FREEBSD)
+    # Without rdynamic FreeBSD does not export some symbols even
+    # when they are used in the final executable and their
+    # addresses are accessed explicitly.
+    set_target_properties(tarantool PROPERTIES LINK_FLAGS "-rdynamic")
+endif()
+
 install (TARGETS tarantool DESTINATION bin)

====================

However I don't know why it helped. Tried to install FreeBSD in VirtualBox,
but it just crashed after installation and an attempt to install git.

Now tests pass (after several reruns, because there are many flaky tests).

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 0/2] Unhide symbols
  2020-04-17 23:48 [Tarantool-patches] [PATCH v2 0/2] Unhide symbols Vladislav Shpilevoy
                   ` (3 preceding siblings ...)
  2020-04-27 10:44 ` Timur Safin
@ 2020-05-18 21:32 ` Vladislav Shpilevoy
  2020-05-19  9:02 ` Kirill Yukhin
  5 siblings, 0 replies; 16+ messages in thread
From: Vladislav Shpilevoy @ 2020-05-18 21:32 UTC (permalink / raw)
  To: tarantool-patches, Kirill Yukhin

I rebased the branch on master.

(gerold103/gh-2971-symbols-v2)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Tarantool-patches] [PATCH v2 0/2] Unhide symbols
  2020-04-17 23:48 [Tarantool-patches] [PATCH v2 0/2] Unhide symbols Vladislav Shpilevoy
                   ` (4 preceding siblings ...)
  2020-05-18 21:32 ` Vladislav Shpilevoy
@ 2020-05-19  9:02 ` Kirill Yukhin
  5 siblings, 0 replies; 16+ messages in thread
From: Kirill Yukhin @ 2020-05-19  9:02 UTC (permalink / raw)
  To: Vladislav Shpilevoy; +Cc: tarantool-patches

Hello,

On 18 апр 01:48, Vladislav Shpilevoy wrote:
> The patchset makes Tarantool stop hiding not explicitly exported
> symbols.

I've checked your patchset into master.

--
Regards, Kirill Yukhin

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2020-05-19  9:02 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-17 23:48 [Tarantool-patches] [PATCH v2 0/2] Unhide symbols Vladislav Shpilevoy
2020-04-17 23:48 ` [Tarantool-patches] [PATCH v2 1/2] cmake: remove double usage of some source files Vladislav Shpilevoy
2020-04-18  9:22   ` Timur Safin
2020-04-18 16:51     ` Vladislav Shpilevoy
2020-04-17 23:48 ` [Tarantool-patches] [PATCH v2 2/2] cmake: remove dynamic-list linker option Vladislav Shpilevoy
2020-04-18 12:39   ` Timur Safin
2020-04-18 16:51     ` Vladislav Shpilevoy
2020-04-18 22:07       ` Timur Safin
2020-04-22 22:08 ` [Tarantool-patches] [PATCH v2 0/2] Unhide symbols Vladislav Shpilevoy
2020-04-22 23:27   ` Timur Safin
2020-04-24  7:47     ` Kirill Yukhin
2020-04-27 10:44 ` Timur Safin
2020-04-27 21:38   ` Vladislav Shpilevoy
2020-04-27 22:58   ` Vladislav Shpilevoy
2020-05-18 21:32 ` Vladislav Shpilevoy
2020-05-19  9:02 ` Kirill Yukhin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox