diff --git a/repos/base-fiasco/lib/mk/base-common.mk b/repos/base-fiasco/lib/mk/base-common.mk index a0a4c7daa..beadde5fd 100644 --- a/repos/base-fiasco/lib/mk/base-common.mk +++ b/repos/base-fiasco/lib/mk/base-common.mk @@ -14,7 +14,7 @@ SRC_CC += allocator/allocator_avl.cc SRC_CC += heap/heap.cc heap/sliced_heap.cc SRC_CC += console/console.cc SRC_CC += child/child.cc -SRC_CC += process/process.cc +SRC_CC += child/process.cc SRC_CC += elf/elf_binary.cc SRC_CC += lock/lock.cc SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc diff --git a/repos/base-foc/lib/mk/base-common.inc b/repos/base-foc/lib/mk/base-common.inc index 30b7d61d2..21580206c 100644 --- a/repos/base-foc/lib/mk/base-common.inc +++ b/repos/base-foc/lib/mk/base-common.inc @@ -13,7 +13,7 @@ SRC_CC += allocator/allocator_avl.cc SRC_CC += heap/heap.cc heap/sliced_heap.cc SRC_CC += console/console.cc SRC_CC += child/child.cc -SRC_CC += process/process.cc +SRC_CC += child/process.cc SRC_CC += elf/elf_binary.cc SRC_CC += lock/lock.cc SRC_CC += env/spin_lock.cc env/cap_map.cc diff --git a/repos/base-hw/lib/mk/base-common.inc b/repos/base-hw/lib/mk/base-common.inc index b371cfa03..4dfd47315 100644 --- a/repos/base-hw/lib/mk/base-common.inc +++ b/repos/base-hw/lib/mk/base-common.inc @@ -14,7 +14,7 @@ SRC_CC += allocator/allocator_avl.cc SRC_CC += heap/heap.cc SRC_CC += heap/sliced_heap.cc SRC_CC += child/child.cc -SRC_CC += process/process.cc +SRC_CC += child/process.cc SRC_CC += elf/elf_binary.cc SRC_CC += console/console.cc SRC_CC += lock/lock.cc diff --git a/repos/base-linux/lib/mk/base-common.mk b/repos/base-linux/lib/mk/base-common.mk index e73a0e629..851e9d3e9 100644 --- a/repos/base-linux/lib/mk/base-common.mk +++ b/repos/base-linux/lib/mk/base-common.mk @@ -13,7 +13,7 @@ SRC_CC += allocator/allocator_avl.cc SRC_CC += heap/heap.cc heap/sliced_heap.cc SRC_CC += console/console.cc SRC_CC += child/child.cc -SRC_CC += process/process.cc +SRC_CC += child/process.cc SRC_CC += elf/elf_binary.cc SRC_CC += lock/lock.cc SRC_CC += env/region_map_mmap.cc env/debug.cc diff --git a/repos/base-linux/src/base/child/process.cc b/repos/base-linux/src/base/child/process.cc new file mode 100644 index 000000000..590b39b9b --- /dev/null +++ b/repos/base-linux/src/base/child/process.cc @@ -0,0 +1,114 @@ +/* + * \brief Implementation of process creation for Linux + * \author Norman Feske + * \date 2006-07-06 + */ + +/* + * Copyright (C) 2006-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include +#include +#include +#include + +/* base-internal includes */ +#include +#include + + +using namespace Genode; + + +/* + * Register main thread at core + * + * At this point in time, we do not yet know the TID and PID of the new + * thread. Those information will be provided to core by the constructor of + * the 'Platform_env' of the new process. + */ +Child::Process::Initial_thread::Initial_thread(Cpu_session &cpu, + Pd_session_capability pd, + char const *name) +: + cpu(cpu), + cap(cpu.create_thread(pd, Cpu_session::DEFAULT_WEIGHT, name)) +{ } + + +Child::Process::Initial_thread::~Initial_thread() { } + + +/* + * On Linux, the ELF loading is performed by the kernel + */ +Child::Process::Loaded_executable::Loaded_executable(Dataspace_capability, + Dataspace_capability, + Ram_session &, + Region_map &, + Region_map &, + Parent_capability) { } + + +Child::Process::Process(Dataspace_capability elf_ds, + Dataspace_capability ldso_ds, + Pd_session_capability pd_cap, + Pd_session &pd, + Ram_session &ram, + Cpu_session &cpu, + Region_map &local_rm, + Region_map &remote_rm, + Parent_capability parent_cap, + char const *name) +: + initial_thread(cpu, pd_cap, name), + loaded_executable(elf_ds, ldso_ds, ram, local_rm, remote_rm, parent_cap) +{ + /* skip loading when called during fork */ + if (!elf_ds.valid()) + return; + + /* attach ELF locally */ + addr_t elf_addr; + try { elf_addr = local_rm.attach(elf_ds); } + catch (Region_map::Attach_failed) { + PERR("local attach of ELF executable failed"); throw; } + + /* setup ELF object and read program entry pointer */ + Elf_binary elf(elf_addr); + if (!elf.valid()) + throw Invalid_executable(); + + bool const dynamically_linked = elf.is_dynamically_linked(); + + local_rm.detach(elf_addr); + + /* + * If the specified executable is a dynamically linked program, we load + * the dynamic linker instead. + */ + if (dynamically_linked) { + + if (!ldso_ds.valid()) { + PERR("attempt to start dynamic executable without dynamic linker"); + throw Missing_dynamic_linker(); + } + + elf_ds = ldso_ds; + } + + pd.assign_parent(parent_cap); + + Linux_native_pd_client + lx_pd(static_cap_cast(pd.native_pd())); + + lx_pd.start(elf_ds); +} + + +Child::Process::~Process() { } diff --git a/repos/base-linux/src/base/process/process.cc b/repos/base-linux/src/base/process/process.cc deleted file mode 100644 index d5355dbeb..000000000 --- a/repos/base-linux/src/base/process/process.cc +++ /dev/null @@ -1,95 +0,0 @@ -/* - * \brief Implementation of process creation for Linux - * \author Norman Feske - * \date 2006-07-06 - */ - -/* - * Copyright (C) 2006-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include -#include -#include - -/* base-internal includes */ -#include -#include - - -using namespace Genode; - -Dataspace_capability Process::_dynamic_linker_cap; - - -/** - * Check for dynamic ELF header - */ -static bool _check_dynamic_elf(Dataspace_capability elf_ds_cap) -{ - /* attach ELF locally */ - addr_t elf_addr; - - try { elf_addr = env()->rm_session()->attach(elf_ds_cap); } - catch (...) { return false; } - - /* - * If attach is called within core, it will return zero because - * Linux uses Core_rm_session. - */ - if (!elf_addr) return false; - - /* read program header and interpreter */ - Elf_binary elf((addr_t)elf_addr); - env()->rm_session()->detach((void *)elf_addr); - - return elf.is_dynamically_linked(); -} - - -Process::Process(Dataspace_capability elf_data_ds_cap, - Pd_session_capability pd_session_cap, - Ram_session_capability ram_session_cap, - Cpu_session_capability cpu_session_cap, - Region_map &, - Parent_capability parent_cap, - char const *name) -: - _pd_session_client(pd_session_cap), - _cpu_session_client(cpu_session_cap) -{ - /* check for dynamic program header */ - if (_check_dynamic_elf(elf_data_ds_cap)) { - if (!_dynamic_linker_cap.valid()) { - PERR("Dynamically linked file found, " - "but no dynamic linker binary present"); - return; - } - elf_data_ds_cap = _dynamic_linker_cap; - } - - /* - * Register main thread at core - * - * At this point in time, we do not yet know the TID and PID of the new - * thread. Those information will be provided to core by the constructor of - * the 'Platform_env' of the new process. - */ - enum { WEIGHT = Cpu_session::DEFAULT_WEIGHT }; - _thread0_cap = _cpu_session_client.create_thread(pd_session_cap, - WEIGHT, name); - - Linux_native_pd_client - lx_pd(static_cap_cast(_pd_session_client.native_pd())); - - _pd_session_client.assign_parent(parent_cap); - lx_pd.start(elf_data_ds_cap); -} - - -Process::~Process() { } diff --git a/repos/base-nova/lib/mk/base-common.mk b/repos/base-nova/lib/mk/base-common.mk index 5109da58c..b4874892b 100644 --- a/repos/base-nova/lib/mk/base-common.mk +++ b/repos/base-nova/lib/mk/base-common.mk @@ -13,7 +13,7 @@ SRC_CC += allocator/allocator_avl.cc SRC_CC += heap/heap.cc heap/sliced_heap.cc SRC_CC += console/console.cc SRC_CC += child/child.cc -SRC_CC += process/process.cc +SRC_CC += child/process.cc SRC_CC += elf/elf_binary.cc SRC_CC += lock/lock.cc SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc diff --git a/repos/base-okl4/lib/mk/base-common.mk b/repos/base-okl4/lib/mk/base-common.mk index a0a4c7daa..beadde5fd 100644 --- a/repos/base-okl4/lib/mk/base-common.mk +++ b/repos/base-okl4/lib/mk/base-common.mk @@ -14,7 +14,7 @@ SRC_CC += allocator/allocator_avl.cc SRC_CC += heap/heap.cc heap/sliced_heap.cc SRC_CC += console/console.cc SRC_CC += child/child.cc -SRC_CC += process/process.cc +SRC_CC += child/process.cc SRC_CC += elf/elf_binary.cc SRC_CC += lock/lock.cc SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc diff --git a/repos/base-pistachio/lib/mk/base-common.mk b/repos/base-pistachio/lib/mk/base-common.mk index 93b7ee797..68e0b9759 100644 --- a/repos/base-pistachio/lib/mk/base-common.mk +++ b/repos/base-pistachio/lib/mk/base-common.mk @@ -14,7 +14,7 @@ SRC_CC += allocator/allocator_avl.cc SRC_CC += heap/heap.cc heap/sliced_heap.cc SRC_CC += console/console.cc SRC_CC += child/child.cc -SRC_CC += process/process.cc +SRC_CC += child/process.cc SRC_CC += elf/elf_binary.cc SRC_CC += lock/lock.cc SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc diff --git a/repos/base-sel4/lib/mk/base-common.inc b/repos/base-sel4/lib/mk/base-common.inc index 1db231895..3ad62dbc1 100644 --- a/repos/base-sel4/lib/mk/base-common.inc +++ b/repos/base-sel4/lib/mk/base-common.inc @@ -13,7 +13,7 @@ SRC_CC += allocator/allocator_avl.cc SRC_CC += heap/heap.cc heap/sliced_heap.cc SRC_CC += console/console.cc SRC_CC += child/child.cc -SRC_CC += process/process.cc +SRC_CC += child/process.cc SRC_CC += elf/elf_binary.cc SRC_CC += lock/lock.cc SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h index b19cbb129..23d80475e 100644 --- a/repos/base/include/base/child.h +++ b/repos/base/include/base/child.h @@ -16,14 +16,16 @@ #include #include -#include #include #include #include -#include +#include +#include +#include +#include +#include namespace Genode { - struct Child_policy; struct Child; } @@ -157,12 +159,8 @@ class Genode::Child : protected Rpc_object /* PD session representing the protection domain of the child */ Pd_session_capability _pd; - /* PD session presented to the child as environment */ - Pd_session_capability _env_pd; - /* RAM session that contains the quota of the child */ Ram_session_capability _ram; - Ram_session_client _ram_session_client { _ram }; /* CPU session that contains the quota of the child */ Cpu_session_capability _cpu; @@ -175,11 +173,11 @@ class Genode::Child : protected Rpc_object /* heap for child-specific allocations using the child's quota */ Heap _heap; - Rpc_entrypoint *_entrypoint; + Rpc_entrypoint &_entrypoint; Parent_capability _parent_cap; /* child policy */ - Child_policy *_policy; + Child_policy &_policy; /* sessions opened by the child */ Lock _lock; /* protect list manipulation */ @@ -200,6 +198,89 @@ class Genode::Child : protected Rpc_object Lock _yield_request_lock; Resource_args _yield_request_args; + struct Process + { + struct Initial_thread + { + Cpu_session &cpu; + Thread_capability cap; + Initial_thread(Cpu_session &, Pd_session_capability, char const *); + ~Initial_thread(); + } initial_thread; + + class Missing_dynamic_linker : Exception { }; + class Invalid_executable : Exception { }; + + struct Loaded_executable + { + /** + * Initial instruction pointer of the new process, as defined + * in the header of the executable. + */ + addr_t entry; + + /** + * Constructor parses the executable and sets up segment + * dataspaces + * + * \param local_rm local address space, needed to make the + * segment dataspaces temporarily visible in + * the local address space to initialize their + * content with the data from the 'elf_ds' + * + * \throw Region_map::Attach_failed + * \throw Invalid_executable + * \throw Missing_dynamic_linker + * \throw Ram_session::Alloc_failed + */ + Loaded_executable(Dataspace_capability elf_ds, + Dataspace_capability ldso_ds, + Ram_session &ram, + Region_map &local_rm, + Region_map &remote_rm, + Parent_capability parent_cap); + } loaded_executable; + + /** + * Constructor + * + * \param ram RAM session used to allocate the BSS and + * DATA segments for the new process + * \param cpu CPU session used to create the initial thread + * \param parent parent of the new protection domain + * \param name name of protection domain + * + * \throw Cpu_session::Thread_creation_failed + * \throw Cpu_session::Out_of_metadata + * \throw Missing_dynamic_linker + * \throw Invalid_executable + * \throw Region_map::Attach_failed + * \throw Ram_session::Alloc_failed + * + * The other arguments correspond to those of 'Child::Child'. + * + * On construction of a protection domain, the initial thread is + * started immediately. + * + * The argument 'elf_ds' may be invalid to create an empty process. + * In this case, all process initialization steps except for the + * creation of the initial thread must be done manually, i.e., as + * done for implementing fork. + */ + Process(Dataspace_capability elf_ds, + Dataspace_capability ldso_ds, + Pd_session_capability pd_cap, + Pd_session &pd, + Ram_session &ram, + Cpu_session &cpu, + Region_map &local_rm, + Region_map &remote_rm, + Parent_capability parent, + char const *name); + + ~Process(); + }; + Process _process; /** @@ -225,52 +306,81 @@ class Genode::Child : protected Rpc_object * solely used for targeting resource donations during * 'Parent::upgrade_quota()' calls. */ - static Service *_parent_service(); + static Service &_parent_service(); public: + /** + * Exception type + * + * The startup of the physical process of the child may fail if the + * ELF binary is invalid, if the ELF binary is dynamically linked + * but no dynamic linker is provided, if the creation of the initial + * thread failed, or if the RAM session of the child is exhausted. + * Each of those conditions will result in a diagnostic log message. + * But for the error handling, we only distinguish the RAM exhaustion + * from the other conditions and subsume the latter as + * 'Process_startup_failed'. + */ + class Process_startup_failed : public Exception { }; + /** * Constructor * - * \param elf_ds dataspace containing the binary - * \param pd PD session representing the protection domain - * \param ram RAM session with the child's quota - * \param cpu CPU session with the child's quota - * \param entrypoint server entrypoint to serve the parent interface - * \param policy child policy + * \param elf_ds dataspace that contains the ELF binary + * \param ldso_ds dataspace that contains the dynamic linker, + * started if 'elf_ds' is a dynamically linked + * executable + * \param pd_cap capability of the new protection domain, + * used as argument for creating the initial + * thread, and handed out to the child as its + * environment + * \param pd PD session used for assigning the parent + * capability of the new process + * \param ram_cap RAM session capability handed out to the + * child as its environment + * \param ram RAM session used to allocate the BSS and + * DATA segments and as backing store for the + * local heap partition to keep child-specific + * meta data + * \param cpu_cap CPU session capability handed out to the + * child as its environment + * \param cpu CPU session for the new protection domain + * \param local_rm local address space + * \param remote_rm address space of new protection domain * \param pd_service provider of the 'pd' session * \param ram_service provider of the 'ram' session * \param cpu_service provider of the 'cpu' session * - * If assigning a separate entry point to each child, the host of - * multiple children is able to handle a blocking invocation of - * the parent interface of one child while still maintaining the - * service to other children, each having an independent entry - * point. + * \throw Ram_session::Alloc_failed + * \throw Process_startup_failed + * + * Usually, the pairs of 'pd' and 'pd_cap', 'cpu' and 'cpu_cap', + * 'ram' and 'ram_cap' belong to each other. References to the + * session interfaces are passed as separate arguments in addition + * to the capabilities to allow the creator of a child to operate on + * locally implemented sessions during the child initialization. * * The 'ram_service', 'cpu_service', and 'pd_service' arguments are * needed to direct quota upgrades referring to the resources of * the child environment. By default, we expect that these * resources are provided by the parent. - * - * The 'env_pd' argument override the PD session capability that is - * handed out as part of the child's environment. Normally, a child - * will receive the physical PD capability of the PD session at core. - * However, a runtime environment may wish to intercept the interaction - * of the child with its PD session by specifying a capability to a - * locally implemented PD session. */ Child(Dataspace_capability elf_ds, - Pd_session_capability pd, - Ram_session_capability ram, - Cpu_session_capability cpu, - Region_map &address_space, - Rpc_entrypoint *entrypoint, - Child_policy *policy, - Service &pd_service = *_parent_service(), - Service &ram_service = *_parent_service(), - Service &cpu_service = *_parent_service(), - Pd_session_capability env_pd = Pd_session_capability()); + Dataspace_capability ldso_ds, + Pd_session_capability pd_cap, + Pd_session &pd, + Ram_session_capability ram_cap, + Ram_session &ram, + Cpu_session_capability cpu_cap, + Cpu_session &cpu, + Region_map &local_rm, + Region_map &remote_rm, + Rpc_entrypoint &entrypoint, + Child_policy &policy, + Service &pd_service = _parent_service(), + Service &ram_service = _parent_service(), + Service &cpu_service = _parent_service()); /** * Destructor @@ -290,10 +400,6 @@ class Genode::Child : protected Rpc_object Cpu_session_capability cpu_session_cap() const { return _cpu; } Parent_capability parent_cap() const { return cap(); } - /** - */ - void env_pd(Pd_session_capability pd) { _env_pd = pd; } - /** * Discard all sessions to specified service * diff --git a/repos/base/include/base/process.h b/repos/base/include/base/process.h deleted file mode 100644 index 0701ac1da..000000000 --- a/repos/base/include/base/process.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * \brief Process-creation interface - * \author Norman Feske - * \date 2006-06-22 - */ - -/* - * Copyright (C) 2006-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__BASE__PROCESS_H_ -#define _INCLUDE__BASE__PROCESS_H_ - -#include -#include -#include -#include -#include - -namespace Genode { class Process; } - - -class Genode::Process -{ - private: - - Pd_session_client _pd_session_client; - Thread_capability _thread0_cap; - Cpu_session_client _cpu_session_client; - - static Dataspace_capability _dynamic_linker_cap; - - public: - - /** - * Constructor - * - * \param elf_data_ds dataspace that contains the elf binary - * \param pd_session the new protection domain - * \param ram_session RAM session providing the BSS for the - * new protection domain - * \param cpu_session CPU session for the new protection domain - * \param address_space region map of new protection domain - * \param parent parent of the new protection domain - * \param name name of protection domain (can be used - * for debugging) - * - * The dataspace 'elf_data_ds' can be read-only. - * - * On construction of a protection domain, execution of the initial - * thread is started immediately. - */ - Process(Dataspace_capability elf_data_ds, - Pd_session_capability pd_session, - Ram_session_capability ram_session, - Cpu_session_capability cpu_session, - Region_map &address_space, - Parent_capability parent, - char const *name); - - /** - * Destructor - * - * When called, the protection domain gets killed. - */ - ~Process(); - - static void dynamic_linker(Dataspace_capability dynamic_linker_cap) - { - _dynamic_linker_cap = dynamic_linker_cap; - } - - Thread_capability main_thread_cap() const { return _thread0_cap; } -}; - -#endif /* _INCLUDE__BASE__PROCESS_H_ */ diff --git a/repos/base/src/base/child/child.cc b/repos/base/src/base/child/child.cc index da2ffa818..3feb66e79 100644 --- a/repos/base/src/base/child/child.cc +++ b/repos/base/src/base/child/child.cc @@ -201,17 +201,17 @@ void Child::_remove_session(Child::Session *s) _session_list.remove(s); /* return session quota to the ram session of the child */ - if (_policy->ref_ram_session()->transfer_quota(_ram, s->donated_ram_quota())) + if (_policy.ref_ram_session()->transfer_quota(_ram, s->donated_ram_quota())) PERR("We ran out of our own quota"); destroy(heap(), s); } -Service *Child::_parent_service() +Service &Child::_parent_service() { static Parent_service parent_service(""); - return &parent_service; + return parent_service; } @@ -247,7 +247,7 @@ void Child::_close(Session* s) */ if (s->service()->ram_session_cap().valid()) { Ram_session_client server_ram(s->service()->ram_session_cap()); - if (server_ram.transfer_quota(_policy->ref_ram_cap(), + if (server_ram.transfer_quota(_policy.ref_ram_cap(), s->donated_ram_quota())) { PERR("Misbehaving server '%s'!", s->service()->name()); } @@ -303,7 +303,7 @@ void Child::announce(Parent::Service_name const &name, Root_capability root) { if (!name.is_valid_string()) return; - _policy->announce_service(name.string(), root, heap(), &_server); + _policy.announce_service(name.string(), root, heap(), &_server); } @@ -316,28 +316,28 @@ Session_capability Child::session(Parent::Service_name const &name, /* return sessions that we created for the child */ if (!strcmp("Env::ram_session", name.string())) return _ram; if (!strcmp("Env::cpu_session", name.string())) return _cpu; - if (!strcmp("Env::pd_session", name.string())) return _env_pd; + if (!strcmp("Env::pd_session", name.string())) return _pd; /* filter session arguments according to the child policy */ strncpy(_args, args.string(), sizeof(_args)); - _policy->filter_session_args(name.string(), _args, sizeof(_args)); + _policy.filter_session_args(name.string(), _args, sizeof(_args)); /* filter session affinity */ - Affinity const filtered_affinity = _policy->filter_session_affinity(affinity); + Affinity const filtered_affinity = _policy.filter_session_affinity(affinity); /* transfer the quota donation from the child's account to ourself */ size_t ram_quota = Arg_string::find_arg(_args, "ram_quota").ulong_value(0); - Transfer donation_from_child(ram_quota, _ram, _policy->ref_ram_cap()); + Transfer donation_from_child(ram_quota, _ram, _policy.ref_ram_cap()); - Service *service = _policy->resolve_session_request(name.string(), _args); + Service *service = _policy.resolve_session_request(name.string(), _args); /* raise an error if no matching service provider could be found */ if (!service) throw Service_denied(); /* transfer session quota from ourself to the service provider */ - Transfer donation_to_service(ram_quota, _policy->ref_ram_cap(), + Transfer donation_to_service(ram_quota, _policy.ref_ram_cap(), service->ram_session_cap()); /* create session */ @@ -391,10 +391,10 @@ void Child::upgrade(Session_capability to_session, Parent::Upgrade_args const &a Arg_string::find_arg(args.string(), "ram_quota").ulong_value(0); /* transfer quota from client to ourself */ - Transfer donation_from_child(ram_quota, _ram, _policy->ref_ram_cap()); + Transfer donation_from_child(ram_quota, _ram, _policy.ref_ram_cap()); /* transfer session quota from ourself to the service provider */ - Transfer donation_to_service(ram_quota, _policy->ref_ram_cap(), + Transfer donation_to_service(ram_quota, _policy.ref_ram_cap(), targeted_service->ram_session_cap()); try { targeted_service->upgrade(to_session, args.string()); } @@ -439,13 +439,13 @@ void Child::exit(int exit_value) * Note that the child object must not be destructed from by this function * because it is executed by the thread contained in the child object. */ - return _policy->exit(exit_value); + return _policy.exit(exit_value); } Thread_capability Child::main_thread_cap() const { - return _process.main_thread_cap(); + return _process.initial_thread.cap; } @@ -457,7 +457,7 @@ void Child::resource_avail_sigh(Signal_context_capability sigh) void Child::resource_request(Resource_args const &args) { - _policy->resource_request(args); + _policy.resource_request(args); } @@ -472,37 +472,48 @@ Parent::Resource_args Child::yield_request() } -void Child::yield_response() { _policy->yield_response(); } +void Child::yield_response() { _policy.yield_response(); } Child::Child(Dataspace_capability elf_ds, - Pd_session_capability pd, - Ram_session_capability ram, - Cpu_session_capability cpu, - Region_map &address_space, - Rpc_entrypoint *entrypoint, - Child_policy *policy, + Dataspace_capability ldso_ds, + Pd_session_capability pd_cap, + Pd_session &pd, + Ram_session_capability ram_cap, + Ram_session &ram, + Cpu_session_capability cpu_cap, + Cpu_session &cpu, + Region_map &local_rm, + Region_map &remote_rm, + Rpc_entrypoint &entrypoint, + Child_policy &policy, Service &pd_service, Service &ram_service, - Service &cpu_service, - Pd_session_capability env_pd) -: - _pd(pd), _env_pd(env_pd.valid() ? env_pd : pd), _ram(ram), - _cpu(cpu), _pd_service(pd_service), - _ram_service(ram_service), _cpu_service(cpu_service), - _heap(&_ram_session_client, env()->rm_session()), + Service &cpu_service) +try : + _pd(pd_cap), _ram(ram_cap), _cpu(cpu_cap), + _pd_service(pd_service), + _ram_service(ram_service), + _cpu_service(cpu_service), + _heap(&ram, &local_rm), _entrypoint(entrypoint), - _parent_cap(_entrypoint->manage(this)), + _parent_cap(_entrypoint.manage(this)), _policy(policy), - _server(ram), - _process(elf_ds, pd, ram, cpu, address_space, _parent_cap, policy->name()) + _server(_ram), + _process(elf_ds, ldso_ds, pd_cap, pd, ram, cpu, local_rm, remote_rm, + _parent_cap, policy.name()) { } +catch (Cpu_session::Thread_creation_failed) { throw Process_startup_failed(); } +catch (Cpu_session::Out_of_metadata) { throw Process_startup_failed(); } +catch (Process::Missing_dynamic_linker) { throw Process_startup_failed(); } +catch (Process::Invalid_executable) { throw Process_startup_failed(); } +catch (Region_map::Attach_failed) { throw Process_startup_failed(); } Child::~Child() { - _entrypoint->dissolve(this); - _policy->unregister_services(); + _entrypoint.dissolve(this); + _policy.unregister_services(); _session_pool.remove_all([&] (Session *s) { _close(s); }); } diff --git a/repos/base/src/base/child/process.cc b/repos/base/src/base/child/process.cc new file mode 100644 index 000000000..c9112cad5 --- /dev/null +++ b/repos/base/src/base/child/process.cc @@ -0,0 +1,213 @@ +/* + * \brief Process creation + * \author Norman Feske + * \author Christian Helmuth + * \date 2006-07-18 + */ + +/* + * Copyright (C) 2006-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include +#include + +/* base-internal includes */ +#include + +using namespace Genode; + + +Child::Process::Loaded_executable::Loaded_executable(Dataspace_capability elf_ds, + Dataspace_capability ldso_ds, + Ram_session &ram, + Region_map &local_rm, + Region_map &remote_rm, + Parent_capability parent_cap) +{ + /* skip loading when called during fork */ + if (!elf_ds.valid()) + return; + + /* attach ELF locally */ + addr_t elf_addr; + try { elf_addr = local_rm.attach(elf_ds); } + catch (Region_map::Attach_failed) { + PERR("local attach of ELF executable failed"); throw; } + + /* setup ELF object and read program entry pointer */ + Elf_binary elf(elf_addr); + if (!elf.valid()) + throw Invalid_executable(); + + /* + * If the specified executable is a dynamically linked program, we load + * the dynamic linker instead. + */ + if (elf.is_dynamically_linked()) { + + local_rm.detach(elf_addr); + + if (!ldso_ds.valid()) { + PERR("attempt to start dynamic executable without dynamic linker"); + throw Missing_dynamic_linker(); + } + + try { elf_addr = local_rm.attach(ldso_ds); } + catch (Region_map::Attach_failed) { + PERR("local attach of dynamic linker failed"); throw; } + + elf_ds = ldso_ds; + elf = Elf_binary(elf_addr); + } + + entry = elf.entry(); + + /* setup region map for the new pd */ + Elf_segment seg; + + for (unsigned n = 0; (seg = elf.get_segment(n)).valid(); ++n) { + if (seg.flags().skip) continue; + + /* same values for r/o and r/w segments */ + addr_t const addr = (addr_t)seg.start(); + size_t const size = seg.mem_size(); + + bool parent_info = false; + + bool const write = seg.flags().w; + bool const exec = seg.flags().x; + + if (write) { + + /* read-write segment */ + + /* + * Note that a failure to allocate a RAM dataspace after other + * segments were successfully allocated will not revert the + * previous allocations. The successful allocations will leak. + * In practice, this is not a problem as each component has its + * distinct RAM session. When the process creation failed, the + * entire RAM session will be destroyed and the memory will be + * regained. + */ + + /* alloc dataspace */ + Dataspace_capability ds_cap; + try { ds_cap = ram.alloc(size); } + catch (Ram_session::Alloc_failed) { + PERR("allocation of read-write segment failed"); throw; }; + + /* attach dataspace */ + void *base; + try { base = local_rm.attach(ds_cap); } + catch (Region_map::Attach_failed) { + PERR("local attach of segment dataspace failed"); throw; } + + void * const ptr = base; + addr_t const laddr = elf_addr + seg.file_offset(); + + /* copy contents and fill with zeros */ + memcpy(ptr, (void *)laddr, seg.file_size()); + if (size > seg.file_size()) + memset((void *)((addr_t)ptr + seg.file_size()), + 0, size - seg.file_size()); + + /* + * We store the parent information at the beginning of the first + * data segment + */ + if (!parent_info) { + Native_capability::Raw *raw = (Native_capability::Raw *)ptr; + + raw->dst = parent_cap.dst(); + raw->local_name = parent_cap.local_name(); + + parent_info = true; + } + + /* detach dataspace */ + local_rm.detach(base); + + off_t const offset = 0; + try { remote_rm.attach_at(ds_cap, addr, size, offset); } + catch (Region_map::Attach_failed) { + PERR("remote attach of read-write segment failed"); throw; } + + } else { + + /* read-only segment */ + + if (seg.file_size() != seg.mem_size()) + PWRN("filesz and memsz for read-only segment differ"); + + off_t const offset = seg.file_offset(); + try { + if (exec) + remote_rm.attach_executable(elf_ds, addr, size, offset); + else + remote_rm.attach_at(elf_ds, addr, size, offset); + } + catch (Region_map::Attach_failed) { + PERR("remote attach of read-only segment failed"); throw; } + } + } + + /* detach ELF */ + local_rm.detach((void *)elf_addr); +} + + +Child::Process::Initial_thread::Initial_thread(Cpu_session &cpu, + Pd_session_capability pd, + char const *name) +: + cpu(cpu), + cap(cpu.create_thread(pd, Cpu_session::DEFAULT_WEIGHT, name)) +{ } + + +Child::Process::Initial_thread::~Initial_thread() +{ + cpu.kill_thread(cap); +} + + +Child::Process::Process(Dataspace_capability elf_ds, + Dataspace_capability ldso_ds, + Pd_session_capability pd_cap, + Pd_session &pd, + Ram_session &ram, + Cpu_session &cpu, + Region_map &local_rm, + Region_map &remote_rm, + Parent_capability parent_cap, + char const *name) +: + initial_thread(cpu, pd_cap, name), + loaded_executable(elf_ds, ldso_ds, ram, local_rm, remote_rm, parent_cap) +{ + /* register parent interface for new protection domain */ + pd.assign_parent(parent_cap); + + /* + * Inhibit start of main thread if the new process happens to be forked + * from another. In this case, the main thread will get manually + * started after constructing the 'Process'. + */ + if (!elf_ds.valid()) + return; + + /* start main thread */ + if (cpu.start(initial_thread.cap, loaded_executable.entry, 0)) { + PERR("start of initial thread failed"); + throw Cpu_session::Thread_creation_failed(); + } +} + + +Child::Process::~Process() { } diff --git a/repos/base/src/base/process/process.cc b/repos/base/src/base/process/process.cc deleted file mode 100644 index ec062aeac..000000000 --- a/repos/base/src/base/process/process.cc +++ /dev/null @@ -1,285 +0,0 @@ -/* - * \brief Process creation - * \author Norman Feske - * \author Christian Helmuth - * \date 2006-07-18 - */ - -/* - * Copyright (C) 2006-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include -#include -#include -#include - -/* base-internal includes */ -#include - -using namespace Genode; - -Dataspace_capability Process::_dynamic_linker_cap; - -/** - * Check for dynamic ELF header - * - * \param elf_ds_cap dataspace containing the ELF binary - */ - -static bool _check_dynamic_elf(Dataspace_capability elf_ds_cap) -{ - /* attach ELF locally */ - addr_t elf_addr; - try { elf_addr = env()->rm_session()->attach(elf_ds_cap); } - catch (Region_map::Attach_failed) { return false; } - - /* read program header */ - Elf_binary elf((addr_t)elf_addr); - env()->rm_session()->detach((void *)elf_addr); - - return elf.is_dynamically_linked(); -} - -/** - * Parse ELF and setup segment dataspace - * - * \param parent_cap parent capability for child (i.e. myself) - * \param elf_ds_cap dataspace containing the ELF binary - * \param ram RAM session of the new protection domain - * \param rm region map of the new protection domain - */ -static addr_t _setup_elf(Parent_capability parent_cap, - Dataspace_capability elf_ds_cap, - Ram_session &ram, Region_map &rm) -{ - /* attach ELF locally */ - addr_t elf_addr; - try { elf_addr = env()->rm_session()->attach(elf_ds_cap); } - catch (Region_map::Attach_failed) { return 0; } - - /* setup ELF object and read program entry pointer */ - Elf_binary elf((addr_t)elf_addr); - if (!elf.valid()) - return 0; - - /* - * entry point of program - can be set to 0 to indicate errors in ELF - * handling - */ - addr_t entry = elf.entry(); - - /* setup region map for the new pd */ - Elf_segment seg; - - for (unsigned n = 0; (seg = elf.get_segment(n)).valid(); ++n) { - if (seg.flags().skip) continue; - - /* same values for r/o and r/w segments */ - addr_t addr = (addr_t)seg.start(); - size_t size = seg.mem_size(); - - bool parent_info = false; - off_t offset; - Dataspace_capability ds_cap; - void *out_ptr = 0; - - bool write = seg.flags().w; - bool exec = seg.flags().x; - - if (write) { - - /* read-write segment */ - offset = 0; - - /* alloc dataspace */ - try { ds_cap = ram.alloc(size); } - catch (Ram_session::Alloc_failed) { - PERR("Ram.alloc() failed"); - entry = 0; - break; - } - - /* attach dataspace */ - void *base; - try { base = env()->rm_session()->attach(ds_cap); } - catch (Region_map::Attach_failed) { - PERR("env()->rm_session()->attach() failed"); - entry = 0; - break; - } - - void *ptr = base; - addr_t laddr = elf_addr + seg.file_offset(); - - /* copy contents and fill with zeros */ - memcpy(ptr, (void *)laddr, seg.file_size()); - if (size > seg.file_size()) - memset((void *)((addr_t)ptr + seg.file_size()), - 0, size - seg.file_size()); - - /* - * we store the parent information at the beginning of the first - * data segment - */ - if (!parent_info) { - Native_capability::Raw *raw = (Native_capability::Raw *)ptr; - - raw->dst = parent_cap.dst(); - raw->local_name = parent_cap.local_name(); - - parent_info = true; - } - - /* detach dataspace */ - env()->rm_session()->detach(base); - - try { out_ptr = rm.attach_at(ds_cap, addr, size, offset); } - catch (Region_map::Attach_failed) { } - - } else { - - /* read-only segment */ - offset = seg.file_offset(); - ds_cap = elf_ds_cap; - - /* XXX currently we assume r/o segment sizes never differ */ - if (seg.file_size() != seg.mem_size()) - PWRN("filesz and memsz for read-only segment differ"); - - if (exec) - try { out_ptr = rm.attach_executable(ds_cap, addr, size, offset); } - catch (Region_map::Attach_failed) { } - else - try { out_ptr = rm.attach_at(ds_cap, addr, size, offset); } - catch (Region_map::Attach_failed) { } - } - - if ((addr_t)out_ptr != addr) - PWRN("addresses differ after attach (addr=%p out_ptr=%p)", - (void *)addr, out_ptr); - } - - /* detach ELF */ - env()->rm_session()->detach((void *)elf_addr); - - return entry; -} - - -Process::Process(Dataspace_capability elf_ds_cap, - Pd_session_capability pd_session_cap, - Ram_session_capability ram_session_cap, - Cpu_session_capability cpu_session_cap, - Region_map &address_space, - Parent_capability parent_cap, - char const *name) -: _pd_session_client(pd_session_cap), - _cpu_session_client(cpu_session_cap) -{ - if (!pd_session_cap.valid()) - return; - - enum Local_exception { THREAD_FAIL, ELF_FAIL, THREAD_START_FAIL }; - - /* XXX this only catches local exceptions */ - - /* FIXME find sane quota values or make them configurable */ - try { - int err; - - /* create thread0 */ - try { - enum { WEIGHT = Cpu_session::DEFAULT_WEIGHT }; - _thread0_cap = _cpu_session_client.create_thread(pd_session_cap, WEIGHT, name); - } catch (Cpu_session::Thread_creation_failed) { - PERR("creation of initial thread failed"); - throw THREAD_FAIL; - } catch (Cpu_session::Out_of_metadata) { - PERR("out of meta data while creating initial thread"); - throw THREAD_FAIL; - } - - /* - * The argument 'elf_ds_cap' may be invalid, which is not an error. - * This can happen when the process library is used to set up a process - * forked from another. In this case, all process initialization should - * be done except for the ELF loading and the startup of the main - * thread (as a forked process does not start its execution at the ELF - * entrypoint). - */ - bool const forked = !elf_ds_cap.valid(); - - /* check for dynamic program header */ - if (!forked && _check_dynamic_elf(elf_ds_cap)) { - if (!_dynamic_linker_cap.valid()) { - PERR("Dynamically linked file found, but no dynamic linker binary present"); - throw ELF_FAIL; - } - elf_ds_cap = _dynamic_linker_cap; - } - - /* init temporary allocator object */ - Ram_session_client ram(ram_session_cap); - - /* parse ELF binary and setup segment dataspaces */ - addr_t entry = 0; - if (elf_ds_cap.valid()) { - entry = _setup_elf(parent_cap, elf_ds_cap, ram, address_space); - if (!entry) { - PERR("Setup ELF failed"); - throw ELF_FAIL; - } - } - - /* register parent interface for new protection domain */ - _pd_session_client.assign_parent(parent_cap); - - /* - * Inhibit start of main thread if the new process happens to be forked - * from another. In this case, the main thread will get manually - * started after constructing the 'Process'. - */ - if (!forked) { - - /* start main thread */ - err = _cpu_session_client.start(_thread0_cap, entry, 0 /* unused */); - if (err) { - PERR("Thread0 startup failed"); - throw THREAD_START_FAIL; - } - } - } - catch (Local_exception cause) { - - switch (cause) { - - case THREAD_START_FAIL: - case ELF_FAIL: - - _cpu_session_client.kill_thread(_thread0_cap); - _thread0_cap = Thread_capability(); - - case THREAD_FAIL: - - default: - PWRN("unknown exception?"); - } - } -} - - -Process::~Process() -{ - /* - * Try to kill thread0, which was created in the process constructor. If - * this fails, do nothing. - */ - try { _cpu_session_client.kill_thread(_thread0_cap); } - catch (Genode::Ipc_error) { } -} diff --git a/repos/base/src/core/main.cc b/repos/base/src/core/main.cc index 1e556ffa9..83c1bc222 100644 --- a/repos/base/src/core/main.cc +++ b/repos/base/src/core/main.cc @@ -111,6 +111,16 @@ class Core_child : public Child_policy Service_registry &_local_services; + /* + * Dynamic linker, does not need to be valid because init is statically + * linked + */ + Dataspace_capability _ldso_ds; + + Pd_session_client _pd; + Ram_session_client _ram; + Cpu_session_client _cpu; + Region_map_client _address_space; Child _child; @@ -127,9 +137,10 @@ class Core_child : public Child_policy : _entrypoint(nullptr, STACK_SIZE, "init", false), _local_services(services), + _pd(pd), _ram(ram), _cpu(cpu), _address_space(Pd_session_client(pd).address_space()), - _child(elf_ds, pd, ram, cpu, _address_space, - &_entrypoint, this, + _child(elf_ds, _ldso_ds, _pd, _pd, _ram, _ram, _cpu, _cpu, + *env()->rm_session(), _address_space, _entrypoint, *this, *_local_services.find(Pd_session::service_name()), *_local_services.find(Ram_session::service_name()), *_local_services.find(Cpu_session::service_name())) diff --git a/repos/base/src/test/rm_fault/main.cc b/repos/base/src/test/rm_fault/main.cc index 79c14622a..831290182 100644 --- a/repos/base/src/test/rm_fault/main.cc +++ b/repos/base/src/test/rm_fault/main.cc @@ -79,7 +79,10 @@ class Test_child : public Child_policy */ Rpc_entrypoint _entrypoint; - Region_map_client _address_space; + Region_map_client _address_space; + Pd_session_client _pd; + Ram_session_client _ram; + Cpu_session_client _cpu; Child _child; @@ -97,8 +100,10 @@ class Test_child : public Child_policy Genode::Cap_session *cap) : _entrypoint(cap, STACK_SIZE, "child", false), - _address_space(pd.address_space()), - _child(elf_ds, pd, ram, cpu, _address_space, &_entrypoint, this), + _address_space(pd.address_space()), _pd(pd), _ram(ram), _cpu(cpu), + _child(elf_ds, Dataspace_capability(), _pd, _pd, _ram, _ram, + _cpu, _cpu, *env()->rm_session(), _address_space, + _entrypoint, *this), _log_service("LOG") { /* start execution of the new child */ diff --git a/repos/demo/include/launchpad/launchpad.h b/repos/demo/include/launchpad/launchpad.h index a9eb8881e..306cfd9ce 100644 --- a/repos/demo/include/launchpad/launchpad.h +++ b/repos/demo/include/launchpad/launchpad.h @@ -152,12 +152,9 @@ class Launchpad_child : public Genode::List::Element { private: - Launchpad *_launchpad; + static Genode::Dataspace_capability _ldso_ds(); - Genode::Rom_session_capability _rom; - Genode::Ram_session_capability _ram; - Genode::Cpu_session_capability _cpu; - Genode::Server _server; + Launchpad *_launchpad; /* * Entry point used for serving the parent interface and the @@ -167,7 +164,14 @@ class Launchpad_child : public Genode::List::Element enum { ENTRYPOINT_STACK_SIZE = 12*1024 }; Genode::Rpc_entrypoint _entrypoint; - Genode::Region_map_client _address_space; + Genode::Region_map_client _address_space; + + Genode::Rom_session_client _rom; + Genode::Pd_session_client _pd; + Genode::Ram_session_client _ram; + Genode::Cpu_session_client _cpu; + + Genode::Server _server; Launchpad_child_policy _policy; Genode::Child _child; @@ -187,13 +191,17 @@ class Launchpad_child : public Genode::List::Element Launchpad *launchpad) : _launchpad(launchpad), - _rom(rom), _ram(ram), _cpu(cpu), _server(_ram), _entrypoint(cap_session, ENTRYPOINT_STACK_SIZE, name, false), _address_space(Genode::Pd_session_client(pd).address_space()), + _rom(rom), _pd(pd), _ram(ram), _cpu(cpu), _server(_ram), _policy(name, &_server, parent_services, child_services, config_ds, elf_ds, &_entrypoint), - _child(elf_ds, pd, ram, cpu, _address_space, &_entrypoint, &_policy) { - _entrypoint.activate(); } + _child(elf_ds, _ldso_ds(), _pd, _pd, _ram, _ram, _cpu, _cpu, + *Genode::env()->rm_session(), _address_space, + _entrypoint, _policy) + { + _entrypoint.activate(); + } Genode::Rom_session_capability rom_session_cap() { return _rom; } Genode::Ram_session_capability ram_session_cap() { return _ram; } diff --git a/repos/demo/src/app/launchpad/main.cc b/repos/demo/src/app/launchpad/main.cc index 39cfac8b2..80aa07f8e 100644 --- a/repos/demo/src/app/launchpad/main.cc +++ b/repos/demo/src/app/launchpad/main.cc @@ -92,12 +92,6 @@ int main(int argc, char **argv) { using namespace Scout; - /* look for dynamic linker */ - try { - static Genode::Rom_connection rom("ld.lib.so"); - Genode::Process::dynamic_linker(rom.dataspace()); - } catch (...) { } - static Nitpicker::Connection nitpicker; static Platform pf(*nitpicker.input()); diff --git a/repos/demo/src/lib/launchpad/launchpad.cc b/repos/demo/src/lib/launchpad/launchpad.cc index 4fc403511..840c9e8d4 100644 --- a/repos/demo/src/lib/launchpad/launchpad.cc +++ b/repos/demo/src/lib/launchpad/launchpad.cc @@ -412,6 +412,23 @@ static Timer::Session *timer_session() } +Dataspace_capability Launchpad_child::_ldso_ds() +{ + static bool first_attempt_failed = false; + + if (!first_attempt_failed) { + try { + static Rom_connection rom("ld.lib.so"); + static Dataspace_capability ds = rom.dataspace(); + return ds; + } catch (...) { } + } + + first_attempt_failed = true; + return Dataspace_capability(); +} + + /* construct child-destructor thread early - in case we run out of threads */ static Child_destructor_thread child_destructor; diff --git a/repos/gems/src/app/launcher/context_dialog.h b/repos/gems/src/app/launcher/context_dialog.h index a7e811ce9..ee6a00a37 100644 --- a/repos/gems/src/app/launcher/context_dialog.h +++ b/repos/gems/src/app/launcher/context_dialog.h @@ -106,10 +106,12 @@ class Launcher::Context_dialog : Input_event_handler, Dialog_generator, public: Context_dialog(Server::Entrypoint &ep, Cap_session &cap, Ram_session &ram, + Dataspace_capability ldso_ds, Report_rom_slave &report_rom_slave, Response_handler &response_handler) : - _dialog(ep, cap, ram, report_rom_slave, "context_dialog", "context_hover", + _dialog(ep, cap, ram, ldso_ds, report_rom_slave, + "context_dialog", "context_hover", *this, *this, *this, *this, Fading_dialog::Position(364, 64)), _response_handler(response_handler) diff --git a/repos/gems/src/app/launcher/fading_dialog.h b/repos/gems/src/app/launcher/fading_dialog.h index 2853f324d..8e9fe737c 100644 --- a/repos/gems/src/app/launcher/fading_dialog.h +++ b/repos/gems/src/app/launcher/fading_dialog.h @@ -212,6 +212,7 @@ class Launcher::Fading_dialog : private Input_event_handler Fading_dialog(Server::Entrypoint &ep, Cap_session &cap, Ram_session &ram, + Dataspace_capability ldso_ds, Report_rom_slave &report_rom_slave, char const *dialog_name, char const *hover_name, @@ -232,8 +233,9 @@ class Launcher::Fading_dialog : private Input_event_handler _hover_update_dispatcher(ep, *this, &Fading_dialog::_handle_hover_update), _fader_slave_ep(&cap, _fader_slave_ep_stack_size, "nit_fader"), _nitpicker_service(ep, _fader_slave_ep, *this), - _nit_fader_slave(_fader_slave_ep, ram, _nitpicker_service), - _menu_view_slave(cap, ram, _nit_fader_slave.nitpicker_session("menu"), + _nit_fader_slave(_fader_slave_ep, ram, _nitpicker_service, ldso_ds), + _menu_view_slave(cap, ram, ldso_ds, + _nit_fader_slave.nitpicker_session("menu"), _dialog_rom, _hover_report, initial_position) { Rom_session_client(_hover_rom).sigh(_hover_update_dispatcher); diff --git a/repos/gems/src/app/launcher/main.cc b/repos/gems/src/app/launcher/main.cc index fbb47b2a7..53b991a9c 100644 --- a/repos/gems/src/app/launcher/main.cc +++ b/repos/gems/src/app/launcher/main.cc @@ -30,6 +30,17 @@ struct Launcher::Main { Server::Entrypoint &_ep; + Genode::Dataspace_capability _request_ldso_ds() + { + try { + static Genode::Rom_connection rom("ld.lib.so"); + return rom.dataspace(); + } catch (...) { } + return Genode::Dataspace_capability(); + } + + Genode::Dataspace_capability _ldso_ds = _request_ldso_ds(); + Genode::Cap_connection _cap; char const *_report_rom_config = @@ -65,9 +76,11 @@ struct Launcher::Main Genode::Signal_rpc_member
_exited_child_dispatcher = { _ep, *this, &Main::_handle_exited_child }; - Subsystem_manager _subsystem_manager { _ep, _cap, _exited_child_dispatcher }; + Subsystem_manager _subsystem_manager { _ep, _cap, _exited_child_dispatcher, + _ldso_ds }; - Panel_dialog _panel_dialog { _ep, _cap, *env()->ram_session(), *env()->heap(), + Panel_dialog _panel_dialog { _ep, _cap, *env()->ram_session(), _ldso_ds, + *env()->heap(), _report_rom_slave, _subsystem_manager, _nitpicker }; void _handle_config(unsigned); @@ -184,12 +197,6 @@ namespace Server { void construct(Entrypoint &ep) { - /* look for dynamic linker */ - try { - static Rom_connection rom("ld.lib.so"); - Process::dynamic_linker(rom.dataspace()); - } catch (...) { } - static Launcher::Main desktop(ep); } } diff --git a/repos/gems/src/app/launcher/menu_dialog.h b/repos/gems/src/app/launcher/menu_dialog.h index 7ee1dfac0..b611ebd84 100644 --- a/repos/gems/src/app/launcher/menu_dialog.h +++ b/repos/gems/src/app/launcher/menu_dialog.h @@ -104,11 +104,13 @@ class Launcher::Menu_dialog : Input_event_handler, Dialog_generator, public: Menu_dialog(Server::Entrypoint &ep, Cap_session &cap, Ram_session &ram, + Dataspace_capability ldso_ds, Report_rom_slave &report_rom_slave, Response_handler &response_handler) : _response_handler(response_handler), - _dialog(ep, cap, ram, report_rom_slave, "menu_dialog", "menu_hover", + _dialog(ep, cap, ram, ldso_ds, report_rom_slave, + "menu_dialog", "menu_hover", *this, *this, *this, *this, _position) { diff --git a/repos/gems/src/app/launcher/menu_view_slave.h b/repos/gems/src/app/launcher/menu_view_slave.h index cae8ba9b6..04e4e9394 100644 --- a/repos/gems/src/app/launcher/menu_view_slave.h +++ b/repos/gems/src/app/launcher/menu_view_slave.h @@ -144,6 +144,7 @@ class Launcher::Menu_view_slave * dataspace */ Menu_view_slave(Genode::Cap_session &cap, Genode::Ram_session &ram, + Genode::Dataspace_capability ldso_ds, Capability nitpicker_session, Capability dialog_rom_session, Capability hover_report_session, @@ -152,7 +153,7 @@ class Launcher::Menu_view_slave _ep(&cap, _ep_stack_size, "nit_fader"), _policy(_ep, ram, nitpicker_session, dialog_rom_session, hover_report_session, initial_position), - _slave(_ep, _policy, _quota) + _slave(_ep, _policy, _quota, env()->ram_session_cap(), ldso_ds) { } void position(Position position) { _policy.position(position); } diff --git a/repos/gems/src/app/launcher/nit_fader_slave.h b/repos/gems/src/app/launcher/nit_fader_slave.h index 6d0f1b4e9..61ae260a4 100644 --- a/repos/gems/src/app/launcher/nit_fader_slave.h +++ b/repos/gems/src/app/launcher/nit_fader_slave.h @@ -113,10 +113,11 @@ class Launcher::Nit_fader_slave * dataspace */ Nit_fader_slave(Rpc_entrypoint &ep, Ram_session &ram, - Genode::Service &nitpicker_service) + Genode::Service &nitpicker_service, + Genode::Dataspace_capability ldso_ds) : _policy(ep, ram, nitpicker_service), - _slave(ep, _policy, _quota), + _slave(ep, _policy, _quota, env()->ram_session_cap(), ldso_ds), _nitpicker_root(_policy.nitpicker_root()) { visible(false); diff --git a/repos/gems/src/app/launcher/panel_dialog.h b/repos/gems/src/app/launcher/panel_dialog.h index 777fa73fb..596bfc159 100644 --- a/repos/gems/src/app/launcher/panel_dialog.h +++ b/repos/gems/src/app/launcher/panel_dialog.h @@ -251,6 +251,7 @@ class Launcher::Panel_dialog : Input_event_handler, Dialog_generator, public: Panel_dialog(Server::Entrypoint &ep, Cap_session &cap, Ram_session &ram, + Dataspace_capability ldso_ds, Genode::Allocator &alloc, Report_rom_slave &report_rom_slave, Subsystem_manager &subsystem_manager, @@ -259,12 +260,13 @@ class Launcher::Panel_dialog : Input_event_handler, Dialog_generator, _alloc(alloc), _subsystem_manager(subsystem_manager), _nitpicker(nitpicker), - _dialog(ep, cap, ram, report_rom_slave, "panel_dialog", "panel_hover", + _dialog(ep, cap, ram, ldso_ds, report_rom_slave, + "panel_dialog", "panel_hover", *this, *this, *this, *this, _position), _timer_dispatcher(ep, *this, &Panel_dialog::_handle_timer), - _context_dialog(ep, cap, ram, report_rom_slave, *this), - _menu_dialog(ep, cap, ram, report_rom_slave, *this) + _context_dialog(ep, cap, ram, ldso_ds, report_rom_slave, *this), + _menu_dialog(ep, cap, ram, ldso_ds, report_rom_slave, *this) { _elements.insert(&_menu_button); _timer.sigh(_timer_dispatcher); diff --git a/repos/gems/src/app/launcher/subsystem_manager.h b/repos/gems/src/app/launcher/subsystem_manager.h index 586acd714..6dc0d90b1 100644 --- a/repos/gems/src/app/launcher/subsystem_manager.h +++ b/repos/gems/src/app/launcher/subsystem_manager.h @@ -27,6 +27,7 @@ namespace Launcher { using Decorator::string_attribute; } + /*************** ** Utilities ** ***************/ @@ -60,8 +61,9 @@ class Launcher::Subsystem_manager private: - Server::Entrypoint &_ep; - Cap_session &_cap; + Server::Entrypoint &_ep; + Cap_session &_cap; + Dataspace_capability _ldso_ds; struct Child : Child_base, List::Element { @@ -74,7 +76,8 @@ class Launcher::Subsystem_manager size_t ram_quota, size_t ram_limit, Signal_context_capability yield_response_sig_cap, - Signal_context_capability exit_sig_cap) + Signal_context_capability exit_sig_cap, + Dataspace_capability ldso_ds) : Child_base(ram, label.string(), @@ -83,7 +86,8 @@ class Launcher::Subsystem_manager ram_quota, ram_limit, yield_response_sig_cap, - exit_sig_cap) + exit_sig_cap, + ldso_ds) { } }; @@ -184,9 +188,11 @@ class Launcher::Subsystem_manager public: Subsystem_manager(Server::Entrypoint &ep, Cap_session &cap, - Genode::Signal_context_capability exited_child_sig_cap) + Genode::Signal_context_capability exited_child_sig_cap, + Dataspace_capability ldso_ds) : - _ep(ep), _cap(cap), _exited_child_sig_cap(exited_child_sig_cap) + _ep(ep), _cap(cap), _ldso_ds(ldso_ds), + _exited_child_sig_cap(exited_child_sig_cap) { } /** @@ -210,7 +216,7 @@ class Launcher::Subsystem_manager Child(_ram, label, binary_name.string(), _cap, ram_config.quantum, ram_config.limit, _yield_broadcast_dispatcher, - _exited_child_sig_cap); + _exited_child_sig_cap, _ldso_ds); /* configure child */ try { diff --git a/repos/libports/src/app/qt5/qt_avplay/main.cpp b/repos/libports/src/app/qt5/qt_avplay/main.cpp index de37c2a27..997b333af 100644 --- a/repos/libports/src/app/qt5/qt_avplay/main.cpp +++ b/repos/libports/src/app/qt5/qt_avplay/main.cpp @@ -19,7 +19,6 @@ /* Genode includes */ #include -#include #include @@ -42,14 +41,6 @@ int main(int argc, char *argv[]) load_stylesheet(); - /* look for dynamic linker */ - try { - static Genode::Rom_connection ldso_rom("ld.lib.so"); - Genode::Process::dynamic_linker(ldso_rom.dataspace()); - } catch (...) { - PERR("ld.lib.so not found"); - } - QMember main_window; main_window->show(); diff --git a/repos/libports/src/app/qt5/qt_launchpad/main.cpp b/repos/libports/src/app/qt5/qt_launchpad/main.cpp index 2462a2248..e1b204a61 100644 --- a/repos/libports/src/app/qt5/qt_launchpad/main.cpp +++ b/repos/libports/src/app/qt5/qt_launchpad/main.cpp @@ -17,14 +17,6 @@ int main(int argc, char *argv[]) { - /* look for dynamic linker */ - try { - static Genode::Rom_connection rom("ld.lib.so"); - Genode::Process::dynamic_linker(rom.dataspace()); - } catch (...) { } - - int result; - static QApplication a(argc, argv); static Qt_launchpad launchpad(Genode::env()->ram_session()->quota()); @@ -38,7 +30,7 @@ int main(int argc, char *argv[]) a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit())); - result = a.exec(); + int const result = a.exec(); return result; } diff --git a/repos/os/include/cli_monitor/child.h b/repos/os/include/cli_monitor/child.h index 8cd5944a0..5f3704004 100644 --- a/repos/os/include/cli_monitor/child.h +++ b/repos/os/include/cli_monitor/child.h @@ -108,7 +108,8 @@ class Child_base : public Genode::Child_policy Genode::size_t ram_quota, Genode::size_t ram_limit, Genode::Signal_context_capability yield_response_sig_cap, - Genode::Signal_context_capability exit_sig_cap) + Genode::Signal_context_capability exit_sig_cap, + Genode::Dataspace_capability ldso_ds) : _ram(ram), _label(label), @@ -120,9 +121,10 @@ class Child_base : public Genode::Child_policy _labeling_policy(_label.string()), _binary_policy("binary", _binary_rom.dataspace(), &_entrypoint), _config_policy("config", _entrypoint, &_resources.ram), - _child(_binary_rom.dataspace(), _resources.pd.cap(), - _resources.ram.cap(), _resources.cpu.cap(), _address_space, - &_entrypoint, this), + _child(_binary_rom.dataspace(), ldso_ds, _resources.pd, _resources.pd, + _resources.ram, _resources.ram, _resources.cpu, _resources.cpu, + *Genode::env()->rm_session(), _address_space, + _entrypoint, *this), _yield_response_sigh_cap(yield_response_sig_cap), _exit_sig_cap(exit_sig_cap) { } diff --git a/repos/os/include/init/child.h b/repos/os/include/init/child.h index 125b5bbb4..5c8fb9144 100644 --- a/repos/os/include/init/child.h +++ b/repos/os/include/init/child.h @@ -370,7 +370,7 @@ class Init::Child : Genode::Child_policy Genode::Xml_node _default_route_node; - Name_registry *_name_registry; + Name_registry &_name_registry; /** * Unique child name and file name of ELF binary @@ -389,7 +389,7 @@ class Init::Child : Genode::Child_policy * \param start_node XML start node * \param registry registry tracking unique names */ - Name(Genode::Xml_node start_node, Name_registry const *registry) { + Name(Genode::Xml_node start_node, Name_registry const ®istry) { try { start_node.attribute("name").value(unique, sizeof(unique)); } catch (Genode::Xml_node::Nonexistent_attribute) { @@ -397,7 +397,7 @@ class Init::Child : Genode::Child_policy throw; } /* check for a name confict with the other children */ - if (!registry->is_unique(unique)) { + if (!registry.is_unique(unique)) { PERR("Child name \"%s\" is not unique", unique); throw Child_name_is_not_unique(); } @@ -527,8 +527,8 @@ class Init::Child : Genode::Child_policy Genode::Region_map_client _address_space { _resources.pd.address_space() }; Genode::Child _child; - Genode::Service_registry *_parent_services; - Genode::Service_registry *_child_services; + Genode::Service_registry &_parent_services; + Genode::Service_registry &_child_services; /** * Policy helpers @@ -542,14 +542,15 @@ class Init::Child : Genode::Child_policy public: - Child(Genode::Xml_node start_node, - Genode::Xml_node default_route_node, - Name_registry *name_registry, - long prio_levels, + Child(Genode::Xml_node start_node, + Genode::Xml_node default_route_node, + Name_registry &name_registry, + long prio_levels, Genode::Affinity::Space const &affinity_space, - Genode::Service_registry *parent_services, - Genode::Service_registry *child_services, - Genode::Cap_session *cap_session) + Genode::Service_registry &parent_services, + Genode::Service_registry &child_services, + Genode::Cap_session &cap_session, + Genode::Dataspace_capability ldso_ds) : _list_element(this), _start_node(start_node), @@ -558,13 +559,16 @@ class Init::Child : Genode::Child_policy _name(start_node, name_registry), _resources(start_node, _name.unique, prio_levels, affinity_space), - _entrypoint(cap_session, ENTRYPOINT_STACK_SIZE, _name.unique, false, _resources.affinity.location()), + _entrypoint(&cap_session, ENTRYPOINT_STACK_SIZE, _name.unique, false, _resources.affinity.location()), _binary_rom(_name.file, _name.file), _binary_rom_ds(_binary_rom.dataspace()), _config(_resources.ram.cap(), start_node), _server(_resources.ram.cap()), - _child(_binary_rom_ds, _resources.pd.cap(), _resources.ram.cap(), - _resources.cpu.cap(), _address_space, &_entrypoint, this), + _child(_binary_rom_ds, ldso_ds, + _resources.pd, _resources.pd, + _resources.ram, _resources.ram, + _resources.cpu, _resources.cpu, + *Genode::env()->rm_session(), _address_space, _entrypoint, *this), _parent_services(parent_services), _child_services(child_services), _labeling_policy(_name.unique), @@ -600,7 +604,7 @@ class Init::Child : Genode::Child_policy if (config_verbose) Genode::printf(" provides service %s\n", name); - child_services->insert(new (_child.heap()) + child_services.insert(new (_child.heap()) Routed_service(name, &_server)); } @@ -609,8 +613,8 @@ class Init::Child : Genode::Child_policy virtual ~Child() { Genode::Service *s; - while ((s = _child_services->find_by_server(&_server))) { - _child_services->remove(s); + while ((s = _child_services.find_by_server(&_server))) { + _child_services.remove(s); } } @@ -667,7 +671,7 @@ class Init::Child : Genode::Child_policy for (; ; target = target.next()) { if (target.has_type("parent")) { - service = _parent_services->find(service_name); + service = _parent_services.find(service_name); if (service) return service; @@ -682,13 +686,13 @@ class Init::Child : Genode::Child_policy server_name[0] = 0; target.attribute("name").value(server_name, sizeof(server_name)); - Genode::Server *server = _name_registry->lookup_server(server_name); + Genode::Server *server = _name_registry.lookup_server(server_name); if (!server) { PWRN("%s: invalid route to non-existing server \"%s\"", name(), server_name); return 0; } - service = _child_services->find(service_name, server); + service = _child_services.find(service_name, server); if (service) return service; @@ -699,11 +703,11 @@ class Init::Child : Genode::Child_policy } if (target.has_type("any-child")) { - if (_child_services->is_ambiguous(service_name)) { + if (_child_services.is_ambiguous(service_name)) { PERR("%s: ambiguous routes to service \"%s\"", name(), service_name); return 0; } - service = _child_services->find(service_name); + service = _child_services.find(service_name); if (service) return service; @@ -767,7 +771,7 @@ class Init::Child : Genode::Child_policy Genode::printf("child \"%s\" announces service \"%s\"\n", name(), service_name); - Genode::Service *s = _child_services->find(service_name, &_server); + Genode::Service *s = _child_services.find(service_name, &_server); Routed_service *rs = dynamic_cast(s); if (!s || !rs) { PERR("%s: illegal announcement of service \"%s\"", name(), service_name); diff --git a/repos/os/include/os/slave.h b/repos/os/include/os/slave.h index 04b840721..ef1fbdd27 100644 --- a/repos/os/include/os/slave.h +++ b/repos/os/include/os/slave.h @@ -187,12 +187,13 @@ class Genode::Slave Slave(Genode::Rpc_entrypoint &entrypoint, Slave_policy &slave_policy, Genode::size_t ram_quota, - Ram_session_capability ram_ref_cap = env()->ram_session_cap()) + Ram_session_capability ram_ref_cap = env()->ram_session_cap(), + Dataspace_capability ldso_ds = Dataspace_capability()) : _resources(slave_policy.name(), ram_quota, ram_ref_cap), - _child(slave_policy.binary(), _resources.pd.cap(), - _resources.ram.cap(), _resources.cpu.cap(), - _address_space, &entrypoint, &slave_policy) + _child(slave_policy.binary(), ldso_ds, _resources.pd, _resources.pd, + _resources.ram, _resources.ram, _resources.cpu, _resources.cpu, + *env()->rm_session(), _address_space, entrypoint, slave_policy) { } Genode::Ram_connection &ram() { return _resources.ram; } diff --git a/repos/os/src/app/cli_monitor/child.h b/repos/os/src/app/cli_monitor/child.h index cd66d2a58..947003bbe 100644 --- a/repos/os/src/app/cli_monitor/child.h +++ b/repos/os/src/app/cli_monitor/child.h @@ -31,7 +31,8 @@ struct Child : Child_base, List::Element Genode::size_t ram_quota, Genode::size_t ram_limit, Genode::Signal_context_capability yield_response_sig_cap, - Genode::Signal_context_capability exit_sig_cap) + Genode::Signal_context_capability exit_sig_cap, + Genode::Dataspace_capability ldso_ds) : Child_base(ram, label, @@ -40,7 +41,8 @@ struct Child : Child_base, List::Element ram_quota, ram_limit, yield_response_sig_cap, - exit_sig_cap), + exit_sig_cap, + ldso_ds), argument(label, "subsystem") { } }; diff --git a/repos/os/src/app/cli_monitor/main.cc b/repos/os/src/app/cli_monitor/main.cc index 77c6b80aa..5918e828b 100644 --- a/repos/os/src/app/cli_monitor/main.cc +++ b/repos/os/src/app/cli_monitor/main.cc @@ -98,9 +98,10 @@ static Subsystem_config_registry &subsystem_config_registry() int main(int argc, char **argv) { /* look for dynamic linker */ + Genode::Dataspace_capability ldso_ds; try { static Genode::Rom_connection rom("ld.lib.so"); - Genode::Process::dynamic_linker(rom.dataspace()); + ldso_ds = rom.dataspace(); } catch (...) { } using Genode::Signal_context; @@ -141,7 +142,8 @@ int main(int argc, char **argv) commands.insert(new Start_command(ram, cap, children, subsystem_config_registry(), yield_response_sig_cap, - exited_child_sig_cap)); + exited_child_sig_cap, + ldso_ds)); commands.insert(new Status_command(ram, children)); commands.insert(new Yield_command(children)); commands.insert(new Ram_command(children)); diff --git a/repos/os/src/app/cli_monitor/start_command.h b/repos/os/src/app/cli_monitor/start_command.h index 21ce27b0b..4c1c8b5ac 100644 --- a/repos/os/src/app/cli_monitor/start_command.h +++ b/repos/os/src/app/cli_monitor/start_command.h @@ -26,6 +26,7 @@ class Start_command : public Command typedef Genode::Xml_node Xml_node; typedef Genode::Signal_context_capability Signal_context_capability; + typedef Genode::Dataspace_capability Dataspace_capability; Ram &_ram; Child_registry &_children; @@ -34,6 +35,7 @@ class Start_command : public Command List _arguments; Signal_context_capability _yield_response_sigh_cap; Signal_context_capability _exit_sig_cap; + Dataspace_capability _ldso_ds; void _execute_subsystem(char const *name, Command_line &cmd, Terminal::Session &terminal, @@ -106,7 +108,7 @@ class Start_command : public Command try { child = new (Genode::env()->heap()) Child(_ram, label, binary_name, _cap, ram, ram_limit, - _yield_response_sigh_cap, _exit_sig_cap); + _yield_response_sigh_cap, _exit_sig_cap, _ldso_ds); } catch (Genode::Rom_connection::Rom_connection_failed) { tprintf(terminal, "Error: could not obtain ROM module \"%s\"\n", @@ -147,13 +149,15 @@ class Start_command : public Command Start_command(Ram &ram, Genode::Cap_session &cap, Child_registry &children, Subsystem_config_registry &subsustem_configs, Signal_context_capability yield_response_sigh_cap, - Signal_context_capability exit_sig_cap) + Signal_context_capability exit_sig_cap, + Dataspace_capability ldso_ds) : Command("start", "create new subsystem"), _ram(ram), _children(children), _cap(cap), _subsystem_configs(subsustem_configs), _yield_response_sigh_cap(yield_response_sigh_cap), - _exit_sig_cap(exit_sig_cap) + _exit_sig_cap(exit_sig_cap), + _ldso_ds(ldso_ds) { add_parameter(new Parameter("--count", Parameter::NUMBER, "number of instances")); add_parameter(new Parameter("--ram", Parameter::NUMBER, "initial RAM quota")); diff --git a/repos/os/src/init/main.cc b/repos/os/src/init/main.cc index dece85aa8..e84c0330f 100644 --- a/repos/os/src/init/main.cc +++ b/repos/os/src/init/main.cc @@ -286,10 +286,11 @@ int main(int, char **) using namespace Init; using namespace Genode; - /* look for dynamic linker */ + /* obtain dynamic linker */ + Dataspace_capability ldso_ds; try { static Rom_connection rom("ld.lib.so"); - Process::dynamic_linker(rom.dataspace()); + ldso_ds = rom.dataspace(); } catch (...) { } static Service_registry parent_services; @@ -344,9 +345,10 @@ int main(int, char **) try { children.insert(new (env()->heap()) Init::Child(start_node, default_route_node, - &children, read_prio_levels(), + children, read_prio_levels(), read_affinity_space(), - &parent_services, &child_services, &cap)); + parent_services, child_services, cap, + ldso_ds)); } catch (Rom_connection::Rom_connection_failed) { /* diff --git a/repos/os/src/server/loader/child.h b/repos/os/src/server/loader/child.h index 5f61f34f9..a5650d52d 100644 --- a/repos/os/src/server/loader/child.h +++ b/repos/os/src/server/loader/child.h @@ -104,6 +104,7 @@ namespace Loader { Child(char const *binary_name, char const *label, + Dataspace_capability ldso_ds, Rpc_entrypoint &ep, Ram_session_client &ram_session_client, size_t ram_quota, @@ -125,9 +126,11 @@ namespace Loader { _binary_rom_session(_rom_session(binary_name)), _binary_policy("binary", _binary_rom_session.dataspace(), &_ep), _labeling_policy(_label.string), - _child(_binary_rom_session.dataspace(), _resources.pd.cap(), - _resources.ram.cap(), _resources.cpu.cap(), - _address_space, &_ep, this) + _child(_binary_rom_session.dataspace(), ldso_ds, + _resources.pd, _resources.pd, + _resources.ram, _resources.ram, + _resources.cpu, _resources.cpu, + *env()->rm_session(), _address_space, _ep, *this) { } ~Child() diff --git a/repos/os/src/server/loader/main.cc b/repos/os/src/server/loader/main.cc index 172d4b35e..3d43ee60e 100644 --- a/repos/os/src/server/loader/main.cc +++ b/repos/os/src/server/loader/main.cc @@ -256,6 +256,7 @@ class Loader::Session_component : public Rpc_object Heap _md_alloc; size_t _subsystem_ram_quota_limit; Rpc_entrypoint _ep; + Dataspace_capability _ldso_ds; Service_registry _parent_services; Rom_module_registry _rom_modules; Local_rom_service _rom_service; @@ -281,13 +282,15 @@ class Loader::Session_component : public Rpc_object /** * Constructor */ - Session_component(size_t quota, Ram_session &ram, Cap_session &cap) + Session_component(size_t quota, Ram_session &ram, Cap_session &cap, + Dataspace_capability ldso_ds) : _ram_quota(quota), _ram_session_client(env()->ram_session_cap(), _ram_quota), _md_alloc(&_ram_session_client, env()->rm_session()), _subsystem_ram_quota_limit(0), _ep(&cap, STACK_SIZE, "session_ep"), + _ldso_ds(ldso_ds), _rom_modules(_ram_session_client, _md_alloc), _rom_service(_ep, _md_alloc, _rom_modules), _nitpicker_service(_ep, _ram_session_client, _md_alloc), @@ -380,7 +383,7 @@ class Loader::Session_component : public Rpc_object try { _child = new (&_md_alloc) - Child(binary_name.string(), label.string(), + Child(binary_name.string(), label.string(), _ldso_ds, _ep, _ram_session_client, ram_quota, _parent_services, _rom_service, _cpu_service, _pd_service, _nitpicker_service, @@ -406,8 +409,9 @@ class Loader::Root : public Root_component { private: - Ram_session &_ram; - Cap_session &_cap; + Ram_session &_ram; + Cap_session &_cap; + Dataspace_capability _ldso_ds; protected: @@ -416,7 +420,7 @@ class Loader::Root : public Root_component size_t quota = Arg_string::find_arg(args, "ram_quota").ulong_value(0); - return new (md_alloc()) Session_component(quota, _ram, _cap); + return new (md_alloc()) Session_component(quota, _ram, _cap, _ldso_ds); } public: @@ -429,14 +433,24 @@ class Loader::Root : public Root_component * component */ Root(Rpc_entrypoint &session_ep, Allocator &md_alloc, - Ram_session &ram, Cap_session &cap) + Ram_session &ram, Cap_session &cap, Dataspace_capability ldso_ds) : Root_component(&session_ep, &md_alloc), - _ram(ram), _cap(cap) + _ram(ram), _cap(cap), _ldso_ds(ldso_ds) { } }; +Genode::Dataspace_capability request_ldso_ds() +{ + try { + static Genode::Rom_connection rom("ld.lib.so"); + return rom.dataspace(); + } catch (...) { } + return Genode::Dataspace_capability(); +} + + int main() { using namespace Genode; @@ -445,7 +459,8 @@ int main() static Cap_connection cap; static Rpc_entrypoint ep(&cap, STACK_SIZE, "loader_ep"); - static Loader::Root root(ep, *env()->heap(), *env()->ram_session(), cap); + static Loader::Root root(ep, *env()->heap(), *env()->ram_session(), cap, + request_ldso_ds()); env()->parent()->announce(ep.manage(&root)); diff --git a/repos/os/src/test/bomb/main.cc b/repos/os/src/test/bomb/main.cc index 8ab73ce56..fa77a6b71 100644 --- a/repos/os/src/test/bomb/main.cc +++ b/repos/os/src/test/bomb/main.cc @@ -92,8 +92,9 @@ class Bomb_child : private Bomb_child_resources, Bomb_child_resources(file_name, unique_name, ram_quota), Init::Child_policy_enforce_labeling(Bomb_child_resources::_name), _entrypoint(cap_session, STACK_SIZE, "bomb_ep_child", false), - _child(_rom.dataspace(), _pd.cap(), _ram.cap(), _cpu.cap(), - _address_space, &_entrypoint, this), + _child(_rom.dataspace(), Genode::Dataspace_capability(), + _pd, _pd, _ram, _ram, _cpu, _cpu, + *Genode::env()->rm_session(), _address_space, _entrypoint, *this), _parent_services(parent_services), _config_policy("config", _entrypoint, &_ram) { diff --git a/repos/os/src/test/fault_detection/main.cc b/repos/os/src/test/fault_detection/main.cc index 532c94ddf..28bbb4e6d 100644 --- a/repos/os/src/test/fault_detection/main.cc +++ b/repos/os/src/test/fault_detection/main.cc @@ -101,8 +101,11 @@ class Test_child : public Genode::Child_policy _resources(sigh, elf_name), _elf(elf_name), _log_service("LOG"), _rm_service("RM"), - _child(_elf.dataspace(), _resources.pd.cap(), _resources.ram.cap(), - _resources.cpu.cap(), _address_space, &ep, this) + _child(_elf.dataspace(), Genode::Dataspace_capability(), + _resources.pd, _resources.pd, + _resources.ram, _resources.ram, + _resources.cpu, _resources.cpu, + *Genode::env()->rm_session(), _address_space, ep, *this) { } diff --git a/repos/os/src/test/vfs_stress/main.cc b/repos/os/src/test/vfs_stress/main.cc index dc00ff50c..1f052949a 100644 --- a/repos/os/src/test/vfs_stress/main.cc +++ b/repos/os/src/test/vfs_stress/main.cc @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -476,12 +475,6 @@ struct Unlink_thread : public Stress_thread int main() { - /* look for dynamic linker */ - try { - static Genode::Rom_connection rom("ld.lib.so"); - Genode::Process::dynamic_linker(rom.dataspace()); - } catch (...) { } - static Vfs::Dir_file_system vfs_root(config()->xml_node().sub_node("vfs"), Vfs::global_file_system_factory()); static char path[Vfs::MAX_PATH_LEN]; diff --git a/repos/ports/src/app/gdb_monitor/app_child.h b/repos/ports/src/app/gdb_monitor/app_child.h index e5dca66e0..9a2892f6f 100644 --- a/repos/ports/src/app/gdb_monitor/app_child.h +++ b/repos/ports/src/app/gdb_monitor/app_child.h @@ -40,7 +40,7 @@ namespace Gdb_monitor { enum { STACK_SIZE = 4*1024*sizeof(long) }; - const char *_unique_name; + const char *_unique_name; Rpc_entrypoint _entrypoint; @@ -56,9 +56,9 @@ namespace Gdb_monitor { Dataspace_pool _managed_ds_map; Cpu_root _cpu_root; - Cpu_session_capability _cpu_session_cap; + Cpu_session_client _cpu_session; - Ram_session_capability _ram_session_cap; + Ram_session_client _ram_session; Pd_session_component _pd { _unique_name, _entrypoint, _managed_ds_map }; @@ -227,6 +227,7 @@ namespace Gdb_monitor { */ App_child(const char *unique_name, Genode::Dataspace_capability elf_ds, + Genode::Dataspace_capability ldso_ds, Genode::Ram_session_capability ram_session, Genode::Cap_session *cap_session, Service_registry *parent_services, @@ -241,10 +242,11 @@ namespace Gdb_monitor { _config_policy("config", _child_config.dataspace(), &_entrypoint), _gdb_stub_thread(), _cpu_root(&_entrypoint, env()->heap() /* should be _child.heap() */, &_gdb_stub_thread), - _cpu_session_cap(_get_cpu_session_cap()), - _ram_session_cap(ram_session), - _child(elf_ds, _pd.cap(), ram_session, _cpu_session_cap, - _address_space, &_entrypoint, this), + _cpu_session(_get_cpu_session_cap()), + _ram_session(ram_session), + _child(elf_ds, ldso_ds, _pd.cap(), _pd, + _ram_session, _ram_session, _cpu_session, _cpu_session, + *Genode::env()->rm_session(), _address_space, _entrypoint, *this), _root_ep(root_ep), _rom_service(&_entrypoint, _child.heap()) { @@ -301,7 +303,7 @@ namespace Gdb_monitor { { /* create and announce proxy for the child's root interface */ Child_service_root *r = new (alloc) - Child_service_root(_ram_session_cap, root); + Child_service_root(_ram_session, root); Genode::env()->parent()->announce(name, _root_ep->manage(r)); return true; diff --git a/repos/ports/src/app/gdb_monitor/main.cc b/repos/ports/src/app/gdb_monitor/main.cc index 489abff18..156b5ad19 100644 --- a/repos/ports/src/app/gdb_monitor/main.cc +++ b/repos/ports/src/app/gdb_monitor/main.cc @@ -41,9 +41,10 @@ extern "C" int _sigprocmask() { return -1; } int main() { /* look for dynamic linker */ + Dataspace_capability ldso_ds; try { Rom_connection ldso_rom("ld.lib.so"); - Process::dynamic_linker(clone_rom(ldso_rom.dataspace())); + ldso_ds = clone_rom(ldso_rom.dataspace()); } catch (...) { PDBG("ld.lib.so not found"); } @@ -114,6 +115,7 @@ int main() new (env()->heap()) App_child(unique_name, elf_cap, + ldso_ds, ram.cap(), &cap_session, &parent_services, diff --git a/repos/ports/src/noux/child.h b/repos/ports/src/noux/child.h index ccc7ccd2c..766dc8b78 100644 --- a/repos/ports/src/noux/child.h +++ b/repos/ports/src/noux/child.h @@ -142,7 +142,6 @@ namespace Noux { */ Rpc_entrypoint &ep; - /** * Locally-provided services for accessing platform resources */ @@ -227,6 +226,8 @@ namespace Noux { Static_dataspace_info _args_ds_info; Static_dataspace_info _env_ds_info; + Dataspace_capability _ldso_ds; + Child_policy _child_policy; Genode::Child _child; @@ -328,6 +329,7 @@ namespace Noux { * the parent */ Child(char const *binary_name, + Dataspace_capability ldso_ds, Parent_exit *parent_exit, Kill_broadcaster &kill_broadcaster, Parent_execve &parent_execve, @@ -374,16 +376,19 @@ namespace Noux { _ldso_ds_info(_ds_registry, ldso_ds_cap()), _args_ds_info(_ds_registry, _args.cap()), _env_ds_info(_ds_registry, _env.cap()), + _ldso_ds(ldso_ds), _child_policy(_elf._name, _elf._binary_ds, _args.cap(), _env.cap(), _entrypoint, _local_noux_service, _local_rom_service, _parent_services, *this, parent_exit, *this, _destruct_context_cap, _resources.ram, verbose), _child(forked ? Dataspace_capability() : _elf._binary_ds, - _pd.core_pd_cap(), _resources.ram.cap(), _resources.cpu.cap(), - _address_space, - &_entrypoint, &_child_policy, _parent_pd_service, - _parent_ram_service, _local_cpu_service, _pd.cap()) + _ldso_ds, _pd.cap(), _pd, + _resources.ram.cap(), _resources.ram, + _resources.cpu.cap(), _resources.cpu, + *Genode::env()->rm_session(), _address_space, + _entrypoint, _child_policy, _parent_pd_service, + _parent_ram_service, _local_cpu_service) { if (verbose) _args.dump(); @@ -542,6 +547,7 @@ namespace Noux { Lock::Guard signal_lock_guard(signal_lock()); Child *child = new Child(filename, + _ldso_ds, _parent_exit, _kill_broadcaster, _parent_execve, diff --git a/repos/ports/src/noux/main.cc b/repos/ports/src/noux/main.cc index c6756bbce..89af7e6c2 100644 --- a/repos/ports/src/noux/main.cc +++ b/repos/ports/src/noux/main.cc @@ -599,6 +599,7 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) * reusing the name of the parent. */ child = new Child(_child_policy.name(), + _ldso_ds, this, _kill_broadcaster, *this, @@ -1134,9 +1135,6 @@ int main(int argc, char **argv) using namespace Noux; PINF("--- noux started ---"); - /* register dynamic linker */ - Genode::Process::dynamic_linker(ldso_ds_cap()); - /* whitelist of service requests to be routed to the parent */ static Genode::Service_registry parent_services; char const *service_names[] = { "LOG", "ROM", "Timer", 0 }; @@ -1198,6 +1196,7 @@ int main(int argc, char **argv) static Kill_broadcaster_implementation kill_broadcaster; init_child = new Noux::Child(name_of_init_process(), + ldso_ds_cap(), 0, kill_broadcaster, *init_child,