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