Home | History | Annotate | Download | only in apriori
      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 
     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 
     72 static void print_shdr_idx(source_t *source, Elf *elf, int idx)
     73 {
     74     print_shdr(source, elf_getscn(elf, idx));
     75 }
     76 
     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 
    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 
    122 static inline void add_to_sources(source_t *src) {
    123     src->next = sources;
    124     sources = src;
    125 }
    126 
    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 
    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 
    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 
    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 
    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 
    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 
    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() */
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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