changeset 259:1835379353e4

[project @ 2003-04-28 22:06:38 by bellard] alacarte linking (Dave Long)
author bellard
date Mon, 28 Apr 2003 22:07:35 +0000
parents 23d6a8deb2d6
children 02017672f663
files tcc.c tccelf.c
diffstat 2 files changed, 63 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/tcc.c	Mon Apr 28 21:23:53 2003 +0000
+++ b/tcc.c	Mon Apr 28 22:07:35 2003 +0000
@@ -398,6 +398,9 @@
     /* if true, static linking is performed */
     int static_link;
 
+    /* if true, only link in referenced objects from archive */
+    int alacarte_link;
+
     /* warning switches */
     int warn_write_strings;
     int warn_unsupported;
@@ -9207,6 +9210,7 @@
     s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
                                       ".dynstrtab", 
                                       ".dynhashtab", SHF_PRIVATE);
+    s->alacarte_link = 1;
     return s;
 }
 
--- a/tccelf.c	Mon Apr 28 21:23:53 2003 +0000
+++ b/tccelf.c	Mon Apr 28 22:07:35 2003 +0000
@@ -1682,6 +1682,55 @@
     char ar_fmag[2];		/* should contain ARFMAG */
 } ArchiveHeader;
 
+static int get_be32(const uint8_t *b)
+{
+    return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
+}
+
+/* load only the objects which resolve undefined symbols */
+static int tcc_load_alacarte(TCCState *s1, int fd, int size)
+{
+    int i, bound, nsyms, sym_index, off, ret;
+    uint8_t *data;
+    const char *ar_names, *p;
+    const uint8_t *ar_index;
+    Elf32_Sym *sym;
+
+    data = tcc_malloc(size);
+    if (read(fd, data, size) != size)
+        goto fail;
+    nsyms = get_be32(data);
+    ar_index = data + 4;
+    ar_names = ar_index + nsyms * 4;
+
+    do {
+	bound = 0;
+	for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
+	    sym_index = find_elf_sym(symtab_section, p);
+	    if(sym_index) {
+		sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
+		if(sym->st_shndx == SHN_UNDEF) {
+		    off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
+#if 0
+		    printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
+#endif
+		    ++bound;
+		    lseek(fd, off, SEEK_SET);
+		    if(tcc_load_object_file(s1, fd, off) < 0) {
+                    fail:
+                        ret = -1;
+                        goto the_end;
+                    }
+		}
+	    }
+	}
+    } while(bound);
+    ret = 0;
+ the_end:
+    tcc_free(data);
+    return ret;
+}
+
 /* load a '.a' file */
 static int tcc_load_archive(TCCState *s1, int fd)
 {
@@ -1714,18 +1763,21 @@
         ar_name[i + 1] = '\0';
         //        printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
         file_offset = lseek(fd, 0, SEEK_CUR);
-        if (!strcmp(ar_name, "/") ||
-            !strcmp(ar_name, "//") ||
-            !strcmp(ar_name, "__.SYMDEF") ||
-            !strcmp(ar_name, "__.SYMDEF/") ||
-            !strcmp(ar_name, "ARFILENAMES/")) {
+        /* align to even */
+        size = (size + 1) & ~1;
+        if (!strcmp(ar_name, "/")) {
+            /* coff symbol table : we handle it */
+	    if(s1->alacarte_link)
+		return tcc_load_alacarte(s1, fd, size);
+        } else if (!strcmp(ar_name, "//") ||
+                   !strcmp(ar_name, "__.SYMDEF") ||
+                   !strcmp(ar_name, "__.SYMDEF/") ||
+                   !strcmp(ar_name, "ARFILENAMES/")) {
             /* skip symbol table or archive names */
         } else {
             if (tcc_load_object_file(s1, fd, file_offset) < 0)
                 return -1;
         }
-        /* align to even */
-        size = (size + 1) & ~1;
         lseek(fd, file_offset + size, SEEK_SET);
     }
     return 0;