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

Changeset 2965

Show
Ignore:
Timestamp:
09/10/13 02:46:29 (7 months ago)
Author:
kaiwang27
Message:

Use string hash table for string sections that do not need suffix
match compression.

Location:
trunk/ld
Files:
6 modified

Legend:

Unmodified
Added
Removed
  • trunk/ld/ld_dynamic.c

    r2930 r2965  
    460460                DT_ENTRY_PTR(DT_STRTAB, lo->lo_dynstr->os_addr); 
    461461                DT_ENTRY_PTR(DT_SYMTAB, lo->lo_dynsym->os_addr); 
    462                 DT_ENTRY_VAL(DT_STRSZ, ld->ld_dynstr->st_size); 
     462                DT_ENTRY_VAL(DT_STRSZ, ld_strtab_getsize(ld->ld_dynstr)); 
    463463                DT_ENTRY_VAL(DT_SYMENT, 
    464464                    lo->lo_ec == ELFCLASS32 ? sizeof(Elf32_Sym) : 
     
    575575{ 
    576576        struct ld_input *li; 
    577         const char *bn; 
     577        char *bn; 
    578578        int ndx; 
    579579 
     
    588588 
    589589                        if (ld->ld_dynstr == NULL) 
    590                                 ld->ld_dynstr = ld_strtab_alloc(ld); 
     590                                ld->ld_dynstr = ld_strtab_alloc(ld, 0); 
    591591 
    592592                        /* Insert DSO name to the .dynstr string table. */ 
  • trunk/ld/ld_layout.c

    r2955 r2965  
    11581158                        assert(ls->ls_loc_counter == 0); 
    11591159                        st = oe->oe_entry; 
    1160                         ls->ls_loc_counter = st->st_size; 
     1160                        ls->ls_loc_counter = ld_strtab_getsize(st); 
    11611161                        break; 
    11621162                default: 
  • trunk/ld/ld_output.c

    r2959 r2965  
    407407{ 
    408408        Elf_Data *d; 
    409  
    410         if (strtab->st_buf == NULL || strtab->st_size == 0) 
     409        void *buf; 
     410        size_t sz; 
     411 
     412        buf = ld_strtab_getbuf(ld, strtab); 
     413        sz = ld_strtab_getsize(strtab); 
     414        if (buf == NULL || sz == 0) 
    411415                return; 
    412416 
     
    417421        d->d_off = 0; 
    418422        d->d_type = ELF_T_BYTE; 
    419         d->d_size = strtab->st_size; 
     423        d->d_size = sz; 
    420424        d->d_version = EV_CURRENT; 
    421         d->d_buf = strtab->st_buf; 
     425        d->d_buf = buf; 
    422426} 
    423427 
     
    965969 
    966970        if (ld->ld_shstrtab == NULL) { 
    967                 ld->ld_shstrtab = ld_strtab_alloc(ld); 
     971                ld->ld_shstrtab = ld_strtab_alloc(ld, 1); 
    968972                ld_strtab_insert(ld, ld->ld_shstrtab, ".symtab"); 
    969973                ld_strtab_insert(ld, ld->ld_shstrtab, ".strtab"); 
     
    984988        lo = ld->ld_output; 
    985989        st = ld->ld_shstrtab; 
    986         assert(st != NULL && st->st_buf != NULL); 
     990        assert(st != NULL); 
    987991 
    988992        STAILQ_FOREACH(os, &lo->lo_oslist, os_next) { 
     
    10501054        lo = ld->ld_output; 
    10511055        st = ld->ld_shstrtab; 
    1052         assert(st != NULL && st->st_buf != NULL); 
     1056        assert(st != NULL); 
    10531057 
    10541058        /* 
     
    11051109        Elf_Data *d; 
    11061110        GElf_Shdr sh; 
    1107  
    1108         assert(st != NULL && st->st_buf != NULL); 
    1109         assert(name != NULL); 
     1111        size_t sz; 
     1112 
     1113        assert(st != NULL && name != NULL); 
    11101114 
    11111115        ls = &ld->ld_state; 
     
    11291133        sh.sh_addralign = 1; 
    11301134        sh.sh_offset = ls->ls_offset; 
    1131         sh.sh_size = st->st_size; 
     1135        sh.sh_size = ld_strtab_getsize(st); 
    11321136        sh.sh_type = SHT_STRTAB; 
    11331137 
    11341138        if (!gelf_update_shdr(scn, &sh)) 
    11351139                ld_fatal(ld, "gelf_update_shdr failed: %s", elf_errmsg(-1)); 
     1140 
     1141        sz = ld_strtab_getsize(st); 
    11361142 
    11371143        if ((d = elf_newdata(scn)) == NULL) 
     
    11411147        d->d_off = 0; 
    11421148        d->d_type = ELF_T_BYTE; 
    1143         d->d_size = st->st_size; 
     1149        d->d_size = sz; 
    11441150        d->d_version = EV_CURRENT; 
    1145         d->d_buf = st->st_buf; 
    1146  
    1147         ls->ls_offset += st->st_size; 
    1148 } 
     1151        d->d_buf = ld_strtab_getbuf(ld, st); 
     1152 
     1153        ls->ls_offset += sz; 
     1154} 
  • trunk/ld/ld_strtab.c

    r2505 r2965  
    11/*- 
    2  * Copyright (c) 2012 Kai Wang 
     2 * Copyright (c) 2012,2013 Kai Wang 
    33 * All rights reserved. 
    44 * 
     
    3232#define _DEFAULT_STRTAB_SIZE    512 
    3333 
     34struct ld_str { 
     35        char *s; 
     36        size_t off, len; 
     37        UT_hash_handle hh; 
     38}; 
     39 
     40struct ld_strtab { 
     41        struct ld_str *st_pool; 
     42        char *st_buf; 
     43        size_t st_cap; 
     44        size_t st_size; 
     45        unsigned char st_suffix; 
     46}; 
     47 
     48 
    3449static void _resize_strtab(struct ld *ld, struct ld_strtab *st, 
    3550    size_t newsize); 
    3651 
    3752struct ld_strtab * 
    38 ld_strtab_alloc(struct ld *ld) 
     53ld_strtab_alloc(struct ld *ld, unsigned char suffix) 
    3954{ 
    4055        struct ld_strtab *st; 
    4156 
    42         if ((st = malloc(sizeof(*st))) == NULL) 
    43                 ld_fatal_std(ld, "malloc"); 
     57        if ((st = calloc(1, sizeof(*st))) == NULL) 
     58                ld_fatal_std(ld, "calloc"); 
     59         
    4460        st->st_size = 0; 
    45         st->st_cap = _DEFAULT_STRTAB_SIZE; 
    46         if ((st->st_buf = calloc(1, st->st_cap)) == NULL) 
    47                 ld_fatal_std(ld, "calloc"); 
    48  
    49         ld_strtab_insert(ld, st, ""); 
     61        if (suffix) { 
     62                st->st_suffix = 1; 
     63                st->st_cap = _DEFAULT_STRTAB_SIZE; 
     64                if ((st->st_buf = calloc(1, st->st_cap)) == NULL) 
     65                        ld_fatal_std(ld, "calloc"); 
     66                ld_strtab_insert(ld, st, ""); 
     67        } else 
     68                st->st_size = 1; 
    5069 
    5170        return (st); 
     
    5574ld_strtab_free(struct ld_strtab *st) 
    5675{ 
     76        struct ld_str *str, *tmp; 
    5777 
    5878        if (st == NULL) 
     
    6181        free(st->st_buf); 
    6282        free(st); 
     83 
     84        if (st->st_pool != NULL) { 
     85                HASH_ITER(hh, st->st_pool, str, tmp) { 
     86                        HASH_DELETE(hh, st->st_pool, str); 
     87                        free(str->s); 
     88                        free(str); 
     89                } 
     90        } 
     91} 
     92 
     93char * 
     94ld_strtab_getbuf(struct ld *ld, struct ld_strtab *st) 
     95{ 
     96        struct ld_str *str, *tmp; 
     97        char *p, *end; 
     98 
     99        assert(st != NULL); 
     100 
     101        if (st->st_suffix) 
     102                return (st->st_buf); 
     103 
     104        if (st->st_buf == NULL) { 
     105                if ((st->st_buf = malloc(st->st_size)) == NULL) 
     106                        ld_fatal_std(ld, "malloc"); 
     107                /* Flatten the string hash table. */ 
     108                p = st->st_buf; 
     109                end = p + st->st_size; 
     110                *p++ = '\0'; 
     111                HASH_ITER(hh, st->st_pool, str, tmp) { 
     112                        memcpy(p, str->s, str->len); 
     113                        p[str->len] = '\0'; 
     114                        p += str->len + 1; 
     115                } 
     116                assert(p == end); 
     117        } 
     118 
     119        return (st->st_buf); 
     120} 
     121 
     122size_t 
     123ld_strtab_getsize(struct ld_strtab *st) 
     124{ 
     125 
     126        return (st->st_size); 
    63127} 
    64128 
     
    67131{ 
    68132 
    69         assert(st != NULL); 
     133        assert(st != NULL && st->st_suffix); 
    70134        if ((st->st_buf = realloc(st->st_buf, newsize)) == NULL) 
    71135                ld_fatal_std(ld, "realloc"); 
    72136        st->st_cap = newsize; 
     137} 
     138 
     139size_t 
     140ld_strtab_insert_no_suffix(struct ld *ld, struct ld_strtab *st, char *s) 
     141{ 
     142        struct ld_str *str; 
     143 
     144        assert(st != NULL && st->st_suffix == 0); 
     145 
     146        if (s == NULL) 
     147                return (0); 
     148 
     149        if (*s == '\0') 
     150                return (0); 
     151 
     152        HASH_FIND_STR(st->st_pool, s, str); 
     153        if (str != NULL) 
     154                return (str->off); 
     155 
     156        if ((str = calloc(1, sizeof(*str))) == NULL) 
     157                ld_fatal_std(ld, "calloc"); 
     158 
     159        if ((str->s = strdup(s)) == NULL) 
     160                ld_fatal_std(ld, "strdup"); 
     161 
     162        str->len = strlen(s); 
     163        HASH_ADD_KEYPTR(hh, st->st_pool, str->s, str->len, str); 
     164 
     165        str->off = st->st_size; 
     166        st->st_size += str->len + 1; 
     167 
     168        return (str->off); 
    73169} 
    74170 
     
    81177        int append; 
    82178 
    83         assert(st != NULL && st->st_buf != NULL); 
     179        assert(st != NULL && st->st_buf != NULL && st->st_suffix); 
    84180 
    85181        if (s == NULL) 
     
    116212} 
    117213 
    118 int 
    119 ld_strtab_insert_no_suffix(struct ld *ld, struct ld_strtab *st, const char *s) 
    120 { 
    121         char *b; 
    122         size_t slen; 
    123         int p; 
    124  
    125         if (s == NULL) 
    126                 return (0); 
    127  
    128         slen = strlen(s); 
    129         for (b = st->st_buf; b < st->st_buf + st->st_size; b += strlen(b) + 1) { 
    130                 if (strlen(b) != slen) 
    131                         continue; 
    132                 if (strcmp(b, s) == 0) 
    133                         return (b - st->st_buf); 
    134         } 
    135  
    136         while (st->st_size + slen + 1 >= st->st_cap) 
    137                 _resize_strtab(ld, st, st->st_cap * 2); 
    138  
    139         b = st->st_buf; 
    140         p = st->st_size; 
    141         strncpy(&b[p], s, slen); 
    142         b[p + slen] = '\0'; 
    143         st->st_size += slen + 1; 
    144  
    145         return (p); 
    146 } 
    147  
    148 int 
     214size_t 
    149215ld_strtab_lookup(struct ld_strtab *st, const char *s) 
    150216{ 
    151217        const char *b, *c, *r; 
    152218        size_t len, slen; 
     219 
     220        assert(st != NULL && st->st_buf != NULL && st->st_suffix); 
    153221 
    154222        if (s == NULL) 
  • trunk/ld/ld_strtab.h

    r2505 r2965  
    11/*- 
    2  * Copyright (c) 2012 Kai Wang 
     2 * Copyright (c) 2012,2013 Kai Wang 
    33 * All rights reserved. 
    44 * 
     
    2727 */ 
    2828 
    29 struct ld_strtab { 
    30         char *st_buf; 
    31         size_t st_cap; 
    32         size_t st_size; 
    33 }; 
    34  
    35 struct ld_strtab *ld_strtab_alloc(struct ld *); 
     29struct ld_strtab *ld_strtab_alloc(struct ld *, unsigned char); 
    3630void    ld_strtab_free(struct ld_strtab *); 
    3731void    ld_strtab_insert(struct ld *, struct ld_strtab *, const char *); 
    38 int     ld_strtab_insert_no_suffix(struct ld *, struct ld_strtab *, 
    39             const char *); 
    40 int     ld_strtab_lookup(struct ld_strtab *, const char *); 
     32size_t  ld_strtab_insert_no_suffix(struct ld *, struct ld_strtab *, char *); 
     33size_t  ld_strtab_lookup(struct ld_strtab *, const char *); 
     34char    *ld_strtab_getbuf(struct ld *, struct ld_strtab *); 
     35size_t  ld_strtab_getsize(struct ld_strtab *); 
  • trunk/ld/ld_symbols.c

    r2956 r2965  
    315315 
    316316        ld->ld_symtab = _alloc_symbol_table(ld); 
    317         ld->ld_strtab = ld_strtab_alloc(ld); 
     317        ld->ld_strtab = ld_strtab_alloc(ld, 0); 
    318318 
    319319        /* Create an initial symbol at the beginning of symbol table. */ 
     
    432432        ld->ld_dynsym = _alloc_symbol_table(ld); 
    433433        if (ld->ld_dynstr == NULL) 
    434                 ld->ld_dynstr = ld_strtab_alloc(ld); 
     434                ld->ld_dynstr = ld_strtab_alloc(ld, 0); 
    435435 
    436436        /* Reserve space for the initial symbol. */