Hi,

The attached, slightly tested patch adds handling of -Wl,--whole-archive
(and -Wl,--no-whole-archive).

commit 6eefe55e4b7993a1d573e7d4db6def85f418f824
Author: Bernhard Reutner-Fischer <rep.dot....@gmail.com>
Date:   Wed Sep 2 15:55:48 2009 +0200

    Handle --whole-archive
    
      Support and document -Wl,--{no-,}whole-archive.
    
      Also move the bounds-checking code to a bcheck.a to avoid undefined
      references to __bound_new_region() (when using a libtcc1_s.so instead
      of libtcc1.a) on i386.
    
    Signed-off-by: aldot <rep.dot....@gmail.com>

diff --git a/Makefile b/Makefile
index 01c3e27..6387246 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,7 @@ include $(TOP)/config.mak
 CFLAGS+=-g -Wall
 CFLAGS_P=$(CFLAGS) -pg -static -DCONFIG_TCC_STATIC
 LIBS_P=
+CFLAGS_PIC ?= -fPIC
 
 ifneq ($(GCC_MAJOR),2)
 CFLAGS+=-fno-strict-aliasing
@@ -32,19 +33,22 @@ LIBS+=-ldl
 endif
 endif
 
+BCHECK=
+BCHECK_O=
+ALLOCA_O=
+
 ifeq ($(ARCH),i386)
 NATIVE_TARGET=-DTCC_TARGET_I386
 LIBTCC1=libtcc1.a
-BCHECK_O=bcheck.o
-ALLOCA_O=alloca86.o alloca86-bt.o
-else
+ALLOCA_O=alloca86.o
+BCHECK_O=bcheck.o alloca86-bt.o
+BCHECK=bcheck.a
+endif
 ifeq ($(ARCH),x86-64)
 NATIVE_TARGET=-DTCC_TARGET_X86_64
 LIBTCC1=libtcc1.a
-BCHECK_O=
 ALLOCA_O=alloca86_64.o
 endif
-endif
 
 ifeq ($(ARCH),arm)
 NATIVE_TARGET=-DTCC_TARGET_ARM
@@ -54,12 +58,10 @@ endif
 
 ifdef CONFIG_WIN32
 NATIVE_TARGET+=-DTCC_TARGET_PE
-BCHECK_O=
 endif
 
 ifneq ($(wildcard /lib/ld-uClibc.so.0),)
 NATIVE_TARGET+=-DTCC_UCLIBC
-BCHECK_O=
 endif
 
 ifdef CONFIG_USE_LIBGCC
@@ -111,7 +113,7 @@ ifdef CONFIG_CROSS
 PROGS+=$(PROGS_CROSS)
 endif
 
-all: $(PROGS) $(LIBTCC1) $(BCHECK_O) libtcc.a tcc-doc.html tcc.1 
libtcc_test$(EXESUF)
+all: $(PROGS) $(LIBTCC1) $(BCHECK) libtcc.a tcc-doc.html tcc.1 
libtcc_test$(EXESUF)
 
 # Host Tiny C Compiler
 tcc$(EXESUF): $(NATIVE_FILES)
@@ -191,12 +193,15 @@ libtcc1.a: $(LIBTCC1_OBJS)
 bcheck.o: bcheck.c
        $(CC) -o $@ -c $< -O2 -Wall
 
+bcheck.a: $(BCHECK_O)
+       $(AR) rcs $@ $^
+
 # install
 TCC_INCLUDES = stdarg.h stddef.h stdbool.h float.h varargs.h tcclib.h
 INSTALL=install
 
 ifndef CONFIG_WIN32
-install: $(PROGS) $(LIBTCC1) $(BCHECK_O) libtcc.a tcc.1 tcc-doc.html
+install: $(PROGS) $(LIBTCC1) $(BCHECK) libtcc.a tcc.1 tcc-doc.html
        mkdir -p "$(bindir)"
        $(INSTALL) -s -m755 $(PROGS) "$(bindir)"
        mkdir -p "$(mandir)/man1"
@@ -206,8 +211,8 @@ install: $(PROGS) $(LIBTCC1) $(BCHECK_O) libtcc.a tcc.1 
tcc-doc.html
 ifneq ($(LIBTCC1),)
        $(INSTALL) -m644 $(LIBTCC1) "$(tccdir)"
 endif
-ifneq ($(BCHECK_O),)
-       $(INSTALL) -m644 $(BCHECK_O) "$(tccdir)"
+ifneq ($(BCHECK),)
+       $(INSTALL) -m644 $(BCHECK) "$(tccdir)"
 endif
        $(INSTALL) -m644 $(addprefix include/,$(TCC_INCLUDES)) 
"$(tccdir)/include"
        mkdir -p "$(docdir)"
@@ -219,7 +224,7 @@ endif
 
 uninstall:
        rm -fv $(foreach P,$(PROGS),"$(bindir)/$P")
-       rm -fv $(foreach P,$(LIBTCC1) $(BCHECK_O),"$(tccdir)/$P")
+       rm -fv $(foreach P,$(LIBTCC1) $(BCHECK),"$(tccdir)/$P")
        rm -fv $(foreach P,$(TCC_INCLUDES),"$(tccdir)/include/$P")
        rm -fv "$(docdir)/tcc-doc.html" "$(mandir)/man1/tcc.1"
        rm -fv "$(libdir)/libtcc.a" "$(includedir)/libtcc.h"
diff --git a/libtcc.c b/libtcc.c
index c25fb2c..e04db5e 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -206,6 +206,7 @@ static int tcc_add_dll(TCCState *s, const char *filename, 
int flags);
 #define AFF_PRINT_ERROR     0x0001 /* print error if file not found */
 #define AFF_REFERENCED_DLL  0x0002 /* load a referenced dll from another dll */
 #define AFF_PREPROCESS      0x0004 /* preprocess file */
+#define AFF_WHOLE_ARCHIVE   0x0008 /* add whole archive not just undef symbol 
*/
 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
 
 /* tcccoff.c */
@@ -2082,7 +2083,7 @@ static int tcc_add_file_internal(TCCState *s1, const char 
*filename, int flags)
 
     if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
         file->line_num = 0; /* do not display line number if error */
-        ret = tcc_load_archive(s1, fd);
+        ret = tcc_load_archive(s1, fd, flags & AFF_WHOLE_ARCHIVE);
         goto the_end;
     }
 
@@ -2099,9 +2100,11 @@ static int tcc_add_file_internal(TCCState *s1, const 
char *filename, int flags)
     /* as GNU ld, consider it is an ld script if not recognized */
     ret = tcc_load_ldscript(s1);
 #endif
+/* TODO: the_end label should be here !! */
     if (ret < 0)
-        error_noabort("unrecognized file type");
-
+        error_noabort("%s: unrecognized file type", filename);
+    else if (s1->verbose)
+        printf("+> %s\n", filename);
 the_end:
     if (file)
         tcc_close(file);
diff --git a/tcc-doc.texi b/tcc-doc.texi
index 7cc61bb..3bb640c 100644
--- a/tcc-doc.texi
+++ b/tcc-doc.texi
@@ -295,6 +295,14 @@ also be given).
 @item -Wl,-Ttext,address
 Set the start of the .text section to @var{address}.
 
+...@item -Wl,--whole-archive
+Add a whole archive, not just the symbols of the archive that would
+satisfy undefined symbols in the program.
+
+...@item -Wl,--no-whole-archive
+Turn off the effect of the --whole-archive option for subsequent archive
+files.
+
 @item -Wl,--oformat,fmt
 Use @var{fmt} as output format. The supported output formats are:
 @table @code
diff --git a/tcc.c b/tcc.c
index 501dc01..d8138a0 100644
--- a/tcc.c
+++ b/tcc.c
@@ -54,6 +54,8 @@ void help(void)
            "  -static     static linking\n"
            "  -rdynamic   export all global symbols to dynamic linker\n"
            "  -r          generate (relocatable) object file\n"
+           "  --whole-archive    include all object files in the archives\n"
+           "  --no-whole-archive turn the effect of --whole-archives off\n"
            "Debugger options:\n"
            "  -g          generate runtime debug info\n"
 #ifdef CONFIG_TCC_BCHECK
@@ -66,13 +68,15 @@ void help(void)
 }
 
 static char **files;
-static int nb_files, nb_libraries;
+static char **whole_archives;
+static int nb_files, nb_libraries, nb_whole_archive;
 static int multiple_files;
 static int print_search_dirs;
 static int output_type;
 static int reloc_output;
 static const char *outfile;
 static int do_bench = 0;
+static unsigned do_whole_archive = 0;
 
 #define TCC_OPTION_HAS_ARG 0x0001
 #define TCC_OPTION_NOSEP   0x0002 /* cannot have space before option and arg */
@@ -227,6 +231,7 @@ int parse_args(TCCState *s, int argc, char **argv)
         if (r[0] != '-' || r[1] == '\0') {
             /* add a new file */
             dynarray_add((void ***)&files, &nb_files, r);
+            dynarray_add((void ***)&whole_archives, &nb_whole_archive, 
(void*)do_whole_archive);
             if (!multiple_files) {
                 optind--;
                 /* argv[0] will be this file */
@@ -297,6 +302,7 @@ int parse_args(TCCState *s, int argc, char **argv)
                 break;
             case TCC_OPTION_l:
                 dynarray_add((void ***)&files, &nb_files, r);
+                dynarray_add((void ***)&whole_archives, &nb_whole_archive, 
(void*)do_whole_archive);
                 nb_libraries++;
                 break;
             case TCC_OPTION_bench:
@@ -400,6 +406,10 @@ int parse_args(TCCState *s, int argc, char **argv)
                         {
                             error("target %s not found", p);
                         }
+                    } else if (strstart(optarg, "--whole-archive", &p)) {
+                        do_whole_archive = 1;
+                    } else if (strstart(optarg, "--no-whole-archive", &p)) {
+                        do_whole_archive = 0;
                     } else {
                         error("unsupported linker option '%s'", optarg);
                     }
@@ -436,8 +446,10 @@ int main(int argc, char **argv)
     outfile = NULL;
     multiple_files = 1;
     files = NULL;
+    whole_archives = NULL;
     nb_files = 0;
     nb_libraries = 0;
+    nb_whole_archive = 0;
     reloc_output = 0;
     print_search_dirs = 0;
     ret = 0;
@@ -521,9 +533,10 @@ int main(int argc, char **argv)
                 ret = 1;
             }
         } else {
+            int whole = ((int)whole_archives[i]) << 3; /* AFF_WHOLE_ARCHIVE */
             if (1 == s->verbose)
-                printf("-> %s\n", filename);
-            if (tcc_add_file(s, filename) < 0)
+                printf("-%c %s\n", whole?'[':'>', filename);
+            if (tcc_add_file_internal(s, filename, whole) < 0)
                 ret = 1;
         }
     }
diff --git a/tccelf.c b/tccelf.c
index b55d55a..45ade9e 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -1188,8 +1188,8 @@ static void tcc_add_runtime(TCCState *s1)
                     ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
                     bounds_section->sh_num, "__bounds_start");
         /* add bound check code */
-        snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
-        tcc_add_file(s1, buf);
+        snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.a");
+        tcc_add_file_internal(s1, buf, AFF_WHOLE_ARCHIVE | AFF_PRINT_ERROR);
 #ifdef TCC_TARGET_I386
         if (s1->output_type != TCC_OUTPUT_MEMORY) {
             /* add 'call __bound_init()' in .init section */
@@ -2329,7 +2329,7 @@ static int get_be32(const uint8_t *b)
 }
 
 /* load only the objects which resolve undefined symbols */
-static int tcc_load_alacarte(TCCState *s1, int fd, int size)
+static int tcc_load_alacarte(TCCState *s1, int fd, int size, int whole_archive)
 {
     int i, bound, nsyms, sym_index, off, ret;
     uint8_t *data;
@@ -2351,6 +2351,7 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int 
size)
             if(sym_index) {
                 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
                 if(sym->st_shndx == SHN_UNDEF) {
+ load_obj:
                     off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
 #if 0
                     printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
@@ -2363,6 +2364,8 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int 
size)
                         goto the_end;
                     }
                 }
+            } else if (whole_archive) {
+                goto load_obj;
             }
         }
     } while(bound);
@@ -2373,7 +2376,7 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int 
size)
 }
 
 /* load a '.a' file */
-static int tcc_load_archive(TCCState *s1, int fd)
+static int tcc_load_archive(TCCState *s1, int fd, int whole_archive)
 {
     ArchiveHeader hdr;
     char ar_size[11];
@@ -2409,7 +2412,7 @@ static int tcc_load_archive(TCCState *s1, int fd)
         if (!strcmp(ar_name, "/")) {
             /* coff symbol table : we handle it */
             if(s1->alacarte_link)
-                return tcc_load_alacarte(s1, fd, size);
+                return tcc_load_alacarte(s1, fd, size, whole_archive);
         } else if (!strcmp(ar_name, "//") ||
                    !strcmp(ar_name, "__.SYMDEF") ||
                    !strcmp(ar_name, "__.SYMDEF/") ||
_______________________________________________
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to