Skip to content

Commit

Permalink
Simpify startup of dynamically linked binaries
Browse files Browse the repository at this point in the history
This patch removes the component_entry_point library, which used to
proved a hook for the libc to intercept the call of the
'Component::construct' function. The mechansim has several shortcomings
(see the discussion in the associated issue) and was complex. So we
eventually discarded the approach in favor of the explicit handling of
the startup.

A regular Genode component provides a 'Component::construct' function,
which is determined by the dynamic linker via a symbol lookup.
For the time being, the dynamic linker falls back to looking up a 'main'
function if no 'Component::construct' function could be found.

The libc provides an implementation of 'Component::construct', which
sets up the libc's task handling and finally call the function
'Libc::Component::construct' from the context of the appllication task.
This function is expected to be provided by the libc-using application.
Consequently, Genode components that use the libc have to implement the
'Libc::Component::construct' function.

The new 'posix' library provides an implementation of
'Libc::Component::construct' that calls a main function. Hence, POSIX
programs that merely use the POSIX API merely have to add 'posix' to the
'LIBS' declaration in their 'target.mk' file. Their execution starts at
'main'.

Issue #2199
  • Loading branch information
nfeske committed Jan 13, 2017
1 parent 8d52103 commit 4da5251
Show file tree
Hide file tree
Showing 112 changed files with 366 additions and 369 deletions.
1 change: 0 additions & 1 deletion repos/base-hw/lib/mk/core-hw.inc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ SRC_CC += env.cc
SRC_CC += region_map_support.cc
SRC_CC += pager.cc
SRC_CC += _main.cc
SRC_CC += component_construct.cc
SRC_CC += kernel/cpu_scheduler.cc
SRC_CC += kernel/double_list.cc
SRC_CC += kernel/init.cc
Expand Down
17 changes: 0 additions & 17 deletions repos/base-linux/src/lib/lx_hybrid/lx_hybrid.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,6 @@ namespace Genode {
extern void bootstrap_component();
extern void call_global_static_constructors();

/*
* Hook for intercepting the call of the 'Component::construct' method. By
* hooking this function pointer in a library constructor, the libc is able
* to create a task context for the component code. This context is
* scheduled by the libc in a cooperative fashion, i.e. when the
* component's entrypoint is activated.
*/

extern void (*call_component_construct)(Genode::Env &) __attribute__((weak));

/*
* This function is normally provided by the cxx library, which is not
* used for lx_hybrid programs. For lx_hybrid programs, the exception
Expand All @@ -96,13 +86,6 @@ namespace Genode {
void init_exception_handling(Env &) { }
}

static void lx_hybrid_component_construct(Genode::Env &env)
{
Component::construct(env);
}

void (*Genode::call_component_construct)(Genode::Env &) = &lx_hybrid_component_construct;

/*
* Static constructors are handled by the Linux startup code - so implement
* this as empty function.
Expand Down
6 changes: 0 additions & 6 deletions repos/base/lib/import/import-base.mk

This file was deleted.

1 change: 0 additions & 1 deletion repos/base/lib/import/import-ld.mk

This file was deleted.

7 changes: 0 additions & 7 deletions repos/base/lib/mk/component_entry_point.mk

This file was deleted.

2 changes: 0 additions & 2 deletions repos/base/lib/mk/ld-platform.inc
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ ENTRY_POINT = _start
LD_OPT += -T$(DIR)/linker.ld
endif

include $(BASE_DIR)/lib/import/import-ld.mk

vpath %.cc $(DIR)

# vi:ft=make
Expand Down
1 change: 0 additions & 1 deletion repos/base/lib/mk/platform.mk
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
LIBS = component_entry_point
2 changes: 1 addition & 1 deletion repos/base/lib/mk/startup.inc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
SRC_S += crt0.s
SRC_CC += _main.cc init_main_thread.cc component_construct.cc
SRC_CC += _main.cc init_main_thread.cc
REP_INC_DIR += src/include
LIBS += syscall

Expand Down
1 change: 0 additions & 1 deletion repos/base/lib/symbols/ld
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,6 @@ _ZN6Genode18Signal_transmitterC1ENS_10CapabilityINS_14Signal_contextEEE T
_ZN6Genode18Signal_transmitterC2ENS_10CapabilityINS_14Signal_contextEEE T
_ZN6Genode18server_socket_pairEv T
_ZN6Genode20env_session_id_spaceEv T
_ZN6Genode21component_entry_pointERNS_3EnvE T
_ZN6Genode25env_stack_area_region_mapE B
_ZN6Genode26env_stack_area_ram_sessionE B
_ZN6Genode29upgrade_pd_quota_non_blockingEm T
Expand Down
2 changes: 0 additions & 2 deletions repos/base/mk/dep_lib.mk
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,9 @@ endif
#
ifeq ($(LIBS),)
ifneq ($(LIB),platform)
ifneq ($(LIB),component_entry_point)
LIBS += platform
endif
endif
endif

#
# Check if the requirements of the target are satisfied
Expand Down
2 changes: 1 addition & 1 deletion repos/base/mk/lib.mk
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ $(LIB_RLIB): $(OBJECTS)
#
ifdef SHARED_LIB
ifneq ($(LIB_IS_DYNAMIC_LINKER),yes)
override DEPS := $(filter-out $(BASE_LIBS:=.lib) component_entry_point.lib,$(DEPS))
override DEPS := $(filter-out $(BASE_LIBS:=.lib),$(DEPS))
endif
endif

Expand Down
15 changes: 1 addition & 14 deletions repos/base/mk/prg.mk
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,8 @@ LD_CMD ?= $(CXX)
LD_CMD += $(CXX_LINK_OPT)

ifeq ($(SHARED_LIBS),)
FILTER_DEPS := $(DEPS:.lib=)
LD_SCRIPTS := $(LD_SCRIPT_STATIC)

#
# Filter out the component-entry-point library since its not used for static
# binaries
#
FILTER_DEPS := $(filter-out component_entry_point,$(DEPS:.lib=))

else

#
Expand All @@ -135,13 +129,6 @@ LD_CMD += -Wl,--dynamic-linker=$(DYNAMIC_LINKER).lib.so \
FILTER_DEPS := $(filter-out $(BASE_LIBS),$(DEPS:.lib=))
SHARED_LIBS += $(LIB_CACHE_DIR)/$(DYNAMIC_LINKER)/$(DYNAMIC_LINKER).lib.so


#
# Link all dynamic executables to the component entry-point library (a
# trampoline for component startup from ldso)
#
FILTER_DEPS += component_entry_point

#
# Build program position independent as well
#
Expand Down
3 changes: 3 additions & 0 deletions repos/base/src/ld/genode_dyn.dl
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@
_ctors_end;
_dtors_start;
_dtors_end;
_ZN9Component9constructERN6Genode3EnvE;
_ZN9Component10stack_sizeEv;
main;
};
25 changes: 16 additions & 9 deletions repos/base/src/ld/genode_dyn.ld
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,10 @@
* under the terms of the GNU General Public License version 2.
*/


/*
* Components don't need to startup with CRT0 as LDSO has done this
* initialization during its own CRT0 already. The component always starts at
* Genode::component_entry_point() as a trampoline to
* call_component_construct().
* The entry point of dynamically linked components is unused. The dynamic
* linker determines the 'Component::construct' function via a symbol lookup.
*/
ENTRY(_ZN6Genode21component_entry_pointERNS_3EnvE)

PHDRS
{
Expand All @@ -37,10 +33,21 @@ SECTIONS
{
_prog_img_beg = .;

/* put entry code at the start of the text segment / raw binary */
*(.text._ZN6Genode21component_entry_pointERNS_3EnvE)
/*
* The ELF entry point is unused for dynamically linked components. The
* dynamic linker determined the entry point by looking up the symbol of
* the 'Component::construct' function or - if it does not exist - the
* 'main' function (for legacy components).
*
* \deprecated The support for legacy main functions will be removed.
*
* The 'KEEP' directive prevents text that is reachable from one of the
* possible entry points from being garbage collected.
*/
KEEP(*(.text._ZN9Component9constructERN6Genode3EnvE .text.main))

*(.text .stub .text.* .gnu.linkonce.t.*)
*(.text
.stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
} : ro =0x0
Expand Down
4 changes: 4 additions & 0 deletions repos/base/src/lib/base/component.cc
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ namespace Genode {
}


Genode::size_t Component::stack_size() __attribute__((weak));
Genode::size_t Component::stack_size() { return 64*1024; }


/*
* We need to execute the constructor of the main entrypoint from a
* class called 'Startup' as 'Startup' is a friend of 'Entrypoint'.
Expand Down
4 changes: 1 addition & 3 deletions repos/base/src/lib/base/entrypoint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ namespace Genode {
extern bool inhibit_tracing;
void call_global_static_constructors();
void destroy_signal_thread();

extern void (*call_component_construct)(Genode::Env &);
}


Expand Down Expand Up @@ -152,7 +150,7 @@ namespace {

Genode::call_global_static_constructors();

Genode::call_component_construct(env);
Component::construct(env);
}
};
}
Expand Down
69 changes: 56 additions & 13 deletions repos/base/src/lib/ldso/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,20 @@ Linker::Ld &Linker::Ld::linker()
}


/*
* Defined in the startup library, passed to legacy main functions.
*/
extern char **genode_argv;
extern int genode_argc;
extern char **genode_envp;

void genode_exit(int status);

static int exit_status;

static void exit_on_suspended() { genode_exit(exit_status); }


/**
* The dynamic binary to load
*/
Expand Down Expand Up @@ -348,16 +362,26 @@ struct Linker::Binary : Root_object, Elf_object

Elf::Addr lookup_symbol(char const *name)
{
Elf::Sym const *symbol = 0;

if ((symbol = Elf_object::lookup_symbol(name, Hash_table::hash(name))))
return reloc_base() + symbol->st_value;

return 0;
try {
Elf::Addr base = 0;
Elf::Sym const *sym = Linker::lookup_symbol(name, dynamic().dep(), &base);
return base + sym->st_value;
}
catch (Linker::Not_found) { return 0; }
}

void call_entry_point(Env &env)
{
/* apply the component-provided stack size */
if (Elf::Addr addr = lookup_symbol("_ZN9Component10stack_sizeEv")) {

/* call 'Component::stack_size()' */
size_t const stack_size = ((size_t(*)())addr)();

/* expand stack according to the component's needs */
Thread::myself()->stack_size(stack_size);
}

/* call static construtors and register destructors */
Func * const ctors_start = (Func *)lookup_symbol("_ctors_start");
Func * const ctors_end = (Func *)lookup_symbol("_ctors_end");
Expand All @@ -367,13 +391,33 @@ struct Linker::Binary : Root_object, Elf_object
Func * const dtors_end = (Func *)lookup_symbol("_dtors_end");
for (Func * dtor = dtors_start; dtor != dtors_end; genode_atexit(*dtor++));

/* call component entry point */
/* XXX the function type for call_component_construct() is a candidate
* for a base-internal header */
typedef void (*Entry)(Env &);
Entry const entry = reinterpret_cast<Entry>(_file->entry);
/* call 'Component::construct' function if present */
if (Elf::Addr addr = lookup_symbol("_ZN9Component9constructERN6Genode3EnvE")) {
((void(*)(Env &))addr)(env);
return;
}

/*
* The 'Component::construct' function is missing. This may be the
* case for legacy components that still implement a 'main' function.
*
* \deprecated the handling of legacy 'main' functions will be removed
*/
if (Elf::Addr addr = lookup_symbol("main")) {
warning("using legacy main function, please convert to 'Component::construct'");

exit_status = ((int (*)(int, char **, char **))addr)(genode_argc,
genode_argv,
genode_envp);

/* trigger suspend in the entry point */
env.ep().schedule_suspend(exit_on_suspended, nullptr);

/* return to entrypoint and exit via exit_on_suspended() */
return;
}

entry(env);
error("dynamic linker: component-entrypoint lookup failed");
}

void relocate(Bind bind) override
Expand Down Expand Up @@ -486,7 +530,6 @@ Elf::Sym const *Linker::lookup_symbol(char const *name, Dependency const &dep,
if (binary_ptr && &dep != binary_ptr->first_dep()) {
return lookup_symbol(name, *binary_ptr->first_dep(), base, undef, other);
} else {
error("LD: could not lookup symbol \"", name, "\"");
throw Not_found();
}
}
Expand Down
21 changes: 21 additions & 0 deletions repos/base/src/lib/startup/_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,24 @@ extern "C" int _main()
/* never reached */
return 0;
}


static int exit_status;
static void exit_on_suspended() { genode_exit(exit_status); }


extern int main(int argc, char **argv, char **envp);


void Component::construct(Genode::Env &env) __attribute__((weak));
void Component::construct(Genode::Env &env)
{
/* call real main function */
exit_status = main(genode_argc, genode_argv, genode_envp);

/* trigger suspend in the entry point */
env.ep().schedule_suspend(exit_on_suspended, nullptr);

/* return to entrypoint and exit via exit_on_suspended() */
}

Loading

0 comments on commit 4da5251

Please sign in to comment.