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/allocator.h>
|
||||||
#include <base/exception.h>
|
#include <base/exception.h>
|
||||||
#include <base/stdint.h>
|
#include <base/stdint.h>
|
||||||
|
#include <rom_session/rom_session.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
class Shared_object;
|
class Shared_object;
|
||||||
struct Address_info;
|
struct Address_info;
|
||||||
|
struct Dynamic_linker;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,4 +120,55 @@ struct Genode::Address_info
|
||||||
Address_info(Genode::addr_t addr);
|
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_ */
|
#endif /* _INCLUDE__BASE__SHARED_OBJECT_H_ */
|
||||||
|
|
|
@ -106,6 +106,7 @@ _ZN6Genode13Shared_objectD1Ev T
|
||||||
_ZN6Genode13Shared_objectD2Ev T
|
_ZN6Genode13Shared_objectD2Ev T
|
||||||
_ZN6Genode13sleep_foreverEv T
|
_ZN6Genode13sleep_foreverEv T
|
||||||
_ZN6Genode14Capability_map6insertEmm 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_entrypoint13_free_rpc_capERNS_10Pd_sessionENS_17Native_capabilityE T
|
||||||
_ZN6Genode14Rpc_entrypoint14_alloc_rpc_capERNS_10Pd_sessionENS_17Native_capabilityEm T
|
_ZN6Genode14Rpc_entrypoint14_alloc_rpc_capERNS_10Pd_sessionENS_17Native_capabilityEm T
|
||||||
_ZN6Genode14Rpc_entrypoint17_activation_entryEv T
|
_ZN6Genode14Rpc_entrypoint17_activation_entryEv T
|
||||||
|
|
|
@ -28,6 +28,12 @@ namespace Linker {
|
||||||
struct Phdr;
|
struct Phdr;
|
||||||
struct File;
|
struct File;
|
||||||
struct Elf_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; }
|
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
|
* 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)
|
void Component::construct(Genode::Env &env)
|
||||||
{
|
{
|
||||||
/* read configuration */
|
/* read configuration */
|
||||||
|
|
Loading…
Reference in New Issue