• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <common.h>
3 #include <debug.h>
4 #include <libelf.h>
5 #include <libebl.h>
6 #ifdef ARM_SPECIFIC_HACKS
7     #include <libebl_arm.h>
8 #endif/*ARM_SPECIFIC_HACKS*/
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 #include <hash.h>
19 #include <apriori.h>
20 #include <source.h>
21 #include <tweak.h>
22 #include <rangesort.h>
23 #include <prelink_info.h>
24 #include <prelinkmap.h>
25 #include <libgen.h>
26 
27 #ifndef ADJUST_ELF
28 #error "ADJUST_ELF must be defined!"
29 #endif
30 
31 /* When this macro is defined, apriori sets to ZERO those relocation values for
32    which it canot find the appropriate referent.
33 */
34 #define PERMISSIVE
35 #define COPY_SECTION_DATA_BUFFER (0)
36 /* When this macro is set to a nonzero value, we replace calls to elf_strptr()
37    on the target ELF handle with code that extracts the strings directly from
38    the data buffers of that ELF handle.  In this case, elf_strptr() does not
39    work as expected, as it tries to read the data buffer of the associated
40    string section directly from the file, and that buffer does not exist yet
41    in the file, since we haven't committed our changes yet.
42 */
43 #define ELF_STRPTR_IS_BROKEN     (1)
44 
45 /* When the macro below is defined, apriori does not mark for removal those
46    relocation sections that it fully handles.  Instead, apriori just sets their
47    sizes to zero.  This is more for debugging than of any actual use.
48 
49    This macro is meaningful only when ADJUST_ELF!=0
50 */
51 #define REMOVE_HANDLED_SECTIONS
52 
53 extern int verbose_flag;
54 
55 static source_t *sources = NULL;
56 
57 #if defined(DEBUG) && 0
58 
print_shdr(source_t * source,Elf_Scn * scn)59 static void print_shdr(source_t *source, Elf_Scn *scn)
60 {
61     GElf_Shdr shdr_mem, *shdr;
62     shdr = gelf_getshdr(scn, &shdr_mem);
63     Elf_Data *data = elf_getdata(scn, NULL);
64     INFO("\t%02d: data = %p, hdr = { offset = %8lld, size = %lld }, "
65          "data->d_buf = %p data->d_off = %lld, data->d_size = %d\n",
66          elf_ndxscn(scn),
67          data,
68          shdr->sh_offset, shdr->sh_size,
69          data->d_buf, data->d_off, data->d_size);
70 }
71 
print_shdr_idx(source_t * source,Elf * elf,int idx)72 static void print_shdr_idx(source_t *source, Elf *elf, int idx)
73 {
74     print_shdr(source, elf_getscn(elf, idx));
75 }
76 
print_shdrs(source_t * source)77 static void print_shdrs(source_t *source) {
78   Elf_Scn *scn = NULL;
79   INFO("section offset dump for new ELF\n");
80   while ((scn = elf_nextscn (source->elf, scn)) != NULL)
81     print_shdr(source, scn);
82 
83   INFO("\nsection offset dump for original ELF\n");
84   while ((scn = elf_nextscn (source->oldelf, scn)) != NULL)
85     print_shdr(source, scn);
86 
87 #if 0
88   {
89     INFO("section offset dump for new ELF\n");
90     int i = 0;
91     for (i = 0; i < source->shnum; i++) {
92       scn = elf_getscn(source->elf, i);
93       print_shdr(source, scn);
94     }
95   }
96 #endif
97 }
98 
99 #endif /* DEBUG */
100 
101 static char * find_file(const char *libname,
102                         char **lib_lookup_dirs,
103                         int num_lib_lookup_dirs);
104 
find_source(const char * name,char ** lib_lookup_dirs,int num_lib_lookup_dirs)105 static inline source_t* find_source(const char *name,
106                                     char **lib_lookup_dirs,
107                                     int num_lib_lookup_dirs) {
108     char *full = find_file(name, lib_lookup_dirs, num_lib_lookup_dirs);
109     if (full) {
110         source_t *trav = sources;
111         while (trav) {
112             if (!strcmp(trav->name, full))
113                 break;
114             trav = trav->next;
115         }
116         free(full);
117         return trav;
118     }
119     return NULL;
120 }
121 
add_to_sources(source_t * src)122 static inline void add_to_sources(source_t *src) {
123     src->next = sources;
124     sources = src;
125 }
126 
handle_range_error(range_error_t err,range_t * left,range_t * right)127 static void handle_range_error(range_error_t err,
128                                range_t *left, range_t *right) {
129     switch (err) {
130     case ERROR_CONTAINS:
131         ERROR("ERROR: section (%lld, %lld bytes) contains "
132               "section (%lld, %lld bytes)\n",
133               left->start, left->length,
134               right->start, right->length);
135         break;
136     case ERROR_OVERLAPS:
137         ERROR("ERROR: Section (%lld, %lld bytes) intersects "
138               "section (%lld, %lld bytes)\n",
139               left->start, left->length,
140               right->start, right->length);
141         break;
142     default:
143         ASSERT(!"Unknown range error code!");
144     }
145 
146     FAILIF(1, "Range error.\n");
147 }
148 
create_elf_sections(source_t * source,Elf * elf)149 static void create_elf_sections(source_t *source, Elf *elf)
150 {
151     INFO("Creating new ELF sections.\n");
152     ASSERT(elf == NULL || source->elf == NULL || source->elf == elf);
153     if (elf == NULL) {
154         ASSERT(source->elf != NULL);
155         elf = source->elf;
156     }
157 
158     int cnt = 1;
159     Elf_Scn *oldscn = NULL, *scn;
160     while ((oldscn = elf_nextscn (source->oldelf, oldscn)) != NULL) {
161         GElf_Shdr *oldshdr, oldshdr_mem;
162 
163         scn = elf_newscn(elf);
164         FAILIF_LIBELF(NULL == scn, elf_newscn);
165 
166         oldshdr = gelf_getshdr(oldscn, &oldshdr_mem);
167         FAILIF_LIBELF(NULL == oldshdr, gelf_getshdr);
168         /* Set the section header of the new section to be the same as the
169            headset of the old section by default. */
170         gelf_update_shdr(scn, oldshdr);
171 
172         /* Copy the section data */
173         Elf_Data *olddata = elf_getdata(oldscn, NULL);
174         FAILIF_LIBELF(NULL == olddata, elf_getdata);
175 
176         Elf_Data *data = elf_newdata(scn);
177         FAILIF_LIBELF(NULL == data, elf_newdata);
178         *data = *olddata;
179 #if COPY_SECTION_DATA_BUFFER
180         if (olddata->d_buf != NULL) {
181             data->d_buf = MALLOC(data->d_size);
182             memcpy(data->d_buf, olddata->d_buf, olddata->d_size);
183         }
184 #endif
185 
186         INFO("\tsection %02d: [%-30s] created\n",
187              cnt,
188              elf_strptr(source->oldelf,
189                         source->shstrndx,
190                         oldshdr->sh_name));
191 
192         if (ADJUST_ELF) {
193             ASSERT(source->shdr_info != NULL);
194             /* Create a new section. */
195             source->shdr_info[cnt].idx = cnt;
196             source->shdr_info[cnt].newscn = scn;
197             source->shdr_info[cnt].data = data;
198             source->shdr_info[cnt].
199                 use_old_shdr_for_relocation_calculations = 1;
200             INFO("\tsection [%s]  (old offset %lld, old size %lld) "
201                  "will have index %d (was %d).\n",
202                  source->shdr_info[cnt].name,
203                  source->shdr_info[cnt].old_shdr.sh_offset,
204                  source->shdr_info[cnt].old_shdr.sh_size,
205                  source->shdr_info[cnt].idx,
206                  elf_ndxscn(source->shdr_info[cnt].scn));
207             /* Same as the next assert */
208             ASSERT(elf_ndxscn (source->shdr_info[cnt].newscn) ==
209                    source->shdr_info[cnt].idx);
210         }
211 
212         ASSERT(elf_ndxscn(scn) == (size_t)cnt);
213         cnt++;
214     }
215 }
216 
217 /* This function sets up the shdr_info[] array of a source_t.  We call it only
218    when ADJUST_ELF is non-zero (i.e., support for adjusting an ELF file for
219    changes in sizes and numbers of relocation sections is compiled in.  Note
220    that setup_shdr_info() depends only on the information in source->oldelf,
221    not on source->elf.
222 */
223 
setup_shdr_info(source_t * source)224 static void setup_shdr_info(source_t *source)
225 {
226     if (ADJUST_ELF)
227     {
228         /* Allocate the section-header-info buffer. */
229         INFO("Allocating section-header info structure (%d) bytes...\n",
230              source->shnum * sizeof (shdr_info_t));
231 
232         source->shdr_info = (shdr_info_t *)CALLOC(source->shnum,
233                                                   sizeof (shdr_info_t));
234 
235         /* Mark the SHT_NULL section as handled. */
236         source->shdr_info[0].idx = 2;
237 
238         int cnt = 1;
239         Elf_Scn *oldscn = NULL;
240         while ((oldscn = elf_nextscn (source->oldelf, oldscn)) != NULL) {
241             /* Copy the section header */
242             ASSERT(elf_ndxscn(oldscn) == (size_t)cnt);
243 
244             /* Initialized the corresponding shdr_info entry */
245             {
246                 /* Mark the section with a non-zero index.  Later, when we
247                    decide to drop a section, we will set its idx to zero, and
248                    assign section numbers to the remaining sections.
249                 */
250                 source->shdr_info[cnt].idx = 1;
251 
252                 source->shdr_info[cnt].scn = oldscn;
253 
254                 /* NOTE: Here we pupulate the section-headset struct with the
255                          same values as the original section's.  After the
256                          first run of prelink(), we will update the sh_size
257                          fields of those sections that need resizing.
258                 */
259                 FAILIF_LIBELF(NULL ==
260                               gelf_getshdr(oldscn,
261                                            &source->shdr_info[cnt].shdr),
262                               gelf_getshdr);
263 
264                 /* Get the name of the section. */
265                 source->shdr_info[cnt].name =
266                     elf_strptr (source->oldelf, source->shstrndx,
267                                 source->shdr_info[cnt].shdr.sh_name);
268 
269                 INFO("\tname: %s\n", source->shdr_info[cnt].name);
270                 FAILIF(source->shdr_info[cnt].name == NULL,
271                        "Malformed file: section %d name is null\n",
272                        cnt);
273 
274                 /* Remember the shdr.sh_link value.  We need to remember this
275                    value for those sections that refer to other sections.  For
276                    example, we need to remember it for relocation-entry
277                    sections, because if we modify the symbol table that a
278                    relocation-entry section is relative to, then we need to
279                    patch the relocation section.  By the time we get to
280                    deciding whether we need to patch the relocation section, we
281                    will have overwritten its header's sh_link field with a new
282                    value.
283                 */
284                 source->shdr_info[cnt].old_shdr = source->shdr_info[cnt].shdr;
285                 INFO("\t\toriginal sh_link: %08d\n",
286                      source->shdr_info[cnt].old_shdr.sh_link);
287                 INFO("\t\toriginal sh_addr: %lld\n",
288                      source->shdr_info[cnt].old_shdr.sh_addr);
289                 INFO("\t\toriginal sh_offset: %lld\n",
290                      source->shdr_info[cnt].old_shdr.sh_offset);
291                 INFO("\t\toriginal sh_size: %lld\n",
292                      source->shdr_info[cnt].old_shdr.sh_size);
293 
294                 FAILIF(source->shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX,
295                        "Cannot handle sh_type SHT_SYMTAB_SHNDX!\n");
296                 FAILIF(source->shdr_info[cnt].shdr.sh_type == SHT_GROUP,
297                        "Cannot handle sh_type SHT_GROUP!\n");
298                 FAILIF(source->shdr_info[cnt].shdr.sh_type == SHT_GNU_versym,
299                        "Cannot handle sh_type SHT_GNU_versym!\n");
300             }
301 
302             cnt++;
303         } /* for each section */
304     } /* if (ADJUST_ELF) */
305 }
306 
init_elf(source_t * source,bool create_new_sections)307 static Elf * init_elf(source_t *source, bool create_new_sections)
308 {
309     Elf *elf;
310     if (source->output != NULL) {
311         if (source->output_is_dir) {
312             source->output_is_dir++;
313             char *dir = source->output;
314             int dirlen = strlen(dir);
315             /* The main() function maintains a pointer to source->output; it
316                frees the buffer after apriori() returns.
317             */
318             source->output = MALLOC(dirlen +
319                                     1 + /* slash */
320                                     strlen(source->name) +
321                                     1); /* null terminator */
322             strcpy(source->output, dir);
323             source->output[dirlen] = '/';
324             strcpy(source->output + dirlen + 1,
325                    basename(source->name));
326         }
327 
328         source->newelf_fd = open(source->output,
329                                  O_RDWR | O_CREAT,
330                                  0666);
331         FAILIF(source->newelf_fd < 0, "open(%s): %s (%d)\n",
332                source->output,
333                strerror(errno),
334                errno);
335         elf = elf_begin(source->newelf_fd, ELF_C_WRITE, NULL);
336         FAILIF_LIBELF(elf == NULL, elf_begin);
337     } else {
338         elf = elf_clone(source->oldelf, ELF_C_EMPTY);
339         FAILIF_LIBELF(elf == NULL, elf_clone);
340     }
341 
342     GElf_Ehdr *oldehdr = gelf_getehdr(source->oldelf, &source->old_ehdr_mem);
343     FAILIF_LIBELF(NULL == oldehdr, gelf_getehdr);
344 
345     /* Create new ELF and program headers for the elf file */
346     INFO("Creating empty ELF and program headers...\n");
347     FAILIF_LIBELF(gelf_newehdr (elf, gelf_getclass (source->oldelf)) == 0,
348                   gelf_newehdr);
349     FAILIF_LIBELF(oldehdr->e_type != ET_REL
350                   && gelf_newphdr (elf,
351                                    oldehdr->e_phnum) == 0,
352                   gelf_newphdr);
353 
354     /* Copy the elf header */
355     INFO("Copying ELF header...\n");
356     GElf_Ehdr *ehdr = gelf_getehdr(elf, &source->ehdr_mem);
357     FAILIF_LIBELF(NULL == ehdr, gelf_getehdr);
358     memcpy(ehdr, oldehdr, sizeof(GElf_Ehdr));
359     FAILIF_LIBELF(!gelf_update_ehdr(elf, ehdr), gelf_update_ehdr);
360 
361     /* Copy out the old program header: notice that if the ELF file does not
362        have a program header, this loop won't execute.
363     */
364     INFO("Copying ELF program header...\n");
365     {
366         int cnt;
367         source->phdr_info = (GElf_Phdr *)CALLOC(ehdr->e_phnum,
368                                                 sizeof(GElf_Phdr));
369         for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) {
370             INFO("\tRetrieving entry %d\n", cnt);
371             FAILIF_LIBELF(NULL ==
372                           gelf_getphdr(source->oldelf, cnt,
373                                        source->phdr_info + cnt),
374                           gelf_getphdr);
375             FAILIF_LIBELF(gelf_update_phdr (elf, cnt,
376                                             source->phdr_info + cnt) == 0,
377                           gelf_update_phdr);
378         }
379     }
380 
381     /* Copy the sections and the section headers. */
382     if (create_new_sections)
383     {
384         create_elf_sections(source, elf);
385     }
386 
387     /* The ELF library better follows our layout when this is not a
388        relocatable object file. */
389     elf_flagelf (elf, ELF_C_SET, (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0));
390 
391     return elf;
392 }
393 
lookup_shdr_info_by_new_section(source_t * source,const char * sname,Elf_Scn * newscn)394 static shdr_info_t *lookup_shdr_info_by_new_section(
395     source_t *source,
396     const char *sname,
397     Elf_Scn *newscn)
398 {
399     if (source->shdr_info == NULL) return NULL;
400     int cnt;
401     for (cnt = 0; cnt < source->shnum; cnt++) {
402         if (source->shdr_info[cnt].newscn == newscn) {
403             INFO("\t\tnew section at %p matches shdr_info[%d], "
404                  "section [%s]!\n",
405                  newscn,
406                  cnt,
407                  source->shdr_info[cnt].name);
408             FAILIF(strcmp(sname, source->shdr_info[cnt].name),
409                    "Matched section's name [%s] does not match "
410                    "looked-up section's name [%s]!\n",
411                    source->shdr_info[cnt].name,
412                    sname);
413             return source->shdr_info + cnt;
414         }
415     }
416     return NULL;
417 }
418 
do_init_source(source_t * source,unsigned base)419 static bool do_init_source(source_t *source, unsigned base)
420 {
421     /* Find various sections. */
422     size_t scnidx;
423     Elf_Scn *scn;
424     GElf_Shdr *shdr, shdr_mem;
425     source->sorted_sections = init_range_list();
426     INFO("Processing [%s]'s sections...\n", source->name);
427     for (scnidx = 1; scnidx < (size_t)source->shnum; scnidx++) {
428         INFO("\tGetting section index %d...\n", scnidx);
429         scn = elf_getscn(source->elf, scnidx);
430         if (NULL == scn) {
431             /* If we get an error from elf_getscn(), it means that a section
432                at the requested index does not exist.  This may happen when
433                we remove sections.  Since we do not update source->shnum
434                (we can't, since we need to know the original number of sections
435                to know source->shdr_info[]'s length), we will attempt to
436                retrieve a section for an index that no longer exists in the
437                new ELF file. */
438             INFO("\tThere is no section at index %d anymore, continuing.\n",
439                  scnidx);
440             continue;
441         }
442         shdr = gelf_getshdr(scn, &shdr_mem);
443         FAILIF_LIBELF(NULL == shdr, gelf_getshdr);
444 
445         /* We haven't modified the shstrtab section, and so shdr->sh_name
446            has the same value as before.  Thus we look up the name based
447            on the old ELF handle.  We cannot use shstrndx on the new ELF
448            handle because the index of the shstrtab section may have
449            changed (and calling elf_getshstrndx() returns the same section
450            index, so libelf can't handle thise ither).
451         */
452         const char *sname =
453           elf_strptr(source->oldelf, source->shstrndx, shdr->sh_name);
454         ASSERT(sname);
455 
456         INFO("\tAdding [%s] (%lld, %lld)...\n",
457              sname,
458              shdr->sh_addr,
459              shdr->sh_addr + shdr->sh_size);
460         if ((shdr->sh_flags & SHF_ALLOC) == SHF_ALLOC) {
461             add_unique_range_nosort(source->sorted_sections,
462                                     shdr->sh_addr,
463                                     shdr->sh_size,
464                                     scn,
465                                     handle_range_error,
466                                     NULL); /* no user-data destructor */
467         }
468 
469         if (shdr->sh_type == SHT_DYNSYM) {
470             source->symtab.scn = scn;
471             source->symtab.data = elf_getdata(scn, NULL);
472             FAILIF_LIBELF(NULL == source->symtab.data, elf_getdata);
473             memcpy(&source->symtab.shdr, shdr, sizeof(GElf_Shdr));
474             source->symtab.info = lookup_shdr_info_by_new_section(
475                 source, sname, scn);
476             ASSERT(source->shdr_info == NULL || source->symtab.info != NULL);
477 
478             /* The sh_link field of the section header of the symbol table
479                contains the index of the associated strings table. */
480             source->strtab.scn = elf_getscn(source->elf,
481                                             source->symtab.shdr.sh_link);
482             FAILIF_LIBELF(NULL == source->strtab.scn, elf_getscn);
483             FAILIF_LIBELF(NULL == gelf_getshdr(source->strtab.scn,
484                                                &source->strtab.shdr),
485                           gelf_getshdr);
486             source->strtab.data = elf_getdata(source->strtab.scn, NULL);
487             FAILIF_LIBELF(NULL == source->strtab.data, elf_getdata);
488             source->strtab.info = lookup_shdr_info_by_new_section(
489                 source,
490                 elf_strptr(source->oldelf, source->shstrndx,
491                            source->strtab.shdr.sh_name),
492                 source->strtab.scn);
493             ASSERT(source->shdr_info == NULL || source->strtab.info != NULL);
494         } else if (shdr->sh_type == SHT_DYNAMIC) {
495             source->dynamic.scn = scn;
496             source->dynamic.data = elf_getdata(scn, NULL);
497             FAILIF_LIBELF(NULL == source->dynamic.data, elf_getdata);
498             memcpy(&source->dynamic.shdr, shdr, sizeof(GElf_Shdr));
499             source->dynamic.info = lookup_shdr_info_by_new_section(
500                 source, sname, scn);
501             ASSERT(source->shdr_info == NULL || source->dynamic.info != NULL);
502         } else if (shdr->sh_type == SHT_HASH) {
503             source->hash.scn = scn;
504             source->hash.data = elf_getdata(scn, NULL);
505             FAILIF_LIBELF(NULL == source->hash.data, elf_getdata);
506             memcpy(&source->hash.shdr, shdr, sizeof(GElf_Shdr));
507             source->hash.info = lookup_shdr_info_by_new_section(
508                 source, sname, scn);
509             ASSERT(source->shdr_info == NULL || source->hash.info != NULL);
510         } else if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) {
511             if (source->num_relocation_sections ==
512                     source->relocation_sections_size) {
513                 source->relocation_sections_size += 5;
514                 source->relocation_sections =
515                 (section_info_t *)REALLOC(source->relocation_sections,
516                                           source->relocation_sections_size *
517                                           sizeof(section_info_t));
518             }
519             section_info_t *reloc =
520             source->relocation_sections + source->num_relocation_sections;
521             reloc->scn = scn;
522             reloc->info = lookup_shdr_info_by_new_section(source, sname, scn);
523             ASSERT(source->shdr_info == NULL || reloc->info != NULL);
524             reloc->data = elf_getdata(scn, NULL);
525             FAILIF_LIBELF(NULL == reloc->data, elf_getdata);
526             memcpy(&reloc->shdr, shdr, sizeof(GElf_Shdr));
527             source->num_relocation_sections++;
528         } else if (!strcmp(sname, ".bss")) {
529             source->bss.scn = scn;
530             source->bss.data = elf_getdata(scn, NULL);
531             source->bss.info = lookup_shdr_info_by_new_section(
532                 source, sname, scn);
533             ASSERT(source->shdr_info == NULL || source->bss.info != NULL);
534             /* The BSS section occupies no space in the ELF file. */
535             FAILIF_LIBELF(NULL == source->bss.data, elf_getdata)
536             FAILIF(NULL != source->bss.data->d_buf,
537                    "Enexpected: section [%s] has data!",
538                    sname);
539             memcpy(&source->bss.shdr, shdr, sizeof(GElf_Shdr));
540         }
541     }
542     sort_ranges(source->sorted_sections);
543 
544     source->unfinished =
545         (unfinished_relocation_t *)CALLOC(source->num_relocation_sections,
546                                           sizeof(unfinished_relocation_t));
547 
548     if (source->dynamic.scn == NULL) {
549         INFO("File [%s] does not have a dynamic section!\n", source->name);
550         /* If this is a static executable, we won't update anything. */
551         source->dry_run = 1;
552         return false;
553     }
554 
555     FAILIF(source->symtab.scn == NULL,
556            "File [%s] does not have a dynamic symbol table!\n",
557            source->name);
558     FAILIF(source->hash.scn == NULL,
559            "File [%s] does not have a hash table!\n",
560            source->name);
561     FAILIF(source->hash.shdr.sh_link != elf_ndxscn(source->symtab.scn),
562            "Hash points to section %d, not to %d as expected!\n",
563            source->hash.shdr.sh_link,
564            elf_ndxscn(source->symtab.scn));
565 
566     /* Now, find out how many symbols we have and allocate the array of
567        satisfied symbols.
568 
569        NOTE: We don't count the number of undefined symbols here; we will
570        iterate over the symbol table later, and count them then, when it is
571        more convenient.
572     */
573     size_t symsize = gelf_fsize (source->elf,
574                                  ELF_T_SYM,
575                                  1, source->elf_hdr.e_version);
576     ASSERT(symsize);
577 
578     source->num_syms = source->symtab.data->d_size / symsize;
579     source->base = (source->oldelf_hdr.e_type == ET_DYN) ? base : 0;
580     INFO("Relink base for [%s]: 0x%lx\n", source->name, source->base);
581     FAILIF(source->base == -1,
582            "Can't prelink [%s]: it's a shared library and you did not "
583            "provide a prelink address!\n",
584            source->name);
585 #ifdef SUPPORT_ANDROID_PRELINK_TAGS
586     FAILIF(source->prelinked && source->base != source->prelink_base,
587            "ERROR: file [%s] has already been prelinked for 0x%08lx.  "
588            "Cannot change to 0x%08lx!\n",
589            source->name,
590            source->prelink_base,
591            source->base);
592 #endif/*SUPPORT_ANDROID_PRELINK_TAGS*/
593 
594     return true;
595 }
596 
init_source(const char * full_path,const char * output,int is_file,int base,int dry_run)597 static source_t* init_source(const char *full_path,
598                              const char *output, int is_file,
599                              int base, int dry_run)
600 {
601     source_t *source = (source_t *)CALLOC(1, sizeof(source_t));
602 
603     ASSERT(full_path);
604     source->name = full_path;
605     source->output = output;
606     source->output_is_dir = !is_file;
607 
608     source->newelf_fd = -1;
609     source->elf_fd = -1;
610     INFO("Opening %s...\n", full_path);
611     source->elf_fd =
612         open(full_path, ((dry_run || output != NULL) ? O_RDONLY : O_RDWR));
613     FAILIF(source->elf_fd < 0, "open(%s): %s (%d)\n",
614            full_path,
615            strerror(errno),
616            errno);
617 
618 	FAILIF(fstat(source->elf_fd, &source->elf_file_info) < 0,
619 		   "fstat(%s(fd %d)): %s (%d)\n",
620 		   source->name,
621 		   source->elf_fd,
622 		   strerror(errno),
623 		   errno);
624 	INFO("File [%s]'s size is %lld bytes!\n",
625 		 source->name,
626 		 source->elf_file_info.st_size);
627 
628     INFO("Calling elf_begin(%s)...\n", full_path);
629 
630     source->oldelf =
631         elf_begin(source->elf_fd,
632                   (dry_run || output != NULL) ? ELF_C_READ : ELF_C_RDWR,
633                   NULL);
634     FAILIF_LIBELF(source->oldelf == NULL, elf_begin);
635 
636     /* libelf can recognize COFF and A.OUT formats, but we handle only ELF. */
637     if(elf_kind(source->oldelf) != ELF_K_ELF) {
638         ERROR("Input file %s is not in ELF format!\n", full_path);
639         return NULL;
640     }
641 
642     /* Make sure this is a shared library or an executable. */
643     {
644         INFO("Making sure %s is a shared library or an executable...\n",
645              full_path);
646         FAILIF_LIBELF(0 == gelf_getehdr(source->oldelf, &source->oldelf_hdr),
647                       gelf_getehdr);
648         FAILIF(source->oldelf_hdr.e_type != ET_DYN &&
649                source->oldelf_hdr.e_type != ET_EXEC,
650                "%s must be a shared library (elf type is %d, expecting %d).\n",
651                full_path,
652                source->oldelf_hdr.e_type,
653                ET_DYN);
654     }
655 
656 #ifdef SUPPORT_ANDROID_PRELINK_TAGS
657     /* First, check to see if the file has been prelinked. */
658     source->prelinked =
659         check_prelinked(source->name,
660                         source->oldelf_hdr.e_ident[EI_DATA] == ELFDATA2LSB,
661                         &source->prelink_base);
662     /* Note that in the INFO() below we need to use oldelf_hdr because we
663        haven't cloned the ELF file yet, and source->elf_hdr is not defined. */
664     if (source->prelinked) {
665         PRINT("%s [%s] is already prelinked at 0x%08lx!\n",
666               (source->oldelf_hdr.e_type == ET_EXEC ?
667                "Executable" : "Shared library"),
668               source->name,
669               source->prelink_base);
670         /* Force a dry run when the file has already been prelinked */
671         source->dry_run = dry_run = 1;
672     }
673     else {
674         INFO("%s [%s] is not prelinked!\n",
675              (source->oldelf_hdr.e_type == ET_EXEC ?
676               "Executable" : "Shared library"),
677              source->name);
678         source->dry_run = dry_run;
679     }
680 #endif/*SUPPORT_ANDROID_PRELINK_TAGS*/
681 
682     /* Get the index of the section-header-strings-table section. */
683     FAILIF_LIBELF(elf_getshstrndx (source->oldelf, &source->shstrndx) < 0,
684                   elf_getshstrndx);
685 
686     FAILIF_LIBELF(elf_getshnum (source->oldelf, (size_t *)&source->shnum) < 0,
687                   elf_getshnum);
688 
689     /* When we have a dry run, or when ADJUST_ELF is enabled, we use
690        source->oldelf for source->elf, because the former is mmapped privately,
691        so changes to it have no effect.  With ADJUST_ELF, the first run of
692        prelink() is a dry run.  We will reopen the elf file for write access
693        after that dry run, before we call adjust_elf. */
694 
695     source->elf = (ADJUST_ELF || source->dry_run) ?
696         source->oldelf : init_elf(source, ADJUST_ELF == 0);
697 
698     FAILIF_LIBELF(0 == gelf_getehdr(source->elf, &source->elf_hdr),
699                   gelf_getehdr);
700 #ifdef DEBUG
701     ASSERT(!memcmp(&source->oldelf_hdr,
702                    &source->elf_hdr,
703                    sizeof(source->elf_hdr)));
704 #endif
705 
706     /* Get the EBL handling.  The -g option is currently the only reason
707        we need EBL so dont open the backend unless necessary.  */
708     source->ebl = ebl_openbackend (source->elf);
709     FAILIF_LIBELF(NULL == source->ebl, ebl_openbackend);
710 #ifdef ARM_SPECIFIC_HACKS
711     FAILIF_LIBELF(0 != arm_init(source->elf, source->elf_hdr.e_machine,
712                                 source->ebl, sizeof(Ebl)),
713                   arm_init);
714 #endif/*ARM_SPECIFIC_HACKS*/
715 
716     add_to_sources(source);
717     if (do_init_source(source, base) == false) return NULL;
718     return source;
719 }
720 
721 /* complements do_init_source() */
do_destroy_source(source_t * source)722 static void do_destroy_source(source_t *source)
723 {
724     int cnt;
725     destroy_range_list(source->sorted_sections);
726     source->sorted_sections = NULL;
727     for (cnt = 0; cnt < source->num_relocation_sections; cnt++) {
728         FREEIF(source->unfinished[cnt].rels);
729         source->unfinished[cnt].rels = NULL;
730         source->unfinished[cnt].num_rels = 0;
731         source->unfinished[cnt].rels_size = 0;
732     }
733     if (source->jmprel.sections != NULL) {
734         destroy_range_list(source->jmprel.sections);
735         source->jmprel.sections = NULL;
736     }
737     if (source->rel.sections != NULL) {
738         destroy_range_list(source->rel.sections);
739         source->rel.sections = NULL;
740     }
741     FREE(source->unfinished); /* do_init_source() */
742     source->unfinished = NULL;
743     FREE(source->relocation_sections); /* do_init_source() */
744     source->relocation_sections = NULL;
745     source->num_relocation_sections = source->relocation_sections_size = 0;
746 }
747 
destroy_source(source_t * source)748 static void destroy_source(source_t *source)
749 {
750     /* Is this a little-endian ELF file? */
751     if (source->oldelf != source->elf) {
752         /* If it's a dynamic executable, this must not be a dry run. */
753         if (!source->dry_run && source->dynamic.scn != NULL)
754         {
755             FAILIF_LIBELF(elf_update(source->elf, ELF_C_WRITE) == -1,
756                           elf_update);
757         }
758         FAILIF_LIBELF(elf_end(source->oldelf), elf_end);
759     }
760     ebl_closebackend(source->ebl);
761     FAILIF_LIBELF(elf_end(source->elf), elf_end);
762     FAILIF(close(source->elf_fd) < 0, "Could not close file %s: %s (%d)!\n",
763            source->name, strerror(errno), errno);
764     FAILIF((source->newelf_fd >= 0) && (close(source->newelf_fd) < 0),
765            "Could not close output file: %s (%d)!\n", strerror(errno), errno);
766 
767 #ifdef SUPPORT_ANDROID_PRELINK_TAGS
768     if (!source->dry_run) {
769         if (source->dynamic.scn != NULL &&
770             source->elf_hdr.e_type != ET_EXEC)
771         {
772             /* For some reason, trying to write directly to source->elf_fd
773                causes a "bad file descriptor" error because of something libelf
774                does.  We just close the file descriptor and open a new one in
775                function setup_prelink_info() below. */
776             INFO("%s: setting up prelink tag at end of file.\n",
777                  source->output ? source->output : source->name);
778             setup_prelink_info(source->output ? source->output : source->name,
779                                source->elf_hdr.e_ident[EI_DATA] == ELFDATA2LSB,
780                                source->base);
781         }
782         else INFO("%s: executable, NOT setting up prelink tag.\n",
783                   source->name);
784     }
785 #endif/*SUPPORT_ANDROID_PRELINK_TAGS*/
786 
787     do_destroy_source(source);
788 
789     if (source->shstrtab_data != NULL)
790         FREEIF(source->shstrtab_data->d_buf); /* adjust_elf */
791 
792     FREE(source->lib_deps); /* list of library dependencies (process_file()) */
793     FREEIF(source->shdr_info); /* setup_shdr_info() */
794     FREEIF(source->phdr_info); /* init_elf() */
795     FREE(source->name); /* assigned to by init_source() */
796     /* If the output is a directory, in init_elf() we allocate a buffer where
797        we copy the directory, a slash, and the file name.  Here we free that
798        buffer.
799     */
800     if (source->output_is_dir > 1) {
801         FREE(source->output);
802     }
803     FREE(source); /* init_source() */
804 }
805 
reinit_source(source_t * source)806 static void reinit_source(source_t *source)
807 {
808     do_destroy_source(source);
809     do_init_source(source, source->base);
810 
811     {
812         /* We've gathered all the DT_DYNAMIC entries; now we need to figure
813            out which relocation sections fit in which range as described by
814            the entries.  Before we do so, however, we will populate the
815            jmprel and rel members of source, as well as their sizes.
816         */
817 
818         size_t dynidx, numdyn;
819         GElf_Dyn *dyn, dyn_mem;
820 
821         numdyn = source->dynamic.shdr.sh_size /
822             source->dynamic.shdr.sh_entsize;
823 
824         source->rel.idx = source->rel.sz_idx = -1;
825         source->jmprel.idx = source->jmprel.sz_idx = -1;
826         for (dynidx = 0; dynidx < numdyn; dynidx++) {
827             dyn = gelf_getdyn (source->dynamic.data,
828                                dynidx,
829                                &dyn_mem);
830             FAILIF_LIBELF(NULL == dyn, gelf_getdyn);
831             switch (dyn->d_tag)
832             {
833             case DT_NEEDED:
834                 break;
835             case DT_JMPREL:
836                 INFO("reinit_source: DT_JMPREL is at index %d, 0x%08llx.\n",
837                      dynidx, dyn->d_un.d_ptr);
838                 source->jmprel.idx = dynidx;
839                 source->jmprel.addr = dyn->d_un.d_ptr;
840                 break;
841             case DT_PLTRELSZ:
842                 INFO("reinit_source: DT_PLTRELSZ is at index %d, 0x%08llx.\n",
843                      dynidx, dyn->d_un.d_val);
844                 source->jmprel.sz_idx = dynidx;
845                 source->jmprel.size = dyn->d_un.d_val;
846                 break;
847             case DT_REL:
848                 INFO("reinit_source: DT_REL is at index %d, 0x%08llx.\n",
849                      dynidx, dyn->d_un.d_ptr);
850                 source->rel.idx = dynidx;
851                 source->rel.addr = dyn->d_un.d_ptr;
852                 break;
853             case DT_RELSZ:
854                 INFO("reinit_source: DT_RELSZ is at index %d, 0x%08llx.\n",
855                      dynidx, dyn->d_un.d_val);
856                 source->rel.sz_idx = dynidx;
857                 source->rel.size = dyn->d_un.d_val;
858                 break;
859             case DT_RELA:
860             case DT_RELASZ:
861                 FAILIF(1, "Can't handle DT_RELA and DT_RELASZ entries!\n");
862                 break;
863             } /* switch */
864         } /* for each dynamic entry... */
865     }
866 }
867 
hash_lookup_global_or_weak_symbol(source_t * lib,const char * symname,GElf_Sym * lib_sym_mem)868 static GElf_Sym *hash_lookup_global_or_weak_symbol(source_t *lib,
869                                                    const char *symname,
870                                                    GElf_Sym *lib_sym_mem)
871 {
872     int lib_symidx = hash_lookup(lib->elf,
873                                  lib->hash.data,
874                                  lib->symtab.data,
875                                  lib->strtab.data,
876                                  symname);
877 
878     GElf_Sym sym_mem;
879     if (SHN_UNDEF != lib_symidx) {
880         /* We found the symbol--now check to see if it is global
881            or weak.  If this is the case, then the symbol satisfies
882            the dependency. */
883         GElf_Sym *lib_sym = gelf_getsymshndx(lib->symtab.data,
884                                              NULL,
885                                              lib_symidx,
886                                              &sym_mem,
887                                              NULL);
888         FAILIF_LIBELF(NULL == lib_sym, gelf_getsymshndx);
889 #if ELF_STRPTR_IS_BROKEN
890         ASSERT(!strcmp(
891                    symname,
892                    ((char *)elf_getdata(elf_getscn(lib->elf,
893                                                    lib->symtab.shdr.sh_link),
894                                         NULL)->d_buf) +
895                    lib_sym->st_name));
896 #else
897         ASSERT(!strcmp(
898                    symname,
899                    elf_strptr(lib->elf, lib->symtab.shdr.sh_link,
900                               lib_sym->st_name)));
901 #endif
902         if (lib_sym->st_shndx != SHN_UNDEF &&
903             (GELF_ST_BIND(lib_sym->st_info) == STB_GLOBAL ||
904              GELF_ST_BIND(lib_sym->st_info) == STB_WEAK)) {
905             memcpy(lib_sym_mem, &sym_mem, sizeof(GElf_Sym));
906             return lib_sym;
907         }
908     }
909 
910     return NULL;
911 }
912 
lookup_symbol_in_dependencies(source_t * source,const char * symname,GElf_Sym * found_sym)913 static source_t *lookup_symbol_in_dependencies(source_t *source,
914                                                const char *symname,
915                                                GElf_Sym *found_sym)
916 {
917     source_t *sym_source = NULL; /* return value */
918 
919     /* This is an undefined symbol.  Go over the list of libraries
920        and look it up. */
921     size_t libidx;
922     int found = 0;
923     source_t *last_found = NULL;
924     for (libidx = 0; libidx < (size_t)source->num_lib_deps; libidx++) {
925         source_t *lib = source->lib_deps[libidx];
926         if (hash_lookup_global_or_weak_symbol(lib, symname, found_sym) != NULL)
927         {
928             sym_source = lib;
929             if (found) {
930                 if (found == 1) {
931                     found++;
932                     ERROR("ERROR: multiple definitions found for [%s:%s]!\n",
933                           source->name, symname);
934                     ERROR("\tthis definition     [%s]\n", lib->name);
935                 }
936                 ERROR("\tprevious definition [%s]\n", last_found->name);
937             }
938             last_found = lib;
939             if (!found) found = 1;
940         }
941     }
942 
943 #if ELF_STRPTR_IS_BROKEN
944     ASSERT(!sym_source ||
945            !strcmp(symname,
946                    (char *)(elf_getdata(elf_getscn(
947                                             sym_source->elf,
948                                             sym_source->symtab.shdr.sh_link),
949                                         NULL)->d_buf) +
950                    found_sym->st_name));
951 #else
952     ASSERT(!sym_source ||
953            !strcmp(symname,
954                    elf_strptr(sym_source->elf,
955                               sym_source->symtab.shdr.sh_link,
956                               found_sym->st_name)));
957 #endif
958 
959     return sym_source;
960 }
961 
do_prelink(source_t * source,Elf_Data * reloc_scn_data,int reloc_scn_entry_size,unfinished_relocation_t * unfinished,int locals_only,bool dry_run,char ** lib_lookup_dirs,int num_lib_lookup_dirs,char ** default_libs,int num_default_libs,int * num_unfinished_relocs)962 static int do_prelink(source_t *source,
963                       Elf_Data *reloc_scn_data,
964                       int reloc_scn_entry_size,
965                       unfinished_relocation_t *unfinished,
966                       int locals_only,
967                       bool dry_run,
968                       char **lib_lookup_dirs, int num_lib_lookup_dirs,
969                       char **default_libs, int num_default_libs,
970                       int *num_unfinished_relocs)
971 {
972     int num_relocations = 0;
973 
974     size_t num_rels;
975     num_rels = reloc_scn_data->d_size / reloc_scn_entry_size;
976 
977     INFO("\tThere are %d relocations.\n", num_rels);
978 
979     int rel_idx;
980     for (rel_idx = 0; rel_idx < (size_t)num_rels; rel_idx++) {
981         GElf_Rel *rel, rel_mem;
982 
983         //INFO("\tHandling relocation %d/%d\n", rel_idx, num_rels);
984 
985         rel = gelf_getrel(reloc_scn_data, rel_idx, &rel_mem);
986         FAILIF_LIBELF(rel == NULL, gelf_getrel);
987         GElf_Sym *sym = NULL, sym_mem;
988         unsigned sym_idx = GELF_R_SYM(rel->r_info);
989         source_t *sym_source = NULL;
990         /* found_sym points to found_sym_mem, when sym_source != NULL, and
991            to sym, when the sybmol is locally defined.  If the symbol is
992            not locally defined and sym_source == NULL, then sym is not
993            defined either. */
994         GElf_Sym *found_sym = NULL, found_sym_mem;
995         const char *symname = NULL;
996         int sym_is_local = 1;
997         if (sym_idx) {
998           sym = gelf_getsymshndx(source->symtab.data,
999                                  NULL,
1000                                  sym_idx,
1001                                  &sym_mem,
1002                                  NULL);
1003           FAILIF_LIBELF(NULL == sym, gelf_getsymshndx);
1004 #if ELF_STRPTR_IS_BROKEN
1005           symname =
1006               ((char *)source->strtab.data->d_buf) +
1007               sym->st_name;
1008 #else
1009           symname = elf_strptr(source->elf,
1010                                elf_ndxscn(source->strtab.scn),
1011                                sym->st_name);
1012 #endif
1013 
1014           /* If the symbol is defined and is either not in the BSS
1015              section, or if it is in the BSS then the relocation is
1016              not a copy relocation, then the symbol's source is this
1017              library (i.e., it is locally-defined).  Otherwise, the
1018              symbol is imported.
1019           */
1020 
1021           sym_is_local = 0;
1022           if (sym->st_shndx != SHN_UNDEF &&
1023               (source->bss.scn == NULL ||
1024                sym->st_shndx != elf_ndxscn(source->bss.scn) ||
1025 #ifdef ARM_SPECIFIC_HACKS
1026                GELF_R_TYPE(rel->r_info) != R_ARM_COPY
1027 #else
1028                1
1029 #endif
1030                ))
1031             {
1032               sym_is_local = 1;
1033             }
1034 
1035           if (sym_is_local) {
1036             INFO("\t\tSymbol [%s:%s] is defined locally.\n",
1037                  source->name,
1038                  symname);
1039             sym_source = source;
1040             found_sym = sym;
1041           }
1042           else if (!locals_only) {
1043             sym_source = lookup_symbol_in_dependencies(source,
1044                                                        symname,
1045                                                        &found_sym_mem);
1046 
1047             /* The symbol was not in the list of dependencies, which by
1048                itself is an error:  it means either that the symbol does
1049                not exist anywhere, or that the library which has the symbol
1050                has not been listed as a dependency in this library or
1051                executable. It could also mean (for a library) that the
1052                symbol is defined in the executable that links agsinst it,
1053                which is obviously not a good thing.  These are bad things,
1054                but they do happen, which is why we have the ability to
1055                provide a list of default dependencies, including
1056                executables. Here we check to see if the symbol has been
1057                defined in any of them.
1058             */
1059             if (NULL == sym_source) {
1060               INFO("\t\tChecking default dependencies...\n");
1061               int i;
1062               source_t *lib, *old_sym_source = NULL;
1063               int printed_initial_error = 0;
1064               for (i = 0; i < num_default_libs; i++) {
1065                 INFO("\tChecking in [%s].\n", default_libs[i]);
1066                 lib = find_source(default_libs[i],
1067                                   lib_lookup_dirs,
1068                                   num_lib_lookup_dirs);
1069                 FAILIF(NULL == lib,
1070                        "Can't find default library [%s]!\n",
1071                        default_libs[i]);
1072                 if (hash_lookup_global_or_weak_symbol(lib,
1073                                                       symname,
1074                                                       &found_sym_mem)) {
1075                   found_sym = &found_sym_mem;
1076                   sym_source = lib;
1077 #if ELF_STRPTR_IS_BROKEN
1078                   ASSERT(!strcmp(symname,
1079                                  (char *)(elf_getdata(
1080                                               elf_getscn(
1081                                                   sym_source->elf,
1082                                                   sym_source->symtab.
1083                                                       shdr.sh_link),
1084                                               NULL)->d_buf) +
1085                                  found_sym->st_name));
1086 #else
1087                   ASSERT(!strcmp(symname,
1088                                  elf_strptr(sym_source->elf,
1089                                             sym_source->symtab.shdr.sh_link,
1090                                             found_sym->st_name)));
1091 
1092 #endif
1093                   INFO("\tFound symbol [%s] in [%s]!\n",
1094                        symname, lib->name);
1095                   if (old_sym_source) {
1096                     if (printed_initial_error == 0) {
1097                       printed_initial_error = 1;
1098                       ERROR("Multiple definition of [%s]:\n"
1099                             "\t[%s]\n",
1100                             symname,
1101                             old_sym_source->name);
1102                     }
1103                     ERROR("\t[%s]\n", sym_source->name);
1104                   }
1105                   old_sym_source = sym_source;
1106                 } else {
1107                   INFO("\tCould not find symbol [%s] in default "
1108                        "lib [%s]!\n", symname, lib->name);
1109                 }
1110               }
1111               if (sym_source) {
1112                 ERROR("ERROR: Could not find [%s:%s] in dependent "
1113                       "libraries (but found in default [%s])!\n",
1114                       source->name,
1115                       symname,
1116                       sym_source->name);
1117               }
1118             } else {
1119               found_sym = &found_sym_mem;
1120               /* We found the symbol in a dependency library. */
1121               INFO("\t\tSymbol [%s:%s, value %lld] is imported from [%s]\n",
1122                    source->name,
1123                    symname,
1124                    found_sym->st_value,
1125                    sym_source->name);
1126             }
1127           } /* if symbol is defined in this library... */
1128 
1129           if (!locals_only) {
1130             /* If a symbol is weak and we haven't found it, then report
1131                an error.  We really need to find a way to set its value
1132                to zero.  The problem is that it needs to refer to some
1133                section. */
1134 
1135             FAILIF(NULL == sym_source &&
1136                    GELF_ST_BIND(sym->st_info) == STB_WEAK,
1137                    "Cannot handle weak symbols yet (%s:%s <- %s).\n",
1138                    source->name,
1139                    symname,
1140                    sym_source->name);
1141 #ifdef PERMISSIVE
1142             if (GELF_ST_BIND(sym->st_info) != STB_WEAK &&
1143                 NULL == sym_source) {
1144               ERROR("ERROR: Can't find symbol [%s:%s] in dependent or "
1145                     "default libraries!\n", source->name, symname);
1146             }
1147 #else
1148             FAILIF(GELF_ST_BIND(sym->st_info) != STB_WEAK &&
1149                    NULL == sym_source,
1150                    "Can't find symbol [%s:%s] in dependent or default "
1151                    "libraries!\n",
1152                    source->name,
1153                    symname);
1154 #endif
1155           } /* if (!locals_only) */
1156         }
1157 #if 0 // too chatty
1158         else
1159           INFO("\t\tno symbol is associated with this relocation\n");
1160 #endif
1161 
1162 
1163         // We prelink only local symbols when locals_only == 1.
1164 
1165         bool can_relocate = true;
1166         if (!sym_is_local &&
1167             (symname[0] == 'd' && symname[1] == 'l' && symname[2] != '\0' &&
1168              (!strcmp(symname + 2, "open") ||
1169               !strcmp(symname + 2, "close") ||
1170               !strcmp(symname + 2, "sym") ||
1171               !strcmp(symname + 2, "error")))) {
1172             INFO("********* NOT RELOCATING LIBDL SYMBOL [%s]\n", symname);
1173             can_relocate = false;
1174         }
1175 
1176         if (can_relocate && (sym_is_local || !locals_only))
1177         {
1178             GElf_Shdr shdr_mem; Elf_Scn *scn; Elf_Data *data;
1179             find_section(source, rel->r_offset, &scn, &shdr_mem, &data);
1180             unsigned *dest =
1181               (unsigned*)(((char *)data->d_buf) +
1182                           (rel->r_offset - shdr_mem.sh_addr));
1183             unsigned rel_type = GELF_R_TYPE(rel->r_info);
1184             char buf[64];
1185             INFO("\t\t%-15s ",
1186                  ebl_reloc_type_name(source->ebl,
1187                                      GELF_R_TYPE(rel->r_info),
1188                                      buf,
1189                                      sizeof(buf)));
1190 
1191             /* Section-name offsets do not change, so we use oldelf to get the
1192                strings.  This makes a difference in the second pass of the
1193                perlinker, after the call to adjust_elf, because
1194                source->shstrndx no longer contains the index of the
1195                section-header-strings table.
1196             */
1197             const char *sname = elf_strptr(
1198                 source->oldelf, source->shstrndx, shdr_mem.sh_name);
1199 
1200             switch (rel_type) {
1201             case R_ARM_JUMP_SLOT:
1202             case R_ARM_GLOB_DAT:
1203             case R_ARM_ABS32:
1204               ASSERT(data->d_buf != NULL);
1205               ASSERT(data->d_size >= rel->r_offset - shdr_mem.sh_addr);
1206 #ifdef PERMISSIVE
1207               if (sym_source == NULL) {
1208                 ERROR("ERROR: Permissive relocation "
1209                       "[%-15s] [%s:%s]: [0x%llx] = ZERO\n",
1210                       ebl_reloc_type_name(source->ebl,
1211                                           GELF_R_TYPE(rel->r_info),
1212                                           buf,
1213                                           sizeof(buf)),
1214                       sname,
1215                       symname,
1216                       rel->r_offset);
1217                 if (!dry_run)
1218                   *dest = 0;
1219               } else
1220 #endif
1221                 {
1222                   ASSERT(sym_source);
1223                   INFO("[%s:%s]: [0x%llx] = 0x%llx + 0x%lx\n",
1224                        sname,
1225                        symname,
1226                        rel->r_offset,
1227                        found_sym->st_value,
1228                        sym_source->base);
1229                   if (!dry_run)
1230                     *dest = found_sym->st_value + sym_source->base;
1231                 }
1232               num_relocations++;
1233               break;
1234             case R_ARM_RELATIVE:
1235               ASSERT(data->d_buf != NULL);
1236               ASSERT(data->d_size >= rel->r_offset - shdr_mem.sh_addr);
1237               FAILIF(sym != NULL,
1238                      "Unsupported RELATIVE form (symbol != 0)...\n");
1239               INFO("[%s:%s]: [0x%llx] = 0x%x + 0x%lx\n",
1240                    sname,
1241                    symname ?: "(symbol has no name)",
1242                    rel->r_offset, *dest, source->base);
1243               if (!dry_run)
1244                 *dest += source->base;
1245               num_relocations++;
1246               break;
1247             case R_ARM_COPY:
1248 #ifdef PERMISSIVE
1249               if (sym_source == NULL) {
1250                 ERROR("ERROR: Permissive relocation "
1251                       "[%-15s] [%s:%s]: NOT PERFORMING\n",
1252                       ebl_reloc_type_name(source->ebl,
1253                                           GELF_R_TYPE(rel->r_info),
1254                                           buf,
1255                                           sizeof(buf)),
1256                       sname,
1257                       symname);
1258               } else
1259 #endif
1260                 {
1261                   ASSERT(sym);
1262                   ASSERT(sym_source);
1263                   GElf_Shdr src_shdr_mem;
1264                   Elf_Scn *src_scn;
1265                   Elf_Data *src_data;
1266                   find_section(sym_source, found_sym->st_value,
1267                                &src_scn,
1268                                &src_shdr_mem,
1269                                &src_data);
1270                   INFO("Found [%s:%s (%lld)] in section [%s] .\n",
1271                        sym_source->name,
1272                        symname,
1273                        found_sym->st_value,
1274 #if ELF_STRPTR_IS_BROKEN
1275                        (((char *)elf_getdata(
1276                              elf_getscn(sym_source->elf,
1277                                         sym_source->shstrndx),
1278                              NULL)->d_buf) + src_shdr_mem.sh_name)
1279 #else
1280                        elf_strptr(sym_source->elf,
1281                                   sym_source->shstrndx,
1282                                   src_shdr_mem.sh_name)
1283 #endif
1284                       );
1285 
1286                   unsigned *src = NULL;
1287                   if (src_data->d_buf == NULL)
1288                     {
1289 #ifdef PERMISSIVE
1290                       if (sym_source->bss.scn == NULL ||
1291                           elf_ndxscn(src_scn) !=
1292                           elf_ndxscn(sym_source->bss.scn)) {
1293                         ERROR("ERROR: Permissive relocation (NULL source "
1294                               "not from .bss) [%-15s] [%s:%s]: "
1295                               "NOT PERFORMING\n",
1296                               ebl_reloc_type_name(source->ebl,
1297                                                   GELF_R_TYPE(rel->r_info),
1298                                                   buf,
1299                                                   sizeof(buf)),
1300                               sname,
1301                               symname);
1302                       }
1303 #endif
1304                     }
1305                   else {
1306                     ASSERT(src_data->d_size >=
1307                            found_sym->st_value - src_shdr_mem.sh_addr);
1308                     src = (unsigned*)(((char *)src_data->d_buf) +
1309                                       (found_sym->st_value -
1310                                        src_shdr_mem.sh_addr));
1311                   }
1312                   ASSERT(symname);
1313                   INFO("[%s:%s]: [0x%llx] <- [0x%llx] size %lld\n",
1314                        sname,
1315                        symname, rel->r_offset,
1316                        found_sym->st_value,
1317                        found_sym->st_size);
1318 
1319 #ifdef PERMISSIVE
1320                   if (src_data->d_buf != NULL ||
1321                       (sym_source->bss.scn != NULL &&
1322                        elf_ndxscn(src_scn) ==
1323                        elf_ndxscn(sym_source->bss.scn)))
1324 #endif/*PERMISSIVE*/
1325                     {
1326                       if (data->d_buf == NULL) {
1327                         INFO("Incomplete relocation [%-15s] of [%s:%s].\n",
1328                              ebl_reloc_type_name(source->ebl,
1329                                                  GELF_R_TYPE(rel->r_info),
1330                                                  buf,
1331                                                  sizeof(buf)),
1332                              sname,
1333                              symname);
1334                         FAILIF(unfinished == NULL,
1335                                "You passed unfinished as NULL expecting "
1336                                "to handle all relocations, "
1337                                "but at least one cannot be handled!\n");
1338                         if (unfinished->num_rels == unfinished->rels_size) {
1339                           unfinished->rels_size += 10;
1340                           unfinished->rels = (GElf_Rel *)REALLOC(
1341                               unfinished->rels,
1342                               unfinished->rels_size *
1343                               sizeof(GElf_Rel));
1344                         }
1345                         unfinished->rels[unfinished->num_rels++] = *rel;
1346                         num_relocations--;
1347                         (*num_unfinished_relocs)++;
1348                       }
1349                       else {
1350                         if (src_data->d_buf != NULL)
1351                           {
1352                             ASSERT(data->d_buf != NULL);
1353                             ASSERT(data->d_size >= rel->r_offset -
1354                                    shdr_mem.sh_addr);
1355                             if (!dry_run)
1356                               memcpy(dest, src, found_sym->st_size);
1357                           }
1358                         else {
1359                           ASSERT(src == NULL);
1360                           ASSERT(elf_ndxscn(src_scn) ==
1361                                  elf_ndxscn(sym_source->bss.scn));
1362                           if (!dry_run)
1363                             memset(dest, 0, found_sym->st_size);
1364                         }
1365                       }
1366                     }
1367                   num_relocations++;
1368                 }
1369               break;
1370             default:
1371               FAILIF(1, "Unknown relocation type %d!\n", rel_type);
1372             } // switch
1373         } // relocate
1374         else {
1375           INFO("\t\tNot relocating symbol [%s]%s\n",
1376                symname,
1377                (can_relocate ? ", relocating only locals" :
1378                 ", which is a libdl symbol"));
1379           FAILIF(unfinished == NULL,
1380                  "You passed unfinished as NULL expecting to handle all "
1381                  "relocations, but at least one cannot be handled!\n");
1382           if (unfinished->num_rels == unfinished->rels_size) {
1383               unfinished->rels_size += 10;
1384               unfinished->rels = (GElf_Rel *)REALLOC(
1385                   unfinished->rels,
1386                   unfinished->rels_size *
1387                   sizeof(GElf_Rel));
1388           }
1389           unfinished->rels[unfinished->num_rels++] = *rel;
1390           (*num_unfinished_relocs)++;
1391         }
1392     } // for each relocation entry
1393 
1394     return num_relocations;
1395 }
1396 
prelink(source_t * source,int locals_only,bool dry_run,char ** lib_lookup_dirs,int num_lib_lookup_dirs,char ** default_libs,int num_default_libs,int * num_unfinished_relocs)1397 static int prelink(source_t *source,
1398                    int locals_only,
1399                    bool dry_run,
1400                    char **lib_lookup_dirs, int num_lib_lookup_dirs,
1401                    char **default_libs, int num_default_libs,
1402                    int *num_unfinished_relocs)
1403 {
1404     INFO("Prelinking [%s] (number of relocation sections: %d)%s...\n",
1405          source->name, source->num_relocation_sections,
1406          (dry_run ? " (dry run)" : ""));
1407     int num_relocations = 0;
1408     int rel_scn_idx;
1409     for (rel_scn_idx = 0; rel_scn_idx < source->num_relocation_sections;
1410          rel_scn_idx++)
1411     {
1412         section_info_t *reloc_scn = source->relocation_sections + rel_scn_idx;
1413         unfinished_relocation_t *unfinished = source->unfinished + rel_scn_idx;
1414 
1415         /* We haven't modified the shstrtab section, and so shdr->sh_name has
1416            the same value as before.  Thus we look up the name based on the old
1417            ELF handle.  We cannot use shstrndx on the new ELF handle because
1418            the index of the shstrtab section may have changed (and calling
1419            elf_getshstrndx() returns the same section index, so libelf can't
1420            handle thise ither).
1421 
1422            If reloc_scn->info is available, we can assert that the
1423            section-name has not changed.  If this assertion fails,
1424            then we cannot use the elf_strptr() trick below to get
1425            the section name.  One solution would be to save it in
1426            the section_info_t structure.
1427         */
1428         ASSERT(reloc_scn->info == NULL ||
1429                reloc_scn->shdr.sh_name == reloc_scn->info->old_shdr.sh_name);
1430         const char *sname =
1431           elf_strptr(source->oldelf,
1432                      source->shstrndx,
1433                      reloc_scn->shdr.sh_name);
1434         ASSERT(sname != NULL);
1435 
1436         INFO("\n\tIterating relocation section [%s]...\n", sname);
1437 
1438         /* In general, the new size of the section differs from the original
1439            size of the section, because we can handle some of the relocations.
1440            This was communicated to adjust_elf, which modified the ELF file
1441            according to the new section sizes.  Now, when prelink() does the
1442            actual work of prelinking, it needs to know the original size of the
1443            relocation section so that it can see all of the original relocation
1444            entries!
1445         */
1446         size_t d_size = reloc_scn->data->d_size;
1447         if (reloc_scn->info != NULL &&
1448             reloc_scn->data->d_size != reloc_scn->info->old_shdr.sh_size)
1449         {
1450             INFO("Setting size of section [%s] to from new size %d to old "
1451                  "size %lld temporarily (so prelinker can see all "
1452                  "relocations).\n",
1453                  reloc_scn->info->name,
1454                  d_size,
1455                  reloc_scn->info->old_shdr.sh_size);
1456             reloc_scn->data->d_size = reloc_scn->info->old_shdr.sh_size;
1457         }
1458 
1459         num_relocations +=
1460           do_prelink(source,
1461                      reloc_scn->data, reloc_scn->shdr.sh_entsize,
1462                      unfinished,
1463                      locals_only, dry_run,
1464                      lib_lookup_dirs, num_lib_lookup_dirs,
1465                      default_libs, num_default_libs,
1466                      num_unfinished_relocs);
1467 
1468         if (reloc_scn->data->d_size != d_size)
1469         {
1470             ASSERT(reloc_scn->info != NULL);
1471             INFO("Resetting size of section [%s] to %d\n",
1472                  reloc_scn->info->name,
1473                  d_size);
1474             reloc_scn->data->d_size = d_size;
1475         }
1476     }
1477 
1478     /* Now prelink those relocation sections which were fully handled, and
1479        therefore removed.  They are not a part of the
1480        source->relocation_sections[] array anymore, but we can find them by
1481        scanning source->shdr_info[] and looking for sections with idx == 0.
1482     */
1483 
1484     if (ADJUST_ELF && source->shdr_info != NULL) {
1485         /* Walk over the shdr_info[] array to see if we've removed any
1486            relocation sections.  prelink() those sections as well.
1487         */
1488         int i;
1489         for (i = 0; i < source->shnum; i++) {
1490             shdr_info_t *info = source->shdr_info + i;
1491             if (info->idx == 0 &&
1492                 (info->shdr.sh_type == SHT_REL ||
1493                  info->shdr.sh_type == SHT_RELA)) {
1494 
1495               Elf_Data *data = elf_getdata(info->scn, NULL);
1496               ASSERT(data->d_size == 0);
1497               data->d_size = info->old_shdr.sh_size;
1498 
1499               INFO("\n\tIterating relocation section [%s], which was "
1500                    "discarded (size %d, entry size %lld).\n",
1501                    info->name,
1502                    data->d_size,
1503                    info->old_shdr.sh_entsize);
1504 
1505               num_relocations +=
1506                 do_prelink(source,
1507                            data, info->old_shdr.sh_entsize,
1508                            NULL, /* the section was fully handled */
1509                            locals_only, dry_run,
1510                            lib_lookup_dirs, num_lib_lookup_dirs,
1511                            default_libs, num_default_libs,
1512                            num_unfinished_relocs);
1513 
1514               data->d_size = 0;
1515             }
1516         }
1517     }
1518     return num_relocations;
1519 }
1520 
find_file(const char * libname,char ** lib_lookup_dirs,int num_lib_lookup_dirs)1521 static char * find_file(const char *libname,
1522                         char **lib_lookup_dirs,
1523                         int num_lib_lookup_dirs) {
1524     if (libname[0] == '/') {
1525         /* This is an absolute path name--just return it. */
1526         /* INFO("ABSOLUTE PATH: [%s].\n", libname); */
1527         return strdup(libname);
1528     } else {
1529         /* First try the working directory. */
1530         int fd;
1531         if ((fd = open(libname, O_RDONLY)) > 0) {
1532             close(fd);
1533             /* INFO("FOUND IN CURRENT DIR: [%s].\n", libname); */
1534             return strdup(libname);
1535         } else {
1536             /* Iterate over all library paths.  For each path, append the file
1537                name and see if there is a file at that place. If that fails,
1538                bail out. */
1539 
1540             char *name;
1541             while (num_lib_lookup_dirs--) {
1542                 size_t lib_len = strlen(*lib_lookup_dirs);
1543                 /* one extra character for the slash, and another for the
1544                    terminating NULL. */
1545                 name = (char *)MALLOC(lib_len + strlen(libname) + 2);
1546                 strcpy(name, *lib_lookup_dirs);
1547                 name[lib_len] = '/';
1548                 strcpy(name + lib_len + 1, libname);
1549                 if ((fd = open(name, O_RDONLY)) > 0) {
1550                     close(fd);
1551                     /* INFO("FOUND: [%s] in [%s].\n", libname, name); */
1552                     return name;
1553                 }
1554                 INFO("NOT FOUND: [%s] in [%s].\n", libname, name);
1555                 free(name);
1556             }
1557         }
1558     }
1559     return NULL;
1560 }
1561 
adjust_dynamic_segment_entry_size(source_t * source,dt_rel_info_t * dyn)1562 static void adjust_dynamic_segment_entry_size(source_t *source,
1563                                               dt_rel_info_t *dyn)
1564 {
1565     /* Update the size entry in the DT_DYNAMIC segment. */
1566     GElf_Dyn *dyn_entry, dyn_entry_mem;
1567     dyn_entry = gelf_getdyn(source->dynamic.data,
1568                             dyn->sz_idx,
1569                             &dyn_entry_mem);
1570     FAILIF_LIBELF(NULL == dyn_entry, gelf_getdyn);
1571     /* If we are calling this function to adjust the size of the dynamic entry,
1572        then there should be some unfinished relocations remaining.  If there
1573        are none, then we should remove the entry from the dynamic section
1574        altogether.
1575     */
1576     ASSERT(dyn->num_unfinished_relocs);
1577 
1578     size_t relsize = gelf_fsize(source->elf,
1579                                 ELF_T_REL,
1580                                 1,
1581                                 source->elf_hdr.e_version);
1582 
1583     if (unlikely(verbose_flag)) {
1584         char buf[64];
1585         INFO("Updating entry %d: [%-10s], %08llx --> %08x\n",
1586              dyn->sz_idx,
1587              ebl_dynamic_tag_name (source->ebl, dyn_entry->d_tag,
1588                                    buf, sizeof (buf)),
1589              dyn_entry->d_un.d_val,
1590              dyn->num_unfinished_relocs * relsize);
1591     }
1592 
1593     dyn_entry->d_un.d_val = dyn->num_unfinished_relocs * relsize;
1594 
1595     FAILIF_LIBELF(!gelf_update_dyn(source->dynamic.data,
1596                                    dyn->sz_idx,
1597                                    dyn_entry),
1598                   gelf_update_dyn);
1599 }
1600 
adjust_dynamic_segment_entries(source_t * source)1601 static void adjust_dynamic_segment_entries(source_t *source)
1602 {
1603     /* This function many remove entries from the dynamic segment, but it won't
1604        resize the relevant section.  It'll just fill the remainted with empty
1605        DT entries.
1606 
1607        FIXME: This is not guaranteed right now.  If a dynamic segment does not
1608        end with null DT entries, I think this will break.
1609     */
1610     FAILIF(source->rel.processed,
1611            "More than one section matches DT_REL entry in dynamic segment!\n");
1612     FAILIF(source->jmprel.processed,
1613            "More than one section matches DT_JMPREL entry in "
1614            "dynamic segment!\n");
1615     source->rel.processed =
1616       source->jmprel.processed = 1;
1617 
1618     if (source->rel.num_unfinished_relocs > 0)
1619         adjust_dynamic_segment_entry_size(source, &source->rel);
1620 
1621     if (source->jmprel.num_unfinished_relocs > 0)
1622         adjust_dynamic_segment_entry_size(source, &source->jmprel);
1623 
1624     /* If at least one of the entries is empty, then we need to remove it.  We
1625        have already adjusted the size of the other.
1626     */
1627     if (source->rel.num_unfinished_relocs == 0 ||
1628         source->jmprel.num_unfinished_relocs == 0)
1629     {
1630         /* We need to delete the DT_REL/DT_RELSZ and DT_PLTREL/DT_PLTRELSZ
1631            entries from the dynamic segment. */
1632 
1633         GElf_Dyn *dyn_entry, dyn_entry_mem;
1634         size_t dynidx, updateidx;
1635 
1636         size_t numdyn =
1637             source->dynamic.shdr.sh_size /
1638             source->dynamic.shdr.sh_entsize;
1639 
1640         for (updateidx = dynidx = 0; dynidx < numdyn; dynidx++)
1641         {
1642             dyn_entry = gelf_getdyn(source->dynamic.data,
1643                                     dynidx,
1644                                     &dyn_entry_mem);
1645             FAILIF_LIBELF(NULL == dyn_entry, gelf_getdyn);
1646             if ((source->rel.num_unfinished_relocs == 0 &&
1647                  (dynidx == source->rel.idx ||
1648                   dynidx == source->rel.sz_idx)) ||
1649                 (source->jmprel.num_unfinished_relocs == 0 &&
1650                  (dynidx == source->jmprel.idx ||
1651                   dynidx == source->jmprel.sz_idx)))
1652             {
1653                 if (unlikely(verbose_flag)) {
1654                     char buf[64];
1655                     INFO("\t(!)\tRemoving entry %02d: [%-10s], %08llx\n",
1656                          dynidx,
1657                          ebl_dynamic_tag_name (source->ebl, dyn_entry->d_tag,
1658                                                buf, sizeof (buf)),
1659                          dyn_entry->d_un.d_val);
1660                 }
1661                 continue;
1662             }
1663 
1664             if (unlikely(verbose_flag)) {
1665                 char buf[64];
1666                 INFO("\t\tKeeping  entry %02d: [%-10s], %08llx\n",
1667                      dynidx,
1668                      ebl_dynamic_tag_name (source->ebl, dyn_entry->d_tag,
1669                                            buf, sizeof (buf)),
1670                      dyn_entry->d_un.d_val);
1671             }
1672 
1673             gelf_update_dyn(source->dynamic.data,
1674                             updateidx,
1675                             &dyn_entry_mem);
1676             updateidx++;
1677         }
1678     }
1679 } /* adjust_dynamic_segment_entries */
1680 
adjust_dynamic_segment_for(source_t * source,dt_rel_info_t * dyn,bool adjust_section_size_only)1681 static bool adjust_dynamic_segment_for(source_t *source,
1682                                        dt_rel_info_t *dyn,
1683                                        bool adjust_section_size_only)
1684 {
1685     bool dropped_sections = false;
1686 
1687     /* Go over the sections that belong to this dynamic range. */
1688     dyn->num_unfinished_relocs = 0;
1689     if (dyn->sections) {
1690         int num_scns, idx;
1691         range_t *scns = get_sorted_ranges(dyn->sections, &num_scns);
1692 
1693         INFO("\tdynamic range %s:[%lld, %lld) contains %d sections.\n",
1694              source->name,
1695              dyn->addr,
1696              dyn->addr + dyn->size,
1697              num_scns);
1698 
1699         ASSERT(scns);
1700         int next_idx = 0, next_rel_off = 0;
1701         /* The total number of unfinished relocations for this dynamic
1702          * entry. */
1703         section_info_t *next = (section_info_t *)scns[next_idx].user;
1704         section_info_t *first = next;
1705         ASSERT(first);
1706         for (idx = 0; idx < num_scns; idx++) {
1707             section_info_t *reloc_scn = (section_info_t *)scns[idx].user;
1708             size_t rel_scn_idx = reloc_scn - source->relocation_sections;
1709             ASSERT(rel_scn_idx < (size_t)source->num_relocation_sections);
1710             unfinished_relocation_t *unfinished =
1711                 &source->unfinished[rel_scn_idx];
1712             int unf_idx;
1713 
1714             ASSERT(reloc_scn->info == NULL ||
1715                    reloc_scn->shdr.sh_name ==
1716                    reloc_scn->info->old_shdr.sh_name);
1717             const char *sname =
1718               elf_strptr(source->oldelf,
1719                          source->shstrndx,
1720                          reloc_scn->shdr.sh_name);
1721 
1722             INFO("\tsection [%s] contains %d unfinished relocs.\n",
1723                  sname,
1724                  unfinished->num_rels);
1725 
1726             for (unf_idx = 0; unf_idx < unfinished->num_rels; unf_idx++)
1727             {
1728                 /* There are unfinished relocations.  Copy them forward to the
1729                    lowest section we can. */
1730 
1731                 while (next_rel_off ==
1732                        (int)(next->shdr.sh_size/next->shdr.sh_entsize))
1733                 {
1734                     INFO("\tsection [%s] has filled up with %d unfinished "
1735                          "relocs.\n",
1736                          sname,
1737                          next_rel_off);
1738 
1739                     next_idx++;
1740                     ASSERT(next_idx <= idx);
1741                     next = (section_info_t *)scns[next_idx].user;
1742                     next_rel_off = 0;
1743                 }
1744 
1745                 if (!adjust_section_size_only) {
1746                     INFO("\t\tmoving unfinished relocation %2d to [%s:%d]\n",
1747                          unf_idx,
1748                          sname,
1749                          next_rel_off);
1750                     FAILIF_LIBELF(0 ==
1751                                   gelf_update_rel(next->data,
1752                                                   next_rel_off,
1753                                                   &unfinished->rels[unf_idx]),
1754                                   gelf_update_rel);
1755                 }
1756 
1757                 next_rel_off++;
1758                 dyn->num_unfinished_relocs++;
1759             }
1760         } /* for */
1761 
1762         /* Set the size of the last section, and mark all subsequent
1763            sections for removal.  At this point, next is the section
1764            to which we last wrote data, next_rel_off is the offset before
1765            which we wrote the last relocation, and so next_rel_off *
1766            relsize is the new size of the section.
1767         */
1768 
1769         bool adjust_file = ADJUST_ELF && source->elf_hdr.e_type != ET_EXEC;
1770         if (adjust_file && !source->dry_run)
1771         {
1772             size_t relsize = gelf_fsize(source->elf,
1773                                         ELF_T_REL,
1774                                         1,
1775                                         source->elf_hdr.e_version);
1776 
1777             ASSERT(next->info == NULL ||
1778                    next->shdr.sh_name == next->info->old_shdr.sh_name);
1779             const char *sname =
1780               elf_strptr(source->oldelf,
1781                          source->shstrndx,
1782                          next->shdr.sh_name);
1783 
1784             INFO("\tsection [%s] (index %d) has %d unfinished relocs, "
1785                  "changing its size to %ld bytes (from %ld bytes).\n",
1786                  sname,
1787                  elf_ndxscn(next->scn),
1788                  next_rel_off,
1789                  (long)(next_rel_off * relsize),
1790                  (long)(next->shdr.sh_size));
1791 
1792             /* source->shdr_info[] must be allocated prior to calling this
1793                function.  This is in fact done in process_file(), by calling
1794                setup_shdr_info() just before we call adjust_dynamic_segment().
1795             */
1796             ASSERT(source->shdr_info != NULL);
1797 
1798             /* We do not update the data field of shdr_info[], because it does
1799                not exist yet (with ADJUST_ELF != 0).  We create the new section
1800                and section data after the first call to prelink().  For now, we
1801                save the results of our analysis by modifying the sh_size field
1802                of the section header.  When we create the new sections' data,
1803                we set the size of the data from the sh_size fields of the
1804                section headers.
1805 
1806                NOTE: The assertion applies only to the first call of
1807                      adjust_dynamic_segment (which calls this function).  By
1808                      the second call, we've already created the data for the
1809                      new sections.  The only sections for which we haven't
1810                      created data are the relocation sections we are removing.
1811             */
1812 #ifdef DEBUG
1813             ASSERT((!adjust_section_size_only &&
1814                     (source->shdr_info[elf_ndxscn(next->scn)].idx > 0)) ||
1815                    source->shdr_info[elf_ndxscn(next->scn)].data == NULL);
1816 #endif
1817 
1818             //FIXME: what else do we need to do here?  Do we need to update
1819             //       another copy of the shdr so that it's picked up when we
1820             //       commit the file?
1821             next->shdr.sh_size = next_rel_off * relsize;
1822             source->shdr_info[elf_ndxscn(next->scn)].shdr.sh_size =
1823                 next->shdr.sh_size;
1824             if (next_rel_off * relsize == 0) {
1825 #ifdef REMOVE_HANDLED_SECTIONS
1826                 INFO("\tsection [%s] (index %d) is now empty, marking for "
1827                      "removal.\n",
1828                      sname,
1829                      elf_ndxscn(next->scn));
1830                 source->shdr_info[elf_ndxscn(next->scn)].idx = 0;
1831                 dropped_sections = true;
1832 #endif
1833             }
1834 
1835             while (++next_idx < num_scns) {
1836                 next = (section_info_t *)scns[next_idx].user;
1837 #ifdef REMOVE_HANDLED_SECTIONS
1838                 ASSERT(next->info == NULL ||
1839                        next->shdr.sh_name == next->info->old_shdr.sh_name);
1840                 const char *sname =
1841                   elf_strptr(source->oldelf,
1842                              source->shstrndx,
1843                              next->shdr.sh_name);
1844                 INFO("\tsection [%s] (index %d) is now empty, marking for "
1845                      "removal.\n",
1846                      sname,
1847                      elf_ndxscn(next->scn));
1848                 /* mark for removal */
1849                 source->shdr_info[elf_ndxscn(next->scn)].idx = 0;
1850                 dropped_sections = true;
1851 #endif
1852             }
1853         }
1854 
1855     } /* if (dyn->sections) */
1856     else {
1857         /* The dynamic entry won't have any sections when it itself doesn't
1858            exist.  This could happen when we remove all relocation sections
1859            from a dynamic entry because we have managed to handle all
1860            relocations in them.
1861         */
1862         INFO("\tNo section for dynamic entry!\n");
1863     }
1864 
1865     return dropped_sections;
1866 }
1867 
adjust_dynamic_segment(source_t * source,bool adjust_section_size_only)1868 static bool adjust_dynamic_segment(source_t *source,
1869                                    bool adjust_section_size_only)
1870 {
1871     bool dropped_section;
1872     INFO("Adjusting dynamic segment%s.\n",
1873          (adjust_section_size_only ? " (section sizes only)" : ""));
1874     INFO("\tadjusting dynamic segment REL.\n");
1875     dropped_section =
1876         adjust_dynamic_segment_for(source, &source->rel,
1877                                    adjust_section_size_only);
1878     INFO("\tadjusting dynamic segment JMPREL.\n");
1879     dropped_section =
1880         adjust_dynamic_segment_for(source, &source->jmprel,
1881                                    adjust_section_size_only) ||
1882         dropped_section;
1883     if (!adjust_section_size_only)
1884         adjust_dynamic_segment_entries(source);
1885     return dropped_section;
1886 }
1887 
match_relocation_sections_to_dynamic_ranges(source_t * source)1888 static void match_relocation_sections_to_dynamic_ranges(source_t *source)
1889 {
1890     /* We've gathered all the DT_DYNAMIC entries; now we need to figure out
1891        which relocation sections fit in which range as described by the
1892        entries.
1893     */
1894 
1895     int relidx;
1896     for (relidx = 0; relidx < source->num_relocation_sections; relidx++) {
1897         section_info_t *reloc_scn = &source->relocation_sections[relidx];
1898 
1899         int index = elf_ndxscn(reloc_scn->scn);
1900 
1901         ASSERT(reloc_scn->info == NULL ||
1902                reloc_scn->shdr.sh_name == reloc_scn->info->old_shdr.sh_name);
1903         const char *sname =
1904           elf_strptr(source->oldelf,
1905                      source->shstrndx,
1906                      reloc_scn->shdr.sh_name);
1907 
1908         INFO("Checking section [%s], index %d, for match to dynamic ranges\n",
1909              sname, index);
1910         if (source->shdr_info == NULL || reloc_scn->info->idx > 0) {
1911             if (source->rel.addr &&
1912                 source->rel.addr <= reloc_scn->shdr.sh_addr &&
1913                 reloc_scn->shdr.sh_addr < source->rel.addr + source->rel.size)
1914                 {
1915                     /* The entire section must fit in the dynamic range. */
1916                     if((reloc_scn->shdr.sh_addr + reloc_scn->shdr.sh_size) >
1917                        (source->rel.addr + source->rel.size))
1918                         {
1919                             PRINT("WARNING: In [%s], section %s:[%lld,%lld) "
1920                                   "is not fully contained in dynamic range "
1921                                   "[%lld,%lld)!\n",
1922                                   source->name,
1923                                   sname,
1924                                   reloc_scn->shdr.sh_addr,
1925                                   reloc_scn->shdr.sh_addr +
1926                                       reloc_scn->shdr.sh_size,
1927                                   source->rel.addr,
1928                                   source->rel.addr + source->rel.size);
1929                         }
1930 
1931                     if (NULL == source->rel.sections) {
1932                         source->rel.sections = init_range_list();
1933                         ASSERT(source->rel.sections);
1934                     }
1935                     add_unique_range_nosort(source->rel.sections,
1936                                             reloc_scn->shdr.sh_addr,
1937                                             reloc_scn->shdr.sh_size,
1938                                             reloc_scn,
1939                                             NULL,
1940                                             NULL);
1941                     INFO("\tSection [%s] matches dynamic range REL.\n",
1942                          sname);
1943                 }
1944             else if (source->jmprel.addr &&
1945                      source->jmprel.addr <= reloc_scn->shdr.sh_addr &&
1946                      reloc_scn->shdr.sh_addr <= source->jmprel.addr +
1947                      source->jmprel.size)
1948                 {
1949                     if((reloc_scn->shdr.sh_addr + reloc_scn->shdr.sh_size) >
1950                        (source->jmprel.addr + source->jmprel.size))
1951                         {
1952                             PRINT("WARNING: In [%s], section %s:[%lld,%lld) "
1953                                   "is not fully "
1954                                   "contained in dynamic range [%lld,%lld)!\n",
1955                                   source->name,
1956                                   sname,
1957                                   reloc_scn->shdr.sh_addr,
1958                                   reloc_scn->shdr.sh_addr +
1959                                       reloc_scn->shdr.sh_size,
1960                                   source->jmprel.addr,
1961                                   source->jmprel.addr + source->jmprel.size);
1962                         }
1963 
1964                     if (NULL == source->jmprel.sections) {
1965                         source->jmprel.sections = init_range_list();
1966                         ASSERT(source->jmprel.sections);
1967                     }
1968                     add_unique_range_nosort(source->jmprel.sections,
1969                                             reloc_scn->shdr.sh_addr,
1970                                             reloc_scn->shdr.sh_size,
1971                                             reloc_scn,
1972                                             NULL,
1973                                             NULL);
1974                     INFO("\tSection [%s] matches dynamic range JMPREL.\n",
1975                          sname);
1976                 }
1977             else
1978                 PRINT("WARNING: Relocation section [%s:%s] does not match "
1979                       "any DT_ entry.\n",
1980                       source->name,
1981                       sname);
1982         }
1983         else {
1984             INFO("Section [%s] was removed, not matching it to dynamic "
1985                  "ranges.\n",
1986                  sname);
1987         }
1988     } /* for ... */
1989 
1990     if (source->rel.sections) sort_ranges(source->rel.sections);
1991     if (source->jmprel.sections) sort_ranges(source->jmprel.sections);
1992 }
1993 
drop_sections(source_t * source)1994 static void drop_sections(source_t *source)
1995 {
1996     INFO("We are dropping some sections from [%s]--creating section entries "
1997          "only for remaining sections.\n",
1998          source->name);
1999     /* Renumber the sections.  The numbers for the sections after those we are
2000        dropping will be shifted back by the number of dropped sections. */
2001     int cnt, idx;
2002     for (cnt = idx = 1; cnt < source->shnum; ++cnt) {
2003         if (source->shdr_info[cnt].idx > 0) {
2004             source->shdr_info[cnt].idx = idx++;
2005 
2006             /* Create a new section. */
2007             FAILIF_LIBELF((source->shdr_info[cnt].newscn =
2008                            elf_newscn(source->elf)) == NULL, elf_newscn);
2009             ASSERT(elf_ndxscn (source->shdr_info[cnt].newscn) ==
2010                    source->shdr_info[cnt].idx);
2011 
2012             /* Copy the section data */
2013             Elf_Data *olddata =
2014                 elf_getdata(source->shdr_info[cnt].scn, // old section
2015                             NULL);
2016             FAILIF_LIBELF(NULL == olddata, elf_getdata);
2017             Elf_Data *data =
2018                 elf_newdata(source->shdr_info[cnt].newscn);
2019             FAILIF_LIBELF(NULL == data, elf_newdata);
2020             *data = *olddata;
2021 #if COPY_SECTION_DATA_BUFFER
2022             if (olddata->d_buf != NULL) {
2023                 data->d_buf = MALLOC(data->d_size);
2024                 memcpy(data->d_buf, olddata->d_buf, olddata->d_size);
2025             }
2026 #endif
2027             source->shdr_info[cnt].data = data;
2028 
2029             if (data->d_size !=
2030                 source->shdr_info[cnt].shdr.sh_size) {
2031                 INFO("Trimming new-section data from %d to %lld bytes "
2032                      "(as calculated by adjust_dynamic_segment()).\n",
2033                      data->d_size,
2034                      source->shdr_info[cnt].shdr.sh_size);
2035                 data->d_size =
2036                     source->shdr_info[cnt].shdr.sh_size;
2037             }
2038 
2039             INFO("\tsection [%s] (old offset %lld, old size %lld) "
2040                  "will have index %d (was %d), new size %d\n",
2041                  source->shdr_info[cnt].name,
2042                  source->shdr_info[cnt].old_shdr.sh_offset,
2043                  source->shdr_info[cnt].old_shdr.sh_size,
2044                  source->shdr_info[cnt].idx,
2045                  elf_ndxscn(source->shdr_info[cnt].scn),
2046                  data->d_size);
2047         } else {
2048             INFO("\tIgnoring section [%s] (offset %lld, size %lld, index %d), "
2049                  "it will be discarded.\n",
2050                  source->shdr_info[cnt].name,
2051                  source->shdr_info[cnt].shdr.sh_offset,
2052                  source->shdr_info[cnt].shdr.sh_size,
2053                  elf_ndxscn(source->shdr_info[cnt].scn));
2054         }
2055 
2056         /* NOTE: We mark use_old_shdr_for_relocation_calculations even for the
2057            sections we are removing.  adjust_elf has an assertion that makes
2058            sure that if the values for the size of a section according to its
2059            header and its data structure differ, then we are using explicitly
2060            the old section header for calculations, and that the section in
2061            question is a relocation section.
2062         */
2063         source->shdr_info[cnt].use_old_shdr_for_relocation_calculations = true;
2064     } /* for */
2065 }
2066 
process_file(const char * filename,const char * output,int is_file,void (* report_library_size_in_memory)(const char * name,off_t fsize),unsigned (* get_next_link_address)(const char * name),int locals_only,char ** lib_lookup_dirs,int num_lib_lookup_dirs,char ** default_libs,int num_default_libs,int dry_run,int * total_num_handled_relocs,int * total_num_unhandled_relocs)2067 static source_t* process_file(const char *filename,
2068                               const char *output, int is_file,
2069                               void (*report_library_size_in_memory)(
2070                                   const char *name, off_t fsize),
2071                               unsigned (*get_next_link_address)(
2072                                   const char *name),
2073                               int locals_only,
2074                               char **lib_lookup_dirs,
2075                               int num_lib_lookup_dirs,
2076                               char **default_libs,
2077                               int num_default_libs,
2078                               int dry_run,
2079                               int *total_num_handled_relocs,
2080                               int *total_num_unhandled_relocs)
2081 {
2082     /* Look up the file in the list of already-handles files, which are
2083        represented by source_t structs.  If we do not find the file, then we
2084        haven't prelinked it yet.  If we find it, then we have, so we do
2085        nothing.  Keep in mind that apriori operates on an entire collection
2086        of files, and if application A used library L, and so does application
2087        B, if we process A first, then by the time we get to B we will have
2088        prelinked L already; that's why we check first to see if a library has
2089        been prelinked.
2090     */
2091     source_t *source =
2092         find_source(filename, lib_lookup_dirs, num_lib_lookup_dirs);
2093     if (NULL == source) {
2094         /* If we could not find the source, then it hasn't been processed yet,
2095            so we go ahead and process it! */
2096         INFO("Processing [%s].\n", filename);
2097         char *full = find_file(filename, lib_lookup_dirs, num_lib_lookup_dirs);
2098         FAILIF(NULL == full,
2099                "Could not find [%s] in the current directory or in any of "
2100                "the search paths!\n", filename);
2101 
2102         unsigned base = get_next_link_address(full);
2103 
2104         source = init_source(full, output, is_file, base, dry_run);
2105 
2106         if (source == NULL) {
2107             INFO("File [%s] is a static executable.\n", filename);
2108             return NULL;
2109         }
2110 		ASSERT(source->dynamic.scn != NULL);
2111 
2112         /* We need to increment the next prelink address only when the file we
2113            are currently handing is a shared library.  Executables do not need
2114            to be prelinked at a different address, they are always at address
2115            zero.
2116 
2117            Also, if we are prelinking locals only, then we are handling a
2118            single file per invokation of apriori, so there is no need to
2119            increment the prelink address unless there is a global prelink map,
2120            in which case we do need to check to see if the library isn't
2121            running into its neighbouts in the prelink map.
2122         */
2123         if (source->oldelf_hdr.e_type != ET_EXEC &&
2124             (!locals_only ||
2125              report_library_size_in_memory ==
2126              pm_report_library_size_in_memory)) {
2127             /* This sets the next link address only if an increment was not
2128                specified by the user.  If an address increment was specified,
2129                then we just check to make sure that the file size is less than
2130                the increment.
2131 
2132                NOTE: The file size is the absolute highest number of bytes that
2133                the file may occupy in memory, if the entire file is loaded, but
2134                this is almost next the case.  A file will often have sections
2135                which are not loaded, which could add a lot of size.  That's why
2136                we start off with the file size and then subtract the size of
2137                the biggest sections that will not get loaded, which are the
2138                varios DWARF sections, all of which of which are named starting
2139                with ".debug_".
2140 
2141                We could do better than this (by caculating exactly how many
2142                bytes from that file will be loaded), but that's an overkill.
2143                Unless the prelink-address increment becomes too small, the file
2144                size after subtracting the sizes of the DWARF section will be a
2145                good-enough upper bound.
2146             */
2147 
2148             unsigned long fsize = source->elf_file_info.st_size;
2149             INFO("Calculating loadable file size for next link address.  "
2150                  "Starting with %ld.\n", fsize);
2151             if (true) {
2152                 Elf_Scn *scn = NULL;
2153                 GElf_Shdr shdr_mem, *shdr;
2154                 const char *scn_name;
2155                 while ((scn = elf_nextscn (source->oldelf, scn)) != NULL) {
2156                     shdr = gelf_getshdr(scn, &shdr_mem);
2157                     FAILIF_LIBELF(NULL == shdr, gelf_getshdr);
2158                     scn_name = elf_strptr (source->oldelf,
2159                                            source->shstrndx, shdr->sh_name);
2160                     ASSERT(scn_name != NULL);
2161 
2162                     if (!(shdr->sh_flags & SHF_ALLOC)) {
2163                         INFO("\tDecrementing by %lld on account of section "
2164                              "[%s].\n",
2165                              shdr->sh_size,
2166                              scn_name);
2167                         fsize -= shdr->sh_size;
2168                     }
2169                 }
2170             }
2171             INFO("Done calculating loadable file size for next link address: "
2172                  "Final value is %ld.\n", fsize);
2173             report_library_size_in_memory(source->name, fsize);
2174         }
2175 
2176         /* Identify the dynamic segment and process it.  Specifically, we find
2177            out what dependencies, if any, this file has.  Whenever we encounter
2178            such a dependency, we process it recursively; we find out where the
2179            various relocation information sections are stored. */
2180 
2181         size_t dynidx;
2182         GElf_Dyn *dyn, dyn_mem;
2183         size_t numdyn =
2184             source->dynamic.shdr.sh_size /
2185             source->dynamic.shdr.sh_entsize;
2186         ASSERT(source->dynamic.shdr.sh_size == source->dynamic.data->d_size);
2187 
2188         source->rel.idx = source->rel.sz_idx = -1;
2189         source->jmprel.idx = source->jmprel.sz_idx = -1;
2190 
2191         for (dynidx = 0; dynidx < numdyn; dynidx++) {
2192             dyn = gelf_getdyn (source->dynamic.data,
2193                                dynidx,
2194                                &dyn_mem);
2195             FAILIF_LIBELF(NULL == dyn, gelf_getdyn);
2196             /* When we are processing only the local relocations in a file,
2197                we don't need to handle any of the dependencies.  It won't
2198                hurt if we do, but we will be doing unnecessary work.
2199             */
2200             switch (dyn->d_tag)
2201             {
2202             case DT_NEEDED:
2203                 if (!locals_only) {
2204                     /* Process the needed library recursively.
2205                      */
2206                     const char *dep_lib =
2207 #if ELF_STRPTR_IS_BROKEN
2208                         (((char *)elf_getdata(
2209                             elf_getscn(source->elf,
2210                                        source->dynamic.shdr.sh_link),
2211                             NULL)->d_buf) + dyn->d_un.d_val);
2212 #else
2213                     elf_strptr (source->elf,
2214                                 source->dynamic.shdr.sh_link,
2215                                 dyn->d_un.d_val);
2216 #endif
2217                     ASSERT(dep_lib != NULL);
2218                     INFO("[%s] depends on [%s].\n", filename, dep_lib);
2219                     ASSERT(output == NULL || is_file == 0);
2220                     source_t *dep = process_file(dep_lib,
2221                                                  output, is_file,
2222                                                  report_library_size_in_memory,
2223                                                  get_next_link_address,
2224                                                  locals_only,
2225                                                  lib_lookup_dirs,
2226                                                  num_lib_lookup_dirs,
2227                                                  default_libs,
2228                                                  num_default_libs,
2229                                                  dry_run,
2230                                                  total_num_handled_relocs,
2231                                                  total_num_unhandled_relocs);
2232 
2233                     /* Add the library to the dependency list. */
2234                     if (source->num_lib_deps == source->lib_deps_size) {
2235                         source->lib_deps_size += 10;
2236                         source->lib_deps = REALLOC(source->lib_deps,
2237                                                    source->lib_deps_size *
2238                                                    sizeof(source_t *));
2239                     }
2240                     source->lib_deps[source->num_lib_deps++] = dep;
2241                 }
2242                 break;
2243             case DT_JMPREL:
2244                 source->jmprel.idx = dynidx;
2245                 source->jmprel.addr = dyn->d_un.d_ptr;
2246                 break;
2247             case DT_PLTRELSZ:
2248                 source->jmprel.sz_idx = dynidx;
2249                 source->jmprel.size = dyn->d_un.d_val;
2250                 break;
2251             case DT_REL:
2252                 source->rel.idx = dynidx;
2253                 source->rel.addr = dyn->d_un.d_ptr;
2254                 break;
2255             case DT_RELSZ:
2256                 source->rel.sz_idx = dynidx;
2257                 source->rel.size = dyn->d_un.d_val;
2258                 break;
2259             case DT_RELA:
2260             case DT_RELASZ:
2261                 FAILIF(1, "Can't handle DT_RELA and DT_RELASZ entries!\n");
2262                 break;
2263             } /* switch */
2264         } /* for each dynamic entry... */
2265 
2266         INFO("Handling [%s].\n", filename);
2267 
2268 #ifdef SUPPORT_ANDROID_PRELINK_TAGS
2269         if (!source->prelinked)
2270 #endif
2271 		{
2272             /* When ADJUST_ELF is defined, this call to prelink is a dry run
2273                intended to calculate the number of relocations that could not
2274                be handled.  This, in turn, allows us to calculate the amount by
2275                which we can shrink the various relocation sections before we
2276                call adjust_elf.  After we've adjusted the sections, we will
2277                call prelink() one more time to do the actual work.
2278 
2279                NOTE: Even when ADJUST_ELF != 0, we cannot adjust an ELF file
2280                that is an executabe, because an executable is not PIC.
2281             */
2282 
2283             int num_unfinished_relocs = 0;
2284             bool adjust_file = ADJUST_ELF && source->elf_hdr.e_type != ET_EXEC;
2285             INFO("\n\n\tPRELINKING %s\n\n",
2286                  adjust_file ?
2287                  "(CALCULATE NUMBER OF HANDLED RELOCATIONS)" :
2288                  "(ACTUAL)");
2289             int num_relocs = prelink(source, locals_only,
2290                                      adjust_file || dry_run,
2291                                      lib_lookup_dirs, num_lib_lookup_dirs,
2292                                      default_libs, num_default_libs,
2293                                      &num_unfinished_relocs);
2294             INFO("[%s]: (calculate changes) handled %d, could not handle %d "
2295                  "relocations.\n",
2296                  source->name,
2297                  num_relocs,
2298                  num_unfinished_relocs);
2299 
2300             if (adjust_file && !dry_run)
2301             {
2302                 /* Find out the new section sizes of the relocation sections,
2303                    but do not move any relocations around, because adjust_elf
2304                    needs to know about all relocations in order to adjust the
2305                    file correctly.
2306                 */
2307                 match_relocation_sections_to_dynamic_ranges(source);
2308 
2309                 /* We haven't set up source->shdr_info[] yet, so we do it now.
2310 
2311                    NOTE: setup_shdr_info() depends only on source->oldelf, not
2312                    on source->elf!  source->elf is not even defined yet.  We
2313                    initialize source->shdr_info[] based on the section
2314                    information of the unmodified ELF file, and then make our
2315                    modifications in the call to adjust_dynamic_segment() based
2316                    on this information.  adjust_dynamic_segment() will
2317                    rearrange the unhandled relocations in the beginning of
2318                    their relocation sections, and adjust the size of those
2319                    relocation sections.  In the case when a relocation section
2320                    is completely handled, adjust_dynamic_segment() will mark it
2321                    for removal by function adjust_elf.
2322                  */
2323 
2324                 ASSERT(source->elf == source->oldelf);
2325                 ASSERT(source->shdr_info == NULL);
2326                 setup_shdr_info(source);
2327                 ASSERT(source->shdr_info != NULL);
2328 
2329                 INFO("\n\n\tADJUSTING DYNAMIC SEGMENT "
2330                      "(CALCULATE CHANGES)\n\n");
2331                 bool drop_some_sections = adjust_dynamic_segment(source, true);
2332 
2333                 /* Reopen the elf file!  Note that we are not doing a dry run
2334                    (the if statement above makes sure of that.)
2335 
2336                    NOTE: We call init_elf() after we called
2337                          adjust_dynamic_segment() in order to have
2338                          adjust_dynamic_segment() refer to source->oldelf when
2339                          it refers to source->elf.  Since
2340                          adjust_dynamic_segment doesn't actually write to the
2341                          ELF file, this is OK.  adjust_dynamic_segment()
2342                          updates the sh_size fields of saved section headers
2343                          and optionally marks sections for removal.
2344 
2345                          Having adjust_dynamic_segment() refer to
2346                          source->oldelf means that we'll have access to
2347                          section-name strings so we can print them out in our
2348                          logging and debug output.
2349                 */
2350                 source->elf = init_elf(source, false);
2351 
2352                 /* This is the same code as in init_source() after the call to
2353                  * init_elf(). */
2354                 ASSERT(source->elf != source->oldelf);
2355                 ebl_closebackend(source->ebl);
2356                 source->ebl = ebl_openbackend (source->elf);
2357                 FAILIF_LIBELF(NULL == source->ebl, ebl_openbackend);
2358 #ifdef ARM_SPECIFIC_HACKS
2359                 FAILIF_LIBELF(0 != arm_init(source->elf,
2360                                             source->elf_hdr.e_machine,
2361                                             source->ebl, sizeof(Ebl)),
2362                               arm_init);
2363 #endif/*ARM_SPECIFIC_HACKS*/
2364 
2365                 if (drop_some_sections)
2366                     drop_sections(source);
2367                 else {
2368                   INFO("All sections remain in [%s]--we are changing at "
2369                        "most section sizes.\n", source->name);
2370                     create_elf_sections(source, NULL);
2371                     int cnt, idx;
2372                     for (cnt = idx = 1; cnt < source->shnum; ++cnt) {
2373                         Elf_Data *data = elf_getdata(
2374                             source->shdr_info[cnt].newscn, // new section
2375                             NULL);
2376                         if (data->d_size !=
2377                             source->shdr_info[cnt].shdr.sh_size) {
2378                             INFO("Trimming new-section data from %d to %lld "
2379                                  "bytes (as calculated by "
2380                                  "adjust_dynamic_segment()).\n",
2381                                  data->d_size,
2382                                  source->shdr_info[cnt].shdr.sh_size);
2383                             data->d_size = source->shdr_info[cnt].shdr.sh_size;
2384                         }
2385                     }
2386                 }
2387 
2388                 /* Shrink it! */
2389                 INFO("\n\n\tADJUSTING ELF\n\n");
2390                 adjust_elf(
2391                     source->oldelf, source->name,
2392                     source->elf, source->name,
2393                     source->ebl,
2394                     &source->old_ehdr_mem,
2395                     NULL, 0, // no symbol filter
2396                     source->shdr_info, // information on how to adjust the ELF
2397                     source->shnum, // length of source->shdr_info[]
2398                     source->phdr_info, // program-header info
2399                     source->shnum, // irrelevant--we're not rebuilding shstrtab
2400                     source->shnum, // number of sections in file
2401                     source->shstrndx, // index of shstrtab (both in
2402                                       // shdr_info[] and as a section index)
2403                     NULL, // irrelevant, since we are not rebuilding shstrtab
2404                     drop_some_sections, // some sections are being dropped
2405                     elf_ndxscn(source->dynamic.scn), // index of .dynamic
2406                     elf_ndxscn(source->symtab.scn), // index of .dynsym
2407                     1, // allow shady business
2408                     &source->shstrtab_data,
2409                     true,
2410                     false); // do not rebuild shstrtab
2411 
2412                 INFO("\n\n\tREINITIALIZING STRUCTURES "
2413                      "(TO CONTAIN ADJUSTMENTS)\n\n");
2414                 reinit_source(source);
2415 
2416                 INFO("\n\n\tPRELINKING (ACTUAL)\n\n");
2417 #ifdef DEBUG
2418                 int old_num_unfinished_relocs = num_unfinished_relocs;
2419 #endif
2420                 num_unfinished_relocs = 0;
2421 #ifdef DEBUG
2422                 int num_relocs_take_two =
2423 #endif
2424                 prelink(source, locals_only,
2425                         false, /* not a dry run */
2426                         lib_lookup_dirs, num_lib_lookup_dirs,
2427                         default_libs, num_default_libs,
2428                         &num_unfinished_relocs);
2429 
2430                 /* The numbers for the total number of relocations and the
2431                    number of unhandled relocations between the first and second
2432                    invokationof prelink() must be the same!  The first time we
2433                    ran prelink() just to calculate the numbers so that we could
2434                    calculate the adjustments to pass to adjust_elf, and the
2435                    second time we actually carry out the prelinking; the
2436                    numbers must stay the same!
2437                 */
2438                 ASSERT(num_relocs == num_relocs_take_two);
2439                 ASSERT(old_num_unfinished_relocs == num_unfinished_relocs);
2440 
2441                 INFO("[%s]: (actual prelink) handled %d, could not "
2442                      "handle %d relocations.\n",
2443                      source->name,
2444                      num_relocs,
2445                      num_unfinished_relocs);
2446             } /* if (adjust_elf && !dry_run) */
2447 
2448             *total_num_handled_relocs += num_relocs;
2449             *total_num_unhandled_relocs += num_unfinished_relocs;
2450 
2451             if(num_unfinished_relocs != 0 &&
2452                source->elf_hdr.e_type != ET_EXEC &&
2453                !locals_only)
2454             {
2455                 /* One reason you could have unfinished relocations in an
2456                    executable file is if this file used dlopen() and friends.
2457                    We do not adjust relocation entries to those symbols,
2458                    because libdl is a dummy only--the real functions are
2459                    provided for by the dynamic linker itsef.
2460 
2461                    NOTE FIXME HACK:  This is specific to the Android dynamic
2462                    linker, and may not be true in other cases.
2463                 */
2464                 PRINT("WARNING: Expecting to have unhandled relocations only "
2465                       "for executables (%s is not an executable)!\n",
2466                       source->name);
2467             }
2468 
2469             match_relocation_sections_to_dynamic_ranges(source);
2470 
2471             /* Now, for each relocation section, check to see if its address
2472                matches one of the DT_DYNAMIC relocation pointers.  If so, then
2473                if the section has no unhandled relocations, simply set the
2474                associated DT_DYNAMIC entry's size to zero.  If the section does
2475                have unhandled entries, then lump them all together at the front
2476                of the respective section and update the size of the respective
2477                DT_DYNAMIC entry to the new size of the section.  A better
2478                approach would be do delete a relocation section if it has been
2479                fully relocated and to remove its entry from the DT_DYNAMIC
2480                array, and for relocation entries that still have some
2481                relocations in them, we should shrink the section if that won't
2482                violate relative offsets.  This is more work, however, and for
2483                the speed improvement we expect from a prelinker, just patching
2484                up DT_DYNAMIC will suffice.
2485 
2486                Note: adjust_dynamic_segment() will modify source->shdr_info[]
2487                      to denote any change in a relocation section's size.  This
2488                      will be picked up by adjust_elf, which will rearrange the
2489                      file to eliminate the gap created by the decrease in size
2490                      of the relocation section.  We do not need to do this, but
2491                      the relocation section could be large, and reduced
2492                      drastically by the prelinking process, so it pays to
2493                      adjust the file.
2494             */
2495 
2496             INFO("\n\n\tADJUSTING DYNAMIC SEGMENT (ACTUAL)\n\n");
2497             adjust_dynamic_segment(source, false);
2498         }
2499 #ifdef SUPPORT_ANDROID_PRELINK_TAGS
2500         else INFO("[%s] is already prelinked at 0x%08lx.\n",
2501                   filename,
2502                   source->prelink_base);
2503 #endif
2504     } else INFO("[%s] has been processed already.\n", filename);
2505 
2506     return source;
2507 }
2508 
apriori(char ** execs,int num_execs,char * output,void (* report_library_size_in_memory)(const char * name,off_t fsize),int (* get_next_link_address)(const char * name),int locals_only,int dry_run,char ** lib_lookup_dirs,int num_lib_lookup_dirs,char ** default_libs,int num_default_libs,char * mapfile)2509 void apriori(char **execs, int num_execs,
2510              char *output,
2511              void (*report_library_size_in_memory)(
2512                  const char *name, off_t fsize),
2513              int (*get_next_link_address)(const char *name),
2514              int locals_only,
2515              int dry_run,
2516              char **lib_lookup_dirs, int num_lib_lookup_dirs,
2517              char **default_libs, int num_default_libs,
2518 			 char *mapfile)
2519 {
2520     source_t *source; /* for general usage */
2521     int input_idx;
2522 
2523     ASSERT(report_library_size_in_memory != NULL);
2524     ASSERT(get_next_link_address != NULL);
2525 
2526     /* Process and prelink each executable and object file.  Function
2527        process_file() is called for each executable in the loop below.
2528        It calls itself recursively for each library.   We prelink each library
2529        after prelinking its dependencies. */
2530     int total_num_handled_relocs = 0, total_num_unhandled_relocs = 0;
2531     for (input_idx = 0; input_idx < num_execs; input_idx++) {
2532         INFO("executable: [%s]\n", execs[input_idx]);
2533         /* Here process_file() is actually processing the top-level
2534            executable files. */
2535         process_file(execs[input_idx], output, num_execs == 1,
2536                      report_library_size_in_memory,
2537                      get_next_link_address, /* executables get a link address
2538                                                of zero, regardless of this
2539                                                value */
2540                      locals_only,
2541                      lib_lookup_dirs, num_lib_lookup_dirs,
2542                      default_libs, num_default_libs,
2543                      dry_run,
2544                      &total_num_handled_relocs,
2545                      &total_num_unhandled_relocs);
2546         /* if source is NULL, then the respective executable is static */
2547         /* Mark the source as an executable */
2548     } /* for each input executable... */
2549 
2550     PRINT("Handled %d relocations.\n", total_num_handled_relocs);
2551     PRINT("Could not handle %d relocations.\n", total_num_unhandled_relocs);
2552 
2553     /* We are done!  Since the end result of our calculations is a set of
2554        symbols for each library that other libraries or executables link
2555        against, we iterate over the set of libraries one last time, and for
2556        each symbol that is marked as satisfying some dependence, we emit
2557        a line with the symbol's name to a text file derived from the library's
2558        name by appending the suffix .syms to it. */
2559 
2560     if (mapfile != NULL) {
2561         const char *mapfile_name = mapfile;
2562 		FILE *fp;
2563         if (*mapfile == '+') {
2564             mapfile_name = mapfile + 1;
2565             INFO("Opening map file %s for append/write.\n",
2566                  mapfile_name);
2567             fp = fopen(mapfile_name, "a");
2568         }
2569         else fp = fopen(mapfile_name, "w");
2570 
2571 		FAILIF(fp == NULL, "Cannot open file [%s]: %s (%d)!\n",
2572 			   mapfile_name,
2573 			   strerror(errno),
2574 			   errno);
2575         source = sources;
2576         while (source) {
2577             /* If it's a library, print the results. */
2578             if (source->elf_hdr.e_type == ET_DYN) {
2579                 /* Add to the memory map file. */
2580 				fprintf(fp, "%s 0x%08lx %lld\n",
2581 						basename(source->name),
2582 						source->base,
2583 						source->elf_file_info.st_size);
2584             }
2585             source = source->next;
2586         }
2587 		fclose(fp);
2588     }
2589 
2590     /* Free the resources--you can't do it in the loop above because function
2591        print_symbol_references() accesses nodes other than the one being
2592        iterated over.
2593      */
2594     source = sources;
2595     while (source) {
2596         source_t *old = source;
2597         source = source->next;
2598         /* Destroy the evidence. */
2599         destroy_source(old);
2600     }
2601 }
2602