Initial Contribution
[0xdroid:external_elfcopy.git] / elfcopy.c
1
2 #include <stdio.h>
3 #include <common.h>
4 #include <debug.h>
5 #include <hash.h>
6 #include <libelf.h>
7 #include <libebl.h>
8 #include <libebl_arm.h>
9 #include <elf.h>
10 #include <gelf.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <string.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <unistd.h>
18 #ifdef DEBUG
19     #include <rangesort.h>
20 #endif
21
22 /* static void print_shdr_array(shdr_info_t *, int); */
23
24 #include <elfcopy.h>
25
26 #define COPY_SECTION_DATA_BUFFER (0)
27
28 /* When this macro is set to a nonzero value, we replace calls to elf_strptr()
29    on the target ELF handle with code that extracts the strings directly from
30    the data buffers of that ELF handle.  In this case, elf_strptr() does not
31    work as expected, as it tries to read the data buffer of the associated
32    string section directly from the file, and that buffer does not exist yet
33    in the file, since we haven't committed our changes yet.
34 */
35 #define ELF_STRPTR_IS_BROKEN     (1)
36
37 static void update_relocations_section_symbol_references(Elf *newelf, Elf *elf,
38                                                          shdr_info_t *info, int info_len,
39                                                          shdr_info_t *relsect_info,
40                                                          Elf32_Word *newsymidx);
41
42 static void update_relocations_section_offsets(Elf *newelf, Elf *elf, Ebl *ebl,
43                                                shdr_info_t *info,
44                                                int info_len,
45                                                shdr_info_t *relsect_info,
46                                                Elf_Data *data,
47                                                range_list_t *old_section_ranges);
48
49 static void update_hash_table(Elf *newelf, Elf *elf,
50                               Elf32_Word hash_scn_idx,
51                               shdr_info_t *symtab_info);
52
53 static inline
54 Elf_Data *create_section_data(shdr_info_t *, Elf_Scn *);
55
56 static Elf64_Off section_to_header_mapping(Elf *elf,
57                                            int phdr_idx,
58                                            shdr_info_t *shdr_info,
59                                            int num_shdr_info,
60                                            Elf64_Off *file_end,
61                                            Elf64_Off *mem_end);
62
63 static void build_dynamic_segment_strings(Elf *elf, Ebl *oldebl,
64                                           int dynidx, /* index of .dynamic section */
65                                           int symtabidx, /* index of symbol table section */
66                                           shdr_info_t *shdr_info,
67                                           int shdr_info_len);
68
69 #ifdef DEBUG
70 static void print_dynamic_segment_strings(Elf *elf, Ebl *oldebl,
71                                           int dynidx, /* index of .dynamic section */
72                                           int symtabidx, /* index of symbol table section */
73                                           shdr_info_t *shdr_info,
74                                           int shdr_info_len);
75 #endif
76
77 static void adjust_dynamic_segment_offsets(Elf *elf, Ebl *oldebl,
78                                            Elf *newelf,
79                                            int idx, /* index of .dynamic section */
80                                            shdr_info_t *shdr_info,
81                                            int shdr_info_len);
82
83 static void update_symbol_values(Elf *elf, GElf_Ehdr *ehdr,
84                                  Elf *newelf,
85                                  shdr_info_t *shdr_info,
86                                  int num_shdr_info,
87                                  int shady,
88                                  int dynamic_idx);
89
90 static bool section_belongs_to_header(GElf_Shdr *shdr, GElf_Phdr *phdr);
91
92 static range_list_t *
93 update_section_offsets(Elf *elf,
94                        Elf *newelf,
95                        GElf_Phdr *phdr_info,
96                        shdr_info_t *shdr_info,
97                        int num_shdr_info,
98                        range_list_t *section_ranges,
99                        bool adjust_alloc_section_offsets);
100
101 void handle_range_error(range_error_t err, range_t *left, range_t *right);
102
103 #ifdef DEBUG
104 static void
105 verify_elf(GElf_Ehdr *ehdr, struct shdr_info_t *shdr_info, int shdr_info_len,
106            GElf_Phdr *phdr_info);
107 #endif
108
109 void adjust_elf(Elf *elf, const char *elf_name,
110                 Elf *newelf, const char *newelf_name,
111                 Ebl *ebl,
112                 GElf_Ehdr *ehdr, /* store ELF header of original library */
113                 bool *sym_filter, int num_symbols,
114                 struct shdr_info_t *shdr_info, int shdr_info_len,
115                 GElf_Phdr *phdr_info,
116                 size_t highest_scn_num,
117                 size_t shnum,
118                 size_t shstrndx,
119                 struct Ebl_Strtab *shst,
120                 bool sections_dropped_or_rearranged,
121                 int dynamic_idx, /* index in shdr_info[] of .dynamic section */
122                 int dynsym_idx, /* index in shdr_info[] of dynamic symbol table */
123                 int shady,
124                 Elf_Data **shstrtab_data,
125                 bool adjust_alloc_section_offsets,
126                 bool rebuild_shstrtab)
127 {
128     int cnt;      /* general-purpose counter */
129     Elf_Scn *scn; /* general-purpose section */
130
131     *shstrtab_data = NULL;
132
133     /* When this flag is true, we have dropped some symbols, which caused
134        a change in the order of symbols in the symbol table (all symbols after
135        the removed symbol have shifted forward), and a change in its size as
136        well.  When the symbol table changes this way, we need to modify the
137        relocation entries that relocate symbols in this symbol table, and we
138        also need to rebuild the hash table (the hash is outdated).
139
140        Note that it is possible to change the symbols in the symbol table
141        without changing their position (that is, without cutting any symbols
142        out).  If a section that a symbol refers to changes (i.e., moves), we
143        need to update that section's index in the symbol entry in the symbol
144        table.  Therefore, there are symbol-table changes that can be made and
145        still have symtab_size_changed == false!
146     */
147     bool symtab_size_changed = false;
148
149     /* We allow adjusting of offsets only for files that are shared libraries.
150        We cannot mess with the relative positions of sections for executable
151        files, because we do not have enough information to adjust them.  The
152        text section is already linked to fixed addresses.
153     */
154     ASSERT(!adjust_alloc_section_offsets || ehdr->e_type == ET_DYN);
155
156     if (!sections_dropped_or_rearranged)
157          INFO("Note: we aren't dropping or rearranging any sections.\n");
158
159     /* Index of the section header table in the shdr_info array.  This is
160        an important variable because it denotes the last section of the old
161        file, as well as the location of the section-strings section of the
162        new one.
163
164        Note: we use this variable only when we are re-creating the section-
165        header-strings table.  Otherwise, we keep it as zero.
166     */
167
168     size_t shdridx = shstrndx;
169     if (rebuild_shstrtab) {
170         INFO("Creating new section-strings section...\n");
171
172         shdridx = shnum;
173
174         /* Create the new section-name-strings section */
175         {
176             INFO("\tNew index will be %d (was %d).\n", highest_scn_num, shstrndx);
177
178             /* Add the section header string table section name. */
179             shdr_info[shdridx] = shdr_info[shstrndx];
180             ASSERT(!strcmp(shdr_info[shdridx].name, ".shstrtab"));
181             shdr_info[shdridx].se = ebl_strtabadd (shst, ".shstrtab", 10);
182             ASSERT(shdr_info[shdridx].se != NULL);
183             shdr_info[shdridx].idx = highest_scn_num;
184
185             /* Create the section header. */
186             shdr_info[shdridx].shdr.sh_type = SHT_STRTAB;
187             shdr_info[shdridx].shdr.sh_flags = 0;
188             shdr_info[shdridx].shdr.sh_addr = 0;
189             shdr_info[shdridx].shdr.sh_link = SHN_UNDEF;
190             shdr_info[shdridx].shdr.sh_info = SHN_UNDEF;
191             shdr_info[shdridx].shdr.sh_entsize = 0;
192
193             shdr_info[shdridx].shdr.sh_offset = shdr_info[shdridx].old_shdr.sh_offset;
194             shdr_info[shdridx].shdr.sh_addralign = 1;
195
196             /* Create the section. */
197             FAILIF_LIBELF((shdr_info[shdridx].newscn = elf_newscn(newelf)) == NULL,
198                           elf_newscn);
199             ASSERT(elf_ndxscn (shdr_info[shdridx].newscn) == highest_scn_num);
200
201             {
202                 /* Finalize the string table and fill in the correct indices in
203                    the section headers. */
204                 FAILIF_LIBELF((*shstrtab_data =
205                                elf_newdata (shdr_info[shdridx].newscn)) == NULL,
206                               elf_newdata);
207                 ebl_strtabfinalize (shst, *shstrtab_data);
208                 /* We have to set the section size. */
209                 INFO("\tNew size will be %d.\n", (*shstrtab_data)->d_size);
210                 shdr_info[shdridx].shdr.sh_size = (*shstrtab_data)->d_size;
211                 /* Setting the data pointer tells the update loop below not to
212                    copy the information from the original section. */
213
214                 shdr_info[shdridx].data = *shstrtab_data;
215 #if COPY_SECTION_DATA_BUFFER
216                 shdr_info[shdridx].data->d_buf = MALLOC(shdr_info[shdridx].data->d_size);
217                 ASSERT((*shstrtab_data)->d_buf);
218                 memcpy(shdr_info[shdridx].data->d_buf, (*shstrtab_data)->d_buf, (*shstrtab_data)->d_size);
219 #endif
220             }
221         }
222     } /* if (rebuild_shstrtab) */
223     else {
224         /* When we are not rebuilding shstrtab, we expect the input parameter
225            shstrndx to be the index of .shstrtab BOTH in shdr_info[] and in
226            as a section index in the ELF file.
227         */
228         ASSERT(!strcmp(shdr_info[shdridx].name, ".shstrtab"));
229     }
230
231     INFO("Updating section information...\n");
232     /* Update the section information. */
233
234 #ifdef DEBUG
235     /* We use this flag to ASSERT that the symbol tables comes
236        before the .dynamic section in the file.  See comments
237        further below.
238     */
239     bool visited_dynsym = false;
240 #endif
241
242     for (cnt = 1; cnt < shdr_info_len; ++cnt) {
243         if (shdr_info[cnt].idx > 0) {
244             Elf_Data *newdata;
245
246             INFO("\t%03d: Updating section %s (index %d, address %lld offset %lld, size %lld, alignment %d)...\n",
247                  cnt,
248                  (shdr_info[cnt].name ?: "(no name)"),
249                  shdr_info[cnt].idx,
250                  shdr_info[cnt].shdr.sh_addr,
251                  shdr_info[cnt].shdr.sh_offset,
252                  shdr_info[cnt].shdr.sh_size,
253                  shdr_info[cnt].shdr.sh_addralign);
254
255             scn = shdr_info[cnt].newscn;
256             ASSERT(scn != NULL);
257             ASSERT(scn == elf_getscn(newelf, shdr_info[cnt].idx));
258
259             /* Update the name. */
260             if (rebuild_shstrtab) {
261                 Elf64_Word new_sh_name = ebl_strtaboffset(shdr_info[cnt].se);
262                 INFO("\t\tname offset %d (was %d).\n",
263                      new_sh_name,
264                      shdr_info[cnt].shdr.sh_name);
265                 shdr_info[cnt].shdr.sh_name = new_sh_name;
266             }
267
268             /* Update the section header from the input file.  Some fields
269                might be section indices which now have to be adjusted. */
270             if (shdr_info[cnt].shdr.sh_link != 0) {
271                 INFO("\t\tsh_link %d (was %d).\n",
272                      shdr_info[shdr_info[cnt].shdr.sh_link].idx,
273                      shdr_info[cnt].shdr.sh_link);
274
275                 shdr_info[cnt].shdr.sh_link =
276                 shdr_info[shdr_info[cnt].shdr.sh_link].idx;
277             }
278
279             /* Handle the SHT_REL, SHT_RELA, and SHF_INFO_LINK flag. */
280             if (SH_INFO_LINK_P (&shdr_info[cnt].shdr)) {
281                 INFO("\t\tsh_info %d (was %d).\n",
282                      shdr_info[shdr_info[cnt].shdr.sh_info].idx,
283                      shdr_info[cnt].shdr.sh_info);
284
285                 shdr_info[cnt].shdr.sh_info =
286                 shdr_info[shdr_info[cnt].shdr.sh_info].idx;
287             }
288
289             /* Get the data from the old file if necessary.  We already
290                created the data for the section header string table, which
291                has a section number equal to shnum--hence the ASSERT().
292             */
293             ASSERT(!rebuild_shstrtab || shdr_info[cnt].data || cnt < shnum);
294             newdata = create_section_data(shdr_info + cnt, scn);
295
296             /* We know the size. */
297             shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
298
299             /* We have to adjust symbol tables.  Each symbol contains
300                a reference to the section it belongs to.  Since we have
301                renumbered the sections (and dropped some), we need to adjust
302                the symbols' section indices as well.  Also, if we do not want
303                to keep a symbol, we drop it from the symbol table in this loop.
304
305                When we drop symbols from the dynamic-symbol table, we need to
306                remove the names of the sybmols from the dynamic-symbol-strings
307                table.  Changing the dynamic-symbol-strings table means that we
308                also have to rebuild the strings that go into the .dynamic
309                section (such as the DT_NEEDED strings, which lists the libraries
310                that the file depends on), since those strings are kept in the
311                same dynamic-symbol-strings table.  That latter statement
312                is an assumption (which we ASSERT against, read on below).
313
314                Note: we process the symbol-table sections only when the user
315                specifies a symbol filter AND that leads to a change in the
316                symbol table, or when section indices change.
317             */
318
319             /* The .dynamic section's strings need not be contained in the
320                same section as the strings of the dynamic symbol table,
321                but we assume that they are (I haven't seen it be otherwise).
322                We assert the validity of our assumption here.
323
324                If this assertion fails, then we *may* need to reorganize
325                this code as follows: we will need to call function
326                build_dynamic_segment_strings() even when sections numbers
327                don't change and there is no filter.  Also, if string section
328                containing the .dynamic section strings changes, then we'd
329                need to update the sh_link of the .dynamic section to point
330                to the new section.
331             */
332
333             ASSERT(shdr_info[dynamic_idx].shdr.sh_link ==
334                    shdr_info[dynsym_idx].shdr.sh_link);
335
336             if (sections_dropped_or_rearranged || (sym_filter != NULL))
337             {
338                 if(shdr_info[cnt].shdr.sh_type == SHT_DYNSYM)
339                 {
340                     INFO("\t\tupdating a symbol table.\n");
341
342                     /* Calculate the size of the external representation of a
343                        symbol. */
344                     size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
345
346                     /* Check the length of the dynamic-symbol filter. (This is the
347                        second of two identical checks, the first one being in
348                        the loop that checks for exceptions.)
349
350                        NOTE: We narrow this assertion down to the dynamic-symbol
351                              table only.  Since we expect the symbol filter to
352                              be parallel to .dynsym, and .dynsym in general
353                              contains fewer symbols than .strtab, we cannot
354                              make this assertion for .strtab.
355                     */
356                     FAILIF(sym_filter != NULL &&
357                            num_symbols != shdr_info[cnt].data->d_size / elsize,
358                            "Length of dynsym filter (%d) must equal the number"
359                            " of dynamic symbols (%d) in section [%s]!\n",
360                            num_symbols,
361                            shdr_info[cnt].data->d_size / elsize,
362                            shdr_info[cnt].name);
363
364                     shdr_info[cnt].symse =
365                         (struct Ebl_Strent **)MALLOC(
366                             (shdr_info[cnt].data->d_size/elsize) *
367                             sizeof(struct Ebl_Strent *));
368                     shdr_info[cnt].dynsymst = ebl_strtabinit(1);
369                     FAILIF_LIBELF(NULL == shdr_info[cnt].dynsymst, ebl_strtabinit);
370
371                     /* Allocate an array of Elf32_Word, one for each symbol.  This
372                        array will hold the new symbol indices.
373                     */
374                     shdr_info[cnt].newsymidx =
375                     (Elf32_Word *)CALLOC(shdr_info[cnt].data->d_size / elsize,
376                                          sizeof (Elf32_Word));
377
378                     bool last_was_local = true;
379                     size_t destidx, // index of the symbol in the new symbol table
380                         inner,  // index of the symbol in the old table
381                         last_local_idx = 0;
382                     int num_kept_undefined_and_special = 0;
383                     int num_kept_global_or_weak = 0;
384                     int num_thrown_away = 0;
385
386                     unsigned long num_symbols = shdr_info[cnt].data->d_size / elsize;
387                     INFO("\t\tsymbol table has %ld symbols.\n", num_symbols);
388
389                     /* In the loop below, determine whether to remove or not each
390                        symbol.
391                     */
392                     for (destidx = inner = 1; inner < num_symbols; ++inner)
393                     {
394                         Elf32_Word sec; /* index of section a symbol refers to */
395                         Elf32_Word xshndx; /* extended-section index of symbol */
396                         /* Retrieve symbol information and separate section index
397                            from the symbol table at the given index. */
398                         GElf_Sym sym_mem; /* holds the symbol */
399
400                         /* Retrieve symbol information and separate section index
401                            from the symbol table at the given index. */
402                         GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
403                                                           NULL, inner,
404                                                           &sym_mem, &xshndx);
405                         ASSERT(sym != NULL);
406
407                         FAILIF(sym->st_shndx == SHN_XINDEX,
408                                "Can't handle symbol's st_shndx == SHN_XINDEX!\n");
409
410                         /* Do not automatically strip the symbol if:
411                             -- the symbol filter is NULL or
412                             -- the symbol is marked to keep or
413                             -- the symbol is neither of:
414                                 -- imported or refers to a nonstandard section
415                                 -- global
416                                 -- weak
417
418                             We do not want to strip imported symbols, because then
419                             we won't be able to link against them.  We do not want
420                             to strip global or weak symbols, because then someone
421                             else will fail to link against them.  Finally, we do
422                             not want to strip nonstandard symbols, because we're
423                             not sure what they are doing there.
424                         */
425
426                         char *symname = elf_strptr(elf,
427                                                    shdr_info[cnt].old_shdr.sh_link,
428                                                    sym->st_name);
429
430                         if (NULL == sym_filter || /* no symfilter */
431                             sym_filter[inner] ||  /* keep the symbol! */
432                             /* don't keep the symbol, but the symbol is undefined
433                                or refers to a specific section */
434                             sym->st_shndx == SHN_UNDEF || sym->st_shndx >= shnum ||
435                             /* don't keep the symbol, which defined and refers to
436                                a normal section, but the symbol is neither global
437                                nor weak. */
438                             (ELF32_ST_BIND(sym->st_info) != STB_GLOBAL &&
439                              ELF32_ST_BIND(sym->st_info) != STB_WEAK))
440                         {
441                             /* Do not remove the symbol. */
442                             if (sym->st_shndx == SHN_UNDEF ||
443                                 sym->st_shndx >= shnum)
444                             {
445                                 /* This symbol has no section index (it is
446                                    absolute). Leave the symbol alone unless it is
447                                    moved. */
448                                 FAILIF_LIBELF(!(destidx == inner ||
449                                                 gelf_update_symshndx(
450                                                     shdr_info[cnt].data,
451                                                     NULL,
452                                                     destidx,
453                                                     sym,
454                                                     xshndx)),
455                                               gelf_update_symshndx);
456
457                                 shdr_info[cnt].newsymidx[inner] = destidx;
458                                 INFO("\t\t\tkeeping %s symbol %d (new index %d), name [%s]\n",
459                                      (sym->st_shndx == SHN_UNDEF ? "undefined" : "special"),
460                                      inner,
461                                      destidx,
462                                      symname);
463                                 /* mark the symbol as kept */
464                                 if (sym_filter) sym_filter[inner] = 1;
465                                 shdr_info[cnt].symse[destidx] =
466                                     ebl_strtabadd (shdr_info[cnt].dynsymst,
467                                                    symname, 0);
468                                 ASSERT(shdr_info[cnt].symse[destidx] != NULL);
469                                 num_kept_undefined_and_special++;
470                                 if (GELF_ST_BIND(sym->st_info) == STB_LOCAL)
471                                     last_local_idx = destidx;
472                                 destidx++;
473                             } else {
474                                 /* Get the full section index. */
475                                 sec = shdr_info[sym->st_shndx].idx;
476
477                                 if (sec) {
478                                     Elf32_Word nxshndx;
479
480                                     ASSERT (sec < SHN_LORESERVE);
481                                     nxshndx = 0;
482
483                                     /* Update the symbol only if something changed,
484                                        that is, if either the symbol's position in
485                                        the symbol table changed (because we deleted
486                                        some symbols), or because its section moved!
487
488                                        NOTE: We don't update the symbol's section
489                                        index, sym->st_shndx here, but in function
490                                        update_symbol_values() instead.  The reason
491                                        is that if we update the symbol-section index,
492                                        now, it won't refer anymore to the shdr_info[]
493                                        entry, which we will need in
494                                        update_symbol_values().
495                                     */
496                                     if (inner != destidx)
497                                     {
498                                         FAILIF_LIBELF(0 ==
499                                                       gelf_update_symshndx(
500                                                           shdr_info[cnt].data,
501                                                           NULL,
502                                                           destidx, sym,
503                                                           nxshndx),
504                                                       gelf_update_symshndx);
505                                     }
506
507                                     shdr_info[cnt].newsymidx[inner] = destidx;
508
509                                     /* If we are not filtering out some symbols,
510                                        there's no point to printing this message
511                                        for every single symbol. */
512                                     if (sym_filter) {
513                                         INFO("\t\t\tkeeping symbol %d (new index %d), name (index %d) [%s]\n",
514                                              inner,
515                                              destidx,
516                                              sym->st_name,
517                                              symname);
518                                         /* mark the symbol as kept */
519                                         sym_filter[inner] = 1;
520                                     }
521                                     shdr_info[cnt].symse[destidx] =
522                                         ebl_strtabadd(shdr_info[cnt].dynsymst,
523                                                       symname, 0);
524                                     ASSERT(shdr_info[cnt].symse[destidx] != NULL);
525                                     num_kept_global_or_weak++;
526                                     if (GELF_ST_BIND(sym->st_info) == STB_LOCAL)
527                                         last_local_idx = destidx;
528                                     destidx++;
529                                 } else {
530                                     /* I am not sure, there might be other types of
531                                        symbols that do not refer to any section, but
532                                        I will handle them case by case when this
533                                        assertion fails--I want to know if each of them
534                                        is safe to remove!
535                                     */
536                                     ASSERT(GELF_ST_TYPE (sym->st_info) == STT_SECTION ||
537                                            GELF_ST_TYPE (sym->st_info) == STT_NOTYPE);
538                                     INFO("\t\t\tignoring %s symbol [%s]"
539                                          " at index %d refering to section %d\n",
540                                          (GELF_ST_TYPE(sym->st_info) == STT_SECTION
541                                           ? "STT_SECTION" : "STT_NOTYPE"),
542                                          symname,
543                                          inner,
544                                          sym->st_shndx);
545                                     num_thrown_away++;
546                                     /* mark the symbol as thrown away */
547                                     if (sym_filter) sym_filter[inner] = 0;
548                                 }
549                             }
550                         } /* to strip or not to strip? */
551                         else {
552                             INFO("\t\t\tremoving symbol [%s]\n", symname);
553                             shdr_info[cnt].newsymidx[inner] = (Elf32_Word)-1;
554                             num_thrown_away++;
555                             /* mark the symbol as thrown away */
556                             if (sym_filter) sym_filter[inner] = 0;
557                         }
558
559                         /* For symbol-table sections, sh_info is one greater than the
560                            symbol table index of the last local symbol.  This is why,
561                            when we find the last local symbol, we update the sh_info
562                            field.
563                         */
564
565                         if (last_was_local) {
566                             if (GELF_ST_BIND (sym->st_info) != STB_LOCAL) {
567                                 last_was_local = false;
568                                 if (last_local_idx) {
569                                     INFO("\t\t\tMARKING ONE PAST LAST LOCAL INDEX %d\n",
570                                          last_local_idx + 1);
571                                     shdr_info[cnt].shdr.sh_info =
572                                         last_local_idx + 1;
573                                 }
574                                 else shdr_info[cnt].shdr.sh_info = 0;
575
576                             }
577                         } else FAILIF(0 && GELF_ST_BIND (sym->st_info) == STB_LOCAL,
578                                       "Internal error in ELF file: symbol table has"
579                                       " local symbols after first global"
580                                       " symbol!\n");
581                     } /* for each symbol */
582
583                     INFO("\t\t%d undefined or special symbols were kept.\n",
584                          num_kept_undefined_and_special);
585                     INFO("\t\t%d global or weak symbols were kept.\n",
586                          num_kept_global_or_weak);
587                     INFO("\t\t%d symbols were thrown away.\n",
588                          num_thrown_away);
589
590                     if (destidx != inner) {
591                         /* The symbol table changed. */
592                         INFO("\t\t\tthe symbol table has changed.\n");
593                         INFO("\t\t\tdestidx = %d, inner = %d.\n", destidx, inner);
594                         INFO("\t\t\tnew size %d (was %lld).\n",
595                              destidx * elsize,
596                              shdr_info[cnt].shdr.sh_size);
597                         shdr_info[cnt].shdr.sh_size = newdata->d_size = destidx * elsize;
598                         symtab_size_changed = true;
599                     } else {
600                         /* The symbol table didn't really change. */
601                         INFO("\t\t\tthe symbol table did not change.\n");
602                         FREE (shdr_info[cnt].newsymidx);
603                         shdr_info[cnt].newsymidx = NULL;
604                     }
605 #ifdef DEBUG
606                     visited_dynsym = shdr_info[cnt].shdr.sh_type == SHT_DYNSYM;
607 #endif
608                 } /* if it's a symbol table... */
609                 else if (shdr_info[cnt].shdr.sh_type == SHT_DYNAMIC) {
610                     /* We get here either when we drop some sections, or
611                        when we are dropping symbols.  If we are not dropping
612                        symbols, then the dynamic-symbol-table and its strings
613                        section won't change, so we won't need to rebuild the
614                        symbols for the SHT_DYNAMIC section either.
615
616                        NOTE: If ever in the future we add the ability in
617                        adjust_elf() to change the strings in the SHT_DYNAMIC
618                        section, then we would need to find a way to rebuild
619                        the dynamic-symbol-table-strings section.
620                     */
621
622                     /* symtab_size_changed has a meaningful value only after
623                        we've processed the symbol table.  If this assertion
624                        is ever violated, it will be because the .dynamic section
625                        came before the symbol table in the list of section in
626                        a file.  If that happens, then we have to break up the
627                        loop into two: one that finds and processes the symbol
628                        tables, and another, after the first one, that finds
629                        and handles the .dynamic sectio.
630                      */
631                     ASSERT(visited_dynsym == true);
632                     if (sym_filter != NULL && symtab_size_changed) {
633                         /* Walk the old dynamic segment.  For each tag that represents
634                            a string, build an entry into the dynamic-symbol-table's
635                            strings table. */
636                         INFO("\t\tbuilding strings for the dynamic section.\n");
637                         ASSERT(cnt == dynamic_idx);
638
639                         /* NOTE:  By passing the the index (in shdr_info[]) of the
640                            dynamic-symbol table to build_dynamic_segment_strings(),
641                            we are making the assumption that those strings will be
642                            kept in that table.  While this does not seem to be
643                            mandated by the ELF spec, it seems to be always the case.
644                            Where else would you put these strings?  You already have
645                            the dynamic-symbol table and its strings table, and that's
646                            guaranteed to be in the file, so why not put it there?
647                         */
648                         build_dynamic_segment_strings(elf, ebl,
649                                                       dynamic_idx,
650                                                       dynsym_idx,
651                                                       shdr_info,
652                                                       shdr_info_len);
653                     }
654                     else {
655                         INFO("\t\tThe dynamic-symbol table is not changing, so no "
656                              "need to rebuild strings for the dynamic section.\n");
657 #ifdef DEBUG
658                         print_dynamic_segment_strings(elf, ebl,
659                                                       dynamic_idx,
660                                                       dynsym_idx,
661                                                       shdr_info,
662                                                       shdr_info_len);
663 #endif
664                     }
665                 }
666             }
667
668             /* Set the section header in the new file. There cannot be any
669                overflows. */
670             INFO("\t\tupdating section header (size %lld)\n",
671                  shdr_info[cnt].shdr.sh_size);
672
673             FAILIF(!gelf_update_shdr (scn, &shdr_info[cnt].shdr),
674                    "Could not update section header for section %s!\n",
675                    shdr_info[cnt].name);
676         } /* if (shdr_info[cnt].idx > 0) */
677         else INFO("\t%03d: not updating section %s, it will be discarded.\n",
678                   cnt,
679                   shdr_info[cnt].name);
680     } /* for (cnt = 1; cnt < shdr_info_len; ++cnt) */
681
682     /* Now, if we removed some symbols and thus modified the symbol table,
683        we need to update the hash table, the relocation sections that use these
684        symbols, and the symbol-strings table to cut out the unused symbols.
685     */
686     if (symtab_size_changed) {
687         for (cnt = 1; cnt < shnum; ++cnt) {
688             if (shdr_info[cnt].idx == 0) {
689                 /* Ignore sections which are discarded, unless these sections
690                    are relocation sections.  This case is for use by the
691                    prelinker. */
692                 if (shdr_info[cnt].shdr.sh_type != SHT_REL &&
693                     shdr_info[cnt].shdr.sh_type != SHT_RELA) {
694                     continue;
695                 }
696             }
697
698             if (shdr_info[cnt].shdr.sh_type == SHT_REL ||
699                 shdr_info[cnt].shdr.sh_type == SHT_RELA) {
700                 /* shdr_info[cnt].old_shdr.sh_link is index of old symbol-table
701                    section that this relocation-table section was relative to.
702                    We can access shdr_info[] at that index to get to the
703                    symbol-table section.
704                 */
705                 Elf32_Word *newsymidx =
706                 shdr_info[shdr_info[cnt].old_shdr.sh_link].newsymidx;
707
708                 /* The referred-to-section must be a symbol table!  Note that
709                    alrhough shdr_info[cnt].shdr refers to the updated section
710                    header, this assertion is still valid, since when updating
711                    the section header we never modify the sh_type field.
712                 */
713                 {
714                     Elf64_Word sh_type =
715                     shdr_info[shdr_info[cnt].shdr.sh_link].shdr.sh_type;
716                     FAILIF(sh_type != SHT_DYNSYM,
717                            "Section refered to from relocation section is not"
718                            " a dynamic symbol table (sh_type=%d)!\n",
719                            sh_type);
720                 }
721
722                 /* If that symbol table hasn't changed, then its newsymidx
723                    field is NULL (see comments to shdr_info_t), so we
724                    don't have to update this relocation-table section
725                 */
726                 if (newsymidx == NULL) continue;
727
728                 update_relocations_section_symbol_references(newelf, elf,
729                                                              shdr_info, shnum,
730                                                              shdr_info + cnt,
731                                                              newsymidx);
732
733             } else if (shdr_info[cnt].shdr.sh_type == SHT_HASH) {
734                 /* We have to recompute the hash table.  A hash table's
735                    sh_link field refers to the symbol table for which the hash
736                    table is generated.
737                 */
738                 Elf32_Word symtabidx = shdr_info[cnt].old_shdr.sh_link;
739
740                 /* We do not have to recompute the hash table if the symbol
741                    table was not changed. */
742                 if (shdr_info[symtabidx].newsymidx == NULL)
743                     continue;
744
745                 FAILIF(shdr_info[cnt].shdr.sh_entsize != sizeof (Elf32_Word),
746                        "Can't handle 64-bit ELF files!\n");
747
748                 update_hash_table(newelf,  /* new ELF */
749                                   elf,     /* old ELF */
750                                   shdr_info[cnt].idx, /* hash table index */
751                                   shdr_info + symtabidx);
752             } /* if SHT_REL else if SHT_HASH ... */
753             else if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM)
754             {
755                 /* The symbol table's sh_link field contains the index of the
756                    strings table for this symbol table.  We want to find the
757                    index of the section in the shdr_info[] array.  That index
758                    corresponds to the index of the section in the original ELF file,
759                    which is why we look at shdr_info[cnt].old_shdr and not
760                    shdr_info[cnt].shdr.
761                 */
762
763                 int symstrndx = shdr_info[cnt].old_shdr.sh_link;
764                 INFO("Updating [%s] (symbol-strings-section data for [%s]).\n",
765                      shdr_info[symstrndx].name,
766                      shdr_info[cnt].name);
767                 ASSERT(shdr_info[symstrndx].newscn);
768                 size_t new_symstrndx = elf_ndxscn(shdr_info[symstrndx].newscn);
769                 Elf_Data *newdata = elf_getdata(shdr_info[symstrndx].newscn, NULL);
770                 ASSERT(NULL != newdata);
771                 INFO("\tbefore update:\n"
772                      "\t\tbuffer: %p\n"
773                      "\t\tsize: %d\n",
774                      newdata->d_buf,
775                      newdata->d_size);
776                 ASSERT(shdr_info[cnt].dynsymst);
777                 ebl_strtabfinalize (shdr_info[cnt].dynsymst, newdata);
778                 INFO("\tafter update:\n"
779                      "\t\tbuffer: %p\n"
780                      "\t\tsize: %d\n",
781                      newdata->d_buf,
782                      newdata->d_size);
783                 FAILIF(new_symstrndx != shdr_info[cnt].shdr.sh_link,
784                        "The index of the symbol-strings table according to elf_ndxscn() is %d, "
785                        "according to shdr_info[] is %d!\n",
786                        new_symstrndx,
787                        shdr_info[cnt].shdr.sh_link);
788
789                 INFO("%d nonprintable\n",
790                      dump_hex_buffer(stdout, newdata->d_buf, newdata->d_size, 0));
791
792                 shdr_info[symstrndx].shdr.sh_size = newdata->d_size;
793                 FAILIF(!gelf_update_shdr(shdr_info[symstrndx].newscn,
794                                          &shdr_info[symstrndx].shdr),
795                        "Could not update section header for section %s!\n",
796                        shdr_info[symstrndx].name);
797
798                 /* Now, update the symbol-name offsets. */
799                 {
800                     size_t i;
801                     size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
802                     for (i = 1; i < shdr_info[cnt].shdr.sh_size / elsize; ++i) {
803                         Elf32_Word xshndx;
804                         GElf_Sym sym_mem;
805                         /* retrieve the symbol information; */
806                         GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
807                                                           NULL, i,
808                                                           &sym_mem, &xshndx);
809                         ASSERT(sym != NULL);
810                         ASSERT(NULL != shdr_info[cnt].symse[i]);
811                         /* calculate the new name offset; */
812                         size_t new_st_name =
813                             ebl_strtaboffset(shdr_info[cnt].symse[i]);
814 #if 1
815                         ASSERT(!strcmp(newdata->d_buf + new_st_name,
816                                        elf_strptr(elf, shdr_info[cnt].old_shdr.sh_link,
817                                                   sym->st_name)));
818 #endif
819                         if (sym_filter && (sym->st_name != new_st_name)) {
820                             /* FIXME: For some reason, elf_strptr() does not return the updated
821                                string value here.  It looks like ebl_strtabfinalize() doesn't
822                                update libelf's internal structures well enough for elf_strptr()
823                                to work on an ELF file that's being compose.
824                             */
825                             INFO("Symbol [%s]'s name (index %d, old value %llx) changes offset: %d -> %d\n",
826 #if 0
827                                  newdata->d_buf + new_st_name,
828 #else
829                                  elf_strptr(elf, shdr_info[cnt].old_shdr.sh_link,
830                                             sym->st_name),
831 #endif
832                                  i,
833                                  sym->st_value,
834                                  sym->st_name,
835                                  new_st_name);
836                         }
837                         sym->st_name = new_st_name;
838                         /* update the symbol info; */
839                         FAILIF_LIBELF(0 ==
840                                       gelf_update_symshndx(
841                                           shdr_info[cnt].data,
842                                           NULL,
843                                           i, sym,
844                                           xshndx),
845                                       gelf_update_symshndx);
846                     } /* for each symbol... */
847                 }
848             }
849
850             FAILIF(shdr_info[cnt].shdr.sh_type == SHT_GNU_versym,
851                    "Can't handle SHT_GNU_versym!\n");
852             FAILIF(shdr_info[cnt].shdr.sh_type == SHT_GROUP,
853                    "Can't handle section groups!\n");
854         } /* for (cnt = 1; cnt < shnum; ++cnt) */
855     } /* if (symtab_size_changed) */
856
857
858     range_list_t *old_section_ranges = init_range_list();
859     range_list_t *section_ranges = NULL;
860     /* Analyze gaps in the ranges before we compact the sections. */
861     INFO("Analyzing gaps in ranges before compacting sections...\n");
862     {
863         size_t scnidx;
864         /* Gather the ranges */
865         for (scnidx = 1; scnidx < shdr_info_len; scnidx++) {
866             if (shdr_info[scnidx].idx > 0) {
867                 if (/*shdr_info[scnidx].old_shdr.sh_type != SHT_NOBITS &&*/
868                     shdr_info[scnidx].old_shdr.sh_flags & SHF_ALLOC) {
869                     add_unique_range_nosort(
870                         old_section_ranges,
871                         shdr_info[scnidx].old_shdr.sh_addr,
872                         shdr_info[scnidx].old_shdr.sh_size,
873                         shdr_info + scnidx,
874                         handle_range_error,
875                         NULL);
876                 }
877             }
878         }
879         sort_ranges(old_section_ranges);
880 #ifdef DEBUG
881         int num_ranges;
882         /* Analyze gaps in the ranges before we compact the sections. */
883         range_t *ranges = get_sorted_ranges(old_section_ranges, &num_ranges);
884         if (ranges) {
885             GElf_Off last_end = ranges->start;
886             int i;
887             for (i = 0; i < num_ranges; i++) {
888                 shdr_info_t *curr = (shdr_info_t *)ranges[i].user;
889                 ASSERT(ranges[i].start >= last_end);
890                 int col_before, col_after;
891                 INFO("[%016lld, %016lld] %n[%s]%n",
892                      ranges[i].start,
893                      ranges[i].start + ranges[i].length,
894                      &col_before,
895                      curr->name,
896                      &col_after);
897                 if (ranges[i].start > last_end) {
898                     shdr_info_t *prev = (shdr_info_t *)ranges[i-1].user;
899                     ASSERT(prev && curr);
900                     while (col_after++ - col_before < 20) INFO(" ");
901                     INFO(" [GAP: %lld bytes with %s]\n",
902                          (ranges[i].start - last_end),
903                          prev->name);
904                 }
905                 else INFO("\n");
906                 last_end = ranges[i].start + ranges[i].length;
907             }
908         }
909 #endif/*DEBUG*/
910     }
911
912     /* Calculate the final section offsets */
913     INFO("Calculating new section offsets...\n");
914     section_ranges = update_section_offsets(elf,
915                                             newelf,
916                                             phdr_info,
917                                             shdr_info,
918                                             shdr_info_len,
919                                             init_range_list(),
920                                             adjust_alloc_section_offsets);
921
922 #ifdef DEBUG
923     {
924         /* Analyze gaps in the ranges after we've compacted the sections. */
925         int num_ranges;
926         range_t *ranges = get_sorted_ranges(section_ranges, &num_ranges);
927         if (ranges) {
928             int last_end = ranges->start;
929             int i;
930             for (i = 0; i < num_ranges; i++) {
931                 shdr_info_t *curr = (shdr_info_t *)ranges[i].user;
932                 ASSERT(ranges[i].start >= last_end);
933                 int col_before, col_after;
934                 INFO("[%016lld, %016lld] %n[%s]%n",
935                      ranges[i].start,
936                      ranges[i].start + ranges[i].length,
937                      &col_before,
938                      curr->name,
939                      &col_after);
940                 if (ranges[i].start > last_end) {
941                     shdr_info_t *prev = (shdr_info_t *)ranges[i-1].user;
942                     ASSERT(prev && curr);
943                     while (col_after++ - col_before < 20) INFO(" ");
944                     INFO(" [GAP: %lld bytes with %s]\n",
945                          (ranges[i].start - last_end),
946                          prev->name);
947                 }
948                 else INFO("\n");
949                 last_end = ranges[i].start + ranges[i].length;
950             }
951         }
952     }
953 #endif
954
955     {
956         /* Now that we have modified the section offsets, we need to scan the
957            symbol tables once again and update their st_value fields.  A symbol's
958            st_value field (in a shared library) contains the virtual address of the
959            symbol.  For each symbol we encounter, we look up the section it was in.
960            If that section's virtual address has changed, then we calculate the
961            delta and update the symbol.
962         */
963
964 #if 0
965         {
966             /* for debugging: Print out all sections and their data pointers and
967                sizes. */
968             int i = 1;
969             for (; i < shdr_info_len; i++) {
970                 PRINT("%8d: %-15s: %2lld %8lld %08lx (%08lx:%8d) %08lx (%08lx:%8d)\n",
971                       i,
972                       shdr_info[i].name,
973                       shdr_info[i].shdr.sh_entsize,
974                       shdr_info[i].shdr.sh_addralign,
975                       (long)shdr_info[i].data,
976                       (long)(shdr_info[i].data ? shdr_info[i].data->d_buf : 0),
977                       (shdr_info[i].data ? shdr_info[i].data->d_size : 0),
978                       (long)shdr_info[i].newdata,
979                       (long)(shdr_info[i].newdata ? shdr_info[i].newdata->d_buf : 0),
980                       (shdr_info[i].newdata ? shdr_info[i].newdata->d_size : 0));
981                 if (!strcmp(shdr_info[i].name, ".got") /* ||
982                                                           !strcmp(shdr_info[i].name, ".plt") */) {
983                     dump_hex_buffer(stdout,
984                                     shdr_info[i].newdata->d_buf,
985                                     shdr_info[i].newdata->d_size,
986                                     shdr_info[i].shdr.sh_entsize);
987                 }
988             }
989         }
990 #endif
991
992         INFO("Updating symbol values...\n");
993         update_symbol_values(elf, ehdr, newelf, shdr_info, shdr_info_len,
994                              shady,
995                              dynamic_idx);
996
997         /* If we are not stripping the debug sections, then we need to adjust
998          * them accordingly, so that the new ELF file is actually debuggable.
999          * For that glorios reason, we call update_dwarf().  Note that
1000          * update_dwarf() won't do anything if there, in fact, no debug
1001          * sections to speak of.
1002          */
1003
1004         INFO("Updating DWARF records...\n");
1005         int num_total_dwarf_patches = 0, num_failed_dwarf_patches = 0;
1006         update_dwarf_if_necessary(
1007             elf, ehdr, newelf,
1008             shdr_info, shdr_info_len,
1009             &num_total_dwarf_patches, &num_failed_dwarf_patches);
1010         INFO("DWARF: %-15s: total %8d failed %8d.\n", elf_name, num_total_dwarf_patches, num_failed_dwarf_patches);
1011
1012         /* Adjust the program-header table.  Since the file offsets of the various
1013            sections may have changed, the file offsets of their containing segments
1014            must change as well.  We update those offsets in the loop below.
1015         */
1016         {
1017             INFO("Adjusting program-header table...\n");
1018             int pi; /* program-header index */
1019             for (pi = 0; pi < ehdr->e_phnum; ++pi) {
1020                 /* Print the segment number.  */
1021                 INFO("\t%2.2zu\t", pi);
1022                 INFO("PT_ header type: %d", phdr_info[pi].p_type);
1023                 if (phdr_info[pi].p_type == PT_NULL) {
1024                     INFO(" PT_NULL (skip)\n");
1025                 }
1026                 else if (phdr_info[pi].p_type == PT_PHDR) {
1027                     INFO(" PT_PHDR\n");
1028                     ASSERT(phdr_info[pi].p_memsz == phdr_info[pi].p_filesz);
1029                     /* Although adjust_elf() does not remove program-header entries,
1030                        we perform this update here because I've seen object files
1031                        whose PHDR table is bigger by one element than it should be.
1032                        Here we check and correct the size, if necessary.
1033                     */
1034                     if (phdr_info[pi].p_memsz != ehdr->e_phentsize * ehdr->e_phnum) {
1035                         ASSERT(phdr_info[pi].p_memsz > ehdr->e_phentsize * ehdr->e_phnum);
1036                         INFO("WARNING: PT_PHDR file and memory sizes are incorrect (%ld instead of %ld).  Correcting.\n",
1037                              (long)phdr_info[pi].p_memsz,
1038                              (long)(ehdr->e_phentsize * ehdr->e_phnum));
1039                         phdr_info[pi].p_memsz = ehdr->e_phentsize * ehdr->e_phnum;
1040                         phdr_info[pi].p_filesz = phdr_info[pi].p_memsz;
1041                     }
1042                 }
1043                 else {
1044
1045                     /*  Go over the section array and find which section's offset
1046                         field matches this program header's, and update the program
1047                         header's offset to refelect the new value.
1048                     */
1049                     Elf64_Off file_end, mem_end;
1050                     Elf64_Off new_phdr_offset =
1051                         section_to_header_mapping(elf, pi,
1052                                                   shdr_info, shdr_info_len,
1053                                                   &file_end,
1054                                                   &mem_end);
1055
1056                     /* Alignments of 0 and 1 mean nothing.  Higher alignments are
1057                        interpreted as powers of 2. */
1058                     if (phdr_info[pi].p_align > 1) {
1059                         INFO("\t\tapplying alignment of 0x%llx to new offset %lld\n",
1060                              phdr_info[pi].p_align,
1061                              new_phdr_offset);
1062                         new_phdr_offset &= ~(phdr_info[pi].p_align - 1);
1063                     }
1064
1065                     Elf32_Sxword delta = new_phdr_offset - phdr_info[pi].p_offset;
1066
1067                     INFO("\t\tnew offset %lld (was %lld)\n",
1068                          new_phdr_offset,
1069                          phdr_info[pi].p_offset);
1070
1071                     phdr_info[pi].p_offset = new_phdr_offset;
1072
1073                     INFO("\t\tnew vaddr 0x%llx (was 0x%llx)\n",
1074                          phdr_info[pi].p_vaddr + delta,
1075                          phdr_info[pi].p_vaddr);
1076                     phdr_info[pi].p_vaddr += delta;
1077
1078                     INFO("\t\tnew paddr 0x%llx (was 0x%llx)\n",
1079                          phdr_info[pi].p_paddr + delta,
1080                          phdr_info[pi].p_paddr);
1081                     phdr_info[pi].p_paddr += delta;
1082
1083                     INFO("\t\tnew mem size %lld (was %lld)\n",
1084                          mem_end - new_phdr_offset,
1085                          phdr_info[pi].p_memsz);
1086                     //phdr_info[pi].p_memsz = mem_end - new_phdr_offset;
1087                     phdr_info[pi].p_memsz = mem_end - phdr_info[pi].p_vaddr;
1088
1089                     INFO("\t\tnew file size %lld (was %lld)\n",
1090                          file_end - new_phdr_offset,
1091                          phdr_info[pi].p_filesz);
1092                     //phdr_info[pi].p_filesz = file_end - new_phdr_offset;
1093                     phdr_info[pi].p_filesz = file_end - phdr_info[pi].p_offset;
1094                 }
1095
1096                 FAILIF_LIBELF(gelf_update_phdr (newelf, pi, &phdr_info[pi]) == 0,
1097                               gelf_update_phdr);
1098             }
1099         }
1100
1101         if (dynamic_idx >= 0) {
1102             /* NOTE: dynamic_idx is the index of .dynamic section in the shdr_info[] array, NOT the
1103                index of the section in the ELF file!
1104             */
1105             adjust_dynamic_segment_offsets(elf, ebl,
1106                                            newelf,
1107                                            dynamic_idx,
1108                                            shdr_info,
1109                                            shdr_info_len);
1110         }
1111         else INFO("There is no dynamic section in this file.\n");
1112
1113         /* Walk the relocation sections (again).  This time, update offsets of the
1114            relocation entries.  Note that there is an implication here that the
1115            offsets are virual addresses, because we are handling a shared library!
1116         */
1117         for (cnt = 1; cnt < shdr_info_len; cnt++) {
1118             /* Note here that we process even those relocation sections that are
1119              * marked for removal.  Normally, we wouldn't need to do this, but
1120              * in the case where we run adjust_elf() after a dry run of
1121              * prelink() (see apriori), we still want to update the relocation
1122              * offsets because those will be picked up by the second run of
1123              * prelink(). If this all seems too cryptic, go yell at Iliyan
1124              * Malchev.
1125              */
1126             if (/* shdr_info[cnt].idx > 0 && */
1127                 (shdr_info[cnt].shdr.sh_type == SHT_REL ||
1128                  shdr_info[cnt].shdr.sh_type == SHT_RELA))
1129             {
1130                 int hacked = shdr_info[cnt].idx == 0;
1131                 Elf_Data *data;
1132                 if (hacked) {
1133                     /* This doesn't work!  elf_ndxscn(shdr_info[cnt].scn) will return the section number
1134                        of the new sectin that has moved into this slot. */
1135                     shdr_info[cnt].idx = elf_ndxscn(shdr_info[cnt].scn);
1136                     data = elf_getdata (elf_getscn (elf, shdr_info[cnt].idx), NULL);
1137                     INFO("PRELINKER HACK: Temporarily restoring index of to-be-removed section [%s] to %d.\n",
1138                          shdr_info[cnt].name,
1139                          shdr_info[cnt].idx);
1140                 }
1141                 else
1142                     data = elf_getdata (elf_getscn (newelf, shdr_info[cnt].idx), NULL);
1143
1144                 update_relocations_section_offsets(newelf, elf, ebl,
1145                                                    shdr_info, shdr_info_len,
1146                                                    shdr_info + cnt,
1147                                                    data,
1148                                                    old_section_ranges);
1149                 if (hacked) {
1150                     INFO("PRELINKER HACK: Done with hack, marking section [%s] for removal again.\n",
1151                          shdr_info[cnt].name);
1152                     shdr_info[cnt].idx = 0;
1153                 }
1154             }
1155         }
1156     }
1157
1158     /* Finally finish the ELF header.  Fill in the fields not handled by
1159        libelf from the old file. */
1160     {
1161         GElf_Ehdr *newehdr, newehdr_mem;
1162         newehdr = gelf_getehdr (newelf, &newehdr_mem);
1163         FAILIF_LIBELF(newehdr == NULL, gelf_getehdr);
1164
1165         INFO("Updating ELF header.\n");
1166
1167         memcpy (newehdr->e_ident, ehdr->e_ident, EI_NIDENT);
1168         newehdr->e_type    = ehdr->e_type;
1169         newehdr->e_machine = ehdr->e_machine;
1170         newehdr->e_version = ehdr->e_version;
1171         newehdr->e_entry   = ehdr->e_entry;
1172         newehdr->e_flags   = ehdr->e_flags;
1173         newehdr->e_phoff   = ehdr->e_phoff;
1174
1175         /* We need to position the section header table. */
1176         {
1177             const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
1178             newehdr->e_shoff = get_last_address(section_ranges);
1179             newehdr->e_shoff += offsize - 1;
1180             newehdr->e_shoff &= ~((GElf_Off) (offsize - 1));
1181             newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT);
1182             INFO("\tsetting section-header-table offset to %lld\n",
1183                  newehdr->e_shoff);
1184         }
1185
1186         if (rebuild_shstrtab) {
1187             /* If we are rebuilding the section-headers string table, then
1188                the new index must not be zero.  This is to guard against
1189                code breakage resulting from rebuild_shstrtab and shdridx
1190                somehow getting out of sync. */
1191             ASSERT(shdridx);
1192             /* The new section header string table index. */
1193             FAILIF(!(shdr_info[shdridx].idx < SHN_HIRESERVE) &&
1194                    likely (shdr_info[shdridx].idx != SHN_XINDEX),
1195                    "Can't handle extended section indices!\n");
1196         }
1197
1198         INFO("Index of shstrtab is now %d (was %d).\n",
1199              shdr_info[shdridx].idx,
1200              ehdr->e_shstrndx);
1201         newehdr->e_shstrndx = shdr_info[shdridx].idx;
1202
1203         FAILIF_LIBELF(gelf_update_ehdr(newelf, newehdr) == 0, gelf_update_ehdr);
1204     }
1205     if (section_ranges != NULL) destroy_range_list(section_ranges);
1206     destroy_range_list(old_section_ranges);
1207
1208 #ifdef DEBUG
1209     verify_elf (ehdr, shdr_info, shdr_info_len, phdr_info);
1210 #endif
1211
1212 }
1213
1214 static void update_hash_table(Elf *newelf, Elf *elf,
1215                               Elf32_Word hash_scn_idx,
1216                               shdr_info_t *symtab_info) {
1217     GElf_Shdr shdr_mem, *shdr = NULL;
1218     Elf32_Word *chain;
1219     Elf32_Word nbucket;
1220
1221     /* The hash table section and data in the new file. */
1222     Elf_Scn *hashscn = elf_getscn (newelf, hash_scn_idx);
1223     ASSERT(hashscn != NULL);
1224     Elf_Data *hashd = elf_getdata (hashscn, NULL);
1225     ASSERT (hashd != NULL);
1226     Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf; /* Sane arches first. */
1227
1228     /* The symbol table data. */
1229     Elf_Data *symd = elf_getdata (elf_getscn (newelf, symtab_info->idx), NULL);
1230     ASSERT (symd != NULL);
1231
1232     GElf_Ehdr ehdr_mem;
1233     GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
1234     FAILIF_LIBELF(NULL == ehdr, gelf_getehdr);
1235     size_t strshndx = symtab_info->old_shdr.sh_link;
1236     size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1237                                 ehdr->e_version);
1238
1239     /* Convert to the correct byte order. */
1240     FAILIF_LIBELF(gelf_xlatetom (newelf, hashd, hashd,
1241                                  BYTE_ORDER == LITTLE_ENDIAN
1242                                  ? ELFDATA2LSB : ELFDATA2MSB) == NULL,
1243                   gelf_xlatetom);
1244
1245     /* Adjust the nchain value.  The symbol table size changed.  We keep the
1246        same size for the bucket array. */
1247     INFO("hash table: buckets: %d (no change).\n", bucket[0]);
1248     INFO("hash table: chains: %d (was %d).\n",
1249          symd->d_size / elsize,
1250          bucket[1]);
1251     bucket[1] = symd->d_size / elsize;
1252     nbucket = bucket[0];
1253     bucket += 2;
1254     chain = bucket + nbucket;
1255
1256     /* New size of the section. */
1257     shdr = gelf_getshdr (hashscn, &shdr_mem);
1258     ASSERT(shdr->sh_type == SHT_HASH);
1259     shdr->sh_size = (2 + symd->d_size / elsize + nbucket) * sizeof (Elf32_Word);
1260     INFO("hash table: size %lld (was %d) bytes.\n",
1261          shdr->sh_size,
1262          hashd->d_size);
1263     hashd->d_size = shdr->sh_size;
1264     (void)gelf_update_shdr (hashscn, shdr);
1265
1266     /* Clear the arrays. */
1267     memset (bucket, '\0',
1268             (symd->d_size / elsize + nbucket)
1269             * sizeof (Elf32_Word));
1270
1271     size_t inner;
1272     for (inner = symtab_info->shdr.sh_info;
1273         inner < symd->d_size / elsize;
1274         ++inner) {
1275         const char *name;
1276         GElf_Sym sym_mem;
1277         GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
1278         ASSERT (sym != NULL);
1279
1280         name = elf_strptr (elf, strshndx, sym->st_name);
1281         ASSERT (name != NULL);
1282         size_t hidx = elf_hash (name) % nbucket;
1283
1284         if (bucket[hidx] == 0)
1285             bucket[hidx] = inner;
1286         else {
1287             hidx = bucket[hidx];
1288             while (chain[hidx] != 0)
1289                 hidx = chain[hidx];
1290             chain[hidx] = inner;
1291         }
1292     }
1293
1294     /* Convert back to the file byte order. */
1295     FAILIF_LIBELF(gelf_xlatetof (newelf, hashd, hashd,
1296                                  BYTE_ORDER == LITTLE_ENDIAN
1297                                  ? ELFDATA2LSB : ELFDATA2MSB) == NULL,
1298                   gelf_xlatetof);
1299 }
1300
1301 /* This function updates the symbol indices of relocation entries.  It does not
1302    update the section offsets of those entries.
1303 */
1304 static void update_relocations_section_symbol_references(
1305     Elf *newelf, Elf *elf __attribute__((unused)),
1306     shdr_info_t *info,
1307     int info_len __attribute__((unused)),
1308     shdr_info_t *relsect_info,
1309     Elf32_Word *newsymidx)
1310 {
1311     /* Get this relocation section's data */
1312     Elf_Data *d = elf_getdata (elf_getscn (newelf, relsect_info->idx), NULL);
1313     ASSERT (d != NULL);
1314     ASSERT (d->d_size == relsect_info->shdr.sh_size);
1315
1316     size_t old_nrels =
1317         relsect_info->old_shdr.sh_size / relsect_info->old_shdr.sh_entsize;
1318     size_t new_nrels =
1319         relsect_info->shdr.sh_size / relsect_info->shdr.sh_entsize;
1320
1321     size_t nrels = new_nrels;
1322     if (relsect_info->use_old_shdr_for_relocation_calculations) {
1323         nrels = old_nrels;
1324         /* Now, we update d->d_size to point to the old size in order to
1325            prevent gelf_update_rel() and gelf_update_rela() from returning
1326            an error.  We restore the value at the end of the function.
1327         */
1328         d->d_size = old_nrels * relsect_info->shdr.sh_entsize;
1329     }
1330
1331     /* Now, walk the relocations one by one.  For each relocation,
1332        check to see whether the symbol it refers to has a new
1333        index in the symbol table, and if so--update it.  We know
1334        if a symbol's index has changed when we look up that
1335        the newsymidx[] array at the old index.  If the value at that
1336        location is different from the array index, then the
1337        symbol's index has changed; otherwise, it remained the same.
1338     */
1339     INFO("Scanning %d relocation entries in section [%s] (taken from %s section header (old %d, new %d))...\n",
1340          nrels,
1341          relsect_info->name,
1342          (relsect_info->use_old_shdr_for_relocation_calculations ? "old" : "new"),
1343          old_nrels, new_nrels);
1344
1345     size_t relidx, newidx;
1346     if (relsect_info->shdr.sh_type == SHT_REL) {
1347         for (newidx = relidx = 0; relidx < nrels; ++relidx) {
1348             GElf_Rel rel_mem;
1349             FAILIF_LIBELF(gelf_getrel (d, relidx, &rel_mem) == NULL,
1350                           gelf_getrel);
1351             size_t symidx = GELF_R_SYM (rel_mem.r_info);
1352             if (newsymidx[symidx] != (Elf32_Word)-1)
1353             {
1354                 rel_mem.r_info = GELF_R_INFO (newsymidx[symidx],
1355                                               GELF_R_TYPE (rel_mem.r_info));
1356                 FAILIF_LIBELF(gelf_update_rel (d, newidx, &rel_mem) == 0,
1357                               gelf_update_rel);
1358                 newidx++;
1359             }
1360             else {
1361                 INFO("Discarding REL entry for symbol [%d], section [%d]\n",
1362                      symidx,
1363                      relsect_info->shdr.sh_info);
1364             }
1365         } /* for each rel entry... */
1366     } else {
1367         for (newidx = relidx = 0; relidx < nrels; ++relidx) {
1368             GElf_Rela rel_mem;
1369             FAILIF_LIBELF(gelf_getrela (d, relidx, &rel_mem) == NULL,
1370                           gelf_getrela);
1371             size_t symidx = GELF_R_SYM (rel_mem.r_info);
1372             if (newsymidx[symidx] != (Elf32_Word)-1)
1373             {
1374                 rel_mem.r_info
1375                 = GELF_R_INFO (newsymidx[symidx],
1376                                GELF_R_TYPE (rel_mem.r_info));
1377
1378                 FAILIF_LIBELF(gelf_update_rela (d, newidx, &rel_mem) == 0,
1379                               gelf_update_rela);
1380                 newidx++;
1381             }
1382             else {
1383                 INFO("Discarding RELA entry for symbol [%d], section [%d]\n",
1384                      symidx,
1385                      relsect_info->shdr.sh_info);
1386             }
1387         } /* for each rela entry... */
1388     } /* if rel else rela */
1389
1390     if (newidx != relidx)
1391     {
1392         INFO("Shrinking relocation section from %lld to %lld bytes (%d -> %d "
1393              "entries).\n",
1394              relsect_info->shdr.sh_size,
1395              relsect_info->shdr.sh_entsize * newidx,
1396              relidx,
1397              newidx);
1398
1399         d->d_size = relsect_info->shdr.sh_size =
1400             relsect_info->shdr.sh_entsize * newidx;
1401     } else INFO("Relocation section [%s]'s size (relocates: %s(%d), "
1402                 "symab: %s(%d)) does not change.\n",
1403                 relsect_info->name,
1404                 info[relsect_info->shdr.sh_info].name,
1405                 relsect_info->shdr.sh_info,
1406                 info[relsect_info->shdr.sh_link].name,
1407                 relsect_info->shdr.sh_link);
1408
1409     /* Restore d->d_size if necessary. */
1410     if (relsect_info->use_old_shdr_for_relocation_calculations)
1411         d->d_size = new_nrels * relsect_info->shdr.sh_entsize;
1412 }
1413
1414 static void update_relocations_section_offsets(Elf *newelf, Elf *elf __attribute((unused)),
1415                                                Ebl *ebl __attribute__((unused)),
1416                                                shdr_info_t *info,
1417                                                int info_len __attribute__((unused)),
1418                                                shdr_info_t *relsect_info,
1419                                                Elf_Data *d,
1420                                                range_list_t *old_section_ranges)
1421 {
1422     /* Get this relocation section's data */
1423     ASSERT (d != NULL);
1424     if (d->d_size != relsect_info->shdr.sh_size) {
1425         /* This is not necessarily a fatal error.  In the case where we call adjust_elf() from apriori
1426            (the prelinker), we may call this function for a relocation section that is marked for
1427            removal.  We still want to process this relocation section because, even though it is marked
1428            for removal, its relocatin entries will be used by the prelinker to know what to prelink.
1429            Once the prelinker is done, it will call adjust_elf() one more time to actually eliminate the
1430            relocation section. */
1431         PRINT("WARNING: section size according to section [%s]'s header is %lld, but according to data buffer is %ld.\n",
1432               relsect_info->name,
1433               relsect_info->shdr.sh_size,
1434               d->d_size);
1435         ASSERT((relsect_info->shdr.sh_type == SHT_REL || relsect_info->shdr.sh_type == SHT_RELA) &&
1436                relsect_info->use_old_shdr_for_relocation_calculations);
1437     }
1438
1439     size_t old_nrels =
1440         relsect_info->old_shdr.sh_size / relsect_info->old_shdr.sh_entsize;
1441     size_t new_nrels =
1442         relsect_info->shdr.sh_size / relsect_info->shdr.sh_entsize;
1443
1444     size_t nrels = new_nrels;
1445     if (relsect_info->use_old_shdr_for_relocation_calculations) {
1446         nrels = old_nrels;
1447         /* Now, we update d->d_size to point to the old size in order to
1448            prevent gelf_update_rel() and gelf_update_rela() from returning
1449            an error.  We restore the value at the end of the function.
1450         */
1451         d->d_size = old_nrels * relsect_info->shdr.sh_entsize;
1452     }
1453
1454     /* Now, walk the relocations one by one.  For each relocation,
1455        check to see whether the symbol it refers to has a new
1456        index in the symbol table, and if so--update it.  We know
1457        if a symbol's index has changed when we look up that
1458        the newsymidx[] array at the old index.  If the value at that
1459        location is different from the array index, then the
1460        symbol's index has changed; otherwise, it remained the same.
1461     */
1462     INFO("Scanning %d relocation entries in section [%s] (taken from %s section header (old %d, new %d))...\n",
1463          nrels,
1464          relsect_info->name,
1465          (relsect_info->use_old_shdr_for_relocation_calculations ? "old" : "new"),
1466          old_nrels, new_nrels);
1467
1468     if (relsect_info->old_shdr.sh_info == 0) {
1469         PRINT("WARNING: Relocation section [%s] relocates the NULL section.\n",
1470               relsect_info->name);
1471     }
1472     else {
1473         FAILIF(info[relsect_info->old_shdr.sh_info].idx == 0,
1474                "Section [%s] relocates section [%s] (index %d), which is being "
1475                "removed!\n",
1476                relsect_info->name,
1477                info[relsect_info->old_shdr.sh_info].name,
1478                relsect_info->old_shdr.sh_info);
1479     }
1480
1481     size_t relidx;
1482     FAILIF(relsect_info->shdr.sh_type == SHT_RELA,
1483            "Can't handle SHT_RELA relocation entries.\n");
1484
1485     if (relsect_info->shdr.sh_type == SHT_REL) {
1486         for (relidx = 0; relidx < nrels; ++relidx) {
1487             GElf_Rel rel_mem;
1488             FAILIF_LIBELF(gelf_getrel (d, relidx, &rel_mem) == NULL,
1489                           gelf_getrel);
1490
1491             range_t *old_range = find_range(old_section_ranges,
1492                                             rel_mem.r_offset);
1493 #if 1
1494             if (NULL == old_range) {
1495                 GElf_Sym *sym, sym_mem;
1496                 unsigned sym_idx = GELF_R_SYM(rel_mem.r_info);
1497                 /* relsect_info->shdr.sh_link is the index of the associated
1498                    symbol table. */
1499                 sym = gelf_getsymshndx(info[relsect_info->shdr.sh_link].data,
1500                                        NULL,
1501                                        sym_idx,
1502                                        &sym_mem,
1503                                        NULL);
1504                 /* info[relsect_info->shdr.sh_link].shdr.sh_link is the index
1505                    of the string table associated with the symbol table
1506                    associated with the relocation section rel_sect. */
1507                 const char *symname = elf_strptr(elf,
1508                                                  info[relsect_info->shdr.sh_link].shdr.sh_link,
1509                                                  sym->st_name);
1510
1511                 {
1512                     int i = 0;
1513                     INFO("ABOUT TO FAIL: old section ranges:\n");
1514
1515                     int num_ranges;
1516                     range_t *ranges = get_sorted_ranges(old_section_ranges, &num_ranges);
1517
1518                     for (; i < num_ranges; i++) {
1519                         shdr_info_t *inf = (shdr_info_t *)ranges[i].user;
1520                         INFO("\t[%8lld, %8lld] (%8lld bytes) [%8lld, %8lld] (%8lld bytes) [%-15s]\n",
1521                              ranges[i].start,
1522                              ranges[i].start + ranges[i].length,
1523                              ranges[i].length,
1524                              inf->old_shdr.sh_addr,
1525                              inf->old_shdr.sh_addr + inf->old_shdr.sh_size,
1526                              inf->old_shdr.sh_size,
1527                              inf->name);
1528                     }
1529                     INFO("\n");
1530                 }
1531
1532                 FAILIF(1,
1533                        "No range matches relocation entry value 0x%llx (%d) [%s]!\n",
1534                        rel_mem.r_offset,
1535                        rel_mem.r_offset,
1536                        symname);
1537             }
1538 #else
1539             FAILIF(NULL == old_range,
1540                    "No range matches relocation entry value 0x%llx!\n",
1541                    rel_mem.r_offset);
1542 #endif
1543             ASSERT(old_range->start <= rel_mem.r_offset &&
1544                    rel_mem.r_offset < old_range->start + old_range->length);
1545             ASSERT(old_range->user);
1546             shdr_info_t *old_range_info = (shdr_info_t *)old_range->user;
1547             ASSERT(old_range_info->idx > 0);
1548             if (relsect_info->old_shdr.sh_info &&
1549                 old_range_info->idx != relsect_info->old_shdr.sh_info) {
1550                 PRINT("Relocation offset 0x%llx does not match section [%s] "
1551                       "but section [%s]!\n",
1552                       rel_mem.r_offset,
1553                       info[relsect_info->old_shdr.sh_info].name,
1554                       old_range_info->name);
1555             }
1556
1557 #if 0 /* This is true only for shared libraries, but not for executables */
1558             ASSERT(old_range_info->shdr.sh_addr == old_range_info->shdr.sh_offset);
1559             ASSERT(old_range_info->old_shdr.sh_addr == old_range_info->old_shdr.sh_offset);
1560 #endif
1561             Elf64_Sxword delta =
1562                 old_range_info->shdr.sh_addr - old_range_info->old_shdr.sh_addr;
1563
1564             if (delta) {
1565                 extern int verbose_flag;
1566                 /* Print out some info about the relocation entry we are
1567                    modifying. */
1568                 if (unlikely(verbose_flag)) {
1569                     /* Get associated (new) symbol table. */
1570                     Elf64_Word symtab = relsect_info->shdr.sh_link;
1571                     /* Get the symbol that is being relocated. */
1572                     size_t symidx = GELF_R_SYM (rel_mem.r_info);
1573                     GElf_Sym sym_mem, *sym;
1574                     /* Since by now we've already updated the symbol index,
1575                        we need to retrieve the symbol from the new symbol table.
1576                     */
1577                     sym = gelf_getsymshndx (elf_getdata(info[symtab].newscn, NULL),
1578                                             NULL,
1579                                             symidx, &sym_mem, NULL);
1580                     FAILIF_LIBELF(NULL == sym, gelf_getsymshndx);
1581                     char buf[64];
1582                     INFO("\t%02d (%-15s) off 0x%llx -> 0x%llx (%lld) (relocates [%s:(%d)%s])\n",
1583                          (unsigned)GELF_R_TYPE(rel_mem.r_info),
1584                          ebl_reloc_type_name(ebl,
1585                                              GELF_R_TYPE(rel_mem.r_info),
1586                                              buf,
1587                                              sizeof(buf)),
1588                          rel_mem.r_offset, rel_mem.r_offset + delta, delta,
1589                          old_range_info->name,
1590                          symidx,
1591 #if ELF_STRPTR_IS_BROKEN
1592                          /* libelf does not keep track of changes very well.
1593                             Looks like, if you use elf_strptr() on a file that
1594                             has not been updated yet, you get bogus results. */
1595                          ((char *)info[info[symtab].old_shdr.sh_link].
1596                           newdata->d_buf) + sym->st_name
1597 #else
1598                          elf_strptr(newelf,
1599                                     info[symtab].shdr.sh_link,
1600                                     sym->st_name)
1601 #endif
1602                          );
1603                 } /* if (verbose_flag) */
1604
1605                 rel_mem.r_offset += delta;
1606                 FAILIF_LIBELF(gelf_update_rel (d, relidx, &rel_mem) == 0,
1607                               gelf_update_rel);
1608
1609 #ifdef ARM_SPECIFIC_HACKS
1610                 if (GELF_R_TYPE(rel_mem.r_info) == R_ARM_RELATIVE) {
1611                     FAILIF(GELF_R_SYM(rel_mem.r_info) != 0,
1612                            "Can't handle relocation!\n");
1613                     /* From the ARM documentation: "when the symbol is zero,
1614                        the R_ARM_RELATIVE entry resolves to the difference
1615                        between the address at which the segment being
1616                        relocated was loaded and the address at which it
1617                        was linked."
1618                     */
1619
1620                     int *ptr =
1621                         (int *)(((char *)old_range_info->newdata->d_buf) +
1622                                 (rel_mem.r_offset -
1623                                  old_range_info->shdr.sh_addr));
1624                     *ptr += (int)delta;
1625
1626                 }
1627 #endif
1628             } /* if (delta) */
1629         } /* for each rel entry... */
1630     }
1631
1632     /* Restore d->d_size if necessary. */
1633     if (relsect_info->use_old_shdr_for_relocation_calculations)
1634         d->d_size = new_nrels * relsect_info->shdr.sh_entsize;
1635 }
1636
1637 static inline
1638 Elf_Data *create_section_data(shdr_info_t *info, Elf_Scn *scn)
1639 {
1640     Elf_Data *newdata = NULL;
1641
1642     if (info->data == NULL) {
1643         info->data = elf_getdata (info->scn, NULL);
1644         FAILIF_LIBELF(NULL == info->data, elf_getdata);
1645         INFO("\t\tcopying data from original section (%d bytes).\n",
1646              info->data->d_size);
1647         /* Set the data.  This is done by copying from the old file. */
1648         newdata = elf_newdata (scn);
1649         FAILIF_LIBELF(newdata == NULL, elf_newdata);
1650         /* Copy the structure.  Note that the data buffer pointer gets
1651            copied, but the buffer itself does not. */
1652         *newdata = *info->data;
1653 #if COPY_SECTION_DATA_BUFFER
1654         if (info->data->d_buf != NULL) {
1655             newdata->d_buf = MALLOC(newdata->d_size);
1656             memcpy(newdata->d_buf, info->data->d_buf, newdata->d_size);
1657         }
1658 #endif
1659     } else {
1660         INFO("\t\tassigning new data to section (%d bytes).\n",
1661              info->data->d_size);
1662         newdata = info->data;
1663     }
1664
1665     info->newdata = newdata;
1666     return newdata;
1667 }
1668
1669 #if 0
1670 static void print_shdr_array(shdr_info_t *info, int num_entries) {
1671     extern int verbose_flag;
1672     if (verbose_flag) {
1673         int i;
1674         for (i = 0; i < num_entries; i++) {
1675             INFO("%03d:"
1676                  "\tname [%s]\n"
1677                  "\tidx  [%d]\n",
1678                  i, info[i].name, info[i].idx);
1679         }
1680     } /* if (verbose_flag) */
1681 }
1682 #endif
1683
1684 static size_t do_update_dyn_entry_address(Elf *elf,
1685                                           GElf_Dyn *dyn,
1686                                           shdr_info_t *shdr_info,
1687                                           int shdr_info_len,
1688                                           int newline)
1689 {
1690     size_t scnidx = 0;
1691     INFO("%#0*llx",
1692          gelf_getclass (elf) == ELFCLASS32 ? 10 : 18,
1693          dyn->d_un.d_val);
1694     for (scnidx = 1; scnidx < shdr_info_len; scnidx++) {
1695         if (shdr_info[scnidx].old_shdr.sh_addr == dyn->d_un.d_ptr) {
1696             if (shdr_info[scnidx].idx > 0) {
1697                 INFO(" (updating to 0x%08llx per section %d (shdr_info[] index %d): [%s])",
1698                      shdr_info[scnidx].shdr.sh_addr,
1699                      shdr_info[scnidx].idx,
1700                      scnidx,
1701                      shdr_info[scnidx].name);
1702                 dyn->d_un.d_ptr = shdr_info[scnidx].shdr.sh_addr;
1703                 break;
1704             }
1705             else {
1706                 /* FIXME:  This should be more intelligent.  What if there is more than one section that fits the
1707                            dynamic entry, and just the first such is being removed?  We should keep on searching here.
1708                 */
1709                 INFO(" (Setting to ZERO per section (shdr_info[] index %d) [%s], which is being removed)",
1710                      scnidx,
1711                      shdr_info[scnidx].name);
1712                 dyn->d_un.d_ptr = 0;
1713                 break;
1714             }
1715         }
1716     }
1717     if (newline) INFO("\n");
1718     return scnidx == shdr_info_len ? 0 : scnidx;
1719 }
1720
1721 static inline size_t update_dyn_entry_address(Elf *elf,
1722                                               GElf_Dyn *dyn,
1723                                               shdr_info_t *shdr_info,
1724                                               int shdr_info_len)
1725 {
1726     return do_update_dyn_entry_address(elf, dyn, shdr_info, shdr_info_len, 1);
1727 }
1728
1729 static void update_dyn_entry_address_and_size(Elf *elf, Ebl *oldebl,
1730                                               GElf_Dyn *dyn,
1731                                               shdr_info_t *shdr_info,
1732                                               int shdr_info_len,
1733                                               Elf_Data *dyn_data,
1734                                               size_t *dyn_size_entries,
1735                                               int dyn_entry_idx)
1736 {
1737     size_t scnidx = do_update_dyn_entry_address(elf, dyn,
1738                                                 shdr_info, shdr_info_len,
1739                                                 0);
1740     if (scnidx) {
1741         char buf[64];
1742         INFO(" (affects tag %s)",
1743              ebl_dynamic_tag_name(oldebl, dyn_entry_idx,
1744                                   buf, sizeof (buf)));
1745         if (dyn_size_entries[dyn_entry_idx]) {
1746             /* We previously encountered this size entry, and because
1747                we did not know which section would affect it, we saved its
1748                index in the dyn_size_entries[] array so that we can update
1749                the entry when we do know.  Now we know that the field
1750                shdr_info[scnidx].shdr.sh_size contains that new value.
1751             */
1752             GElf_Dyn *szdyn, szdyn_mem;
1753
1754             szdyn = gelf_getdyn (dyn_data,
1755                                  dyn_size_entries[dyn_entry_idx],
1756                                  &szdyn_mem);
1757             FAILIF_LIBELF(NULL == szdyn, gelf_getdyn);
1758             ASSERT(szdyn->d_tag == dyn_entry_idx);
1759
1760             INFO("\n (!)\t%-17s completing deferred update (%lld -> %lld bytes)"
1761                  " per section %d [%s]",
1762                  ebl_dynamic_tag_name (oldebl, szdyn->d_tag,
1763                                        buf, sizeof (buf)),
1764                  szdyn->d_un.d_val,
1765                  shdr_info[scnidx].shdr.sh_size,
1766                  shdr_info[scnidx].idx,
1767                  shdr_info[scnidx].name);
1768
1769             szdyn->d_un.d_val = shdr_info[scnidx].shdr.sh_size;
1770             FAILIF_LIBELF(0 == gelf_update_dyn(dyn_data,
1771                                                dyn_size_entries[dyn_entry_idx],
1772                                                szdyn),
1773                           gelf_update_dyn);
1774 #ifdef DEBUG
1775             dyn_size_entries[dyn_entry_idx] = -1;
1776 #endif
1777         }
1778         else dyn_size_entries[dyn_entry_idx] = scnidx;
1779     } /* if (scnidx) */
1780
1781     INFO("\n");
1782 }
1783
1784 static void do_build_dynamic_segment_strings(Elf *elf, Ebl *oldebl,
1785                                              int dynidx, /* index of .dynamic section */
1786                                              int symtabidx, /* index of symbol table section */
1787                                              shdr_info_t *shdr_info,
1788                                              int shdr_info_len __attribute__((unused)),
1789                                              bool print_strings_only)
1790 {
1791     Elf_Scn *dynscn = elf_getscn(elf, dynidx);
1792     FAILIF_LIBELF(NULL == dynscn, elf_getscn);
1793     Elf_Data *data = elf_getdata (dynscn, NULL);
1794     ASSERT(data != NULL);
1795
1796     size_t cnt;
1797
1798     if (!print_strings_only) {
1799       /* Allocate an array of string-offset structures. */
1800       shdr_info[dynidx].symse =
1801         (struct Ebl_Strent **)CALLOC(
1802                                      shdr_info[dynidx].shdr.sh_size/shdr_info[dynidx].shdr.sh_entsize,
1803                                      sizeof(struct Ebl_Strent *));
1804     }
1805
1806     for (cnt = 0;
1807          cnt < shdr_info[dynidx].shdr.sh_size/shdr_info[dynidx].shdr.sh_entsize;
1808          ++cnt)
1809     {
1810         char buf[64];
1811         GElf_Dyn dynmem;
1812         GElf_Dyn *dyn;
1813
1814         dyn = gelf_getdyn (data, cnt, &dynmem);
1815         FAILIF_LIBELF(NULL == dyn, gelf_getdyn);
1816
1817         switch (dyn->d_tag) {
1818         case DT_NEEDED:
1819         case DT_SONAME:
1820         case DT_RPATH:
1821         case DT_RUNPATH:
1822             {
1823                 const char *str =
1824                     elf_strptr (elf,
1825                                  shdr_info[dynidx].shdr.sh_link,
1826                                  dyn->d_un.d_val);
1827                 ASSERT(str != NULL);
1828                 INFO("\t\t\t%-17s: ",
1829                      ebl_dynamic_tag_name (oldebl,
1830                                            dyn->d_tag,
1831                                            buf, sizeof (buf)));
1832                 INFO("[%s] (offset %ld)\n", str, dyn->d_un.d_val);
1833                 if (!print_strings_only) {
1834                     /* We append the strings to the string table belonging to the
1835                        dynamic-symbol-table section.  We keep the dynsymst handle
1836                        for the strings section in the shdr_info[] entry for the
1837                        dynamic-sybmol table.  Confusing, I know.
1838                     */
1839                     ASSERT(shdr_info[symtabidx].dynsymst);
1840                     /* The string tables for the symbol table and the .dynamic
1841                        section must be the same.
1842                     */
1843                     ASSERT(shdr_info[symtabidx].shdr.sh_link ==
1844                            shdr_info[dynidx].shdr.sh_link);
1845                     shdr_info[dynidx].symse[cnt] =
1846                       ebl_strtabadd(shdr_info[symtabidx].dynsymst, str?:"", 0);
1847                     ASSERT(shdr_info[dynidx].symse[cnt] != NULL);
1848                 }
1849             }
1850             break;
1851         default:
1852             break;
1853         }
1854     } /* for (...) */
1855 } /* build_dynamic_segment_strings() */
1856
1857 static void build_dynamic_segment_strings(Elf *elf, Ebl *oldebl,
1858                                           int dynidx, /* index of .dynamic section */
1859                                           int symtabidx, /* index of symbol table section */
1860                                           shdr_info_t *shdr_info,
1861                                           int shdr_info_len __attribute__((unused)))
1862 {
1863     INFO("\t\tbuilding string offsets for dynamic section [%s], index %d\n",
1864          shdr_info[dynidx].name,
1865          dynidx);
1866     do_build_dynamic_segment_strings(elf, oldebl, dynidx, symtabidx,
1867                                      shdr_info, shdr_info_len, false);
1868 }
1869
1870 #ifdef DEBUG
1871 static void print_dynamic_segment_strings(Elf *elf, Ebl *oldebl,
1872                                           int dynidx, /* index of .dynamic section */
1873                                           int symtabidx, /* index of symbol table section */
1874                                           shdr_info_t *shdr_info,
1875                                           int shdr_info_len __attribute__((unused)))
1876 {
1877     INFO("\t\tprinting string offsets for dynamic section [%s], index %d\n",
1878          shdr_info[dynidx].name,
1879          dynidx);
1880     do_build_dynamic_segment_strings(elf, oldebl, dynidx, symtabidx,
1881                                      shdr_info, shdr_info_len, true);
1882 }
1883 #endif
1884
1885 static void adjust_dynamic_segment_offsets(Elf *elf, Ebl *oldebl,
1886                                            Elf *newelf,
1887                                            int dynidx, /* index of .dynamic section in shdr_info[] */
1888                                            shdr_info_t *shdr_info,
1889                                            int shdr_info_len)
1890 {
1891     Elf_Scn *scn = shdr_info[dynidx].newscn;
1892     FAILIF_LIBELF(NULL == scn, elf_getscn);
1893     Elf_Data *data = elf_getdata (scn, NULL);
1894     ASSERT(data != NULL);
1895
1896     size_t cnt;
1897     INFO("Updating dynamic section [%s], index %d\n",
1898          shdr_info[dynidx].name,
1899          dynidx);
1900
1901     size_t *dyn_size_entries = (size_t *)CALLOC(DT_NUM, sizeof(size_t));
1902
1903     ASSERT(data->d_type == ELF_T_DYN);
1904
1905     for (cnt = 0; cnt < shdr_info[dynidx].shdr.sh_size / shdr_info[dynidx].shdr.sh_entsize; ++cnt) {
1906         char buf[64];
1907         GElf_Dyn dynmem;
1908         GElf_Dyn *dyn;
1909
1910         dyn = gelf_getdyn (data, cnt, &dynmem);
1911         FAILIF_LIBELF(NULL == dyn, gelf_getdyn);
1912
1913         INFO("\t%-17s ",
1914              ebl_dynamic_tag_name (oldebl, dyn->d_tag, buf, sizeof (buf)));
1915
1916         switch (dyn->d_tag) {
1917         /* Updates to addresses */
1918
1919         /* We assume that the address entries come before the size entries.
1920         */
1921
1922         case DT_PLTGOT:
1923         case DT_HASH:
1924         case DT_SYMTAB:
1925             (void)update_dyn_entry_address(elf, dyn, shdr_info, shdr_info_len);
1926             break;
1927         case DT_STRTAB:
1928             /* Defer-update DT_STRSZ as well, if not already updated. */
1929             update_dyn_entry_address_and_size(elf, oldebl, dyn,
1930                                               shdr_info, shdr_info_len,
1931                                               data,
1932                                               dyn_size_entries,
1933                                               DT_STRSZ);
1934             break;
1935         case DT_RELA:
1936             /* Defer-update DT_RELASZ as well, if not already updated. */
1937             update_dyn_entry_address_and_size(elf, oldebl, dyn,
1938                                               shdr_info, shdr_info_len,
1939                                               data,
1940                                               dyn_size_entries,
1941                                               DT_RELASZ);
1942             break;
1943         case DT_REL:
1944             /* Defer-update DT_RELSZ as well, if not already updated. */
1945             update_dyn_entry_address_and_size(elf, oldebl, dyn,
1946                                               shdr_info, shdr_info_len,
1947                                               data,
1948                                               dyn_size_entries,
1949                                               DT_RELSZ);
1950             break;
1951         case DT_JMPREL:
1952             /* Defer-update DT_PLTRELSZ as well, if not already updated. */
1953             update_dyn_entry_address_and_size(elf, oldebl, dyn,
1954                                               shdr_info, shdr_info_len,
1955                                               data,
1956                                               dyn_size_entries,
1957                                               DT_PLTRELSZ);
1958             break;
1959         case DT_INIT_ARRAY:
1960         case DT_FINI_ARRAY:
1961         case DT_PREINIT_ARRAY:
1962         case DT_INIT:
1963         case DT_FINI:
1964              (void)update_dyn_entry_address(elf, dyn, shdr_info, shdr_info_len);
1965              break;
1966
1967         /* Updates to sizes */
1968         case DT_PLTRELSZ: /* DT_JMPREL or DT_PLTGOT */
1969         case DT_STRSZ:    /* DT_STRTAB */
1970         case DT_RELSZ:    /* DT_REL */
1971         case DT_RELASZ:   /* DR_RELA */
1972             if (dyn_size_entries[dyn->d_tag] == 0) {
1973                 /* We have not yet found the new size for this entry, so we
1974                    save the index of the dynamic entry in the dyn_size_entries[]
1975                    array.  When we find the section affecting this field (in
1976                    code above), we will update the entry.
1977                 */
1978                 INFO("(!) (deferring update: new value not known yet)\n");
1979                 dyn_size_entries[dyn->d_tag] = cnt;
1980             }
1981             else {
1982                 ASSERT(dyn_size_entries[dyn->d_tag] < shdr_info_len);
1983                 INFO("%lld (bytes) (updating to %lld bytes "
1984                      "per section %d [%s])\n",
1985                      dyn->d_un.d_val,
1986                      shdr_info[dyn_size_entries[dyn->d_tag]].shdr.sh_size,
1987                      shdr_info[dyn_size_entries[dyn->d_tag]].idx,
1988                      shdr_info[dyn_size_entries[dyn->d_tag]].name);
1989                 dyn->d_un.d_val =
1990                     shdr_info[dyn_size_entries[dyn->d_tag]].shdr.sh_size;
1991 #ifdef DEBUG
1992                 /* Clear the array so that we know we are done with it. */
1993                 dyn_size_entries[dyn->d_tag] = (size_t)-1;
1994 #endif
1995             }
1996             break;
1997         /* End of updates. */
1998
1999         case DT_NULL:
2000         case DT_DEBUG:
2001         case DT_BIND_NOW:
2002         case DT_TEXTREL:
2003             /* No further output.  */
2004             INFO("\n");
2005             break;
2006
2007             /* String-entry updates. */
2008         case DT_NEEDED:
2009         case DT_SONAME:
2010         case DT_RPATH:
2011         case DT_RUNPATH:
2012             if (shdr_info[dynidx].symse != NULL)
2013             {
2014                 Elf64_Xword new_offset =
2015                     ebl_strtaboffset(shdr_info[dynidx].symse[cnt]);
2016                 INFO("string [%s] offset changes: %lld -> %lld\n",
2017                      elf_strptr (elf,
2018                                  shdr_info[dynidx].shdr.sh_link,
2019                                  dyn->d_un.d_val),
2020                      dyn->d_un.d_val,
2021                      new_offset);
2022                 dyn->d_un.d_val = new_offset;
2023                 FAILIF_LIBELF(0 == gelf_update_dyn(data, cnt, dyn),
2024                               gelf_update_dyn);
2025             }
2026             else
2027                 INFO("string [%s] offset has not changed from %lld, not updating\n",
2028                      elf_strptr (elf,
2029                                  shdr_info[dynidx].shdr.sh_link,
2030                                  dyn->d_un.d_val),
2031                      dyn->d_un.d_val);
2032             break;
2033
2034         case DT_RELAENT:
2035         case DT_SYMENT:
2036         case DT_RELENT:
2037         case DT_PLTPADSZ:
2038         case DT_MOVEENT:
2039         case DT_MOVESZ:
2040         case DT_INIT_ARRAYSZ:
2041         case DT_FINI_ARRAYSZ:
2042         case DT_SYMINSZ:
2043         case DT_SYMINENT:
2044         case DT_GNU_CONFLICTSZ:
2045         case DT_GNU_LIBLISTSZ:
2046             INFO("%lld (bytes)\n", dyn->d_un.d_val);
2047             break;
2048
2049         case DT_VERDEFNUM:
2050         case DT_VERNEEDNUM:
2051         case DT_RELACOUNT:
2052         case DT_RELCOUNT:
2053             INFO("%lld\n", dyn->d_un.d_val);
2054             break;
2055
2056         case DT_PLTREL: /* Specifies whether PLTREL (same as JMPREL) has REL or RELA entries */
2057             INFO("%s (%d)\n", ebl_dynamic_tag_name (oldebl, dyn->d_un.d_val, NULL, 0), dyn->d_un.d_val);
2058             break;
2059
2060         default:
2061             INFO("%#0*llx\n",
2062                  gelf_getclass (elf) == ELFCLASS32 ? 10 : 18,
2063                  dyn->d_un.d_val);
2064             break;
2065         }
2066
2067         FAILIF_LIBELF(0 == gelf_update_dyn(data, cnt, dyn),
2068                       gelf_update_dyn);
2069     } /* for (...) */
2070
2071 #ifdef DEBUG
2072     if (1) {
2073         int i;
2074         for (i = 0; i < DT_NUM; i++)
2075             ASSERT((ssize_t)dyn_size_entries[i] <= 0);
2076     }
2077 #endif
2078
2079     FREE(dyn_size_entries);
2080 } /* adjust_dynamic_segment_offsets() */
2081
2082 static bool section_belongs_to_header(GElf_Shdr *shdr, GElf_Phdr *phdr)
2083 {
2084     if (shdr->sh_size) {
2085        /* Compare allocated sections by VMA, unallocated
2086           sections by file offset.  */
2087         if(shdr->sh_flags & SHF_ALLOC) {
2088             if(shdr->sh_addr >= phdr->p_vaddr
2089                && (shdr->sh_addr + shdr->sh_size
2090                    <= phdr->p_vaddr + phdr->p_memsz))
2091             {
2092                 return true;
2093             }
2094         }
2095         else {
2096             if (shdr->sh_offset >= phdr->p_offset
2097                 && (shdr->sh_offset + shdr->sh_size
2098                     <= phdr->p_offset + phdr->p_filesz))
2099             {
2100                 return true;
2101             }
2102         }
2103     }
2104
2105     return false;
2106 }
2107
2108 static Elf64_Off section_to_header_mapping(Elf *elf,
2109                                            int phdr_idx,
2110                                            shdr_info_t *shdr_info,
2111                                            int num_shdr_info,
2112                                            Elf64_Off *file_end,
2113                                            Elf64_Off *mem_end)
2114 {
2115     Elf64_Off start;
2116     GElf_Phdr phdr_mem;
2117     GElf_Phdr *phdr = gelf_getphdr (elf, phdr_idx, &phdr_mem);
2118     FAILIF_LIBELF(NULL == phdr, gelf_getphdr);
2119     size_t inner;
2120
2121     FAILIF(phdr->p_type == PT_GNU_RELRO,
2122            "Can't handle segments of type PT_GNU_RELRO!\n");
2123
2124     /* Iterate over the sections.  */
2125     start = (Elf64_Off)-1;
2126     *file_end = *mem_end = 0;
2127     INFO("\n\t\t");
2128     for (inner = 1; inner < num_shdr_info; ++inner)
2129     {
2130         if (shdr_info[inner].idx > 0) {
2131             /* Check to see the section is in the segment.  We use the old
2132                header because that header contains the old offset and length
2133                information about a section.
2134             */
2135             if (section_belongs_to_header(&shdr_info[inner].old_shdr, phdr))
2136             {
2137                 INFO("%-17s", shdr_info[inner].name);
2138 #define SECT_MEM_END(s) ((s).sh_addr + (s).sh_size)
2139                 if ((shdr_info[inner].shdr.sh_flags & SHF_ALLOC)) {
2140                     if (SECT_MEM_END(shdr_info[inner].shdr) > *mem_end) {
2141                         INFO("(mem_end 0x%llx --> 0x%llx) ", *mem_end, SECT_MEM_END(shdr_info[inner].shdr));
2142                         *mem_end = SECT_MEM_END(shdr_info[inner].shdr);
2143                     }
2144 #undef SECT_MEM_END
2145 #define SECT_FILE_END(s) ((s).sh_offset + (s).sh_size)
2146                     if (shdr_info[inner].shdr.sh_type != SHT_NOBITS) {
2147                         if (SECT_FILE_END(shdr_info[inner].shdr) > *file_end) {
2148                             INFO("(file_end 0x%llx --> 0x%llx) ", *file_end, SECT_FILE_END(shdr_info[inner].shdr));
2149                             *file_end = SECT_FILE_END(shdr_info[inner].shdr);
2150                         }
2151                     }
2152 #undef SECT_FILE_END
2153                     if (shdr_info[inner].shdr.sh_offset < start) {
2154                         start = shdr_info[inner].shdr.sh_offset;
2155                     }
2156                 } /* if section takes space */
2157                 INFO("\n\t\t");
2158             }
2159             else
2160               INFO("(!) %-17s does not match\n\t\t", shdr_info[inner].name);
2161         }
2162         else
2163           INFO("(!) %-17s is not considered, it is being removed\n\t\t", shdr_info[inner].name);
2164     }
2165
2166     /* Finish the line.  */
2167     INFO("start: %lld\n", start);
2168     INFO("\t\tends: %lld file, %lld mem\n", *file_end, *mem_end);
2169
2170     return start;
2171 }
2172
2173 static void
2174 update_symbol_values(Elf *elf, GElf_Ehdr *ehdr,
2175                      Elf *newelf __attribute__((unused)),
2176                      shdr_info_t *shdr_info,
2177                      int num_shdr_info,
2178                      int shady,
2179                      int dynamic_idx)
2180 {
2181     /* Scan the sections, looking for the symbol table. */
2182     size_t i;
2183     for (i = 1; i < num_shdr_info; i++) {
2184         if (shdr_info[i].idx > 0 &&
2185             (shdr_info[i].shdr.sh_type == SHT_SYMTAB ||
2186              shdr_info[i].shdr.sh_type == SHT_DYNSYM))
2187         {
2188             size_t inner;
2189             size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
2190             Elf_Data *symdata = shdr_info[i].newdata;
2191             /* shdr_info[i].old_shdr.sh_link is the index of the strings table
2192                in the old ELF file.  This index still points to the same section
2193                in the shdr_info[] array.  The idx field of that entry is that
2194                section's new index.  That index must, therefore, be equal to
2195                the new value of sh_link. */
2196             ASSERT(shdr_info[shdr_info[i].old_shdr.sh_link].idx ==
2197                    shdr_info[i].shdr.sh_link);
2198             ASSERT(shdr_info[shdr_info[i].old_shdr.sh_link].data);
2199
2200             INFO("\tupdating symbol values for section [%s]...\n",
2201                  shdr_info[i].name);
2202
2203 #if 1 /* DEBUG */
2204             {
2205                 Elf_Scn *symstrscn = elf_getscn(newelf,  shdr_info[i].shdr.sh_link);
2206                 ASSERT(symstrscn);
2207                 Elf_Data *symstrdata = elf_getdata(symstrscn, NULL);
2208                 ASSERT(symstrdata);
2209                 INFO("%d nonprintable\n",
2210                      dump_hex_buffer(stdout, symstrdata->d_buf, symstrdata->d_size, 0));
2211             }
2212 #endif
2213
2214             INFO("\tnumber of symbols to update: %d (%d bytes)\n",
2215                  symdata->d_size / elsize, symdata->d_size);
2216             for (inner = 0; inner < symdata->d_size / elsize; ++inner)
2217             {
2218                 GElf_Sym sym_mem;
2219                 GElf_Sym *sym;
2220                 size_t shnum;
2221                 FAILIF_LIBELF(elf_getshnum (elf, &shnum) < 0, elf_getshnum);
2222
2223                 sym = gelf_getsymshndx (symdata, NULL,
2224                                         inner, &sym_mem, NULL);
2225                 FAILIF_LIBELF(sym == NULL, gelf_getsymshndx);
2226
2227 #if 0 /* DEBUG */
2228                 if (shdr_info[i].shdr.sh_type == SHT_SYMTAB) {
2229                     PRINT("%8d: name %d info %02x other %02x shndx %d size %lld value %lld\n",
2230                           inner,
2231                           sym->st_info,
2232                           sym->st_name,
2233                           sym->st_other,
2234                           sym->st_shndx,
2235                           sym->st_size,
2236                           sym->st_value);
2237                 }
2238 #endif
2239
2240                 size_t scnidx = sym->st_shndx;
2241                 FAILIF(scnidx == SHN_XINDEX,
2242                        "Can't handle SHN_XINDEX!\n");
2243
2244                 char *symname = NULL;
2245                 {
2246 #if ELF_STRPTR_IS_BROKEN
2247                     Elf_Scn *symstrscn = elf_getscn(newelf,  shdr_info[i].shdr.sh_link);
2248                     ASSERT(symstrscn);
2249                     Elf_Data *symstrdata = elf_getdata(symstrscn, NULL);
2250                     ASSERT(symstrdata);
2251                     symname = symstrdata->d_buf + sym->st_name;
2252 #else
2253                     symname = elf_strptr(newelf,
2254                                          shdr_info[i].shdr.sh_link,
2255                                          sym->st_name);
2256 #endif
2257                 }
2258
2259                 extern int verbose_flag;
2260                 if (unlikely(verbose_flag))
2261                 {
2262                     int c, max = 40;
2263                     INFO("%-8d [", inner);
2264                     for (c=0; c<max-1; c++) {
2265                         if (symname[c]) {
2266                             INFO("%c", symname[c]);
2267                         }
2268                         else break;
2269                     }
2270                     if (c < max-1) {
2271                         while (c++ < max) INFO(" ");
2272                     }
2273                     else INFO("<");
2274                     INFO("]");
2275                 } /* if (unlikely(verbose_flag)) */
2276
2277                 /* Notice that shdr_info[] is an array whose indices correspond
2278                    to the section indices in the original ELF file.  Of those
2279                    sections, some have been discarded, and one is moved to the
2280                    end of the file--this is section .shstrtab.  Of course, no
2281                    symbol refers to this section, so it is safe for us to
2282                    address sections by their original indices in the
2283                    shdr_info[] array directly.
2284                 */
2285
2286                 /* Note that we do not skip over the STT_SECTION symbols. Since
2287                    they contain the addresses of sections, we update their
2288                    values as well.
2289                 */
2290                 if (scnidx == SHN_UNDEF) {
2291                     INFO("   undefined\n");
2292                     continue;
2293                 }
2294                 if (scnidx >= shnum ||
2295                     (scnidx >= SHN_LORESERVE &&
2296                      scnidx <= SHN_HIRESERVE))
2297                 {
2298                     INFO("   special (scn %d, value 0x%llx, size %lld)\n",
2299                          scnidx,
2300                          sym->st_value,
2301                          sym->st_size);
2302
2303                     /* We shouldn't be messing with these symbols, but they are
2304                        often absolute symbols that encode the starting address
2305                        or the ending address of some section.  As a heuristic,
2306                        we will check to see if the value of the symbol matches
2307                        the start or the end of any section, and if so, we will
2308                        update it, but only if --shady is enabled.
2309                     */
2310
2311                     if (shady && sym->st_value) {
2312                         size_t scnidx;
2313                         /* Is it the special symbol _DYNAMIC? */
2314                         if (!strcmp(symname, "_DYNAMIC")) {
2315                             /* The _DYNAMIC symbol points to the DYNAMIC
2316                                segment.  It is used by linker to bootstrap
2317                                itself. */
2318                             ASSERT(dynamic_idx >= 0);
2319                             PRINT("*** SHADY *** symbol %s: "
2320                                   "new st_value = %lld (was %lld), "
2321                                   "st_size = %lld (was %lld)\n",
2322                                   symname,
2323                                   shdr_info[dynamic_idx].shdr.sh_addr,
2324                                   sym->st_value,
2325                                   shdr_info[dynamic_idx].shdr.sh_size,
2326                                   sym->st_size);
2327                             sym->st_value =
2328                                 shdr_info[dynamic_idx].shdr.sh_addr;
2329                             sym->st_size  =
2330                                 shdr_info[dynamic_idx].shdr.sh_size;
2331                             /* NOTE: We don't update st_shndx, because this is a special
2332                                      symbol.  I am not sure if it's necessary though.
2333                             */
2334                             FAILIF_LIBELF(gelf_update_symshndx(symdata,
2335                                                                NULL,
2336                                                                inner,
2337                                                                sym,
2338                                                                0) == 0,
2339                                           gelf_update_symshndx);
2340                         }
2341                         else {
2342                             for (scnidx = 1; scnidx < num_shdr_info; scnidx++) {
2343                                 if (sym->st_value ==
2344                                     shdr_info[scnidx].old_shdr.sh_addr) {
2345                                     if (shdr_info[scnidx].shdr.sh_addr !=
2346                                         sym->st_value) {
2347                                         PRINT("*** SHADY *** symbol %s matches old "
2348                                               "start %lld of section %s, updating "
2349                                               "to %lld.\n",
2350                                               symname,
2351                                               shdr_info[scnidx].old_shdr.sh_addr,
2352                                               shdr_info[scnidx].name,
2353                                               shdr_info[scnidx].shdr.sh_addr);
2354                                         sym->st_value = shdr_info[scnidx].shdr.sh_addr;
2355                                     }
2356                                     break;
2357                                 }
2358                                 else {
2359                                     Elf64_Addr oldaddr =
2360                                         shdr_info[scnidx].old_shdr.sh_addr +
2361                                         shdr_info[scnidx].old_shdr.sh_size;
2362                                     if (sym->st_value == oldaddr) {
2363                                         Elf64_Addr newaddr =
2364                                             shdr_info[scnidx].shdr.sh_addr +
2365                                             shdr_info[scnidx].shdr.sh_size;
2366                                         if (newaddr != sym->st_value) {
2367                                             PRINT("*** SHADY *** symbol %s matches old "
2368                                                   "end %lld of section %s, updating "
2369                                                   "to %lld.\n",
2370                                                   symname,
2371                                                   oldaddr,
2372                                                   shdr_info[scnidx].name,
2373                                                   newaddr);
2374                                             sym->st_value = newaddr;
2375                                         }
2376                                         break;
2377                                     }
2378                                 }
2379                             } /* for each section... */
2380                             /* NOTE: We don't update st_shndx, because this is a special
2381                                      symbol.  I am not sure if it's necessary though.
2382                             */
2383                             if (scnidx < num_shdr_info) {
2384                                 FAILIF_LIBELF(gelf_update_symshndx(symdata,
2385                                                                    NULL,
2386                                                                    inner,
2387                                                                    sym,
2388                                                                    0) == 0,
2389                                               gelf_update_symshndx);
2390                             }
2391                         } /* if symbol is _DYNAMIC else */
2392                     }
2393
2394                     continue;
2395                 } /* handle special-section symbols */
2396
2397                 /* The symbol must refer to a section which is not being
2398                    removed. */
2399                 if(shdr_info[scnidx].idx == 0)
2400                 {
2401                     FAILIF(GELF_ST_TYPE (sym->st_info) != STT_SECTION,
2402                            "Non-STT_SECTION symbol [%s] refers to section [%s],"
2403                            " which is being removed.\n",
2404                            symname,
2405                            shdr_info[scnidx].name);
2406                     INFO("STT_SECTION symbol [%s] refers to section [%s], "
2407                          "which is being removed.  Skipping...\n",
2408                          symname,
2409                          shdr_info[scnidx].name);
2410                     continue;
2411                 }
2412
2413                 INFO("   %8d %-17s   ",
2414                      sym->st_shndx,
2415                      shdr_info[sym->st_shndx].name);
2416
2417                 /* Has the section's offset (hence its virtual address,