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 cris_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_ule32 (dso, dyn->d_un.d_ptr);
44 /* If .got[0] points to _DYNAMIC, it needs to be adjusted. */
45 if (data == dso->shdr[n].sh_addr && data >= start)
46 write_le32 (dso, dyn->d_un.d_ptr, data + adjust);
48 data = read_ule32 (dso, dyn->d_un.d_ptr + 4);
49 /* If .got[1] points to .plt + 28, 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 + 28
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_le32 (dso, dyn->d_un.d_ptr + 4, data + adjust);
69 cris_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start,
72 error (0, 0, "%s: CRIS doesn't support REL relocs", dso->filename);
77 cris_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start,
82 switch (GELF_R_TYPE (rela->r_info))
85 if ((Elf32_Addr) rela->r_addend >= start)
86 rela->r_addend += (Elf32_Sword) adjust;
88 case R_CRIS_JUMP_SLOT:
89 data = read_ule32 (dso, rela->r_offset);
91 write_le32 (dso, rela->r_offset, data + adjust);
99 cris_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr)
101 error (0, 0, "%s: CRIS doesn't support REL relocs", info->dso->filename);
106 cris_prelink_rela (struct prelink_info *info, GElf_Rela *rela,
113 if (GELF_R_TYPE (rela->r_info) == R_CRIS_NONE)
114 /* Fast path: nothing to do. */
116 else if (GELF_R_TYPE (rela->r_info) == R_CRIS_RELATIVE)
118 write_le32 (dso, rela->r_offset, rela->r_addend);
121 value = info->resolve (info, GELF_R_SYM (rela->r_info),
122 GELF_R_TYPE (rela->r_info));
123 value += rela->r_addend;
124 switch (GELF_R_TYPE (rela->r_info))
126 case R_CRIS_GLOB_DAT:
127 case R_CRIS_JUMP_SLOT:
129 write_le32 (dso, rela->r_offset, value);
132 write_le16 (dso, rela->r_offset, value);
135 write_8 (dso, rela->r_offset, value);
137 case R_CRIS_32_PCREL:
138 write_le32 (dso, rela->r_offset, value - rela->r_offset - 4);
140 case R_CRIS_16_PCREL:
141 write_le16 (dso, rela->r_offset, value - rela->r_offset - 2);
144 write_8 (dso, rela->r_offset, value - rela->r_offset - 1);
147 if (dso->ehdr.e_type == ET_EXEC)
148 /* COPY relocs are handled specially in generic code. */
150 error (0, 0, "%s: R_CRIS_COPY reloc in shared library?", dso->filename);
153 error (0, 0, "%s: Unknown cris relocation type %d", dso->filename,
154 (int) GELF_R_TYPE (rela->r_info));
161 cris_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela,
162 char *buf, GElf_Addr dest_addr)
164 switch (GELF_R_TYPE (rela->r_info))
166 case R_CRIS_GLOB_DAT:
167 case R_CRIS_JUMP_SLOT:
169 buf_write_le32 (buf, rela->r_addend);
172 buf_write_le16 (buf, rela->r_addend);
175 buf_write_8 (buf, rela->r_addend);
184 cris_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf)
186 error (0, 0, "%s: CRIS doesn't support REL relocs", info->dso->filename);
191 cris_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf)
195 value = info->resolve (info, GELF_R_SYM (rela->r_info),
196 GELF_R_TYPE (rela->r_info));
197 value += rela->r_addend;
198 switch (GELF_R_TYPE (rela->r_info))
202 case R_CRIS_GLOB_DAT:
203 case R_CRIS_JUMP_SLOT:
205 buf_write_le32 (buf, value);
208 buf_write_le16 (buf, value);
211 buf_write_8 (buf, value);
213 case R_CRIS_32_PCREL:
214 buf_write_le32 (buf, value - rela->r_offset - 4);
216 case R_CRIS_16_PCREL:
217 buf_write_le16 (buf, value - rela->r_offset - 2);
220 buf_write_8 (buf, value - rela->r_offset - 1);
224 case R_CRIS_RELATIVE:
225 error (0, 0, "%s: R_CRIS_RELATIVE in ET_EXEC object?", info->dso->filename);
234 cris_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel,
237 error (0, 0, "%s: CRIS doesn't support REL relocs", dso->filename);
242 cris_prelink_conflict_rela (DSO *dso, struct prelink_info *info,
243 GElf_Rela *rela, GElf_Addr relaaddr)
246 struct prelink_conflict *conflict;
249 if (GELF_R_TYPE (rela->r_info) == R_CRIS_RELATIVE
250 || GELF_R_TYPE (rela->r_info) == R_CRIS_NONE
252 /* Fast path: nothing to do. */
254 conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info),
255 GELF_R_TYPE (rela->r_info));
256 if (conflict == NULL)
258 else if (conflict->ifunc)
260 error (0, 0, "%s: STT_GNU_IFUNC not handled on CRIS yet",
264 value = conflict_lookup_value (conflict);
265 ret = prelink_conflict_add_rela (info);
268 ret->r_offset = rela->r_offset;
269 ret->r_info = GELF_R_INFO (0, GELF_R_TYPE (rela->r_info));
270 value += rela->r_addend;
271 switch (GELF_R_TYPE (rela->r_info))
273 case R_CRIS_GLOB_DAT:
274 case R_CRIS_JUMP_SLOT:
278 ret->r_addend = (Elf32_Sword) (value + rela->r_addend);
280 case R_CRIS_32_PCREL:
281 ret->r_addend = (Elf32_Sword) (value + rela->r_addend
282 - rela->r_offset - 4);
283 ret->r_info = GELF_R_INFO (0, R_CRIS_32);
285 case R_CRIS_16_PCREL:
286 ret->r_addend = (Elf32_Sword) (value + rela->r_addend
287 - rela->r_offset - 2);
288 ret->r_info = GELF_R_INFO (0, R_CRIS_16);
291 ret->r_addend = (Elf32_Sword) (value + rela->r_addend
292 - rela->r_offset - 1);
293 ret->r_info = GELF_R_INFO (0, R_CRIS_8);
296 error (0, 0, "R_CRIS_COPY should not be present in shared libraries");
299 error (0, 0, "%s: Unknown cris relocation type %d", dso->filename,
300 (int) GELF_R_TYPE (rela->r_info));
307 cris_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela)
313 cris_need_rel_to_rela (DSO *dso, int first, int last)
319 cris_arch_prelink (struct prelink_info *info)
325 if (dso->info[DT_PLTGOT])
327 /* Write address of .plt + 28 into got[1].
328 .plt + 28 is what got[3] contains unless prelinking. */
329 int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]);
335 for (i = 1; i < dso->ehdr.e_shnum; i++)
336 if (dso->shdr[i].sh_type == SHT_PROGBITS
337 && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx,
338 dso->shdr[i].sh_name),
342 assert (i < dso->ehdr.e_shnum);
343 data = dso->shdr[i].sh_addr + 28;
344 write_le32 (dso, dso->info[DT_PLTGOT] + 4, data);
351 cris_reloc_size (int reloc_type)
356 case R_CRIS_16_PCREL:
367 cris_reloc_class (int reloc_type)
371 case R_CRIS_COPY: return RTYPE_CLASS_COPY;
372 case R_CRIS_JUMP_SLOT: return RTYPE_CLASS_PLT;
373 default: return RTYPE_CLASS_VALID;
381 .alternate_machine = { EM_NONE },
382 .R_JUMP_SLOT = R_CRIS_JUMP_SLOT,
383 .R_COPY = R_CRIS_COPY,
384 .R_RELATIVE = R_CRIS_RELATIVE,
385 .rtype_class_valid = RTYPE_CLASS_VALID,
386 .dynamic_linker = "/lib/ld.so.1",
387 .adjust_dyn = cris_adjust_dyn,
388 .adjust_rel = cris_adjust_rel,
389 .adjust_rela = cris_adjust_rela,
390 .prelink_rel = cris_prelink_rel,
391 .prelink_rela = cris_prelink_rela,
392 .prelink_conflict_rel = cris_prelink_conflict_rel,
393 .prelink_conflict_rela = cris_prelink_conflict_rela,
394 .apply_conflict_rela = cris_apply_conflict_rela,
395 .apply_rel = cris_apply_rel,
396 .apply_rela = cris_apply_rela,
397 .rel_to_rela = cris_rel_to_rela,
398 .need_rel_to_rela = cris_need_rel_to_rela,
399 .reloc_size = cris_reloc_size,
400 .reloc_class = cris_reloc_class,
402 .arch_prelink = cris_arch_prelink,
403 /* Although TASK_UNMAPPED_BASE is 0x3aaaa000, we leave some
404 area so that mmap of /etc/ld.so.cache and ld.so's malloc
405 does not take some library's VA slot.
406 Also, if this guard area isn't too small, typically
407 even dlopened libraries will get the slots they desire. */
408 .mmap_base = 0x3c000000,
409 .mmap_end = 0x48000000,
410 .max_page_size = 0x2000,