1a1ba9ba4Schristos /* ELF strtab with GC and suffix merging support. 2*b2396a7bSchristos Copyright (C) 2001-2016 Free Software Foundation, Inc. 3a1ba9ba4Schristos Written by Jakub Jelinek <jakub@redhat.com>. 4a1ba9ba4Schristos 5a1ba9ba4Schristos This file is part of BFD, the Binary File Descriptor library. 6a1ba9ba4Schristos 7a1ba9ba4Schristos This program is free software; you can redistribute it and/or modify 8a1ba9ba4Schristos it under the terms of the GNU General Public License as published by 9a1ba9ba4Schristos the Free Software Foundation; either version 3 of the License, or 10a1ba9ba4Schristos (at your option) any later version. 11a1ba9ba4Schristos 12a1ba9ba4Schristos This program is distributed in the hope that it will be useful, 13a1ba9ba4Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 14a1ba9ba4Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15a1ba9ba4Schristos GNU General Public License for more details. 16a1ba9ba4Schristos 17a1ba9ba4Schristos You should have received a copy of the GNU General Public License 18a1ba9ba4Schristos along with this program; if not, write to the Free Software 19a1ba9ba4Schristos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20a1ba9ba4Schristos MA 02110-1301, USA. */ 21a1ba9ba4Schristos 22a1ba9ba4Schristos #include "sysdep.h" 23a1ba9ba4Schristos #include "bfd.h" 24a1ba9ba4Schristos #include "libbfd.h" 25a1ba9ba4Schristos #include "elf-bfd.h" 26a1ba9ba4Schristos #include "hashtab.h" 27a1ba9ba4Schristos #include "libiberty.h" 28a1ba9ba4Schristos 29a1ba9ba4Schristos /* An entry in the strtab hash table. */ 30a1ba9ba4Schristos 31a1ba9ba4Schristos struct elf_strtab_hash_entry 32a1ba9ba4Schristos { 33a1ba9ba4Schristos struct bfd_hash_entry root; 34a1ba9ba4Schristos /* Length of this entry. This includes the zero terminator. */ 35a1ba9ba4Schristos int len; 36a1ba9ba4Schristos unsigned int refcount; 37a1ba9ba4Schristos union { 38a1ba9ba4Schristos /* Index within the merged section. */ 39a1ba9ba4Schristos bfd_size_type index; 40a1ba9ba4Schristos /* Entry this is a suffix of (if len < 0). */ 41a1ba9ba4Schristos struct elf_strtab_hash_entry *suffix; 42a1ba9ba4Schristos } u; 43a1ba9ba4Schristos }; 44a1ba9ba4Schristos 45a1ba9ba4Schristos /* The strtab hash table. */ 46a1ba9ba4Schristos 47a1ba9ba4Schristos struct elf_strtab_hash 48a1ba9ba4Schristos { 49a1ba9ba4Schristos struct bfd_hash_table table; 50a1ba9ba4Schristos /* Next available index. */ 51*b2396a7bSchristos size_t size; 52a1ba9ba4Schristos /* Number of array entries alloced. */ 53*b2396a7bSchristos size_t alloced; 54a1ba9ba4Schristos /* Final strtab size. */ 55a1ba9ba4Schristos bfd_size_type sec_size; 56a1ba9ba4Schristos /* Array of pointers to strtab entries. */ 57a1ba9ba4Schristos struct elf_strtab_hash_entry **array; 58a1ba9ba4Schristos }; 59a1ba9ba4Schristos 60a1ba9ba4Schristos /* Routine to create an entry in a section merge hashtab. */ 61a1ba9ba4Schristos 62a1ba9ba4Schristos static struct bfd_hash_entry * 63a1ba9ba4Schristos elf_strtab_hash_newfunc (struct bfd_hash_entry *entry, 64a1ba9ba4Schristos struct bfd_hash_table *table, 65a1ba9ba4Schristos const char *string) 66a1ba9ba4Schristos { 67a1ba9ba4Schristos /* Allocate the structure if it has not already been allocated by a 68a1ba9ba4Schristos subclass. */ 69a1ba9ba4Schristos if (entry == NULL) 70a1ba9ba4Schristos entry = (struct bfd_hash_entry *) 71a1ba9ba4Schristos bfd_hash_allocate (table, sizeof (struct elf_strtab_hash_entry)); 72a1ba9ba4Schristos if (entry == NULL) 73a1ba9ba4Schristos return NULL; 74a1ba9ba4Schristos 75a1ba9ba4Schristos /* Call the allocation method of the superclass. */ 76a1ba9ba4Schristos entry = bfd_hash_newfunc (entry, table, string); 77a1ba9ba4Schristos 78a1ba9ba4Schristos if (entry) 79a1ba9ba4Schristos { 80a1ba9ba4Schristos /* Initialize the local fields. */ 81a1ba9ba4Schristos struct elf_strtab_hash_entry *ret; 82a1ba9ba4Schristos 83a1ba9ba4Schristos ret = (struct elf_strtab_hash_entry *) entry; 84a1ba9ba4Schristos ret->u.index = -1; 85a1ba9ba4Schristos ret->refcount = 0; 86a1ba9ba4Schristos ret->len = 0; 87a1ba9ba4Schristos } 88a1ba9ba4Schristos 89a1ba9ba4Schristos return entry; 90a1ba9ba4Schristos } 91a1ba9ba4Schristos 92a1ba9ba4Schristos /* Create a new hash table. */ 93a1ba9ba4Schristos 94a1ba9ba4Schristos struct elf_strtab_hash * 95a1ba9ba4Schristos _bfd_elf_strtab_init (void) 96a1ba9ba4Schristos { 97a1ba9ba4Schristos struct elf_strtab_hash *table; 98a1ba9ba4Schristos bfd_size_type amt = sizeof (struct elf_strtab_hash); 99a1ba9ba4Schristos 100a1ba9ba4Schristos table = (struct elf_strtab_hash *) bfd_malloc (amt); 101a1ba9ba4Schristos if (table == NULL) 102a1ba9ba4Schristos return NULL; 103a1ba9ba4Schristos 104a1ba9ba4Schristos if (!bfd_hash_table_init (&table->table, elf_strtab_hash_newfunc, 105a1ba9ba4Schristos sizeof (struct elf_strtab_hash_entry))) 106a1ba9ba4Schristos { 107a1ba9ba4Schristos free (table); 108a1ba9ba4Schristos return NULL; 109a1ba9ba4Schristos } 110a1ba9ba4Schristos 111a1ba9ba4Schristos table->sec_size = 0; 112a1ba9ba4Schristos table->size = 1; 113a1ba9ba4Schristos table->alloced = 64; 114a1ba9ba4Schristos amt = sizeof (struct elf_strtab_hasn_entry *); 115*b2396a7bSchristos table->array = ((struct elf_strtab_hash_entry **) 116*b2396a7bSchristos bfd_malloc (table->alloced * amt)); 117a1ba9ba4Schristos if (table->array == NULL) 118a1ba9ba4Schristos { 119a1ba9ba4Schristos free (table); 120a1ba9ba4Schristos return NULL; 121a1ba9ba4Schristos } 122a1ba9ba4Schristos 123a1ba9ba4Schristos table->array[0] = NULL; 124a1ba9ba4Schristos 125a1ba9ba4Schristos return table; 126a1ba9ba4Schristos } 127a1ba9ba4Schristos 128a1ba9ba4Schristos /* Free a strtab. */ 129a1ba9ba4Schristos 130a1ba9ba4Schristos void 131a1ba9ba4Schristos _bfd_elf_strtab_free (struct elf_strtab_hash *tab) 132a1ba9ba4Schristos { 133a1ba9ba4Schristos bfd_hash_table_free (&tab->table); 134a1ba9ba4Schristos free (tab->array); 135a1ba9ba4Schristos free (tab); 136a1ba9ba4Schristos } 137a1ba9ba4Schristos 138a1ba9ba4Schristos /* Get the index of an entity in a hash table, adding it if it is not 139a1ba9ba4Schristos already present. */ 140a1ba9ba4Schristos 141*b2396a7bSchristos size_t 142a1ba9ba4Schristos _bfd_elf_strtab_add (struct elf_strtab_hash *tab, 143a1ba9ba4Schristos const char *str, 144a1ba9ba4Schristos bfd_boolean copy) 145a1ba9ba4Schristos { 146a1ba9ba4Schristos register struct elf_strtab_hash_entry *entry; 147a1ba9ba4Schristos 148a1ba9ba4Schristos /* We handle this specially, since we don't want to do refcounting 149a1ba9ba4Schristos on it. */ 150a1ba9ba4Schristos if (*str == '\0') 151a1ba9ba4Schristos return 0; 152a1ba9ba4Schristos 153a1ba9ba4Schristos BFD_ASSERT (tab->sec_size == 0); 154a1ba9ba4Schristos entry = (struct elf_strtab_hash_entry *) 155a1ba9ba4Schristos bfd_hash_lookup (&tab->table, str, TRUE, copy); 156a1ba9ba4Schristos 157a1ba9ba4Schristos if (entry == NULL) 158*b2396a7bSchristos return (size_t) -1; 159a1ba9ba4Schristos 160a1ba9ba4Schristos entry->refcount++; 161a1ba9ba4Schristos if (entry->len == 0) 162a1ba9ba4Schristos { 163a1ba9ba4Schristos entry->len = strlen (str) + 1; 164a1ba9ba4Schristos /* 2G strings lose. */ 165a1ba9ba4Schristos BFD_ASSERT (entry->len > 0); 166a1ba9ba4Schristos if (tab->size == tab->alloced) 167a1ba9ba4Schristos { 168a1ba9ba4Schristos bfd_size_type amt = sizeof (struct elf_strtab_hash_entry *); 169a1ba9ba4Schristos tab->alloced *= 2; 170a1ba9ba4Schristos tab->array = (struct elf_strtab_hash_entry **) 171a1ba9ba4Schristos bfd_realloc_or_free (tab->array, tab->alloced * amt); 172a1ba9ba4Schristos if (tab->array == NULL) 173*b2396a7bSchristos return (size_t) -1; 174a1ba9ba4Schristos } 175a1ba9ba4Schristos 176a1ba9ba4Schristos entry->u.index = tab->size++; 177a1ba9ba4Schristos tab->array[entry->u.index] = entry; 178a1ba9ba4Schristos } 179a1ba9ba4Schristos return entry->u.index; 180a1ba9ba4Schristos } 181a1ba9ba4Schristos 182a1ba9ba4Schristos void 183*b2396a7bSchristos _bfd_elf_strtab_addref (struct elf_strtab_hash *tab, size_t idx) 184a1ba9ba4Schristos { 185*b2396a7bSchristos if (idx == 0 || idx == (size_t) -1) 186a1ba9ba4Schristos return; 187a1ba9ba4Schristos BFD_ASSERT (tab->sec_size == 0); 188a1ba9ba4Schristos BFD_ASSERT (idx < tab->size); 189a1ba9ba4Schristos ++tab->array[idx]->refcount; 190a1ba9ba4Schristos } 191a1ba9ba4Schristos 192a1ba9ba4Schristos void 193*b2396a7bSchristos _bfd_elf_strtab_delref (struct elf_strtab_hash *tab, size_t idx) 194a1ba9ba4Schristos { 195*b2396a7bSchristos if (idx == 0 || idx == (size_t) -1) 196a1ba9ba4Schristos return; 197a1ba9ba4Schristos BFD_ASSERT (tab->sec_size == 0); 198a1ba9ba4Schristos BFD_ASSERT (idx < tab->size); 199a1ba9ba4Schristos BFD_ASSERT (tab->array[idx]->refcount > 0); 200a1ba9ba4Schristos --tab->array[idx]->refcount; 201a1ba9ba4Schristos } 202a1ba9ba4Schristos 203a1ba9ba4Schristos unsigned int 204*b2396a7bSchristos _bfd_elf_strtab_refcount (struct elf_strtab_hash *tab, size_t idx) 205a1ba9ba4Schristos { 206a1ba9ba4Schristos return tab->array[idx]->refcount; 207a1ba9ba4Schristos } 208a1ba9ba4Schristos 209a1ba9ba4Schristos void 210a1ba9ba4Schristos _bfd_elf_strtab_clear_all_refs (struct elf_strtab_hash *tab) 211a1ba9ba4Schristos { 212*b2396a7bSchristos size_t idx; 213a1ba9ba4Schristos 214a1ba9ba4Schristos for (idx = 1; idx < tab->size; idx++) 215a1ba9ba4Schristos tab->array[idx]->refcount = 0; 216a1ba9ba4Schristos } 217a1ba9ba4Schristos 218*b2396a7bSchristos /* Save strtab refcounts prior to adding --as-needed library. */ 219*b2396a7bSchristos 220*b2396a7bSchristos struct strtab_save 221a1ba9ba4Schristos { 222*b2396a7bSchristos size_t size; 223*b2396a7bSchristos unsigned int refcount[1]; 224*b2396a7bSchristos }; 225*b2396a7bSchristos 226*b2396a7bSchristos void * 227*b2396a7bSchristos _bfd_elf_strtab_save (struct elf_strtab_hash *tab) 228*b2396a7bSchristos { 229*b2396a7bSchristos struct strtab_save *save; 230*b2396a7bSchristos size_t idx, size; 231*b2396a7bSchristos 232*b2396a7bSchristos size = sizeof (*save) + (tab->size - 1) * sizeof (save->refcount[0]); 233*b2396a7bSchristos save = bfd_malloc (size); 234*b2396a7bSchristos if (save == NULL) 235*b2396a7bSchristos return save; 236*b2396a7bSchristos 237*b2396a7bSchristos save->size = tab->size; 238*b2396a7bSchristos for (idx = 1; idx < tab->size; idx++) 239*b2396a7bSchristos save->refcount[idx] = tab->array[idx]->refcount; 240*b2396a7bSchristos return save; 241*b2396a7bSchristos } 242*b2396a7bSchristos 243*b2396a7bSchristos /* Restore strtab refcounts on finding --as-needed library not needed. */ 244*b2396a7bSchristos 245*b2396a7bSchristos void 246*b2396a7bSchristos _bfd_elf_strtab_restore (struct elf_strtab_hash *tab, void *buf) 247*b2396a7bSchristos { 248*b2396a7bSchristos size_t idx, curr_size = tab->size; 249*b2396a7bSchristos struct strtab_save *save = (struct strtab_save *) buf; 250a1ba9ba4Schristos 251a1ba9ba4Schristos BFD_ASSERT (tab->sec_size == 0); 252*b2396a7bSchristos BFD_ASSERT (save->size <= curr_size); 253*b2396a7bSchristos tab->size = save->size; 254*b2396a7bSchristos for (idx = 1; idx < save->size; ++idx) 255*b2396a7bSchristos tab->array[idx]->refcount = save->refcount[idx]; 256*b2396a7bSchristos 257a1ba9ba4Schristos for (; idx < curr_size; ++idx) 258a1ba9ba4Schristos { 259a1ba9ba4Schristos /* We don't remove entries from the hash table, just set their 260a1ba9ba4Schristos REFCOUNT to zero. Setting LEN zero will result in the size 261a1ba9ba4Schristos growing if the entry is added again. See _bfd_elf_strtab_add. */ 262a1ba9ba4Schristos tab->array[idx]->refcount = 0; 263a1ba9ba4Schristos tab->array[idx]->len = 0; 264a1ba9ba4Schristos } 265a1ba9ba4Schristos } 266a1ba9ba4Schristos 267a1ba9ba4Schristos bfd_size_type 268a1ba9ba4Schristos _bfd_elf_strtab_size (struct elf_strtab_hash *tab) 269a1ba9ba4Schristos { 270a1ba9ba4Schristos return tab->sec_size ? tab->sec_size : tab->size; 271a1ba9ba4Schristos } 272a1ba9ba4Schristos 273a1ba9ba4Schristos bfd_size_type 274*b2396a7bSchristos _bfd_elf_strtab_offset (struct elf_strtab_hash *tab, size_t idx) 275a1ba9ba4Schristos { 276a1ba9ba4Schristos struct elf_strtab_hash_entry *entry; 277a1ba9ba4Schristos 278a1ba9ba4Schristos if (idx == 0) 279a1ba9ba4Schristos return 0; 280a1ba9ba4Schristos BFD_ASSERT (idx < tab->size); 281a1ba9ba4Schristos BFD_ASSERT (tab->sec_size); 282a1ba9ba4Schristos entry = tab->array[idx]; 283a1ba9ba4Schristos BFD_ASSERT (entry->refcount > 0); 284a1ba9ba4Schristos entry->refcount--; 285a1ba9ba4Schristos return tab->array[idx]->u.index; 286a1ba9ba4Schristos } 287a1ba9ba4Schristos 288a1ba9ba4Schristos bfd_boolean 289a1ba9ba4Schristos _bfd_elf_strtab_emit (register bfd *abfd, struct elf_strtab_hash *tab) 290a1ba9ba4Schristos { 291*b2396a7bSchristos bfd_size_type off = 1; 292*b2396a7bSchristos size_t i; 293a1ba9ba4Schristos 294a1ba9ba4Schristos if (bfd_bwrite ("", 1, abfd) != 1) 295a1ba9ba4Schristos return FALSE; 296a1ba9ba4Schristos 297a1ba9ba4Schristos for (i = 1; i < tab->size; ++i) 298a1ba9ba4Schristos { 299a1ba9ba4Schristos register const char *str; 300a1ba9ba4Schristos register unsigned int len; 301a1ba9ba4Schristos 302a1ba9ba4Schristos BFD_ASSERT (tab->array[i]->refcount == 0); 303a1ba9ba4Schristos len = tab->array[i]->len; 304a1ba9ba4Schristos if ((int) len < 0) 305a1ba9ba4Schristos continue; 306a1ba9ba4Schristos 307a1ba9ba4Schristos str = tab->array[i]->root.string; 308a1ba9ba4Schristos if (bfd_bwrite (str, len, abfd) != len) 309a1ba9ba4Schristos return FALSE; 310a1ba9ba4Schristos 311a1ba9ba4Schristos off += len; 312a1ba9ba4Schristos } 313a1ba9ba4Schristos 314a1ba9ba4Schristos BFD_ASSERT (off == tab->sec_size); 315a1ba9ba4Schristos return TRUE; 316a1ba9ba4Schristos } 317a1ba9ba4Schristos 318a1ba9ba4Schristos /* Compare two elf_strtab_hash_entry structures. Called via qsort. */ 319a1ba9ba4Schristos 320a1ba9ba4Schristos static int 321a1ba9ba4Schristos strrevcmp (const void *a, const void *b) 322a1ba9ba4Schristos { 323a1ba9ba4Schristos struct elf_strtab_hash_entry *A = *(struct elf_strtab_hash_entry **) a; 324a1ba9ba4Schristos struct elf_strtab_hash_entry *B = *(struct elf_strtab_hash_entry **) b; 325a1ba9ba4Schristos unsigned int lenA = A->len; 326a1ba9ba4Schristos unsigned int lenB = B->len; 327a1ba9ba4Schristos const unsigned char *s = (const unsigned char *) A->root.string + lenA - 1; 328a1ba9ba4Schristos const unsigned char *t = (const unsigned char *) B->root.string + lenB - 1; 329a1ba9ba4Schristos int l = lenA < lenB ? lenA : lenB; 330a1ba9ba4Schristos 331a1ba9ba4Schristos while (l) 332a1ba9ba4Schristos { 333a1ba9ba4Schristos if (*s != *t) 334a1ba9ba4Schristos return (int) *s - (int) *t; 335a1ba9ba4Schristos s--; 336a1ba9ba4Schristos t--; 337a1ba9ba4Schristos l--; 338a1ba9ba4Schristos } 339a1ba9ba4Schristos return lenA - lenB; 340a1ba9ba4Schristos } 341a1ba9ba4Schristos 342a1ba9ba4Schristos static inline int 343a1ba9ba4Schristos is_suffix (const struct elf_strtab_hash_entry *A, 344a1ba9ba4Schristos const struct elf_strtab_hash_entry *B) 345a1ba9ba4Schristos { 346a1ba9ba4Schristos if (A->len <= B->len) 347a1ba9ba4Schristos /* B cannot be a suffix of A unless A is equal to B, which is guaranteed 348a1ba9ba4Schristos not to be equal by the hash table. */ 349a1ba9ba4Schristos return 0; 350a1ba9ba4Schristos 351a1ba9ba4Schristos return memcmp (A->root.string + (A->len - B->len), 352a1ba9ba4Schristos B->root.string, B->len - 1) == 0; 353a1ba9ba4Schristos } 354a1ba9ba4Schristos 355a1ba9ba4Schristos /* This function assigns final string table offsets for used strings, 356a1ba9ba4Schristos merging strings matching suffixes of longer strings if possible. */ 357a1ba9ba4Schristos 358a1ba9ba4Schristos void 359a1ba9ba4Schristos _bfd_elf_strtab_finalize (struct elf_strtab_hash *tab) 360a1ba9ba4Schristos { 361a1ba9ba4Schristos struct elf_strtab_hash_entry **array, **a, *e; 362*b2396a7bSchristos bfd_size_type amt, sec_size; 363*b2396a7bSchristos size_t size, i; 364a1ba9ba4Schristos 365a1ba9ba4Schristos /* Sort the strings by suffix and length. */ 366*b2396a7bSchristos amt = tab->size; 367*b2396a7bSchristos amt *= sizeof (struct elf_strtab_hash_entry *); 368a1ba9ba4Schristos array = (struct elf_strtab_hash_entry **) bfd_malloc (amt); 369a1ba9ba4Schristos if (array == NULL) 370a1ba9ba4Schristos goto alloc_failure; 371a1ba9ba4Schristos 372a1ba9ba4Schristos for (i = 1, a = array; i < tab->size; ++i) 373a1ba9ba4Schristos { 374a1ba9ba4Schristos e = tab->array[i]; 375a1ba9ba4Schristos if (e->refcount) 376a1ba9ba4Schristos { 377a1ba9ba4Schristos *a++ = e; 378a1ba9ba4Schristos /* Adjust the length to not include the zero terminator. */ 379a1ba9ba4Schristos e->len -= 1; 380a1ba9ba4Schristos } 381a1ba9ba4Schristos else 382a1ba9ba4Schristos e->len = 0; 383a1ba9ba4Schristos } 384a1ba9ba4Schristos 385a1ba9ba4Schristos size = a - array; 386a1ba9ba4Schristos if (size != 0) 387a1ba9ba4Schristos { 388a1ba9ba4Schristos qsort (array, size, sizeof (struct elf_strtab_hash_entry *), strrevcmp); 389a1ba9ba4Schristos 390a1ba9ba4Schristos /* Loop over the sorted array and merge suffixes. Start from the 391a1ba9ba4Schristos end because we want eg. 392a1ba9ba4Schristos 393a1ba9ba4Schristos s1 -> "d" 394a1ba9ba4Schristos s2 -> "bcd" 395a1ba9ba4Schristos s3 -> "abcd" 396a1ba9ba4Schristos 397a1ba9ba4Schristos to end up as 398a1ba9ba4Schristos 399a1ba9ba4Schristos s3 -> "abcd" 400a1ba9ba4Schristos s2 _____^ 401a1ba9ba4Schristos s1 _______^ 402a1ba9ba4Schristos 403a1ba9ba4Schristos ie. we don't want s1 pointing into the old s2. */ 404a1ba9ba4Schristos e = *--a; 405a1ba9ba4Schristos e->len += 1; 406a1ba9ba4Schristos while (--a >= array) 407a1ba9ba4Schristos { 408a1ba9ba4Schristos struct elf_strtab_hash_entry *cmp = *a; 409a1ba9ba4Schristos 410a1ba9ba4Schristos cmp->len += 1; 411a1ba9ba4Schristos if (is_suffix (e, cmp)) 412a1ba9ba4Schristos { 413a1ba9ba4Schristos cmp->u.suffix = e; 414a1ba9ba4Schristos cmp->len = -cmp->len; 415a1ba9ba4Schristos } 416a1ba9ba4Schristos else 417a1ba9ba4Schristos e = cmp; 418a1ba9ba4Schristos } 419a1ba9ba4Schristos } 420a1ba9ba4Schristos 421a1ba9ba4Schristos alloc_failure: 422a1ba9ba4Schristos if (array) 423a1ba9ba4Schristos free (array); 424a1ba9ba4Schristos 425a1ba9ba4Schristos /* Assign positions to the strings we want to keep. */ 426*b2396a7bSchristos sec_size = 1; 427a1ba9ba4Schristos for (i = 1; i < tab->size; ++i) 428a1ba9ba4Schristos { 429a1ba9ba4Schristos e = tab->array[i]; 430a1ba9ba4Schristos if (e->refcount && e->len > 0) 431a1ba9ba4Schristos { 432*b2396a7bSchristos e->u.index = sec_size; 433*b2396a7bSchristos sec_size += e->len; 434a1ba9ba4Schristos } 435a1ba9ba4Schristos } 436a1ba9ba4Schristos 437*b2396a7bSchristos tab->sec_size = sec_size; 438a1ba9ba4Schristos 439a1ba9ba4Schristos /* Adjust the rest. */ 440a1ba9ba4Schristos for (i = 1; i < tab->size; ++i) 441a1ba9ba4Schristos { 442a1ba9ba4Schristos e = tab->array[i]; 443a1ba9ba4Schristos if (e->refcount && e->len < 0) 444a1ba9ba4Schristos e->u.index = e->u.suffix->u.index + (e->u.suffix->len + e->len); 445a1ba9ba4Schristos } 446a1ba9ba4Schristos } 447