mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-23 09:15:36 +00:00
Introduce 'spec' subdirectories to outline aspects
Instead of holding SPEC-variable dependent files and directories inline within the repository structure, move them into 'spec' subdirectories at the corresponding levels, e.g.: repos/base/include/spec repos/base/mk/spec repos/base/lib/mk/spec repos/base/src/core/spec ... Moreover, this commit removes the 'platform' directories. That term was used in an overloaded sense. All SPEC-relative 'platform' directories are now named 'spec'. Other files, like for instance those related to the kernel/architecture specific startup library, where moved from 'platform' directories to explicit, more meaningful places like e.g.: 'src/lib/startup'. Fix #1673
This commit is contained in:
committed by
Christian Helmuth
parent
6cdb823187
commit
ed52d5a211
@ -11,8 +11,8 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__ARM__RELOCATION_H_
|
||||
#define _INCLUDE__ARM__RELOCATION_H_
|
||||
#ifndef _LIB__LDSO__SPEC__ARM__RELOCATION_H_
|
||||
#define _LIB__LDSO__SPEC__ARM__RELOCATION_H_
|
||||
|
||||
#include <relocation_generic.h>
|
||||
|
||||
@ -113,4 +113,4 @@ class Linker::Reloc_non_plt : public Reloc_non_plt_generic
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__ARM__RELOCATION_H_ */
|
||||
#endif /* _LIB__LDSO__SPEC__ARM__RELOCATION_H_ */
|
@ -11,8 +11,8 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _X86_32__RELOCATION_H_
|
||||
#define _X86_32__RELOCATION_H_
|
||||
#ifndef _LIB__LDSO__SPEC__X86_32__RELOCATION_H_
|
||||
#define _LIB__LDSO__SPEC__X86_32__RELOCATION_H_
|
||||
|
||||
#include <relocation_generic.h>
|
||||
|
||||
@ -93,4 +93,4 @@ class Linker::Reloc_non_plt : public Reloc_non_plt_generic
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _X86_32__RELOCATION_H_ */
|
||||
#endif /* _LIB__LDSO__SPEC__X86_32__RELOCATION_H_ */
|
@ -11,8 +11,8 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__X86_64__RELOCATION_H_
|
||||
#define _INCLUDE__X86_64__RELOCATION_H_
|
||||
#ifndef _LIB__LDSO__SPEC__X86_64__RELOCATION_H_
|
||||
#define _LIB__LDSO__SPEC__X86_64__RELOCATION_H_
|
||||
|
||||
#include <relocation_generic.h>
|
||||
|
||||
@ -99,4 +99,4 @@ class Linker::Reloc_non_plt : public Reloc_non_plt_generic
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__X86_64__RELOCATION_H_ */
|
||||
#endif /* _LIB__LDSO__SPEC__X86_64__RELOCATION_H_ */
|
253
repos/base/src/lib/startup/_main.cc
Normal file
253
repos/base/src/lib/startup/_main.cc
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
* \brief Startup code
|
||||
* \author Christian Helmuth
|
||||
* \author Christian Prochaska
|
||||
* \date 2006-04-12
|
||||
*
|
||||
* The startup code calls constructors for static objects before calling
|
||||
* main(). Furthermore, this file contains the support of exit handlers
|
||||
* and destructors.
|
||||
*
|
||||
* Some code within this file is based on 'atexit.c' of FreeBSD's libc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <base/crt0.h>
|
||||
#include <base/env.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
/* platform-specific local helper functions */
|
||||
#include <_main_parent_cap.h>
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
extern int main(int argc, char **argv, char **envp);
|
||||
|
||||
enum { ATEXIT_SIZE = 256 };
|
||||
|
||||
|
||||
/***************
|
||||
** C++ stuff **
|
||||
***************/
|
||||
|
||||
void * __dso_handle = 0;
|
||||
|
||||
enum Atexit_fn_type { ATEXIT_FN_EMPTY, ATEXIT_FN_STD, ATEXIT_FN_CXA };
|
||||
|
||||
struct atexit_fn
|
||||
{
|
||||
Atexit_fn_type fn_type;
|
||||
union
|
||||
{
|
||||
void (*std_func)(void);
|
||||
void (*cxa_func)(void *);
|
||||
} fn_ptr; /* function pointer */
|
||||
void *fn_arg; /* argument for CXA callback */
|
||||
void *fn_dso; /* shared module handle */
|
||||
};
|
||||
|
||||
/* all members are initialized with 0 */
|
||||
static struct atexit
|
||||
{
|
||||
bool enabled;
|
||||
int index;
|
||||
struct atexit_fn fns[ATEXIT_SIZE];
|
||||
} _atexit;
|
||||
|
||||
|
||||
static Lock &atexit_lock()
|
||||
{
|
||||
static Lock _atexit_lock;
|
||||
return _atexit_lock;
|
||||
}
|
||||
|
||||
|
||||
static void atexit_enable()
|
||||
{
|
||||
_atexit.enabled = true;
|
||||
}
|
||||
|
||||
|
||||
static int atexit_register(struct atexit_fn *fn)
|
||||
{
|
||||
Lock::Guard atexit_lock_guard(atexit_lock());
|
||||
|
||||
if (!_atexit.enabled)
|
||||
return 0;
|
||||
|
||||
if (_atexit.index >= ATEXIT_SIZE) {
|
||||
PERR("Cannot register exit handler - ATEXIT_SIZE reached");
|
||||
return -1;
|
||||
}
|
||||
|
||||
_atexit.fns[_atexit.index++] = *fn;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register a function to be performed at exit
|
||||
*/
|
||||
int genode_atexit(void (*func)(void))
|
||||
{
|
||||
struct atexit_fn fn;
|
||||
int error;
|
||||
|
||||
fn.fn_type = ATEXIT_FN_STD;
|
||||
fn.fn_ptr.std_func = func;
|
||||
fn.fn_arg = 0;
|
||||
fn.fn_dso = 0;
|
||||
|
||||
error = atexit_register(&fn);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register a function to be performed at exit or when an shared object
|
||||
* with given dso handle is unloaded dynamically.
|
||||
*
|
||||
* This function is called directly by compiler generated code, so
|
||||
* it needs to be declared as extern "C" and cannot be local to
|
||||
* the cxx lib.
|
||||
*/
|
||||
int genode___cxa_atexit(void (*func)(void*), void *arg, void *dso)
|
||||
{
|
||||
struct atexit_fn fn;
|
||||
int error;
|
||||
|
||||
fn.fn_type = ATEXIT_FN_CXA;
|
||||
fn.fn_ptr.cxa_func = func;
|
||||
fn.fn_arg = arg;
|
||||
fn.fn_dso = dso;
|
||||
|
||||
error = atexit_register(&fn);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Call all handlers registered with __cxa_atexit for the shared
|
||||
* object owning 'dso'. Note: if 'dso' is NULL, then all remaining
|
||||
* handlers are called.
|
||||
*/
|
||||
void genode___cxa_finalize(void *dso)
|
||||
{
|
||||
struct atexit_fn fn;
|
||||
int n = 0;
|
||||
|
||||
atexit_lock().lock();
|
||||
for (n = _atexit.index; --n >= 0;) {
|
||||
if (_atexit.fns[n].fn_type == ATEXIT_FN_EMPTY)
|
||||
continue; /* already been called */
|
||||
if (dso != 0 && dso != _atexit.fns[n].fn_dso)
|
||||
continue; /* wrong DSO */
|
||||
fn = _atexit.fns[n];
|
||||
|
||||
/*
|
||||
* Mark entry to indicate that this particular handler
|
||||
* has already been called.
|
||||
*/
|
||||
_atexit.fns[n].fn_type = ATEXIT_FN_EMPTY;
|
||||
atexit_lock().unlock();
|
||||
|
||||
/* call the function of correct type */
|
||||
if (fn.fn_type == ATEXIT_FN_CXA)
|
||||
fn.fn_ptr.cxa_func(fn.fn_arg);
|
||||
else if (fn.fn_type == ATEXIT_FN_STD)
|
||||
fn.fn_ptr.std_func();
|
||||
|
||||
atexit_lock().lock();
|
||||
}
|
||||
atexit_lock().unlock();
|
||||
}
|
||||
|
||||
|
||||
extern "C" void __cxa_finalize(void *dso);
|
||||
|
||||
/**
|
||||
* Terminate the process.
|
||||
*/
|
||||
void genode_exit(int status)
|
||||
{
|
||||
/* call handlers registered with 'atexit()' or '__cxa_atexit()' */
|
||||
__cxa_finalize(0);
|
||||
|
||||
/* call destructors for global static objects. */
|
||||
void (**func)();
|
||||
for (func = &_dtors_start; func != &_dtors_end; (*func++)());
|
||||
|
||||
/* inform parent about the exit status */
|
||||
env()->parent()->exit(status);
|
||||
|
||||
/* wait for destruction by the parent */
|
||||
sleep_forever();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dummy default arguments for main function
|
||||
*/
|
||||
static char argv0[] = { '_', 'm', 'a', 'i', 'n', 0};
|
||||
static char *argv[1] = { argv0 };
|
||||
|
||||
|
||||
/**
|
||||
* Arguments for main function
|
||||
*
|
||||
* These global variables may be initialized by a constructor provided by an
|
||||
* external library.
|
||||
*/
|
||||
char **genode_argv = argv;
|
||||
int genode_argc = 1;
|
||||
char **genode_envp = 0;
|
||||
|
||||
|
||||
namespace Genode { extern bool inhibit_tracing; }
|
||||
|
||||
|
||||
/**
|
||||
* C entry function called by the crt0 startup code
|
||||
*
|
||||
* Note, _main is executed twice when starting dynamic programs: in ld.lib.so
|
||||
* and also in the loaded binary.
|
||||
*/
|
||||
extern "C" int _main()
|
||||
{
|
||||
/*
|
||||
* Allow exit handlers to be registered.
|
||||
*
|
||||
* This is done after the creation of the environment to prevent its
|
||||
* destruction. The environment is still needed to notify the parent
|
||||
* after all exit handlers (including static object destructors) have
|
||||
* been called.
|
||||
*/
|
||||
atexit_enable();
|
||||
|
||||
/* call constructors for static objects */
|
||||
void (**func)();
|
||||
for (func = &_ctors_end; func != &_ctors_start; (*--func)());
|
||||
|
||||
/* now, it is save to call printf */
|
||||
|
||||
/* enable tracing support */
|
||||
inhibit_tracing = false;
|
||||
|
||||
/* call real main function */
|
||||
int ret = main(genode_argc, genode_argv, genode_envp);
|
||||
|
||||
genode_exit(ret);
|
||||
|
||||
/* not reached */
|
||||
return ret;
|
||||
}
|
33
repos/base/src/lib/startup/_main_parent_cap.h
Normal file
33
repos/base/src/lib/startup/_main_parent_cap.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* \brief Obtain parent capability
|
||||
* \author Norman Feske
|
||||
* \date 2010-01-26
|
||||
*
|
||||
* This implementation is used on platforms that rely on global IDs (thread
|
||||
* IDs, global unique object IDs) as capability representation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-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 _LIB__STARTUP___MAIN_PARENT_CAP_H_
|
||||
#define _LIB__STARTUP___MAIN_PARENT_CAP_H_
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* Return constructed parent capability
|
||||
*/
|
||||
Parent_capability parent_cap()
|
||||
{
|
||||
Parent_capability cap;
|
||||
memcpy(&cap, (void *)&_parent_cap, sizeof(cap));
|
||||
return Parent_capability(cap);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _LIB__STARTUP___MAIN_PARENT_CAP_H_ */
|
20
repos/base/src/lib/startup/cap_copy.cc
Normal file
20
repos/base/src/lib/startup/cap_copy.cc
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* \brief Copy a platform-capability to another protection domain.
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-03-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-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.
|
||||
*/
|
||||
|
||||
#include <util/string.h>
|
||||
#include <base/native_types.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
void Cap_dst_policy::copy(void* dst, Native_capability_tpl<Cap_dst_policy>* src) {
|
||||
memcpy(dst, src, sizeof(Native_capability_tpl<Cap_dst_policy>)); }
|
136
repos/base/src/lib/startup/init_main_thread.cc
Normal file
136
repos/base/src/lib/startup/init_main_thread.cc
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* \brief Setup the thread environment of a programs first thread
|
||||
* \author Christian Helmuth
|
||||
* \author Christian Prochaska
|
||||
* \author Martin Stein
|
||||
* \date 2013-12-04
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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 <util/construct_at.h>
|
||||
#include <base/env.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/thread.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
addr_t init_main_thread_result;
|
||||
|
||||
extern void init_exception_handling();
|
||||
|
||||
namespace Genode { Rm_session * env_context_area_rm_session(); }
|
||||
|
||||
void prepare_init_main_thread();
|
||||
|
||||
enum { MAIN_THREAD_STACK_SIZE = 16UL * 1024 * sizeof(Genode::addr_t) };
|
||||
|
||||
/**
|
||||
* Satisfy crt0.s in static programs, LDSO overrides this symbol
|
||||
*/
|
||||
extern "C" void init_rtld() __attribute__((weak));
|
||||
void init_rtld() { }
|
||||
|
||||
/**
|
||||
* The first thread in a program
|
||||
*/
|
||||
class Main_thread : public Thread<MAIN_THREAD_STACK_SIZE>
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param reinit wether this is called for reinitialization
|
||||
*/
|
||||
Main_thread(bool reinit)
|
||||
:
|
||||
Thread("main", reinit ? REINITIALIZED_MAIN : MAIN)
|
||||
{ }
|
||||
|
||||
/**********************
|
||||
** Thread interface **
|
||||
**********************/
|
||||
|
||||
void entry() { }
|
||||
};
|
||||
|
||||
|
||||
Main_thread * main_thread()
|
||||
{
|
||||
static Main_thread s(false);
|
||||
return &s;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a thread object for the main thread
|
||||
*
|
||||
* \return stack pointer of the new environment via init_main_thread_result
|
||||
*
|
||||
* This function must be called only once per program and before the _main
|
||||
* function. It can be called as soon as a temporary environment provides
|
||||
* some stack space and inter-process communication. At this stage, global
|
||||
* static objects are not registered for implicit destruction at program exit.
|
||||
*/
|
||||
extern "C" void init_main_thread()
|
||||
{
|
||||
/* do platform specific preparation */
|
||||
prepare_init_main_thread();
|
||||
|
||||
/*
|
||||
* Explicitly setup program environment at this point to ensure that its
|
||||
* destructor won't be registered for the atexit routine.
|
||||
*/
|
||||
(void*)env();
|
||||
|
||||
/* initialize exception handling */
|
||||
init_exception_handling();
|
||||
|
||||
/*
|
||||
* We create the thread-context area as early as possible to prevent other
|
||||
* mappings from occupying the predefined virtual-memory region.
|
||||
*/
|
||||
env_context_area_rm_session();
|
||||
|
||||
/*
|
||||
* Trigger first exception. This step has two purposes.
|
||||
* First, it enables us to detect problems related to exception handling as
|
||||
* early as possible. If there are problems with the C++ support library,
|
||||
* it is much easier to debug them at this early stage. Otherwise problems
|
||||
* with half-working exception handling cause subtle failures that are hard
|
||||
* to interpret.
|
||||
*
|
||||
* Second, the C++ support library allocates data structures lazily on the
|
||||
* first occurrence of an exception. This allocation traverses into
|
||||
* Genode's heap and, in some corner cases, consumes several KB of stack.
|
||||
* This is usually not a problem when the first exception is triggered from
|
||||
* the main thread but it becomes an issue when the first exception is
|
||||
* thrown from the context of a thread with a specially tailored (and
|
||||
* otherwise sufficient) stack size. By throwing an exception here, we
|
||||
* mitigate this issue by eagerly performing those allocations.
|
||||
*/
|
||||
try { throw 1; } catch (...) { }
|
||||
|
||||
/* create a thread object for the main thread */
|
||||
main_thread();
|
||||
|
||||
/**
|
||||
* The new stack pointer enables the caller to switch from its current
|
||||
* environment to the those that the thread object provides.
|
||||
*/
|
||||
addr_t sp = reinterpret_cast<addr_t>(main_thread()->stack_top());
|
||||
init_main_thread_result = sp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reinitialize main-thread object according to a reinitialized environment
|
||||
*/
|
||||
void reinit_main_thread() { construct_at<Main_thread>(main_thread(), true); }
|
64
repos/base/src/lib/startup/spec/arm/crt0.s
Normal file
64
repos/base/src/lib/startup/spec/arm/crt0.s
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* \brief Startup code for Genode applications on ARM
|
||||
* \author Norman Feske
|
||||
* \author Martin Stein
|
||||
* \date 2007-04-28
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2007-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.
|
||||
*/
|
||||
|
||||
|
||||
/**************************
|
||||
** .text (program code) **
|
||||
**************************/
|
||||
|
||||
.section ".text.crt0"
|
||||
|
||||
/* program entry-point */
|
||||
.global _start
|
||||
_start:
|
||||
|
||||
/* make initial value of some registers available to higher-level code */
|
||||
ldr r4, =__initial_sp
|
||||
str sp, [r4]
|
||||
|
||||
/*
|
||||
* Install initial temporary environment that is replaced later by the
|
||||
* environment that init_main_thread creates.
|
||||
*/
|
||||
ldr sp, =_stack_high
|
||||
|
||||
/* if this is the dynamic linker, init_rtld relocates the linker */
|
||||
bl init_rtld
|
||||
|
||||
/* create proper environment for main thread */
|
||||
bl init_main_thread
|
||||
|
||||
/* apply environment that was created by init_main_thread */
|
||||
ldr sp, =init_main_thread_result
|
||||
ldr sp, [sp]
|
||||
|
||||
/* jump into init C code instead of calling it as it should never return */
|
||||
b _main
|
||||
|
||||
|
||||
/*********************************
|
||||
** .bss (non-initialized data) **
|
||||
*********************************/
|
||||
|
||||
.section ".bss"
|
||||
|
||||
/* stack of the temporary initial environment */
|
||||
.p2align 4
|
||||
.space 32 * 1024
|
||||
_stack_high:
|
||||
|
||||
/* initial value of the SP register */
|
||||
.global __initial_sp
|
||||
__initial_sp:
|
||||
.space 4
|
83
repos/base/src/lib/startup/spec/x86_32/crt0.s
Normal file
83
repos/base/src/lib/startup/spec/x86_32/crt0.s
Normal file
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* \brief Startup code for Genode applications
|
||||
* \author Christian Helmuth
|
||||
* \author Martin Stein
|
||||
* \date 2009-08-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-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.
|
||||
*/
|
||||
|
||||
|
||||
/**************************
|
||||
** .text (program code) **
|
||||
**************************/
|
||||
|
||||
.section ".text.crt0"
|
||||
|
||||
/* program entry-point */
|
||||
.global _start
|
||||
_start:
|
||||
|
||||
/* save initial register values using GOT-relative addressing */
|
||||
3:
|
||||
movl $., %ecx
|
||||
addl $_GLOBAL_OFFSET_TABLE_ + (. - 3b) , %ecx
|
||||
movl %esp, __initial_sp@GOTOFF(%ecx)
|
||||
movl %eax, __initial_ax@GOTOFF(%ecx)
|
||||
movl %ebx, __initial_bx@GOTOFF(%ecx)
|
||||
movl %edi, __initial_di@GOTOFF(%ecx)
|
||||
|
||||
/* initialize GOT pointer in EBX as expected by the tool chain */
|
||||
mov %ecx, %ebx
|
||||
|
||||
/*
|
||||
* Install initial temporary environment that is replaced later by the
|
||||
* environment that init_main_thread creates.
|
||||
*/
|
||||
leal _stack_high@GOTOFF(%ebx), %esp
|
||||
|
||||
/* if this is the dynamic linker, init_rtld relocates the linker */
|
||||
call init_rtld
|
||||
|
||||
/* create proper environment for the main thread */
|
||||
call init_main_thread
|
||||
|
||||
/* apply environment that was created by init_main_thread */
|
||||
movl init_main_thread_result, %esp
|
||||
|
||||
/* clear the base pointer in order that stack backtraces will work */
|
||||
xor %ebp, %ebp
|
||||
|
||||
/* jump into init C code instead of calling it as it should never return */
|
||||
jmp _main
|
||||
|
||||
|
||||
/*********************************
|
||||
** .bss (non-initialized data) **
|
||||
*********************************/
|
||||
|
||||
.bss
|
||||
|
||||
/* stack of the temporary initial environment */
|
||||
.p2align 4
|
||||
.space 32 * 1024
|
||||
_stack_high:
|
||||
|
||||
/* initial value of the ESP, EAX and EDI register */
|
||||
.global __initial_sp
|
||||
__initial_sp:
|
||||
.space 4
|
||||
.global __initial_ax
|
||||
__initial_ax:
|
||||
.space 4
|
||||
.global __initial_bx
|
||||
__initial_bx:
|
||||
.space 4
|
||||
.global __initial_di
|
||||
__initial_di:
|
||||
.space 4
|
87
repos/base/src/lib/startup/spec/x86_64/crt0.s
Normal file
87
repos/base/src/lib/startup/spec/x86_64/crt0.s
Normal file
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* \brief Startup code for Genode 64Bit applications
|
||||
* \author Sebastian Sumpf
|
||||
* \author Martin Stein
|
||||
* \date 2011-05-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-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.
|
||||
*/
|
||||
|
||||
|
||||
/**************************
|
||||
** .text (program code) **
|
||||
**************************/
|
||||
|
||||
.section ".text.crt0"
|
||||
|
||||
/* program entry-point */
|
||||
.global _start
|
||||
_start:
|
||||
|
||||
/* initialize GLOBAL OFFSET TABLE */
|
||||
leaq _GLOBAL_OFFSET_TABLE_(%rip), %r15
|
||||
|
||||
/* make initial value of some registers available to higher-level code */
|
||||
movq __initial_ax@GOTPCREL(%rip), %rbx
|
||||
movq %rax, (%rbx)
|
||||
movq __initial_di@GOTPCREL(%rip), %rbx
|
||||
movq %rdi, (%rbx)
|
||||
movq __initial_sp@GOTPCREL(%rip), %rax
|
||||
movq %rsp, (%rax)
|
||||
|
||||
/*
|
||||
* Install initial temporary environment that is replaced later by the
|
||||
* environment that init_main_thread creates.
|
||||
*/
|
||||
leaq _stack_high@GOTPCREL(%rip),%rax
|
||||
movq (%rax), %rsp
|
||||
|
||||
/* if this is the dynamic linker, init_rtld relocates the linker */
|
||||
call init_rtld
|
||||
|
||||
/* create proper environment for the main thread */
|
||||
call init_main_thread
|
||||
|
||||
/* apply environment that was created by init_main_thread */
|
||||
movq init_main_thread_result@GOTPCREL(%rip), %rax
|
||||
movq (%rax), %rsp
|
||||
|
||||
/* clear the base pointer in order that stack backtraces will work */
|
||||
xorq %rbp, %rbp
|
||||
|
||||
/*
|
||||
* We jump into initial C code instead of calling it as it should never
|
||||
* return on the one hand and because the alignment of the stack pointer
|
||||
* that init_main_thread returned expects a jump at the other hand. The
|
||||
* latter matters because GCC expects the initial stack pointer to be
|
||||
* aligned to 16 byte for at least the handling of floating points.
|
||||
*/
|
||||
jmp _main
|
||||
|
||||
|
||||
/*********************************
|
||||
** .bss (non-initialized data) **
|
||||
*********************************/
|
||||
|
||||
.bss
|
||||
|
||||
/* stack of the temporary initial environment */
|
||||
.p2align 8
|
||||
.space 32 * 1024
|
||||
_stack_high:
|
||||
|
||||
/* initial value of the RSP, RAX and RDI register */
|
||||
.globl __initial_sp
|
||||
__initial_sp:
|
||||
.space 8
|
||||
.globl __initial_ax
|
||||
__initial_ax:
|
||||
.space 8
|
||||
.globl __initial_di
|
||||
__initial_di:
|
||||
.space 8
|
Reference in New Issue
Block a user