2016-01-20 20:52:51 +01:00
|
|
|
/*
|
2014-05-20 11:40:50 +02:00
|
|
|
* \brief Dynamic linker interface
|
|
|
|
* \author Sebastian Sumpf
|
|
|
|
* \date 2014-10-09
|
|
|
|
*/
|
|
|
|
|
2016-01-20 20:52:51 +01:00
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2014-2017 Genode Labs GmbH
|
2016-01-20 20:52:51 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2016-01-20 20:52:51 +01:00
|
|
|
*/
|
|
|
|
|
2014-05-20 11:40:50 +02:00
|
|
|
#ifndef _INCLUDE__BASE__SHARED_OBJECT_H_
|
|
|
|
#define _INCLUDE__BASE__SHARED_OBJECT_H_
|
|
|
|
|
2017-01-31 16:00:13 +01:00
|
|
|
#include <base/env.h>
|
|
|
|
#include <base/allocator.h>
|
2014-05-20 11:40:50 +02:00
|
|
|
#include <base/exception.h>
|
|
|
|
#include <base/stdint.h>
|
2019-08-14 16:00:18 +02:00
|
|
|
#include <rom_session/rom_session.h>
|
2014-05-20 11:40:50 +02:00
|
|
|
|
|
|
|
namespace Genode {
|
2015-03-04 21:12:14 +01:00
|
|
|
|
2014-05-20 11:40:50 +02:00
|
|
|
class Shared_object;
|
|
|
|
struct Address_info;
|
2019-08-14 16:00:18 +02:00
|
|
|
struct Dynamic_linker;
|
2014-05-20 11:40:50 +02:00
|
|
|
};
|
|
|
|
|
2015-03-04 21:12:14 +01:00
|
|
|
|
2014-05-20 11:40:50 +02:00
|
|
|
class Genode::Shared_object
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
|
|
void *_handle = nullptr;
|
|
|
|
void *_lookup(const char *symbol) const;
|
|
|
|
|
2016-10-30 15:17:24 +01:00
|
|
|
Allocator &_md_alloc;
|
|
|
|
|
Follow practices suggested by "Effective C++"
The patch adjust the code of the base, base-<kernel>, and os repository.
To adapt existing components to fix violations of the best practices
suggested by "Effective C++" as reported by the -Weffc++ compiler
argument. The changes follow the patterns outlined below:
* A class with virtual functions can no longer publicly inherit base
classed without a vtable. The inherited object may either be moved
to a member variable, or inherited privately. The latter would be
used for classes that inherit 'List::Element' or 'Avl_node'. In order
to enable the 'List' and 'Avl_tree' to access the meta data, the
'List' must become a friend.
* Instead of adding a virtual destructor to abstract base classes,
we inherit the new 'Interface' class, which contains a virtual
destructor. This way, single-line abstract base classes can stay
as compact as they are now. The 'Interface' utility resides in
base/include/util/interface.h.
* With the new warnings enabled, all member variables must be explicitly
initialized. Basic types may be initialized with '='. All other types
are initialized with braces '{ ... }' or as class initializers. If
basic types and non-basic types appear in a row, it is nice to only
use the brace syntax (also for basic types) and align the braces.
* If a class contains pointers as members, it must now also provide a
copy constructor and assignment operator. In the most cases, one
would make them private, effectively disallowing the objects to be
copied. Unfortunately, this warning cannot be fixed be inheriting
our existing 'Noncopyable' class (the compiler fails to detect that
the inheriting class cannot be copied and still gives the error).
For now, we have to manually add declarations for both the copy
constructor and assignment operator as private class members. Those
declarations should be prepended with a comment like this:
/*
* Noncopyable
*/
Thread(Thread const &);
Thread &operator = (Thread const &);
In the future, we should revisit these places and try to replace
the pointers with references. In the presence of at least one
reference member, the compiler would no longer implicitly generate
a copy constructor. So we could remove the manual declaration.
Issue #465
2017-12-21 15:42:15 +01:00
|
|
|
/*
|
|
|
|
* Noncopyable
|
|
|
|
*/
|
|
|
|
Shared_object(Shared_object const &);
|
|
|
|
Shared_object &operator = (Shared_object const &);
|
|
|
|
|
2014-05-20 11:40:50 +02:00
|
|
|
public:
|
|
|
|
|
2016-10-30 15:17:24 +01:00
|
|
|
class Invalid_rom_module : public Genode::Exception { };
|
|
|
|
class Invalid_symbol : public Genode::Exception { };
|
2014-05-20 11:40:50 +02:00
|
|
|
|
2016-10-30 15:17:24 +01:00
|
|
|
enum Keep { DONT_KEEP, KEEP };
|
|
|
|
enum Bind { BIND_LAZY, BIND_NOW };
|
2014-05-20 11:40:50 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Load shared object and dependencies
|
|
|
|
*
|
2016-10-30 15:17:24 +01:00
|
|
|
* \param env Genode environment, needed to obtain the ROM module
|
|
|
|
* for the shared object and to populate the linker
|
|
|
|
* area of the component's address space
|
|
|
|
* \param md_alloc backing store for the linker's dynamically allocated
|
|
|
|
* meta data
|
|
|
|
* \param name ROM module name of shared object to load
|
|
|
|
* \param bind bind functions immediately (BIND_NOW) or on
|
|
|
|
* demand (BIND_LAZY)
|
|
|
|
* \param keep unload ELF object if no longer needed (DONT_KEEP),
|
|
|
|
* or keep ELF object loaded at all times (KEEP)
|
2014-05-20 11:40:50 +02:00
|
|
|
*
|
2016-10-30 15:17:24 +01:00
|
|
|
* \throw Invalid_rom_module
|
2014-05-20 11:40:50 +02:00
|
|
|
*/
|
2016-10-30 15:17:24 +01:00
|
|
|
Shared_object(Env &, Allocator &md_alloc, char const *name,
|
|
|
|
Bind bind, Keep keep);
|
2014-05-20 11:40:50 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Close and unload shared object
|
|
|
|
*/
|
|
|
|
~Shared_object();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Lookup a symbol in shared object and it's dependencies
|
|
|
|
*
|
|
|
|
* \param symbol Symbol name
|
|
|
|
*
|
|
|
|
* \throw Invalid_symbol
|
|
|
|
*
|
|
|
|
* \return Symbol address
|
|
|
|
*/
|
|
|
|
template<typename T = void *> T lookup(const char *symbol) const
|
|
|
|
{
|
2014-11-26 17:57:40 +01:00
|
|
|
return reinterpret_cast<T>(_lookup(symbol));
|
2014-05-20 11:40:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Link information
|
|
|
|
*/
|
|
|
|
struct Link_map
|
|
|
|
{
|
|
|
|
Genode::addr_t addr; /* load address */
|
2016-10-30 15:17:24 +01:00
|
|
|
char const *path; /* object path */
|
|
|
|
void const *dynamic; /* pointer to DYNAMIC section */
|
|
|
|
Link_map const *next;
|
|
|
|
Link_map const *prev;
|
2014-05-20 11:40:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return link map of shared object
|
|
|
|
*/
|
2016-10-30 15:17:24 +01:00
|
|
|
Link_map const &link_map() const;
|
2014-05-20 11:40:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct Genode::Address_info
|
|
|
|
{
|
Follow practices suggested by "Effective C++"
The patch adjust the code of the base, base-<kernel>, and os repository.
To adapt existing components to fix violations of the best practices
suggested by "Effective C++" as reported by the -Weffc++ compiler
argument. The changes follow the patterns outlined below:
* A class with virtual functions can no longer publicly inherit base
classed without a vtable. The inherited object may either be moved
to a member variable, or inherited privately. The latter would be
used for classes that inherit 'List::Element' or 'Avl_node'. In order
to enable the 'List' and 'Avl_tree' to access the meta data, the
'List' must become a friend.
* Instead of adding a virtual destructor to abstract base classes,
we inherit the new 'Interface' class, which contains a virtual
destructor. This way, single-line abstract base classes can stay
as compact as they are now. The 'Interface' utility resides in
base/include/util/interface.h.
* With the new warnings enabled, all member variables must be explicitly
initialized. Basic types may be initialized with '='. All other types
are initialized with braces '{ ... }' or as class initializers. If
basic types and non-basic types appear in a row, it is nice to only
use the brace syntax (also for basic types) and align the braces.
* If a class contains pointers as members, it must now also provide a
copy constructor and assignment operator. In the most cases, one
would make them private, effectively disallowing the objects to be
copied. Unfortunately, this warning cannot be fixed be inheriting
our existing 'Noncopyable' class (the compiler fails to detect that
the inheriting class cannot be copied and still gives the error).
For now, we have to manually add declarations for both the copy
constructor and assignment operator as private class members. Those
declarations should be prepended with a comment like this:
/*
* Noncopyable
*/
Thread(Thread const &);
Thread &operator = (Thread const &);
In the future, we should revisit these places and try to replace
the pointers with references. In the presence of at least one
reference member, the compiler would no longer implicitly generate
a copy constructor. So we could remove the manual declaration.
Issue #465
2017-12-21 15:42:15 +01:00
|
|
|
char const *path { nullptr }; /* path of shared object */
|
|
|
|
Genode::addr_t base { 0 }; /* base of shared object */
|
|
|
|
char const *name { nullptr }; /* name of symbol */
|
|
|
|
Genode::addr_t addr { 0 }; /* address of symbol */
|
2014-05-20 11:40:50 +02:00
|
|
|
|
|
|
|
class Invalid_address : public Genode::Exception { };
|
|
|
|
|
|
|
|
Address_info(Genode::addr_t addr);
|
|
|
|
};
|
|
|
|
|
2019-08-14 16:00:18 +02:00
|
|
|
|
|
|
|
class Genode::Dynamic_linker
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
struct Object_info
|
|
|
|
{
|
|
|
|
/* name of shared library, or "binary" for the main program */
|
|
|
|
typedef String<64> Name;
|
|
|
|
Name name;
|
|
|
|
|
|
|
|
Rom_dataspace_capability ds_cap;
|
|
|
|
|
|
|
|
/* pointer to the start of the read/writeable segment */
|
|
|
|
void *rw_start;
|
|
|
|
|
|
|
|
/* size of the read-writeable segment in bytes */
|
|
|
|
size_t rw_size;
|
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
struct For_each_fn : Interface
|
|
|
|
{
|
|
|
|
virtual void supply_object_info(Object_info const &) const = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void _for_each_loaded_object(Env &, For_each_fn const &);
|
|
|
|
|
2019-08-20 12:18:05 +02:00
|
|
|
static void *_respawn(Env &, char const *, char const *);
|
|
|
|
|
2019-08-14 16:00:18 +02:00
|
|
|
public:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Call 'fn' for each loaded object with 'Object_info' as argument
|
|
|
|
*/
|
|
|
|
template <typename FN>
|
|
|
|
static inline void for_each_loaded_object(Env &env, FN const &fn)
|
|
|
|
{
|
|
|
|
struct For_each_fn_impl : For_each_fn
|
|
|
|
{
|
|
|
|
FN const &fn;
|
|
|
|
|
|
|
|
void supply_object_info(Object_info const &info) const { fn(info); }
|
|
|
|
|
|
|
|
For_each_fn_impl(FN const &fn) : fn(fn) { }
|
|
|
|
|
|
|
|
} wrapped_fn { fn };
|
|
|
|
|
|
|
|
_for_each_loaded_object(env, wrapped_fn);
|
|
|
|
}
|
2019-08-20 12:18:05 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Prevent loaded shared object 'name' to be unloaded
|
|
|
|
*/
|
|
|
|
static void keep(Env &, char const *name);
|
|
|
|
|
|
|
|
typedef Shared_object::Invalid_rom_module Invalid_rom_module;
|
|
|
|
typedef Shared_object::Invalid_symbol Invalid_symbol;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replace executable binary
|
|
|
|
*
|
|
|
|
* \param binary_name ROM module name of new executable binary
|
|
|
|
* \param start_symbol symbol name of the binary's entry point
|
|
|
|
*
|
|
|
|
* \return pointer to entry point of the new executable
|
|
|
|
*
|
|
|
|
* \throw Invalid_rom_module
|
|
|
|
* \throw Invalid_symbol
|
|
|
|
*/
|
|
|
|
template<typename T = void *>
|
|
|
|
static T respawn(Env &env, char const *binary_name, char const *entrypoint_name)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<T>(_respawn(env, binary_name, entrypoint_name));
|
|
|
|
}
|
2019-08-14 16:00:18 +02:00
|
|
|
};
|
|
|
|
|
2014-05-20 11:40:50 +02:00
|
|
|
#endif /* _INCLUDE__BASE__SHARED_OBJECT_H_ */
|