Genode application binary interface (ABI)
This patch decouples the kernel-specific implementation of the dynamic linker from its kernel-agnostic binary interface. The name of the kernel-specific dynamic linker binary now corresponds to the kernel, e.g., 'ld-linux.lib.so' or 'ld-nova.lib.so'. Applications are no longer linked directly against a concrete instance of the dynamic linker but against a shallow stub called 'ld.lib.so'. This stub contains nothing but the symbols provided by the dynamic linker. It thereby represents the Genode ABI. At system-integration time, the kernel-specific run/boot_dir back ends integrate the matching the kernel-specific variant of the dynamic linker as 'ld.lib.so' into the boot image. The ABI symbol file for the dynamic linker is located at 'base/lib/symbols/ld'. It contains the joint ABI of all supported architectures. The new utility 'tool/abi_symbols' eases the creation of such an ABI symbol file for a given shared library. Its result should be manually inspected and edited as needed. The patch removes the 'syscall' library from 'base_libs.mk' to avoid polluting the kernel-agnostic ABI with kernel-specific interfaces. Issue #2190 Issue #2195
This commit is contained in:
98
tool/abi_symbols
Executable file
98
tool/abi_symbols
Executable file
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/tclsh
|
||||
|
||||
#
|
||||
# \brief Generate ABI symbol list for a shared library
|
||||
# \author Norman Feske
|
||||
# \date 2016-12-07
|
||||
#
|
||||
# The tool takes the shared library as argument and writes the output to
|
||||
# standard output. Each line of the resulting output contains the symbol name,
|
||||
# type, and size
|
||||
#
|
||||
|
||||
# obtain symbol information via 'nm'
|
||||
set symbols [exec nm --format posix --dynamic $argv]
|
||||
|
||||
# obtain demangled input via c++filt
|
||||
set demangled [exec c++filt << $symbols]
|
||||
|
||||
set demangled_lines [split $demangled "\n"]
|
||||
|
||||
set i 0
|
||||
set output_lines {}
|
||||
foreach line [split $symbols "\n"] {
|
||||
|
||||
set size_hex 0
|
||||
set type "U"
|
||||
|
||||
# match undefined symbol
|
||||
regexp {^(\w+) U\s*$} $line dummy name
|
||||
|
||||
# match defined symbol, which does not always feature a size value
|
||||
regexp {^(\w+) (\w) \w+ ?(\w*)$} $line dummy name type size_hex
|
||||
|
||||
# decimal symbol size
|
||||
set size_dec [expr 0x0$size_hex]
|
||||
|
||||
set demangled_name $name
|
||||
regexp {^(.+) \w \w+( \w+)?$} [lindex $demangled_lines $i] dummy demangled_name
|
||||
|
||||
set keep 1
|
||||
|
||||
#
|
||||
# Ignore undefined symbols
|
||||
#
|
||||
if {$type == "U"} { set keep 0 }
|
||||
|
||||
#
|
||||
# Check if the unmangled line contains a template-argument delimiter ('<')
|
||||
# prior the first opening parenthesis. This way, template methods match but
|
||||
# signatures of non-template functions/methods that take templated
|
||||
# arguments won't. We can discard symbols for the former but not the
|
||||
# latter.
|
||||
#
|
||||
if {[regexp {^[^(]+<} $demangled_name dummy]} { set keep 0 }
|
||||
|
||||
#
|
||||
# Drop weak vtable and typeinfo symbols
|
||||
#
|
||||
# Those symbols are solely used to merge vtables between the executable and
|
||||
# shared library. When linking object files that use the same types, the
|
||||
# merging saves a lot space. However, the benefit at the coarse granularity
|
||||
# of shared libraries is rather small compared to the huge inflation of the
|
||||
# ABI size caused by such symbols.
|
||||
#
|
||||
if {($type == "V") && ([regexp {^(typeinfo |vtable )} $demangled_name dummy])} {
|
||||
set keep 0 }
|
||||
|
||||
#
|
||||
# Drop weak C++ symbols
|
||||
#
|
||||
# In contrast to weak C symbols, which are rarely and always deliberately
|
||||
# created, weak C++ symbols are implicitly created by the compiler for
|
||||
# inline functions.
|
||||
#
|
||||
if {[regexp {W|V} $type] && ($name != $demangled_name)} {
|
||||
set keep 0 }
|
||||
|
||||
# write result
|
||||
if {$keep} {
|
||||
|
||||
#
|
||||
# Annotate the size for global data symbols where the size is needed to
|
||||
# create copy relations (ARM EABI) in the binary that is linked against
|
||||
# the shared library. For each global read-only data symbol found in
|
||||
# the shared object, the linker reserves space (according to the
|
||||
# symbol's size) in the binary's BSS segment. At runtime, the dynamic
|
||||
# linker copies the data from the shared library's symbol into the
|
||||
# binary's BSS.
|
||||
#
|
||||
if {$type == "D"} {
|
||||
puts "$name $type $size_dec"
|
||||
} else {
|
||||
puts "$name $type"
|
||||
}
|
||||
}
|
||||
incr i
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
proc binary_name_ld_lib_so { } { return "ld-fiasco.lib.so" }
|
||||
|
||||
|
||||
##
|
||||
# Read the location of the Fiasco user directory from 'etc/fiasco.conf'
|
||||
#
|
||||
@@ -23,15 +26,6 @@ proc l4_dir { } {
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
# Return whether the l4-buid-directory is provided from the outside
|
||||
#
|
||||
proc l4_dir_external { } {
|
||||
if {[l4_dir] == "[pwd]/l4"} { return 0 }
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
# Return the location of the Fiasco kernel
|
||||
#
|
||||
@@ -40,15 +34,6 @@ proc fiasco { } {
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
# Return whether fiasco kernel is provided from the outside
|
||||
#
|
||||
proc fiasco_external { } {
|
||||
if {[fiasco] == "[pwd]/kernel/fiasco/fiasco"} { return 0 }
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
proc bin_dir { } {
|
||||
if {[have_spec x86_32]} { return "[l4_dir]/bin/x86_586" }
|
||||
|
||||
@@ -71,15 +56,14 @@ proc core_link_address { } { return "0x01000000" }
|
||||
#
|
||||
proc run_boot_dir {binaries} {
|
||||
|
||||
build { lib/ld/fiasco kernel bootstrap sigma0 }
|
||||
|
||||
build_core_image $binaries
|
||||
|
||||
global fiasco_serial_esc_arg
|
||||
|
||||
exec mkdir -p [run_dir]/fiasco
|
||||
|
||||
if {![fiasco_external]} { build { kernel } }
|
||||
if {![l4_dir_external]} { build { bootstrap sigma0 } }
|
||||
|
||||
# assert existence of the L4 build directory
|
||||
l4_dir
|
||||
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
# This file is meant to be used as '--include' argument for 'tool/run'.
|
||||
#
|
||||
|
||||
proc binary_name_ld_lib_so { } { return "ld-foc.lib.so" }
|
||||
|
||||
|
||||
##
|
||||
# Return the location of the Fiasco.OC user directory
|
||||
#
|
||||
@@ -102,11 +105,12 @@ proc core_link_address { } {
|
||||
}
|
||||
|
||||
proc run_boot_dir_x86 {binaries} {
|
||||
|
||||
global fiasco_serial_esc_arg
|
||||
|
||||
exec mkdir -p [run_dir]/fiasco
|
||||
|
||||
set foc_targets { }
|
||||
set foc_targets { lib/ld/foc }
|
||||
if {![fiasco_external] && ![file exists kernel]} { lappend foc_targets kernel }
|
||||
if {![l4_dir_external]} {
|
||||
if {![file exists bootstrap]} { lappend foc_targets bootstrap }
|
||||
@@ -114,6 +118,8 @@ proc run_boot_dir_x86 {binaries} {
|
||||
}
|
||||
if {[llength $foc_targets] > 0} { build $foc_targets }
|
||||
|
||||
build_core_image $binaries
|
||||
|
||||
# assert existence of the L4 build directory
|
||||
l4_dir
|
||||
|
||||
@@ -185,7 +191,9 @@ proc run_boot_dir_arm {binaries} {
|
||||
global run_target
|
||||
global fiasco_serial_esc_arg
|
||||
|
||||
build "kernel sigma0 bootstrap"
|
||||
build { lib/ld/foc kernel sigma0 bootstrap }
|
||||
|
||||
build_core_image $binaries
|
||||
|
||||
#
|
||||
# Generate bootstrap config
|
||||
@@ -239,7 +247,6 @@ proc run_boot_string { } {
|
||||
# Populate boot directory with binaries on fiasco.OC
|
||||
#
|
||||
proc run_boot_dir {binaries} {
|
||||
build_core_image $binaries
|
||||
|
||||
if {[have_spec x86]} { return [run_boot_dir_x86 $binaries] }
|
||||
if {[have_spec arm]} { return [run_boot_dir_arm $binaries] }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
proc run_boot_string { } {
|
||||
return "\nkernel initialized"
|
||||
}
|
||||
proc binary_name_ld_lib_so { } { return "ld-hw.lib.so" }
|
||||
|
||||
|
||||
proc run_boot_string { } { return "\nkernel initialized" }
|
||||
|
||||
|
||||
proc core_link_address { } {
|
||||
@@ -33,6 +34,8 @@ proc run_boot_dir {binaries} {
|
||||
close $fh
|
||||
}
|
||||
|
||||
build { lib/ld/hw }
|
||||
|
||||
build_core_image $binaries
|
||||
|
||||
if {[have_include "image/iso"] || [have_include "image/disk"]} {
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
proc binary_name_ld_lib_so { } { return "ld-linux.lib.so" }
|
||||
|
||||
|
||||
##
|
||||
# Populate boot directory with binaries on Linux
|
||||
#
|
||||
proc run_boot_dir {binaries} {
|
||||
|
||||
build { lib/ld/linux }
|
||||
|
||||
foreach binary $binaries {
|
||||
exec ln -sf ../../../../bin/$binary [run_dir]/genode }
|
||||
set src_binary_path "../../../../bin/[kernel_specific_binary $binary]"
|
||||
exec ln -sf $src_binary_path [run_dir]/genode/$binary }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
proc binary_name_ld_lib_so { } { return "ld-nova.lib.so" }
|
||||
|
||||
|
||||
##
|
||||
# Read the location of the NOVA kernel directory from 'etc/nova.conf'
|
||||
#
|
||||
@@ -43,13 +46,17 @@ proc core_ld_opts { } {
|
||||
#
|
||||
proc run_boot_dir {binaries} {
|
||||
|
||||
if {![nova_external]} {
|
||||
build { lib/ld/nova kernel }
|
||||
} else {
|
||||
build { lib/ld/nova }
|
||||
}
|
||||
|
||||
#
|
||||
# Collect contents of the ISO image
|
||||
#
|
||||
build_core_image $binaries
|
||||
|
||||
if {![nova_external]} { build { kernel } }
|
||||
|
||||
puts "using NOVA kernel at [nova_kernel]"
|
||||
exec [cross_dev_prefix]objcopy -O elf32-i386 [nova_kernel] [run_dir]/hypervisor
|
||||
exec [cross_dev_prefix]strip [run_dir]/hypervisor
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
proc binary_name_ld_lib_so { } { return "ld-okl4.lib.so" }
|
||||
|
||||
|
||||
##
|
||||
# Get the base-okl4 repository
|
||||
#
|
||||
@@ -113,10 +116,8 @@ proc core_link_address { } { return "0x03000000" }
|
||||
# Populate directory with binaries on OKL4
|
||||
#
|
||||
proc run_boot_dir {binaries} {
|
||||
global weaver_xml_template
|
||||
|
||||
build_core_image $binaries
|
||||
exec mv [run_dir]/image.elf [run_dir].image
|
||||
global weaver_xml_template
|
||||
|
||||
#
|
||||
# Build kernel if needed
|
||||
@@ -127,7 +128,14 @@ proc run_boot_dir {binaries} {
|
||||
# the kernel does not stand in the way of the everyday's work flow of
|
||||
# executing run scripts as quick as possible.
|
||||
#
|
||||
if {![okl4_external] && ![file exists [okl4]]} { build { kernel } }
|
||||
if {![okl4_external] && ![file exists [okl4]]} {
|
||||
build { lib/ld/okl4 kernel }
|
||||
} else {
|
||||
build { lib/ld/okl4 }
|
||||
}
|
||||
|
||||
build_core_image $binaries
|
||||
exec mv [run_dir]/image.elf [run_dir].image
|
||||
|
||||
exec cp [okl4] [run_dir]/kernel
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
# This file is meant to be used as '--include' argument for 'tool/run'.
|
||||
#
|
||||
|
||||
proc binary_name_ld_lib_so { } { return "ld-pistachio.lib.so" }
|
||||
|
||||
|
||||
##
|
||||
# Install files needed to boot via PXE
|
||||
@@ -74,12 +76,16 @@ proc core_link_address { } { return "0x02000000" }
|
||||
#
|
||||
proc run_boot_dir {binaries} {
|
||||
|
||||
if {![kernel_external] && ![file exists [pistachio_kernel]]} {
|
||||
build { lib/ld/pistachio kernel }
|
||||
} else {
|
||||
build { lib/ld/pistachio }
|
||||
}
|
||||
|
||||
build_core_image $binaries
|
||||
|
||||
exec mkdir -p [run_dir]/pistachio
|
||||
|
||||
if {![kernel_external] && ![file exists [pistachio_kernel]]} { build { kernel } }
|
||||
|
||||
exec cp [pistachio_kernel] [run_dir]/pistachio/kernel
|
||||
exec cp [pistachio_user_dir]/serv/sigma0/sigma0 [run_dir]/pistachio
|
||||
exec cp [pistachio_user_dir]/util/kickstart/kickstart [run_dir]/pistachio
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#
|
||||
# Based on boot_dir/hw
|
||||
#
|
||||
proc binary_name_ld_lib_so { } { return "ld-sel4.lib.so" }
|
||||
|
||||
|
||||
proc run_boot_string { } { return "\n\rStarting node #0" }
|
||||
|
||||
@@ -14,7 +13,7 @@ proc core_link_address { } { return "0x02000000" }
|
||||
proc run_boot_dir {binaries} {
|
||||
|
||||
# build sel4 kernel
|
||||
build { kernel }
|
||||
build { lib/ld/sel4 kernel }
|
||||
exec cp bin/sel4 [run_dir]/sel4
|
||||
|
||||
build_core_image $binaries
|
||||
|
||||
29
tool/run/run
29
tool/run/run
@@ -438,6 +438,33 @@ proc kernel_location_from_config_file { config_file default_location } {
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
# Return name of kernel-specific binary for a given generic name
|
||||
#
|
||||
# The boot_dir plugin may provide functions named 'binary_name_<binary>'
|
||||
# where '<binary>' stands for a generic name like "timer" or "nic". The
|
||||
# function returns the name of the binary to integrate into the boot
|
||||
# directory under the name '<binary>'.
|
||||
#
|
||||
# If no such function exists, it returns the argument as is. This is the
|
||||
# case for regular binaries that appear in the boot directory under their
|
||||
# original name.
|
||||
#
|
||||
proc kernel_specific_binary { binary } {
|
||||
|
||||
regsub -all {\.} $binary "_" function_suffix
|
||||
set function_name "binary_name_$function_suffix"
|
||||
|
||||
if {[info procs $function_name] == $function_name} {
|
||||
set binary_name [$function_name]
|
||||
puts "using '$binary_name' as '$binary'"
|
||||
return [$function_name]
|
||||
}
|
||||
|
||||
return $binary
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
# Copy the specified binaries from the 'bin/' directory to the run
|
||||
# directory and try to strip executables.
|
||||
@@ -445,7 +472,7 @@ proc kernel_location_from_config_file { config_file default_location } {
|
||||
proc copy_and_strip_genode_binaries_to_run_dir { binaries } {
|
||||
|
||||
foreach binary $binaries {
|
||||
exec cp bin/$binary [run_dir]/genode
|
||||
exec cp bin/[kernel_specific_binary $binary] [run_dir]/genode/$binary
|
||||
catch {
|
||||
exec [cross_dev_prefix]strip [run_dir]/genode/$binary || true }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user