Skip to content

Commit af2d371

Browse files
committed
Makefile: add option to build kernel with most symbols hidden
This patch adds new build configuration option - conf_hide_symbols - that allows to build OSv kernel with all non-glibc symbols hidden when enabled (set to 1). By default the conf_hide_symbols is set to disabled so the kernel is still built with all symbols exported. In order to build kernel with most symbols hidden, one can use following command: ``` ./scripts/build image=native-example fs=rofs conf_hide_symbols=1 -j$(nproc) ``` The main idea behind the changes to the makefile below, is to compile all source files except the ones under musl/ and libc/ directories with the special compiler flags - '-fvisibility=hidden' and '-fvisibility-inlines-hidden' (C++ only) if conf_hide_symbols is enabled. This makes the symbols in all those relevant files as hidden except the ones annotated with OSV_***_API macros to expose them as public. On other hand, the musl sources come with its own symbol visibility mechanism where the symbols to be hidden are annotated with the 'hidden' macro and everything else is public. Therefore we do not need to compile the musl files with the visibility flags. Same goes for the files under libc/ that originate from musl. Lastly, the C++ files under libc/ that have been written from scratch to provide parts of glibc API (like libc/pthread.cc) are compiled with the compatibility flags. They are part of the libc_to_hide set. Also depending on conf_hide_symbols, the makefile uses different linker flags to link the standard C++ and others fully or not. Relatedly, when conf_hide_symbols is enabled, the OSv dynamic linker (core/elf.cc) does not advertise libstdc++.so.6 anymore. The symbol hiding mechanism enabled with conf_hide_symbols is powerful enough to hide most non-glibc symbols and leaves under 1,700 symbols exported including some vtable and typeinfo left C++ ones which is ~10% of the original number. The remaining C++ symbols will be removed from symbols table once we enable version script when linking in future patches. With conf_hide_symbols on, the resulting kernel-stripped.elf is ~ 5.1 MB in size, down from 6.7 MB, mainly due to libstdc++.a not linked fully. Once we enable linker garbage collection, the size should go down even more. Please note that the kernel with hidden symbols does not support building ZFS images as some of the symbols libzfs.so, zfs.so and zpool.so depend on are no longer visible. To fix this we will probably need to change how this apps are linked so they do not depend on those symbols exported by kernel. In addition around 35 unit tests cannot run on the kernel with most hidden symbols as they directly use OSv internal symbols. Finally most OSv apps and modules like httpserver.so rely on OSv specific API symbols and they will not work either. To address this, we will need to expose some of the OSv C++ API as C. It is not clear if this patch fully addresses the issue #97. We could however close it and open smaller ones to address remaining gaps. Refs #97 Signed-off-by: Waldemar Kozaczuk <[email protected]>
1 parent 9e8451f commit af2d371

File tree

4 files changed

+76
-17
lines changed

4 files changed

+76
-17
lines changed

Makefile

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,12 @@ $(out)/bsd/%.o: source-dialects =
279279
$(out)/libc/%.o: source-dialects =
280280
$(out)/musl/%.o: source-dialects =
281281

282-
kernel-defines = -D_KERNEL $(source-dialects)
282+
# do not hide symbols in musl/libc because it has it's own hiding mechanism
283+
$(out)/libc/%.o: cc-hide-flags =
284+
$(out)/libc/%.o: cxx-hide-flags =
285+
$(out)/musl/%.o: cc-hide-flags =
286+
287+
kernel-defines = -D_KERNEL $(source-dialects) $(cc-hide-flags)
283288

284289
# This play the same role as "_KERNEL", but _KERNEL unfortunately is too
285290
# overloaded. A lot of files will expect it to be set no matter what, specially
@@ -310,9 +315,17 @@ tracing-flags-0 =
310315
tracing-flags-1 = -finstrument-functions -finstrument-functions-exclude-file-list=c++,trace.cc,trace.hh,align.hh,mmintrin.h
311316
tracing-flags = $(tracing-flags-$(conf-tracing))
312317

318+
cc-hide-flags-0 =
319+
cc-hide-flags-1 = -fvisibility=hidden
320+
cc-hide-flags = $(cc-hide-flags-$(conf_hide_symbols))
321+
322+
cxx-hide-flags-0 =
323+
cxx-hide-flags-1 = -fvisibility-inlines-hidden
324+
cxx-hide-flags = $(cxx-hide-flags-$(conf_hide_symbols))
325+
313326
gcc-opt-Og := $(call compiler-flag, -Og, -Og, compiler/empty.cc)
314327

315-
CXXFLAGS = -std=gnu++11 $(COMMON)
328+
CXXFLAGS = -std=gnu++11 $(COMMON) $(cxx-hide-flags)
316329
CFLAGS = -std=gnu99 $(COMMON)
317330

318331
# should be limited to files under libc/ eventually
@@ -794,6 +807,7 @@ drivers += drivers/clock-common.o
794807
drivers += drivers/clockevent.o
795808
drivers += drivers/isa-serial-base.o
796809
drivers += core/elf.o
810+
$(out)/core/elf.o: CXXFLAGS += -DHIDE_SYMBOLS=$(conf_hide_symbols)
797811
drivers += drivers/random.o
798812
drivers += drivers/zfs.o
799813
drivers += drivers/null.o
@@ -949,6 +963,7 @@ objects += core/options.o
949963

950964
#include $(src)/libc/build.mk:
951965
libc =
966+
libc_to_hide =
952967
musl =
953968
environ_libc =
954969
environ_musl =
@@ -960,6 +975,7 @@ musl_arch = aarch64
960975
endif
961976

962977
libc += internal/_chk_fail.o
978+
libc_to_hide += internal/_chk_fail.o
963979
libc += internal/floatscan.o
964980
libc += internal/intscan.o
965981
libc += internal/libc.o
@@ -1029,6 +1045,7 @@ libc += errno/strerror.o
10291045

10301046
musl += locale/catclose.o
10311047
musl += locale/__mo_lookup.o
1048+
$(out)/musl/src/locale/__mo_lookup.o: CFLAGS += $(cc-hide-flags-$(conf_hide_symbols))
10321049
musl += locale/pleval.o
10331050
musl += locale/catgets.o
10341051
libc += locale/catopen.o
@@ -1316,13 +1333,16 @@ musl += misc/ffsll.o
13161333
musl += misc/get_current_dir_name.o
13171334
libc += misc/gethostid.o
13181335
libc += misc/getopt.o
1336+
libc_to_hide += misc/getopt.o
13191337
libc += misc/getopt_long.o
1338+
libc_to_hide += misc/getopt_long.o
13201339
musl += misc/getsubopt.o
13211340
libc += misc/realpath.o
13221341
libc += misc/backtrace.o
13231342
libc += misc/uname.o
13241343
libc += misc/lockf.o
13251344
libc += misc/mntent.o
1345+
libc_to_hide += misc/mntent.o
13261346
musl += misc/nftw.o
13271347
libc += misc/__longjmp_chk.o
13281348

@@ -1360,7 +1380,7 @@ musl += network/gethostbyaddr_r.o
13601380
musl += network/gethostbyaddr.o
13611381
musl += network/resolvconf.o
13621382
musl += network/res_msend.o
1363-
$(out)/musl/src/network/res_msend.o: CFLAGS += -Wno-maybe-uninitialized --include libc/syscall_to_function.h --include libc/internal/pthread_stubs.h
1383+
$(out)/musl/src/network/res_msend.o: CFLAGS += -Wno-maybe-uninitialized --include libc/syscall_to_function.h --include libc/internal/pthread_stubs.h $(cc-hide-flags-$(conf_hide_symbols))
13641384
$(out)/libc/multibyte/mbsrtowcs.o: CFLAGS += -Imusl/src/multibyte
13651385
musl += network/lookup_ipliteral.o
13661386
libc += network/getaddrinfo.o
@@ -1374,7 +1394,9 @@ musl += network/lookup_name.o
13741394
musl += network/lookup_serv.o
13751395
libc += network/getnameinfo.o
13761396
libc += network/__dns.o
1397+
libc_to_hide += network/__dns.o
13771398
libc += network/__ipparse.o
1399+
libc_to_hide += network/__ipparse.o
13781400
musl += network/inet_addr.o
13791401
musl += network/inet_aton.o
13801402
musl += network/inet_pton.o
@@ -1423,6 +1445,7 @@ ifeq ($(arch),x64)
14231445
libc += arch/$(arch)/ucontext/getcontext.o
14241446
libc += arch/$(arch)/ucontext/setcontext.o
14251447
libc += arch/$(arch)/ucontext/start_context.o
1448+
libc_to_hide += arch/$(arch)/ucontext/start_context.o
14261449
libc += arch/$(arch)/ucontext/ucontext.o
14271450
libc += string/memmove.o
14281451
endif
@@ -1590,11 +1613,13 @@ musl += string/memccpy.o
15901613
musl += string/memchr.o
15911614
musl += string/memcmp.o
15921615
libc += string/memcpy.o
1616+
libc_to_hide += string/memcpy.o
15931617
musl += string/memmem.o
15941618
musl += string/mempcpy.o
15951619
musl += string/memrchr.o
15961620
libc += string/__memmove_chk.o
15971621
libc += string/memset.o
1622+
libc_to_hide += string/memset.o
15981623
libc += string/__memset_chk.o
15991624
libc += string/rawmemchr.o
16001625
musl += string/rindex.o
@@ -1628,6 +1653,7 @@ musl += string/strpbrk.o
16281653
musl += string/strrchr.o
16291654
musl += string/strsep.o
16301655
libc += string/stresep.o
1656+
libc_to_hide += string/stresep.o
16311657
musl += string/strsignal.o
16321658
musl += string/strspn.o
16331659
musl += string/strstr.o
@@ -1727,21 +1753,31 @@ musl += regex/tre-mem.o
17271753
$(out)/musl/src/regex/tre-mem.o: CFLAGS += -UNDEBUG
17281754

17291755
libc += pthread.o
1756+
libc_to_hide += pthread.o
17301757
libc += pthread_barrier.o
17311758
libc += libc.o
17321759
libc += dlfcn.o
17331760
libc += time.o
1761+
libc_to_hide += time.o
17341762
libc += signal.o
1763+
libc_to_hide += signal.o
17351764
libc += mman.o
1765+
libc_to_hide += mman.o
17361766
libc += sem.o
1767+
libc_to_hide += sem.o
17371768
libc += pipe_buffer.o
1769+
libc_to_hide += pipe_buffer.o
17381770
libc += pipe.o
1771+
libc_to_hide += pipe.o
17391772
libc += af_local.o
1773+
libc_to_hide += af_local.o
17401774
libc += user.o
17411775
libc += resource.o
17421776
libc += mount.o
17431777
libc += eventfd.o
1778+
libc_to_hide += eventfd.o
17441779
libc += timerfd.o
1780+
libc_to_hide += timerfd.o
17451781
libc += shm.o
17461782
libc += inotify.o
17471783
libc += __pread64_chk.o
@@ -1814,6 +1850,10 @@ objects += $(addprefix fs/, $(fs_objs))
18141850
objects += $(addprefix libc/, $(libc))
18151851
objects += $(addprefix musl/src/, $(musl))
18161852

1853+
libc_objects_to_hide = $(addprefix $(out)/libc/, $(libc_to_hide))
1854+
$(libc_objects_to_hide): cc-hide-flags = $(cc-hide-flags-$(conf_hide_symbols))
1855+
$(libc_objects_to_hide): cxx-hide-flags = $(cxx-hide-flags-$(conf_hide_symbols))
1856+
18171857
libstdc++.a := $(shell $(CXX) -print-file-name=libstdc++.a)
18181858
ifeq ($(filter /%,$(libstdc++.a)),)
18191859
ifeq ($(arch),aarch64)
@@ -1914,15 +1954,18 @@ $(loader_options_dep): stage1
19141954
echo -n "APP_LOCAL_EXEC_TLS_SIZE = $(app_local_exec_tls_size);" > $(loader_options_dep) ; \
19151955
fi
19161956

1957+
ifeq ($(conf_hide_symbols),1)
1958+
linker_archives_options = --no-whole-archive $(libstdc++.a) $(libgcc.a) $(libgcc_eh.a) $(boost-libs) --exclude-libs libstdc++.a
1959+
else
1960+
linker_archives_options = --whole-archive $(libstdc++.a) $(libgcc_eh.a) $(boost-libs) --no-whole-archive $(libgcc.a)
1961+
endif
1962+
19171963
$(out)/loader.elf: $(stage1_targets) arch/$(arch)/loader.ld $(out)/bootfs.o $(loader_options_dep)
19181964
$(call quiet, $(LD) -o $@ --defsym=OSV_KERNEL_BASE=$(kernel_base) \
19191965
--defsym=OSV_KERNEL_VM_BASE=$(kernel_vm_base) --defsym=OSV_KERNEL_VM_SHIFT=$(kernel_vm_shift) \
19201966
-Bdynamic --export-dynamic --eh-frame-hdr --enable-new-dtags -L$(out)/arch/$(arch) \
19211967
$(^:%.ld=-T %.ld) \
1922-
--whole-archive \
1923-
$(libstdc++.a) $(libgcc_eh.a) \
1924-
$(boost-libs) \
1925-
--no-whole-archive $(libgcc.a), \
1968+
$(linker_archives_options), \
19261969
LINK loader.elf)
19271970
@# Build libosv.so matching this loader.elf. This is not a separate
19281971
@# rule because that caused bug #545.
@@ -1935,10 +1978,7 @@ $(out)/kernel.elf: $(stage1_targets) arch/$(arch)/loader.ld $(out)/empty_bootfs.
19351978
--defsym=OSV_KERNEL_VM_BASE=$(kernel_vm_base) --defsym=OSV_KERNEL_VM_SHIFT=$(kernel_vm_shift) \
19361979
-Bdynamic --export-dynamic --eh-frame-hdr --enable-new-dtags -L$(out)/arch/$(arch) \
19371980
$(^:%.ld=-T %.ld) \
1938-
--whole-archive \
1939-
$(libstdc++.a) $(libgcc_eh.a) \
1940-
$(boost-libs) \
1941-
--no-whole-archive $(libgcc.a), \
1981+
$(linker_archives_options), \
19421982
LINK kernel.elf)
19431983
$(call quiet, $(STRIP) $(out)/kernel.elf -o $(out)/kernel-stripped.elf, STRIP kernel.elf -> kernel-stripped.elf )
19441984
$(call very-quiet, cp $(out)/kernel-stripped.elf $(out)/kernel.elf)

conf/base.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ conf-logger_debug=0
1111
conf-DEBUG_BUILD=0
1212

1313
conf-debug_elf=0
14+
conf_hide_symbols=0

core/elf.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,19 +1315,25 @@ program::program(void* addr)
13151315
// this library, it will not be visible for the application and
13161316
// it will need to load its own version of this library.
13171317
#if BOOST_VERSION < 106900
1318+
#if HIDE_SYMBOLS < 1
13181319
"libboost_system.so.1.55.0",
13191320
#endif
1321+
#endif
13201322
#endif /* __x86_64__ */
13211323
#ifdef __aarch64__
13221324
"ld-linux-aarch64.so.1",
13231325
#if BOOST_VERSION < 106900
1326+
#if HIDE_SYMBOLS < 1
13241327
"libboost_system-mt.so.1.55.0",
13251328
#endif
1329+
#endif
13261330
#endif /* __aarch64__ */
13271331
"libpthread.so.0",
13281332
"libdl.so.2",
13291333
"librt.so.1",
1334+
#if HIDE_SYMBOLS < 1
13301335
"libstdc++.so.6",
1336+
#endif
13311337
"libaio.so.1",
13321338
"libxenstore.so.3.0",
13331339
"libcrypt.so.1",

scripts/manifest_from_host.sh

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,15 @@ output_manifest()
6868
echo "# --------------------" | tee -a $OUTPUT
6969
echo "# Dependencies" | tee -a $OUTPUT
7070
echo "# --------------------" | tee -a $OUTPUT
71-
lddtree $so_path | grep -v "not found" | grep -v "$so_path" | grep -v "ld-linux-${MACHINE}" | \
72-
grep -Pv 'lib(gcc_s|resolv|c|m|pthread|dl|rt|stdc\+\+|aio|xenstore|crypt|selinux)\.so([\d.]+)?' | \
73-
sed 's/ =>/:/' | sed 's/^\s*lib/\/usr\/lib\/lib/' | sort | uniq | tee -a $OUTPUT
71+
if [[ $conf_hide_symbols == 1 ]]; then
72+
lddtree $so_path | grep -v "not found" | grep -v "$so_path" | grep -v "ld-linux-${MACHINE}" | \
73+
grep -Pv 'lib(gcc_s|resolv|c|m|pthread|dl|rt|aio|xenstore|crypt|selinux)\.so([\d.]+)?' | \
74+
sed 's/ =>/:/' | sed 's/^\s*lib/\/usr\/lib\/lib/' | sort | uniq | tee -a $OUTPUT
75+
else
76+
lddtree $so_path | grep -v "not found" | grep -v "$so_path" | grep -v "ld-linux-${MACHINE}" | \
77+
grep -Pv 'lib(gcc_s|resolv|c|m|pthread|dl|rt|stdc\+\+|aio|xenstore|crypt|selinux)\.so([\d.]+)?' | \
78+
sed 's/ =>/:/' | sed 's/^\s*lib/\/usr\/lib\/lib/' | sort | uniq | tee -a $OUTPUT
79+
fi
7480
}
7581

7682
detect_elf()
@@ -144,9 +150,15 @@ if [[ -d $NAME_OR_PATH ]]; then
144150
echo "# --------------------" | tee -a $OUTPUT
145151
echo "# Dependencies" | tee -a $OUTPUT
146152
echo "# --------------------" | tee -a $OUTPUT
147-
lddtree $SO_FILES | grep -v "not found" | grep -v "$NAME_OR_PATH/$SUBDIRECTORY_PATH" | grep -v "ld-linux-${MACHINE}" | \
148-
grep -Pv 'lib(gcc_s|resolv|c|m|pthread|dl|rt|stdc\+\+|aio|xenstore|crypt|selinux)\.so([\d.]+)?' | \
149-
sed 's/ =>/:/' | sed 's/^\s*lib/\/usr\/lib\/lib/' | sort | uniq | tee -a $OUTPUT
153+
if [[ $conf_hide_symbols == 1 ]]; then
154+
lddtree $SO_FILES | grep -v "not found" | grep -v "$NAME_OR_PATH/$SUBDIRECTORY_PATH" | grep -v "ld-linux-${MACHINE}" | \
155+
grep -Pv 'lib(gcc_s|resolv|c|m|pthread|dl|rt|aio|xenstore|crypt|selinux)\.so([\d.]+)?' | \
156+
sed 's/ =>/:/' | sed 's/^\s*lib/\/usr\/lib\/lib/' | sort | uniq | tee -a $OUTPUT
157+
else
158+
lddtree $SO_FILES | grep -v "not found" | grep -v "$NAME_OR_PATH/$SUBDIRECTORY_PATH" | grep -v "ld-linux-${MACHINE}" | \
159+
grep -Pv 'lib(gcc_s|resolv|c|m|pthread|dl|rt|stdc\+\+|aio|xenstore|crypt|selinux)\.so([\d.]+)?' | \
160+
sed 's/ =>/:/' | sed 's/^\s*lib/\/usr\/lib\/lib/' | sort | uniq | tee -a $OUTPUT
161+
fi
150162
fi
151163
exit 0
152164
fi

0 commit comments

Comments
 (0)