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