os: remove startup lib from dynamic programs

All the pre- and post-processing of the startup lib around the main
function of a dynamic program is now done by LDSO. Hence LDSO directly
calls the main function of the program.

Issue #1042
This commit is contained in:
Martin Stein 2014-02-05 15:18:21 +01:00 committed by Norman Feske
parent 8d21064b5e
commit bd52e49698
15 changed files with 81 additions and 230 deletions

View File

@ -80,15 +80,6 @@ LIBS += ldso-startup
ifneq ($(LIB),$(DYNAMIC_LINKER))
LIBS += $(DYNAMIC_LINKER)
#
# Ensure that startup_dyn is build for the dynamic programs that depend on a
# shared library. They add it to their dependencies as replacement for the
# static-case startup as soon as they recognize that they are dynamic.
# The current library in contrast filters-out startup_dyn from its
# dependencies before they get merged.
#
LIBS += startup_dyn
endif
#

View File

@ -126,17 +126,11 @@ $(LIB_A): $(OBJECTS)
$(MSG_MERGE)$(LIB_A)
$(VERBOSE)$(AR) -rc $@ $(OBJECTS)
#
# Prevent linkage of startup_dyn as we added it only in order that it gets
# build for the dynamic programs.
#
ifdef SHARED_LIB
override DEPS := $(filter-out startup_dyn.lib,$(DEPS))
#
# Prevent linkage of startup code and base libs against shared libraries except
# for ld.lib.so
#
ifdef SHARED_LIB
ifneq ($(LIB),ld)
override DEPS := $(filter-out $(BASE_LIBS:=.lib) startup.lib,$(DEPS))
endif

View File

@ -126,13 +126,9 @@ LD_CMD += -Wl,--dynamic-linker=$(DYNAMIC_LINKER).lib.so \
-Wl,--eh-frame-hdr
#
# Filter out the base libraries since they will be provided by the LDSO
# library and the startup library as the CRT0 part of program startup is
# done by LDSO already. As replacement for the startup library startup_dyn
# is used. The startup_dyn build is triggered by any shared library without
# merging it to the library.
# Filter out the base libraries since they will be provided by the LDSO library
#
FILTER_DEPS := $(filter-out $(BASE_LIBS) startup,$(DEPS:.lib=)) startup_dyn
FILTER_DEPS := $(filter-out $(BASE_LIBS) startup,$(DEPS:.lib=))
SHARED_LIBS += $(LIB_CACHE_DIR)/$(DYNAMIC_LINKER)/$(DYNAMIC_LINKER).lib.so
#

View File

@ -56,7 +56,6 @@
/* stack of the temporary initial environment */
.p2align 4
.space 32 * 1024
.global _stack_high
_stack_high:
/* initial value of the SP register */

View File

@ -59,7 +59,6 @@
/* stack of the temporary initial environment */
.p2align 4
.space 32 * 1024
.global _stack_high
_stack_high:
/* initial value of the ESP, EAX and EDI register */

View File

@ -70,16 +70,15 @@
/* stack of the temporary initial environment */
.p2align 8
.space 32 * 1024
.global _stack_high
_stack_high:
/* initial value of the RSP, RAX and RDI register */
.globl __initial_sp
.globl __initial_sp
__initial_sp:
.space 8
.globl __initial_ax
.globl __initial_ax
__initial_ax:
.space 8
.globl __initial_di
.globl __initial_di
__initial_di:
.space 8

View File

@ -1,5 +0,0 @@
SRC_CC += _main.cc
REP_INC_DIR += src/platform
vpath _main.cc $(BASE_DIR)/src/platform

View File

@ -0,0 +1,58 @@
/*
* \brief Call the main function of the dynamic program
* \author Martin Stein
* \date 2013-12-14
*/
/*
* Copyright (C) 2014 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.
*/
typedef void (*Func)(void);
int genode_atexit(Func);
extern "C" { void const ** get_program_var_addr(char const * name); }
extern char ** genode_argv;
extern int genode_argc;
extern char ** genode_envp;
/**
* Cast a given function pointer into a 'void (*)()' function pointer
*
* \param ptr source function pointer
*/
template <typename Func_ptr>
static Func * func(Func_ptr ptr)
{
return reinterpret_cast<Func *>(const_cast<void **>(ptr));
}
/**
* Call the main function of the dynamic program
*
* \param main_ptr raw pointer of program main-function
*
* \return return value of the program main-function
*/
extern "C" int call_program_main(Func main_func)
{
/* call constructors of global objects of the program */
Func * const _ctors_end = func(get_program_var_addr("_ctors_end"));
Func * const _ctors_start = func(get_program_var_addr("_ctors_start"));
for (Func * ctor = _ctors_end; ctor != _ctors_start; (*--ctor)());
/* register global-object destructors of program at LDSO atexit-array */
Func * const _dtors_end = func(get_program_var_addr("_dtors_end"));
Func * const _dtors_start = func(get_program_var_addr("_dtors_start"));
for (Func * dtor = _dtors_start; dtor != _dtors_end; genode_atexit(*dtor++));
/* call main function of the program */
typedef int (*Main)(int, char **, char **);
Main const main = reinterpret_cast<Main>(main_func);
return main(genode_argc, genode_argv, genode_envp);
}

View File

@ -1,45 +0,0 @@
/*
* \brief Call main function (ARM specific)
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
* \author Martin Stein
* \date 2011-05-05
*/
/*
* 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.
*/
#ifndef _ARM__CALL_MAIN_H_
#define _ARM__CALL_MAIN_H_
void * my_stack_top();
void set_program_var(const char *, const void *);
extern void * __initial_sp;
/**
* Call program _main with the environment that its CRT0 would have created
*
* \param _main_fp pointer to _main function of dynamic program
*/
void call_main(void (*_main_fp)(void))
{
/* make initial value of some registers available to dynamic program */
set_program_var("__initial_sp", __initial_sp);
/*
* We could also do a call but that would enable the the program main to
* return to LDSO wich isn't desired. This means also that not resetting
* the SP to stack top as we do would waste stack memory for dead LDSO
* frames.
*/
asm volatile ("mov sp, %[sp];"
"bx %[ip];"
:: [sp] "r" (my_stack_top()),
[ip] "r" (_main_fp)
: "memory");
}
#endif /* _ARM__CALL_MAIN_H_ */

View File

@ -1,50 +0,0 @@
/*
* \brief Call main function (X86 specific)
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
* \author Martin Stein
* \date 2011-05-02
*/
/*
* 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.
*/
#ifndef _X86_32__CALL_MAIN_H_
#define _X86_32__CALL_MAIN_H_
void * my_stack_top();
void set_program_var(const char *, const void *);
extern void * __initial_sp;
extern void * __initial_ax;
extern void * __initial_di;
/**
* Call program _main with the environment that its CRT0 would have created
*
* \param _main_fp pointer to _main function of dynamic program
*/
void call_main(void (*_main_fp)(void))
{
/* make initial value of some registers available to dynamic program */
set_program_var("__initial_sp", __initial_sp);
set_program_var("__initial_ax", __initial_ax);
set_program_var("__initial_di", __initial_di);
/*
* We could also do a call but that would enable the the program main to
* return to LDSO wich isn't desired. This means also that not resetting
* the SP to stack top as we do would waste stack memory for dead LDSO
* frames.
*/
asm volatile ("mov %[sp], %%esp;"
"xor %%ebp, %%ebp;"
"jmp *%[ip];"
:: [sp] "r" (my_stack_top()),
[ip] "r" (_main_fp)
: "memory");
}
#endif /* _X86_32__CALL_MAIN_H_ */

View File

@ -1,50 +0,0 @@
/*
* \brief Call main function (X86 64 bit specific)
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
* \author Martin Stein
* \date 2011-05-011
*/
/*
* 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.
*/
#ifndef _X86_64__CALL_MAIN_H_
#define _X86_64__CALL_MAIN_H_
void * my_stack_top();
void set_program_var(const char *, const void *);
extern void * __initial_sp;
extern void * __initial_ax;
extern void * __initial_di;
/**
* Call program _main with the environment that its CRT0 would have created
*
* \param _main_fp pointer to _main function of dynamic program
*/
void call_main(void (*_main_fp)(void))
{
/* make initial value of some registers available to dynamic program */
set_program_var("__initial_sp", __initial_sp);
set_program_var("__initial_ax", __initial_ax);
set_program_var("__initial_di", __initial_di);
/*
* We could also do a call but that would enable the the program main to
* return to LDSO wich isn't desired. This means also that not resetting
* the SP to stack top as we do would waste stack memory for dead LDSO
* frames.
*/
asm volatile ("movq %[sp], %%rsp;"
"xorq %%rbp, %%rbp;"
"jmpq *%[ip];"
:: [sp] "r" (my_stack_top()),
[ip] "r" (_main_fp)
: "memory");
}
#endif /* _X86_64__CALL_MAIN_H_ */

View File

@ -19,8 +19,6 @@
#include <string.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <base/crt0.h>
#include <call_main.h>
#include "file.h"
typedef void (*func_ptr_type)();
@ -30,6 +28,9 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp);
extern char **lx_environ;
int call_program_main(void (*main_func)(void));
static void *setup_stack(const char *name, long fd)
{
char **p;
@ -86,27 +87,8 @@ int main(int argc, char **argv)
/* build dummy stack */
void *sp = setup_stack(binary, (long)fd);
func_ptr_type const program_main = _rtld(sp, &exit_proc, &objp);
/* DEBUGGING
printf("Starting ldso ...\n");
*/
/* this is usually '_start' */
func_ptr_type main_func = _rtld(sp, &exit_proc, &objp);
/* DEBUGGING
char **p;
for(p = environ; *p; p++)
printf("env: %s\n", *p);
printf("Starting application ... environ: %p\n", lx_environ);
*/
/* start loaded application */
call_main(main_func);
exit_proc();
printf("Exiting ldso\n");
return 0;
/* call main function of dynamic program */
return call_program_main(program_main);
}

View File

@ -8,7 +8,7 @@ SRC_S = rtld_start.S
SRC_C = reloc.c rtld.c map_object.c xmalloc.c debug.c main.c \
ldso_types.c rtld_dummies.c platform.c
SRC_CC = stdio.cc stdlib.cc file.cc err.cc string.cc lock.cc \
test.cc environ.cc thread.cc
test.cc environ.cc call_program_main.cc
INC_DIR += $(DIR)/ \
$(DIR)/contrib \

View File

@ -1,24 +0,0 @@
/*
* \brief Thread related C helpers
* \author Martin Stein
* \date 2013-12-13
*/
/*
* 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 <base/thread.h>
/**
* Return top end of the stack of the calling thread
*/
extern "C" void * my_stack_top()
{
return Genode::Thread_base::myself()->stack_top();
}

View File

@ -16,7 +16,7 @@
* Program doesn't need to startup with CRT0 as LDSO has done this
* initialization during its own CRT0 already.
*/
ENTRY(_main)
ENTRY(main)
PHDRS
{
@ -171,6 +171,7 @@ SECTIONS
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
@ -181,17 +182,20 @@ SECTIONS
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
KEEP (*(.init_array)) /* list of constructors specific for ARM eabi */
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
_ctors_end = .;
}
.dtors :
{
_dtors_start = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
_dtors_start = .;
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
_dtors_end = .;
}
.jcr : { KEEP (*(.jcr)) }
@ -217,6 +221,9 @@ SECTIONS
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
__dso_handle = .;
LONG(0x0);
}
.data1 : { *(.data1) }
_edata = .; PROVIDE (edata = .);