From abdf422681c5f0a92f48022584fbfa4ec412b3a6 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 14 Aug 2019 16:00:18 +0200 Subject: [PATCH] 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 --- repos/base/include/base/shared_object.h | 53 +++++++++++++++++++++++++ repos/base/lib/symbols/ld | 1 + repos/base/src/lib/ldso/include/file.h | 23 ++++++++--- repos/base/src/lib/ldso/main.cc | 23 +++++++++++ 4 files changed, 94 insertions(+), 6 deletions(-) diff --git a/repos/base/include/base/shared_object.h b/repos/base/include/base/shared_object.h index cf586a9d7..fc24b71cf 100644 --- a/repos/base/include/base/shared_object.h +++ b/repos/base/include/base/shared_object.h @@ -18,11 +18,13 @@ #include #include #include +#include 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 + 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_ */ diff --git a/repos/base/lib/symbols/ld b/repos/base/lib/symbols/ld index 25b1a5d35..0afaeb5f6 100644 --- a/repos/base/lib/symbols/ld +++ b/repos/base/lib/symbols/ld @@ -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 diff --git a/repos/base/src/lib/ldso/include/file.h b/repos/base/src/lib/ldso/include/file.h index d951211f9..fce09531f 100644 --- a/repos/base/src/lib/ldso/include/file.h +++ b/repos/base/src/lib/ldso/include/file.h @@ -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 + 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 */ diff --git a/repos/base/src/lib/ldso/main.cc b/repos/base/src/lib/ldso/main.cc index 4d05713ba..9f3cc2111 100644 --- a/repos/base/src/lib/ldso/main.cc +++ b/repos/base/src/lib/ldso/main.cc @@ -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(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 */