2016-04-27 16:04:58 +02:00
|
|
|
/*
|
|
|
|
* \brief Process creation
|
|
|
|
* \author Norman Feske
|
|
|
|
* \author Christian Helmuth
|
|
|
|
* \date 2006-07-18
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2006-2017 Genode Labs GmbH
|
2016-04-27 16:04:58 +02:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2016-04-27 16:04:58 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode includes */
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
#include <base/log.h>
|
2016-04-27 16:04:58 +02:00
|
|
|
#include <base/child.h>
|
2016-05-10 18:05:38 +02:00
|
|
|
#include <cpu_thread/client.h>
|
2016-04-27 16:04:58 +02:00
|
|
|
|
|
|
|
/* base-internal includes */
|
|
|
|
#include <base/internal/elf.h>
|
2016-06-13 15:14:32 +02:00
|
|
|
#include <base/internal/parent_cap.h>
|
2016-04-27 16:04:58 +02:00
|
|
|
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
|
|
|
2018-07-04 18:48:04 +02:00
|
|
|
Child::Process::Loaded_executable::Loaded_executable(Type type,
|
2016-04-27 16:04:58 +02:00
|
|
|
Dataspace_capability ldso_ds,
|
2019-01-30 17:53:16 +01:00
|
|
|
Ram_session &ram,
|
2016-04-27 16:04:58 +02:00
|
|
|
Region_map &local_rm,
|
|
|
|
Region_map &remote_rm,
|
|
|
|
Parent_capability parent_cap)
|
|
|
|
{
|
|
|
|
/* skip loading when called during fork */
|
2018-07-04 18:48:04 +02:00
|
|
|
if (type == TYPE_FORKED)
|
2016-04-27 16:04:58 +02:00
|
|
|
return;
|
|
|
|
|
2018-07-04 18:48:04 +02:00
|
|
|
/* 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); }
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
catch (Region_map::Invalid_dataspace) {
|
2018-07-04 18:48:04 +02:00
|
|
|
error("dynamic linker is an invalid dataspace"); throw; }
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
catch (Region_map::Region_conflict) {
|
2018-07-04 18:48:04 +02:00
|
|
|
error("region conflict while attaching dynamic linker"); throw; }
|
2016-04-27 16:04:58 +02:00
|
|
|
|
|
|
|
Elf_binary elf(elf_addr);
|
|
|
|
|
|
|
|
entry = elf.entry();
|
|
|
|
|
|
|
|
/* setup region map for the new pd */
|
|
|
|
Elf_segment seg;
|
|
|
|
|
2018-10-25 16:37:51 +02:00
|
|
|
bool parent_info = false;
|
|
|
|
|
2016-04-27 16:04:58 +02:00
|
|
|
for (unsigned n = 0; (seg = elf.get_segment(n)).valid(); ++n) {
|
2016-09-15 16:08:33 +02:00
|
|
|
if (seg.flags().skip) continue;
|
|
|
|
if (seg.mem_size() == 0) continue;
|
2016-04-27 16:04:58 +02:00
|
|
|
|
|
|
|
/* 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 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;
|
2019-01-30 17:53:16 +01:00
|
|
|
try { ds_cap = ram.alloc(size); }
|
2017-05-08 19:55:54 +02:00
|
|
|
catch (Out_of_ram) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
error("allocation of read-write segment failed"); throw; };
|
2016-04-27 16:04:58 +02:00
|
|
|
|
|
|
|
/* attach dataspace */
|
|
|
|
void *base;
|
|
|
|
try { base = local_rm.attach(ds_cap); }
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
catch (Region_map::Invalid_dataspace) {
|
|
|
|
error("attempt to attach invalid segment dataspace"); throw; }
|
|
|
|
catch (Region_map::Region_conflict) {
|
|
|
|
error("region conflict while locally attaching ELF segment"); throw; }
|
2016-04-27 16:04:58 +02:00
|
|
|
|
|
|
|
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) {
|
2016-06-13 15:14:32 +02:00
|
|
|
*(Untyped_capability::Raw *)ptr = parent_cap.raw();
|
2016-04-27 16:04:58 +02:00
|
|
|
parent_info = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* detach dataspace */
|
|
|
|
local_rm.detach(base);
|
|
|
|
|
|
|
|
off_t const offset = 0;
|
|
|
|
try { remote_rm.attach_at(ds_cap, addr, size, offset); }
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
catch (Region_map::Region_conflict) {
|
2018-07-04 18:48:04 +02:00
|
|
|
error("region conflict while remotely attaching ELF segment");
|
|
|
|
error("addr=", (void *)addr, " size=", (void *)size, " offset=", (void *)offset);
|
|
|
|
throw; }
|
2016-04-27 16:04:58 +02:00
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/* read-only segment */
|
|
|
|
|
|
|
|
if (seg.file_size() != seg.mem_size())
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
warning("filesz and memsz for read-only segment differ");
|
2016-04-27 16:04:58 +02:00
|
|
|
|
|
|
|
off_t const offset = seg.file_offset();
|
|
|
|
try {
|
|
|
|
if (exec)
|
2018-07-04 18:48:04 +02:00
|
|
|
remote_rm.attach_executable(ldso_ds, addr, size, offset);
|
2016-04-27 16:04:58 +02:00
|
|
|
else
|
2018-07-04 18:48:04 +02:00
|
|
|
remote_rm.attach_at(ldso_ds, addr, size, offset);
|
2016-04-27 16:04:58 +02:00
|
|
|
}
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
catch (Region_map::Region_conflict) {
|
|
|
|
error("region conflict while remotely attaching read-only ELF segment");
|
2018-07-04 18:48:04 +02:00
|
|
|
error("addr=", (void *)addr, " size=", (void *)size, " offset=", (void *)offset);
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
throw;
|
|
|
|
}
|
|
|
|
catch (Region_map::Invalid_dataspace) {
|
|
|
|
error("attempt to attach invalid read-only segment dataspace");
|
|
|
|
throw;
|
|
|
|
}
|
2016-04-27 16:04:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* detach ELF */
|
|
|
|
local_rm.detach((void *)elf_addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-10 18:05:38 +02:00
|
|
|
Child::Initial_thread::Initial_thread(Cpu_session &cpu,
|
|
|
|
Pd_session_capability pd,
|
|
|
|
Name const &name)
|
2016-04-27 16:04:58 +02:00
|
|
|
:
|
2016-05-10 18:05:38 +02:00
|
|
|
_cpu(cpu),
|
|
|
|
_cap(cpu.create_thread(pd, name, Affinity::Location(), Cpu_session::Weight()))
|
2016-04-27 16:04:58 +02:00
|
|
|
{ }
|
|
|
|
|
|
|
|
|
2016-05-10 18:05:38 +02:00
|
|
|
Child::Initial_thread::~Initial_thread()
|
2016-04-27 16:04:58 +02:00
|
|
|
{
|
2016-05-10 18:05:38 +02:00
|
|
|
_cpu.kill_thread(_cap);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Child::Initial_thread::start(addr_t ip)
|
|
|
|
{
|
|
|
|
Cpu_thread_client(_cap).start(ip, 0);
|
2016-04-27 16:04:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-04 18:48:04 +02:00
|
|
|
Child::Process::Process(Type type,
|
2016-04-27 16:04:58 +02:00
|
|
|
Dataspace_capability ldso_ds,
|
|
|
|
Pd_session &pd,
|
2016-05-10 18:05:38 +02:00
|
|
|
Initial_thread_base &initial_thread,
|
2016-04-27 16:04:58 +02:00
|
|
|
Region_map &local_rm,
|
|
|
|
Region_map &remote_rm,
|
2016-05-10 18:05:38 +02:00
|
|
|
Parent_capability parent_cap)
|
2016-04-27 16:04:58 +02:00
|
|
|
:
|
2018-07-04 18:48:04 +02:00
|
|
|
loaded_executable(type, ldso_ds, pd, local_rm, remote_rm, parent_cap)
|
2016-04-27 16:04:58 +02:00
|
|
|
{
|
|
|
|
/* 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'.
|
|
|
|
*/
|
2018-07-04 18:48:04 +02:00
|
|
|
if (type == TYPE_FORKED)
|
2016-04-27 16:04:58 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* start main thread */
|
2016-05-10 18:05:38 +02:00
|
|
|
initial_thread.start(loaded_executable.entry);
|
2016-04-27 16:04:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Child::Process::~Process() { }
|