elf32-epiphany.c revision 1.1.1.2 1 1.1 christos /* Adapteva epiphany specific support for 32-bit ELF
2 1.1 christos Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2011, 2012
3 1.1 christos Free Software Foundation, Inc.
4 1.1 christos Contributed by Embecosm on behalf of Adapteva, Inc.
5 1.1 christos
6 1.1 christos This file is part of BFD, the Binary File Descriptor library.
7 1.1 christos
8 1.1 christos This program is free software; you can redistribute it and/or modify
9 1.1 christos it under the terms of the GNU General Public License as published by
10 1.1 christos the Free Software Foundation; either version 3 of the License, or
11 1.1 christos (at your option) any later version.
12 1.1 christos
13 1.1 christos This program is distributed in the hope that it will be useful,
14 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
15 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 1.1 christos GNU General Public License for more details.
17 1.1 christos
18 1.1 christos You should have received a copy of the GNU General Public License
19 1.1 christos along with this program; if not, write to the Free Software
20 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 1.1 christos MA 02110-1301, USA. */
22 1.1 christos
23 1.1 christos #include "sysdep.h"
24 1.1 christos #include "bfd.h"
25 1.1 christos #include "libbfd.h"
26 1.1 christos #include "elf-bfd.h"
27 1.1 christos #include "elf/epiphany.h"
28 1.1 christos #include "libiberty.h"
29 1.1 christos
30 1.1 christos /* Struct used to pass miscellaneous paramaters which
31 1.1 christos helps to avoid overly long parameter lists. */
32 1.1 christos struct misc
33 1.1 christos {
34 1.1 christos Elf_Internal_Shdr * symtab_hdr;
35 1.1 christos Elf_Internal_Rela * irelbase;
36 1.1 christos bfd_byte * contents;
37 1.1 christos Elf_Internal_Sym * isymbuf;
38 1.1 christos };
39 1.1 christos
40 1.1 christos struct epiphany_opcode
41 1.1 christos {
42 1.1 christos unsigned short opcode;
43 1.1 christos unsigned short mask;
44 1.1 christos };
45 1.1 christos
46 1.1 christos static bfd_boolean epiphany_relaxed = FALSE;
47 1.1 christos
48 1.1 christos /* Relocation tables. */
49 1.1 christos static reloc_howto_type epiphany_elf_howto_table [] =
50 1.1 christos {
51 1.1 christos #define AHOW(t,rs,s,bs,pr,bp,co,name,sm,dm) \
52 1.1 christos HOWTO(t, /* type */ \
53 1.1 christos rs, /* rightshift */ \
54 1.1 christos s, /* size (0 = byte, 1 = short, 2 = long) */ \
55 1.1 christos bs, /* bitsize */ \
56 1.1 christos pr, /* pc_relative */ \
57 1.1 christos bp, /* bitpos */ \
58 1.1 christos co, /* complain_on_overflow */ \
59 1.1 christos bfd_elf_generic_reloc,/* special_function */ \
60 1.1 christos name, /* name */ \
61 1.1 christos FALSE, /* partial_inplace */ \
62 1.1 christos sm, /* src_mask */ \
63 1.1 christos dm, /* dst_mask */ \
64 1.1 christos pr) /* pcrel_offset */
65 1.1 christos
66 1.1 christos /* This reloc does nothing. */
67 1.1 christos AHOW (R_EPIPHANY_NONE, 0, 0,32, FALSE, 0, complain_overflow_dont, "R_EPIPHANY_NONE", 0, 0),
68 1.1 christos
69 1.1 christos /* 8 bit absolute (not likely) */
70 1.1 christos AHOW (R_EPIPHANY_8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_8", 0x000000ff, 0x000000ff),
71 1.1 christos /* 16 bit absolute */
72 1.1 christos AHOW (R_EPIPHANY_16, 0, 1,16, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_16", 0x0000ffff, 0x00ff1fe0),
73 1.1 christos /* A 32 bit absolute relocation. */
74 1.1 christos AHOW (R_EPIPHANY_32, 0, 2,32, FALSE, 0, complain_overflow_dont, "R_EPIPHANY_32", 0xffffffff, 0xffffffff),
75 1.1 christos
76 1.1 christos /* 8 bit relative relocation */
77 1.1 christos HOWTO ( R_EPIPHANY_8_PCREL, 0, 0, 8, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_EPIPHANY_8_PCREL", FALSE, 0x000000ff, 0x000000ff, FALSE),
78 1.1 christos /* 16 bit relative relocation */
79 1.1 christos HOWTO ( R_EPIPHANY_16_PCREL, 0, 1, 16, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_EPIPHANY_8_PCREL", FALSE, 0x000000ff, 0x000000ff, FALSE),
80 1.1 christos /* 32 bit relative relocation */
81 1.1 christos HOWTO ( R_EPIPHANY_32_PCREL, 0, 2, 32, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_EPIPHANY_8_PCREL", FALSE, 0x000000ff, 0x000000ff, FALSE),
82 1.1 christos
83 1.1 christos /* 8 bit pc-relative relocation */
84 1.1 christos AHOW (R_EPIPHANY_SIMM8, 1, 0, 8, TRUE, 8, complain_overflow_signed, "R_EPIPHANY_SIMM8", 0x000000ff, 0x0000ff00),
85 1.1 christos /* 24 bit pc-relative relocation */
86 1.1 christos AHOW (R_EPIPHANY_SIMM24, 1, 2,24, TRUE, 8, complain_overflow_signed, "R_EPIPHANY_SIMM24", 0x00ffffff, 0xffffff00),
87 1.1 christos
88 1.1 christos /* %HIGH(EA) */
89 1.1 christos AHOW (R_EPIPHANY_HIGH, 0, 2,16, FALSE, 0, complain_overflow_dont, "R_EPIPHANY_HIGH", 0x0ff01fe0, 0x0ff01fe0),
90 1.1 christos
91 1.1 christos /* %LOW(EA) */
92 1.1 christos AHOW (R_EPIPHANY_LOW, 0, 2,16, FALSE, 0, complain_overflow_dont, "R_EPIPHANY_LOW", 0x0ff01fe0, 0x0ff01fe0),
93 1.1 christos
94 1.1 christos /* simm11 */
95 1.1 christos AHOW (R_EPIPHANY_SIMM11, 0, 2,11, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_SIMM11", 0x00ff0380, 0x00ff0380),
96 1.1 christos /* imm12 - sign-magnitude */
97 1.1 christos AHOW (R_EPIPHANY_IMM11, 0, 2,11, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_IMM12", 0x00ff0380, 0x00ff0380),
98 1.1 christos /* imm8 */
99 1.1 christos AHOW (R_EPIPHANY_IMM8, 0, 1, 8, FALSE, 8, complain_overflow_signed, "R_EPIPHANY_IMM8", 0x0000ff00, 0x0000ff00)
100 1.1 christos
101 1.1 christos
102 1.1 christos };
103 1.1 christos #undef AHOW
104 1.1 christos
105 1.1 christos /* Map BFD reloc types to EPIPHANY ELF reloc types. */
106 1.1 christos
107 1.1 christos static reloc_howto_type *
108 1.1 christos epiphany_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
109 1.1 christos bfd_reloc_code_real_type code)
110 1.1 christos {
111 1.1 christos /* Note that the epiphany_elf_howto_table is indxed by the R_
112 1.1 christos constants. Thus, the order that the howto records appear in the
113 1.1 christos table *must* match the order of the relocation types defined in
114 1.1 christos include/elf/epiphany.h. */
115 1.1 christos
116 1.1 christos switch (code)
117 1.1 christos {
118 1.1 christos case BFD_RELOC_NONE:
119 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_NONE];
120 1.1 christos
121 1.1 christos case BFD_RELOC_EPIPHANY_SIMM8:
122 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_SIMM8];
123 1.1 christos case BFD_RELOC_EPIPHANY_SIMM24:
124 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_SIMM24];
125 1.1 christos
126 1.1 christos case BFD_RELOC_8_PCREL:
127 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_8_PCREL];
128 1.1 christos case BFD_RELOC_16_PCREL:
129 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_16_PCREL];
130 1.1 christos case BFD_RELOC_32_PCREL:
131 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_32_PCREL];
132 1.1 christos
133 1.1 christos case BFD_RELOC_8:
134 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_8];
135 1.1 christos case BFD_RELOC_16:
136 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_16];
137 1.1 christos case BFD_RELOC_32:
138 1.1 christos return &epiphany_elf_howto_table[ (int) R_EPIPHANY_32];
139 1.1 christos
140 1.1 christos case BFD_RELOC_EPIPHANY_HIGH:
141 1.1 christos return & epiphany_elf_howto_table[ (int) R_EPIPHANY_HIGH];
142 1.1 christos case BFD_RELOC_EPIPHANY_LOW:
143 1.1 christos return & epiphany_elf_howto_table[ (int) R_EPIPHANY_LOW];
144 1.1 christos
145 1.1 christos case BFD_RELOC_EPIPHANY_SIMM11:
146 1.1 christos return & epiphany_elf_howto_table[ (int) R_EPIPHANY_SIMM11];
147 1.1 christos case BFD_RELOC_EPIPHANY_IMM11:
148 1.1 christos return & epiphany_elf_howto_table[ (int) R_EPIPHANY_IMM11];
149 1.1 christos
150 1.1 christos case BFD_RELOC_EPIPHANY_IMM8:
151 1.1 christos return & epiphany_elf_howto_table[ (int) R_EPIPHANY_IMM8];
152 1.1 christos
153 1.1 christos default:
154 1.1 christos /* Pacify gcc -Wall. */
155 1.1 christos return NULL;
156 1.1 christos }
157 1.1 christos return NULL;
158 1.1 christos }
159 1.1 christos
160 1.1 christos static reloc_howto_type *
161 1.1 christos epiphany_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
162 1.1 christos {
163 1.1 christos unsigned int i;
164 1.1 christos
165 1.1 christos for (i = 0; i < ARRAY_SIZE (epiphany_elf_howto_table); i++)
166 1.1 christos if (epiphany_elf_howto_table[i].name != NULL
167 1.1 christos && strcasecmp (epiphany_elf_howto_table[i].name, r_name) == 0)
168 1.1 christos return &epiphany_elf_howto_table[i];
169 1.1 christos
170 1.1 christos return NULL;
171 1.1 christos }
172 1.1 christos
173 1.1 christos #define PAGENO(ABSADDR) ((ABSADDR) & 0xFFFFC000)
174 1.1 christos #define BASEADDR(SEC) ((SEC)->output_section->vma + (SEC)->output_offset)
175 1.1 christos
176 1.1 christos /* This function handles relaxing for the epiphany.
177 1.1 christos Dummy placeholder for future optimizations. */
178 1.1 christos
179 1.1 christos static bfd_boolean
180 1.1 christos epiphany_elf_relax_section (bfd *abfd, asection *sec,
181 1.1 christos struct bfd_link_info *link_info,
182 1.1 christos bfd_boolean *again)
183 1.1 christos {
184 1.1 christos Elf_Internal_Shdr *symtab_hdr;
185 1.1 christos Elf_Internal_Rela *internal_relocs;
186 1.1 christos bfd_byte *contents = NULL;
187 1.1 christos Elf_Internal_Sym *isymbuf = NULL;
188 1.1 christos static asection * first_section = NULL;
189 1.1 christos static unsigned long search_addr;
190 1.1 christos static unsigned long page_start = 0;
191 1.1 christos static unsigned long page_end = 0;
192 1.1 christos static unsigned int pass = 0;
193 1.1 christos static bfd_boolean new_pass = FALSE;
194 1.1 christos static bfd_boolean changed = FALSE;
195 1.1 christos struct misc misc ATTRIBUTE_UNUSED;
196 1.1 christos asection *stab;
197 1.1 christos
198 1.1 christos /* Assume nothing changes. */
199 1.1 christos *again = FALSE;
200 1.1 christos
201 1.1 christos if (first_section == NULL)
202 1.1 christos {
203 1.1 christos epiphany_relaxed = TRUE;
204 1.1 christos first_section = sec;
205 1.1 christos }
206 1.1 christos
207 1.1 christos if (first_section == sec)
208 1.1 christos {
209 1.1 christos pass++;
210 1.1 christos new_pass = TRUE;
211 1.1 christos }
212 1.1 christos
213 1.1 christos /* We don't have to do anything for a relocatable link,
214 1.1 christos if this section does not have relocs, or if this is
215 1.1 christos not a code section. */
216 1.1 christos if (link_info->relocatable
217 1.1 christos || (sec->flags & SEC_RELOC) == 0
218 1.1 christos || sec->reloc_count == 0
219 1.1 christos || (sec->flags & SEC_CODE) == 0)
220 1.1 christos return TRUE;
221 1.1 christos
222 1.1 christos symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
223 1.1 christos
224 1.1 christos internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
225 1.1 christos link_info->keep_memory);
226 1.1 christos if (internal_relocs == NULL)
227 1.1 christos goto error_return;
228 1.1 christos
229 1.1 christos /* Make sure the stac.rela stuff gets read in. */
230 1.1 christos stab = bfd_get_section_by_name (abfd, ".stab");
231 1.1 christos
232 1.1 christos if (stab)
233 1.1 christos {
234 1.1 christos /* So stab does exits. */
235 1.1 christos Elf_Internal_Rela * irelbase ATTRIBUTE_UNUSED;
236 1.1 christos
237 1.1 christos irelbase = _bfd_elf_link_read_relocs (abfd, stab, NULL, NULL,
238 1.1 christos link_info->keep_memory);
239 1.1 christos }
240 1.1 christos
241 1.1 christos /* Get section contents cached copy if it exists. */
242 1.1 christos if (contents == NULL)
243 1.1 christos {
244 1.1 christos /* Get cached copy if it exists. */
245 1.1 christos if (elf_section_data (sec)->this_hdr.contents != NULL)
246 1.1 christos contents = elf_section_data (sec)->this_hdr.contents;
247 1.1 christos else
248 1.1 christos {
249 1.1 christos /* Go get them off disk. */
250 1.1 christos if (!bfd_malloc_and_get_section (abfd, sec, &contents))
251 1.1 christos goto error_return;
252 1.1 christos }
253 1.1 christos }
254 1.1 christos
255 1.1 christos /* Read this BFD's symbols cached copy if it exists. */
256 1.1 christos if (isymbuf == NULL && symtab_hdr->sh_info != 0)
257 1.1 christos {
258 1.1 christos isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
259 1.1 christos if (isymbuf == NULL)
260 1.1 christos isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
261 1.1 christos symtab_hdr->sh_info, 0,
262 1.1 christos NULL, NULL, NULL);
263 1.1 christos if (isymbuf == NULL)
264 1.1 christos goto error_return;
265 1.1 christos }
266 1.1 christos
267 1.1 christos misc.symtab_hdr = symtab_hdr;
268 1.1 christos misc.isymbuf = isymbuf;
269 1.1 christos misc.irelbase = internal_relocs;
270 1.1 christos misc.contents = contents;
271 1.1 christos
272 1.1 christos /* This is where all the relaxation actually get done. */
273 1.1 christos if ((pass == 1) || (new_pass && !changed))
274 1.1 christos {
275 1.1 christos /* On the first pass we simply search for the lowest page that
276 1.1 christos we havn't relaxed yet. Note that the pass count is reset
277 1.1 christos each time a page is complete in order to move on to the next page.
278 1.1 christos If we can't find any more pages then we are finished. */
279 1.1 christos if (new_pass)
280 1.1 christos {
281 1.1 christos pass = 1;
282 1.1 christos new_pass = FALSE;
283 1.1 christos changed = TRUE; /* Pre-initialize to break out of pass 1. */
284 1.1 christos search_addr = 0xFFFFFFFF;
285 1.1 christos }
286 1.1 christos
287 1.1 christos if ((BASEADDR (sec) + sec->size < search_addr)
288 1.1 christos && (BASEADDR (sec) + sec->size > page_end))
289 1.1 christos {
290 1.1 christos if (BASEADDR (sec) <= page_end)
291 1.1 christos search_addr = page_end + 1;
292 1.1 christos else
293 1.1 christos search_addr = BASEADDR (sec);
294 1.1 christos
295 1.1 christos /* Found a page => more work to do. */
296 1.1 christos *again = TRUE;
297 1.1 christos }
298 1.1 christos }
299 1.1 christos else
300 1.1 christos {
301 1.1 christos if (new_pass)
302 1.1 christos {
303 1.1 christos new_pass = FALSE;
304 1.1 christos changed = FALSE;
305 1.1 christos page_start = PAGENO (search_addr);
306 1.1 christos page_end = page_start | 0x00003FFF;
307 1.1 christos }
308 1.1 christos
309 1.1 christos /* Only process sections in range. */
310 1.1 christos if ((BASEADDR (sec) + sec->size >= page_start)
311 1.1 christos && (BASEADDR (sec) <= page_end))
312 1.1 christos {
313 1.1 christos #if 0
314 1.1 christos if (!epiphany_elf_relax_section_page (abfd, sec, &changed, &misc,
315 1.1 christos page_start, page_end))
316 1.1 christos #endif
317 1.1 christos return FALSE;
318 1.1 christos }
319 1.1 christos *again = TRUE;
320 1.1 christos }
321 1.1 christos
322 1.1 christos /* Perform some house keeping after relaxing the section. */
323 1.1 christos
324 1.1 christos if (isymbuf != NULL
325 1.1 christos && symtab_hdr->contents != (unsigned char *) isymbuf)
326 1.1 christos {
327 1.1 christos if (! link_info->keep_memory)
328 1.1 christos free (isymbuf);
329 1.1 christos else
330 1.1 christos symtab_hdr->contents = (unsigned char *) isymbuf;
331 1.1 christos }
332 1.1 christos
333 1.1 christos if (contents != NULL
334 1.1 christos && elf_section_data (sec)->this_hdr.contents != contents)
335 1.1 christos {
336 1.1 christos if (! link_info->keep_memory)
337 1.1 christos free (contents);
338 1.1 christos else
339 1.1 christos {
340 1.1 christos /* Cache the section contents for elf_link_input_bfd. */
341 1.1 christos elf_section_data (sec)->this_hdr.contents = contents;
342 1.1 christos }
343 1.1 christos }
344 1.1 christos
345 1.1 christos if (internal_relocs != NULL
346 1.1 christos && elf_section_data (sec)->relocs != internal_relocs)
347 1.1 christos free (internal_relocs);
348 1.1 christos
349 1.1 christos return TRUE;
350 1.1 christos
351 1.1 christos error_return:
352 1.1 christos if (isymbuf != NULL
353 1.1 christos && symtab_hdr->contents != (unsigned char *) isymbuf)
354 1.1 christos free (isymbuf);
355 1.1 christos if (contents != NULL
356 1.1 christos && elf_section_data (sec)->this_hdr.contents != contents)
357 1.1 christos free (contents);
358 1.1 christos if (internal_relocs != NULL
359 1.1 christos && elf_section_data (sec)->relocs != internal_relocs)
360 1.1 christos free (internal_relocs);
361 1.1 christos return FALSE;
362 1.1 christos }
363 1.1 christos
364 1.1 christos /* Set the howto pointer for a EPIPHANY ELF reloc. */
365 1.1 christos
366 1.1 christos static void
367 1.1 christos epiphany_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
368 1.1 christos arelent * cache_ptr,
369 1.1 christos Elf_Internal_Rela * dst)
370 1.1 christos {
371 1.1 christos unsigned int r_type;
372 1.1 christos
373 1.1 christos r_type = ELF32_R_TYPE (dst->r_info);
374 1.1 christos cache_ptr->howto = & epiphany_elf_howto_table [r_type];
375 1.1 christos }
376 1.1 christos
377 1.1 christos /* Perform a single relocation.
378 1.1 christos By default we use the standard BFD routines. */
379 1.1 christos
380 1.1 christos static bfd_reloc_status_type
381 1.1 christos epiphany_final_link_relocate (reloc_howto_type * howto,
382 1.1 christos bfd * input_bfd,
383 1.1 christos asection * input_section,
384 1.1 christos bfd_byte * contents,
385 1.1 christos Elf_Internal_Rela * rel,
386 1.1 christos bfd_vma relocation)
387 1.1 christos {
388 1.1 christos switch (howto->type)
389 1.1 christos {
390 1.1 christos /* Handle 16 bit immediates. */
391 1.1 christos case R_EPIPHANY_HIGH:
392 1.1 christos relocation += rel->r_addend;
393 1.1 christos relocation >>= 16;
394 1.1 christos goto common;
395 1.1 christos
396 1.1 christos case R_EPIPHANY_LOW:
397 1.1 christos relocation += rel->r_addend;
398 1.1 christos common:
399 1.1 christos relocation = ((relocation & 0xff00L) << 12)
400 1.1 christos | ((relocation & 0x00ffL) << 5);
401 1.1 christos /* Sanity check the address. */
402 1.1 christos if (rel->r_offset > bfd_get_section_limit (input_bfd, input_section))
403 1.1 christos return bfd_reloc_outofrange;
404 1.1 christos
405 1.1 christos return _bfd_relocate_contents (howto, input_bfd, relocation,
406 1.1 christos contents + rel->r_offset);
407 1.1 christos
408 1.1 christos case R_EPIPHANY_SIMM11:
409 1.1 christos relocation += rel->r_addend;
410 1.1 christos /* Check signed overflow. */
411 1.1 christos if ((int)relocation > 1023 || (int)relocation < -1024)
412 1.1 christos return bfd_reloc_outofrange;
413 1.1 christos goto disp11;
414 1.1 christos
415 1.1 christos case R_EPIPHANY_IMM11:
416 1.1 christos relocation += rel->r_addend;
417 1.1 christos if ((unsigned int) relocation > 0x7ff)
418 1.1 christos return bfd_reloc_outofrange;
419 1.1 christos disp11:
420 1.1 christos relocation = ((relocation & 7) << 5)
421 1.1 christos || ((relocation & 0x7f8 ) << 13);
422 1.1 christos return _bfd_relocate_contents (howto, input_bfd, relocation,
423 1.1 christos contents + rel->r_offset);
424 1.1 christos
425 1.1 christos /* Pass others through. */
426 1.1 christos default:
427 1.1 christos break;
428 1.1 christos }
429 1.1 christos
430 1.1 christos /* Only install relocation if above tests did not disqualify it. */
431 1.1 christos return _bfd_final_link_relocate (howto, input_bfd, input_section,
432 1.1 christos contents, rel->r_offset,
433 1.1 christos relocation, rel->r_addend);
434 1.1 christos }
435 1.1 christos
436 1.1 christos /* Relocate an EPIPHANY ELF section.
437 1.1 christos
438 1.1 christos The RELOCATE_SECTION function is called by the new ELF backend linker
439 1.1 christos to handle the relocations for a section.
440 1.1 christos
441 1.1 christos The relocs are always passed as Rela structures; if the section
442 1.1 christos actually uses Rel structures, the r_addend field will always be
443 1.1 christos zero.
444 1.1 christos
445 1.1 christos This function is responsible for adjusting the section contents as
446 1.1 christos necessary, and (if using Rela relocs and generating a relocatable
447 1.1 christos output file) adjusting the reloc addend as necessary.
448 1.1 christos
449 1.1 christos This function does not have to worry about setting the reloc
450 1.1 christos address or the reloc symbol index.
451 1.1 christos
452 1.1 christos LOCAL_SYMS is a pointer to the swapped in local symbols.
453 1.1 christos
454 1.1 christos LOCAL_SECTIONS is an array giving the section in the input file
455 1.1 christos corresponding to the st_shndx field of each local symbol.
456 1.1 christos
457 1.1 christos The global hash table entry for the global symbols can be found
458 1.1 christos via elf_sym_hashes (input_bfd).
459 1.1 christos
460 1.1 christos When generating relocatable output, this function must handle
461 1.1 christos STB_LOCAL/STT_SECTION symbols specially. The output symbol is
462 1.1 christos going to be the section symbol corresponding to the output
463 1.1 christos section, which means that the addend must be adjusted
464 1.1 christos accordingly. */
465 1.1 christos
466 1.1 christos static bfd_boolean
467 1.1 christos epiphany_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
468 1.1 christos struct bfd_link_info *info,
469 1.1 christos bfd *input_bfd,
470 1.1 christos asection *input_section,
471 1.1 christos bfd_byte *contents,
472 1.1 christos Elf_Internal_Rela *relocs,
473 1.1 christos Elf_Internal_Sym *local_syms,
474 1.1 christos asection **local_sections)
475 1.1 christos {
476 1.1 christos Elf_Internal_Shdr *symtab_hdr;
477 1.1 christos struct elf_link_hash_entry **sym_hashes;
478 1.1 christos Elf_Internal_Rela *rel;
479 1.1 christos Elf_Internal_Rela *relend;
480 1.1 christos
481 1.1 christos symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
482 1.1 christos sym_hashes = elf_sym_hashes (input_bfd);
483 1.1 christos relend = relocs + input_section->reloc_count;
484 1.1 christos
485 1.1 christos for (rel = relocs; rel < relend; rel ++)
486 1.1 christos {
487 1.1 christos reloc_howto_type * howto;
488 1.1 christos unsigned long r_symndx;
489 1.1 christos Elf_Internal_Sym * sym;
490 1.1 christos asection * sec;
491 1.1 christos struct elf_link_hash_entry * h;
492 1.1 christos bfd_vma relocation;
493 1.1 christos bfd_reloc_status_type r;
494 1.1 christos const char * name = NULL;
495 1.1 christos int r_type ATTRIBUTE_UNUSED;
496 1.1 christos
497 1.1 christos r_type = ELF32_R_TYPE (rel->r_info);
498 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info);
499 1.1 christos howto = epiphany_elf_howto_table + ELF32_R_TYPE (rel->r_info);
500 1.1 christos h = NULL;
501 1.1 christos sym = NULL;
502 1.1 christos sec = NULL;
503 1.1 christos
504 1.1 christos if (r_symndx < symtab_hdr->sh_info)
505 1.1 christos {
506 1.1 christos sym = local_syms + r_symndx;
507 1.1 christos sec = local_sections [r_symndx];
508 1.1 christos relocation = BASEADDR (sec) + sym->st_value;
509 1.1 christos
510 1.1 christos name = bfd_elf_string_from_elf_section
511 1.1 christos (input_bfd, symtab_hdr->sh_link, sym->st_name);
512 1.1 christos name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
513 1.1 christos }
514 1.1 christos else
515 1.1 christos {
516 1.1 christos bfd_boolean warned ATTRIBUTE_UNUSED;
517 1.1 christos bfd_boolean unresolved_reloc ATTRIBUTE_UNUSED;
518 1.1.1.2 christos bfd_boolean ignored ATTRIBUTE_UNUSED;
519 1.1 christos
520 1.1 christos RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
521 1.1 christos r_symndx, symtab_hdr, sym_hashes,
522 1.1 christos h, sec, relocation,
523 1.1.1.2 christos unresolved_reloc, warned, ignored);
524 1.1 christos
525 1.1 christos name = h->root.root.string;
526 1.1 christos }
527 1.1 christos
528 1.1 christos if (sec != NULL && discarded_section (sec))
529 1.1 christos RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
530 1.1 christos rel, 1, relend, howto, 0, contents);
531 1.1 christos
532 1.1 christos if (info->relocatable)
533 1.1 christos continue;
534 1.1 christos
535 1.1 christos /* Finally, the sole EPIPHANY-specific part. */
536 1.1 christos r = epiphany_final_link_relocate (howto, input_bfd, input_section,
537 1.1 christos contents, rel, relocation);
538 1.1 christos
539 1.1 christos if (r != bfd_reloc_ok)
540 1.1 christos {
541 1.1 christos const char * msg = NULL;
542 1.1 christos
543 1.1 christos switch (r)
544 1.1 christos {
545 1.1 christos case bfd_reloc_overflow:
546 1.1 christos r = info->callbacks->reloc_overflow
547 1.1 christos (info, (h ? &h->root : NULL), name, howto->name,
548 1.1 christos (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
549 1.1 christos break;
550 1.1 christos
551 1.1 christos case bfd_reloc_undefined:
552 1.1 christos r = info->callbacks->undefined_symbol
553 1.1 christos (info, name, input_bfd, input_section, rel->r_offset, TRUE);
554 1.1 christos break;
555 1.1 christos
556 1.1 christos case bfd_reloc_outofrange:
557 1.1 christos msg = _("internal error: out of range error");
558 1.1 christos break;
559 1.1 christos
560 1.1 christos /* This is how epiphany_final_link_relocate tells us of a
561 1.1 christos non-kosher reference between insn & data address spaces. */
562 1.1 christos case bfd_reloc_notsupported:
563 1.1 christos if (sym != NULL) /* Only if it's not an unresolved symbol. */
564 1.1 christos msg = _("unsupported relocation between data/insn address spaces");
565 1.1 christos break;
566 1.1 christos
567 1.1 christos case bfd_reloc_dangerous:
568 1.1 christos msg = _("internal error: dangerous relocation");
569 1.1 christos break;
570 1.1 christos
571 1.1 christos default:
572 1.1 christos msg = _("internal error: unknown error");
573 1.1 christos break;
574 1.1 christos }
575 1.1 christos
576 1.1 christos if (msg)
577 1.1 christos r = info->callbacks->warning
578 1.1 christos (info, msg, name, input_bfd, input_section, rel->r_offset);
579 1.1 christos
580 1.1 christos if (! r)
581 1.1 christos return FALSE;
582 1.1 christos }
583 1.1 christos }
584 1.1 christos
585 1.1 christos return TRUE;
586 1.1 christos }
587 1.1 christos
588 1.1 christos /* We only have a little-endian target. */
589 1.1 christos #define TARGET_LITTLE_SYM bfd_elf32_epiphany_vec
590 1.1 christos #define TARGET_LITTLE_NAME "elf32-epiphany"
591 1.1 christos
592 1.1 christos #define ELF_ARCH bfd_arch_epiphany
593 1.1 christos #define ELF_MACHINE_CODE EM_ADAPTEVA_EPIPHANY
594 1.1 christos
595 1.1 christos #define ELF_MAXPAGESIZE 0x8000 /* No pages on the EPIPHANY. */
596 1.1 christos
597 1.1 christos #define elf_info_to_howto_rel NULL
598 1.1 christos #define elf_info_to_howto epiphany_info_to_howto_rela
599 1.1 christos
600 1.1 christos #define elf_backend_can_gc_sections 1
601 1.1 christos #define elf_backend_rela_normal 1
602 1.1 christos #define elf_backend_relocate_section epiphany_elf_relocate_section
603 1.1 christos
604 1.1 christos #define elf_symbol_leading_char '_'
605 1.1 christos #define bfd_elf32_bfd_reloc_type_lookup epiphany_reloc_type_lookup
606 1.1 christos #define bfd_elf32_bfd_reloc_name_lookup epiphany_reloc_name_lookup
607 1.1 christos #define bfd_elf32_bfd_relax_section epiphany_elf_relax_section
608 1.1 christos
609 1.1 christos #include "elf32-target.h"
610