1 /* Copyright (C) 2001, 2002, 2004, 2009 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. */
32 arm_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start,
35 if (dyn->d_tag == DT_PLTGOT)
37 int sec = addr_to_sec (dso, dyn->d_un.d_ptr);
43 data = read_une32 (dso, dyn->d_un.d_ptr);
44 /* If .got.plt[0] points to _DYNAMIC, it needs to be adjusted. */
45 if (data == dso->shdr[n].sh_addr && data >= start)
46 write_ne32 (dso, dyn->d_un.d_ptr, data + adjust);
48 data = read_une32 (dso, dyn->d_un.d_ptr + 4);
49 /* If .got.plt[1] points to .plt, it needs to be adjusted. */
50 if (data && data >= start)
54 for (i = 1; i < dso->ehdr.e_shnum; i++)
55 if (data == dso->shdr[i].sh_addr
56 && dso->shdr[i].sh_type == SHT_PROGBITS
57 && strcmp (strptr (dso, dso->ehdr.e_shstrndx,
58 dso->shdr[i].sh_name), ".plt") == 0)
60 write_ne32 (dso, dyn->d_un.d_ptr + 4, data + adjust);
69 arm_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start,
73 switch (GELF_R_TYPE (rel->r_info))
77 data = read_une32 (dso, rel->r_offset);
79 write_ne32 (dso, rel->r_offset, data + adjust);
86 arm_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start,
91 switch (GELF_R_TYPE (rela->r_info))
94 if ((Elf32_Addr) rela->r_addend >= start)
96 rela->r_addend += (Elf32_Sword) adjust;
97 /* Write it to the memory location as well.
98 Not necessary, but we can do it. */
99 write_ne32 (dso, rela->r_offset, rela->r_addend);
102 case R_ARM_JUMP_SLOT:
103 data = read_une32 (dso, rela->r_offset);
105 write_ne32 (dso, rela->r_offset, data + adjust);
113 arm_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr)
118 if (GELF_R_TYPE (rel->r_info) == R_ARM_RELATIVE
119 || GELF_R_TYPE (rel->r_info) == R_ARM_NONE)
120 /* Fast path: nothing to do. */
123 value = info->resolve (info, GELF_R_SYM (rel->r_info),
124 GELF_R_TYPE (rel->r_info));
125 switch (GELF_R_TYPE (rel->r_info))
128 case R_ARM_JUMP_SLOT:
129 write_ne32 (dso, rel->r_offset, value);
133 if (read_une32 (dso, rel->r_offset))
135 error (0, 0, "%s: R_ARM_ABS32 relocs with non-zero addend should not be present in prelinked REL sections",
139 rel->r_info = GELF_R_INFO (GELF_R_SYM (rel->r_info), R_ARM_GLOB_DAT);
140 write_ne32 (dso, rel->r_offset, value);
141 /* Tell prelink_rel routine *rel has changed. */
145 error (0, 0, "%s: R_ARM_PC24 relocs with non-zero addend should not be present in prelinked REL sections",
149 if (dso->ehdr.e_type == ET_EXEC)
150 /* COPY relocs are handled specially in generic code. */
152 error (0, 0, "%s: R_ARM_COPY reloc in shared library?", dso->filename);
154 case R_ARM_TLS_DTPOFF32:
155 write_ne32 (dso, rel->r_offset, value);
157 /* DTPMOD32 and TPOFF32 is impossible to predict in shared libraries
158 unless prelink sets the rules. */
159 case R_ARM_TLS_DTPMOD32:
160 if (dso->ehdr.e_type == ET_EXEC)
162 error (0, 0, "%s: R_ARM_TLS_DTPMOD32 reloc in executable?",
167 case R_ARM_TLS_TPOFF32:
168 if (dso->ehdr.e_type == ET_EXEC)
169 error (0, 0, "%s: R_ARM_TLS_TPOFF32 relocs should not be present in "
170 "prelinked ET_EXEC REL sections",
174 error (0, 0, "%s: Unknown arm relocation type %d", dso->filename,
175 (int) GELF_R_TYPE (rel->r_info));
182 arm_prelink_rela (struct prelink_info *info, GElf_Rela *rela,
189 if (GELF_R_TYPE (rela->r_info) == R_ARM_RELATIVE
190 || GELF_R_TYPE (rela->r_info) == R_ARM_NONE)
191 /* Fast path: nothing to do. */
194 value = info->resolve (info, GELF_R_SYM (rela->r_info),
195 GELF_R_TYPE (rela->r_info));
196 switch (GELF_R_TYPE (rela->r_info))
199 case R_ARM_JUMP_SLOT:
200 write_ne32 (dso, rela->r_offset, value + rela->r_addend);
203 write_ne32 (dso, rela->r_offset, value + rela->r_addend);
206 val = value + rela->r_addend - rela->r_offset;
208 if ((Elf32_Word) val + 0x800000 >= 0x1000000)
210 error (0, 0, "%s: R_ARM_PC24 overflow", dso->filename);
214 write_ne32 (dso, rela->r_offset,
215 (read_une32 (dso, rela->r_offset) & 0xff000000) | val);
218 if (dso->ehdr.e_type == ET_EXEC)
219 /* COPY relocs are handled specially in generic code. */
221 error (0, 0, "%s: R_ARM_COPY reloc in shared library?", dso->filename);
223 case R_ARM_TLS_DTPOFF32:
224 write_ne32 (dso, rela->r_offset, value + rela->r_addend);
226 /* DTPMOD32 and TPOFF32 is impossible to predict in shared libraries
227 unless prelink sets the rules. */
228 case R_ARM_TLS_DTPMOD32:
229 if (dso->ehdr.e_type == ET_EXEC)
231 error (0, 0, "%s: R_ARM_TLS_DTPMOD32 reloc in executable?",
236 case R_ARM_TLS_TPOFF32:
237 if (dso->ehdr.e_type == ET_EXEC && info->resolvetls)
238 write_ne32 (dso, rela->r_offset,
239 value + rela->r_addend + info->resolvetls->offset);
242 error (0, 0, "%s: Unknown arm relocation type %d", dso->filename,
243 (int) GELF_R_TYPE (rela->r_info));
250 arm_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela,
251 char *buf, GElf_Addr dest_addr)
253 switch (GELF_R_TYPE (rela->r_info))
256 case R_ARM_JUMP_SLOT:
258 buf_write_ne32 (info->dso, buf, rela->r_addend);
267 arm_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf)
272 value = info->resolve (info, GELF_R_SYM (rel->r_info),
273 GELF_R_TYPE (rel->r_info));
274 switch (GELF_R_TYPE (rel->r_info))
279 case R_ARM_JUMP_SLOT:
280 buf_write_ne32 (info->dso, buf, value);
283 buf_write_ne32 (info->dso, buf, value + read_une32 (info->dso, rel->r_offset));
286 val = value + rel->r_offset;
287 value = read_une32 (info->dso, rel->r_offset) << 8;
288 value = ((Elf32_Sword) value) >> 6;
291 if ((Elf32_Word) val + 0x800000 >= 0x1000000)
293 error (0, 0, "%s: R_ARM_PC24 overflow", info->dso->filename);
297 buf_write_ne32 (info->dso, buf, (buf_read_une32 (info->dso, buf) & 0xff000000) | val);
302 error (0, 0, "%s: R_ARM_RELATIVE in ET_EXEC object?", info->dso->filename);
311 arm_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf)
316 value = info->resolve (info, GELF_R_SYM (rela->r_info),
317 GELF_R_TYPE (rela->r_info));
318 switch (GELF_R_TYPE (rela->r_info))
323 case R_ARM_JUMP_SLOT:
325 buf_write_ne32 (info->dso, buf, value + rela->r_addend);
328 val = value + rela->r_addend - rela->r_offset;
330 if ((Elf32_Word) val + 0x800000 >= 0x1000000)
332 error (0, 0, "%s: R_ARM_PC24 overflow", info->dso->filename);
336 buf_write_ne32 (info->dso, buf, (buf_read_une32 (info->dso, buf) & 0xff000000) | val);
341 error (0, 0, "%s: R_ARM_RELATIVE in ET_EXEC object?", info->dso->filename);
350 arm_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel,
354 struct prelink_conflict *conflict;
355 struct prelink_tls *tls;
358 if (GELF_R_TYPE (rel->r_info) == R_ARM_RELATIVE
359 || GELF_R_TYPE (rel->r_info) == R_ARM_NONE
361 /* Fast path: nothing to do. */
363 conflict = prelink_conflict (info, GELF_R_SYM (rel->r_info),
364 GELF_R_TYPE (rel->r_info));
365 if (conflict == NULL)
367 if (info->curtls == NULL)
370 switch (GELF_R_TYPE (rel->r_info))
372 /* Even local DTPMOD and TPOFF relocs need conflicts. */
373 case R_ARM_TLS_DTPMOD32:
374 case R_ARM_TLS_TPOFF32:
382 else if (conflict->ifunc)
384 error (0, 0, "%s: STT_GNU_IFUNC not handled on ARM yet",
390 /* DTPOFF32 wants to see only real conflicts, not lookups
391 with reloc_class RTYPE_CLASS_TLS. */
392 if (GELF_R_TYPE (rel->r_info) == R_ARM_TLS_DTPOFF32
393 && conflict->lookup.tls == conflict->conflict.tls
394 && conflict->lookupval == conflict->conflictval)
397 value = conflict_lookup_value (conflict);
400 ret = prelink_conflict_add_rela (info);
403 ret->r_offset = rel->r_offset;
404 ret->r_info = GELF_R_INFO (0, GELF_R_TYPE (rel->r_info));
405 switch (GELF_R_TYPE (rel->r_info))
408 case R_ARM_JUMP_SLOT:
409 ret->r_addend = (Elf32_Sword) value;
413 error (0, 0, "%s: R_ARM_%s relocs should not be present in prelinked REL sections",
414 dso->filename, GELF_R_TYPE (rel->r_info) == R_ARM_ABS32 ? "ABS32" : "PC24");
417 error (0, 0, "R_ARM_COPY should not be present in shared libraries");
419 case R_ARM_TLS_DTPMOD32:
420 case R_ARM_TLS_DTPOFF32:
421 case R_ARM_TLS_TPOFF32:
423 && (conflict->reloc_class != RTYPE_CLASS_TLS
424 || conflict->lookup.tls == NULL))
426 error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol",
430 tls = conflict ? conflict->lookup.tls : info->curtls;
431 ret->r_info = GELF_R_INFO (0, R_ARM_ABS32);
432 switch (GELF_R_TYPE (rel->r_info))
434 case R_ARM_TLS_DTPMOD32:
435 ret->r_addend = tls->modid;
437 case R_ARM_TLS_DTPOFF32:
438 ret->r_addend = value;
440 case R_ARM_TLS_TPOFF32:
441 ret->r_addend = (value + read_une32 (dso, rel->r_offset)
447 error (0, 0, "%s: Unknown arm relocation type %d", dso->filename,
448 (int) GELF_R_TYPE (rel->r_info));
455 arm_prelink_conflict_rela (DSO *dso, struct prelink_info *info,
456 GElf_Rela *rela, GElf_Addr relaaddr)
459 struct prelink_conflict *conflict;
460 struct prelink_tls *tls;
464 if (GELF_R_TYPE (rela->r_info) == R_ARM_RELATIVE
465 || GELF_R_TYPE (rela->r_info) == R_ARM_NONE
467 /* Fast path: nothing to do. */
469 conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info),
470 GELF_R_TYPE (rela->r_info));
472 if (conflict == NULL)
474 if (info->curtls == NULL)
477 switch (GELF_R_TYPE (rela->r_info))
479 /* Even local DTPMOD and TPOFF relocs need conflicts. */
480 case R_ARM_TLS_DTPMOD32:
481 case R_ARM_TLS_TPOFF32:
489 else if (conflict->ifunc)
491 error (0, 0, "%s: STT_GNU_IFUNC not handled on ARM yet",
497 /* DTPOFF32 wants to see only real conflicts, not lookups
498 with reloc_class RTYPE_CLASS_TLS. */
499 if (GELF_R_TYPE (rela->r_info) == R_ARM_TLS_DTPOFF32
500 && conflict->lookup.tls == conflict->conflict.tls
501 && conflict->lookupval == conflict->conflictval)
504 value = conflict_lookup_value (conflict);
507 ret = prelink_conflict_add_rela (info);
510 ret->r_offset = rela->r_offset;
511 ret->r_info = GELF_R_INFO (0, GELF_R_TYPE (rela->r_info));
512 switch (GELF_R_TYPE (rela->r_info))
515 case R_ARM_JUMP_SLOT:
517 ret->r_addend = (Elf32_Sword) (value + rela->r_addend);
520 val = value + rela->r_addend - rela->r_offset;
522 if ((Elf32_Word) val + 0x800000 >= 0x1000000)
524 error (0, 0, "%s: R_ARM_PC24 overflow", dso->filename);
527 value = read_une32 (dso, rela->r_offset) & 0xff000000;
528 ret->r_addend = (Elf32_Sword) (value | (val & 0xffffff));
529 ret->r_info = GELF_R_INFO (0, R_ARM_ABS32);
532 error (0, 0, "R_ARM_COPY should not be present in shared libraries");
534 case R_ARM_TLS_DTPMOD32:
535 case R_ARM_TLS_DTPOFF32:
536 case R_ARM_TLS_TPOFF32:
538 && (conflict->reloc_class != RTYPE_CLASS_TLS
539 || conflict->lookup.tls == NULL))
541 error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol",
545 tls = conflict ? conflict->lookup.tls : info->curtls;
546 ret->r_info = GELF_R_INFO (0, R_ARM_ABS32);
547 switch (GELF_R_TYPE (rela->r_info))
549 case R_ARM_TLS_DTPMOD32:
550 ret->r_addend = tls->modid;
552 case R_ARM_TLS_DTPOFF32:
553 ret->r_addend = value;
555 case R_ARM_TLS_TPOFF32:
556 ret->r_addend = value + rela->r_addend + tls->offset;
561 error (0, 0, "%s: Unknown arm relocation type %d", dso->filename,
562 (int) GELF_R_TYPE (rela->r_info));
569 arm_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela)
571 rela->r_offset = rel->r_offset;
572 rela->r_info = rel->r_info;
573 switch (GELF_R_TYPE (rel->r_info))
575 case R_ARM_JUMP_SLOT:
576 /* We should be never converting .rel.plt into .rela.plt. */
580 case R_ARM_TLS_TPOFF32:
581 rela->r_addend = (Elf32_Sword) read_une32 (dso, rel->r_offset);
584 rela->r_addend = read_une32 (dso, rel->r_offset) << 8;
585 rela->r_addend = ((Elf32_Sword) rela->r_addend) >> 6;
589 case R_ARM_TLS_DTPMOD32:
590 case R_ARM_TLS_DTPOFF32:
598 arm_rela_to_rel (DSO *dso, GElf_Rela *rela, GElf_Rel *rel)
600 rel->r_offset = rela->r_offset;
601 rel->r_info = rela->r_info;
602 switch (GELF_R_TYPE (rel->r_info))
604 case R_ARM_JUMP_SLOT:
605 /* We should be never converting .rel.plt into .rela.plt
606 and thus never .rela.plt back to .rel.plt. */
610 case R_ARM_TLS_TPOFF32:
611 write_ne32 (dso, rela->r_offset, rela->r_addend);
614 write_ne32 (dso, rela->r_offset,
615 (read_une32 (dso, rela->r_offset) & 0xff000000)
616 | ((rela->r_addend >> 2) & 0xffffff));
619 case R_ARM_TLS_DTPMOD32:
620 case R_ARM_TLS_DTPOFF32:
621 write_ne32 (dso, rela->r_offset, 0);
628 arm_need_rel_to_rela (DSO *dso, int first, int last)
632 Elf32_Rel *rel, *relend;
635 while (first <= last)
638 scn = dso->scn[first++];
639 while ((data = elf_getdata (scn, data)) != NULL)
641 rel = (Elf32_Rel *) data->d_buf;
642 relend = rel + data->d_size / sizeof (Elf32_Rel);
643 for (; rel < relend; rel++)
644 switch (ELF32_R_TYPE (rel->r_info))
647 val = read_une32 (dso, rel->r_offset);
648 /* R_ARM_ABS32 with addend 0 can be converted
649 to R_ARM_GLOB_DAT and we don't have to convert
650 to RELA because of that. */
656 case R_ARM_TLS_TPOFF32:
657 /* In shared libraries TPOFF is changed always into
658 conflicts, for executables we need to preserve
660 if (dso->ehdr.e_type == ET_EXEC)
671 arm_arch_prelink (struct prelink_info *info)
677 if (dso->info[DT_PLTGOT])
679 /* Write address of .plt into got[1].
680 .plt is what got[3] contains unless prelinking. */
681 int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]);
687 for (i = 1; i < dso->ehdr.e_shnum; i++)
688 if (dso->shdr[i].sh_type == SHT_PROGBITS
689 && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx,
690 dso->shdr[i].sh_name),
694 if (i == dso->ehdr.e_shnum)
696 data = dso->shdr[i].sh_addr;
697 write_ne32 (dso, dso->info[DT_PLTGOT] + 4, data);
704 arm_arch_undo_prelink (DSO *dso)
708 if (dso->info[DT_PLTGOT])
710 /* Clear got[1] if it contains address of .plt. */
711 int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]);
717 for (i = 1; i < dso->ehdr.e_shnum; i++)
718 if (dso->shdr[i].sh_type == SHT_PROGBITS
719 && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx,
720 dso->shdr[i].sh_name),
724 if (i == dso->ehdr.e_shnum)
726 data = read_une32 (dso, dso->info[DT_PLTGOT] + 4);
727 if (data == dso->shdr[i].sh_addr)
728 write_ne32 (dso, dso->info[DT_PLTGOT] + 4, 0);
735 arm_undo_prelink_rel (DSO *dso, GElf_Rel *rel, GElf_Addr reladdr)
740 switch (GELF_R_TYPE (rel->r_info))
745 case R_ARM_JUMP_SLOT:
746 sec = addr_to_sec (dso, rel->r_offset);
747 name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[sec].sh_name);
748 if (sec == -1 || (strcmp (name, ".got") && strcmp (name, ".got.plt")))
750 error (0, 0, "%s: R_ARM_JMP_SLOT not pointing into .got section",
756 Elf32_Addr data = read_une32 (dso, dso->shdr[sec].sh_addr + 4);
758 assert (rel->r_offset >= dso->shdr[sec].sh_addr + 12);
759 assert (((rel->r_offset - dso->shdr[sec].sh_addr) & 3) == 0);
760 write_ne32 (dso, rel->r_offset, data);
764 sec = addr_to_sec (dso, rel->r_offset);
766 write_ne32 (dso, rel->r_offset, 0);
769 if (strcmp (strptr (dso, dso->ehdr.e_shstrndx,
770 dso->shdr[sec].sh_name),
773 rel->r_info = GELF_R_INFO (GELF_R_SYM (rel->r_info), R_ARM_ABS32);
780 error (0, 0, "%s: R_ARM_%s relocs should not be present in prelinked REL sections",
781 GELF_R_TYPE (rel->r_info) == R_ARM_ABS32 ? "ABS32" : "PC24",
785 if (dso->ehdr.e_type == ET_EXEC)
786 /* COPY relocs are handled specially in generic code. */
788 error (0, 0, "%s: R_ARM_COPY reloc in shared library?", dso->filename);
790 case R_ARM_TLS_DTPMOD32:
791 case R_ARM_TLS_DTPOFF32:
792 write_ne32 (dso, rel->r_offset, 0);
794 case R_ARM_TLS_TPOFF32:
797 error (0, 0, "%s: Unknown arm relocation type %d", dso->filename,
798 (int) GELF_R_TYPE (rel->r_info));
805 arm_reloc_size (int reloc_type)
807 assert (reloc_type != R_ARM_COPY);
812 arm_reloc_class (int reloc_type)
816 case R_ARM_COPY: return RTYPE_CLASS_COPY;
817 case R_ARM_JUMP_SLOT: return RTYPE_CLASS_PLT;
818 case R_ARM_TLS_DTPMOD32:
819 case R_ARM_TLS_DTPOFF32:
820 case R_ARM_TLS_TPOFF32:
821 return RTYPE_CLASS_TLS;
822 default: return RTYPE_CLASS_VALID;
830 .alternate_machine = { EM_NONE },
831 .R_JMP_SLOT = R_ARM_JUMP_SLOT,
832 .R_COPY = R_ARM_COPY,
833 .R_RELATIVE = R_ARM_RELATIVE,
834 .rtype_class_valid = RTYPE_CLASS_VALID,
835 .dynamic_linker = "/lib/ld-linux.so.2",
836 .adjust_dyn = arm_adjust_dyn,
837 .adjust_rel = arm_adjust_rel,
838 .adjust_rela = arm_adjust_rela,
839 .prelink_rel = arm_prelink_rel,
840 .prelink_rela = arm_prelink_rela,
841 .prelink_conflict_rel = arm_prelink_conflict_rel,
842 .prelink_conflict_rela = arm_prelink_conflict_rela,
843 .apply_conflict_rela = arm_apply_conflict_rela,
844 .apply_rel = arm_apply_rel,
845 .apply_rela = arm_apply_rela,
846 .rel_to_rela = arm_rel_to_rela,
847 .rela_to_rel = arm_rela_to_rel,
848 .need_rel_to_rela = arm_need_rel_to_rela,
849 .reloc_size = arm_reloc_size,
850 .reloc_class = arm_reloc_class,
852 .arch_prelink = arm_arch_prelink,
853 .arch_undo_prelink = arm_arch_undo_prelink,
854 .undo_prelink_rel = arm_undo_prelink_rel,
855 /* Although TASK_UNMAPPED_BASE is 0x40000000, we leave some
856 area so that mmap of /etc/ld.so.cache and ld.so's malloc
857 does not take some library's VA slot.
858 Also, if this guard area isn't too small, typically
859 even dlopened libraries will get the slots they desire. */
860 .mmap_base = 0x41000000,
861 .mmap_end = 0x50000000,
862 .max_page_size = 0x8000,