elf32-epiphany.c revision 1.1.1.6 1 1.1 christos /* Adapteva epiphany specific support for 32-bit ELF
2 1.1.1.6 christos Copyright (C) 2000-2022 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->flags & SEC_RELOC) == 0
217 1.1 christos || sec->reloc_count == 0
218 1.1 christos || (sec->flags & SEC_CODE) == 0)
219 1.1.1.6 christos return true;
220 1.1 christos
221 1.1 christos symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
222 1.1 christos
223 1.1 christos internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
224 1.1 christos link_info->keep_memory);
225 1.1 christos if (internal_relocs == NULL)
226 1.1 christos goto error_return;
227 1.1 christos
228 1.1 christos /* Make sure the stac.rela stuff gets read in. */
229 1.1 christos stab = bfd_get_section_by_name (abfd, ".stab");
230 1.1 christos
231 1.1 christos if (stab)
232 1.1 christos {
233 1.1 christos /* So stab does exits. */
234 1.1 christos Elf_Internal_Rela * irelbase ATTRIBUTE_UNUSED;
235 1.1 christos
236 1.1 christos irelbase = _bfd_elf_link_read_relocs (abfd, stab, NULL, NULL,
237 1.1 christos link_info->keep_memory);
238 1.1 christos }
239 1.1 christos
240 1.1 christos /* Get section contents cached copy if it exists. */
241 1.1 christos if (contents == NULL)
242 1.1 christos {
243 1.1 christos /* Get cached copy if it exists. */
244 1.1 christos if (elf_section_data (sec)->this_hdr.contents != NULL)
245 1.1 christos contents = elf_section_data (sec)->this_hdr.contents;
246 1.1 christos else
247 1.1 christos {
248 1.1 christos /* Go get them off disk. */
249 1.1 christos if (!bfd_malloc_and_get_section (abfd, sec, &contents))
250 1.1 christos goto error_return;
251 1.1 christos }
252 1.1 christos }
253 1.1 christos
254 1.1 christos /* Read this BFD's symbols cached copy if it exists. */
255 1.1 christos if (isymbuf == NULL && symtab_hdr->sh_info != 0)
256 1.1 christos {
257 1.1 christos isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
258 1.1 christos if (isymbuf == NULL)
259 1.1 christos isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
260 1.1 christos symtab_hdr->sh_info, 0,
261 1.1 christos NULL, NULL, NULL);
262 1.1 christos if (isymbuf == NULL)
263 1.1 christos goto error_return;
264 1.1 christos }
265 1.1 christos
266 1.1 christos misc.symtab_hdr = symtab_hdr;
267 1.1 christos misc.isymbuf = isymbuf;
268 1.1 christos misc.irelbase = internal_relocs;
269 1.1 christos misc.contents = contents;
270 1.1 christos
271 1.1 christos /* This is where all the relaxation actually get done. */
272 1.1 christos if ((pass == 1) || (new_pass && !changed))
273 1.1 christos {
274 1.1 christos /* On the first pass we simply search for the lowest page that
275 1.1 christos we havn't relaxed yet. Note that the pass count is reset
276 1.1 christos each time a page is complete in order to move on to the next page.
277 1.1 christos If we can't find any more pages then we are finished. */
278 1.1 christos if (new_pass)
279 1.1 christos {
280 1.1 christos pass = 1;
281 1.1.1.6 christos new_pass = false;
282 1.1.1.6 christos changed = true; /* Pre-initialize to break out of pass 1. */
283 1.1 christos search_addr = 0xFFFFFFFF;
284 1.1 christos }
285 1.1 christos
286 1.1 christos if ((BASEADDR (sec) + sec->size < search_addr)
287 1.1 christos && (BASEADDR (sec) + sec->size > page_end))
288 1.1 christos {
289 1.1 christos if (BASEADDR (sec) <= page_end)
290 1.1 christos search_addr = page_end + 1;
291 1.1 christos else
292 1.1 christos search_addr = BASEADDR (sec);
293 1.1 christos
294 1.1 christos /* Found a page => more work to do. */
295 1.1.1.6 christos *again = true;
296 1.1 christos }
297 1.1 christos }
298 1.1 christos else
299 1.1 christos {
300 1.1 christos if (new_pass)
301 1.1 christos {
302 1.1.1.6 christos new_pass = false;
303 1.1.1.6 christos changed = false;
304 1.1 christos page_start = PAGENO (search_addr);
305 1.1 christos page_end = page_start | 0x00003FFF;
306 1.1 christos }
307 1.1 christos
308 1.1 christos /* Only process sections in range. */
309 1.1 christos if ((BASEADDR (sec) + sec->size >= page_start)
310 1.1 christos && (BASEADDR (sec) <= page_end))
311 1.1 christos {
312 1.1 christos #if 0
313 1.1 christos if (!epiphany_elf_relax_section_page (abfd, sec, &changed, &misc,
314 1.1 christos page_start, page_end))
315 1.1 christos #endif
316 1.1.1.6 christos return false;
317 1.1 christos }
318 1.1.1.6 christos *again = true;
319 1.1 christos }
320 1.1 christos
321 1.1 christos /* Perform some house keeping after relaxing the section. */
322 1.1 christos
323 1.1 christos if (isymbuf != NULL
324 1.1 christos && symtab_hdr->contents != (unsigned char *) isymbuf)
325 1.1 christos {
326 1.1 christos if (! link_info->keep_memory)
327 1.1 christos free (isymbuf);
328 1.1 christos else
329 1.1 christos symtab_hdr->contents = (unsigned char *) isymbuf;
330 1.1 christos }
331 1.1 christos
332 1.1 christos if (contents != NULL
333 1.1 christos && elf_section_data (sec)->this_hdr.contents != contents)
334 1.1 christos {
335 1.1 christos if (! link_info->keep_memory)
336 1.1 christos free (contents);
337 1.1 christos else
338 1.1 christos {
339 1.1 christos /* Cache the section contents for elf_link_input_bfd. */
340 1.1 christos elf_section_data (sec)->this_hdr.contents = contents;
341 1.1 christos }
342 1.1 christos }
343 1.1 christos
344 1.1.1.6 christos if (elf_section_data (sec)->relocs != internal_relocs)
345 1.1 christos free (internal_relocs);
346 1.1 christos
347 1.1.1.6 christos return true;
348 1.1 christos
349 1.1 christos error_return:
350 1.1.1.6 christos if (symtab_hdr->contents != (unsigned char *) isymbuf)
351 1.1 christos free (isymbuf);
352 1.1.1.6 christos if (elf_section_data (sec)->this_hdr.contents != contents)
353 1.1 christos free (contents);
354 1.1.1.6 christos if (elf_section_data (sec)->relocs != internal_relocs)
355 1.1 christos free (internal_relocs);
356 1.1.1.6 christos return false;
357 1.1 christos }
358 1.1 christos
359 1.1 christos /* Set the howto pointer for a EPIPHANY ELF reloc. */
360 1.1 christos
361 1.1.1.6 christos static bool
362 1.1.1.4 christos epiphany_info_to_howto_rela (bfd * abfd,
363 1.1 christos arelent * cache_ptr,
364 1.1 christos Elf_Internal_Rela * dst)
365 1.1 christos {
366 1.1 christos unsigned int r_type;
367 1.1 christos
368 1.1 christos r_type = ELF32_R_TYPE (dst->r_info);
369 1.1.1.2 christos if (r_type >= (unsigned int) R_EPIPHANY_max)
370 1.1.1.2 christos {
371 1.1.1.4 christos /* xgettext:c-format */
372 1.1.1.4 christos _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
373 1.1.1.4 christos abfd, r_type);
374 1.1.1.4 christos bfd_set_error (bfd_error_bad_value);
375 1.1.1.6 christos return false;
376 1.1.1.2 christos }
377 1.1 christos cache_ptr->howto = & epiphany_elf_howto_table [r_type];
378 1.1.1.6 christos return true;
379 1.1 christos }
380 1.1 christos
381 1.1 christos /* Perform a single relocation.
382 1.1 christos By default we use the standard BFD routines. */
383 1.1 christos
384 1.1 christos static bfd_reloc_status_type
385 1.1 christos epiphany_final_link_relocate (reloc_howto_type * howto,
386 1.1.1.4 christos bfd * input_bfd,
387 1.1.1.4 christos asection * input_section,
388 1.1.1.4 christos bfd_byte * contents,
389 1.1 christos Elf_Internal_Rela * rel,
390 1.1.1.4 christos bfd_vma relocation)
391 1.1 christos {
392 1.1 christos switch (howto->type)
393 1.1 christos {
394 1.1 christos /* Handle 16 bit immediates. */
395 1.1 christos case R_EPIPHANY_HIGH:
396 1.1 christos relocation += rel->r_addend;
397 1.1 christos relocation >>= 16;
398 1.1 christos goto common;
399 1.1 christos
400 1.1 christos case R_EPIPHANY_LOW:
401 1.1 christos relocation += rel->r_addend;
402 1.1 christos common:
403 1.1 christos relocation = ((relocation & 0xff00L) << 12)
404 1.1 christos | ((relocation & 0x00ffL) << 5);
405 1.1 christos /* Sanity check the address. */
406 1.1 christos if (rel->r_offset > bfd_get_section_limit (input_bfd, input_section))
407 1.1 christos return bfd_reloc_outofrange;
408 1.1 christos
409 1.1 christos return _bfd_relocate_contents (howto, input_bfd, relocation,
410 1.1 christos contents + rel->r_offset);
411 1.1 christos
412 1.1 christos case R_EPIPHANY_SIMM11:
413 1.1 christos relocation += rel->r_addend;
414 1.1 christos /* Check signed overflow. */
415 1.1 christos if ((int)relocation > 1023 || (int)relocation < -1024)
416 1.1 christos return bfd_reloc_outofrange;
417 1.1 christos goto disp11;
418 1.1 christos
419 1.1 christos case R_EPIPHANY_IMM11:
420 1.1 christos relocation += rel->r_addend;
421 1.1 christos if ((unsigned int) relocation > 0x7ff)
422 1.1 christos return bfd_reloc_outofrange;
423 1.1.1.4 christos /* Fall through. */
424 1.1 christos disp11:
425 1.1.1.4 christos relocation = (((relocation & 7) << 5)
426 1.1.1.4 christos | ((relocation & 0x7f8 ) << 13));
427 1.1 christos return _bfd_relocate_contents (howto, input_bfd, relocation,
428 1.1 christos contents + rel->r_offset);
429 1.1 christos
430 1.1 christos /* Pass others through. */
431 1.1 christos default:
432 1.1 christos break;
433 1.1 christos }
434 1.1 christos
435 1.1 christos /* Only install relocation if above tests did not disqualify it. */
436 1.1 christos return _bfd_final_link_relocate (howto, input_bfd, input_section,
437 1.1 christos contents, rel->r_offset,
438 1.1 christos relocation, rel->r_addend);
439 1.1 christos }
440 1.1 christos
441 1.1 christos /* Relocate an EPIPHANY ELF section.
442 1.1 christos
443 1.1 christos The RELOCATE_SECTION function is called by the new ELF backend linker
444 1.1 christos to handle the relocations for a section.
445 1.1 christos
446 1.1 christos The relocs are always passed as Rela structures; if the section
447 1.1 christos actually uses Rel structures, the r_addend field will always be
448 1.1 christos zero.
449 1.1 christos
450 1.1 christos This function is responsible for adjusting the section contents as
451 1.1 christos necessary, and (if using Rela relocs and generating a relocatable
452 1.1 christos output file) adjusting the reloc addend as necessary.
453 1.1 christos
454 1.1 christos This function does not have to worry about setting the reloc
455 1.1 christos address or the reloc symbol index.
456 1.1 christos
457 1.1 christos LOCAL_SYMS is a pointer to the swapped in local symbols.
458 1.1 christos
459 1.1 christos LOCAL_SECTIONS is an array giving the section in the input file
460 1.1 christos corresponding to the st_shndx field of each local symbol.
461 1.1 christos
462 1.1 christos The global hash table entry for the global symbols can be found
463 1.1 christos via elf_sym_hashes (input_bfd).
464 1.1 christos
465 1.1 christos When generating relocatable output, this function must handle
466 1.1 christos STB_LOCAL/STT_SECTION symbols specially. The output symbol is
467 1.1 christos going to be the section symbol corresponding to the output
468 1.1 christos section, which means that the addend must be adjusted
469 1.1 christos accordingly. */
470 1.1 christos
471 1.1.1.6 christos static int
472 1.1 christos epiphany_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
473 1.1 christos struct bfd_link_info *info,
474 1.1 christos bfd *input_bfd,
475 1.1 christos asection *input_section,
476 1.1 christos bfd_byte *contents,
477 1.1 christos Elf_Internal_Rela *relocs,
478 1.1 christos Elf_Internal_Sym *local_syms,
479 1.1 christos asection **local_sections)
480 1.1 christos {
481 1.1 christos Elf_Internal_Shdr *symtab_hdr;
482 1.1 christos struct elf_link_hash_entry **sym_hashes;
483 1.1 christos Elf_Internal_Rela *rel;
484 1.1 christos Elf_Internal_Rela *relend;
485 1.1 christos
486 1.1 christos symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
487 1.1 christos sym_hashes = elf_sym_hashes (input_bfd);
488 1.1 christos relend = relocs + input_section->reloc_count;
489 1.1 christos
490 1.1 christos for (rel = relocs; rel < relend; rel ++)
491 1.1 christos {
492 1.1.1.4 christos reloc_howto_type * howto;
493 1.1.1.4 christos unsigned long r_symndx;
494 1.1.1.4 christos Elf_Internal_Sym * sym;
495 1.1.1.4 christos asection * sec;
496 1.1 christos struct elf_link_hash_entry * h;
497 1.1.1.4 christos bfd_vma relocation;
498 1.1.1.4 christos bfd_reloc_status_type r;
499 1.1.1.4 christos const char * name = NULL;
500 1.1.1.4 christos int r_type ATTRIBUTE_UNUSED;
501 1.1 christos
502 1.1 christos r_type = ELF32_R_TYPE (rel->r_info);
503 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info);
504 1.1 christos howto = epiphany_elf_howto_table + ELF32_R_TYPE (rel->r_info);
505 1.1 christos h = NULL;
506 1.1 christos sym = NULL;
507 1.1 christos sec = NULL;
508 1.1 christos
509 1.1 christos if (r_symndx < symtab_hdr->sh_info)
510 1.1 christos {
511 1.1 christos sym = local_syms + r_symndx;
512 1.1 christos sec = local_sections [r_symndx];
513 1.1 christos relocation = BASEADDR (sec) + sym->st_value;
514 1.1 christos
515 1.1 christos name = bfd_elf_string_from_elf_section
516 1.1 christos (input_bfd, symtab_hdr->sh_link, sym->st_name);
517 1.1.1.5 christos name = name == NULL ? bfd_section_name (sec) : name;
518 1.1 christos }
519 1.1 christos else
520 1.1 christos {
521 1.1.1.6 christos bool warned ATTRIBUTE_UNUSED;
522 1.1.1.6 christos bool unresolved_reloc ATTRIBUTE_UNUSED;
523 1.1.1.6 christos bool ignored ATTRIBUTE_UNUSED;
524 1.1 christos
525 1.1 christos RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
526 1.1 christos r_symndx, symtab_hdr, sym_hashes,
527 1.1 christos h, sec, relocation,
528 1.1.1.2 christos unresolved_reloc, warned, ignored);
529 1.1 christos
530 1.1 christos name = h->root.root.string;
531 1.1 christos }
532 1.1 christos
533 1.1 christos if (sec != NULL && discarded_section (sec))
534 1.1 christos RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
535 1.1 christos rel, 1, relend, howto, 0, contents);
536 1.1 christos
537 1.1.1.2 christos if (bfd_link_relocatable (info))
538 1.1 christos continue;
539 1.1 christos
540 1.1 christos /* Finally, the sole EPIPHANY-specific part. */
541 1.1 christos r = epiphany_final_link_relocate (howto, input_bfd, input_section,
542 1.1 christos contents, rel, relocation);
543 1.1 christos
544 1.1 christos if (r != bfd_reloc_ok)
545 1.1 christos {
546 1.1 christos const char * msg = NULL;
547 1.1 christos
548 1.1 christos switch (r)
549 1.1 christos {
550 1.1 christos case bfd_reloc_overflow:
551 1.1.1.3 christos (*info->callbacks->reloc_overflow)
552 1.1 christos (info, (h ? &h->root : NULL), name, howto->name,
553 1.1 christos (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
554 1.1 christos break;
555 1.1 christos
556 1.1 christos case bfd_reloc_undefined:
557 1.1.1.3 christos (*info->callbacks->undefined_symbol)
558 1.1.1.6 christos (info, name, input_bfd, input_section, rel->r_offset, true);
559 1.1 christos break;
560 1.1 christos
561 1.1 christos case bfd_reloc_outofrange:
562 1.1 christos msg = _("internal error: out of range error");
563 1.1 christos break;
564 1.1 christos
565 1.1 christos /* This is how epiphany_final_link_relocate tells us of a
566 1.1 christos non-kosher reference between insn & data address spaces. */
567 1.1 christos case bfd_reloc_notsupported:
568 1.1 christos if (sym != NULL) /* Only if it's not an unresolved symbol. */
569 1.1 christos msg = _("unsupported relocation between data/insn address spaces");
570 1.1 christos break;
571 1.1 christos
572 1.1 christos case bfd_reloc_dangerous:
573 1.1 christos msg = _("internal error: dangerous relocation");
574 1.1 christos break;
575 1.1 christos
576 1.1 christos default:
577 1.1 christos msg = _("internal error: unknown error");
578 1.1 christos break;
579 1.1 christos }
580 1.1 christos
581 1.1 christos if (msg)
582 1.1.1.3 christos (*info->callbacks->warning) (info, msg, name, input_bfd,
583 1.1.1.3 christos input_section, rel->r_offset);
584 1.1 christos }
585 1.1 christos }
586 1.1 christos
587 1.1.1.6 christos return true;
588 1.1 christos }
589 1.1 christos
590 1.1 christos /* We only have a little-endian target. */
591 1.1.1.2 christos #define TARGET_LITTLE_SYM epiphany_elf32_vec
592 1.1 christos #define TARGET_LITTLE_NAME "elf32-epiphany"
593 1.1 christos
594 1.1 christos #define ELF_ARCH bfd_arch_epiphany
595 1.1 christos #define ELF_MACHINE_CODE EM_ADAPTEVA_EPIPHANY
596 1.1 christos
597 1.1 christos #define ELF_MAXPAGESIZE 0x8000 /* No pages on the EPIPHANY. */
598 1.1 christos
599 1.1 christos #define elf_info_to_howto_rel NULL
600 1.1 christos #define elf_info_to_howto epiphany_info_to_howto_rela
601 1.1 christos
602 1.1.1.4 christos #define elf_backend_can_gc_sections 1
603 1.1 christos #define elf_backend_rela_normal 1
604 1.1 christos #define elf_backend_relocate_section epiphany_elf_relocate_section
605 1.1 christos
606 1.1 christos #define elf_symbol_leading_char '_'
607 1.1 christos #define bfd_elf32_bfd_reloc_type_lookup epiphany_reloc_type_lookup
608 1.1 christos #define bfd_elf32_bfd_reloc_name_lookup epiphany_reloc_name_lookup
609 1.1 christos #define bfd_elf32_bfd_relax_section epiphany_elf_relax_section
610 1.1 christos
611 1.1 christos #include "elf32-target.h"
612