[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