2011-12-22 16:19:25 +01:00
|
|
|
/*
|
|
|
|
* \brief Implementation of process creation for Linux
|
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2006-07-06
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2013-01-10 21:44:47 +01:00
|
|
|
* Copyright (C) 2006-2013 Genode Labs GmbH
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
|
|
|
* 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 <base/elf.h>
|
|
|
|
#include <base/env.h>
|
|
|
|
#include <base/process.h>
|
|
|
|
#include <base/printf.h>
|
2012-08-15 19:14:05 +02:00
|
|
|
#include <linux_pd_session/client.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2012-08-15 19:14:05 +02:00
|
|
|
/* framework-internal includes */
|
2011-12-22 16:19:25 +01:00
|
|
|
#include <linux_syscalls.h>
|
|
|
|
|
|
|
|
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
|
|
Dataspace_capability Process::_dynamic_linker_cap;
|
|
|
|
|
2012-08-08 22:01:04 +02:00
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
/**
|
|
|
|
* 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();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-15 19:14:05 +02:00
|
|
|
Process::Process(Dataspace_capability elf_data_ds_cap,
|
|
|
|
Ram_session_capability ram_session_cap,
|
|
|
|
Cpu_session_capability cpu_session_cap,
|
|
|
|
Rm_session_capability rm_session_cap,
|
|
|
|
Parent_capability parent_cap,
|
2012-10-11 20:57:10 +02:00
|
|
|
char const *name,
|
2012-11-21 15:20:21 +01:00
|
|
|
Native_pd_args const *pd_args)
|
2012-08-15 19:14:05 +02:00
|
|
|
:
|
2012-11-21 15:20:21 +01:00
|
|
|
_pd(name, pd_args),
|
2013-01-03 16:23:11 +01:00
|
|
|
_cpu_session_client(cpu_session_cap),
|
2012-08-15 19:14:05 +02:00
|
|
|
_rm_session_client(Rm_session_capability())
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
|
|
|
/* 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");
|
2012-08-15 19:14:05 +02:00
|
|
|
return;
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
2013-05-24 11:04:42 +02:00
|
|
|
/*
|
|
|
|
* Starting the dynamic linker directly may cause it to be loaded at the
|
|
|
|
* wrong address on ARM-Linux. But since the dynamically linked
|
|
|
|
* application has a dynamic linker (by default ld.lib.so) defined as its
|
|
|
|
* interpreter in the ELF image, it's okay to just start the application
|
|
|
|
* directly on Linux.
|
|
|
|
*/
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
|
2013-01-03 16:23:11 +01:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
_thread0_cap = _cpu_session_client.create_thread(name);
|
|
|
|
|
2012-08-15 19:14:05 +02:00
|
|
|
Linux_pd_session_client lx_pd(static_cap_cast<Linux_pd_session>(_pd.cap()));
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2012-08-15 19:14:05 +02:00
|
|
|
lx_pd.assign_parent(parent_cap);
|
2012-10-11 20:57:10 +02:00
|
|
|
lx_pd.start(elf_data_ds_cap);
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Process::~Process() { }
|