changeset 287:462860741295

[project @ 2003-10-04 14:45:23 by bellard] .gnu.linkonce section support (useful to link with recent glibc)
author bellard
date Sat, 04 Oct 2003 14:45:23 +0000
parents 141f2a86d4a8
children e8abebbf04bd
files tccelf.c
diffstat 1 files changed, 28 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/tccelf.c	Sat Oct 04 14:41:18 2003 +0000
+++ b/tccelf.c	Sat Oct 04 14:45:23 2003 +0000
@@ -1508,7 +1508,8 @@
 typedef struct SectionMergeInfo {
     Section *s;            /* corresponding existing section */
     unsigned long offset;  /* offset of the new section in the existing section */
-    int new_section;       /* true if section 's' was added */
+    uint8_t new_section;       /* true if section 's' was added */
+    uint8_t link_once;         /* true if link once section */
 } SectionMergeInfo;
 
 /* load an object file and merge it with current files */
@@ -1595,8 +1596,19 @@
         /* find corresponding section, if any */
         for(j = 1; j < s1->nb_sections;j++) {
             s = s1->sections[j];
-            if (!strcmp(s->name, sh_name))
-                goto found;
+            if (!strcmp(s->name, sh_name)) {
+                if (!strncmp(sh_name, ".gnu.linkonce", 
+                             sizeof(".gnu.linkonce") - 1)) {
+                    /* if a 'linkonce' section is already present, we
+                       do not add it again. It is a little tricky as
+                       symbols can still be defined in
+                       it. */
+                    sm_table[i].link_once = 1;
+                    goto next;
+                } else {
+                    goto found;
+                }
+            }
         }
         /* not found: create new section */
         s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
@@ -1630,6 +1642,7 @@
         } else {
             s->data_offset += size;
         }
+    next: ;
     }
 
     /* second short pass to update sh_link and sh_info fields of new
@@ -1657,6 +1670,18 @@
         if (sym->st_shndx != SHN_UNDEF &&
             sym->st_shndx < SHN_LORESERVE) {
             sm = &sm_table[sym->st_shndx];
+            if (sm->link_once) {
+                /* if a symbol is in a link once section, we use the
+                   already defined symbol. It is very important to get
+                   correct relocations */
+                if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
+                    name = strtab + sym->st_name;
+                    sym_index = find_elf_sym(symtab_section, name);
+                    if (sym_index)
+                        old_to_new_syms[i] = sym_index;
+                }
+                continue;
+            }
             /* if no corresponding section added, no need to add symbol */
             if (!sm->s)
                 continue;