diff --git a/base-codezero/src/core/core_rm_session.cc b/base-codezero/src/core/core_rm_session.cc index 3aae24cdb..fbb08fad1 100644 --- a/base-codezero/src/core/core_rm_session.cc +++ b/base-codezero/src/core/core_rm_session.cc @@ -25,7 +25,8 @@ using namespace Genode; Rm_session::Local_addr Core_rm_session::attach(Dataspace_capability ds_cap, size_t size, off_t offset, bool use_local_addr, - Rm_session::Local_addr local_addr) + Rm_session::Local_addr local_addr, + bool executable) { using namespace Codezero; diff --git a/base-codezero/src/core/include/core_rm_session.h b/base-codezero/src/core/include/core_rm_session.h index 567599f0c..7920b2088 100644 --- a/base-codezero/src/core/include/core_rm_session.h +++ b/base-codezero/src/core/include/core_rm_session.h @@ -34,7 +34,8 @@ namespace Genode { Local_addr attach(Dataspace_capability ds_cap, size_t size = 0, off_t offset = 0, bool use_local_addr = false, - Local_addr local_addr = 0); + Local_addr local_addr = 0, + bool executable = false); void detach(Local_addr) { } diff --git a/base-linux/include/base/platform_env.h b/base-linux/include/base/platform_env.h index 4d3691225..fc132b695 100644 --- a/base-linux/include/base/platform_env.h +++ b/base-linux/include/base/platform_env.h @@ -206,7 +206,8 @@ namespace Genode { **************************************/ Local_addr attach(Dataspace_capability ds, size_t size, - off_t, bool, Local_addr); + off_t, bool, Local_addr, + bool executable); void detach(Local_addr local_addr); diff --git a/base-linux/include/rm_session/client.h b/base-linux/include/rm_session/client.h index fbcf49f80..9e44c415c 100644 --- a/base-linux/include/rm_session/client.h +++ b/base-linux/include/rm_session/client.h @@ -34,9 +34,11 @@ namespace Genode { : _cap(session) { } Local_addr attach(Dataspace_capability ds, size_t size, off_t offset, - bool use_local_addr, Local_addr local_addr) + bool use_local_addr, Local_addr local_addr, + bool executable = false) { - return _local()->attach(ds, size, offset, use_local_addr, local_addr); + return _local()->attach(ds, size, offset, use_local_addr, + local_addr, executable); } void detach(Local_addr local_addr) { diff --git a/base-linux/src/base/env/rm_session_mmap.cc b/base-linux/src/base/env/rm_session_mmap.cc index 5b068f10f..83d12156c 100644 --- a/base-linux/src/base/env/rm_session_mmap.cc +++ b/base-linux/src/base/env/rm_session_mmap.cc @@ -43,7 +43,8 @@ static bool is_sub_rm_session(Dataspace_capability ds) static void *map_local(Dataspace_capability ds, Genode::size_t size, - addr_t offset, bool use_local_addr, addr_t local_addr) + addr_t offset, bool use_local_addr, addr_t local_addr, + bool executable) { Linux_dataspace::Filename fname = Linux_dataspace_client(ds).fname(); fname.buf[sizeof(fname.buf) - 1] = 0; @@ -56,7 +57,7 @@ static void *map_local(Dataspace_capability ds, Genode::size_t size, } int flags = MAP_SHARED | (use_local_addr ? MAP_FIXED : 0); - int prot = PROT_READ | PROT_EXEC | (writable ? PROT_WRITE : 0); + int prot = PROT_READ | (writable ? PROT_WRITE : 0) | (executable ? PROT_EXEC : 0); void *addr = lx_mmap(use_local_addr ? (void*)local_addr : 0, size, prot, flags, fd, offset); @@ -84,7 +85,8 @@ Rm_session::Local_addr Platform_env::Rm_session_mmap::attach(Dataspace_capability ds, size_t size, off_t offset, bool use_local_addr, - Rm_session::Local_addr local_addr) + Rm_session::Local_addr local_addr, + bool executable) { Lock::Guard lock_guard(_lock); @@ -150,7 +152,7 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds, * and map it. */ if (_is_attached()) - map_local(ds, region_size, offset, true, _base + (addr_t)local_addr); + map_local(ds, region_size, offset, true, _base + (addr_t)local_addr, executable); return (void *)local_addr; @@ -197,7 +199,8 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds, continue; map_local(region.dataspace(), region.size(), region.offset(), - true, rm->_base + region.start() + region.offset()); + true, rm->_base + region.start() + region.offset(), + executable); } return rm->_base; @@ -209,7 +212,8 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds, * * Boring, a plain dataspace is attached to a root RM session. */ - void *addr = map_local(ds, region_size, offset, use_local_addr, local_addr); + void *addr = map_local(ds, region_size, offset, use_local_addr, + local_addr, executable); _add_to_rmap(Region((addr_t)addr, offset, ds, region_size)); diff --git a/base-linux/src/core/context_area.cc b/base-linux/src/core/context_area.cc index cca16d269..5cf77f840 100644 --- a/base-linux/src/core/context_area.cc +++ b/base-linux/src/core/context_area.cc @@ -39,7 +39,8 @@ class Context_area_rm_session : public Genode::Rm_session */ Local_addr attach(Genode::Dataspace_capability ds_cap, Genode::size_t size, Genode::off_t offset, - bool use_local_addr, Local_addr local_addr) + bool use_local_addr, Local_addr local_addr, + bool executable) { using namespace Genode; diff --git a/base-linux/src/core/include/rm_session_component.h b/base-linux/src/core/include/rm_session_component.h index aac891f30..07d4dd423 100644 --- a/base-linux/src/core/include/rm_session_component.h +++ b/base-linux/src/core/include/rm_session_component.h @@ -40,7 +40,7 @@ namespace Genode { void upgrade_ram_quota(size_t ram_quota) { } - Local_addr attach(Dataspace_capability, size_t, off_t, bool, Local_addr) { + Local_addr attach(Dataspace_capability, size_t, off_t, bool, Local_addr, bool) { return (addr_t)0; } void detach(Local_addr) { } diff --git a/base-mb/src/core/core_rm_session.cc b/base-mb/src/core/core_rm_session.cc index 444fbd93d..75506d092 100644 --- a/base-mb/src/core/core_rm_session.cc +++ b/base-mb/src/core/core_rm_session.cc @@ -25,7 +25,8 @@ using namespace Genode; Rm_session::Local_addr Core_rm_session::attach(Dataspace_capability ds_cap, size_t size, off_t offset, bool use_local_addr, - Rm_session::Local_addr local_addr) + Rm_session::Local_addr local_addr, + bool executable) { Dataspace_component *ds = static_cast(_ds_ep->obj_by_cap(ds_cap)); if (!ds) diff --git a/base-mb/src/core/include/core_rm_session.h b/base-mb/src/core/include/core_rm_session.h index 372e19719..d3a978055 100644 --- a/base-mb/src/core/include/core_rm_session.h +++ b/base-mb/src/core/include/core_rm_session.h @@ -34,7 +34,8 @@ namespace Genode { Local_addr attach(Dataspace_capability ds_cap, size_t size=0, off_t offset=0, bool use_local_addr = false, - Local_addr local_addr = 0); + Local_addr local_addr = 0, + bool executable = false); void detach(Local_addr) { } diff --git a/base-nova/src/core/core_rm_session.cc b/base-nova/src/core/core_rm_session.cc index dff76bd79..1344b8a92 100644 --- a/base-nova/src/core/core_rm_session.cc +++ b/base-nova/src/core/core_rm_session.cc @@ -29,7 +29,8 @@ using namespace Genode; Rm_session::Local_addr Core_rm_session::attach(Dataspace_capability ds_cap, size_t size, off_t offset, bool use_local_addr, - Rm_session::Local_addr local_addr) + Rm_session::Local_addr local_addr, + bool executable) { Dataspace_component *ds = static_cast(_ds_ep->obj_by_cap(ds_cap)); if (!ds) diff --git a/base-nova/src/core/include/core_rm_session.h b/base-nova/src/core/include/core_rm_session.h index 372e19719..d3a978055 100644 --- a/base-nova/src/core/include/core_rm_session.h +++ b/base-nova/src/core/include/core_rm_session.h @@ -34,7 +34,8 @@ namespace Genode { Local_addr attach(Dataspace_capability ds_cap, size_t size=0, off_t offset=0, bool use_local_addr = false, - Local_addr local_addr = 0); + Local_addr local_addr = 0, + bool executable = false); void detach(Local_addr) { } diff --git a/base-okl4/src/core/core_rm_session.cc b/base-okl4/src/core/core_rm_session.cc index 4a9c2f88b..6e7f413d5 100644 --- a/base-okl4/src/core/core_rm_session.cc +++ b/base-okl4/src/core/core_rm_session.cc @@ -22,7 +22,7 @@ using namespace Genode; Rm_session::Local_addr Core_rm_session::attach(Dataspace_capability ds_cap, size_t size, off_t offset, bool use_local_addr, - Rm_session::Local_addr) + Rm_session::Local_addr, bool executable) { using namespace Okl4; diff --git a/base-okl4/src/core/include/core_rm_session.h b/base-okl4/src/core/include/core_rm_session.h index 3f7d25022..a6a26a6d4 100644 --- a/base-okl4/src/core/include/core_rm_session.h +++ b/base-okl4/src/core/include/core_rm_session.h @@ -39,7 +39,8 @@ namespace Genode { Local_addr attach(Dataspace_capability ds_cap, size_t size=0, off_t offset=0, bool use_local_addr = false, - Local_addr local_addr = 0); + Local_addr local_addr = 0, + bool executable = false); void detach(Local_addr) { } diff --git a/base/include/base/platform_env.h b/base/include/base/platform_env.h index 1850af355..77c89d39e 100644 --- a/base/include/base/platform_env.h +++ b/base/include/base/platform_env.h @@ -46,7 +46,8 @@ namespace Genode { Local_addr attach(Dataspace_capability ds, size_t size = 0, off_t offset = 0, bool use_local_addr = false, - Local_addr local_addr = (addr_t)0) { + Local_addr local_addr = (addr_t)0, + bool executable = false) { bool try_again; do { @@ -54,7 +55,8 @@ namespace Genode { try { return Rm_session_client::attach(ds, size, offset, use_local_addr, - local_addr); + local_addr, + executable); } catch (Rm_session::Out_of_metadata) { diff --git a/base/include/rm_session/client.h b/base/include/rm_session/client.h index 1caa54286..363add669 100644 --- a/base/include/rm_session/client.h +++ b/base/include/rm_session/client.h @@ -25,10 +25,12 @@ namespace Genode { : Rpc_client(session) { } Local_addr attach(Dataspace_capability ds, size_t size, off_t offset, - bool use_local_addr, Local_addr local_addr) + bool use_local_addr, Local_addr local_addr, + bool executable = false) { return call(ds, size, offset, - use_local_addr, local_addr); + use_local_addr, local_addr, + executable); } void detach(Local_addr local_addr) { diff --git a/base/include/rm_session/rm_session.h b/base/include/rm_session/rm_session.h index 20a635953..9f566a57f 100644 --- a/base/include/rm_session/rm_session.h +++ b/base/include/rm_session/rm_session.h @@ -117,6 +117,7 @@ namespace Genode { * \param use_local_addr if set to true, attach the dataspace at * the specified 'local_addr' * \param local_addr local destination address + * \param executable if the mapping should be executable * * \throw Attach_failed if dataspace or offset is invalid, * or on region conflict @@ -128,7 +129,8 @@ namespace Genode { virtual Local_addr attach(Dataspace_capability ds, size_t size = 0, off_t offset = 0, bool use_local_addr = false, - Local_addr local_addr = (addr_t)0) = 0; + Local_addr local_addr = (addr_t)0, + bool executable = false) = 0; /** * Shortcut for attaching a dataspace at a predefined local address @@ -137,6 +139,13 @@ namespace Genode { size_t size = 0, off_t offset = 0) { return attach(ds, size, offset, true, local_addr); } + /** + * Shortcut for attaching a dataspace executable at a predefined local address + */ + Local_addr attach_executable(Dataspace_capability ds, addr_t local_addr, + size_t size = 0, off_t offset = 0) { + return attach(ds, size, offset, true, local_addr, true); } + /** * Remove region from local address space */ @@ -179,7 +188,7 @@ namespace Genode { GENODE_RPC_THROW(Rpc_attach, Local_addr, attach, GENODE_TYPE_LIST(Invalid_dataspace, Region_conflict, Out_of_metadata, Invalid_args), - Dataspace_capability, size_t, off_t, bool, Local_addr); + Dataspace_capability, size_t, off_t, bool, Local_addr, bool); GENODE_RPC(Rpc_detach, void, detach, Local_addr); GENODE_RPC_THROW(Rpc_add_client, Pager_capability, add_client, GENODE_TYPE_LIST(Invalid_thread, Out_of_memory), diff --git a/base/run/sub_rm.run b/base/run/sub_rm.run index 90791a2da..d0db11424 100644 --- a/base/run/sub_rm.run +++ b/base/run/sub_rm.run @@ -42,15 +42,15 @@ if [have_spec linux_x86_32] { puts "Error: detaching from sub RM session failed" exit -1 } - if {![regexp {60040000-60044000 rwxs} $maps]} { + if {![regexp {60040000-60044000 rw.s} $maps]} { puts "Error: populating already attached sub RM session failed" exit -1 } - if {![regexp {60080000-60083000 rwxs 00001000} $maps]} { + if {![regexp {60080000-60083000 rw.s 00001000} $maps]} { puts "Error: using offset parameter to sub RM attach did not work" exit -1 } - if {![regexp {600c0000-600c2000 rwxs 00001000} $maps]} { + if {![regexp {600c0000-600c2000 rw.s 00001000} $maps]} { puts "Error: using offset and size parameters to sub RM attach did not work" exit -1 } diff --git a/base/src/base/process/process.cc b/base/src/base/process/process.cc index 37510c985..6f102a1a0 100644 --- a/base/src/base/process/process.cc +++ b/base/src/base/process/process.cc @@ -84,8 +84,11 @@ static addr_t _setup_elf(Parent_capability parent_cap, 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 */ @@ -133,6 +136,9 @@ static addr_t _setup_elf(Parent_capability parent_cap, /* detach dataspace */ env()->rm_session()->detach(base); + try { out_ptr = rm.attach_at(ds_cap, addr, size, offset); } + catch (Rm_session::Attach_failed) { } + } else { /* read-only segment */ @@ -142,11 +148,14 @@ static addr_t _setup_elf(Parent_capability parent_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"); - } - void *out_ptr = 0; - try { out_ptr = rm.attach(ds_cap, size, offset, true, addr); } - catch (Rm_session::Attach_failed) { } + if (exec) + try { out_ptr = rm.attach_executable(ds_cap, addr, size, offset); } + catch (Rm_session::Attach_failed) { } + else + try { out_ptr = rm.attach_at(ds_cap, addr, size, offset); } + catch (Rm_session::Attach_failed) { } + } if ((addr_t)out_ptr != addr) PWRN("addresses differ after attach (addr=%p out_ptr=%p)", diff --git a/base/src/core/context_area.cc b/base/src/core/context_area.cc index 59495fbdd..53cb276e0 100644 --- a/base/src/core/context_area.cc +++ b/base/src/core/context_area.cc @@ -49,7 +49,8 @@ class Context_area_rm_session : public Rm_session */ Local_addr attach(Dataspace_capability ds_cap, size_t size, off_t offset, - bool use_local_addr, Local_addr local_addr) + bool use_local_addr, Local_addr local_addr, + bool executable) { Dataspace_component *ds = dynamic_cast(Dataspace_capability::deref(ds_cap)); diff --git a/base/src/core/include/core_rm_session.h b/base/src/core/include/core_rm_session.h index d50940300..6940654e6 100644 --- a/base/src/core/include/core_rm_session.h +++ b/base/src/core/include/core_rm_session.h @@ -38,7 +38,8 @@ namespace Genode { Local_addr attach(Dataspace_capability ds_cap, size_t size=0, off_t offset=0, bool use_local_addr = false, - Local_addr local_addr = 0) + Local_addr local_addr = 0, + bool executable = false) { Dataspace_component *ds = static_cast(_ds_ep->obj_by_cap(ds_cap)); if (!ds) diff --git a/base/src/core/include/rm_session_component.h b/base/src/core/include/rm_session_component.h index 2506528ec..54a77f3d3 100644 --- a/base/src/core/include/rm_session_component.h +++ b/base/src/core/include/rm_session_component.h @@ -342,7 +342,7 @@ namespace Genode { ** Region manager session interface ** **************************************/ - Local_addr attach (Dataspace_capability, size_t, off_t, bool, Local_addr); + Local_addr attach (Dataspace_capability, size_t, off_t, bool, Local_addr, bool); void detach (Local_addr); Pager_capability add_client (Thread_capability); void fault_handler (Signal_context_capability handler); diff --git a/base/src/core/rm_session_component.cc b/base/src/core/rm_session_component.cc index 2d72277a7..1943f8dc9 100644 --- a/base/src/core/rm_session_component.cc +++ b/base/src/core/rm_session_component.cc @@ -318,7 +318,8 @@ void Rm_faulter::continue_after_resolved_fault() Rm_session::Local_addr Rm_session_component::attach(Dataspace_capability ds_cap, size_t size, off_t offset, bool use_local_addr, - Rm_session::Local_addr local_addr) + Rm_session::Local_addr local_addr, + bool executable) { /* serialize access */ Lock::Guard lock_guard(_lock); diff --git a/os/src/lib/ldso/file.cc b/os/src/lib/ldso/file.cc index 9dd703d81..57964923b 100644 --- a/os/src/lib/ldso/file.cc +++ b/os/src/lib/ldso/file.cc @@ -78,6 +78,13 @@ namespace Genode { size_t size = 0, off_t offset = 0) { return Rm_connection::attach_at(ds, local_addr - _base, size, offset); } + /** + * Overwritten from 'Rm_connection' + */ + Local_addr attach_executable(Dataspace_capability ds, addr_t local_addr, + size_t size = 0, off_t offset = 0) { + return Rm_connection::attach_executable(ds, local_addr - _base, size, offset); } + void detach(Local_addr local_addr) { Rm_connection::detach((addr_t)local_addr - _base); } }; @@ -128,7 +135,7 @@ namespace Genode { void setup_text(addr_t vaddr, size_t size, off_t offset) { _vaddr = vaddr; - Rm_area::r()->attach_at(_ds_rom, vaddr, size, offset); + Rm_area::r()->attach_executable(_ds_rom, vaddr, size, offset); } addr_t alloc_region(addr_t vaddr, addr_t vlimit) diff --git a/ports/src/app/gdb_monitor/rm_session_component.cc b/ports/src/app/gdb_monitor/rm_session_component.cc index cd19a13ec..e1795bf50 100644 --- a/ports/src/app/gdb_monitor/rm_session_component.cc +++ b/ports/src/app/gdb_monitor/rm_session_component.cc @@ -57,7 +57,8 @@ Rm_session_component::Region *Rm_session_component::find_region(void *local_addr Rm_session::Local_addr Rm_session_component::attach(Dataspace_capability ds_cap, size_t size, off_t offset, bool use_local_addr, - Rm_session::Local_addr local_addr) + Rm_session::Local_addr local_addr, + bool executable) { if (verbose) PDBG("size = %zd, offset = %x", size, (unsigned int)offset); @@ -76,7 +77,9 @@ Rm_session_component::attach(Dataspace_capability ds_cap, size_t size, throw Invalid_args(); } - void *addr = _parent_rm_session.attach(ds_cap, size, offset, use_local_addr, local_addr); + void *addr = _parent_rm_session.attach(ds_cap, size, offset, + use_local_addr, local_addr, + executable); Lock::Guard lock_guard(_region_map_lock); _region_map.insert(new (env()->heap()) Region(addr, (void*)((addr_t)addr + size - 1), ds_cap, offset)); diff --git a/ports/src/app/gdb_monitor/rm_session_component.h b/ports/src/app/gdb_monitor/rm_session_component.h index dd1fb0d2f..02845d4d7 100644 --- a/ports/src/app/gdb_monitor/rm_session_component.h +++ b/ports/src/app/gdb_monitor/rm_session_component.h @@ -93,7 +93,7 @@ namespace Gdb_monitor { **************************************/ Local_addr attach (Dataspace_capability, Genode::size_t, - Genode::off_t, bool, Local_addr); + Genode::off_t, bool, Local_addr, bool); void detach (Local_addr); Pager_capability add_client (Thread_capability); void fault_handler (Signal_context_capability handler); diff --git a/ports/src/noux/rm_session_component.h b/ports/src/noux/rm_session_component.h index 9e02b2af8..3a35c7515 100644 --- a/ports/src/noux/rm_session_component.h +++ b/ports/src/noux/rm_session_component.h @@ -188,7 +188,8 @@ namespace Noux { Local_addr attach(Dataspace_capability ds, size_t size = 0, off_t offset = 0, bool use_local_addr = false, - Local_addr local_addr = (addr_t)0) + Local_addr local_addr = (addr_t)0, + bool executable = false) { if (size == 0) size = Dataspace_client(ds).size(); @@ -199,7 +200,8 @@ namespace Noux { */ local_addr = _rm.attach(ds, size, offset, - use_local_addr, local_addr); + use_local_addr, local_addr, + executable); /* * Record attachement for later replay (needed during