From e499a04de730e72818a564ac4d133588f1b54b6f Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Thu, 15 Aug 2019 10:28:50 +0200 Subject: [PATCH] ldso: config option to disarm ctors check By specifying the config attribute 'check_ctors="no"', the dynamic linker won't abort the program on a missing call of 'Env::exec_static_constructors'. This is the case for forked programs where the ctors were already executed by the forking program prior the fork operation. Issue #3478 --- repos/base/src/lib/ldso/README | 12 ++++++++++++ repos/base/src/lib/ldso/include/config.h | 8 +++++--- repos/base/src/lib/ldso/main.cc | 7 +++++-- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/repos/base/src/lib/ldso/README b/repos/base/src/lib/ldso/README index 10776d822f..85958c675d 100644 --- a/repos/base/src/lib/ldso/README +++ b/repos/base/src/lib/ldso/README @@ -68,3 +68,15 @@ Debugging dynamic binaries with GDB stubs GDB 7.2 has a regression bug in its line information parser. These issue has been fixed with version 7.3. +Execution of global static constructors +--------------------------------------- + +The dynamic linker does not implicitely execute global static constructors +(ctors) at the loading time of a program but leaves this up to the loaded +program, which can trigger the execution of the ctors by calling +'Env::exec_static_constructors()'. This gives the program the power over +the point in time for such initializations. However, once a component's +initialization is complete (when 'Component::construct') returned, the linker +checks that static constructors - if present - were executed and aborts +otherwise. This check can be explicitely disabled by specifying the config +attribute 'ld_check_ctors="no"'. diff --git a/repos/base/src/lib/ldso/include/config.h b/repos/base/src/lib/ldso/include/config.h index f5bd99b19b..5708df0930 100644 --- a/repos/base/src/lib/ldso/include/config.h +++ b/repos/base/src/lib/ldso/include/config.h @@ -47,14 +47,16 @@ class Linker::Config : Noncopyable Bind const _bind = _config.attribute_value("ld_bind_now", false) ? BIND_NOW : BIND_LAZY; - bool const _verbose = _config.attribute_value("ld_verbose", false); + bool const _verbose = _config.attribute_value("ld_verbose", false); + bool const _check_ctors = _config.attribute_value("ld_check_ctors", true); public: Config(Env &env) : _config(env) { } - Bind bind() const { return _bind; } - bool verbose() const { return _verbose; } + Bind bind() const { return _bind; } + bool verbose() const { return _verbose; } + bool check_ctors() const { return _check_ctors; } typedef String<100> Rom_name; diff --git a/repos/base/src/lib/ldso/main.cc b/repos/base/src/lib/ldso/main.cc index 9f3cc2111f..d1f2a2496c 100644 --- a/repos/base/src/lib/ldso/main.cc +++ b/repos/base/src/lib/ldso/main.cc @@ -345,13 +345,16 @@ struct Linker::Binary : private Root_object, public Elf_object { using Root_object::first_dep; + bool const _check_ctors; + bool static_construction_finished = false; Binary(Env &env, Allocator &md_alloc, Config const &config) : Root_object(md_alloc), Elf_object(env, md_alloc, binary_name(), - *new (md_alloc) Dependency(*this, this), KEEP) + *new (md_alloc) Dependency(*this, this), KEEP), + _check_ctors(config.check_ctors()) { /* create dep for binary and linker */ Dependency *binary = const_cast(&dynamic().dep()); @@ -423,7 +426,7 @@ struct Linker::Binary : private Root_object, public Elf_object if (Elf::Addr addr = lookup_symbol("_ZN9Component9constructERN6Genode3EnvE")) { ((void(*)(Env &))addr)(env); - if (static_construction_pending()) { + if (_check_ctors && static_construction_pending()) { error("Component::construct() returned without executing " "pending static constructors (fix by calling " "Genode::Env::exec_static_constructors())");