diff --git a/repos/base-linux/run/lx_fs.run b/repos/base-linux/run/lx_fs.run index 5e8f6c653..8162b567f 100644 --- a/repos/base-linux/run/lx_fs.run +++ b/repos/base-linux/run/lx_fs.run @@ -32,7 +32,7 @@ install_config { - + diff --git a/repos/base-linux/run/lx_hybrid_ctors.run b/repos/base-linux/run/lx_hybrid_ctors.run index f5064a40c..6fa4e07ec 100644 --- a/repos/base-linux/run/lx_hybrid_ctors.run +++ b/repos/base-linux/run/lx_hybrid_ctors.run @@ -32,7 +32,7 @@ install_config { - + diff --git a/repos/base-linux/run/lx_hybrid_errno.run b/repos/base-linux/run/lx_hybrid_errno.run index 8f9548f76..2a47c87b8 100644 --- a/repos/base-linux/run/lx_hybrid_errno.run +++ b/repos/base-linux/run/lx_hybrid_errno.run @@ -25,7 +25,7 @@ install_config { - + diff --git a/repos/base-linux/run/lx_hybrid_exception.run b/repos/base-linux/run/lx_hybrid_exception.run index 29ef601f5..18bc0d228 100644 --- a/repos/base-linux/run/lx_hybrid_exception.run +++ b/repos/base-linux/run/lx_hybrid_exception.run @@ -31,7 +31,7 @@ install_config { - + diff --git a/repos/base-linux/run/lx_hybrid_pthread_ipc.run b/repos/base-linux/run/lx_hybrid_pthread_ipc.run index d151fd5dd..1468b210a 100644 --- a/repos/base-linux/run/lx_hybrid_pthread_ipc.run +++ b/repos/base-linux/run/lx_hybrid_pthread_ipc.run @@ -28,7 +28,7 @@ install_config { - + diff --git a/repos/base-linux/src/lib/base/child_process.cc b/repos/base-linux/src/lib/base/child_process.cc index 9427d8b37..48fd021c3 100644 --- a/repos/base-linux/src/lib/base/child_process.cc +++ b/repos/base-linux/src/lib/base/child_process.cc @@ -50,7 +50,7 @@ void Child::Initial_thread::start(addr_t) { } /* * On Linux, the ELF loading is performed by the kernel */ -Child::Process::Loaded_executable::Loaded_executable(Dataspace_capability, +Child::Process::Loaded_executable::Loaded_executable(Type, Dataspace_capability, Ram_session &, Region_map &, @@ -58,51 +58,27 @@ Child::Process::Loaded_executable::Loaded_executable(Dataspace_capability, Parent_capability) { } -Child::Process::Process(Dataspace_capability elf_ds, +Child::Process::Process(Type type, Dataspace_capability ldso_ds, - Pd_session_capability, Pd_session &pd, - Ram_session &ram, Initial_thread_base &, Region_map &local_rm, Region_map &remote_rm, Parent_capability parent_cap) : - loaded_executable(elf_ds, ldso_ds, ram, local_rm, remote_rm, parent_cap) + loaded_executable(type, ldso_ds, pd, local_rm, remote_rm, parent_cap) { /* skip loading when called during fork */ - if (!elf_ds.valid()) + if (type == TYPE_FORKED) return; - /* attach ELF locally */ - addr_t elf_addr; - try { elf_addr = local_rm.attach(elf_ds); } - catch (Region_map::Invalid_dataspace) { - error("local attach of ELF executable failed (Invalid_dataspace)"); throw; } - catch (Region_map::Region_conflict) { - error("local attach of ELF executable failed (Region_conflict)"); 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.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()) { - error("attempt to start dynamic executable without dynamic linker"); - throw Missing_dynamic_linker(); - } - - elf_ds = ldso_ds; + if (!ldso_ds.valid()) { + error("attempt to start dynamic executable without dynamic linker"); + throw Missing_dynamic_linker(); } pd.assign_parent(parent_cap); @@ -110,7 +86,7 @@ Child::Process::Process(Dataspace_capability elf_ds, Linux_native_pd_client lx_pd(static_cap_cast(pd.native_pd())); - lx_pd.start(elf_ds); + lx_pd.start(ldso_ds); } diff --git a/repos/base-nova/run/platform.run b/repos/base-nova/run/platform.run index a674eb9cb..0adfbcd62 100644 --- a/repos/base-nova/run/platform.run +++ b/repos/base-nova/run/platform.run @@ -24,7 +24,7 @@ set config { - + } append config " diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h index ffab7cc50..ea001a4ea 100644 --- a/repos/base/include/base/child.h +++ b/repos/base/include/base/child.h @@ -222,6 +222,11 @@ struct Genode::Child_policy * would otherwise produce a deadlock. */ virtual Region_map *address_space(Pd_session &) { return nullptr; } + + /** + * Return true if ELF loading should be inhibited + */ + virtual bool forked() const { return false; } }; @@ -344,6 +349,8 @@ class Genode::Child : protected Rpc_object, class Missing_dynamic_linker : Exception { }; class Invalid_executable : Exception { }; + enum Type { TYPE_LOADED, TYPE_FORKED }; + struct Loaded_executable { /** @@ -368,7 +375,7 @@ class Genode::Child : protected Rpc_object, * \throw Out_of_ram * \throw Out_of_caps */ - Loaded_executable(Dataspace_capability elf_ds, + Loaded_executable(Type type, Dataspace_capability ldso_ds, Ram_session &ram, Region_map &local_rm, @@ -379,11 +386,6 @@ class Genode::Child : protected Rpc_object, /** * Constructor * - * \param ram RAM session used to allocate the BSS and - * DATA segments for the new process - * \param parent parent of the new protection domain - * \param name name of protection domain - * * \throw Missing_dynamic_linker * \throw Invalid_executable * \throw Region_map::Region_conflict @@ -391,25 +393,21 @@ class Genode::Child : protected Rpc_object, * \throw Out_of_ram * \throw Out_of_caps * - * 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. + * The 'type' 'TYPE_FORKED' creates 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, - Initial_thread_base &initial_thread, - Region_map &local_rm, - Region_map &remote_rm, - Parent_capability parent); + Process(Type type, + Dataspace_capability ldso_ds, + Pd_session &pd, + Initial_thread_base &initial_thread, + Region_map &local_rm, + Region_map &remote_rm, + Parent_capability parent); ~Process(); }; diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc index 99b74f604..b2132f1e3 100644 --- a/repos/base/src/lib/base/child.cc +++ b/repos/base/src/lib/base/child.cc @@ -771,10 +771,11 @@ void Child::_try_construct_env_dependent_members() _policy.init(_cpu.session(), _cpu.cap()); + Process::Type const type = _policy.forked() + ? Process::TYPE_FORKED : Process::TYPE_LOADED; try { _initial_thread.construct(_cpu.session(), _pd.cap(), _policy.name()); - _process.construct(_binary.session().dataspace(), _linker_dataspace(), - _pd.cap(), _pd.session(), _pd.session(), + _process.construct(type, _linker_dataspace(), _pd.session(), *_initial_thread, _local_rm, Child_address_space(_pd.session(), _policy).region_map(), cap()); diff --git a/repos/base/src/lib/base/child_process.cc b/repos/base/src/lib/base/child_process.cc index 420005854..63d4c9945 100644 --- a/repos/base/src/lib/base/child_process.cc +++ b/repos/base/src/lib/base/child_process.cc @@ -24,53 +24,32 @@ using namespace Genode; -Child::Process::Loaded_executable::Loaded_executable(Dataspace_capability elf_ds, +Child::Process::Loaded_executable::Loaded_executable(Type type, Dataspace_capability ldso_ds, - Ram_session &ram, + Pd_session &pd, Region_map &local_rm, Region_map &remote_rm, Parent_capability parent_cap) { /* skip loading when called during fork */ - if (!elf_ds.valid()) + if (type == TYPE_FORKED) return; - /* attach ELF locally */ - addr_t elf_addr; - try { elf_addr = local_rm.attach(elf_ds); } - catch (Region_map::Invalid_dataspace) { - error("local attach of ELF executable failed (invalid dataspace)"); throw; } - catch (Region_map::Region_conflict) { - error("local attach of ELF executable failed (region conflict)"); 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.dynamically_linked()) { - - local_rm.detach(elf_addr); - - if (!ldso_ds.valid()) { - error("attempt to start dynamic executable without dynamic linker"); - throw Missing_dynamic_linker(); - } - - try { elf_addr = local_rm.attach(ldso_ds); } - catch (Region_map::Invalid_dataspace) { - error("dynamic linker is an invalid dataspace"); throw; } - catch (Region_map::Region_conflict) { - error("region conflict while attaching dynamic linker"); throw; } - - elf_ds = ldso_ds; - elf = Elf_binary(elf_addr); + /* locally attach ELF binary of the dynamic linker */ + if (!ldso_ds.valid()) { + error("attempt to start dynamic executable without dynamic linker"); + throw Missing_dynamic_linker(); } + addr_t elf_addr = 0; + try { elf_addr = local_rm.attach(ldso_ds); } + catch (Region_map::Invalid_dataspace) { + error("dynamic linker is an invalid dataspace"); throw; } + catch (Region_map::Region_conflict) { + error("region conflict while attaching dynamic linker"); throw; } + + Elf_binary elf(elf_addr); + entry = elf.entry(); /* setup region map for the new pd */ @@ -105,7 +84,7 @@ Child::Process::Loaded_executable::Loaded_executable(Dataspace_capability elf_ds /* alloc dataspace */ Dataspace_capability ds_cap; - try { ds_cap = ram.alloc(size); } + try { ds_cap = pd.alloc(size); } catch (Out_of_ram) { error("allocation of read-write segment failed"); throw; }; @@ -141,7 +120,9 @@ Child::Process::Loaded_executable::Loaded_executable(Dataspace_capability elf_ds off_t const offset = 0; try { remote_rm.attach_at(ds_cap, addr, size, offset); } catch (Region_map::Region_conflict) { - error("region conflict while remotely attaching ELF segment"); throw; } + error("region conflict while remotely attaching ELF segment"); + error("addr=", (void *)addr, " size=", (void *)size, " offset=", (void *)offset); + throw; } } else { @@ -153,12 +134,13 @@ Child::Process::Loaded_executable::Loaded_executable(Dataspace_capability elf_ds off_t const offset = seg.file_offset(); try { if (exec) - remote_rm.attach_executable(elf_ds, addr, size, offset); + remote_rm.attach_executable(ldso_ds, addr, size, offset); else - remote_rm.attach_at(elf_ds, addr, size, offset); + remote_rm.attach_at(ldso_ds, addr, size, offset); } catch (Region_map::Region_conflict) { error("region conflict while remotely attaching read-only ELF segment"); + error("addr=", (void *)addr, " size=", (void *)size, " offset=", (void *)offset); throw; } catch (Region_map::Invalid_dataspace) { @@ -194,17 +176,15 @@ void Child::Initial_thread::start(addr_t ip) } -Child::Process::Process(Dataspace_capability elf_ds, +Child::Process::Process(Type type, Dataspace_capability ldso_ds, - Pd_session_capability, Pd_session &pd, - Ram_session &ram, Initial_thread_base &initial_thread, Region_map &local_rm, Region_map &remote_rm, Parent_capability parent_cap) : - loaded_executable(elf_ds, ldso_ds, ram, local_rm, remote_rm, parent_cap) + loaded_executable(type, ldso_ds, pd, local_rm, remote_rm, parent_cap) { /* register parent interface for new protection domain */ pd.assign_parent(parent_cap); @@ -214,7 +194,7 @@ Child::Process::Process(Dataspace_capability elf_ds, * from another. In this case, the main thread will get manually * started after constructing the 'Process'. */ - if (!elf_ds.valid()) + if (type == TYPE_FORKED) return; /* start main thread */ diff --git a/repos/gems/run/cpu_load_display.run b/repos/gems/run/cpu_load_display.run index 41f52280b..f3a6dd55e 100644 --- a/repos/gems/run/cpu_load_display.run +++ b/repos/gems/run/cpu_load_display.run @@ -56,7 +56,7 @@ append config { } append_if [have_spec sdl] config { - + diff --git a/repos/gems/run/gpt_write.run b/repos/gems/run/gpt_write.run index 1ace87a05..43ed451a4 100644 --- a/repos/gems/run/gpt_write.run +++ b/repos/gems/run/gpt_write.run @@ -34,7 +34,7 @@ install_config { - + diff --git a/repos/gems/run/leitzentrale.run b/repos/gems/run/leitzentrale.run index 6e88ab8fe..97ba031aa 100644 --- a/repos/gems/run/leitzentrale.run +++ b/repos/gems/run/leitzentrale.run @@ -202,7 +202,7 @@ install_config { - + diff --git a/repos/libports/run/avplay.run b/repos/libports/run/avplay.run index 1691a7039..d99b97dd9 100644 --- a/repos/libports/run/avplay.run +++ b/repos/libports/run/avplay.run @@ -49,7 +49,7 @@ set config { } append_if [have_spec sdl] config { - + diff --git a/repos/libports/run/mesa.inc b/repos/libports/run/mesa.inc index ce8c82bbc..36704c861 100644 --- a/repos/libports/run/mesa.inc +++ b/repos/libports/run/mesa.inc @@ -53,7 +53,7 @@ set config { } append_if [have_spec linux] config { - + diff --git a/repos/libports/run/qt5_drivers.inc b/repos/libports/run/qt5_drivers.inc index 40921a13e..d6479742d 100644 --- a/repos/libports/run/qt5_drivers.inc +++ b/repos/libports/run/qt5_drivers.inc @@ -165,7 +165,7 @@ proc drivers_start_nodes { feature_arg } { } append_if [use_fb_sdl feature] start_nodes { - + diff --git a/repos/libports/run/sdl.run b/repos/libports/run/sdl.run index 9d99f707c..ab985fc2c 100644 --- a/repos/libports/run/sdl.run +++ b/repos/libports/run/sdl.run @@ -38,7 +38,7 @@ append config { } append_if [have_spec sdl] config { - + diff --git a/repos/os/recipes/raw/drivers_interactive-linux/drivers.config b/repos/os/recipes/raw/drivers_interactive-linux/drivers.config index 5f4e87482..36676a10f 100644 --- a/repos/os/recipes/raw/drivers_interactive-linux/drivers.config +++ b/repos/os/recipes/raw/drivers_interactive-linux/drivers.config @@ -13,7 +13,7 @@ - + diff --git a/repos/os/run/block_tester.run b/repos/os/run/block_tester.run index c718a7dbd..b43dc94e1 100644 --- a/repos/os/run/block_tester.run +++ b/repos/os/run/block_tester.run @@ -71,7 +71,7 @@ append_if [expr !$use_linux] config { append_if $use_linux config { - + diff --git a/repos/os/run/demo.run b/repos/os/run/demo.run index ebb095986..e8ec816d4 100644 --- a/repos/os/run/demo.run +++ b/repos/os/run/demo.run @@ -58,7 +58,7 @@ append config { } append_if [have_spec sdl] config { - + diff --git a/repos/os/run/fb_bench.run b/repos/os/run/fb_bench.run index 99afe92dc..b48876d71 100644 --- a/repos/os/run/fb_bench.run +++ b/repos/os/run/fb_bench.run @@ -61,7 +61,7 @@ append_if [have_spec gpio] config " " append_if [have_spec sdl] config { - + diff --git a/repos/os/run/framebuffer.run b/repos/os/run/framebuffer.run index 5430ac94e..85fa2a340 100644 --- a/repos/os/run/framebuffer.run +++ b/repos/os/run/framebuffer.run @@ -46,7 +46,7 @@ append config { } append_if [have_spec sdl] config { - + diff --git a/repos/os/run/input.run b/repos/os/run/input.run index 0eb19c0e2..8c1feb7f3 100644 --- a/repos/os/run/input.run +++ b/repos/os/run/input.run @@ -77,7 +77,7 @@ append_if [have_spec ps2] config { } append_if [have_spec sdl] config { - + diff --git a/repos/os/run/loader.run b/repos/os/run/loader.run index ad3c97b6e..bba24425a 100644 --- a/repos/os/run/loader.run +++ b/repos/os/run/loader.run @@ -41,7 +41,7 @@ append config { append_platform_drv_config append_if [have_spec sdl] config { - + diff --git a/repos/os/run/lx_block.run b/repos/os/run/lx_block.run index 0138bb9d0..df9181903 100644 --- a/repos/os/run/lx_block.run +++ b/repos/os/run/lx_block.run @@ -34,7 +34,7 @@ install_config { - + diff --git a/repos/os/run/pointer.run b/repos/os/run/pointer.run index 210c94bdd..a6e41863d 100644 --- a/repos/os/run/pointer.run +++ b/repos/os/run/pointer.run @@ -50,7 +50,7 @@ set config { - + diff --git a/repos/os/run/rom_to_file.run b/repos/os/run/rom_to_file.run index e41d26059..680e7fa22 100644 --- a/repos/os/run/rom_to_file.run +++ b/repos/os/run/rom_to_file.run @@ -44,7 +44,7 @@ install_config { - + diff --git a/repos/os/src/init/child.cc b/repos/os/src/init/child.cc index 67b386a7a..eaa7a7241 100644 --- a/repos/os/src/init/child.cc +++ b/repos/os/src/init/child.cc @@ -496,6 +496,10 @@ Init::Child::Route Init::Child::resolve_session_request(Service::Name const &ser label == _unique_name && _unique_name != _binary_name) return resolve_session_request(service_name, _binary_name); + /* supply binary as dynamic linker if '' */ + if (!_use_ld && service_name == Rom_session::service_name() && label == "ld.lib.so") + return resolve_session_request(service_name, _binary_name); + /* check for "session_requests" ROM request */ if (service_name == Rom_session::service_name() && label.last_element() == Session_requester::rom_name()) diff --git a/repos/os/src/init/child.h b/repos/os/src/init/child.h index 986789ba6..140a3f7e0 100644 --- a/repos/os/src/init/child.h +++ b/repos/os/src/init/child.h @@ -90,6 +90,11 @@ class Init::Child : Child_policy, Routed_service::Wakeup typedef String<80> Version; Version _version { _start_node->xml().attribute_value("version", Version()) }; + /* + * True if the binary is loaded with ld.lib.so + */ + bool const _use_ld = _start_node->xml().attribute_value("ld", true); + Default_route_accessor &_default_route_accessor; Default_caps_accessor &_default_caps_accessor; Ram_limit_accessor &_ram_limit_accessor; diff --git a/repos/os/src/init/config.xsd b/repos/os/src/init/config.xsd index 511aeaa95..e5da52ba8 100644 --- a/repos/os/src/init/config.xsd +++ b/repos/os/src/init/config.xsd @@ -144,6 +144,7 @@ + diff --git a/repos/ports/run/dosbox.run b/repos/ports/run/dosbox.run index 94fbe430f..e47b765e4 100644 --- a/repos/ports/run/dosbox.run +++ b/repos/ports/run/dosbox.run @@ -48,7 +48,7 @@ append config { } append_if [have_spec sdl] config { - + diff --git a/repos/ports/run/netperf.inc b/repos/ports/run/netperf.inc index eb3557978..a4fce3829 100644 --- a/repos/ports/run/netperf.inc +++ b/repos/ports/run/netperf.inc @@ -216,8 +216,14 @@ append_if $use_usb_driver config { } +# don't use the dynamic linker for loading the lx_hybrid nic_drv on Linux +proc nic_drv_ld_attr {} { + if {[have_spec linux]} { return {ld="no"} } + return "" +} + append_if $use_nic_driver config { - + diff --git a/repos/ports/run/seoul.inc b/repos/ports/run/seoul.inc index 1f7fbf8a2..76dbc6b49 100644 --- a/repos/ports/run/seoul.inc +++ b/repos/ports/run/seoul.inc @@ -250,7 +250,7 @@ append_if $use_framebuffer config { if {!$use_fancy_stuff} { append config { - + } append config " " @@ -264,10 +264,9 @@ append_if [expr $use_nic_session && !$use_nic_bridge] config { append_if $use_framebuffer config { } append_if $use_genode_iso config { + - - } append config { diff --git a/repos/ports/run/virtualbox.run b/repos/ports/run/virtualbox.run index f366f697f..814b0b2cf 100644 --- a/repos/ports/run/virtualbox.run +++ b/repos/ports/run/virtualbox.run @@ -108,7 +108,7 @@ append_if [have_spec framebuffer] config { } append_if [have_spec sdl] config { - + diff --git a/repos/ports/src/noux/child_policy.h b/repos/ports/src/noux/child_policy.h index 51f9ad626..caad94efa 100644 --- a/repos/ports/src/noux/child_policy.h +++ b/repos/ports/src/noux/child_policy.h @@ -194,6 +194,8 @@ class Noux::Child_policy : public Genode::Child_policy { return &static_cast(pd).address_space_region_map(); } + + bool forked() const override { return _forked; } }; #endif /* _NOUX__CHILD_POLICY_H_ */