PR17074 - ignore line terminator characters found inside strings.
[deliverable/binutils-gdb.git] / bfd / elf32-fr30.c
1 /* FR30-specific support for 32-bit ELF.
2 Copyright (C) 1998 Free Software Foundation, Inc.
3
4 This file is part of BFD, the Binary File Descriptor library.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20 #include "bfd.h"
21 #include "sysdep.h"
22 #include "libbfd.h"
23 #include "elf-bfd.h"
24 #include "elf/fr30.h"
25
26 /* Forward declarations. */
27 static bfd_reloc_status_type fr30_elf_i20_reloc
28 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
29
30 static reloc_howto_type fr30_elf_howto_table [] =
31 {
32 /* This reloc does nothing. */
33 HOWTO (R_FR30_NONE, /* type */
34 0, /* rightshift */
35 2, /* size (0 = byte, 1 = short, 2 = long) */
36 32, /* bitsize */
37 false, /* pc_relative */
38 0, /* bitpos */
39 complain_overflow_bitfield, /* complain_on_overflow */
40 bfd_elf_generic_reloc, /* special_function */
41 "R_FR30_NONE", /* name */
42 false, /* partial_inplace */
43 0, /* src_mask */
44 0, /* dst_mask */
45 false), /* pcrel_offset */
46
47 /* An 8 bit absolute relocation. */
48 HOWTO (R_FR30_8, /* type */
49 0, /* rightshift */
50 1, /* size (0 = byte, 1 = short, 2 = long) */
51 8, /* bitsize */
52 false, /* pc_relative */
53 4, /* bitpos */
54 complain_overflow_bitfield, /* complain_on_overflow */
55 bfd_elf_generic_reloc, /* special_function */
56 "R_FR30_8", /* name */
57 true, /* partial_inplace */
58 0x0ff0, /* src_mask */
59 0x0ff0, /* dst_mask */
60 false), /* pcrel_offset */
61
62 /* A 20 bit absolute relocation. */
63 HOWTO (R_FR30_20, /* type */
64 0, /* rightshift */
65 2, /* size (0 = byte, 1 = short, 2 = long) */
66 20, /* bitsize */
67 false, /* pc_relative */
68 0, /* bitpos */
69 complain_overflow_bitfield, /* complain_on_overflow */
70 fr30_elf_i20_reloc, /* special_function */
71 "R_FR30_20", /* name */
72 true, /* partial_inplace */
73 0x00f0ffff, /* src_mask */
74 0x00f0ffff, /* dst_mask */
75 false), /* pcrel_offset */
76
77 /* A 32 bit absolute relocation. */
78 HOWTO (R_FR30_32, /* type */
79 0, /* rightshift */
80 2, /* size (0 = byte, 1 = short, 2 = long) */
81 32, /* bitsize */
82 false, /* pc_relative */
83 0, /* bitpos */
84 complain_overflow_bitfield, /* complain_on_overflow */
85 bfd_elf_generic_reloc, /* special_function */
86 "R_FR30_32", /* name */
87 true, /* partial_inplace */
88 0xffffffff, /* src_mask */
89 0xffffffff, /* dst_mask */
90 false), /* pcrel_offset */
91
92 /* A 6 bit absolute relocation. */
93 HOWTO (R_FR30_6_IN_4, /* type */
94 2, /* rightshift */
95 1, /* size (0 = byte, 1 = short, 2 = long) */
96 6, /* bitsize */
97 false, /* pc_relative */
98 4, /* bitpos */
99 complain_overflow_unsigned, /* complain_on_overflow */
100 bfd_elf_generic_reloc, /* special_function */
101 "R_FR30_6_IN_4", /* name */
102 true, /* partial_inplace */
103 0x00f0, /* src_mask */
104 0x00f0, /* dst_mask */
105 false), /* pcrel_offset */
106
107 /* An 8 bit absolute relocation. */
108 HOWTO (R_FR30_8_IN_8, /* type */
109 0, /* rightshift */
110 1, /* size (0 = byte, 1 = short, 2 = long) */
111 8, /* bitsize */
112 false, /* pc_relative */
113 4, /* bitpos */
114 complain_overflow_signed, /* complain_on_overflow */
115 bfd_elf_generic_reloc,/* special_function */
116 "R_FR30_8_IN_8", /* name */
117 true, /* partial_inplace */
118 0x0ff0, /* src_mask */
119 0x0ff0, /* dst_mask */
120 false), /* pcrel_offset */
121
122 /* A 9 bit absolute relocation. */
123 HOWTO (R_FR30_9_IN_8, /* type */
124 1, /* rightshift */
125 1, /* size (0 = byte, 1 = short, 2 = long) */
126 9, /* bitsize */
127 false, /* pc_relative */
128 4, /* bitpos */
129 complain_overflow_signed, /* complain_on_overflow */
130 bfd_elf_generic_reloc,/* special_function */
131 "R_FR30_9_IN_8", /* name */
132 true, /* partial_inplace */
133 0x0ff0, /* src_mask */
134 0x0ff0, /* dst_mask */
135 false), /* pcrel_offset */
136
137 /* A 10 bit absolute relocation. */
138 HOWTO (R_FR30_10_IN_8, /* type */
139 2, /* rightshift */
140 1, /* size (0 = byte, 1 = short, 2 = long) */
141 10, /* bitsize */
142 false, /* pc_relative */
143 4, /* bitpos */
144 complain_overflow_signed, /* complain_on_overflow */
145 bfd_elf_generic_reloc,/* special_function */
146 "R_FR30_10_IN_8", /* name */
147 true, /* partial_inplace */
148 0x0ff0, /* src_mask */
149 0x0ff0, /* dst_mask */
150 false), /* pcrel_offset */
151
152 /* A PC relative 9 bit relocation, right shifted by 1. */
153 HOWTO (R_FR30_9_PCREL, /* type */
154 1, /* rightshift */
155 1, /* size (0 = byte, 1 = short, 2 = long) */
156 9, /* bitsize */
157 true, /* pc_relative */
158 0, /* bitpos */
159 complain_overflow_signed, /* complain_on_overflow */
160 bfd_elf_generic_reloc, /* special_function */
161 "R_FR30_9_PCREL", /* name */
162 false, /* partial_inplace */
163 0x00ff, /* src_mask */
164 0x00ff, /* dst_mask */
165 true), /* pcrel_offset */
166
167 /* A PC relative 12 bit relocation, right shifted by 1. */
168 HOWTO (R_FR30_12_PCREL, /* type */
169 1, /* rightshift */
170 1, /* size (0 = byte, 1 = short, 2 = long) */
171 12, /* bitsize */
172 true, /* pc_relative */
173 0, /* bitpos */
174 complain_overflow_signed, /* complain_on_overflow */
175 bfd_elf_generic_reloc, /* special_function */
176 "R_FR30_12_PCREL", /* name */
177 false, /* partial_inplace */
178 0x07ff, /* src_mask */
179 0x07ff, /* dst_mask */
180 true), /* pcrel_offset */
181 };
182 \f
183 /* Utility to actually perform an R_FR30_20 reloc. */
184
185 static bfd_reloc_status_type
186 fr30_elf_i20_reloc (abfd, reloc_entry, symbol, data,
187 input_section, output_bfd, error_message)
188 bfd * abfd;
189 arelent * reloc_entry;
190 asymbol * symbol;
191 PTR data;
192 asection * input_section;
193 bfd * output_bfd;
194 char ** error_message;
195 {
196 bfd_vma relocation;
197 unsigned long x;
198
199 /* This part is from bfd_elf_generic_reloc. */
200 if (output_bfd != (bfd *) NULL
201 && (symbol->flags & BSF_SECTION_SYM) == 0
202 && (! reloc_entry->howto->partial_inplace
203 || reloc_entry->addend == 0))
204 {
205 reloc_entry->address += input_section->output_offset;
206 return bfd_reloc_ok;
207 }
208
209 if (output_bfd != NULL)
210 /* FIXME: See bfd_perform_relocation. Is this right? */
211 return bfd_reloc_continue;
212
213 relocation =
214 symbol->value
215 + symbol->section->output_section->vma
216 + symbol->section->output_offset
217 + reloc_entry->addend;
218
219 if (relocation > ((1U << 20) - 1))
220 return bfd_reloc_overflow;
221
222 x = bfd_get_32 (abfd, data + reloc_entry->address);
223 x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
224 bfd_put_32 (abfd, x, data + reloc_entry->address);
225
226 return bfd_reloc_ok;
227 }
228
229 \f
230 /* Map BFD reloc types to FR30 ELF reloc types. */
231
232 struct fr30_reloc_map
233 {
234 unsigned char bfd_reloc_val;
235 unsigned char elf_reloc_val;
236 };
237
238 static const struct fr30_reloc_map fr30_reloc_map [] =
239 {
240 { BFD_RELOC_NONE, R_FR30_NONE },
241 { BFD_RELOC_8, R_FR30_8 },
242 { BFD_RELOC_FR30_20, R_FR30_20 },
243 { BFD_RELOC_32, R_FR30_32 },
244 { BFD_RELOC_FR30_6_IN_4, R_FR30_6_IN_4 },
245 { BFD_RELOC_FR30_8_IN_8, R_FR30_8_IN_8 },
246 { BFD_RELOC_FR30_9_IN_8, R_FR30_9_IN_8 },
247 { BFD_RELOC_FR30_10_IN_8, R_FR30_10_IN_8 },
248 { BFD_RELOC_FR30_9_PCREL, R_FR30_9_PCREL },
249 { BFD_RELOC_FR30_12_PCREL, R_FR30_12_PCREL },
250 };
251
252 static reloc_howto_type *
253 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
254 bfd * abfd;
255 bfd_reloc_code_real_type code;
256 {
257 unsigned int i;
258
259 for (i = sizeof (fr30_reloc_map) / sizeof (fr30_reloc_map[0]);
260 --i;)
261 {
262 if (fr30_reloc_map [i].bfd_reloc_val == code)
263 return & fr30_elf_howto_table [fr30_reloc_map[i].elf_reloc_val];
264 }
265
266 return NULL;
267 }
268
269 /* Set the howto pointer for an FR30 ELF reloc. */
270
271 static void
272 fr30_info_to_howto_rel (abfd, cache_ptr, dst)
273 bfd * abfd;
274 arelent * cache_ptr;
275 Elf32_Internal_Rela * dst;
276 {
277 unsigned int r_type;
278
279 r_type = ELF32_R_TYPE (dst->r_info);
280 BFD_ASSERT (r_type < (unsigned int) R_FR30_max);
281 cache_ptr->howto = & fr30_elf_howto_table [r_type];
282 }
283 \f
284 /* Relocate an FR30 ELF section.
285 There is some attempt to make this function usable for many architectures,
286 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
287 if only to serve as a learning tool.
288
289 The RELOCATE_SECTION function is called by the new ELF backend linker
290 to handle the relocations for a section.
291
292 The relocs are always passed as Rela structures; if the section
293 actually uses Rel structures, the r_addend field will always be
294 zero.
295
296 This function is responsible for adjusting the section contents as
297 necessary, and (if using Rela relocs and generating a relocateable
298 output file) adjusting the reloc addend as necessary.
299
300 This function does not have to worry about setting the reloc
301 address or the reloc symbol index.
302
303 LOCAL_SYMS is a pointer to the swapped in local symbols.
304
305 LOCAL_SECTIONS is an array giving the section in the input file
306 corresponding to the st_shndx field of each local symbol.
307
308 The global hash table entry for the global symbols can be found
309 via elf_sym_hashes (input_bfd).
310
311 When generating relocateable output, this function must handle
312 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
313 going to be the section symbol corresponding to the output
314 section, which means that the addend must be adjusted
315 accordingly. */
316
317 static boolean
318 fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section,
319 contents, relocs, local_syms, local_sections)
320 bfd * output_bfd;
321 struct bfd_link_info * info;
322 bfd * input_bfd;
323 asection * input_section;
324 bfd_byte * contents;
325 Elf_Internal_Rela * relocs;
326 Elf_Internal_Sym * local_syms;
327 asection ** local_sections;
328 {
329 Elf_Internal_Shdr * symtab_hdr;
330 struct elf_link_hash_entry ** sym_hashes;
331 Elf_Internal_Rela * rel;
332 Elf_Internal_Rela * relend;
333
334 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
335 sym_hashes = elf_sym_hashes (input_bfd);
336 relend = relocs + input_section->reloc_count;
337
338 for (rel = relocs; rel < relend; rel ++)
339 {
340 reloc_howto_type * howto;
341 unsigned long r_symndx;
342 Elf_Internal_Sym * sym;
343 asection * sec;
344 struct elf_link_hash_entry * h;
345 bfd_vma relocation;
346 bfd_reloc_status_type r;
347 const char * name;
348
349 r_symndx = ELF32_R_SYM (rel->r_info);
350
351 if (info->relocateable)
352 {
353 /* This is a relocateable link. We don't have to change
354 anything, unless the reloc is against a section symbol,
355 in which case we have to adjust according to where the
356 section symbol winds up in the output section. */
357 if (r_symndx < symtab_hdr->sh_info)
358 {
359 sym = local_syms + r_symndx;
360
361 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
362 {
363 sec = local_sections [r_symndx];
364 rel->r_addend += sec->output_offset + sym->st_value;
365 }
366 }
367
368 continue;
369 }
370
371 /* This is a final link. */
372 howto = fr30_elf_howto_table + ELF32_R_TYPE (rel->r_info);
373 h = NULL;
374 sym = NULL;
375 sec = NULL;
376
377 if (r_symndx < symtab_hdr->sh_info)
378 {
379 sym = local_syms + r_symndx;
380 sec = local_sections [r_symndx];
381 relocation = (sec->output_section->vma
382 + sec->output_offset
383 + sym->st_value);
384
385 name = bfd_elf_string_from_elf_section
386 (input_bfd, symtab_hdr->sh_link, sym->st_name);
387 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
388 #if 0
389 fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
390 sec->name, name, sym->st_name,
391 sec->output_section->vma, sec->output_offset,
392 sym->st_value, rel->r_addend);
393 #endif
394 }
395 else
396 {
397 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
398
399 while (h->root.type == bfd_link_hash_indirect
400 || h->root.type == bfd_link_hash_warning)
401 h = (struct elf_link_hash_entry *) h->root.u.i.link;
402
403 name = h->root.root.string;
404
405 if (h->root.type == bfd_link_hash_defined
406 || h->root.type == bfd_link_hash_defweak)
407 {
408 sec = h->root.u.def.section;
409 relocation = (h->root.u.def.value
410 + sec->output_section->vma
411 + sec->output_offset);
412 #if 0
413 fprintf (stderr,
414 "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
415 sec->name, name, h->root.u.def.value,
416 sec->output_section->vma, sec->output_offset, relocation);
417 #endif
418 }
419 else if (h->root.type == bfd_link_hash_undefweak)
420 {
421 #if 0
422 fprintf (stderr, "undefined: sec: %s, name: %s\n",
423 sec->name, name);
424 #endif
425 relocation = 0;
426 }
427 else
428 {
429 if (! ((*info->callbacks->undefined_symbol)
430 (info, h->root.root.string, input_bfd,
431 input_section, rel->r_offset)))
432 return false;
433 #if 0
434 fprintf (stderr, "unknown: name: %s\n", name);
435 #endif
436 relocation = 0;
437 }
438 }
439
440 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
441 contents, rel->r_offset,
442 relocation, rel->r_addend);
443
444 if (r != bfd_reloc_ok)
445 {
446 const char * msg = (const char *)0;
447
448 switch (r)
449 {
450 case bfd_reloc_overflow:
451 if (! ((*info->callbacks->reloc_overflow)
452 (info, name, howto->name, (bfd_vma) 0,
453 input_bfd, input_section, rel->r_offset)))
454 return false;
455 break;
456
457 case bfd_reloc_undefined:
458 if (! ((*info->callbacks->undefined_symbol)
459 (info, name, input_bfd, input_section,
460 rel->r_offset)))
461 return false;
462 break;
463
464 case bfd_reloc_outofrange:
465 msg = _("internal error: out of range error");
466 goto common_error;
467
468 case bfd_reloc_notsupported:
469 msg = _("internal error: unsupported relocation error");
470 goto common_error;
471
472 case bfd_reloc_dangerous:
473 msg = _("internal error: dangerous relocation");
474 goto common_error;
475
476 case bfd_reloc_other:
477 msg = _("could not locate special linker symbol __gp");
478 goto common_error;
479
480 case bfd_reloc_continue:
481 msg = _("could not locate special linker symbol __ep");
482 goto common_error;
483
484 case (bfd_reloc_dangerous + 1):
485 msg = _("could not locate special linker symbol __ctbp");
486 goto common_error;
487
488 default:
489 msg = _("internal error: unknown error");
490 /* fall through */
491
492 common_error:
493 if (!((*info->callbacks->warning)
494 (info, msg, name, input_bfd, input_section,
495 rel->r_offset)))
496 return false;
497 break;
498 }
499 }
500 }
501
502 return true;
503 }
504 \f
505 #define ELF_ARCH bfd_arch_fr30
506 #define ELF_MACHINE_CODE EM_CYGNUS_FR30
507 #define ELF_MAXPAGESIZE 0x1000
508
509 #define TARGET_BIG_SYM bfd_elf32_fr30_vec
510 #define TARGET_BIG_NAME "elf32-fr30"
511
512 #define elf_info_to_howto 0
513 #define elf_info_to_howto_rel fr30_info_to_howto_rel
514 #define elf_backend_relocate_section fr30_elf_relocate_section
515
516 #include "elf32-target.h"
This page took 0.045677 seconds and 4 git commands to generate.