liblzma: #define lzma_attr_visibility_hidden in common.h.
In ELF shared libs: -fvisibility=hidden affects definitions of symbols but not declarations.[*] This doesn't affect direct calls to functions inside liblzma as a linker can replace a call to lzma_foo@plt with a call directly to lzma_foo when -fvisibility=hidden is used. [*] It has to be like this because otherwise every installed header file would need to explictly set the symbol visibility to default. When accessing extern variables that aren't defined in the same translation unit, compiler assumes that the variable has the default visibility and thus indirection is needed. Unlike function calls, linker cannot optimize this. Using __attribute__((__visibility__("hidden"))) with the extern variable declarations tells the compiler that indirection isn't needed because the definition is in the same shared library. About 15+ years ago, someone told me that it would be good if the CRC tables would be defined in the same translation unit as the C code of the CRC functions. While I understood that it could help a tiny amount, I didn't want to change the code because a separate translation unit for the CRC tables was needed for the x86 assembly code anyway. But when visibility attributes are supported, simply marking the extern declaration with the hidden attribute will get identical result. When there are only a few affected variables, this is trivial to do. I wish I had understood this back then already.
This commit is contained in:
parent
2c7ee92e44
commit
a2f5ca706a
|
@ -17,17 +17,28 @@
|
||||||
#include "mythread.h"
|
#include "mythread.h"
|
||||||
#include "tuklib_integer.h"
|
#include "tuklib_integer.h"
|
||||||
|
|
||||||
|
// LZMA_API_EXPORT is used to mark the exported API functions.
|
||||||
|
// It's used to define the LZMA_API macro.
|
||||||
|
//
|
||||||
|
// lzma_attr_visibility_hidden is used for marking *declarations* of extern
|
||||||
|
// variables that are internal to liblzma (-fvisibility=hidden alone is
|
||||||
|
// enough to hide the *definitions*). Such markings allow slightly more
|
||||||
|
// efficient code to accesses those variables in ELF shared libraries.
|
||||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||||
# ifdef DLL_EXPORT
|
# ifdef DLL_EXPORT
|
||||||
# define LZMA_API_EXPORT __declspec(dllexport)
|
# define LZMA_API_EXPORT __declspec(dllexport)
|
||||||
# else
|
# else
|
||||||
# define LZMA_API_EXPORT
|
# define LZMA_API_EXPORT
|
||||||
# endif
|
# endif
|
||||||
|
# define lzma_attr_visibility_hidden
|
||||||
// Don't use ifdef or defined() below.
|
// Don't use ifdef or defined() below.
|
||||||
#elif HAVE_VISIBILITY
|
#elif HAVE_VISIBILITY
|
||||||
# define LZMA_API_EXPORT __attribute__((__visibility__("default")))
|
# define LZMA_API_EXPORT __attribute__((__visibility__("default")))
|
||||||
|
# define lzma_attr_visibility_hidden \
|
||||||
|
__attribute__((__visibility__("hidden")))
|
||||||
#else
|
#else
|
||||||
# define LZMA_API_EXPORT
|
# define LZMA_API_EXPORT
|
||||||
|
# define lzma_attr_visibility_hidden
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LZMA_API(type) LZMA_API_EXPORT type LZMA_API_CALL
|
#define LZMA_API(type) LZMA_API_EXPORT type LZMA_API_CALL
|
||||||
|
|
Loading…
Reference in New Issue