diff --git a/repos/base/src/lib/ldso/README b/repos/base/src/lib/ldso/README
index 73b47adaf..10776d822 100644
--- a/repos/base/src/lib/ldso/README
+++ b/repos/base/src/lib/ldso/README
@@ -15,10 +15,9 @@ dynamically linked program, the dynamic linker 'ldso.lib.so' and all used shared
objects must be loaded as well.
The linker can be configured through the '' node when loading a dynamic
-binary. Currently there are to configurations options, 'ld_bind_now="yes"'
-causes the linker to resolve all symbol references on program loading.
-'ld_verbose="yes"' outputs library load informations before starting the
-program.
+binary. The configuration option 'ld_bind_now="yes"' prompts the linker to
+resolve all symbol references on program loading. 'ld_verbose="yes"' outputs
+library load information before starting the program.
Configuration snippet:
@@ -29,6 +28,21 @@ Configuration snippet:
!
!
+Preloading libraries
+--------------------
+
+The dynamic linker supports the preloading of libraries according to its
+configuration. The list of libraries must be specified within an ''
+sub node of the configuration:
+
+!
+! ...
+!
+!
+!
+! ...
+!
+
Debugging dynamic binaries with GDB stubs
-----------------------------------------
diff --git a/repos/base/src/lib/ldso/dependency.cc b/repos/base/src/lib/ldso/dependency.cc
index 7fbfe1eb9..cb66211c4 100644
--- a/repos/base/src/lib/ldso/dependency.cc
+++ b/repos/base/src/lib/ldso/dependency.cc
@@ -58,18 +58,31 @@ bool Linker::Dependency::in_dep(char const *file, Fifo const &dep)
}
+void Linker::Dependency::_load(Env &env, Allocator &alloc, char const *path,
+ Fifo &deps, Keep keep)
+{
+ if (!in_dep(Linker::file(path), deps))
+ new (alloc) Dependency(env, alloc, path, _root, deps, keep);
+
+ /* re-order initializer list, if needed object has been already added */
+ else if (Object *o = Init::list()->contains(Linker::file(path)))
+ Init::list()->reorder(o);
+}
+
+
+void Linker::Dependency::preload(Env &env, Allocator &alloc,
+ Fifo &deps, Config const &config)
+{
+ config.for_each_library([&] (Config::Rom_name const &rom, Keep keep) {
+ _load(env, alloc, rom.string(), deps, keep); });
+}
+
+
void Linker::Dependency::load_needed(Env &env, Allocator &md_alloc,
Fifo &deps, Keep keep)
{
_obj.dynamic().for_each_dependency([&] (char const *path) {
-
- if (!in_dep(Linker::file(path), deps))
- new (md_alloc) Dependency(env, md_alloc, path, _root, deps, keep);
-
- /* re-order initializer list, if needed object has been already added */
- else if (Object *o = Init::list()->contains(Linker::file(path)))
- Init::list()->reorder(o);
- });
+ _load(env, md_alloc, path, deps, keep); });
}
diff --git a/repos/base/src/lib/ldso/include/config.h b/repos/base/src/lib/ldso/include/config.h
new file mode 100644
index 000000000..f5bd99b19
--- /dev/null
+++ b/repos/base/src/lib/ldso/include/config.h
@@ -0,0 +1,84 @@
+/*
+ * \brief Linker configuration
+ * \author Norman Feske
+ * \date 2019-08-13
+ */
+
+/*
+ * Copyright (C) 2019 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef _INCLUDE__CONFIG_H_
+#define _INCLUDE__CONFIG_H_
+
+#include
+#include
+
+namespace Linker { class Config; }
+
+
+class Linker::Config : Noncopyable
+{
+ private:
+
+ /*
+ * Helper to transparently handle the case where no "config" ROM is
+ * available.
+ */
+ struct Xml_config : Xml_node
+ {
+ Constructible _rom { };
+
+ Xml_config(Env &env) : Xml_node("")
+ {
+ try {
+ _rom.construct(env, "config");
+ static_cast(*this) = _rom->xml();
+ }
+ catch (...) { }
+ }
+ };
+
+ Xml_config const _config;
+
+ Bind const _bind = _config.attribute_value("ld_bind_now", false)
+ ? BIND_NOW : BIND_LAZY;
+
+ bool const _verbose = _config.attribute_value("ld_verbose", false);
+
+ public:
+
+ Config(Env &env) : _config(env) { }
+
+ Bind bind() const { return _bind; }
+ bool verbose() const { return _verbose; }
+
+ typedef String<100> Rom_name;
+
+ /**
+ * Call fn for each library specified in the configuration
+ *
+ * The functor 'fn' is called with 'Rom_name', 'Keep' as arguments.
+ */
+ template
+ void for_each_library(FN const &fn) const
+ {
+ _config.with_sub_node("ld", [&] (Xml_node ld) {
+
+ ld.for_each_sub_node("library", [&] (Xml_node lib) {
+
+ Rom_name const rom = lib.attribute_value("rom", Rom_name());
+
+ Keep const keep = lib.attribute_value("keep", false)
+ ? DONT_KEEP : KEEP;
+
+ fn(rom, keep);
+ });
+ });
+ }
+};
+
+#endif /* _INCLUDE__CONFIG_H_ */
diff --git a/repos/base/src/lib/ldso/include/linker.h b/repos/base/src/lib/ldso/include/linker.h
index bb3ca7e4e..8ce581902 100644
--- a/repos/base/src/lib/ldso/include/linker.h
+++ b/repos/base/src/lib/ldso/include/linker.h
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
/*
* Mark functions that are used during the linkers self-relocation phase as
@@ -224,6 +225,8 @@ class Linker::Dependency : public Fifo::Element, Noncopyable
*/
bool in_dep(char const *file, Fifo const &);
+ void _load(Env &, Allocator &, char const *, Fifo &, Keep);
+
public:
/*
@@ -241,6 +244,11 @@ class Linker::Dependency : public Fifo::Element, Noncopyable
*/
void load_needed(Env &, Allocator &, Fifo &, Keep);
+ /**
+ * Preload ELF object
+ */
+ void preload(Env &, Allocator &, Fifo &, Config const &);
+
bool root() const { return _root != nullptr; }
Object const &obj() const { return _obj; }
diff --git a/repos/base/src/lib/ldso/main.cc b/repos/base/src/lib/ldso/main.cc
index bc7490dbb..4d05713ba 100644
--- a/repos/base/src/lib/ldso/main.cc
+++ b/repos/base/src/lib/ldso/main.cc
@@ -28,6 +28,7 @@
#include
#include
#include
+#include
using namespace Linker;
@@ -346,7 +347,7 @@ struct Linker::Binary : private Root_object, public Elf_object
bool static_construction_finished = false;
- Binary(Env &env, Allocator &md_alloc, Bind bind)
+ Binary(Env &env, Allocator &md_alloc, Config const &config)
:
Root_object(md_alloc),
Elf_object(env, md_alloc, binary_name(),
@@ -363,11 +364,14 @@ struct Linker::Binary : private Root_object, public Elf_object
/* place linker on second place in link map */
Ld::linker().setup_link_map();
+ /* preload libraries specified in the configuration */
+ binary->preload(env, md_alloc, deps(), config);
+
/* load dependencies */
binary->load_needed(env, md_alloc, deps(), DONT_KEEP);
/* relocate and call constructors */
- Init::list()->initialize(bind, STAGE_BINARY);
+ Init::list()->initialize(config.bind(), STAGE_BINARY);
}
Elf::Addr lookup_symbol(char const *name)
@@ -634,32 +638,6 @@ extern "C" void init_rtld()
}
-class Linker::Config
-{
- private:
-
- Bind _bind = BIND_LAZY;
- bool _verbose = false;
-
- public:
-
- Config(Env &env)
- {
- try {
- Attached_rom_dataspace config(env, "config");
-
- if (config.xml().attribute_value("ld_bind_now", false))
- _bind = BIND_NOW;
-
- _verbose = config.xml().attribute_value("ld_verbose", false);
- } catch (Rom_connection::Rom_connection_failed) { }
- }
-
- Bind bind() const { return _bind; }
- bool verbose() const { return _verbose; }
-};
-
-
static Genode::Constructible &heap()
{
return *unmanaged_singleton>();
@@ -684,12 +662,13 @@ void Genode::exec_static_constructors()
void Component::construct(Genode::Env &env)
{
/* read configuration */
- static Config config(env);
+ Config const config(env);
+
verbose = config.verbose();
/* load binary and all dependencies */
try {
- binary_ptr = unmanaged_singleton(env, *heap(), config.bind());
+ binary_ptr = unmanaged_singleton(env, *heap(), config);
} catch(Linker::Not_found &symbol) {
error("LD: symbol not found: '", symbol, "'");
throw;