On my Ubuntu 20.04 applying the patch, I am attaching below, shrinks the 
kernel.elf from 6.8MB down to 5MB (on Fedora 32 from 6.7MB down to 5MB, and 
older Ubuntu 19.04 [gcc 8.3] from 6.2MB down to 4.9MB). And this is before 
applying any GCC optimizations I was suggesting in 
https://groups.google.com/forum/#!topic/osv-dev/hCYGRzytaJ4 and 
modularization ideas in 
https://groups.google.com/forum/#!topic/osv-dev/BHwN6Stm3n4) (except hiding 
C++ library).

diff --git a/Makefile b/Makefile
index 20ddf3b1..8caac77b 100644
--- a/Makefile
+++ b/Makefile
@@ -1873,10 +1873,11 @@ $(out)/kernel.elf: $(stage1_targets) 
arch/$(arch)/loader.ld $(out)/empty_bootfs.
      --defsym=OSV_KERNEL_VM_BASE=$(kernel_vm_base) 
--defsym=OSV_KERNEL_VM_SHIFT=$(kernel_vm_shift) \
  -Bdynamic --export-dynamic --eh-frame-hdr --enable-new-dtags 
-L$(out)/arch/$(arch) \
      $(^:%.ld=-T %.ld) \
+     --version-script=/tmp/version_script \
      --whole-archive \
-       $(libstdc++.a) $(libgcc_eh.a) \
+       $(libgcc_eh.a) \
        $(boost-libs) \
-     --no-whole-archive $(libgcc.a), \
+     --no-whole-archive $(libstdc++.a) $(libgcc.a), \
  LINK kernel.elf)
  $(call quiet, $(STRIP) $(out)/kernel.elf -o $(out)/kernel-stripped.elf, 
STRIP kernel.elf -> kernel-stripped.elf )
  $(call very-quiet, cp $(out)/kernel-stripped.elf $(out)/kernel.elf)
diff --git a/core/elf.cc b/core/elf.cc
index ffb16004..830b2577 100644
--- a/core/elf.cc
+++ b/core/elf.cc
@@ -1310,7 +1310,6 @@ program::program(void* addr)
           "libpthread.so.0",
           "libdl.so.2",
           "librt.so.1",
-          "libstdc++.so.6",
           "libaio.so.1",
           "libxenstore.so.3.0",
           "libcrypt.so.1",
diff --git a/scripts/generate_version_script.sh 
b/scripts/generate_version_script.sh
new file mode 100755
index 00000000..607c71fa
--- /dev/null
+++ b/scripts/generate_version_script.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+VERSION_SCRIPT_FILE=$1
+
+extract_symbols_from_library()
+{
+  local LIB_NAME=$1
+  local LIB_PATH=$(gcc -print-file-name=$LIB_NAME)
+  echo "/*------- $LIB_PATH */" >> $VERSION_SCRIPT_FILE
+  nm -g -CD --defined-only $LIB_PATH | awk '// { printf("    %s;\n",$3) }' 
>> $VERSION_SCRIPT_FILE
+}
+
+
+VERSION_SCRIPT_START=$(cat <<"EOF"
+{
+  global:
+EOF
+)
+
+VERSION_SCRIPT_END=$(cat <<"EOF"
+  local:
+    *;
+};
+EOF
+)
+
+echo "$VERSION_SCRIPT_START" > $VERSION_SCRIPT_FILE
+
+extract_symbols_from_library "libresolv.so.2"
+extract_symbols_from_library "libc.so.6"
+extract_symbols_from_library "libm.so.6"
+extract_symbols_from_library "ld-linux-x86-64.so.2"
+extract_symbols_from_library "libpthread.so.0"
+extract_symbols_from_library "libdl.so.2"
+extract_symbols_from_library "librt.so.1"
+extract_symbols_from_library "libcrypt.so.1"
+extract_symbols_from_library "libaio.so.1"
+extract_symbols_from_library "libxenstore.so.3.0"
+#extract_symbols_from_library "libboost_system.so"
+
+echo "$VERSION_SCRIPT_END" >> $VERSION_SCRIPT_FILE
+#-fvisibility=hidden -fvisibility-inlines-hidden
diff --git a/scripts/manifest_from_host.sh b/scripts/manifest_from_host.sh
index 71b3340d..82b47d1a 100755
--- a/scripts/manifest_from_host.sh
+++ b/scripts/manifest_from_host.sh
@@ -61,7 +61,7 @@ output_manifest()
  echo "# Dependencies" | tee -a $OUTPUT
  echo "# --------------------" | tee -a $OUTPUT
  lddtree $so_path | grep -v "not found" | grep -v "$so_path" | grep -v 
'ld-linux-x86-64' | \
- grep -Pv 
'lib(gcc_s|resolv|c|m|pthread|dl|rt|stdc\+\+|aio|xenstore|crypt|selinux)\.so([\d.]+)?'
 
| \
+ grep -Pv 
'lib(gcc_s|resolv|c|m|pthread|dl|rt|aio|xenstore|crypt|selinux)\.so([\d.]+)?' 
| \
  sed 's/ =>/:/' | sed 's/^\s*lib/\/usr\/lib\/lib/' | sort | uniq | tee -a 
$OUTPUT
 }
 
@@ -135,7 +135,7 @@ if [[ -d $NAME_OR_PATH ]]; then
  echo "# Dependencies" | tee -a $OUTPUT
  echo "# --------------------" | tee -a $OUTPUT
  lddtree $SO_FILES | grep -v "not found" | grep -v 
"$NAME_OR_PATH/$SUBDIRECTORY_PATH" | grep -v 'ld-linux-x86-64' | \
- grep -Pv 
'lib(gcc_s|resolv|c|m|pthread|dl|rt|stdc\+\+|aio|xenstore|crypt|selinux)\.so([\d.]+)?'
 
| \
+ grep -Pv 
'lib(gcc_s|resolv|c|m|pthread|dl|rt|aio|xenstore|crypt|selinux)\.so([\d.]+)?' 
| \
  sed 's/ =>/:/' | sed 's/^\s*lib/\/usr\/lib\/lib/' | sort | uniq | tee -a 
$OUTPUT
  fi
  exit 0


In essence, this PoC patch hides most symbols as well as links libstdc++.a 
with '--no-whole-archive' (please note it only applies to kernel.elf not 
loader.elf for now). I have successfully tested both ZFS and ROFS images 
with native-example, java-example (running '/usr/bin/java -cp /java-example 
Hello !' so that it does not use our java wrapper), golang-pie-example and 
redis-memonly. 

You will notice that it adds a new script - scripts/generate_version_script.sh 
- to generate limited number of symbols to be visible from kernel.elf. Feel 
free to offer suggestions for doing it better (other options for nm or 
using readelf).

Here is the output from bloaty before applying my patch:

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  55.8%  3.74Mi  51.3%  3.74Mi    .text
  10.4%   714Ki   9.6%   714Ki    .dynstr
   0.0%       0   8.1%   605Ki    .bss
   8.7%   597Ki   8.0%   597Ki    .eh_frame
   6.8%   467Ki   6.3%   467Ki    .rodata
   5.8%   397Ki   5.3%   397Ki    .dynsym
   2.8%   192Ki   2.6%   192Ki    .percpu
   2.1%   146Ki   2.0%   146Ki    .gnu.hash
   1.9%   130Ki   1.7%   130Ki    .hash
   1.9%   130Ki   1.7%   130Ki    .eh_frame_hdr
   1.5%   102Ki   1.4%   102Ki    .gcc_except_table
   1.2%  80.1Ki   1.1%  80.0Ki    .data.rel.ro
   0.4%  26.7Ki   0.4%  26.7Ki    .data
   0.2%  10.4Ki   0.2%  12.5Ki    [LOAD #0 [RWX]]
   0.2%  12.3Ki   0.2%  12.2Ki    .tracepoint_patch_sites
   0.2%  10.6Ki   0.1%  10.6Ki    .data.rel.local
   0.1%  6.98Ki   0.1%  3.95Ki    [47 Others]
   0.1%  5.61Ki   0.1%  5.55Ki    .data.rel
   0.0%  2.22Ki   0.0%  2.16Ki    .init_array
   0.0%  1.99Ki   0.0%       0    .shstrtab
   0.0%       0   0.0%  1.73Ki    .tbss
 100.0%  6.71Mi 100.0%  7.30Mi    TOTAL

and number of exported symbols:
nm -g -CD --defined-only build/release/kernel.elf | wc -l
16960


After hiding most symbols but C++ library still whole-archive:
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  69.1%  3.74Mi  62.3%  3.74Mi    .text
   0.0%       0   9.8%   605Ki    .bss
  10.8%   597Ki   9.7%   597Ki    .eh_frame
   8.4%   467Ki   7.6%   467Ki    .rodata
   3.5%   192Ki   3.1%   192Ki    .percpu
   2.3%   130Ki   2.1%   130Ki    .eh_frame_hdr
   1.9%   102Ki   1.7%   102Ki    .gcc_except_table
   1.4%  80.1Ki   1.3%  80.0Ki    .data.rel.ro
   0.6%  31.6Ki   0.5%  31.6Ki    .dynsym
   0.5%  26.7Ki   0.4%  26.7Ki    .data
   0.2%  12.5Ki   0.2%  14.6Ki    [LOAD #0 [RWX]]
   0.2%  12.3Ki   0.2%  12.2Ki    .tracepoint_patch_sites
   0.2%  12.3Ki   0.2%  12.2Ki    .dynstr
   0.2%  10.6Ki   0.2%  10.6Ki    .data.rel.local
   0.2%  10.3Ki   0.2%  10.3Ki    .gnu.hash
   0.2%  9.36Ki   0.2%  9.30Ki    .hash
   0.1%  6.58Ki   0.1%  3.54Ki    [47 Others]
   0.1%  5.61Ki   0.1%  5.55Ki    .data.rel
   0.0%  2.22Ki   0.0%  2.16Ki    .init_array
   0.0%  1.99Ki   0.0%       0    .shstrtab
   0.0%       0   0.0%  1.73Ki    .tbss
 100.0%  5.42Mi 100.0%  6.01Mi    TOTAL

nm -g -CD --defined-only build/release/kernel.elf | wc -l
1339

Full patch:
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  68.5%  3.42Mi  61.3%  3.42Mi    .text
   0.0%       0  10.6%   604Ki    .bss
  10.6%   541Ki   9.5%   541Ki    .eh_frame
   8.9%   454Ki   7.9%   454Ki    .rodata
   3.8%   192Ki   3.4%   192Ki    .percpu
   2.3%   119Ki   2.1%   119Ki    .eh_frame_hdr
   1.8%  90.1Ki   1.6%  90.0Ki    .gcc_except_table
   1.5%  74.6Ki   1.3%  74.5Ki    .data.rel.ro
   0.6%  31.6Ki   0.6%  31.6Ki    .dynsym
   0.5%  26.7Ki   0.5%  26.7Ki    .data
   0.2%  11.9Ki   0.2%  14.1Ki    [LOAD #0 [RWX]]
   0.2%  12.3Ki   0.2%  12.2Ki    .tracepoint_patch_sites
   0.2%  12.3Ki   0.2%  12.2Ki    .dynstr
   0.2%  10.6Ki   0.2%  10.6Ki    .data.rel.local
   0.2%  10.3Ki   0.2%  10.3Ki    .gnu.hash
   0.2%  9.36Ki   0.2%  9.30Ki    .hash
   0.1%  6.08Ki   0.1%  3.48Ki    [39 Others]
   0.1%  5.61Ki   0.1%  5.55Ki    .data.rel
   0.0%  2.20Ki   0.0%  2.13Ki    .init_array
   0.0%       0   0.0%  1.73Ki    .tbss
   0.0%  1.62Ki   0.0%       0    .shstrtab
 100.0%  5.00Mi 100.0%  5.59Mi    TOTAL

nm -g -CD --defined-only build/release/kernel.elf | wc -l
1339

I wonder if it would be beneficial to compile as many sources as possible 
with '-fvisibility=hidden -fvisibility-inlines-hidden' - it will not make 
the kernel much smaller if any, but may produce more optimized code 
sometimes, no?

We still need to figure out what exactly to do with internal apps like 
cpiod, httpserver and tests that need some of the hidden symbols available. 
Possibly expose those extra symbols as C.

Waldek

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/147d66a0-dcc3-41f8-b94f-71d761dbb98e%40googlegroups.com.

Reply via email to