1. Summary
  2. Files
  3. Support
  4. Report Spam
  5. Create account
  6. Log in

Changeset 2486

Show
Ignore:
Timestamp:
04/07/12 19:12:22 (2 years ago)
Author:
kaiwang27
Message:

Add support for common symbols.

Location:
trunk/ld
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • trunk/ld/ld.h

    r2478 r2486  
    9191        struct ld_symbol *ld_symtab_def;/* hash for defined symbols */ 
    9292        struct ld_symbol *ld_symtab_undef; /* hash for undefined symbols */ 
     93        struct ld_symbol *ld_symtab_common; /* hash for common symbols */ 
    9394        struct ld_symbol_table *ld_symtab; /* .symtab symbol table */ 
    9495        struct ld_strtab *ld_strtab;    /* .strtab string table */ 
  • trunk/ld/ld_input.c

    r2482 r2486  
    174174{ 
    175175        struct ld_input_section *is; 
     176        struct ld_symbol *lsb, *tmp; 
    176177        Elf *e; 
    177178        Elf_Scn *scn; 
     
    187188                    elf_errmsg(-1)); 
    188189 
     190        /* Allocate one more pseudo section to hold common symbols */ 
     191        li->li_shnum++; 
     192 
    189193        assert(li->li_is == NULL); 
    190194        if ((li->li_is = calloc(li->li_shnum, sizeof(*is))) == NULL) 
     
    210214                            elf_errmsg(-1)); 
    211215 
    212                 if (ndx >= li->li_shnum) 
     216                if (ndx >= li->li_shnum - 1) 
    213217                        ld_fatal(ld, "%s: section index of '%s' section is" 
    214218                            " invalid", li->li_name, name); 
     
    247251                    elf_errmsg(elferr)); 
    248252 
     253        /* 
     254         * Create a pseudo section named COMMON to keep track of common symbols. 
     255         * Go through the common symbols hash table, if there are common symbols 
     256         * belonging to this input object, increase the size of the pseudo COMMON 
     257         * section accordingly. 
     258         */ 
     259 
     260        is = &li->li_is[li->li_shnum - 1]; 
     261        if ((is->is_name = strdup("COMMON")) == NULL) 
     262                ld_fatal_std(ld, "%s: calloc", li->li_name); 
     263        is->is_off = 0; 
     264        is->is_size = 0; 
     265        is->is_entsize = 1; 
     266        is->is_align = 1; 
     267        is->is_type = SHT_NOBITS; 
     268        is->is_flags = SHF_ALLOC | SHF_WRITE; 
     269        is->is_link = 0; 
     270        is->is_info = 0; 
     271        is->is_index = SHN_COMMON; 
     272        is->is_input = li; 
     273        is->is_orphan = 1; 
     274        HASH_ITER(hh, ld->ld_symtab_common, lsb, tmp) { 
     275                if (lsb->lsb_input != li) 
     276                        continue; 
     277#if 0 
     278                printf("add common symbol %s to %s\n", lsb->lsb_name, 
     279                    li->li_name); 
     280#endif 
     281                if (lsb->lsb_size > is->is_align) 
     282                        is->is_align = lsb->lsb_size; 
     283                lsb->lsb_value = is->is_size; 
     284                is->is_size += lsb->lsb_size; 
     285        } 
     286 
    249287        ld_input_unload(ld, li); 
    250288} 
  • trunk/ld/ld_script.c

    r2470 r2486  
    106106                ls->ls_loc_counter = (uint64_t) ldv->ldv_val; 
    107107        } 
    108         printf("%s = %#jx\n", var->le_name, (uint64_t) ldv->ldv_val); 
    109108} 
    110109 
  • trunk/ld/ld_symbols.c

    r2481 r2486  
    116116#define _symbol_add(tbl, s) \ 
    117117        HASH_ADD_KEYPTR(hh, (tbl), (s)->lsb_name, strlen((s)->lsb_name), (s)) 
    118 #define _symbol_remove(tbl, s) HASH_DEL((tbl), (s)); 
     118#define _symbol_remove(tbl, s) HASH_DEL((tbl), (s)) 
    119119 
    120120static void 
     
    126126        name = lsb->lsb_name; 
    127127        if (lsb->lsb_shndx == SHN_UNDEF) { 
     128                if (_symbol_find(ld->ld_symtab_def, name) != NULL || 
     129                    _symbol_find(ld->ld_symtab_undef, name) != NULL || 
     130                    _symbol_find(ld->ld_symtab_common, name) != NULL) 
     131                        return; 
     132                _symbol_add(ld->ld_symtab_undef, lsb); 
     133        } else if (lsb->lsb_shndx == SHN_COMMON) { 
    128134                if (_symbol_find(ld->ld_symtab_def, name) != NULL) 
    129135                        return; 
    130                 if (_symbol_find(ld->ld_symtab_undef, name) != NULL) 
    131                         return; 
    132                 _symbol_add(ld->ld_symtab_undef, lsb); 
     136                if ((_lsb = _symbol_find(ld->ld_symtab_undef, name)) != NULL) 
     137                        _symbol_remove(ld->ld_symtab_undef, _lsb); 
     138                if ((_lsb = _symbol_find(ld->ld_symtab_common, name)) != NULL) { 
     139                        if (lsb->lsb_size > _lsb->lsb_size) 
     140                                _symbol_remove(ld->ld_symtab_common, _lsb); 
     141                        else 
     142                                return; 
     143                } 
     144                _symbol_add(ld->ld_symtab_common, lsb); 
    133145        } else { 
    134146                if ((_lsb = _symbol_find(ld->ld_symtab_def, name)) != NULL) { 
     
    140152                        } 
    141153                } 
    142                 if ((_lsb = _symbol_find(ld->ld_symtab_undef, name)) != NULL) { 
     154                if ((_lsb = _symbol_find(ld->ld_symtab_undef, name)) != NULL) 
    143155                        _symbol_remove(ld->ld_symtab_undef, _lsb); 
    144                 } 
     156                if ((_lsb = _symbol_find(ld->ld_symtab_common, name)) != NULL) 
     157                        _symbol_remove(ld->ld_symtab_common, _lsb); 
    145158                _symbol_add(ld->ld_symtab_def, lsb); 
    146159        } 
     
    373386        struct ld_symbol *lsb; 
    374387 
    375         if ((lsb = _symbol_find(ld->ld_symtab_def, name)) == NULL) 
     388        if ((lsb = _symbol_find(ld->ld_symtab_def, name)) != NULL) 
     389                *val = lsb->lsb_value; 
     390        else if ((lsb = _symbol_find(ld->ld_symtab_common, name)) != NULL) 
     391                *val = lsb->lsb_value; 
     392        else 
    376393                return (-1); 
    377  
    378         *val = lsb->lsb_value; 
    379394 
    380395        return (0); 
     
    389404        struct ld_output_section *os; 
    390405 
    391         if (lsb->lsb_shndx == SHN_ABS || lsb->lsb_shndx == SHN_COMMON) 
     406        if (lsb->lsb_shndx == SHN_ABS) 
    392407                return; 
    393408 
     
    396411 
    397412        li = lsb->lsb_input; 
    398         is = &li->li_is[lsb->lsb_shndx]; 
     413        if (lsb->lsb_shndx == SHN_COMMON) 
     414                is = &li->li_is[li->li_shnum - 1]; 
     415        else 
     416                is = &li->li_is[lsb->lsb_shndx]; 
    399417        if ((os = is->is_output) == NULL) 
    400418                return; 
     
    419437 
    420438        HASH_ITER(hh, ld->ld_symtab_def, lsb, _lsb) { 
     439                _update_symbol(ld, lsb); 
     440        } 
     441 
     442        HASH_ITER(hh, ld->ld_symtab_common, lsb, _lsb) { 
    421443                _update_symbol(ld, lsb); 
    422444        } 
     
    489511        /* Copy undefined weak symbols. */ 
    490512        HASH_ITER(hh, ld->ld_symtab_undef, lsb, tmp) { 
     513                _add_to_symbol_table(ld, ld->ld_symtab, ld->ld_strtab, lsb); 
     514        } 
     515 
     516        /* Copy common symbols. */ 
     517        HASH_ITER(hh, ld->ld_symtab_common, lsb, tmp) { 
    491518                _add_to_symbol_table(ld, ld->ld_symtab, ld->ld_strtab, lsb); 
    492519        }