[PATCH/RFC] PIC and flat shared library support for m68k

David McCullough david_mccullough at au.securecomputing.com
Thu Jul 6 22:15:51 UTC 2006


Jivin Richard Sandiford lays it down ...
> This patch adds m68k support for flat shared libraries and uClinux-style
> PIC.  The reason I've stuck "RFC" in the subject line is that the shared
> library side of things is rather different from the uClinux-dist version,
> and this might make the patch a little controversial.  However, the new
> approach should still be compatible with the old one, as explained below.
> 
> Stepping back a bit, the traditional method for building flat shared
> libraries does not allow either the libraries or the executable to have
> constructors and destructors:
> 
>   http://www.ucdot.org/article.pl?sid=03/11/25/1126257&mode=thread

Could you run over how the constructots/destructors are broken in the
current arrangement used by the uClinux-dist.  Myself and a couple
of others are fairly certain that they were working when we were doing
m68k on a daily basis.

I won't argue that the uClibc support for flat shared libs needs some
work though :-)

Cheers,
Davidm

> I wanted to remove this restriction.  I also wanted to remove the
> need for the user to provide an implementation of main() for shared
> libraries; constructors make this unnecessary.
> 
> The patch does this by adding a separate shared-library version of
> crt1.o called Scrt1.o (as for ELF shared libraries).  The entry point
> is called lib_main() to retain compatibility with the traditional build
> system.
> 
> When the new shared flat library support is enabled, both executables
> and shared libraries will use a "library"[1] registration function
> called __shared_flat_add_library().  This function will arrange for
> the library's _init, _fini, .preinit_array, etc., to be used.
> __uClibc_main() will then be passed pointers to __shared_flat_init() and
> __shared_flat_fini(), which do the actual constructing and destructing.
> 
> The traditional build system will still work because it suppresses
> the normal start and end files.  Neither crt1.o nor Scrt1.o will be used,
> and the new __shared_flat_*() routines will not be pulled in from libc.a.
> 
> To take full advantage of the new scheme, gcc needs to select Scrt1.o
> rather than crt1.o in STARTFILE_SPEC when linking shared libraries (i.e.
> when -shared-lib-id is nonzero).  gcc's csl/coldfire-4_1 branch contains
> this change, and we hope to merge it into gcc mainline during stage 1 of
> 4.3.  You can then link libraries with:
> 
>     m68k-uclinux-gcc -mid-shared-library -mshared-library-id=N \
>       -o foo ...inputs...
> 
> which is much simpler than the traditional link line.  In the meantime,
> you can use -nostartfiles and list Scrt1.o, crti.o, crtbegin.o, crtend.o
> and crtn.o manually.
> 
> Other notes:
> 
>   - We now have three ways of loading an external text symbol: absolute,
>     PC-relative and GOT-based.  We need GOT-based accesses for
>     -mid-shared-library because the symbol might be provided by a
>     dependent library.  However, PC-relative accesses are otherwise
>     better than GOT accesses because they don't involve any run-time
>     relocations.
> 
>     Rather than scatter conditional logic throughout sysdeps/linux/m68k,
>     I've added a new file -- m68k_pic.S -- that encapsulates the differences.
> 
>   - The patch adds new configuration options for building a shared libc.
>     Unfortunately, this libc will not be usable as-is, because libc.gdb
>     will export all global symbols, including those which are supposed
>     to be local to the library.
> 
>     The traditional way of dealing with this has been to run a separate
>     objcopy post-pass that uses -L to localise specific symbols by name
>     (see the page linked above for details).  However, I think a better
>     approach is to localise every hidden symbol, and objcopy now has a
>     --localize-hidden option to do just that:
> 
>       http://sources.redhat.com/ml/binutils/2006-06/msg00204.html
> 
>     This option isn't yet in any released binutils though (it'll be in 2.18).
> 
>     I'll soon submit a patch to uclinux-dev that (subject to
>     configuration options) will make ld-elf2flt use --localize-hidden
>     on shared libraries by default.  I hope this might eventually become
>     standard, so no post-processing step is necessary, either in the libc
>     makefile, or in user makefiles.
> 
>     In other words, I've written the makefile so that it will work
>     out-of-box with the patched ld-elf2flt, when configured appropriately,
>     but so that the user will need a separate post-processing step otherwise.
>     I don't know if that's acceptable.
> 
>   - The only existing mention of flat library support in uClibc mainline
>     appears to be the block at the end of Rules.mak.  However, that
>     block is conditional on CONFIG_BINFMT_SHARED_FLAT, which isn't a
>     uClibc option, and sets variables that are not used within the
>     uClibc tree itself.  I've therefore removed the block in this patch.
>     I assume it was there to help the uClinux build process, but if we go
>     with something like the patch below, it shouldn't be needed any more.
> 
> Hopefully the comments in the patch are enough to explain the rest.
> Let me know if not though (it's not easy to tell when you're so
> close to the thiing).
> 
> Tested on an M5208EVB with default options, -msep-data, and
> -mid-shared-library (using a shared libc).  Does it look OK?
> 
> Richard
> 
> [1] On uClinux, an executable is treated as shared library 0.
> 
> FWIW, here's a GNU-style changelog, in case it's useful:
> 
> 	* extra/Configs/Config.in (HAVE_SHARED_FLAT): New option.
> 	(SHARED_FLAT_ID): Likewise.
> 	* Makefile.in (install_dev): If HAVE_SHARED_FLAT, install the
> 	shared flat libraries and their aassociated .gdb files.
> 	* Makerules (libs): Depend on $(lib-gdb-y) if HAVE_SHARED_FLAT.
> 	(LINK_FLAT_CRTS): New variable.
> 	(link-flat.so): New multiline variable.
> 	(CRTS): Add S$(CRT).o for HAVE_SHARED_FLAT too.
> 	* Rules.mak: Remove old CONFIG_BINFMT_SHARED_FLAT handling.
> 	* libc/Makefile.in (lib-gdb-y): Add $(top_builddir)lib/libc.gdb.
> 	($(top_builddir)lib/libc.gdb): New rule.
> 	* libc/sysdeps/linux/m68k/m68k_pic.S: New file.
> 	* libc/sysdeps/linux/m68k/clone.S: Include m68k_pic.S.
> 	(clone): Branch to syscall_error_trampoline rather than syscall_error.
> 	(__syscall_error_trampoline): New.  Use JUMP to jump to
> 	__syscall_error.
> 	* libc/sysdeps/linux/m68k/crti.S: Include m68k_pic.S.
> 	Remove gcc-derived .file and .ident directives.
> 	(init): Remove APP and NO_APP markers.  Use INIT_GP.
> 	(fini): Likewise.
> 	* libc/sysdeps/linux/m68k/setjmp.S: Include m68k_pic.S.
> 	(__sigsetjmp): JUMP to __sigjmp_save.
> 	* libc/sysdeps/linux/m68k/crtn.S: Include m68k_pic.S.
> 	Remove gcc-derived .file and .ident directives.  Use FINI_GP.
> 	* libc/sysdeps/linux/m68k/bsd-setjmp.S: Include m68k_pic.S.
> 	(setjmp): JUMP to __sigjmp_save.
> 	* libc/sysdeps/linux/m68k/crt1.S: Include features.h and m68k_pic.S.
> 	(_start): Guard with #ifndef L_Scrt1.  Initialize the GOT for uClinux
> 	PIC.  Call __shared_flat_add_library if using shared flat libraries.
> 	If using shared flat libraries, pass __shared_flat_fini and
> 	__shared_flat_init rather than _fini and _init.  Use PEA_TEXT to
> 	push text addresses and CALL to call functions.
> 	(lib_main): New routine, selected when L_Scrt1 is defined.
> 	* libc/misc/internals/Makefile.in (libc-static-$(HAVE_SHARED_FLAT)):
> 	Add shared_flat_initfini.o and shared_flat_add_library.o.
> 	* libc/misc/internals/__uClibc_main.c: Guard init/fini array
> 	definitions with !defined (__HAVE_SHARED_FLAT__).
> 	(__uClibc_fini): Do not perform separate array finalisation
> 	if __HAVE_SHARED_FLAT__.
> 	(__uClibc_main): Likewise initialisation.
> 	* libc/misc/internals/shared_flat_initfini.c: New file.
> 	* libc/misc/internals/shared_flat_lib.h: Likewise.
> 	* libc/misc/internals/shared_flat_add_library.c: Likewise.
> 
> Signed-off-by: Richard Sandiford <richard at codesourcery.com>
> 

> Index: Makefile.in
> ===================================================================
> --- Makefile.in	(revision 15618)
> +++ Makefile.in	(working copy)
> @@ -246,6 +246,15 @@ ifeq ($(DOPIC),y)
>  	fi
>  endif
>  endif
> +ifeq ($(HAVE_SHARED_FLAT),y)
> +	for file in lib/lib*.gdb; do \
> +		if test -f $$file; then \
> +			$(INSTALL) -m 755 $$file $(PREFIX)$(DEVEL_PREFIX)lib; \
> +			$(INSTALL) -m 755 `echo $$file | sed 's/\.gdb$$//'` \
> +			  $(PREFIX)$(DEVEL_PREFIX)lib; \
> +		fi; \
> +	done
> +endif
>  
>  # Installs run-time libraries
>  install_runtime:
> Index: extra/Configs/Config.in
> ===================================================================
> --- extra/Configs/Config.in	(revision 15618)
> +++ extra/Configs/Config.in	(working copy)
> @@ -196,6 +196,30 @@ config DOPIC
>  	  If you wish to build all of uClibc as PIC objects, then answer Y here.
>  	  If you are unsure, then you should answer N.
>  
> +config HAVE_SHARED_FLAT
> +	bool "Generate a flat-format shared library"
> +	default n
> +	depends on !ARCH_USE_MMU
> +	help
> +	  Answer Y here if you are using uClinux and wish to build uClibc
> +	  as a flat-format shared library.
> +
> +config SHARED_FLAT_ID
> +	int "Shared library id"
> +	default 1
> +	depends on HAVE_SHARED_FLAT
> +	help
> +	  When using flat shared libraries, every library has a unique
> +	  system-wide identifier.  Identifier 0 is reserved for
> +	  executables and true shared libraries have identifiers
> +	  starting at 1.  The maximum shared library identifier is
> +	  determined by the kernel and is usually 3.  Shared library
> +	  N must be available on the target system as "/lib/libN.so".
> +
> +	  When a shared C library is used, it usually has identifier 1,
> +	  but you can use this option to select a different identifier
> +	  if you need to.
> +
>  config HAVE_NO_SHARED
>  	bool
>  	default n
> Index: Makerules
> ===================================================================
> --- Makerules	(revision 15618)
> +++ Makerules	(working copy)
> @@ -11,6 +11,9 @@ libs: $(lib-so-y) $(lib-a-y)
>  $(lib-so-y): $(interp)
>  else
>  .LIBPATTERNS: "lib%.a"
> +ifeq ($(HAVE_SHARED_FLAT),y)
> +libs: $(lib-gdb-y)
> +endif
>  libs: $(lib-a-y)
>  endif
>  objs: all_objs
> @@ -131,6 +134,29 @@ define link.so
>  	$(Q)$(LN) -sf $(1) $@
>  endef
>  
> +# CRT files needed by link-flat.so
> +LINK_FLAT_CRTS := $(top_builddir)lib/Scrt1.o $(top_builddir)lib/crti.o \
> +	$(top_builddir)lib/crtn.o
> +
> +# Create a shared flat library from the archive named by the first dependency.
> +# $@ names the shared library's .gdb file, not the flat file itself.
> +# (This is because the .gdb suffix makes the ELF file more distinctive
> +# than the suffixless flat file.)
> +#
> +# Argument 1 is the shared library file -- i.e. $(@:.gdb=) -- and argument 2
> +# is the shared library identifier.  If it wasn't for $(disp_ld), we could
> +# avoid passing $(@:.gdb=) as an argument and use $(@:.gdb=) instead of $(1).
> +define link-flat.so
> +	$(Q)$(INSTALL) -d $(dir $@)
> +	$(Q)$(RM) $(1) $@
> +	@$(disp_ld)
> +	$(Q)$(LD) $(LDFLAGS-$(notdir $@)) -o $(1) \
> +		-elf2flt -shared-lib-id $(2) $(top_builddir)lib/Scrt1.o \
> +		$(top_builddir)/lib/crti.o --whole-archive $(firstword $^) \
> +		--no-whole-archive $(LIBS-$(notdir $@)) $(LIBGCC) \
> +		$(top_builddir)/lib/crtn.o
> +endef
> +
>  define linkm.so
>  	$(Q)$(INSTALL) -d $(dir $@)
>  	$(Q)$(RM) $@ $@.$(2) $(dir $@)$(1)
> @@ -183,7 +209,7 @@ $(headers_dep):
>  
>  CRT := crt1
>  
> -ifeq ($(HAVE_SHARED),y)
> +ifeq ($(HAVE_SHARED)$(HAVE_SHARED_FLAT),y)
>  CRTS=$(top_builddir)lib/$(CRT).o $(top_builddir)lib/S$(CRT).o
>  else
>  CRTS=$(top_builddir)lib/$(CRT).o
> Index: Rules.mak
> ===================================================================
> --- Rules.mak	(revision 15618)
> +++ Rules.mak	(working copy)
> @@ -489,16 +489,3 @@ ifeq ($(UCLIBC_CTOR_DTOR),y)
>  SHARED_START_FILES:=$(top_builddir)lib/crti.o $(LIBGCC_DIR)crtbeginS.o
>  SHARED_END_FILES:=$(LIBGCC_DIR)crtendS.o $(top_builddir)lib/crtn.o
>  endif
> -
> -########################################
> -#
> -# uClinux shared lib support
> -#
> -
> -ifeq ($(CONFIG_BINFMT_SHARED_FLAT),y)
> -  # For the shared version of this, we specify no stack and its library ID
> -  FLTFLAGS += -s 0
> -  LIBID=1
> -  export LIBID FLTFLAGS
> -  SHARED_TARGET = lib/libc
> -endif
> Index: libc/Makefile.in
> ===================================================================
> --- libc/Makefile.in	(revision 15618)
> +++ libc/Makefile.in	(working copy)
> @@ -51,6 +51,7 @@ libc-multi-y = $(filter-out $(libc-nomul
>  endif
>  
>  lib-a-y += $(top_builddir)lib/libc.a
> +lib-gdb-y += $(top_builddir)lib/libc.gdb
>  lib-so-y += $(libc)
>  objclean-y += libc_clean
>  
> @@ -90,5 +91,8 @@ $(top_builddir)lib/libc.a: $(libc-a-y) |
>  	$(do_strip)
>  	$(do_ar)
>  
> +$(top_builddir)lib/libc.gdb: $(top_builddir)lib/libc.a $(LINK_FLAT_CRTS)
> +	$(call link-flat.so,$(@:.gdb=),$(SHARED_FLAT_ID))
> +
>  libc_clean:
>  	$(RM) $(libc_OUT)/*.{o,os,oS,a}
> Index: libc/sysdeps/linux/m68k/m68k_pic.S
> ===================================================================
> --- libc/sysdeps/linux/m68k/m68k_pic.S	(revision 0)
> +++ libc/sysdeps/linux/m68k/m68k_pic.S	(revision 0)
> @@ -0,0 +1,64 @@
> +/*
> + * Copyright (C) 2006 CodeSourcery Inc
> + *
> + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
> + *
> + * This file defines some m68k assembly macros for handling the differences
> + * between PIC and non-PIC.
> + */
> +#include <features.h>
> +
> +	/* When assembling code for shared flat libraries, this is nonzero
> +	   if %a5 points the current library's GOT.  */
> +	.equ	have_current_got, 0
> +
> +	/* Perform the equivalent of "<op> <target>", where <target> is
> +	   a text address.  <tmp> is available as a temporary address
> +	   register.  */
> +	.macro	DO_TEXT op,target,tmp
> +#if defined __HAVE_SHARED_FLAT__
> +	.ifne	have_current_got
> +	move.l \target at GOT(%a5),\tmp
> +	.else
> +	move.l _current_shared_library_a5_offset_(%a5),\tmp
> +	move.l \target at GOT(\tmp),\tmp
> +	.endif
> +	\op (\tmp)
> +#elif defined __PIC__
> +	lea \target-.-8,\tmp
> +	\op (%pc,\tmp)
> +#else
> +	\op \target
> +#endif
> +	.endm
> +
> +	/* Do "pea <target>" when <target> is a text address.
> +	   <tmp> is available as a temporary register.  */
> +	.macro PEA_TEXT target,tmp
> +	DO_TEXT pea,\target,\tmp
> +	.endm
> +
> +	/* Likewise jsr.  */
> +	.macro CALL target,tmp
> +	DO_TEXT jsr,\target,\tmp
> +	.endm
> +
> +	/* Likewise jmp.  */
> +	.macro JUMP target,tmp
> +	DO_TEXT jmp,\target,\tmp
> +	.endm
> +
> +	/* Initialize the global pointer, if functions need to do that.  */
> +	.macro INIT_GP
> +#if defined __HAVE_SHARED_FLAT__
> +	move.l	%a5,-(%sp)
> +	move.l _current_shared_library_a5_offset_(%a5),%a5
> +#endif
> +	.endm
> +
> +	/* Undo the effects of INIT_GP.  */
> +	.macro FINI_GP
> +#if defined __HAVE_SHARED_FLAT__
> +	move.l	(%sp)+,%a5
> +#endif
> +	.endm
> Index: libc/sysdeps/linux/m68k/clone.S
> ===================================================================
> --- libc/sysdeps/linux/m68k/clone.S	(revision 15618)
> +++ libc/sysdeps/linux/m68k/clone.S	(working copy)
> @@ -8,6 +8,7 @@
>  #include <features.h>
>  #include <bits/errno.h>
>  #include <sys/syscall.h>
> +#include "m68k_pic.S"
>  
>  /* int _clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
>  
> @@ -21,11 +22,11 @@ clone:
>  	movel   4(%sp), %d1             /* no NULL function pointers */
>  	movel	%d1, %a0
>  	tstl    %d1
> -	jbeq    __syscall_error
> +	beq.w	__syscall_error_trampoline
>  	movel   8(%sp), %d1             /* no NULL stack pointers */
>  	movel	%d1, %a1
>  	tstl    %d1
> -	jbeq    __syscall_error
> +	beq.w   __syscall_error_trampoline
>  
>  	/* Allocate space and copy the argument onto the new stack.  */
>  	movel   16(%sp), -(%a1)
> @@ -50,7 +51,7 @@ clone:
>  #endif
>  
>  	tstl    %d0
> -	jbmi    __syscall_error
> +	bmi.w   __syscall_error_trampoline
>  	beq.w   thread_start
>  
>  	rts
> @@ -62,3 +63,7 @@ thread_start:
>  	movel	#__NR_exit, %d0
>  	trap	#0
>  	/*jsr    exit*/
> +
> +__syscall_error_trampoline:
> +	JUMP	__syscall_error,%a0
> +
> Index: libc/sysdeps/linux/m68k/crti.S
> ===================================================================
> --- libc/sysdeps/linux/m68k/crti.S	(revision 15618)
> +++ libc/sysdeps/linux/m68k/crti.S	(working copy)
> @@ -1,27 +1,17 @@
> -	.file	"initfini.c"
> -#APP
> -	
> +#include "m68k_pic.S"
> +
>  	.section .init
> -#NO_APP
>  	.align	2
>  	.globl	_init
>  	.type	_init, @function
>  _init:
> -	link.w %a6,#0
> -#APP
> -	
> -	.align 2
> -	
> +	link.w	%a6,#0
> +	INIT_GP
>  	
>  	.section .fini
> -#NO_APP
>  	.align	2
>  	.globl	_fini
>  	.type	_fini, @function
>  _fini:
> -	link.w %a6,#0
> -#APP
> -	.align 2
> -	
> -	
> -	.ident	"GCC: (GNU) 3.3.2"
> +	link.w	%a6,#0
> +	INIT_GP
> Index: libc/sysdeps/linux/m68k/setjmp.S
> ===================================================================
> --- libc/sysdeps/linux/m68k/setjmp.S	(revision 15618)
> +++ libc/sysdeps/linux/m68k/setjmp.S	(working copy)
> @@ -5,6 +5,7 @@
>  #define _ASM
>  #define _SETJMP_H
>  #include <bits/setjmp.h>
> +#include "m68k_pic.S"
>  
>  .globl __sigsetjmp;
>  .type  __sigsetjmp, at function
> @@ -18,6 +19,5 @@ __sigsetjmp:
>  	fmovemx %fp2-%fp7, %a0@(JB_FPREGS)
>  #endif
>  	clrl	%d0
> -	lea		__sigjmp_save-.-8, %a0
> -	jmp		0(%pc, %a0)
> +	JUMP	__sigjmp_save,%a0
>  
> Index: libc/sysdeps/linux/m68k/crtn.S
> ===================================================================
> --- libc/sysdeps/linux/m68k/crtn.S	(revision 15618)
> +++ libc/sysdeps/linux/m68k/crtn.S	(working copy)
> @@ -1,26 +1,11 @@
> -	.file	"initfini.c"
> -#APP
> -	
> +#include "m68k_pic.S"
> +
>  	.section .init
> -#NO_APP
> -	.align	2
> -	.globl	_init
> -	.type	_init, @function
> -#NO_APP
> -	unlk %a6
> +	FINI_GP
> +	unlk	%a6
>  	rts
> -	.size	_init, .-_init
> -#APP
>  	
>  	.section .fini
> -#NO_APP
> -	.align	2
> -	.globl	_fini
> -	.type	_fini, @function
> -#NO_APP
> -	unlk %a6
> +	FINI_GP
> +	unlk	%a6
>  	rts
> -	.size	_fini, .-_fini
> -#APP
> -	
> -	.ident	"GCC: (GNU) 3.3.2"
> Index: libc/sysdeps/linux/m68k/bsd-setjmp.S
> ===================================================================
> --- libc/sysdeps/linux/m68k/bsd-setjmp.S	(revision 15618)
> +++ libc/sysdeps/linux/m68k/bsd-setjmp.S	(working copy)
> @@ -5,6 +5,7 @@
>  #define _ASM
>  #define _SETJMP_H
>  #include <bits/setjmp.h>
> +#include "m68k_pic.S"
>  
>  .globl setjmp;
>  .type  setjmp, at function
> @@ -18,6 +19,5 @@ setjmp:
>  	fmovemx %fp2-%fp7, %a0@(JB_FPREGS)
>  #endif
>  	clrl	%d0
> -	lea		__sigjmp_save-.-8, %a0
> -	jmp		0(%pc, %a0)
> +	JUMP	__sigjmp_save,%a0
>  
> Index: libc/sysdeps/linux/m68k/crt1.S
> ===================================================================
> --- libc/sysdeps/linux/m68k/crt1.S	(revision 15618)
> +++ libc/sysdeps/linux/m68k/crt1.S	(working copy)
> @@ -34,6 +34,10 @@
>     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
>     02111-1307 USA.  */
>  
> +#include <features.h>
> +#include "m68k_pic.S"
> +
> +#ifndef L_Scrt1
>  /* This is the canonical entry point, usually the first thing in the text
>     segment.  The SVR4/m68k ABI says that when the entry point runs,
>     most registers' values are unspecified, except for:
> @@ -60,8 +64,6 @@
>  		8(%sp)			envp
>  */
>  
> -#include <features.h>
> -
>  	.text
>  	.type	_init,%function
>  	.type	_fini,%function
> @@ -76,6 +78,17 @@ _start:
>  	   the outermost frame obviously.  */
>  	sub.l %fp, %fp
>  
> +#if !defined __ARCH_USE_MMU__ && defined __PIC__
> +	/* Set up the global pointer.  The GOT is at the beginning of the
> +	   data segment, whose address is in %d5.  */
> +	move.l %d5,%a5
> +	.equ have_current_got, 1
> +#endif
> +	
> +#ifdef __HAVE_SHARED_FLAT__
> +	CALL __shared_flat_add_library,%a1
> +#endif
> +
>  	/* Extract the arguments as encoded on the stack and set up the
>  	   arguments for `main': argc, argv.  envp will be determined
>  	   later in __libc_start_main.  */
> @@ -100,19 +113,35 @@ _start:
>  
>  	/* Push the address of our own entry points to `.fini' and
>  	   `.init'.  */
> -	pea _fini
> -	pea _init
> +#if defined __HAVE_SHARED_FLAT__
> +	PEA_TEXT __shared_flat_fini,%a1
> +	PEA_TEXT __shared_flat_init,%a1
> +#else
> +	PEA_TEXT _fini,%a1
> +	PEA_TEXT _init,%a1
> +#endif
>  
>  	pea (%a0)		/* Push second argument: argv.  */
>  	move.l %d0, -(%sp)	/* Push first argument: argc.  */
>  
> -	pea main
> +	PEA_TEXT main,%a1
>  
>  	/* Call the user's main function, and exit with its value.  But
>  	   let the libc call main.  */
> -	jbsr __uClibc_main
> +	CALL __uClibc_main,%a1
>  
>  	illegal			/* Crash if somehow `exit' does return.  */
> +#else
> +	.text
> +	.globl lib_main
> +	.hidden lib_main
> +	.type lib_main, at function
> +lib_main:
> +	move.l %d5,%a5
> +	JUMP __shared_flat_add_library,%a0
> +
> +	.hidden _current_shared_library_a5_offset_
> +#endif
>  
>  /* Define a symbol for the first piece of initialized data.  */
>  	.data
> Index: libc/misc/internals/Makefile.in
> ===================================================================
> --- libc/misc/internals/Makefile.in	(revision 15618)
> +++ libc/misc/internals/Makefile.in	(working copy)
> @@ -19,7 +19,9 @@ MISC_INTERNALS_OBJ := $(patsubst %.c,$(M
>  libc-y += $(MISC_INTERNALS_OBJ)
>  libc-shared-y += $(MISC_INTERNALS_OUT)/__uClibc_main.oS
>  libc-static-y += $(MISC_INTERNALS_OUT)/__uClibc_main.o
> -
> +libc-static-$(HAVE_SHARED_FLAT) += \
> +  $(MISC_INTERNALS_OUT)/shared_flat_initfini.o \
> +  $(MISC_INTERNALS_OUT)/shared_flat_add_library.o
>  libc-nomulti-y += $(MISC_INTERNALS_OUT)/__uClibc_main.o
>  
>  objclean-y += misc_internals_objclean
> Index: libc/misc/internals/__uClibc_main.c
> ===================================================================
> --- libc/misc/internals/__uClibc_main.c	(revision 15618)
> +++ libc/misc/internals/__uClibc_main.c	(working copy)
> @@ -88,7 +88,9 @@ extern void weak_function _locale_init(v
>  extern void weak_function __pthread_initialize_minimal(void);
>  #endif
>  
> -#ifdef __UCLIBC_CTOR_DTOR__
> +/* If __HAVE_SHARED_FLAT__, all array initialisation and finalisation
> +   is handled by the routines passed to __uClibc_main().  */
> +#if defined (__UCLIBC_CTOR_DTOR__) && !defined (__HAVE_SHARED_FLAT__)
>  extern void _dl_app_init_array(void);
>  extern void _dl_app_fini_array(void);
>  # ifndef SHARED
> @@ -247,9 +249,11 @@ libc_hidden_proto(__uClibc_fini)
>  void __uClibc_fini(void)
>  {
>  #ifdef __UCLIBC_CTOR_DTOR__
> +  /* If __HAVE_SHARED_FLAT__, all array finalisation is handled
> +     by __app_fini.  */
>  # ifdef SHARED
>      _dl_app_fini_array();
> -# else
> +# elif !defined (__HAVE_SHARED_FLAT__)
>      size_t i = __fini_array_end - __fini_array_start;
>      while (i-- > 0)
>  	(*__fini_array_start [i]) ();
> @@ -347,7 +351,9 @@ void __uClibc_main(int (*main)(int, char
>      /* Arrange for the application's dtors to run before we exit.  */
>      __app_fini = app_fini;
>  
> -# ifndef SHARED
> +    /* If __HAVE_SHARED_FLAT__, all array initialisation is handled
> +       by __app_init.  */
> +# if !defined (SHARED) && !defined (__HAVE_SHARED_FLAT__)
>      /* For dynamically linked executables the preinit array is executed by
>         the dynamic linker (before initializing any shared object).
>         For static executables, preinit happens rights before init.  */
> @@ -362,9 +368,11 @@ void __uClibc_main(int (*main)(int, char
>      if (app_init!=NULL) {
>  	app_init();
>      }
> +    /* If __HAVE_SHARED_FLAT__, all array initialisation is handled
> +       by __app_init.  */
>  # ifdef SHARED
>      _dl_app_init_array();
> -# else
> +# elif !defined (__HAVE_SHARED_FLAT__)
>      {
>  	const size_t size = __init_array_end - __init_array_start;
>  	size_t i;
> Index: libc/misc/internals/shared_flat_initfini.c
> ===================================================================
> --- libc/misc/internals/shared_flat_initfini.c	(revision 0)
> +++ libc/misc/internals/shared_flat_initfini.c	(revision 0)
> @@ -0,0 +1,55 @@
> +/*
> + * Copyright (C) 2006 CodeSourcery Inc
> + *
> + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
> + *
> + * This file defines the main initialisation and finalisation code for
> + * shared flat libraries.  It in turn calls the initialisation and
> + * finalisation code for each registered library.
> + */
> +#include "shared_flat_lib.h"
> +
> +/* A doubly-linked list of shared libraries.  Those nearer the head
> +   of the list should be initialised first and finalised last.  */
> +struct shared_flat_lib *__first_shared_lib;
> +struct shared_flat_lib *__last_shared_lib;
> +
> +void
> +__shared_flat_init (void)
> +{
> +    struct shared_flat_lib *lib;
> +    void (**start) (void);
> +    void (**end) (void);
> +
> +    for (lib = __first_shared_lib; lib; lib = lib->next) {
> +	end = lib->preinit_array_end;
> +	for (start = lib->preinit_array_start; start < end; start++)
> +	    (*start)();
> +    }
> +
> +    for (lib = __first_shared_lib; lib; lib = lib->next) {
> +	if (lib->init)
> +	    lib->init();
> +
> +	end = lib->init_array_end;
> +	for (start = lib->init_array_start; start < end; start++)
> +	    (*start)();
> +    }
> +}
> +
> +void
> +__shared_flat_fini (void)
> +{
> +    struct shared_flat_lib *lib;
> +    void (**start) (void);
> +    void (**end) (void);
> +
> +    for (lib = __last_shared_lib; lib; lib = lib->prev) {
> +	start = lib->fini_array_start;
> +	for (end = lib->fini_array_end; end > start;)
> +	    (*--end)();
> +
> +	if (lib->fini)
> +	    lib->fini();
> +    }
> +}
> Index: libc/misc/internals/shared_flat_lib.h
> ===================================================================
> --- libc/misc/internals/shared_flat_lib.h	(revision 0)
> +++ libc/misc/internals/shared_flat_lib.h	(revision 0)
> @@ -0,0 +1,34 @@
> +/*
> + * Copyright (C) 2006 CodeSourcery Inc
> + *
> + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
> + *
> + * This file defines the shared_flat_lib structure and the global library
> + * list.   The structure is used to provide something close to ELF-like
> + * initialisation and finalisation when using shared flat libraries.
> + */
> +#ifndef __SHARED_FLAT_LIB__
> +#define __SHARED_FLAT_LIB__
> +
> +struct shared_flat_lib {
> +  struct shared_flat_lib *prev;
> +  struct shared_flat_lib *next;
> +  /* .preinit_array is usually only supported for executables.  However,
> +     the distinction between the executable and its shared libraries isn't
> +     as pronounced for flat files; a shared library is really just a part
> +     of an executable that can be shared with other executables.  We therefore
> +     allow .preinit_array to be used in libraries too.  */
> +  void (**preinit_array_start) (void);
> +  void (**preinit_array_end) (void);
> +  void (**init_array_start) (void);
> +  void (**init_array_end) (void);
> +  void (**fini_array_start) (void);
> +  void (**fini_array_end) (void);
> +  void (*init) (void);
> +  void (*fini) (void);
> +};
> +
> +extern struct shared_flat_lib *__first_shared_lib;
> +extern struct shared_flat_lib *__last_shared_lib;
> +
> +#endif
> Index: libc/misc/internals/shared_flat_add_library.c
> ===================================================================
> --- libc/misc/internals/shared_flat_add_library.c	(revision 0)
> +++ libc/misc/internals/shared_flat_add_library.c	(revision 0)
> @@ -0,0 +1,47 @@
> +/*
> + * Copyright (C) 2006 CodeSourcery Inc
> + *
> + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
> + *
> + * This file defines __shared_flat_add_library.  If a library has
> + * initialistion and finalisation code, it should use this routine
> + * to register itself.
> + */
> +#include "shared_flat_lib.h"
> +
> +/* The initialisation and finalisation symbols for this library.  */
> +extern void _init (void) attribute_hidden weak_function;
> +extern void _fini (void) attribute_hidden weak_function;
> +extern void (*__preinit_array_start []) (void) attribute_hidden;
> +extern void (*__preinit_array_end []) (void) attribute_hidden;
> +extern void (*__init_array_start []) (void) attribute_hidden;
> +extern void (*__init_array_end []) (void) attribute_hidden;
> +extern void (*__fini_array_start []) (void) attribute_hidden;
> +extern void (*__fini_array_end []) (void) attribute_hidden;
> +
> +/* The shared_flat_lib structure that describes this library.  */
> +static struct shared_flat_lib this_lib = {
> +  0,
> +  0,
> +  __preinit_array_start,
> +  __preinit_array_end,
> +  __init_array_start,
> +  __init_array_end,
> +  __fini_array_start,
> +  __fini_array_end,
> +  _init,
> +  _fini
> +};
> +
> +/* Add this_lib to the end of the global list. */
> +void __shared_flat_add_library (void) attribute_hidden;
> +void
> +__shared_flat_add_library (void)
> +{
> +  this_lib.prev = __last_shared_lib;
> +  if (this_lib.prev)
> +    this_lib.prev->next = &this_lib;
> +  else
> +    __first_shared_lib = &this_lib;
> +  __last_shared_lib = &this_lib;
> +}

> _______________________________________________
> uClibc mailing list
> uClibc at uclibc.org
> http://busybox.net/cgi-bin/mailman/listinfo/uclibc

-- 
David McCullough,  david_mccullough at securecomputing.com,   Ph:+61 734352815
Secure Computing - SnapGear  http://www.uCdot.org http://www.cyberguard.com



More information about the uClibc mailing list