1 /* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
2 Written by Jakub Jelinek <jakub@redhat.com>, 2001.
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)
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.
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. */
31 update_dynamic_tags (DSO *dso, GElf_Shdr *shdr, GElf_Shdr *old_shdr,
32 struct section_move *move)
36 for (i = 1; i < move->new_shnum; ++i)
38 j = move->new_to_old[i];
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)))
76 prelink_exec (struct prelink_info *info)
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;
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];
93 Elf32_Lib *liblist = NULL;
94 struct readonly_adjust adjust;
95 struct section_move *move = NULL;
97 if (prelink_build_conflicts (info))
100 if (find_reloc_sections (dso, &rinfo))
103 move = init_section_move (dso);
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));
111 memcpy (shdr, dso->shdr, dso->ehdr.e_shnum * sizeof (GElf_Shdr));
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"))
118 if (undo < dso->ehdr.e_shnum)
122 if (undo_sections (dso, undo, move, &rinfo, &ehdr, phdr, shdr))
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);
135 dso->undo.d_buf = malloc (dso->undo.d_size);
136 if (dso->undo.d_buf == NULL)
138 error (0, ENOMEM, "%s: Could not create .gnu.prelink_undo section",
142 memcpy (dso->undo.d_buf, data->d_buf, data->d_size);
143 ehdr.e_shstrndx = dso->ehdr.e_shstrndx;
147 memcpy (shdr_after_undo, shdr, ehdr.e_shnum * sizeof (GElf_Shdr));
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),
155 if (dynstrndx == dso->ehdr.e_shnum)
157 error (0, 0, "%s: Could not find .dynstr section", dso->filename);
161 dynstrndxnew = move->old_to_new[dynstrndx];
162 shstrndxnew = move->old_to_new[dso->ehdr.e_shstrndx];
163 shnum_after_undo = move->new_shnum;
167 liblist = calloc (ndeps - 1, sizeof (Elf32_Lib));
170 error (0, ENOMEM, "%s: Cannot build .gnu.liblist section",
178 for (i = 0; i < ndeps - 1; ++i)
180 struct prelink_entry *ent = info->ent->depends[i];
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;
193 old_bss = addr_to_sec (dso, info->dynbss_base);
194 assert (old_bss != -1);
195 if (move->old_to_new[old_bss] == -1)
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);
204 old_sbss = addr_to_sec (dso, info->sdynbss_base);
205 assert (old_sbss != -1);
206 if (move->old_to_new[old_sbss] == -1)
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);
215 if (rinfo.first != -1)
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)
222 rinfonew.rel_to_rela = 1;
223 rinfonew.reldyn_rela = 0;
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)
232 rinfonew.rel_to_rela_plt = 1;
233 rinfonew.plt_rela = 0;
237 for (i = 1, j = 1; i < ehdr.e_shnum; ++i)
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"))
247 if (! strcmp (name, ".gnu.conflict"))
249 old_conflict = move->new_to_old[j];
250 remove_section (move, j);
252 else if (! strcmp (name, ".gnu.liblist"))
254 old_liblist = move->new_to_old[j];
255 remove_section (move, j);
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);
268 assert (j == move->new_shnum);
271 if (old_sdynbss != -1 && old_dynbss == -1)
273 old_dynbss = old_sdynbss;
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));
285 if (rinfonew.rel_to_rela)
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
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;
296 for (j = rinfo.first + 1; j <= rinfo.last; ++j)
298 add[i] = shdr_after_undo[rinfonew.first - rinfo.first + j];
299 add[i].sh_size = add[i].sh_size / 2 * 3;
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;
313 else if (rinfonew.rel_to_rela_plt)
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;
324 add[i] = shdr_after_undo[dynstrndxnew];
325 add[i].sh_size += growdynstr;
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;
336 if (info->conflict_rela_size)
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;
347 memset (&adjust, 0, sizeof (adjust));
351 for (i = 0; i < addcnt; ++i)
353 new[i] = find_readonly_space (dso, add + i, &ehdr, phdr, shdr, &adjust);
356 add_section (move, new[i]);
360 move->old_to_new[old[i]] = new[i];
361 move->new_to_old[new[i]] = old[i];
365 int k, l = new[new_reloc];
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)
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;
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;
388 if (old_sdynbss == -1)
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;
395 add_section (move, new_sdynbss);
396 for (i = 0; i < addcnt; ++i)
397 if (new[i] >= new_sdynbss)
401 new_sdynbss = move->old_to_new[old_sdynbss];
406 if (old_dynbss == -1)
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;
413 add_section (move, new_dynbss);
414 for (i = 0; i < addcnt; ++i)
415 if (new[i] >= new_dynbss)
419 new_dynbss = move->old_to_new[old_dynbss];
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;
431 for (i = 0; i < addcnt; ++i)
434 add_section (move, undo);
438 ehdr.e_shnum = dso->ehdr.e_shnum;
440 memcpy (dso->phdr, phdr, ehdr.e_phnum * sizeof (GElf_Phdr));
441 if (reopen_dso (dso, move, NULL))
444 assert (i == dso->ehdr.e_shnum);
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));
452 if (shdr_after_undo[shstrndxnew].sh_size
453 < dso->shdr[dso->ehdr.e_shstrndx].sh_size)
455 Elf_Data *data = elf_getdata (dso->scn[dso->ehdr.e_shstrndx], NULL);
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;
465 for (i = 1; i < dso->ehdr.e_shnum; ++i)
466 if (move->new_to_old[i] == -1)
467 dso->shdr[i] = shdr[i];
470 if (shdr[i].sh_type == SHT_PROGBITS
471 && dso->shdr[i].sh_type == SHT_NOBITS)
473 Elf_Data *data = elf_getdata (dso->scn[i], NULL);
475 assert (data->d_buf == NULL);
476 data->d_size = shdr[i].sh_size;
479 data->d_buf = calloc (shdr[i].sh_size, 1);
480 if (data->d_buf == NULL)
482 error (0, ENOMEM, "%s: Could not convert NOBITS section into PROGBITS",
487 data->d_type = ELF_T_BYTE;
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;
495 for (i = 0; i < dso->ehdr.e_phnum; ++i)
496 if (dso->phdr[i].p_type == PT_LOAD)
498 GElf_Addr last_offset = dso->phdr[i].p_offset;
500 int sfirst = 0, slast = 0, last = 0;
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)
507 if (dso->shdr[j].sh_type != SHT_NOBITS
508 || (dso->shdr[j].sh_flags & SHF_TLS))
512 error (0, 0, "%s: NOBITS section followed by non-NOBITS section in the same segment",
521 if (strcmp (strptr (dso, dso->ehdr.e_shstrndx,
522 dso->shdr[j].sh_name), ".plt") == 0)
524 else if (j == new_dynbss || j == new_sdynbss)
530 for (j = sfirst; j < slast; ++j)
532 Elf_Data *data = elf_getdata (dso->scn[j], NULL);
534 assert (data->d_size == dso->shdr[j].sh_size
535 || j == new_dynbss + 1
536 || j == new_sdynbss + 1);
539 data->d_buf = realloc (data->d_buf, data->d_size);
540 if (data->d_buf == NULL)
542 error (0, ENOMEM, "%s: Could not convert NOBITS section into PROGBITS",
547 memset (data->d_buf, 0, data->d_size);
548 data->d_type = ELF_T_BYTE;
549 dso->shdr[j].sh_type = SHT_PROGBITS;
552 adj = dso->shdr[slast - 1].sh_addr + dso->shdr[slast - 1].sh_size
553 - dso->phdr[i].p_vaddr;
555 if (adj > dso->phdr[i].p_filesz)
557 adj -= dso->phdr[i].p_filesz;
559 j < dso->ehdr.e_shnum
560 && (dso->shdr[j].sh_flags
561 & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR));
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);
568 dso->phdr[i].p_filesz += adj;
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)
580 if (dso->shdr[j].sh_type == SHT_NOBITS)
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;
590 else if (dso->shdr[j].sh_addr + dso->shdr[j].sh_size
591 > dso->phdr[i].p_vaddr + dso->phdr[i].p_filesz)
593 error (0, 0, "%s: section spans beyond end of segment",
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;
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)
612 dso->phdr[j].p_vaddr += adj;
613 dso->phdr[j].p_paddr += adj;
614 dso->phdr[j].p_offset += adj;
618 while (j < dso->ehdr.e_shnum
619 && (dso->shdr[j].sh_flags
620 & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR)))
622 dso->shdr[j].sh_offset += adj;
623 dso->shdr[j++].sh_addr += adj;
626 if (adjust_dso_nonalloc (dso, last + 1,
627 dso->shdr[sfirst].sh_offset,
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]);
642 if (rinfo.rel_to_rela)
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)
650 = dso->shdr[j].sh_size / 3 * 2;
651 if (convert_rel_to_rela (dso, j))
653 dso->shdr[j].sh_size = shdr[j].sh_size;
656 else if (rinfonew.rel_to_rela)
658 assert (new_reloc != -1);
659 for (j = rinfo.first; j <= rinfo.last; ++j)
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;
667 /* Adjust .rel*.plt if necessary. */
668 rinfo.plt = move->old_to_new[rinfo.plt];
671 assert (rinfo.plt == new[new_plt]);
672 if (rinfo.rel_to_rela_plt)
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))
680 dso->shdr[rinfo.plt].sh_size = shdr[rinfo.plt].sh_size;
682 else if (rinfonew.rel_to_rela_plt)
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;
690 /* Add new strings into .dynstr if necessary. */
691 if (new_dynstr != -1)
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)
702 error (0, ENOMEM, "%s: Could not append names needed for .gnu.liblist to .dynstr",
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)
711 liblist[j].l_name = ptr - (char *) data->d_buf;
712 ptr = stpcpy (ptr, info->sonames[j + 1]) + 1;
714 assert (ptr == (char *) data->d_buf + data->d_size);
717 /* Create or update .sdynbss if necessary. */
718 if (new_sdynbss != -1)
722 if (old_sdynbss == -1)
724 dso->shdr[new_sdynbss] = dso->shdr[new_sdynbss + 1];
726 dso->shdr[new_sdynbss].sh_name = shstrtabadd (dso, ".sdynbss");
727 if (dso->shdr[new_sdynbss].sh_name == 0)
730 dso->shdr[new_sdynbss].sh_size =
731 info->sdynbss_base + info->sdynbss_size
732 - dso->shdr[new_sdynbss].sh_addr;
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;
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)
750 error (0, 0, "%s: Copy relocs don't point into .sdynbss section",
755 data = elf_getdata (dso->scn[new_sdynbss], NULL);
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)
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)
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;
776 /* Create or update .dynbss if necessary. */
777 if (new_dynbss != -1)
781 if (old_dynbss == -1)
785 dso->shdr[new_dynbss] = dso->shdr[new_dynbss + 1];
787 if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx,
788 dso->shdr[new_dynbss + 1].sh_name),
790 && new_sdynbss == -1)
791 dso->shdr[new_dynbss].sh_name = shstrtabadd (dso, ".sdynbss");
793 dso->shdr[new_dynbss].sh_name = shstrtabadd (dso, ".dynbss");
794 if (dso->shdr[new_dynbss].sh_name == 0)
797 dso->shdr[new_dynbss].sh_size =
798 info->dynbss_base + info->dynbss_size
799 - dso->shdr[new_dynbss].sh_addr;
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;
809 if (dso->shdr[new_dynbss + 1].sh_type == SHT_NOBITS)
811 GElf_Addr last_offset;
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)
819 assert (i < dso->ehdr.e_phnum);
821 for (j = new_dynbss - 1; j; --j)
823 if (dso->shdr[j].sh_addr < dso->phdr[i].p_vaddr)
825 if (dso->shdr[j].sh_type == SHT_NOBITS
826 && (dso->shdr[j].sh_flags & SHF_TLS) == 0)
828 error (0, 0, "%s: COPY relocs not present at start of first SHT_NOBITS section",
834 if (dso->phdr[i].p_filesz
835 < info->dynbss_base + info->dynbss_size
836 - dso->phdr[i].p_vaddr)
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);
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;
847 dso->shdr[new_dynbss].sh_offset += adj;
848 dso->shdr[new_dynbss + 1].sh_offset += adj;
850 adj += dso->shdr[new_dynbss].sh_size;
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));
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);
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)
866 dso->phdr[j].p_vaddr += adj;
867 dso->phdr[j].p_paddr += adj;
868 dso->phdr[j].p_offset += adj;
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)
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;
889 while (j < dso->ehdr.e_shnum
890 && (dso->shdr[j].sh_flags
891 & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR)))
893 dso->shdr[j].sh_offset += adj;
894 dso->shdr[j++].sh_addr += adj;
897 if (adjust_dso_nonalloc (dso, new_dynbss + 2,
898 dso->shdr[new_dynbss].sh_offset,
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)
911 error (0, 0, "%s: Copy relocs don't point into .dynbss section",
916 data = elf_getdata (dso->scn[new_dynbss], NULL);
918 data->d_buf = info->dynbss;
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)
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)
930 char *buf_start = data->d_buf;
931 char *buf_end = buf_start + data->d_size;
933 while (buf_start < buf_end)
936 assert (buf_start == buf_end);
941 if (data->d_size != dso->shdr[new_dynbss + 1].sh_size)
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;
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)
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);
968 data->d_buf = liblist;
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))
975 if (set_dynamic (dso, DT_GNU_LIBLISTSZ, dso->shdr[i].sh_size, 1))
979 /* Create the conflict list if necessary. */
980 if (new_conflict != -1)
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);
990 data->d_align = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT);
991 data->d_version = EV_CURRENT;
994 data->d_buf = realloc (data->d_buf, data->d_size);
995 if (data->d_buf == NULL)
997 error (0, ENOMEM, "%s: Could not build .gnu.conflict section",
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;
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)
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)
1023 if (set_dynamic (dso, DT_GNU_CONFLICT, dso->shdr[i].sh_addr, 1))
1025 if (set_dynamic (dso, DT_GNU_CONFLICTSZ, dso->shdr[i].sh_size, 1))
1033 GElf_Addr newoffset;
1035 dso->shdr[undo].sh_name = shstrtabadd (dso, ".gnu.prelink_undo");
1036 if (dso->shdr[undo].sh_name == 0)
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))
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);
1055 dso->undo.d_buf = NULL;
1058 recompute_nonalloc_offsets (dso);
1060 if (update_dynamic_tags (dso, dso->shdr, old_shdr, move))
1063 if (update_dynamic_rel (dso, &rinfo))