Initialize Tizen 2.3
[external/prelink.git] / src / exec.c
1 /* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
2    Written by Jakub Jelinek <jakub@redhat.com>, 2001.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software Foundation,
16    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 #include <config.h>
19 #include <assert.h>
20 #include <errno.h>
21 #include <error.h>
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include "prelink.h"
27 #include "reloc.h"
28 #include "space.h"
29
30 int
31 update_dynamic_tags (DSO *dso, GElf_Shdr *shdr, GElf_Shdr *old_shdr,
32                      struct section_move *move)
33 {
34   int i, j;
35
36   for (i = 1; i < move->new_shnum; ++i)
37     {
38       j = move->new_to_old[i];
39       if (j == -1)
40         continue;
41       if ((dynamic_info_is_set (dso, DT_HASH)
42            && dso->info[DT_HASH] == old_shdr[j].sh_addr
43            && old_shdr[j].sh_type == SHT_HASH
44            && set_dynamic (dso, DT_HASH, shdr[i].sh_addr, 1))
45           || (dynamic_info_is_set (dso, DT_SYMTAB)
46               && dso->info[DT_SYMTAB] == old_shdr[j].sh_addr
47               && old_shdr[j].sh_type == SHT_DYNSYM
48               && set_dynamic (dso, DT_SYMTAB, shdr[i].sh_addr, 1))
49           || (dynamic_info_is_set (dso, DT_STRTAB)
50               && dso->info[DT_STRTAB] == old_shdr[j].sh_addr
51               && old_shdr[j].sh_type == SHT_STRTAB
52               && set_dynamic (dso, DT_STRTAB, shdr[i].sh_addr, 1))
53           || (dynamic_info_is_set (dso, DT_VERDEF_BIT)
54               && dso->info_DT_VERDEF == old_shdr[j].sh_addr
55               && old_shdr[j].sh_type == SHT_GNU_verdef
56               && set_dynamic (dso, DT_VERDEF, shdr[i].sh_addr, 1))
57           || (dynamic_info_is_set (dso, DT_VERNEED_BIT)
58               && dso->info_DT_VERNEED == old_shdr[j].sh_addr
59               && old_shdr[j].sh_type == SHT_GNU_verneed
60               && set_dynamic (dso, DT_VERNEED, shdr[i].sh_addr, 1))
61           || (dynamic_info_is_set (dso, DT_VERSYM_BIT)
62               && dso->info_DT_VERSYM == old_shdr[j].sh_addr
63               && old_shdr[j].sh_type == SHT_GNU_versym
64               && set_dynamic (dso, DT_VERSYM, shdr[i].sh_addr, 1))
65           || (dynamic_info_is_set (dso, DT_GNU_HASH_BIT)
66               && dso->info_DT_GNU_HASH == old_shdr[j].sh_addr
67               && old_shdr[j].sh_type == SHT_GNU_HASH
68               && set_dynamic (dso, DT_GNU_HASH, shdr[i].sh_addr, 1)))
69         return 1;
70     }
71
72   return 0;
73 }
74
75 int
76 prelink_exec (struct prelink_info *info)
77 {
78   int i, j, ndeps = info->ent->ndepends + 1;
79   int dynstrndx, dynstrndxnew, growdynstr = 0, shstrndxnew;
80   int old_conflict = 0, old_liblist = 0;
81   int new_conflict = -1, new_liblist = -1;
82   int new_reloc = -1, new_plt = -1, new_dynstr = -1;
83   int old_dynbss = -1, old_bss = -1, new_dynbss = -1;
84   int old_sdynbss = -1, old_sbss = -1, new_sdynbss = -1;
85   int addcnt, undo, shnum_after_undo;
86   struct reloc_info rinfo, rinfonew;
87   DSO *dso = info->dso;
88   GElf_Ehdr ehdr;
89   GElf_Phdr phdr[dso->ehdr.e_phnum + 1];
90   GElf_Shdr old_shdr[dso->ehdr.e_shnum], new_shdr[dso->ehdr.e_shnum + 20];
91   GElf_Shdr shdr_after_undo[dso->ehdr.e_shnum + 20];
92   GElf_Shdr *shdr;
93   Elf32_Lib *liblist = NULL;
94   struct readonly_adjust adjust;
95   struct section_move *move = NULL;
96
97   if (prelink_build_conflicts (info))
98     return 1;
99
100   if (find_reloc_sections (dso, &rinfo))
101     return 1;
102
103   move = init_section_move (dso);
104   if (move == NULL)
105     return 1;
106
107   ehdr = dso->ehdr;
108   memcpy (phdr, dso->phdr, dso->ehdr.e_phnum * sizeof (GElf_Phdr));
109   memcpy (old_shdr, dso->shdr, dso->ehdr.e_shnum * sizeof (GElf_Shdr));
110   shdr = new_shdr;
111   memcpy (shdr, dso->shdr, dso->ehdr.e_shnum * sizeof (GElf_Shdr));
112
113   for (undo = 1; undo < dso->ehdr.e_shnum; ++undo)
114     if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[undo].sh_name),
115                   ".gnu.prelink_undo"))
116       break;
117
118   if (undo < dso->ehdr.e_shnum)
119     {
120       Elf_Data *data;
121
122       if (undo_sections (dso, undo, move, &rinfo, &ehdr, phdr, shdr))
123         {
124 error_out:
125           free (liblist);
126           free (move);
127           return 1;
128         }
129
130       data = elf_getdata (dso->scn[undo], NULL);
131       assert (data->d_buf != NULL);
132       assert (data->d_off == 0);
133       assert (data->d_size == dso->shdr[undo].sh_size);
134       dso->undo = *data;
135       dso->undo.d_buf = malloc (dso->undo.d_size);
136       if (dso->undo.d_buf == NULL)
137         {
138           error (0, ENOMEM, "%s: Could not create .gnu.prelink_undo section",
139                  dso->filename);
140           goto error_out;
141         }
142       memcpy (dso->undo.d_buf, data->d_buf, data->d_size);
143       ehdr.e_shstrndx = dso->ehdr.e_shstrndx;
144     }
145   undo = 0;
146
147   memcpy (shdr_after_undo, shdr, ehdr.e_shnum * sizeof (GElf_Shdr));
148
149   for (dynstrndx = 1; dynstrndx < dso->ehdr.e_shnum; ++dynstrndx)
150     if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx,
151                           dso->shdr[dynstrndx].sh_name),
152                   ".dynstr"))
153       break;
154
155   if (dynstrndx == dso->ehdr.e_shnum)
156     {
157       error (0, 0, "%s: Could not find .dynstr section", dso->filename);
158       goto error_out;
159     }
160
161   dynstrndxnew = move->old_to_new[dynstrndx];
162   shstrndxnew = move->old_to_new[dso->ehdr.e_shstrndx];
163   shnum_after_undo = move->new_shnum;
164
165   if (ndeps > 1)
166     {
167       liblist = calloc (ndeps - 1, sizeof (Elf32_Lib));
168       if (liblist == NULL)
169         {
170           error (0, ENOMEM, "%s: Cannot build .gnu.liblist section",
171                  dso->filename);
172           goto error_out;
173         }
174     }
175   else
176     liblist = NULL;
177
178   for (i = 0; i < ndeps - 1; ++i)
179     {
180       struct prelink_entry *ent = info->ent->depends[i];
181
182       liblist[i].l_name = strtabfind (dso, dynstrndx, info->sonames[i + 1]);
183       if (liblist[i].l_name >= shdr[dynstrndxnew].sh_size)
184         liblist[i].l_name = 0;
185       if (liblist[i].l_name == 0)
186         growdynstr += strlen (info->sonames[i + 1]) + 1;
187       liblist[i].l_time_stamp = ent->timestamp;
188       liblist[i].l_checksum = ent->checksum;
189     }
190
191   if (info->dynbss)
192     {
193       old_bss = addr_to_sec (dso, info->dynbss_base);
194       assert (old_bss != -1);
195       if (move->old_to_new[old_bss] == -1)
196         ++old_bss;
197       assert (move->old_to_new[old_bss] != -1);
198       assert (shdr[move->old_to_new[old_bss]].sh_addr <= info->dynbss_base);
199       assert (shdr[move->old_to_new[old_bss]].sh_addr
200               + shdr[move->old_to_new[old_bss]].sh_size > info->dynbss_base);
201     }
202   if (info->sdynbss)
203     {
204       old_sbss = addr_to_sec (dso, info->sdynbss_base);
205       assert (old_sbss != -1);
206       if (move->old_to_new[old_sbss] == -1)
207         ++old_sbss;
208       assert (move->old_to_new[old_sbss] != -1);
209       assert (shdr[move->old_to_new[old_sbss]].sh_addr <= info->sdynbss_base);
210       assert (shdr[move->old_to_new[old_sbss]].sh_addr
211               + shdr[move->old_to_new[old_sbss]].sh_size > info->sdynbss_base);
212     }
213
214   rinfonew = rinfo;
215   if (rinfo.first != -1)
216     {
217       rinfonew.first = move->old_to_new[rinfo.first];
218       rinfonew.last = move->old_to_new[rinfo.last];
219       if (shdr[rinfonew.first].sh_type == SHT_REL
220           && dso->shdr[rinfo.first].sh_type == SHT_RELA)
221         {
222           rinfonew.rel_to_rela = 1;
223           rinfonew.reldyn_rela = 0;
224         }
225     }
226   if (rinfo.plt != -1)
227     {
228       rinfonew.plt = move->old_to_new[rinfo.plt];
229       if (shdr[rinfonew.plt].sh_type == SHT_REL
230           && dso->shdr[rinfo.plt].sh_type == SHT_RELA)
231         {
232           rinfonew.rel_to_rela_plt = 1;
233           rinfonew.plt_rela = 0;
234         }
235     }
236
237   for (i = 1, j = 1; i < ehdr.e_shnum; ++i)
238     {
239       const char *name;
240       name = strptr (dso, dso->ehdr.e_shstrndx, shdr[i].sh_name);
241       if (! strcmp (name, ".dynbss"))
242         old_dynbss = move->new_to_old[j];
243       else if (! strcmp (name, ".sdynbss"))
244         old_sdynbss = move->new_to_old[j];
245       else if (! strcmp (name, ".gnu.prelink_undo"))
246         undo = -1;
247       if (! strcmp (name, ".gnu.conflict"))
248         {
249           old_conflict = move->new_to_old[j];
250           remove_section (move, j);
251         }
252       else if (! strcmp (name, ".gnu.liblist"))
253         {
254           old_liblist = move->new_to_old[j];
255           remove_section (move, j);
256         }
257       else if (rinfonew.rel_to_rela
258                && i >= rinfonew.first && i <= rinfonew.last)
259         remove_section (move, j);
260       else if (i == rinfonew.plt
261                && (rinfonew.rel_to_rela || rinfonew.rel_to_rela_plt))
262         remove_section (move, j);
263       else if (i == dynstrndxnew && growdynstr)
264         remove_section (move, j);
265       else
266         shdr[j++] = shdr[i];
267     }
268   assert (j == move->new_shnum);
269   ehdr.e_shnum = j;
270
271   if (old_sdynbss != -1 && old_dynbss == -1)
272     {
273       old_dynbss = old_sdynbss;
274       old_sdynbss = -1;
275     }
276
277   GElf_Shdr add[rinfo.last - rinfo.first + 5];
278   int old[rinfo.last - rinfo.first + 5];
279   int new[rinfo.last - rinfo.first + 5];
280   memset (add, 0, sizeof (add));
281   memset (old, 0, sizeof (old));
282   memset (new, 0, sizeof (new));
283
284   i = 0;
285   if (rinfonew.rel_to_rela)
286     {
287       add[i] = shdr_after_undo[rinfonew.first];
288       add[i].sh_size = shdr_after_undo[rinfonew.last].sh_addr
289                        + shdr_after_undo[rinfonew.last].sh_size
290                        - add[i].sh_addr;
291       assert (sizeof (Elf32_Rel) * 3 == sizeof (Elf32_Rela) * 2);
292       assert (sizeof (Elf64_Rel) * 3 == sizeof (Elf64_Rela) * 2);
293       add[i].sh_size = add[i].sh_size / 2 * 3;
294       old[i] = rinfo.first;
295       new_reloc = i++;
296       for (j = rinfo.first + 1; j <= rinfo.last; ++j)
297         {
298           add[i] = shdr_after_undo[rinfonew.first - rinfo.first + j];
299           add[i].sh_size = add[i].sh_size / 2 * 3;
300           old[i++] = j;
301         }
302       if (rinfonew.plt)
303         {
304           add[i] = shdr_after_undo[rinfonew.plt];
305           if (rinfonew.rel_to_rela_plt)
306             add[i].sh_size = add[i].sh_size / 2 * 3;
307           /* Temporarily merge them, so that they are allocated adjacently.  */
308           add[new_reloc].sh_size += add[i].sh_size;
309           old[i] = rinfo.plt;
310           new_plt = i++;
311         }
312     }
313   else if (rinfonew.rel_to_rela_plt)
314     {
315       add[i] = shdr_after_undo[rinfonew.plt];
316       assert (sizeof (Elf32_Rel) * 3 == sizeof (Elf32_Rela) * 2);
317       assert (sizeof (Elf64_Rel) * 3 == sizeof (Elf64_Rela) * 2);
318       add[i].sh_size = add[i].sh_size / 2 * 3;
319       old[i] = rinfo.plt;
320       new_plt = i++;
321     }
322   if (growdynstr)
323     {
324       add[i] = shdr_after_undo[dynstrndxnew];
325       add[i].sh_size += growdynstr;
326       old[i] = dynstrndx;
327       new_dynstr = i++;
328     }
329   add[i].sh_flags = SHF_ALLOC;
330   add[i].sh_type = SHT_GNU_LIBLIST;
331   add[i].sh_size = (ndeps - 1) * sizeof (Elf32_Lib);
332   add[i].sh_addralign = sizeof (GElf_Word);
333   add[i].sh_entsize = sizeof (Elf32_Lib);
334   old[i] = old_liblist;
335   new_liblist = i++;
336   if (info->conflict_rela_size)
337     {
338       add[i].sh_flags = SHF_ALLOC;
339       add[i].sh_type = SHT_RELA;
340       add[i].sh_entsize = gelf_fsize (dso->elf, ELF_T_RELA, 1, EV_CURRENT);
341       add[i].sh_size = info->conflict_rela_size * add[i].sh_entsize;
342       add[i].sh_addralign = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT);
343       old[i] = old_conflict;
344       new_conflict = i++;
345     }
346   addcnt = i;
347   memset (&adjust, 0, sizeof (adjust));
348   adjust.new = new;
349   adjust.move = move;
350
351   for (i = 0; i < addcnt; ++i)
352     {
353       new[i] = find_readonly_space (dso, add + i, &ehdr, phdr, shdr, &adjust);
354       if (new[i] == 0)
355         goto error_out;
356       add_section (move, new[i]);
357       ++adjust.newcount;
358       if (old[i])
359         {
360           move->old_to_new[old[i]] = new[i];
361           move->new_to_old[new[i]] = old[i];
362         }
363       if (i == new_reloc)
364         {
365           int k, l = new[new_reloc];
366
367           j = rinfo.last - rinfo.first + (new_plt != -1);
368           shdr[l].sh_size = shdr_after_undo[rinfonew.first].sh_size / 2 * 3;
369           for (k = 1; k <= j; ++k)
370             {
371               insert_readonly_section (&ehdr, shdr, l + k, &adjust);
372               shdr[l + k] = add[new_reloc + k];
373               shdr[l + k].sh_addr = shdr[l + k - 1].sh_addr
374                                     + shdr[l + k - 1].sh_size;
375               shdr[l + k].sh_offset = shdr[l + k - 1].sh_offset
376                                       + shdr[l + k - 1].sh_size;
377               new[++i] = l + k;
378               add_section (move, l + k);
379               move->old_to_new[rinfo.first + k] = l + k;
380               move->new_to_old[l + k] = rinfo.first + k;
381               ++adjust.newcount;
382             }
383         }
384     }
385
386   if (info->sdynbss)
387     {
388       if (old_sdynbss == -1)
389         {
390           new_sdynbss = move->old_to_new[old_sbss];
391           memmove (&shdr[new_sdynbss + 1], &shdr[new_sdynbss],
392                    (ehdr.e_shnum - new_sdynbss) * sizeof (GElf_Shdr));
393           shdr[new_sdynbss].sh_size = 0;
394           ++ehdr.e_shnum;
395           add_section (move, new_sdynbss);
396           for (i = 0; i < addcnt; ++i)
397             if (new[i] >= new_sdynbss)
398               ++new[i];
399         }
400       else
401         new_sdynbss = move->old_to_new[old_sdynbss];
402     }
403
404   if (info->dynbss)
405     {
406       if (old_dynbss == -1)
407         {
408           new_dynbss = move->old_to_new[old_bss];
409           memmove (&shdr[new_dynbss + 1], &shdr[new_dynbss],
410                    (ehdr.e_shnum - new_dynbss) * sizeof (GElf_Shdr));
411           shdr[new_dynbss].sh_size = 0;
412           ++ehdr.e_shnum;
413           add_section (move, new_dynbss);
414           for (i = 0; i < addcnt; ++i)
415             if (new[i] >= new_dynbss)
416               ++new[i];
417         }
418       else
419         new_dynbss = move->old_to_new[old_dynbss];
420     }
421
422   if (undo != -1)
423     {
424       undo = move->old_to_new[dso->ehdr.e_shstrndx];
425       memmove (&shdr[undo + 1], &shdr[undo],
426                (ehdr.e_shnum - undo) * sizeof (GElf_Shdr));
427       memset (&shdr[undo], 0, sizeof (shdr[undo]));
428       shdr[undo].sh_type = SHT_PROGBITS;
429       shdr[undo].sh_addralign = dso->undo.d_align;
430       ++ehdr.e_shnum;
431       for (i = 0; i < addcnt; ++i)
432         if (new[i] >= undo)
433           ++new[i];
434       add_section (move, undo);
435     }
436
437   i = ehdr.e_shnum;
438   ehdr.e_shnum = dso->ehdr.e_shnum;
439   dso->ehdr = ehdr;
440   memcpy (dso->phdr, phdr, ehdr.e_phnum * sizeof (GElf_Phdr));
441   if (reopen_dso (dso, move, NULL))
442     goto error_out;
443
444   assert (i == dso->ehdr.e_shnum);
445
446   if (shnum_after_undo != move->new_shnum)
447     adjust_nonalloc (dso, &dso->ehdr, shdr, 0,
448                      dso->ehdr.e_shoff + 1,
449                      ((long) move->new_shnum - (long) shnum_after_undo)
450                      * gelf_fsize (dso->elf, ELF_T_SHDR, 1, EV_CURRENT));
451
452   if (shdr_after_undo[shstrndxnew].sh_size
453       < dso->shdr[dso->ehdr.e_shstrndx].sh_size)
454     {
455       Elf_Data *data = elf_getdata (dso->scn[dso->ehdr.e_shstrndx], NULL);
456
457       assert (elf_getdata (dso->scn[dso->ehdr.e_shstrndx], data) == NULL);
458       assert (data->d_off == 0);
459       assert (shdr_after_undo[shstrndxnew].sh_size
460               == shdr[dso->ehdr.e_shstrndx].sh_size);
461       assert (data->d_size == dso->shdr[dso->ehdr.e_shstrndx].sh_size);
462       data->d_size = shdr_after_undo[shstrndxnew].sh_size;
463     }
464
465   for (i = 1; i < dso->ehdr.e_shnum; ++i)
466     if (move->new_to_old[i] == -1)
467       dso->shdr[i] = shdr[i];
468     else
469       {
470         if (shdr[i].sh_type == SHT_PROGBITS
471             && dso->shdr[i].sh_type == SHT_NOBITS)
472           {
473             Elf_Data *data = elf_getdata (dso->scn[i], NULL);
474
475             assert (data->d_buf == NULL);
476             data->d_size = shdr[i].sh_size;
477             if (data->d_size)
478               {
479                 data->d_buf = calloc (shdr[i].sh_size, 1);
480                 if (data->d_buf == NULL)
481                   {
482                     error (0, ENOMEM, "%s: Could not convert NOBITS section into PROGBITS",
483                            dso->filename);
484                     goto error_out;
485                   }
486               }
487             data->d_type = ELF_T_BYTE;
488           }
489         dso->shdr[i].sh_type = shdr[i].sh_type;
490         dso->shdr[i].sh_addr = shdr[i].sh_addr;
491         dso->shdr[i].sh_size = shdr[i].sh_size;
492         dso->shdr[i].sh_offset = shdr[i].sh_offset;
493       }
494
495   for (i = 0; i < dso->ehdr.e_phnum; ++i)
496     if (dso->phdr[i].p_type == PT_LOAD)
497       {
498         GElf_Addr last_offset = dso->phdr[i].p_offset;
499         GElf_Addr adj = 0;
500         int sfirst = 0, slast = 0, last = 0;
501
502         for (j = 1; j < dso->ehdr.e_shnum; ++j)
503           if (dso->shdr[j].sh_addr >= dso->phdr[i].p_vaddr
504               && dso->shdr[j].sh_addr + dso->shdr[j].sh_size
505                  <= dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz)
506             {
507               if (dso->shdr[j].sh_type != SHT_NOBITS
508                   || (dso->shdr[j].sh_flags & SHF_TLS))
509                 {
510                   if (sfirst)
511                     {
512                       error (0, 0, "%s: NOBITS section followed by non-NOBITS section in the same segment",
513                              dso->filename);
514                       goto error_out;
515                     }
516                   continue;
517                 }
518
519               if (!sfirst)
520                 sfirst = j;
521               if (strcmp (strptr (dso, dso->ehdr.e_shstrndx,
522                                   dso->shdr[j].sh_name), ".plt") == 0)
523                 slast = j + 1;
524               else if (j == new_dynbss || j == new_sdynbss)
525                 slast = j;
526             }
527
528         if (sfirst && slast)
529           {
530             for (j = sfirst; j < slast; ++j)
531               {
532                 Elf_Data *data = elf_getdata (dso->scn[j], NULL);
533
534                 assert (data->d_size == dso->shdr[j].sh_size
535                         || j == new_dynbss + 1
536                         || j == new_sdynbss + 1);
537                 if (data->d_size)
538                   {
539                     data->d_buf = realloc (data->d_buf, data->d_size);
540                     if (data->d_buf == NULL)
541                       {
542                         error (0, ENOMEM, "%s: Could not convert NOBITS section into PROGBITS",
543                                dso->filename);
544                         goto error_out;
545                       }
546                   }
547                 memset (data->d_buf, 0, data->d_size);
548                 data->d_type = ELF_T_BYTE;
549                 dso->shdr[j].sh_type = SHT_PROGBITS;
550               }
551
552             adj = dso->shdr[slast - 1].sh_addr + dso->shdr[slast - 1].sh_size
553                   - dso->phdr[i].p_vaddr;
554
555             if (adj > dso->phdr[i].p_filesz)
556               {
557                 adj -= dso->phdr[i].p_filesz;
558                 for (j = slast;
559                      j < dso->ehdr.e_shnum
560                      && (dso->shdr[j].sh_flags
561                          & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR));
562                      ++j)
563                   if (dso->shdr[j].sh_addr >= dso->phdr[i].p_vaddr
564                                               + dso->phdr[i].p_memsz)
565                     adj = (adj + dso->shdr[j].sh_addralign - 1)
566                           & ~(dso->shdr[j].sh_addralign - 1);
567
568                 dso->phdr[i].p_filesz += adj;
569               }
570             else
571               adj = 0;
572           }
573
574         for (j = 1; j < dso->ehdr.e_shnum; ++j)
575           if (dso->shdr[j].sh_addr >= dso->phdr[i].p_vaddr
576               && dso->shdr[j].sh_addr + dso->shdr[j].sh_size
577                  <= dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz)
578             {
579               last = j;
580               if (dso->shdr[j].sh_type == SHT_NOBITS)
581                 {
582                   last_offset += dso->shdr[j].sh_addralign - 1;
583                   last_offset &= ~(dso->shdr[j].sh_addralign - 1);
584                   if (last_offset > dso->phdr[i].p_offset
585                                     + dso->phdr[i].p_filesz)
586                     last_offset = dso->phdr[i].p_offset
587                                   + dso->phdr[i].p_filesz;
588                   dso->shdr[j].sh_offset = last_offset;
589                 }
590               else if (dso->shdr[j].sh_addr + dso->shdr[j].sh_size
591                        > dso->phdr[i].p_vaddr + dso->phdr[i].p_filesz)
592                 {
593                   error (0, 0, "%s: section spans beyond end of segment",
594                          dso->filename);
595                   goto error_out;
596                 }
597               else
598                 {
599                   dso->shdr[j].sh_offset
600                     = dso->phdr[i].p_offset + dso->shdr[j].sh_addr
601                       - dso->phdr[i].p_vaddr;
602                   last_offset = dso->shdr[j].sh_offset + dso->shdr[j].sh_size;
603                 }
604             }
605
606         if (adj)
607           {
608             for (j = i + 1; j < dso->ehdr.e_phnum; ++j)
609               if (dso->phdr[j].p_type == PT_LOAD
610                   && dso->phdr[j].p_vaddr >= dso->shdr[slast - 1].sh_addr)
611                 {
612                   dso->phdr[j].p_vaddr += adj;
613                   dso->phdr[j].p_paddr += adj;
614                   dso->phdr[j].p_offset += adj;
615                 }
616
617             j = last + 1;
618             while (j < dso->ehdr.e_shnum
619                    && (dso->shdr[j].sh_flags
620                        & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR)))
621               {
622                 dso->shdr[j].sh_offset += adj;
623                 dso->shdr[j++].sh_addr += adj;
624               }
625
626             if (adjust_dso_nonalloc (dso, last + 1,
627                                      dso->shdr[sfirst].sh_offset,
628                                      adj))
629               goto error_out;
630           }
631       }
632
633   /* Adjust .rel*.dyn (or .rel*.*) if necessary.  */
634   assert (new_reloc == -1
635           || (rinfo.last - rinfo.first
636               == (move->old_to_new[rinfo.last]
637                   - move->old_to_new[rinfo.first])));
638   rinfo.first = move->old_to_new[rinfo.first];
639   rinfo.last = move->old_to_new[rinfo.last];
640   assert (new_reloc == -1 || rinfo.first == new[new_reloc]);
641
642   if (rinfo.rel_to_rela)
643     {
644       assert (sizeof (Elf32_Rel) * 3 == sizeof (Elf32_Rela) * 2);
645       assert (sizeof (Elf64_Rel) * 3 == sizeof (Elf64_Rela) * 2);
646       assert (new_reloc != -1);
647       for (j = rinfo.first; j <= rinfo.last; ++j)
648         {
649           dso->shdr[j].sh_size
650             = dso->shdr[j].sh_size / 3 * 2;
651           if (convert_rel_to_rela (dso, j))
652             goto error_out;
653           dso->shdr[j].sh_size = shdr[j].sh_size;
654         }
655     }
656   else if (rinfonew.rel_to_rela)
657     {
658       assert (new_reloc != -1);
659       for (j = rinfo.first; j <= rinfo.last; ++j)
660         {
661           dso->shdr[j].sh_entsize
662             = gelf_fsize (dso->elf, ELF_T_RELA, 1, EV_CURRENT);
663           dso->shdr[j].sh_type = SHT_RELA;
664         }
665     }
666
667   /* Adjust .rel*.plt if necessary.  */
668   rinfo.plt = move->old_to_new[rinfo.plt];
669   if (new_plt != -1)
670     {
671       assert (rinfo.plt == new[new_plt]);
672       if (rinfo.rel_to_rela_plt)
673         {
674           assert (sizeof (Elf32_Rel) * 3 == sizeof (Elf32_Rela) * 2);
675           assert (sizeof (Elf64_Rel) * 3 == sizeof (Elf64_Rela) * 2);
676           dso->shdr[rinfo.first].sh_size
677             = dso->shdr[rinfo.first].sh_size / 3 * 2;
678           if (convert_rel_to_rela (dso, rinfo.plt))
679             goto error_out;
680           dso->shdr[rinfo.plt].sh_size = shdr[rinfo.plt].sh_size;
681         }
682       else if (rinfonew.rel_to_rela_plt)
683         {
684           dso->shdr[rinfo.plt].sh_entsize
685             = gelf_fsize (dso->elf, ELF_T_RELA, 1, EV_CURRENT);
686           dso->shdr[rinfo.plt].sh_type = SHT_RELA;
687         }
688     }
689
690   /* Add new strings into .dynstr if necessary.  */
691   if (new_dynstr != -1)
692     {
693       Elf_Data *data;
694       char *ptr;
695
696       i = new[new_dynstr];
697       data = elf_getdata (dso->scn[i], NULL);
698       assert (data->d_off == 0);
699       data->d_buf = realloc (data->d_buf, dso->shdr[i].sh_size);
700       if (data->d_buf == NULL)
701         {
702           error (0, ENOMEM, "%s: Could not append names needed for .gnu.liblist to .dynstr",
703                  dso->filename);
704           goto error_out;
705         }
706       ptr = data->d_buf + shdr_after_undo[dynstrndxnew].sh_size;
707       data->d_size = dso->shdr[i].sh_size;
708       for (j = 0; j < ndeps - 1; ++j)
709         if (liblist[j].l_name == 0)
710           {
711             liblist[j].l_name = ptr - (char *) data->d_buf;
712             ptr = stpcpy (ptr, info->sonames[j + 1]) + 1;
713           }
714       assert (ptr == (char *) data->d_buf + data->d_size);
715     }
716
717   /* Create or update .sdynbss if necessary.  */
718   if (new_sdynbss != -1)
719     {
720       Elf_Data *data;
721
722       if (old_sdynbss == -1)
723         {
724           dso->shdr[new_sdynbss] = dso->shdr[new_sdynbss + 1];
725
726           dso->shdr[new_sdynbss].sh_name = shstrtabadd (dso, ".sdynbss");
727           if (dso->shdr[new_sdynbss].sh_name == 0)
728             goto error_out;
729
730           dso->shdr[new_sdynbss].sh_size =
731             info->sdynbss_base + info->sdynbss_size
732             - dso->shdr[new_sdynbss].sh_addr;
733
734           dso->shdr[new_sdynbss + 1].sh_size
735             -= dso->shdr[new_sdynbss].sh_size;
736           dso->shdr[new_sdynbss + 1].sh_addr
737             += dso->shdr[new_sdynbss].sh_size;
738           dso->shdr[new_sdynbss + 1].sh_offset
739             += dso->shdr[new_sdynbss].sh_size;
740           dso->shdr[new_sdynbss].sh_type = SHT_PROGBITS;
741         }
742       else
743         {
744           if (dso->shdr[new_sdynbss].sh_type != SHT_PROGBITS
745               || dso->shdr[new_sdynbss].sh_addr > info->sdynbss_base
746               || dso->shdr[new_sdynbss].sh_addr
747                  + dso->shdr[new_sdynbss].sh_size
748                  < info->sdynbss_base + info->sdynbss_size)
749             {
750               error (0, 0, "%s: Copy relocs don't point into .sdynbss section",
751                      dso->filename);
752               goto error_out;
753             }
754         }
755       data = elf_getdata (dso->scn[new_sdynbss], NULL);
756       free (data->d_buf);
757       data->d_buf = info->sdynbss;
758       info->sdynbss = NULL;
759       data->d_off = info->sdynbss_base - dso->shdr[new_sdynbss].sh_addr;
760       data->d_size = info->sdynbss_size;
761       data->d_type = ELF_T_BYTE;
762       if (old_sdynbss == -1)
763         {
764           data = elf_getdata (dso->scn[new_sdynbss + 1], NULL);
765           assert (dso->shdr[new_sdynbss + 1].sh_type != SHT_NOBITS
766                   || data->d_buf == NULL);
767           if (data->d_size != dso->shdr[new_sdynbss + 1].sh_size)
768             {
769               assert (data->d_size == dso->shdr[new_sdynbss].sh_size
770                                       + dso->shdr[new_sdynbss + 1].sh_size);
771               data->d_size -= dso->shdr[new_sdynbss].sh_size;
772             }
773         }
774     }
775
776   /* Create or update .dynbss if necessary.  */
777   if (new_dynbss != -1)
778     {
779       Elf_Data *data;
780
781       if (old_dynbss == -1)
782         {
783           GElf_Addr adj;
784
785           dso->shdr[new_dynbss] = dso->shdr[new_dynbss + 1];
786
787           if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx,
788                                 dso->shdr[new_dynbss + 1].sh_name),
789                         ".sbss")
790               && new_sdynbss == -1)
791             dso->shdr[new_dynbss].sh_name = shstrtabadd (dso, ".sdynbss");
792           else
793             dso->shdr[new_dynbss].sh_name = shstrtabadd (dso, ".dynbss");
794           if (dso->shdr[new_dynbss].sh_name == 0)
795             goto error_out;
796
797           dso->shdr[new_dynbss].sh_size =
798             info->dynbss_base + info->dynbss_size
799             - dso->shdr[new_dynbss].sh_addr;
800
801           dso->shdr[new_dynbss + 1].sh_size
802             -= dso->shdr[new_dynbss].sh_size;
803           dso->shdr[new_dynbss + 1].sh_addr
804             += dso->shdr[new_dynbss].sh_size;
805           dso->shdr[new_dynbss + 1].sh_offset
806             += dso->shdr[new_dynbss].sh_size;
807           dso->shdr[new_dynbss].sh_type = SHT_PROGBITS;
808
809           if (dso->shdr[new_dynbss + 1].sh_type == SHT_NOBITS)
810             {
811               GElf_Addr last_offset;
812
813               for (i = 0; i < dso->ehdr.e_phnum; ++i)
814                 if (dso->phdr[i].p_type == PT_LOAD
815                     && dso->phdr[i].p_vaddr <= dso->shdr[new_dynbss].sh_addr
816                     && dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz
817                        >= info->dynbss_base + info->dynbss_size)
818                   break;
819               assert (i < dso->ehdr.e_phnum);
820
821               for (j = new_dynbss - 1; j; --j)
822                 {
823                   if (dso->shdr[j].sh_addr < dso->phdr[i].p_vaddr)
824                     break;
825                   if (dso->shdr[j].sh_type == SHT_NOBITS
826                       && (dso->shdr[j].sh_flags & SHF_TLS) == 0)
827                     {
828                       error (0, 0, "%s: COPY relocs not present at start of first SHT_NOBITS section",
829                              dso->filename);
830                       goto error_out;
831                     }
832                 }
833
834               if (dso->phdr[i].p_filesz
835                   < info->dynbss_base + info->dynbss_size
836                     - dso->phdr[i].p_vaddr)
837                 {
838                   dso->phdr[i].p_filesz =
839                     info->dynbss_base + info->dynbss_size
840                     - dso->phdr[i].p_vaddr;
841                   assert (dso->phdr[i].p_filesz <= dso->phdr[i].p_memsz);
842                 }
843
844               adj = dso->phdr[i].p_offset + dso->shdr[new_dynbss].sh_addr
845                     - dso->phdr[i].p_vaddr - dso->shdr[new_dynbss].sh_offset;
846
847               dso->shdr[new_dynbss].sh_offset += adj;
848               dso->shdr[new_dynbss + 1].sh_offset += adj;
849
850               adj += dso->shdr[new_dynbss].sh_size;
851
852               for (j = new_dynbss + 2;
853                    j < dso->ehdr.e_shnum
854                    && (dso->shdr[j].sh_flags
855                        & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR));
856                    ++j)
857                 if (dso->shdr[j].sh_addr >= dso->phdr[i].p_vaddr
858                                             + dso->phdr[i].p_memsz)
859                   adj = (adj + dso->shdr[j].sh_addralign - 1)
860                         & ~(dso->shdr[j].sh_addralign - 1);
861
862               for (j = i + 1; j < dso->ehdr.e_phnum; ++j)
863                 if (dso->phdr[j].p_type == PT_LOAD
864                     && dso->phdr[j].p_vaddr >= dso->shdr[new_dynbss].sh_addr)
865                   {
866                     dso->phdr[j].p_vaddr += adj;
867                     dso->phdr[j].p_paddr += adj;
868                     dso->phdr[j].p_offset += adj;
869                   }
870
871               last_offset = dso->shdr[new_dynbss + 1].sh_offset;
872               for (j = new_dynbss + 2; j < dso->ehdr.e_shnum; ++j)
873                 if (dso->shdr[j].sh_type != SHT_NOBITS
874                     || dso->shdr[j].sh_addr < dso->phdr[i].p_vaddr
875                     || dso->shdr[j].sh_addr + dso->shdr[j].sh_size
876                        > dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz)
877                   break;
878                 else
879                   {
880                     last_offset += dso->shdr[j].sh_addralign - 1;
881                     last_offset &= ~(dso->shdr[j].sh_addralign - 1);
882                     if (last_offset > dso->phdr[i].p_offset
883                                       + dso->phdr[i].p_filesz)
884                       last_offset = dso->phdr[i].p_offset
885                                     + dso->phdr[i].p_filesz;
886                     dso->shdr[j].sh_offset = last_offset;
887                   }
888
889               while (j < dso->ehdr.e_shnum
890                      && (dso->shdr[j].sh_flags
891                          & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR)))
892                 {
893                   dso->shdr[j].sh_offset += adj;
894                   dso->shdr[j++].sh_addr += adj;
895                 }
896
897               if (adjust_dso_nonalloc (dso, new_dynbss + 2,
898                                        dso->shdr[new_dynbss].sh_offset,
899                                        adj))
900                 goto error_out;
901             }
902         }
903       else
904         {
905           if (dso->shdr[new_dynbss].sh_type != SHT_PROGBITS
906               || dso->shdr[new_dynbss].sh_addr > info->dynbss_base
907               || dso->shdr[new_dynbss].sh_addr
908                  + dso->shdr[new_dynbss].sh_size
909                  < info->dynbss_base + info->dynbss_size)
910             {
911               error (0, 0, "%s: Copy relocs don't point into .dynbss section",
912                      dso->filename);
913               goto error_out;
914             }
915         }
916       data = elf_getdata (dso->scn[new_dynbss], NULL);
917       free (data->d_buf);
918       data->d_buf = info->dynbss;
919       info->dynbss = NULL;
920       data->d_off = info->dynbss_base - dso->shdr[new_dynbss].sh_addr;
921       data->d_size = info->dynbss_size;
922       data->d_type = ELF_T_BYTE;
923       if (old_dynbss == -1)
924         {
925           data = elf_getdata (dso->scn[new_dynbss + 1], NULL);
926           if (dso->shdr[new_dynbss + 1].sh_type == SHT_NOBITS
927               && data->d_buf != NULL)
928             {
929 #ifndef NDEBUG
930               char *buf_start = data->d_buf;
931               char *buf_end = buf_start + data->d_size;
932
933               while (buf_start < buf_end)
934                 if (*buf_start++)
935                   break;
936               assert (buf_start == buf_end);
937 #endif
938               free (data->d_buf);
939               data->d_buf = NULL;
940             }
941           if (data->d_size != dso->shdr[new_dynbss + 1].sh_size)
942             {
943               assert (data->d_size == dso->shdr[new_dynbss].sh_size
944                                       + dso->shdr[new_dynbss + 1].sh_size);
945               data->d_size -= dso->shdr[new_dynbss].sh_size;
946             }
947         }
948     }
949
950   /* Create the liblist.  */
951   i = new[new_liblist];
952   dso->shdr[i].sh_flags = shdr[i].sh_flags;
953   dso->shdr[i].sh_addralign = shdr[i].sh_addralign;
954   dso->shdr[i].sh_entsize = shdr[i].sh_entsize;
955   dso->shdr[i].sh_name = shstrtabadd (dso, ".gnu.liblist");
956   if (dso->shdr[i].sh_name == 0)
957     goto error_out;
958   else
959     {
960       Elf_Data *data;
961
962       dso->shdr[i].sh_link
963         = new_dynstr != -1 ? new[new_dynstr] : move->old_to_new[dynstrndx];
964       data = elf_getdata (dso->scn[i], NULL);
965       data->d_type = ELF_T_WORD;
966       data->d_size = (ndeps - 1) * sizeof (Elf32_Lib);
967       free (data->d_buf);
968       data->d_buf = liblist;
969       liblist = NULL;
970       data->d_off = 0;
971       data->d_align = sizeof (GElf_Word);
972       data->d_version = EV_CURRENT;
973       if (set_dynamic (dso, DT_GNU_LIBLIST, dso->shdr[i].sh_addr, 1))
974         goto error_out;
975       if (set_dynamic (dso, DT_GNU_LIBLISTSZ, dso->shdr[i].sh_size, 1))
976         goto error_out;
977     }
978
979   /* Create the conflict list if necessary.  */
980   if (new_conflict != -1)
981     {
982       Elf_Data *data;
983
984       i = new[new_conflict];
985       data = elf_getdata (dso->scn[i], NULL);
986       data->d_type = ELF_T_RELA;
987       data->d_size = info->conflict_rela_size
988                      * gelf_fsize (dso->elf, ELF_T_RELA, 1, EV_CURRENT);
989       data->d_off = 0;
990       data->d_align = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT);
991       data->d_version = EV_CURRENT;
992       if (data->d_size)
993         {
994           data->d_buf = realloc (data->d_buf, data->d_size);
995           if (data->d_buf == NULL)
996             {
997               error (0, ENOMEM, "%s: Could not build .gnu.conflict section",
998                      dso->filename);
999               goto error_out;
1000             }
1001         }
1002       else
1003         {
1004           free (data->d_buf);
1005           data->d_buf = NULL;
1006         }
1007       for (j = 0; j < info->conflict_rela_size; ++j)
1008         gelfx_update_rela (dso->elf, data, j, info->conflict_rela + j);
1009       free (info->conflict_rela);
1010       info->conflict_rela = NULL;
1011
1012       dso->shdr[i].sh_flags = shdr[i].sh_flags;
1013       dso->shdr[i].sh_addralign = shdr[i].sh_addralign;
1014       dso->shdr[i].sh_entsize = shdr[i].sh_entsize;
1015       for (j = 1; j < dso->ehdr.e_shnum; ++j)
1016         if (dso->shdr[j].sh_type == SHT_DYNSYM)
1017           break;
1018       assert (j < dso->ehdr.e_shnum);
1019       dso->shdr[i].sh_link = j;
1020       dso->shdr[i].sh_name = shstrtabadd (dso, ".gnu.conflict");
1021       if (dso->shdr[i].sh_name == 0)
1022         goto error_out;
1023       if (set_dynamic (dso, DT_GNU_CONFLICT, dso->shdr[i].sh_addr, 1))
1024         goto error_out;
1025       if (set_dynamic (dso, DT_GNU_CONFLICTSZ, dso->shdr[i].sh_size, 1))
1026         goto error_out;
1027     }
1028
1029   if (undo != -1)
1030     {
1031       Elf_Scn *scn;
1032       Elf_Data *data;
1033       GElf_Addr newoffset;
1034
1035       dso->shdr[undo].sh_name = shstrtabadd (dso, ".gnu.prelink_undo");
1036       if (dso->shdr[undo].sh_name == 0)
1037         return 1;
1038       dso->shdr[undo].sh_offset = dso->shdr[undo - 1].sh_offset;
1039       if (dso->shdr[undo - 1].sh_type != SHT_NOBITS)
1040         dso->shdr[undo].sh_offset += dso->shdr[undo - 1].sh_size;
1041       dso->shdr[undo].sh_entsize = 1;
1042       dso->shdr[undo].sh_size = dso->undo.d_size;
1043       newoffset = dso->shdr[undo].sh_offset + dso->undo.d_align - 1;
1044       newoffset &= ~(dso->shdr[undo].sh_addralign - 1);
1045       if (adjust_dso_nonalloc (dso, undo + 1, dso->shdr[undo].sh_offset,
1046                                dso->undo.d_size + newoffset
1047                                - dso->shdr[undo].sh_offset))
1048         return 1;
1049       dso->shdr[undo].sh_offset = newoffset;
1050       scn = dso->scn[undo];
1051       data = elf_getdata (scn, NULL);
1052       assert (data != NULL && elf_getdata (scn, data) == NULL);
1053       free (data->d_buf);
1054       *data = dso->undo;
1055       dso->undo.d_buf = NULL;
1056     }
1057
1058   recompute_nonalloc_offsets (dso);
1059
1060   if (update_dynamic_tags (dso, dso->shdr, old_shdr, move))
1061     goto error_out;
1062
1063   if (update_dynamic_rel (dso, &rinfo))
1064     goto error_out;
1065
1066   free (move);
1067   return 0;
1068 }