ldso: interface to get infos about loaded objects

This patch enhances the 'base/shared_object.h' interface of the dynamic
linker with the function 'for_each_loaded_object', which allows the
caller to obtain information about the currently loaded binary and
shared libraries.

The new interface is a base mechanism needed for implementing 'fork' in
the libc.

Issue #3478
This commit is contained in:
Norman Feske 2019-08-14 16:00:18 +02:00 committed by Christian Helmuth
parent fd8a209da2
commit abdf422681
4 changed files with 94 additions and 6 deletions

View File

@ -18,11 +18,13 @@
#include <base/allocator.h>
#include <base/exception.h>
#include <base/stdint.h>
#include <rom_session/rom_session.h>
namespace Genode {
class Shared_object;
struct Address_info;
struct Dynamic_linker;
};
@ -118,4 +120,55 @@ struct Genode::Address_info
Address_info(Genode::addr_t addr);
};
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 &);
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);
}
};
#endif /* _INCLUDE__BASE__SHARED_OBJECT_H_ */

View File

@ -106,6 +106,7 @@ _ZN6Genode13Shared_objectD1Ev T
_ZN6Genode13Shared_objectD2Ev T
_ZN6Genode13sleep_foreverEv T
_ZN6Genode14Capability_map6insertEmm T
_ZN6Genode14Dynamic_linker23_for_each_loaded_objectERNS_3EnvERKNS0_11For_each_fnE T
_ZN6Genode14Rpc_entrypoint13_free_rpc_capERNS_10Pd_sessionENS_17Native_capabilityE T
_ZN6Genode14Rpc_entrypoint14_alloc_rpc_capERNS_10Pd_sessionENS_17Native_capabilityEm T
_ZN6Genode14Rpc_entrypoint17_activation_entryEv T

View File

@ -28,6 +28,12 @@ namespace Linker {
struct Phdr;
struct File;
struct Elf_file;
static inline bool is_rx(Elf::Phdr const &ph) {
return ((ph.p_flags & PF_MASK) == (PF_R | PF_X)); }
static inline bool is_rw(Elf::Phdr const &ph) {
return ((ph.p_flags & PF_MASK) == (PF_R | PF_W)); }
}
@ -67,6 +73,17 @@ struct Linker::File
}
unsigned elf_phdr_count() const { return phdr.count; }
template <typename FN>
void with_rw_phdr(FN const &fn) const
{
for (unsigned i = 0; i < phdr.count; i++) {
if (is_rw(phdr.phdr[i])) {
fn(phdr.phdr[i]);
return;
}
}
}
};
@ -212,12 +229,6 @@ struct Linker::Elf_file : File
}
}
bool is_rx(Elf::Phdr const &ph) {
return ((ph.p_flags & PF_MASK) == (PF_R | PF_X)); }
bool is_rw(Elf::Phdr const &ph) {
return ((ph.p_flags & PF_MASK) == (PF_R | PF_W)); }
/**
* Load PT_LOAD segments
*/

View File

@ -659,6 +659,29 @@ void Genode::exec_static_constructors()
}
void Genode::Dynamic_linker::_for_each_loaded_object(Env &, For_each_fn const &fn)
{
Elf_object::obj_list()->for_each([&] (Object const &obj) {
Elf_file const *elf_file_ptr =
obj.file() ? dynamic_cast<Elf_file const *>(obj.file()) : nullptr;
if (!elf_file_ptr)
return;
elf_file_ptr->with_rw_phdr([&] (Elf::Phdr const &phdr) {
Object_info info { .name = obj.name(),
.ds_cap = elf_file_ptr->rom_cap,
.rw_start = (void *)(obj.reloc_base() + phdr.p_vaddr),
.rw_size = phdr.p_memsz };
fn.supply_object_info(info);
});
});
}
void Component::construct(Genode::Env &env)
{
/* read configuration */