mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-21 00:23:16 +00:00
committed by
Christian Helmuth
parent
3acb509b9e
commit
686dd8affd
@ -15,10 +15,9 @@ dynamically linked program, the dynamic linker 'ldso.lib.so' and all used shared
|
|||||||
objects must be loaded as well.
|
objects must be loaded as well.
|
||||||
|
|
||||||
The linker can be configured through the '<config>' node when loading a dynamic
|
The linker can be configured through the '<config>' node when loading a dynamic
|
||||||
binary. Currently there are to configurations options, 'ld_bind_now="yes"'
|
binary. The configuration option 'ld_bind_now="yes"' prompts the linker to
|
||||||
causes the linker to resolve all symbol references on program loading.
|
resolve all symbol references on program loading. 'ld_verbose="yes"' outputs
|
||||||
'ld_verbose="yes"' outputs library load informations before starting the
|
library load information before starting the program.
|
||||||
program.
|
|
||||||
|
|
||||||
Configuration snippet:
|
Configuration snippet:
|
||||||
|
|
||||||
@ -29,6 +28,21 @@ Configuration snippet:
|
|||||||
! </config>
|
! </config>
|
||||||
!</start>
|
!</start>
|
||||||
|
|
||||||
|
Preloading libraries
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The dynamic linker supports the preloading of libraries according to its
|
||||||
|
configuration. The list of libraries must be specified within an '<ld>'
|
||||||
|
sub node of the configuration:
|
||||||
|
|
||||||
|
! <config>
|
||||||
|
! ...
|
||||||
|
! <ld>
|
||||||
|
! <library rom="libc_customization.lib.so"/>
|
||||||
|
! </ld>
|
||||||
|
! ...
|
||||||
|
! </config>
|
||||||
|
|
||||||
Debugging dynamic binaries with GDB stubs
|
Debugging dynamic binaries with GDB stubs
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
|
@ -58,18 +58,31 @@ bool Linker::Dependency::in_dep(char const *file, Fifo<Dependency> const &dep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Linker::Dependency::load_needed(Env &env, Allocator &md_alloc,
|
void Linker::Dependency::_load(Env &env, Allocator &alloc, char const *path,
|
||||||
Fifo<Dependency> &deps, Keep keep)
|
Fifo<Dependency> &deps, Keep keep)
|
||||||
{
|
{
|
||||||
_obj.dynamic().for_each_dependency([&] (char const *path) {
|
|
||||||
|
|
||||||
if (!in_dep(Linker::file(path), deps))
|
if (!in_dep(Linker::file(path), deps))
|
||||||
new (md_alloc) Dependency(env, md_alloc, path, _root, deps, keep);
|
new (alloc) Dependency(env, alloc, path, _root, deps, keep);
|
||||||
|
|
||||||
/* re-order initializer list, if needed object has been already added */
|
/* re-order initializer list, if needed object has been already added */
|
||||||
else if (Object *o = Init::list()->contains(Linker::file(path)))
|
else if (Object *o = Init::list()->contains(Linker::file(path)))
|
||||||
Init::list()->reorder(o);
|
Init::list()->reorder(o);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Linker::Dependency::preload(Env &env, Allocator &alloc,
|
||||||
|
Fifo<Dependency> &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<Dependency> &deps, Keep keep)
|
||||||
|
{
|
||||||
|
_obj.dynamic().for_each_dependency([&] (char const *path) {
|
||||||
|
_load(env, md_alloc, path, deps, keep); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
84
repos/base/src/lib/ldso/include/config.h
Normal file
84
repos/base/src/lib/ldso/include/config.h
Normal file
@ -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 <util/reconstructible.h>
|
||||||
|
#include <base/attached_rom_dataspace.h>
|
||||||
|
|
||||||
|
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<Attached_rom_dataspace> _rom { };
|
||||||
|
|
||||||
|
Xml_config(Env &env) : Xml_node("<empty/>")
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
_rom.construct(env, "config");
|
||||||
|
static_cast<Xml_node &>(*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 <typename FN>
|
||||||
|
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_ */
|
@ -19,6 +19,7 @@
|
|||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
#include <file.h>
|
#include <file.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark functions that are used during the linkers self-relocation phase as
|
* Mark functions that are used during the linkers self-relocation phase as
|
||||||
@ -224,6 +225,8 @@ class Linker::Dependency : public Fifo<Dependency>::Element, Noncopyable
|
|||||||
*/
|
*/
|
||||||
bool in_dep(char const *file, Fifo<Dependency> const &);
|
bool in_dep(char const *file, Fifo<Dependency> const &);
|
||||||
|
|
||||||
|
void _load(Env &, Allocator &, char const *, Fifo<Dependency> &, Keep);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -241,6 +244,11 @@ class Linker::Dependency : public Fifo<Dependency>::Element, Noncopyable
|
|||||||
*/
|
*/
|
||||||
void load_needed(Env &, Allocator &, Fifo<Dependency> &, Keep);
|
void load_needed(Env &, Allocator &, Fifo<Dependency> &, Keep);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preload ELF object
|
||||||
|
*/
|
||||||
|
void preload(Env &, Allocator &, Fifo<Dependency> &, Config const &);
|
||||||
|
|
||||||
bool root() const { return _root != nullptr; }
|
bool root() const { return _root != nullptr; }
|
||||||
|
|
||||||
Object const &obj() const { return _obj; }
|
Object const &obj() const { return _obj; }
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <dynamic.h>
|
#include <dynamic.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
#include <region_map.h>
|
#include <region_map.h>
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
using namespace Linker;
|
using namespace Linker;
|
||||||
|
|
||||||
@ -346,7 +347,7 @@ struct Linker::Binary : private Root_object, public Elf_object
|
|||||||
|
|
||||||
bool static_construction_finished = false;
|
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),
|
Root_object(md_alloc),
|
||||||
Elf_object(env, md_alloc, binary_name(),
|
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 */
|
/* place linker on second place in link map */
|
||||||
Ld::linker().setup_link_map();
|
Ld::linker().setup_link_map();
|
||||||
|
|
||||||
|
/* preload libraries specified in the configuration */
|
||||||
|
binary->preload(env, md_alloc, deps(), config);
|
||||||
|
|
||||||
/* load dependencies */
|
/* load dependencies */
|
||||||
binary->load_needed(env, md_alloc, deps(), DONT_KEEP);
|
binary->load_needed(env, md_alloc, deps(), DONT_KEEP);
|
||||||
|
|
||||||
/* relocate and call constructors */
|
/* relocate and call constructors */
|
||||||
Init::list()->initialize(bind, STAGE_BINARY);
|
Init::list()->initialize(config.bind(), STAGE_BINARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
Elf::Addr lookup_symbol(char const *name)
|
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> &heap()
|
static Genode::Constructible<Heap> &heap()
|
||||||
{
|
{
|
||||||
return *unmanaged_singleton<Constructible<Heap>>();
|
return *unmanaged_singleton<Constructible<Heap>>();
|
||||||
@ -684,12 +662,13 @@ void Genode::exec_static_constructors()
|
|||||||
void Component::construct(Genode::Env &env)
|
void Component::construct(Genode::Env &env)
|
||||||
{
|
{
|
||||||
/* read configuration */
|
/* read configuration */
|
||||||
static Config config(env);
|
Config const config(env);
|
||||||
|
|
||||||
verbose = config.verbose();
|
verbose = config.verbose();
|
||||||
|
|
||||||
/* load binary and all dependencies */
|
/* load binary and all dependencies */
|
||||||
try {
|
try {
|
||||||
binary_ptr = unmanaged_singleton<Binary>(env, *heap(), config.bind());
|
binary_ptr = unmanaged_singleton<Binary>(env, *heap(), config);
|
||||||
} catch(Linker::Not_found &symbol) {
|
} catch(Linker::Not_found &symbol) {
|
||||||
error("LD: symbol not found: '", symbol, "'");
|
error("LD: symbol not found: '", symbol, "'");
|
||||||
throw;
|
throw;
|
||||||
|
Reference in New Issue
Block a user