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

Timur Safin tsafin at tarantool.org
Sat Apr 18 15:39:54 MSK 2020


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

: From: Vladislav Shpilevoy <v.shpilevoy at 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 at .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 at 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 at 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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: export-symbol-subpatch.patch
Type: application/octet-stream
Size: 24672 bytes
Desc: not available
URL: <https://lists.tarantool.org/pipermail/tarantool-patches/attachments/20200418/9f7033d7/attachment.obj>


More information about the Tarantool-patches mailing list