mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-19 03:06:39 +00:00
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:
parent
fd8a209da2
commit
abdf422681
@ -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_ */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user