elf32-pru.c revision 1.1 1 1.1 christos /* 32-bit ELF support for TI PRU.
2 1.1 christos Copyright (C) 2014-2017 Free Software Foundation, Inc.
3 1.1 christos Contributed by Dimitar Dimitrov <dimitar (at) dinux.eu>
4 1.1 christos Based on elf32-nios2.c
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 /* This file handles TI PRU ELF targets. */
24 1.1 christos
25 1.1 christos #include "sysdep.h"
26 1.1 christos #include "bfd.h"
27 1.1 christos #include "libbfd.h"
28 1.1 christos #include "bfdlink.h"
29 1.1 christos #include "genlink.h"
30 1.1 christos #include "elf-bfd.h"
31 1.1 christos #include "elf/pru.h"
32 1.1 christos #include "opcode/pru.h"
33 1.1 christos
34 1.1 christos #define SWAP_VALS(A,B) \
35 1.1 christos do { \
36 1.1 christos (A) ^= (B); \
37 1.1 christos (B) ^= (A); \
38 1.1 christos (A) ^= (B); \
39 1.1 christos } while (0)
40 1.1 christos
41 1.1 christos /* Enable debugging printout at stdout with this variable. */
42 1.1 christos static bfd_boolean debug_relax = FALSE;
43 1.1 christos
44 1.1 christos /* Forward declarations. */
45 1.1 christos static bfd_reloc_status_type pru_elf32_pmem_relocate
46 1.1 christos (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
47 1.1 christos static bfd_reloc_status_type pru_elf32_s10_pcrel_relocate
48 1.1 christos (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
49 1.1 christos static bfd_reloc_status_type pru_elf32_u8_pcrel_relocate
50 1.1 christos (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
51 1.1 christos static bfd_reloc_status_type pru_elf32_ldi32_relocate
52 1.1 christos (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
53 1.1 christos static bfd_reloc_status_type bfd_elf_pru_diff_relocate
54 1.1 christos (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
55 1.1 christos
56 1.1 christos /* Target vector. */
57 1.1 christos extern const bfd_target pru_elf32_vec;
58 1.1 christos
59 1.1 christos /* The relocation table used for SHT_REL sections. */
60 1.1 christos static reloc_howto_type elf_pru_howto_table_rel[] = {
61 1.1 christos /* No relocation. */
62 1.1 christos HOWTO (R_PRU_NONE, /* type */
63 1.1 christos 0, /* rightshift */
64 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
65 1.1 christos 3, /* bitsize */
66 1.1 christos FALSE, /* pc_relative */
67 1.1 christos 0, /* bitpos */
68 1.1 christos complain_overflow_dont,/* complain_on_overflow */
69 1.1 christos bfd_elf_generic_reloc, /* special_function */
70 1.1 christos "R_PRU_NONE", /* name */
71 1.1 christos FALSE, /* partial_inplace */
72 1.1 christos 0, /* src_mask */
73 1.1 christos 0, /* dst_mask */
74 1.1 christos FALSE), /* pcrel_offset */
75 1.1 christos
76 1.1 christos HOWTO (R_PRU_16_PMEM,
77 1.1 christos 2,
78 1.1 christos 1, /* short */
79 1.1 christos 32,
80 1.1 christos FALSE,
81 1.1 christos 0,
82 1.1 christos complain_overflow_dont,
83 1.1 christos bfd_elf_generic_reloc,
84 1.1 christos "R_PRU_16_PMEM",
85 1.1 christos FALSE,
86 1.1 christos 0, /* src_mask */
87 1.1 christos 0xffff,
88 1.1 christos FALSE),
89 1.1 christos
90 1.1 christos HOWTO (R_PRU_U16_PMEMIMM,
91 1.1 christos 2,
92 1.1 christos 2,
93 1.1 christos 32,
94 1.1 christos FALSE,
95 1.1 christos 8,
96 1.1 christos complain_overflow_unsigned,
97 1.1 christos pru_elf32_pmem_relocate,
98 1.1 christos "R_PRU_U16_PMEMIMM",
99 1.1 christos FALSE,
100 1.1 christos 0, /* src_mask */
101 1.1 christos 0x00ffff00,
102 1.1 christos FALSE),
103 1.1 christos
104 1.1 christos HOWTO (R_PRU_BFD_RELOC_16,
105 1.1 christos 0,
106 1.1 christos 1, /* short */
107 1.1 christos 16,
108 1.1 christos FALSE,
109 1.1 christos 0,
110 1.1 christos complain_overflow_bitfield,
111 1.1 christos bfd_elf_generic_reloc,
112 1.1 christos "R_PRU_BFD_RELOC16",
113 1.1 christos FALSE,
114 1.1 christos 0, /* src_mask */
115 1.1 christos 0x0000ffff,
116 1.1 christos FALSE),
117 1.1 christos
118 1.1 christos /* 16-bit unsigned immediate relocation. */
119 1.1 christos HOWTO (R_PRU_U16, /* type */
120 1.1 christos 0, /* rightshift */
121 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
122 1.1 christos 16, /* bitsize */
123 1.1 christos FALSE, /* pc_relative */
124 1.1 christos 8, /* bitpos */
125 1.1 christos complain_overflow_unsigned, /* complain on overflow */
126 1.1 christos bfd_elf_generic_reloc, /* special function */
127 1.1 christos "R_PRU_U16", /* name */
128 1.1 christos FALSE, /* partial_inplace */
129 1.1 christos 0, /* src_mask */
130 1.1 christos 0x00ffff00, /* dest_mask */
131 1.1 christos FALSE), /* pcrel_offset */
132 1.1 christos
133 1.1 christos HOWTO (R_PRU_32_PMEM,
134 1.1 christos 2,
135 1.1 christos 2, /* long */
136 1.1 christos 32,
137 1.1 christos FALSE,
138 1.1 christos 0,
139 1.1 christos complain_overflow_dont,
140 1.1 christos pru_elf32_pmem_relocate,
141 1.1 christos "R_PRU_32_PMEM",
142 1.1 christos FALSE,
143 1.1 christos 0, /* src_mask */
144 1.1 christos 0xffffffff,
145 1.1 christos FALSE),
146 1.1 christos
147 1.1 christos HOWTO (R_PRU_BFD_RELOC_32,
148 1.1 christos 0,
149 1.1 christos 2, /* long */
150 1.1 christos 32,
151 1.1 christos FALSE,
152 1.1 christos 0,
153 1.1 christos complain_overflow_dont,
154 1.1 christos bfd_elf_generic_reloc,
155 1.1 christos "R_PRU_BFD_RELOC32",
156 1.1 christos FALSE,
157 1.1 christos 0, /* src_mask */
158 1.1 christos 0xffffffff,
159 1.1 christos FALSE),
160 1.1 christos
161 1.1 christos HOWTO (R_PRU_S10_PCREL,
162 1.1 christos 2,
163 1.1 christos 2,
164 1.1 christos 10,
165 1.1 christos TRUE,
166 1.1 christos 0,
167 1.1 christos complain_overflow_bitfield,
168 1.1 christos pru_elf32_s10_pcrel_relocate,
169 1.1 christos "R_PRU_S10_PCREL",
170 1.1 christos FALSE,
171 1.1 christos 0, /* src_mask */
172 1.1 christos 0x060000ff,
173 1.1 christos TRUE),
174 1.1 christos
175 1.1 christos HOWTO (R_PRU_U8_PCREL,
176 1.1 christos 2,
177 1.1 christos 2,
178 1.1 christos 8,
179 1.1 christos TRUE,
180 1.1 christos 0,
181 1.1 christos complain_overflow_unsigned,
182 1.1 christos pru_elf32_u8_pcrel_relocate,
183 1.1 christos "R_PRU_U8_PCREL",
184 1.1 christos FALSE,
185 1.1 christos 0, /* src_mask */
186 1.1 christos 0x000000ff,
187 1.1 christos TRUE),
188 1.1 christos
189 1.1 christos HOWTO (R_PRU_LDI32,
190 1.1 christos 0, /* rightshift */
191 1.1 christos 4, /* size (4 = 8bytes) */
192 1.1 christos 32, /* bitsize */
193 1.1 christos FALSE, /* pc_relative */
194 1.1 christos 0, /* bitpos */
195 1.1 christos complain_overflow_unsigned, /* complain on overflow */
196 1.1 christos pru_elf32_ldi32_relocate, /* special function */
197 1.1 christos "R_PRU_LDI32", /* name */
198 1.1 christos FALSE, /* partial_inplace */
199 1.1 christos 0, /* src_mask */
200 1.1 christos 0xffffffff, /* dest_mask */
201 1.1 christos FALSE), /* pcrel_offset */
202 1.1 christos
203 1.1 christos /* GNU-specific relocations. */
204 1.1 christos HOWTO (R_PRU_GNU_BFD_RELOC_8,
205 1.1 christos 0,
206 1.1 christos 0, /* byte */
207 1.1 christos 8,
208 1.1 christos FALSE,
209 1.1 christos 0,
210 1.1 christos complain_overflow_bitfield,
211 1.1 christos bfd_elf_generic_reloc,
212 1.1 christos "R_PRU_BFD_RELOC8",
213 1.1 christos FALSE,
214 1.1 christos 0, /* src_mask */
215 1.1 christos 0x000000ff,
216 1.1 christos FALSE),
217 1.1 christos
218 1.1 christos HOWTO (R_PRU_GNU_DIFF8, /* type */
219 1.1 christos 0, /* rightshift */
220 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
221 1.1 christos 8, /* bitsize */
222 1.1 christos FALSE, /* pc_relative */
223 1.1 christos 0, /* bitpos */
224 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
225 1.1 christos bfd_elf_pru_diff_relocate, /* special_function */
226 1.1 christos "R_PRU_DIFF8", /* name */
227 1.1 christos FALSE, /* partial_inplace */
228 1.1 christos 0, /* src_mask */
229 1.1 christos 0xff, /* dst_mask */
230 1.1 christos FALSE), /* pcrel_offset */
231 1.1 christos
232 1.1 christos HOWTO (R_PRU_GNU_DIFF16, /* type */
233 1.1 christos 0, /* rightshift */
234 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
235 1.1 christos 16, /* bitsize */
236 1.1 christos FALSE, /* pc_relative */
237 1.1 christos 0, /* bitpos */
238 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
239 1.1 christos bfd_elf_pru_diff_relocate,/* special_function */
240 1.1 christos "R_PRU_DIFF16", /* name */
241 1.1 christos FALSE, /* partial_inplace */
242 1.1 christos 0, /* src_mask */
243 1.1 christos 0xffff, /* dst_mask */
244 1.1 christos FALSE), /* pcrel_offset */
245 1.1 christos
246 1.1 christos HOWTO (R_PRU_GNU_DIFF32, /* type */
247 1.1 christos 0, /* rightshift */
248 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
249 1.1 christos 32, /* bitsize */
250 1.1 christos FALSE, /* pc_relative */
251 1.1 christos 0, /* bitpos */
252 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
253 1.1 christos bfd_elf_pru_diff_relocate,/* special_function */
254 1.1 christos "R_PRU_DIFF32", /* name */
255 1.1 christos FALSE, /* partial_inplace */
256 1.1 christos 0, /* src_mask */
257 1.1 christos 0xffffffff, /* dst_mask */
258 1.1 christos FALSE), /* pcrel_offset */
259 1.1 christos
260 1.1 christos HOWTO (R_PRU_GNU_DIFF16_PMEM, /* type */
261 1.1 christos 0, /* rightshift */
262 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
263 1.1 christos 16, /* bitsize */
264 1.1 christos FALSE, /* pc_relative */
265 1.1 christos 0, /* bitpos */
266 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
267 1.1 christos bfd_elf_pru_diff_relocate,/* special_function */
268 1.1 christos "R_PRU_DIFF16_PMEM", /* name */
269 1.1 christos FALSE, /* partial_inplace */
270 1.1 christos 0, /* src_mask */
271 1.1 christos 0xffff, /* dst_mask */
272 1.1 christos FALSE), /* pcrel_offset */
273 1.1 christos
274 1.1 christos HOWTO (R_PRU_GNU_DIFF32_PMEM, /* type */
275 1.1 christos 0, /* rightshift */
276 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
277 1.1 christos 32, /* bitsize */
278 1.1 christos FALSE, /* pc_relative */
279 1.1 christos 0, /* bitpos */
280 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
281 1.1 christos bfd_elf_pru_diff_relocate,/* special_function */
282 1.1 christos "R_PRU_DIFF32_PMEM", /* name */
283 1.1 christos FALSE, /* partial_inplace */
284 1.1 christos 0, /* src_mask */
285 1.1 christos 0xffffffff, /* dst_mask */
286 1.1 christos FALSE), /* pcrel_offset */
287 1.1 christos
288 1.1 christos /* Add other relocations here. */
289 1.1 christos };
290 1.1 christos
291 1.1 christos static unsigned char elf_code_to_howto_index[R_PRU_ILLEGAL + 1];
292 1.1 christos
293 1.1 christos /* Return the howto for relocation RTYPE. */
294 1.1 christos static reloc_howto_type *
295 1.1 christos lookup_howto (unsigned int rtype)
296 1.1 christos {
297 1.1 christos static int initialized = 0;
298 1.1 christos int i;
299 1.1 christos int howto_tbl_size = (int) (sizeof (elf_pru_howto_table_rel)
300 1.1 christos / sizeof (elf_pru_howto_table_rel[0]));
301 1.1 christos
302 1.1 christos if (!initialized)
303 1.1 christos {
304 1.1 christos initialized = 1;
305 1.1 christos memset (elf_code_to_howto_index, 0xff,
306 1.1 christos sizeof (elf_code_to_howto_index));
307 1.1 christos for (i = 0; i < howto_tbl_size; i++)
308 1.1 christos elf_code_to_howto_index[elf_pru_howto_table_rel[i].type] = i;
309 1.1 christos }
310 1.1 christos
311 1.1 christos BFD_ASSERT (rtype <= R_PRU_ILLEGAL);
312 1.1 christos i = elf_code_to_howto_index[rtype];
313 1.1 christos if (i >= howto_tbl_size)
314 1.1 christos return 0;
315 1.1 christos return elf_pru_howto_table_rel + i;
316 1.1 christos }
317 1.1 christos
318 1.1 christos /* Map for converting BFD reloc types to PRU reloc types. */
319 1.1 christos struct elf_reloc_map
320 1.1 christos {
321 1.1 christos bfd_reloc_code_real_type bfd_val;
322 1.1 christos enum elf_pru_reloc_type elf_val;
323 1.1 christos };
324 1.1 christos
325 1.1 christos static const struct elf_reloc_map pru_reloc_map[] = {
326 1.1 christos {BFD_RELOC_NONE, R_PRU_NONE},
327 1.1 christos {BFD_RELOC_PRU_16_PMEM, R_PRU_16_PMEM},
328 1.1 christos {BFD_RELOC_PRU_U16_PMEMIMM, R_PRU_U16_PMEMIMM},
329 1.1 christos {BFD_RELOC_16, R_PRU_BFD_RELOC_16},
330 1.1 christos {BFD_RELOC_PRU_U16, R_PRU_U16},
331 1.1 christos {BFD_RELOC_PRU_32_PMEM, R_PRU_32_PMEM},
332 1.1 christos {BFD_RELOC_32, R_PRU_BFD_RELOC_32},
333 1.1 christos {BFD_RELOC_PRU_S10_PCREL, R_PRU_S10_PCREL},
334 1.1 christos {BFD_RELOC_PRU_U8_PCREL, R_PRU_U8_PCREL},
335 1.1 christos {BFD_RELOC_PRU_LDI32, R_PRU_LDI32},
336 1.1 christos
337 1.1 christos {BFD_RELOC_8, R_PRU_GNU_BFD_RELOC_8},
338 1.1 christos {BFD_RELOC_PRU_GNU_DIFF8, R_PRU_GNU_DIFF8},
339 1.1 christos {BFD_RELOC_PRU_GNU_DIFF16, R_PRU_GNU_DIFF16},
340 1.1 christos {BFD_RELOC_PRU_GNU_DIFF32, R_PRU_GNU_DIFF32},
341 1.1 christos {BFD_RELOC_PRU_GNU_DIFF16_PMEM, R_PRU_GNU_DIFF16_PMEM},
342 1.1 christos {BFD_RELOC_PRU_GNU_DIFF32_PMEM, R_PRU_GNU_DIFF32_PMEM},
343 1.1 christos };
344 1.1 christos
345 1.1 christos
346 1.1 christos /* Assorted hash table functions. */
347 1.1 christos
348 1.1 christos /* Create an entry in a PRU ELF linker hash table. */
349 1.1 christos static struct bfd_hash_entry *
350 1.1 christos link_hash_newfunc (struct bfd_hash_entry *entry,
351 1.1 christos struct bfd_hash_table *table, const char *string)
352 1.1 christos {
353 1.1 christos /* Allocate the structure if it has not already been allocated by a
354 1.1 christos subclass. */
355 1.1 christos if (entry == NULL)
356 1.1 christos {
357 1.1 christos entry = bfd_hash_allocate (table,
358 1.1 christos sizeof (struct elf_link_hash_entry));
359 1.1 christos if (entry == NULL)
360 1.1 christos return entry;
361 1.1 christos }
362 1.1 christos
363 1.1 christos /* Call the allocation method of the superclass. */
364 1.1 christos entry = _bfd_elf_link_hash_newfunc (entry, table, string);
365 1.1 christos
366 1.1 christos return entry;
367 1.1 christos }
368 1.1 christos
369 1.1 christos /* Implement bfd_elf32_bfd_reloc_type_lookup:
370 1.1 christos Given a BFD reloc type, return a howto structure. */
371 1.1 christos static reloc_howto_type *
372 1.1 christos pru_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
373 1.1 christos bfd_reloc_code_real_type code)
374 1.1 christos {
375 1.1 christos int i;
376 1.1 christos for (i = 0;
377 1.1 christos i < (int) (sizeof (pru_reloc_map) / sizeof (struct elf_reloc_map));
378 1.1 christos ++i)
379 1.1 christos if (pru_reloc_map[i].bfd_val == code)
380 1.1 christos return lookup_howto ((unsigned int) pru_reloc_map[i].elf_val);
381 1.1 christos return NULL;
382 1.1 christos }
383 1.1 christos
384 1.1 christos /* Implement bfd_elf32_bfd_reloc_name_lookup:
385 1.1 christos Given a reloc name, return a howto structure. */
386 1.1 christos static reloc_howto_type *
387 1.1 christos pru_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
388 1.1 christos const char *r_name)
389 1.1 christos {
390 1.1 christos unsigned int i;
391 1.1 christos for (i = 0;
392 1.1 christos i < (sizeof (elf_pru_howto_table_rel)
393 1.1 christos / sizeof (elf_pru_howto_table_rel[0]));
394 1.1 christos i++)
395 1.1 christos if (elf_pru_howto_table_rel[i].name
396 1.1 christos && strcasecmp (elf_pru_howto_table_rel[i].name, r_name) == 0)
397 1.1 christos return &elf_pru_howto_table_rel[i];
398 1.1 christos
399 1.1 christos return NULL;
400 1.1 christos }
401 1.1 christos
402 1.1 christos /* Implement elf_info_to_howto:
403 1.1 christos Given a ELF32 relocation, fill in a arelent structure. */
404 1.1 christos static void
405 1.1 christos pru_elf32_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
406 1.1 christos Elf_Internal_Rela *dst)
407 1.1 christos {
408 1.1 christos unsigned int r_type;
409 1.1 christos
410 1.1 christos r_type = ELF32_R_TYPE (dst->r_info);
411 1.1 christos BFD_ASSERT (r_type < R_PRU_ILLEGAL);
412 1.1 christos cache_ptr->howto = lookup_howto (r_type);
413 1.1 christos }
414 1.1 christos
415 1.1 christos /* Do the relocations that require special handling. */
416 1.1 christos /* Produce a word address for program memory. Linker scripts will put .text
417 1.1 christos at a high offset in order to differentiate it from .data. So here we also
418 1.1 christos mask the high bits of PMEM address.
419 1.1 christos
420 1.1 christos But why 1MB when internal Program Memory much smaller? We want to catch
421 1.1 christos unintended overflows.
422 1.1 christos
423 1.1 christos Why not use (1<<31) as an offset and a mask? Sitara DDRAM usually resides
424 1.1 christos there, and users might want to put some shared carveout memory region in
425 1.1 christos their linker scripts. So 0x80000000 might be a valid .data address.
426 1.1 christos
427 1.1 christos Note that we still keep and pass down the original howto. This way we
428 1.1 christos can reuse this function for several different relocations. */
429 1.1 christos static bfd_reloc_status_type
430 1.1 christos pru_elf32_do_pmem_relocate (bfd *abfd, reloc_howto_type *howto,
431 1.1 christos asection *input_section,
432 1.1 christos bfd_byte *data, bfd_vma offset,
433 1.1 christos bfd_vma symbol_value, bfd_vma addend)
434 1.1 christos {
435 1.1 christos symbol_value = symbol_value + addend;
436 1.1 christos addend = 0;
437 1.1 christos symbol_value &= 0x3fffff;
438 1.1 christos return _bfd_final_link_relocate (howto, abfd, input_section,
439 1.1 christos data, offset, symbol_value, addend);
440 1.1 christos }
441 1.1 christos
442 1.1 christos /* Direct copy of _bfd_final_link_relocate, but with special
443 1.1 christos "fill-in". This copy-paste mumbo jumbo is only needed because BFD
444 1.1 christos cannot deal correctly with non-contiguous bit fields. */
445 1.1 christos static bfd_reloc_status_type
446 1.1 christos pru_elf32_do_s10_pcrel_relocate (bfd *input_bfd, reloc_howto_type *howto,
447 1.1 christos asection *input_section,
448 1.1 christos bfd_byte *contents, bfd_vma address,
449 1.1 christos bfd_vma relocation, bfd_vma addend)
450 1.1 christos {
451 1.1 christos bfd_byte *location;
452 1.1 christos bfd_vma x = 0;
453 1.1 christos bfd_vma qboff;
454 1.1 christos bfd_reloc_status_type flag = bfd_reloc_ok;
455 1.1 christos
456 1.1 christos /* Sanity check the address. */
457 1.1 christos if (address > bfd_get_section_limit (input_bfd, input_section))
458 1.1 christos return bfd_reloc_outofrange;
459 1.1 christos
460 1.1 christos BFD_ASSERT (howto->pc_relative);
461 1.1 christos BFD_ASSERT (howto->pcrel_offset);
462 1.1 christos
463 1.1 christos relocation = relocation + addend - (input_section->output_section->vma
464 1.1 christos + input_section->output_offset) - address;
465 1.1 christos
466 1.1 christos location = contents + address;
467 1.1 christos
468 1.1 christos /* Get the value we are going to relocate. */
469 1.1 christos BFD_ASSERT (bfd_get_reloc_size (howto) == 4);
470 1.1 christos x = bfd_get_32 (input_bfd, location);
471 1.1 christos
472 1.1 christos qboff = GET_BROFF_SIGNED (x) << howto->rightshift;
473 1.1 christos relocation += qboff;
474 1.1 christos
475 1.1 christos BFD_ASSERT (howto->complain_on_overflow == complain_overflow_bitfield);
476 1.1 christos
477 1.1 christos if (relocation > 2047 && relocation < (bfd_vma)-2048l)
478 1.1 christos flag = bfd_reloc_overflow;
479 1.1 christos
480 1.1 christos /* Check that target address is word-aligned. */
481 1.1 christos if (relocation & ((1 << howto->rightshift) - 1))
482 1.1 christos flag = bfd_reloc_outofrange;
483 1.1 christos
484 1.1 christos relocation >>= (bfd_vma) howto->rightshift;
485 1.1 christos
486 1.1 christos /* Fill-in the RELOCATION to the right bits of X. */
487 1.1 christos SET_BROFF_URAW (x, relocation);
488 1.1 christos
489 1.1 christos bfd_put_32 (input_bfd, x, location);
490 1.1 christos
491 1.1 christos return flag;
492 1.1 christos }
493 1.1 christos
494 1.1 christos static bfd_reloc_status_type
495 1.1 christos pru_elf32_do_u8_pcrel_relocate (bfd *abfd, reloc_howto_type *howto,
496 1.1 christos asection *input_section,
497 1.1 christos bfd_byte *data, bfd_vma offset,
498 1.1 christos bfd_vma symbol_value, bfd_vma addend)
499 1.1 christos {
500 1.1 christos bfd_vma relocation;
501 1.1 christos
502 1.1 christos BFD_ASSERT (howto->pc_relative);
503 1.1 christos BFD_ASSERT (howto->pcrel_offset);
504 1.1 christos
505 1.1 christos relocation = symbol_value + addend - (input_section->output_section->vma
506 1.1 christos + input_section->output_offset) - offset;
507 1.1 christos relocation >>= howto->rightshift;
508 1.1 christos
509 1.1 christos /* 0 and 1 are invalid target labels for LOOP. We cannot
510 1.1 christos encode this info in HOWTO, so catch such cases here. */
511 1.1 christos if (relocation < 2)
512 1.1 christos return bfd_reloc_outofrange;
513 1.1 christos
514 1.1 christos return _bfd_final_link_relocate (howto, abfd, input_section,
515 1.1 christos data, offset, symbol_value, addend);
516 1.1 christos }
517 1.1 christos
518 1.1 christos /* Idea and code taken from elf32-d30v. */
519 1.1 christos static bfd_reloc_status_type
520 1.1 christos pru_elf32_do_ldi32_relocate (bfd *abfd, reloc_howto_type *howto,
521 1.1 christos asection *input_section,
522 1.1 christos bfd_byte *data, bfd_vma offset,
523 1.1 christos bfd_vma symbol_value, bfd_vma addend)
524 1.1 christos {
525 1.1 christos bfd_signed_vma relocation;
526 1.1 christos bfd_size_type octets = offset * bfd_octets_per_byte (abfd);
527 1.1 christos bfd_byte *location;
528 1.1 christos unsigned long in1, in2, num;
529 1.1 christos
530 1.1 christos /* A hacked-up version of _bfd_final_link_relocate() follows. */
531 1.1 christos
532 1.1 christos /* Sanity check the address. */
533 1.1 christos if (octets + bfd_get_reloc_size (howto)
534 1.1 christos > bfd_get_section_limit_octets (abfd, input_section))
535 1.1 christos return bfd_reloc_outofrange;
536 1.1 christos
537 1.1 christos /* This function assumes that we are dealing with a basic relocation
538 1.1 christos against a symbol. We want to compute the value of the symbol to
539 1.1 christos relocate to. This is just VALUE, the value of the symbol, plus
540 1.1 christos ADDEND, any addend associated with the reloc. */
541 1.1 christos relocation = symbol_value + addend;
542 1.1 christos
543 1.1 christos BFD_ASSERT (!howto->pc_relative);
544 1.1 christos
545 1.1 christos /* A hacked-up version of _bfd_relocate_contents() follows. */
546 1.1 christos location = data + offset * bfd_octets_per_byte (abfd);
547 1.1 christos
548 1.1 christos BFD_ASSERT (!howto->pc_relative);
549 1.1 christos
550 1.1 christos in1 = bfd_get_32 (abfd, location);
551 1.1 christos in2 = bfd_get_32 (abfd, location + 4);
552 1.1 christos
553 1.1 christos /* Extract the addend - should be zero per my understanding. */
554 1.1 christos num = GET_INSN_FIELD (IMM16, in1) | (GET_INSN_FIELD (IMM16, in2) << 16);
555 1.1 christos BFD_ASSERT (!num);
556 1.1 christos
557 1.1 christos relocation += num;
558 1.1 christos
559 1.1 christos SET_INSN_FIELD (IMM16, in1, relocation & 0xffff);
560 1.1 christos SET_INSN_FIELD (IMM16, in2, relocation >> 16);
561 1.1 christos
562 1.1 christos bfd_put_32 (abfd, in1, location);
563 1.1 christos bfd_put_32 (abfd, in2, location + 4);
564 1.1 christos
565 1.1 christos return bfd_reloc_ok;
566 1.1 christos }
567 1.1 christos
568 1.1 christos /* HOWTO handlers for relocations that require special handling. */
569 1.1 christos
570 1.1 christos static bfd_reloc_status_type
571 1.1 christos pru_elf32_pmem_relocate (bfd *abfd, arelent *reloc_entry,
572 1.1 christos asymbol *symbol, void *data,
573 1.1 christos asection *input_section, bfd *output_bfd,
574 1.1 christos char **error_message)
575 1.1 christos {
576 1.1 christos /* If this is a relocatable link (output_bfd test tells us), just
577 1.1 christos call the generic function. Any adjustment will be done at final
578 1.1 christos link time. */
579 1.1 christos if (output_bfd != NULL)
580 1.1 christos return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
581 1.1 christos input_section, output_bfd, error_message);
582 1.1 christos
583 1.1 christos return pru_elf32_do_pmem_relocate (abfd, reloc_entry->howto,
584 1.1 christos input_section,
585 1.1 christos data, reloc_entry->address,
586 1.1 christos (symbol->value
587 1.1 christos + symbol->section->output_section->vma
588 1.1 christos + symbol->section->output_offset),
589 1.1 christos reloc_entry->addend);
590 1.1 christos }
591 1.1 christos
592 1.1 christos static bfd_reloc_status_type
593 1.1 christos pru_elf32_s10_pcrel_relocate (bfd *abfd, arelent *reloc_entry,
594 1.1 christos asymbol *symbol, void *data,
595 1.1 christos asection *input_section, bfd *output_bfd,
596 1.1 christos char **error_message)
597 1.1 christos {
598 1.1 christos /* If this is a relocatable link (output_bfd test tells us), just
599 1.1 christos call the generic function. Any adjustment will be done at final
600 1.1 christos link time. */
601 1.1 christos if (output_bfd != NULL)
602 1.1 christos return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
603 1.1 christos input_section, output_bfd, error_message);
604 1.1 christos
605 1.1 christos return pru_elf32_do_s10_pcrel_relocate (abfd, reloc_entry->howto,
606 1.1 christos input_section, data,
607 1.1 christos reloc_entry->address,
608 1.1 christos (symbol->value
609 1.1 christos + symbol->section->output_section->vma
610 1.1 christos + symbol->section->output_offset),
611 1.1 christos reloc_entry->addend);
612 1.1 christos }
613 1.1 christos
614 1.1 christos static bfd_reloc_status_type
615 1.1 christos pru_elf32_u8_pcrel_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
616 1.1 christos void *data, asection *input_section,
617 1.1 christos bfd *output_bfd,
618 1.1 christos char **error_message)
619 1.1 christos {
620 1.1 christos /* If this is a relocatable link (output_bfd test tells us), just
621 1.1 christos call the generic function. Any adjustment will be done at final
622 1.1 christos link time. */
623 1.1 christos if (output_bfd != NULL)
624 1.1 christos return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
625 1.1 christos input_section, output_bfd, error_message);
626 1.1 christos
627 1.1 christos return pru_elf32_do_u8_pcrel_relocate (abfd, reloc_entry->howto,
628 1.1 christos input_section,
629 1.1 christos data, reloc_entry->address,
630 1.1 christos (symbol->value
631 1.1 christos + symbol->section->output_section->vma
632 1.1 christos + symbol->section->output_offset),
633 1.1 christos reloc_entry->addend);
634 1.1 christos }
635 1.1 christos
636 1.1 christos static bfd_reloc_status_type
637 1.1 christos pru_elf32_ldi32_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
638 1.1 christos void *data, asection *input_section,
639 1.1 christos bfd *output_bfd,
640 1.1 christos char **error_message)
641 1.1 christos {
642 1.1 christos /* If this is a relocatable link (output_bfd test tells us), just
643 1.1 christos call the generic function. Any adjustment will be done at final
644 1.1 christos link time. */
645 1.1 christos if (output_bfd != NULL)
646 1.1 christos return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
647 1.1 christos input_section, output_bfd, error_message);
648 1.1 christos
649 1.1 christos return pru_elf32_do_ldi32_relocate (abfd, reloc_entry->howto,
650 1.1 christos input_section,
651 1.1 christos data, reloc_entry->address,
652 1.1 christos (symbol->value
653 1.1 christos + symbol->section->output_section->vma
654 1.1 christos + symbol->section->output_offset),
655 1.1 christos reloc_entry->addend);
656 1.1 christos }
657 1.1 christos
658 1.1 christos
659 1.1 christos /* Implement elf_backend_relocate_section. */
660 1.1 christos static bfd_boolean
661 1.1 christos pru_elf32_relocate_section (bfd *output_bfd,
662 1.1 christos struct bfd_link_info *info,
663 1.1 christos bfd *input_bfd,
664 1.1 christos asection *input_section,
665 1.1 christos bfd_byte *contents,
666 1.1 christos Elf_Internal_Rela *relocs,
667 1.1 christos Elf_Internal_Sym *local_syms,
668 1.1 christos asection **local_sections)
669 1.1 christos {
670 1.1 christos Elf_Internal_Shdr *symtab_hdr;
671 1.1 christos struct elf_link_hash_entry **sym_hashes;
672 1.1 christos Elf_Internal_Rela *rel;
673 1.1 christos Elf_Internal_Rela *relend;
674 1.1 christos
675 1.1 christos symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
676 1.1 christos sym_hashes = elf_sym_hashes (input_bfd);
677 1.1 christos relend = relocs + input_section->reloc_count;
678 1.1 christos
679 1.1 christos for (rel = relocs; rel < relend; rel++)
680 1.1 christos {
681 1.1 christos reloc_howto_type *howto;
682 1.1 christos unsigned long r_symndx;
683 1.1 christos Elf_Internal_Sym *sym;
684 1.1 christos asection *sec;
685 1.1 christos struct elf_link_hash_entry *h;
686 1.1 christos bfd_vma relocation;
687 1.1 christos bfd_reloc_status_type r = bfd_reloc_ok;
688 1.1 christos const char *name = NULL;
689 1.1 christos const char* msg = (const char*) NULL;
690 1.1 christos bfd_boolean unresolved_reloc;
691 1.1 christos
692 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info);
693 1.1 christos
694 1.1 christos howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
695 1.1 christos h = NULL;
696 1.1 christos sym = NULL;
697 1.1 christos sec = NULL;
698 1.1 christos
699 1.1 christos if (r_symndx < symtab_hdr->sh_info)
700 1.1 christos {
701 1.1 christos sym = local_syms + r_symndx;
702 1.1 christos sec = local_sections[r_symndx];
703 1.1 christos relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
704 1.1 christos }
705 1.1 christos else
706 1.1 christos {
707 1.1 christos bfd_boolean warned, ignored;
708 1.1 christos
709 1.1 christos RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
710 1.1 christos r_symndx, symtab_hdr, sym_hashes,
711 1.1 christos h, sec, relocation,
712 1.1 christos unresolved_reloc, warned, ignored);
713 1.1 christos }
714 1.1 christos
715 1.1 christos if (sec && discarded_section (sec))
716 1.1 christos RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
717 1.1 christos rel, 1, relend, howto, 0, contents);
718 1.1 christos
719 1.1 christos /* Nothing more to do unless this is a final link. */
720 1.1 christos if (bfd_link_relocatable (info))
721 1.1 christos continue;
722 1.1 christos
723 1.1 christos if (howto)
724 1.1 christos {
725 1.1 christos switch (howto->type)
726 1.1 christos {
727 1.1 christos case R_PRU_NONE:
728 1.1 christos /* We don't need to find a value for this symbol. It's just a
729 1.1 christos marker. */
730 1.1 christos r = bfd_reloc_ok;
731 1.1 christos break;
732 1.1 christos
733 1.1 christos case R_PRU_U16_PMEMIMM:
734 1.1 christos case R_PRU_32_PMEM:
735 1.1 christos case R_PRU_16_PMEM:
736 1.1 christos r = pru_elf32_do_pmem_relocate (input_bfd, howto,
737 1.1 christos input_section,
738 1.1 christos contents, rel->r_offset,
739 1.1 christos relocation, rel->r_addend);
740 1.1 christos break;
741 1.1 christos case R_PRU_S10_PCREL:
742 1.1 christos r = pru_elf32_do_s10_pcrel_relocate (input_bfd, howto,
743 1.1 christos input_section,
744 1.1 christos contents,
745 1.1 christos rel->r_offset,
746 1.1 christos relocation,
747 1.1 christos rel->r_addend);
748 1.1 christos break;
749 1.1 christos case R_PRU_U8_PCREL:
750 1.1 christos r = pru_elf32_do_u8_pcrel_relocate (input_bfd, howto,
751 1.1 christos input_section,
752 1.1 christos contents,
753 1.1 christos rel->r_offset,
754 1.1 christos relocation,
755 1.1 christos rel->r_addend);
756 1.1 christos break;
757 1.1 christos case R_PRU_LDI32:
758 1.1 christos r = pru_elf32_do_ldi32_relocate (input_bfd, howto,
759 1.1 christos input_section,
760 1.1 christos contents,
761 1.1 christos rel->r_offset,
762 1.1 christos relocation,
763 1.1 christos rel->r_addend);
764 1.1 christos break;
765 1.1 christos case R_PRU_GNU_DIFF8:
766 1.1 christos case R_PRU_GNU_DIFF16:
767 1.1 christos case R_PRU_GNU_DIFF32:
768 1.1 christos case R_PRU_GNU_DIFF16_PMEM:
769 1.1 christos case R_PRU_GNU_DIFF32_PMEM:
770 1.1 christos /* Nothing to do here, as contents already contain the
771 1.1 christos diff value. */
772 1.1 christos r = bfd_reloc_ok;
773 1.1 christos break;
774 1.1 christos
775 1.1 christos default:
776 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd,
777 1.1 christos input_section, contents,
778 1.1 christos rel->r_offset, relocation,
779 1.1 christos rel->r_addend);
780 1.1 christos break;
781 1.1 christos }
782 1.1 christos }
783 1.1 christos else
784 1.1 christos r = bfd_reloc_notsupported;
785 1.1 christos
786 1.1 christos if (r != bfd_reloc_ok)
787 1.1 christos {
788 1.1 christos if (h != NULL)
789 1.1 christos name = h->root.root.string;
790 1.1 christos else
791 1.1 christos {
792 1.1 christos name = bfd_elf_string_from_elf_section (input_bfd,
793 1.1 christos symtab_hdr->sh_link,
794 1.1 christos sym->st_name);
795 1.1 christos if (name == NULL || *name == '\0')
796 1.1 christos name = bfd_section_name (input_bfd, sec);
797 1.1 christos }
798 1.1 christos
799 1.1 christos switch (r)
800 1.1 christos {
801 1.1 christos case bfd_reloc_overflow:
802 1.1 christos (*info->callbacks->reloc_overflow) (info, NULL, name,
803 1.1 christos howto->name, (bfd_vma) 0,
804 1.1 christos input_bfd, input_section,
805 1.1 christos rel->r_offset);
806 1.1 christos break;
807 1.1 christos
808 1.1 christos case bfd_reloc_undefined:
809 1.1 christos (*info->callbacks->undefined_symbol) (info, name, input_bfd,
810 1.1 christos input_section,
811 1.1 christos rel->r_offset, TRUE);
812 1.1 christos break;
813 1.1 christos
814 1.1 christos case bfd_reloc_outofrange:
815 1.1 christos if (msg == NULL)
816 1.1 christos msg = _("relocation out of range");
817 1.1 christos break;
818 1.1 christos
819 1.1 christos case bfd_reloc_notsupported:
820 1.1 christos if (msg == NULL)
821 1.1 christos msg = _("unsupported relocation");
822 1.1 christos break;
823 1.1 christos
824 1.1 christos case bfd_reloc_dangerous:
825 1.1 christos if (msg == NULL)
826 1.1 christos msg = _("dangerous relocation");
827 1.1 christos break;
828 1.1 christos
829 1.1 christos default:
830 1.1 christos if (msg == NULL)
831 1.1 christos msg = _("unknown error");
832 1.1 christos break;
833 1.1 christos }
834 1.1 christos
835 1.1 christos if (msg)
836 1.1 christos {
837 1.1 christos (*info->callbacks->warning) (info, msg, name, input_bfd,
838 1.1 christos input_section, rel->r_offset);
839 1.1 christos return FALSE;
840 1.1 christos }
841 1.1 christos }
842 1.1 christos }
843 1.1 christos return TRUE;
844 1.1 christos }
845 1.1 christos
846 1.1 christos
847 1.1 christos /* Perform a diff relocation. Nothing to do, as the difference value is
849 1.1 christos already written into the section's contents. */
850 1.1 christos
851 1.1 christos static bfd_reloc_status_type
852 1.1 christos bfd_elf_pru_diff_relocate (bfd *abfd ATTRIBUTE_UNUSED,
853 1.1 christos arelent *reloc_entry ATTRIBUTE_UNUSED,
854 1.1 christos asymbol *symbol ATTRIBUTE_UNUSED,
855 1.1 christos void *data ATTRIBUTE_UNUSED,
856 1.1 christos asection *input_section ATTRIBUTE_UNUSED,
857 1.1 christos bfd *output_bfd ATTRIBUTE_UNUSED,
858 1.1 christos char **error_message ATTRIBUTE_UNUSED)
859 1.1 christos {
860 1.1 christos return bfd_reloc_ok;
861 1.1 christos }
862 1.1 christos
863 1.1 christos
864 1.1 christos /* Returns whether the relocation type passed is a diff reloc. */
865 1.1 christos
866 1.1 christos static bfd_boolean
867 1.1 christos elf32_pru_is_diff_reloc (Elf_Internal_Rela *irel)
868 1.1 christos {
869 1.1 christos return (ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF8
870 1.1 christos || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16
871 1.1 christos || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32
872 1.1 christos || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16_PMEM
873 1.1 christos || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32_PMEM);
874 1.1 christos }
875 1.1 christos
876 1.1 christos /* Reduce the diff value written in the section by count if the shrinked
877 1.1 christos insn address happens to fall between the two symbols for which this
878 1.1 christos diff reloc was emitted. */
879 1.1 christos
880 1.1 christos static void
881 1.1 christos elf32_pru_adjust_diff_reloc_value (bfd *abfd,
882 1.1 christos struct bfd_section *isec,
883 1.1 christos Elf_Internal_Rela *irel,
884 1.1 christos bfd_vma symval,
885 1.1 christos bfd_vma shrinked_insn_address,
886 1.1 christos int count)
887 1.1 christos {
888 1.1 christos unsigned char *reloc_contents = NULL;
889 1.1 christos unsigned char *isec_contents = elf_section_data (isec)->this_hdr.contents;
890 1.1 christos if (isec_contents == NULL)
891 1.1 christos {
892 1.1 christos if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents))
893 1.1 christos return;
894 1.1 christos
895 1.1 christos elf_section_data (isec)->this_hdr.contents = isec_contents;
896 1.1 christos }
897 1.1 christos
898 1.1 christos reloc_contents = isec_contents + irel->r_offset;
899 1.1 christos
900 1.1 christos /* Read value written in object file. */
901 1.1 christos bfd_signed_vma x = 0;
902 1.1 christos switch (ELF32_R_TYPE (irel->r_info))
903 1.1 christos {
904 1.1 christos case R_PRU_GNU_DIFF8:
905 1.1 christos {
906 1.1 christos x = bfd_get_signed_8 (abfd, reloc_contents);
907 1.1 christos break;
908 1.1 christos }
909 1.1 christos case R_PRU_GNU_DIFF16:
910 1.1 christos {
911 1.1 christos x = bfd_get_signed_16 (abfd, reloc_contents);
912 1.1 christos break;
913 1.1 christos }
914 1.1 christos case R_PRU_GNU_DIFF32:
915 1.1 christos {
916 1.1 christos x = bfd_get_signed_32 (abfd, reloc_contents);
917 1.1 christos break;
918 1.1 christos }
919 1.1 christos case R_PRU_GNU_DIFF16_PMEM:
920 1.1 christos {
921 1.1 christos x = bfd_get_signed_16 (abfd, reloc_contents) * 4;
922 1.1 christos break;
923 1.1 christos }
924 1.1 christos case R_PRU_GNU_DIFF32_PMEM:
925 1.1 christos {
926 1.1 christos x = bfd_get_signed_32 (abfd, reloc_contents) * 4;
927 1.1 christos break;
928 1.1 christos }
929 1.1 christos default:
930 1.1 christos {
931 1.1 christos BFD_FAIL ();
932 1.1 christos }
933 1.1 christos }
934 1.1 christos
935 1.1 christos /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written
936 1.1 christos into the object file at the reloc offset. sym2's logical value is
937 1.1 christos symval (<start_of_section>) + reloc addend. Compute the start and end
938 1.1 christos addresses and check if the shrinked insn falls between sym1 and sym2. */
939 1.1 christos
940 1.1 christos bfd_vma end_address = symval + irel->r_addend;
941 1.1 christos bfd_vma start_address = end_address - x;
942 1.1 christos
943 1.1 christos /* Shrink the absolute DIFF value (get the to labels "closer"
944 1.1 christos together), because we have removed data between labels. */
945 1.1 christos if (x < 0)
946 1.1 christos {
947 1.1 christos x += count;
948 1.1 christos /* In case the signed x is negative, restore order. */
949 1.1 christos SWAP_VALS (end_address, start_address);
950 1.1 christos }
951 1.1 christos else
952 1.1 christos {
953 1.1 christos x -= count;
954 1.1 christos }
955 1.1 christos
956 1.1 christos /* Reduce the diff value by count bytes and write it back into section
957 1.1 christos contents. */
958 1.1 christos
959 1.1 christos if (shrinked_insn_address >= start_address
960 1.1 christos && shrinked_insn_address <= end_address)
961 1.1 christos {
962 1.1 christos switch (ELF32_R_TYPE (irel->r_info))
963 1.1 christos {
964 1.1 christos case R_PRU_GNU_DIFF8:
965 1.1 christos {
966 1.1 christos bfd_put_signed_8 (abfd, x & 0xFF, reloc_contents);
967 1.1 christos break;
968 1.1 christos }
969 1.1 christos case R_PRU_GNU_DIFF16:
970 1.1 christos {
971 1.1 christos bfd_put_signed_16 (abfd, x & 0xFFFF, reloc_contents);
972 1.1 christos break;
973 1.1 christos }
974 1.1 christos case R_PRU_GNU_DIFF32:
975 1.1 christos {
976 1.1 christos bfd_put_signed_32 (abfd, x & 0xFFFFFFFF, reloc_contents);
977 1.1 christos break;
978 1.1 christos }
979 1.1 christos case R_PRU_GNU_DIFF16_PMEM:
980 1.1 christos {
981 1.1 christos bfd_put_signed_16 (abfd, (x / 4) & 0xFFFF, reloc_contents);
982 1.1 christos break;
983 1.1 christos }
984 1.1 christos case R_PRU_GNU_DIFF32_PMEM:
985 1.1 christos {
986 1.1 christos bfd_put_signed_32 (abfd, (x / 4) & 0xFFFFFFFF, reloc_contents);
987 1.1 christos break;
988 1.1 christos }
989 1.1 christos default:
990 1.1 christos {
991 1.1 christos BFD_FAIL ();
992 1.1 christos }
993 1.1 christos }
994 1.1 christos
995 1.1 christos }
996 1.1 christos }
997 1.1 christos
998 1.1 christos /* Delete some bytes from a section while changing the size of an instruction.
999 1.1 christos The parameter "addr" denotes the section-relative offset pointing just
1000 1.1 christos behind the shrinked instruction. "addr+count" point at the first
1001 1.1 christos byte just behind the original unshrinked instruction.
1002 1.1 christos
1003 1.1 christos Idea copied from the AVR port. */
1004 1.1 christos
1005 1.1 christos static bfd_boolean
1006 1.1 christos pru_elf_relax_delete_bytes (bfd *abfd,
1007 1.1 christos asection *sec,
1008 1.1 christos bfd_vma addr,
1009 1.1 christos int count)
1010 1.1 christos {
1011 1.1 christos Elf_Internal_Shdr *symtab_hdr;
1012 1.1 christos unsigned int sec_shndx;
1013 1.1 christos bfd_byte *contents;
1014 1.1 christos Elf_Internal_Rela *irel, *irelend;
1015 1.1 christos Elf_Internal_Sym *isym;
1016 1.1 christos Elf_Internal_Sym *isymbuf = NULL;
1017 1.1 christos bfd_vma toaddr;
1018 1.1 christos struct elf_link_hash_entry **sym_hashes;
1019 1.1 christos struct elf_link_hash_entry **end_hashes;
1020 1.1 christos unsigned int symcount;
1021 1.1 christos
1022 1.1 christos symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1023 1.1 christos sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1024 1.1 christos contents = elf_section_data (sec)->this_hdr.contents;
1025 1.1 christos
1026 1.1 christos toaddr = sec->size;
1027 1.1 christos
1028 1.1 christos irel = elf_section_data (sec)->relocs;
1029 1.1 christos irelend = irel + sec->reloc_count;
1030 1.1 christos
1031 1.1 christos /* Actually delete the bytes. */
1032 1.1 christos if (toaddr - addr - count > 0)
1033 1.1 christos memmove (contents + addr, contents + addr + count,
1034 1.1 christos (size_t) (toaddr - addr - count));
1035 1.1 christos sec->size -= count;
1036 1.1 christos
1037 1.1 christos /* Adjust all the reloc addresses. */
1038 1.1 christos for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1039 1.1 christos {
1040 1.1 christos bfd_vma old_reloc_address;
1041 1.1 christos
1042 1.1 christos old_reloc_address = (sec->output_section->vma
1043 1.1 christos + sec->output_offset + irel->r_offset);
1044 1.1 christos
1045 1.1 christos /* Get the new reloc address. */
1046 1.1 christos if ((irel->r_offset > addr
1047 1.1 christos && irel->r_offset < toaddr))
1048 1.1 christos {
1049 1.1 christos if (debug_relax)
1050 1.1 christos printf ("Relocation at address 0x%x needs to be moved.\n"
1051 1.1 christos "Old section offset: 0x%x, New section offset: 0x%x \n",
1052 1.1 christos (unsigned int) old_reloc_address,
1053 1.1 christos (unsigned int) irel->r_offset,
1054 1.1 christos (unsigned int) ((irel->r_offset) - count));
1055 1.1 christos
1056 1.1 christos irel->r_offset -= count;
1057 1.1 christos }
1058 1.1 christos
1059 1.1 christos }
1060 1.1 christos
1061 1.1 christos /* The reloc's own addresses are now ok. However, we need to readjust
1062 1.1 christos the reloc's addend, i.e. the reloc's value if two conditions are met:
1063 1.1 christos 1.) the reloc is relative to a symbol in this section that
1064 1.1 christos is located in front of the shrinked instruction
1065 1.1 christos 2.) symbol plus addend end up behind the shrinked instruction.
1066 1.1 christos
1067 1.1 christos The most common case where this happens are relocs relative to
1068 1.1 christos the section-start symbol.
1069 1.1 christos
1070 1.1 christos This step needs to be done for all of the sections of the bfd. */
1071 1.1 christos
1072 1.1 christos {
1073 1.1 christos struct bfd_section *isec;
1074 1.1 christos
1075 1.1 christos for (isec = abfd->sections; isec; isec = isec->next)
1076 1.1 christos {
1077 1.1 christos bfd_vma symval;
1078 1.1 christos bfd_vma shrinked_insn_address;
1079 1.1 christos
1080 1.1 christos if (isec->reloc_count == 0)
1081 1.1 christos continue;
1082 1.1 christos
1083 1.1 christos shrinked_insn_address = (sec->output_section->vma
1084 1.1 christos + sec->output_offset + addr - count);
1085 1.1 christos
1086 1.1 christos irel = elf_section_data (isec)->relocs;
1087 1.1 christos /* PR 12161: Read in the relocs for this section if necessary. */
1088 1.1 christos if (irel == NULL)
1089 1.1 christos irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE);
1090 1.1 christos
1091 1.1 christos for (irelend = irel + isec->reloc_count;
1092 1.1 christos irel < irelend;
1093 1.1 christos irel++)
1094 1.1 christos {
1095 1.1 christos /* Read this BFD's local symbols if we haven't done
1096 1.1 christos so already. */
1097 1.1 christos if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1098 1.1 christos {
1099 1.1 christos isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1100 1.1 christos if (isymbuf == NULL)
1101 1.1 christos isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1102 1.1 christos symtab_hdr->sh_info, 0,
1103 1.1 christos NULL, NULL, NULL);
1104 1.1 christos if (isymbuf == NULL)
1105 1.1 christos return FALSE;
1106 1.1 christos }
1107 1.1 christos
1108 1.1 christos /* Get the value of the symbol referred to by the reloc. */
1109 1.1 christos if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1110 1.1 christos {
1111 1.1 christos /* A local symbol. */
1112 1.1 christos asection *sym_sec;
1113 1.1 christos
1114 1.1 christos isym = isymbuf + ELF32_R_SYM (irel->r_info);
1115 1.1 christos sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1116 1.1 christos symval = isym->st_value;
1117 1.1 christos /* If the reloc is absolute, it will not have
1118 1.1 christos a symbol or section associated with it. */
1119 1.1 christos if (sym_sec == sec)
1120 1.1 christos {
1121 1.1 christos symval += sym_sec->output_section->vma
1122 1.1 christos + sym_sec->output_offset;
1123 1.1 christos
1124 1.1 christos if (debug_relax)
1125 1.1 christos printf ("Checking if the relocation's "
1126 1.1 christos "addend needs corrections.\n"
1127 1.1 christos "Address of anchor symbol: 0x%x \n"
1128 1.1 christos "Address of relocation target: 0x%x \n"
1129 1.1 christos "Address of relaxed insn: 0x%x \n",
1130 1.1 christos (unsigned int) symval,
1131 1.1 christos (unsigned int) (symval + irel->r_addend),
1132 1.1 christos (unsigned int) shrinked_insn_address);
1133 1.1 christos
1134 1.1 christos /* Shrink the special DIFF relocations. */
1135 1.1 christos if (elf32_pru_is_diff_reloc (irel))
1136 1.1 christos {
1137 1.1 christos elf32_pru_adjust_diff_reloc_value (abfd, isec, irel,
1138 1.1 christos symval,
1139 1.1 christos shrinked_insn_address,
1140 1.1 christos count);
1141 1.1 christos }
1142 1.1 christos
1143 1.1 christos /* Fix the addend, if it is affected. */
1144 1.1 christos if (symval <= shrinked_insn_address
1145 1.1 christos && (symval + irel->r_addend) > shrinked_insn_address)
1146 1.1 christos {
1147 1.1 christos
1148 1.1 christos irel->r_addend -= count;
1149 1.1 christos
1150 1.1 christos if (debug_relax)
1151 1.1 christos printf ("Relocation's addend needed to be fixed \n");
1152 1.1 christos }
1153 1.1 christos }
1154 1.1 christos /* else...Reference symbol is absolute.
1155 1.1 christos No adjustment needed. */
1156 1.1 christos }
1157 1.1 christos /* else...Reference symbol is extern. No need for adjusting
1158 1.1 christos the addend. */
1159 1.1 christos }
1160 1.1 christos }
1161 1.1 christos }
1162 1.1 christos
1163 1.1 christos /* Adjust the local symbols defined in this section. */
1164 1.1 christos isym = (Elf_Internal_Sym *) symtab_hdr->contents;
1165 1.1 christos /* Fix PR 9841, there may be no local symbols. */
1166 1.1 christos if (isym != NULL)
1167 1.1 christos {
1168 1.1 christos Elf_Internal_Sym *isymend;
1169 1.1 christos
1170 1.1 christos isymend = isym + symtab_hdr->sh_info;
1171 1.1 christos for (; isym < isymend; isym++)
1172 1.1 christos {
1173 1.1 christos if (isym->st_shndx == sec_shndx)
1174 1.1 christos {
1175 1.1 christos if (isym->st_value > addr
1176 1.1 christos && isym->st_value <= toaddr)
1177 1.1 christos isym->st_value -= count;
1178 1.1 christos
1179 1.1 christos if (isym->st_value <= addr
1180 1.1 christos && isym->st_value + isym->st_size > addr)
1181 1.1 christos {
1182 1.1 christos /* If this assert fires then we have a symbol that ends
1183 1.1 christos part way through an instruction. Does that make
1184 1.1 christos sense? */
1185 1.1 christos BFD_ASSERT (isym->st_value + isym->st_size >= addr + count);
1186 1.1 christos isym->st_size -= count;
1187 1.1 christos }
1188 1.1 christos }
1189 1.1 christos }
1190 1.1 christos }
1191 1.1 christos
1192 1.1 christos /* Now adjust the global symbols defined in this section. */
1193 1.1 christos symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1194 1.1 christos - symtab_hdr->sh_info);
1195 1.1 christos sym_hashes = elf_sym_hashes (abfd);
1196 1.1 christos end_hashes = sym_hashes + symcount;
1197 1.1 christos for (; sym_hashes < end_hashes; sym_hashes++)
1198 1.1 christos {
1199 1.1 christos struct elf_link_hash_entry *sym_hash = *sym_hashes;
1200 1.1 christos if ((sym_hash->root.type == bfd_link_hash_defined
1201 1.1 christos || sym_hash->root.type == bfd_link_hash_defweak)
1202 1.1 christos && sym_hash->root.u.def.section == sec)
1203 1.1 christos {
1204 1.1 christos if (sym_hash->root.u.def.value > addr
1205 1.1 christos && sym_hash->root.u.def.value <= toaddr)
1206 1.1 christos sym_hash->root.u.def.value -= count;
1207 1.1 christos
1208 1.1 christos if (sym_hash->root.u.def.value <= addr
1209 1.1 christos && (sym_hash->root.u.def.value + sym_hash->size > addr))
1210 1.1 christos {
1211 1.1 christos /* If this assert fires then we have a symbol that ends
1212 1.1 christos part way through an instruction. Does that make
1213 1.1 christos sense? */
1214 1.1 christos BFD_ASSERT (sym_hash->root.u.def.value + sym_hash->size
1215 1.1 christos >= addr + count);
1216 1.1 christos sym_hash->size -= count;
1217 1.1 christos }
1218 1.1 christos }
1219 1.1 christos }
1220 1.1 christos
1221 1.1 christos return TRUE;
1222 1.1 christos }
1223 1.1 christos
1224 1.1 christos static bfd_boolean
1225 1.1 christos pru_elf32_relax_section (bfd * abfd, asection * sec,
1226 1.1 christos struct bfd_link_info * link_info,
1227 1.1 christos bfd_boolean * again)
1228 1.1 christos {
1229 1.1 christos Elf_Internal_Shdr * symtab_hdr;
1230 1.1 christos Elf_Internal_Rela * internal_relocs;
1231 1.1 christos Elf_Internal_Rela * irel;
1232 1.1 christos Elf_Internal_Rela * irelend;
1233 1.1 christos bfd_byte * contents = NULL;
1234 1.1 christos Elf_Internal_Sym * isymbuf = NULL;
1235 1.1 christos
1236 1.1 christos /* Assume nothing changes. */
1237 1.1 christos *again = FALSE;
1238 1.1 christos
1239 1.1 christos /* We don't have to do anything for a relocatable link, if
1240 1.1 christos this section does not have relocs, or if this is not a
1241 1.1 christos code section. */
1242 1.1 christos if (bfd_link_relocatable (link_info)
1243 1.1 christos || (sec->flags & SEC_RELOC) == 0
1244 1.1 christos || sec->reloc_count == 0 || (sec->flags & SEC_CODE) == 0)
1245 1.1 christos return TRUE;
1246 1.1 christos
1247 1.1 christos symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
1248 1.1 christos
1249 1.1 christos /* Get a copy of the native relocations. */
1250 1.1 christos internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1251 1.1 christos link_info->keep_memory);
1252 1.1 christos if (internal_relocs == NULL)
1253 1.1 christos goto error_return;
1254 1.1 christos
1255 1.1 christos /* Walk through them looking for relaxing opportunities. */
1256 1.1 christos irelend = internal_relocs + sec->reloc_count;
1257 1.1 christos
1258 1.1 christos for (irel = internal_relocs; irel < irelend; irel++)
1259 1.1 christos {
1260 1.1 christos bfd_vma symval;
1261 1.1 christos
1262 1.1 christos /* Get the section contents if we haven't done so already. */
1263 1.1 christos if (contents == NULL)
1264 1.1 christos {
1265 1.1 christos /* Get cached copy if it exists. */
1266 1.1 christos if (elf_section_data (sec)->this_hdr.contents != NULL)
1267 1.1 christos contents = elf_section_data (sec)->this_hdr.contents;
1268 1.1 christos else if (! bfd_malloc_and_get_section (abfd, sec, &contents))
1269 1.1 christos goto error_return;
1270 1.1 christos }
1271 1.1 christos
1272 1.1 christos /* Read this BFD's local symbols if we haven't done so already. */
1273 1.1 christos if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1274 1.1 christos {
1275 1.1 christos isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1276 1.1 christos if (isymbuf == NULL)
1277 1.1 christos isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1278 1.1 christos symtab_hdr->sh_info, 0,
1279 1.1 christos NULL, NULL, NULL);
1280 1.1 christos if (isymbuf == NULL)
1281 1.1 christos goto error_return;
1282 1.1 christos }
1283 1.1 christos
1284 1.1 christos /* Get the value of the symbol referred to by the reloc. */
1285 1.1 christos if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1286 1.1 christos {
1287 1.1 christos /* A local symbol. */
1288 1.1 christos Elf_Internal_Sym *isym;
1289 1.1 christos asection *sym_sec;
1290 1.1 christos
1291 1.1 christos isym = isymbuf + ELF32_R_SYM (irel->r_info);
1292 1.1 christos if (isym->st_shndx == SHN_UNDEF)
1293 1.1 christos sym_sec = bfd_und_section_ptr;
1294 1.1 christos else if (isym->st_shndx == SHN_ABS)
1295 1.1 christos sym_sec = bfd_abs_section_ptr;
1296 1.1 christos else if (isym->st_shndx == SHN_COMMON)
1297 1.1 christos sym_sec = bfd_com_section_ptr;
1298 1.1 christos else
1299 1.1 christos sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1300 1.1 christos symval = (isym->st_value
1301 1.1 christos + sym_sec->output_section->vma + sym_sec->output_offset);
1302 1.1 christos }
1303 1.1 christos else
1304 1.1 christos {
1305 1.1 christos unsigned long indx;
1306 1.1 christos struct elf_link_hash_entry *h;
1307 1.1 christos
1308 1.1 christos /* An external symbol. */
1309 1.1 christos indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1310 1.1 christos h = elf_sym_hashes (abfd)[indx];
1311 1.1 christos BFD_ASSERT (h != NULL);
1312 1.1 christos
1313 1.1 christos if (h->root.type != bfd_link_hash_defined
1314 1.1 christos && h->root.type != bfd_link_hash_defweak)
1315 1.1 christos /* This appears to be a reference to an undefined
1316 1.1 christos symbol. Just ignore it--it will be caught by the
1317 1.1 christos regular reloc processing. */
1318 1.1 christos continue;
1319 1.1 christos
1320 1.1 christos symval = (h->root.u.def.value
1321 1.1 christos + h->root.u.def.section->output_section->vma
1322 1.1 christos + h->root.u.def.section->output_offset);
1323 1.1 christos }
1324 1.1 christos
1325 1.1 christos /* For simplicity of coding, we are going to modify the section
1326 1.1 christos contents, the section relocs, and the BFD symbol table. We
1327 1.1 christos must tell the rest of the code not to free up this
1328 1.1 christos information. It would be possible to instead create a table
1329 1.1 christos of changes which have to be made, as is done in coff-mips.c;
1330 1.1 christos that would be more work, but would require less memory when
1331 1.1 christos the linker is run. */
1332 1.1 christos
1333 1.1 christos /* Check if we can remove an LDI instruction from the LDI32
1334 1.1 christos pseudo instruction if the upper 16 operand bits are zero. */
1335 1.1 christos if (ELF32_R_TYPE (irel->r_info) == (int) R_PRU_LDI32)
1336 1.1 christos {
1337 1.1 christos bfd_vma value = symval + irel->r_addend;
1338 1.1 christos
1339 1.1 christos if (debug_relax)
1340 1.1 christos printf ("R_PRU_LDI32 with value=0x%lx\n", (long) value);
1341 1.1 christos
1342 1.1 christos if ((long) value >> 16 == 0)
1343 1.1 christos {
1344 1.1 christos /* Note that we've changed the relocs, section contents. */
1345 1.1 christos elf_section_data (sec)->relocs = internal_relocs;
1346 1.1 christos elf_section_data (sec)->this_hdr.contents = contents;
1347 1.1 christos symtab_hdr->contents = (unsigned char *) isymbuf;
1348 1.1 christos
1349 1.1 christos /* Delete bytes. */
1350 1.1 christos if (!pru_elf_relax_delete_bytes (abfd, sec, irel->r_offset + 4, 4))
1351 1.1 christos goto error_return;
1352 1.1 christos
1353 1.1 christos /* We're done with deletion of the second instruction.
1354 1.1 christos Set a regular LDI relocation for the first instruction
1355 1.1 christos we left to load the 16-bit value into the 32-bit
1356 1.1 christos register. */
1357 1.1 christos irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1358 1.1 christos R_PRU_U16);
1359 1.1 christos
1360 1.1 christos /* That will change things, so, we should relax again.
1361 1.1 christos Note that this is not required, and it may be slow. */
1362 1.1 christos *again = TRUE;
1363 1.1 christos }
1364 1.1 christos }
1365 1.1 christos }
1366 1.1 christos
1367 1.1 christos if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1368 1.1 christos {
1369 1.1 christos if (!link_info->keep_memory)
1370 1.1 christos free (isymbuf);
1371 1.1 christos else
1372 1.1 christos {
1373 1.1 christos /* Cache the symbols for elf_link_input_bfd. */
1374 1.1 christos symtab_hdr->contents = (unsigned char *) isymbuf;
1375 1.1 christos }
1376 1.1 christos }
1377 1.1 christos
1378 1.1 christos if (contents != NULL
1379 1.1 christos && elf_section_data (sec)->this_hdr.contents != contents)
1380 1.1 christos {
1381 1.1 christos if (!link_info->keep_memory)
1382 1.1 christos free (contents);
1383 1.1 christos else
1384 1.1 christos {
1385 1.1 christos /* Cache the section contents for elf_link_input_bfd. */
1386 1.1 christos elf_section_data (sec)->this_hdr.contents = contents;
1387 1.1 christos }
1388 1.1 christos }
1389 1.1 christos
1390 1.1 christos if (internal_relocs != NULL
1391 1.1 christos && elf_section_data (sec)->relocs != internal_relocs)
1392 1.1 christos free (internal_relocs);
1393 1.1 christos
1394 1.1 christos return TRUE;
1395 1.1 christos
1396 1.1 christos error_return:
1397 1.1 christos if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1398 1.1 christos free (isymbuf);
1399 1.1 christos if (contents != NULL
1400 1.1 christos && elf_section_data (sec)->this_hdr.contents != contents)
1401 1.1 christos free (contents);
1402 1.1 christos if (internal_relocs != NULL
1403 1.1 christos && elf_section_data (sec)->relocs != internal_relocs)
1404 1.1 christos free (internal_relocs);
1405 1.1 christos
1406 1.1 christos return FALSE;
1407 1.1 christos }
1408 1.1 christos
1409 1.1 christos /* Free the derived linker hash table. */
1410 1.1 christos static void
1411 1.1 christos pru_elf32_link_hash_table_free (bfd *obfd)
1412 1.1 christos {
1413 1.1 christos _bfd_elf_link_hash_table_free (obfd);
1414 1.1 christos }
1415 1.1 christos
1416 1.1 christos /* Implement bfd_elf32_bfd_link_hash_table_create. */
1417 1.1 christos static struct bfd_link_hash_table *
1418 1.1 christos pru_elf32_link_hash_table_create (bfd *abfd)
1419 1.1 christos {
1420 1.1 christos struct elf_link_hash_table *ret;
1421 1.1 christos bfd_size_type amt = sizeof (struct elf_link_hash_table);
1422 1.1 christos
1423 1.1 christos ret = bfd_zmalloc (amt);
1424 1.1 christos if (ret == NULL)
1425 1.1 christos return NULL;
1426 1.1 christos
1427 1.1 christos if (!_bfd_elf_link_hash_table_init (ret, abfd,
1428 1.1 christos link_hash_newfunc,
1429 1.1 christos sizeof (struct
1430 1.1 christos elf_link_hash_entry),
1431 1.1 christos PRU_ELF_DATA))
1432 1.1 christos {
1433 1.1 christos free (ret);
1434 1.1 christos return NULL;
1435 1.1 christos }
1436 1.1 christos
1437 1.1 christos ret->root.hash_table_free = pru_elf32_link_hash_table_free;
1438 1.1 christos
1439 1.1 christos return &ret->root;
1440 1.1 christos }
1441 1.1 christos
1442 1.1 christos #define ELF_ARCH bfd_arch_pru
1443 1.1 christos #define ELF_TARGET_ID PRU_ELF_DATA
1444 1.1 christos #define ELF_MACHINE_CODE EM_TI_PRU
1445 1.1 christos
1446 1.1 christos #define ELF_MAXPAGESIZE 1
1447 1.1 christos
1448 1.1 christos #define bfd_elf32_bfd_link_hash_table_create \
1449 1.1 christos pru_elf32_link_hash_table_create
1450 1.1 christos
1451 1.1 christos /* Relocation table lookup macros. */
1452 1.1 christos
1453 1.1 christos #define bfd_elf32_bfd_reloc_type_lookup pru_elf32_bfd_reloc_type_lookup
1454 1.1 christos #define bfd_elf32_bfd_reloc_name_lookup pru_elf32_bfd_reloc_name_lookup
1455 1.1 christos
1456 1.1 christos /* elf_info_to_howto (using RELA relocations). */
1457 1.1 christos
1458 1.1 christos #define elf_info_to_howto pru_elf32_info_to_howto
1459 1.1 christos
1460 1.1 christos /* elf backend functions. */
1461 1.1 christos
1462 1.1 christos #define elf_backend_rela_normal 1
1463 1.1 christos
1464 1.1 christos #define elf_backend_relocate_section pru_elf32_relocate_section
1465 1.1 christos #define bfd_elf32_bfd_relax_section pru_elf32_relax_section
1466 1.1 christos
1467 1.1 christos #define TARGET_LITTLE_SYM pru_elf32_vec
1468 1.1 christos #define TARGET_LITTLE_NAME "elf32-pru"
1469 1.1 christos
1470 #include "elf32-target.h"
1471