1 /* Copyright (C) 2001, 2002, 2003, 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 sh_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 + 36, 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 + 36
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 sh_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start,
72 error (0, 0, "%s: SH doesn't support REL relocs", dso->filename);
77 sh_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start,
82 switch (GELF_R_TYPE (rela->r_info))
85 if (rela->r_addend && (Elf32_Addr) rela->r_addend >= start)
87 rela->r_addend += (Elf32_Sword) adjust;
92 data = read_une32 (dso, rela->r_offset);
94 write_ne32 (dso, rela->r_offset, data + adjust);
102 sh_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr)
104 error (0, 0, "%s: SH doesn't support REL relocs", info->dso->filename);
109 sh_prelink_rela (struct prelink_info *info, GElf_Rela *rela,
116 if (GELF_R_TYPE (rela->r_info) == R_SH_NONE)
117 /* Fast path: nothing to do. */
119 else if (GELF_R_TYPE (rela->r_info) == R_SH_RELATIVE)
122 write_ne32 (dso, rela->r_offset, rela->r_addend);
125 value = info->resolve (info, GELF_R_SYM (rela->r_info),
126 GELF_R_TYPE (rela->r_info));
127 value += rela->r_addend;
128 switch (GELF_R_TYPE (rela->r_info))
133 write_ne32 (dso, rela->r_offset, value);
136 write_ne32 (dso, rela->r_offset, value - rela->r_addend);
139 if (dso->ehdr.e_type == ET_EXEC)
140 /* COPY relocs are handled specially in generic code. */
142 error (0, 0, "%s: R_SH_COPY reloc in shared library?", dso->filename);
145 error (0, 0, "%s: Unknown sh relocation type %d", dso->filename,
146 (int) GELF_R_TYPE (rela->r_info));
153 sh_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela,
154 char *buf, GElf_Addr dest_addr)
156 switch (GELF_R_TYPE (rela->r_info))
161 buf_write_ne32 (info->dso, buf, rela->r_addend);
170 sh_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf)
172 error (0, 0, "%s: SH doesn't support REL relocs", info->dso->filename);
177 sh_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf)
181 value = info->resolve (info, GELF_R_SYM (rela->r_info),
182 GELF_R_TYPE (rela->r_info));
183 value += rela->r_addend;
184 switch (GELF_R_TYPE (rela->r_info))
191 buf_write_ne32 (info->dso, buf, value);
194 buf_write_ne32 (info->dso, buf, value - rela->r_offset);
199 error (0, 0, "%s: R_SH_RELATIVE in ET_EXEC object?", info->dso->filename);
208 sh_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel,
211 error (0, 0, "%s: SH doesn't support REL relocs", dso->filename);
216 sh_prelink_conflict_rela (DSO *dso, struct prelink_info *info,
217 GElf_Rela *rela, GElf_Addr relaaddr)
220 struct prelink_conflict *conflict;
223 if (GELF_R_TYPE (rela->r_info) == R_SH_RELATIVE
224 || GELF_R_TYPE (rela->r_info) == R_SH_NONE
226 /* Fast path: nothing to do. */
228 conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info),
229 GELF_R_TYPE (rela->r_info));
230 if (conflict == NULL)
232 else if (conflict->ifunc)
234 error (0, 0, "%s: STT_GNU_IFUNC not handled on SuperH yet",
238 value = conflict_lookup_value (conflict);
239 ret = prelink_conflict_add_rela (info);
242 ret->r_offset = rela->r_offset;
243 ret->r_info = GELF_R_INFO (0, GELF_R_TYPE (rela->r_info));
244 value += rela->r_addend;
245 switch (GELF_R_TYPE (rela->r_info))
248 value -= rela->r_offset;
249 ret->r_info = GELF_R_INFO (0, R_SH_DIR32);
252 if ((rela->r_offset & 3) == 0)
253 ret->r_info = GELF_R_INFO (0, R_SH_GLOB_DAT);
257 ret->r_addend = (Elf32_Sword) (value + rela->r_addend);
260 error (0, 0, "R_SH_COPY should not be present in shared libraries");
263 error (0, 0, "%s: Unknown sh relocation type %d", dso->filename,
264 (int) GELF_R_TYPE (rela->r_info));
271 sh_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela)
277 sh_need_rel_to_rela (DSO *dso, int first, int last)
283 sh_arch_prelink (struct prelink_info *info)
289 if (dso->info[DT_PLTGOT])
291 /* Write address of .plt + 36 into got[1].
292 .plt + 36 is what got[3] contains unless prelinking. */
293 int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]);
299 for (i = 1; i < dso->ehdr.e_shnum; i++)
300 if (dso->shdr[i].sh_type == SHT_PROGBITS
301 && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx,
302 dso->shdr[i].sh_name),
306 if (i == dso->ehdr.e_shnum)
308 data = dso->shdr[i].sh_addr + 36;
309 write_ne32 (dso, dso->info[DT_PLTGOT] + 4, data);
316 sh_arch_undo_prelink (DSO *dso)
320 if (dso->info[DT_PLTGOT])
322 /* Clear got[1] if it contains address of .plt + 36. */
323 int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]);
329 for (i = 1; i < dso->ehdr.e_shnum; i++)
330 if (dso->shdr[i].sh_type == SHT_PROGBITS
331 && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx,
332 dso->shdr[i].sh_name),
336 if (i == dso->ehdr.e_shnum)
338 data = read_une32 (dso, dso->info[DT_PLTGOT] + 4);
339 if (data == dso->shdr[i].sh_addr + 36)
340 write_ne32 (dso, dso->info[DT_PLTGOT] + 4, 0);
347 sh_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr)
352 switch (GELF_R_TYPE (rela->r_info))
358 write_le32 (dso, rela->r_offset, 0);
361 sec = addr_to_sec (dso, rela->r_offset);
362 name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[sec].sh_name);
363 if (sec == -1 || (strcmp (name, ".got") && strcmp (name, ".got.plt")))
365 error (0, 0, "%s: R_SH_JMP_SLOT not pointing into .got section",
371 Elf32_Addr data = read_une32 (dso, dso->shdr[sec].sh_addr + 4);
373 assert (rela->r_offset >= dso->shdr[sec].sh_addr + 12);
374 assert (((rela->r_offset - dso->shdr[sec].sh_addr) & 3) == 0);
375 write_ne32 (dso, rela->r_offset,
376 7 * (rela->r_offset - dso->shdr[sec].sh_addr - 12)
383 write_ne32 (dso, rela->r_offset, 0);
386 if (dso->ehdr.e_type == ET_EXEC)
387 /* COPY relocs are handled specially in generic code. */
389 error (0, 0, "%s: R_SH_COPY reloc in shared library?", dso->filename);
392 error (0, 0, "%s: Unknown sh relocation type %d", dso->filename,
393 (int) GELF_R_TYPE (rela->r_info));
400 sh_reloc_size (int reloc_type)
406 sh_reloc_class (int reloc_type)
410 case R_SH_COPY: return RTYPE_CLASS_COPY;
411 case R_SH_JMP_SLOT: return RTYPE_CLASS_PLT;
412 default: return RTYPE_CLASS_VALID;
420 .alternate_machine = { EM_NONE },
421 .R_JMP_SLOT = R_SH_JMP_SLOT,
423 .R_RELATIVE = R_SH_RELATIVE,
424 .rtype_class_valid = RTYPE_CLASS_VALID,
425 .dynamic_linker = "/lib/ld-linux.so.2",
426 .adjust_dyn = sh_adjust_dyn,
427 .adjust_rel = sh_adjust_rel,
428 .adjust_rela = sh_adjust_rela,
429 .prelink_rel = sh_prelink_rel,
430 .prelink_rela = sh_prelink_rela,
431 .prelink_conflict_rel = sh_prelink_conflict_rel,
432 .prelink_conflict_rela = sh_prelink_conflict_rela,
433 .apply_conflict_rela = sh_apply_conflict_rela,
434 .apply_rel = sh_apply_rel,
435 .apply_rela = sh_apply_rela,
436 .rel_to_rela = sh_rel_to_rela,
437 .need_rel_to_rela = sh_need_rel_to_rela,
438 .reloc_size = sh_reloc_size,
439 .reloc_class = sh_reloc_class,
441 .arch_prelink = sh_arch_prelink,
442 .arch_undo_prelink = sh_arch_undo_prelink,
443 .undo_prelink_rela = sh_undo_prelink_rela,
444 /* Although TASK_UNMAPPED_BASE is 0x29555000, we leave some
445 area so that mmap of /etc/ld.so.cache and ld.so's malloc
446 does not take some library's VA slot.
447 Also, if this guard area isn't too small, typically
448 even dlopened libraries will get the slots they desire. */
449 .mmap_base = 0x30000000,
450 .mmap_end = 0x40000000,
451 .max_page_size = 0x2000,