There are some comments embedded and bonus patch at the end, please not miss it... : From: Vladislav Shpilevoy : ... : 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 ``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 : + * 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 : 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 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 } 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