Comment typo fix.
[deliverable/binutils-gdb.git] / bfd / elf32-v850.c
CommitLineData
01b49cb3 1/* V850-specific support for 32-bit ELF
de224d6a 2 Copyright (C) 1996, 1997 Free Software Foundation, Inc.
01b49cb3
C
3
4This file is part of BFD, the Binary File Descriptor library.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
90ffe48b
JL
20
21
22/* XXX FIXME: This code is littered with 32bit int, 16bit short, 8bit char
23 dependencies. As is the gas & simulator code or the v850. */
24
25
01b49cb3
C
26#include "bfd.h"
27#include "sysdep.h"
725b96f5 28#include "bfdlink.h"
01b49cb3
C
29#include "libbfd.h"
30#include "elf-bfd.h"
de224d6a 31#include "elf/v850.h"
01b49cb3 32
de224d6a 33static reloc_howto_type *v850_elf_reloc_type_lookup
01b49cb3 34 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
de224d6a 35static void v850_elf_info_to_howto_rel
01b49cb3 36 PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
de224d6a 37static bfd_reloc_status_type v850_elf_reloc
e73b6ae6 38 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
8988d935 39static boolean v850_elf_is_local_label_name PARAMS ((bfd *, const char *));
de224d6a
MM
40static boolean v850_elf_relocate_section PARAMS((bfd *,
41 struct bfd_link_info *,
42 bfd *,
43 asection *,
44 bfd_byte *,
45 Elf_Internal_Rela *,
46 Elf_Internal_Sym *,
47 asection **));
01b49cb3
C
48
49/* Try to minimize the amount of space occupied by relocation tables
50 on the ROM (not that the ROM won't be swamped by other ELF overhead). */
51#define USE_REL
52
de224d6a 53static reloc_howto_type v850_elf_howto_table[] =
01b49cb3
C
54{
55 /* This reloc does nothing. */
de224d6a
MM
56 HOWTO (R_V850_NONE, /* type */
57 0, /* rightshift */
58 2, /* size (0 = byte, 1 = short, 2 = long) */
59 32, /* bitsize */
60 false, /* pc_relative */
61 0, /* bitpos */
62 complain_overflow_bitfield, /* complain_on_overflow */
63 bfd_elf_generic_reloc, /* special_function */
64 "R_V850_NONE", /* name */
65 false, /* partial_inplace */
66 0, /* src_mask */
67 0, /* dst_mask */
68 false), /* pcrel_offset */
01b49cb3
C
69
70 /* A PC relative 9 bit branch. */
de224d6a
MM
71 HOWTO (R_V850_9_PCREL, /* type */
72 2, /* rightshift */
73 2, /* size (0 = byte, 1 = short, 2 = long) */
74 26, /* bitsize */
75 true, /* pc_relative */
76 0, /* bitpos */
77 complain_overflow_bitfield, /* complain_on_overflow */
78 v850_elf_reloc, /* special_function */
79 "R_V850_9_PCREL", /* name */
80 false, /* partial_inplace */
81 0x00ffffff, /* src_mask */
82 0x00ffffff, /* dst_mask */
83 true), /* pcrel_offset */
01b49cb3 84
8988d935
NC
85 /* A PC relative 16 bit load/store. */
86 HOWTO (R_V850_16_PCREL, /* type */
87 0, /* rightshift */
88 2, /* size (0 = byte, 1 = short, 2 = long) */
89 15, /* bitsize */
90 true, /* pc_relative */
91 17, /* bitpos */
92 complain_overflow_bitfield, /* complain_on_overflow */
93 v850_elf_reloc, /* special_function */
94 "R_V850_16_PCREL", /* name */
95 false, /* partial_inplace */
96 0xfffe0000, /* src_mask */
97 0xfffe0000, /* dst_mask */
98 true), /* pcrel_offset */
99
01b49cb3 100 /* A PC relative 22 bit branch. */
de224d6a
MM
101 HOWTO (R_V850_22_PCREL, /* type */
102 2, /* rightshift */
103 2, /* size (0 = byte, 1 = short, 2 = long) */
104 22, /* bitsize */
105 true, /* pc_relative */
106 7, /* bitpos */
107 complain_overflow_signed, /* complain_on_overflow */
108 v850_elf_reloc, /* special_function */
109 "R_V850_22_PCREL", /* name */
110 false, /* partial_inplace */
111 0x07ffff80, /* src_mask */
112 0x07ffff80, /* dst_mask */
113 true), /* pcrel_offset */
01b49cb3
C
114
115 /* High 16 bits of symbol value. */
de224d6a
MM
116 HOWTO (R_V850_HI16_S, /* type */
117 0, /* rightshift */
118 1, /* size (0 = byte, 1 = short, 2 = long) */
119 16, /* bitsize */
120 false, /* pc_relative */
121 0, /* bitpos */
122 complain_overflow_dont, /* complain_on_overflow */
123 v850_elf_reloc, /* special_function */
124 "R_V850_HI16_S", /* name */
125 true, /* partial_inplace */
126 0xffff, /* src_mask */
127 0xffff, /* dst_mask */
128 false), /* pcrel_offset */
01b49cb3
C
129
130 /* High 16 bits of symbol value. */
de224d6a
MM
131 HOWTO (R_V850_HI16, /* type */
132 0, /* rightshift */
133 1, /* size (0 = byte, 1 = short, 2 = long) */
134 16, /* bitsize */
135 false, /* pc_relative */
136 0, /* bitpos */
137 complain_overflow_dont, /* complain_on_overflow */
138 v850_elf_reloc, /* special_function */
139 "R_V850_HI16", /* name */
140 true, /* partial_inplace */
141 0xffff, /* src_mask */
142 0xffff, /* dst_mask */
143 false), /* pcrel_offset */
01b49cb3
C
144
145 /* Low 16 bits of symbol value. */
de224d6a
MM
146 HOWTO (R_V850_LO16, /* type */
147 0, /* rightshift */
148 1, /* size (0 = byte, 1 = short, 2 = long) */
149 16, /* bitsize */
150 false, /* pc_relative */
151 0, /* bitpos */
152 complain_overflow_dont, /* complain_on_overflow */
8988d935 153 v850_elf_reloc, /* special_function */
de224d6a
MM
154 "R_V850_LO16", /* name */
155 true, /* partial_inplace */
156 0xffff, /* src_mask */
157 0xffff, /* dst_mask */
158 false), /* pcrel_offset */
237b5c4c
JL
159
160 /* Simple 32bit reloc. */
de224d6a
MM
161 HOWTO (R_V850_32, /* type */
162 0, /* rightshift */
163 2, /* size (0 = byte, 1 = short, 2 = long) */
164 32, /* bitsize */
165 false, /* pc_relative */
166 0, /* bitpos */
167 complain_overflow_dont, /* complain_on_overflow */
168 bfd_elf_generic_reloc, /* special_function */
169 "R_V850_32", /* name */
170 true, /* partial_inplace */
171 0xffffffff, /* src_mask */
172 0xffffffff, /* dst_mask */
173 false), /* pcrel_offset */
237b5c4c
JL
174
175 /* Simple 16bit reloc. */
de224d6a
MM
176 HOWTO (R_V850_16, /* type */
177 0, /* rightshift */
178 1, /* size (0 = byte, 1 = short, 2 = long) */
179 16, /* bitsize */
180 false, /* pc_relative */
181 0, /* bitpos */
182 complain_overflow_dont, /* complain_on_overflow */
183 bfd_elf_generic_reloc, /* special_function */
184 "R_V850_16", /* name */
185 true, /* partial_inplace */
186 0xffff, /* src_mask */
187 0xffff, /* dst_mask */
188 false), /* pcrel_offset */
afaed5e9
MM
189
190 /* Simple 8bit reloc. */
de224d6a
MM
191 HOWTO (R_V850_8, /* type */
192 0, /* rightshift */
193 0, /* size (0 = byte, 1 = short, 2 = long) */
194 8, /* bitsize */
195 false, /* pc_relative */
196 0, /* bitpos */
197 complain_overflow_dont, /* complain_on_overflow */
198 bfd_elf_generic_reloc, /* special_function */
199 "R_V850_8", /* name */
200 true, /* partial_inplace */
201 0xff, /* src_mask */
202 0xff, /* dst_mask */
203 false), /* pcrel_offset */
b6d08fce
JL
204
205 /* Offset from the short data area pointer. */
de224d6a
MM
206 HOWTO (R_V850_SDA_OFFSET, /* type */
207 0, /* rightshift */
208 1, /* size (0 = byte, 1 = short, 2 = long) */
209 16, /* bitsize */
210 false, /* pc_relative */
211 0, /* bitpos */
212 complain_overflow_dont, /* complain_on_overflow */
8988d935 213 v850_elf_reloc, /* special_function */
de224d6a
MM
214 "R_V850_SDA_OFFSET", /* name */
215 true, /* partial_inplace */
216 0xffff, /* src_mask */
217 0xffff, /* dst_mask */
218 false), /* pcrel_offset */
b6d08fce 219
c322f1b5 220 /* Offset from the zero data area pointer. */
de224d6a
MM
221 HOWTO (R_V850_ZDA_OFFSET, /* type */
222 0, /* rightshift */
223 1, /* size (0 = byte, 1 = short, 2 = long) */
224 16, /* bitsize */
225 false, /* pc_relative */
226 0, /* bitpos */
227 complain_overflow_dont, /* complain_on_overflow */
8988d935 228 v850_elf_reloc, /* special_function */
de224d6a
MM
229 "R_V850_ZDA_OFFSET", /* name */
230 true, /* partial_inplace */
231 0xffff, /* src_mask */
232 0xffff, /* dst_mask */
233 false), /* pcrel_offset */
b6d08fce 234
c322f1b5 235 /* Offset from the tiny data area pointer. */
de224d6a
MM
236 HOWTO (R_V850_TDA_OFFSET, /* type */
237 0, /* rightshift */
238 2, /* size (0 = byte, 1 = short, 2 = long) */
239 8, /* bitsize */
240 false, /* pc_relative */
241 0, /* bitpos */
242 complain_overflow_dont, /* complain_on_overflow */
8988d935 243 v850_elf_reloc, /* special_function */
de224d6a
MM
244 "R_V850_TDA_OFFSET", /* name */
245 true, /* partial_inplace */
246 0xff, /* src_mask */
247 0xff, /* dst_mask */
248 false), /* pcrel_offset */
b6d08fce 249
01b49cb3
C
250};
251
252/* Map BFD reloc types to V850 ELF reloc types. */
253
de224d6a 254struct v850_elf_reloc_map
01b49cb3
C
255{
256 unsigned char bfd_reloc_val;
257 unsigned char elf_reloc_val;
258};
259
de224d6a 260static const struct v850_elf_reloc_map v850_elf_reloc_map[] =
01b49cb3 261{
de224d6a
MM
262 { BFD_RELOC_NONE, R_V850_NONE, },
263 { BFD_RELOC_V850_9_PCREL, R_V850_9_PCREL, },
8988d935 264 { BFD_RELOC_V850_16_PCREL, R_V850_16_PCREL, },
de224d6a
MM
265 { BFD_RELOC_V850_22_PCREL, R_V850_22_PCREL, },
266 { BFD_RELOC_HI16_S, R_V850_HI16_S, },
267 { BFD_RELOC_HI16, R_V850_HI16, },
268 { BFD_RELOC_LO16, R_V850_LO16, },
269 { BFD_RELOC_32, R_V850_32, },
270 { BFD_RELOC_16, R_V850_16, },
271 { BFD_RELOC_8, R_V850_8, },
272 { BFD_RELOC_V850_TDA_OFFSET, R_V850_TDA_OFFSET, },
273 { BFD_RELOC_V850_SDA_OFFSET, R_V850_SDA_OFFSET, },
274 { BFD_RELOC_V850_ZDA_OFFSET, R_V850_ZDA_OFFSET, },
01b49cb3
C
275};
276
de224d6a
MM
277\f
278/* Map a bfd relocation into the appropriate howto structure */
01b49cb3 279static reloc_howto_type *
de224d6a 280v850_elf_reloc_type_lookup (abfd, code)
01b49cb3
C
281 bfd *abfd;
282 bfd_reloc_code_real_type code;
283{
284 unsigned int i;
285
286 for (i = 0;
de224d6a 287 i < sizeof (v850_elf_reloc_map) / sizeof (struct v850_elf_reloc_map);
01b49cb3
C
288 i++)
289 {
de224d6a
MM
290 if (v850_elf_reloc_map[i].bfd_reloc_val == code)
291 return &v850_elf_howto_table[v850_elf_reloc_map[i].elf_reloc_val];
01b49cb3
C
292 }
293
294 return NULL;
295}
296
de224d6a 297\f
01b49cb3 298/* Set the howto pointer for an V850 ELF reloc. */
01b49cb3 299static void
de224d6a 300v850_elf_info_to_howto_rel (abfd, cache_ptr, dst)
01b49cb3
C
301 bfd *abfd;
302 arelent *cache_ptr;
303 Elf32_Internal_Rel *dst;
304{
305 unsigned int r_type;
306
307 r_type = ELF32_R_TYPE (dst->r_info);
308 BFD_ASSERT (r_type < (unsigned int) R_V850_max);
de224d6a
MM
309 cache_ptr->howto = &v850_elf_howto_table[r_type];
310}
311
312\f
313/* Look through the relocs for a section during the first phase, and
314 allocate space in the global offset table or procedure linkage
315 table. */
316
317static boolean
318v850_elf_check_relocs (abfd, info, sec, relocs)
319 bfd *abfd;
320 struct bfd_link_info *info;
321 asection *sec;
322 const Elf_Internal_Rela *relocs;
323{
324 boolean ret = true;
325 bfd *dynobj;
326 Elf_Internal_Shdr *symtab_hdr;
327 struct elf_link_hash_entry **sym_hashes;
328 const Elf_Internal_Rela *rel;
329 const Elf_Internal_Rela *rel_end;
330 asection *sreloc;
331 enum reloc_type r_type;
332 int other = 0;
333 const char *common = (const char *)0;
334
335 if (info->relocateable)
336 return true;
337
338#ifdef DEBUG
339 fprintf (stderr, "v850_elf_check_relocs called for section %s in %s\n",
340 bfd_get_section_name (abfd, sec),
341 bfd_get_filename (abfd));
342#endif
343
344 dynobj = elf_hash_table (info)->dynobj;
345 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
346 sym_hashes = elf_sym_hashes (abfd);
347 sreloc = NULL;
348
349 rel_end = relocs + sec->reloc_count;
350 for (rel = relocs; rel < rel_end; rel++)
351 {
352 unsigned long r_symndx;
353 struct elf_link_hash_entry *h;
354
355 r_symndx = ELF32_R_SYM (rel->r_info);
356 if (r_symndx < symtab_hdr->sh_info)
357 h = NULL;
358 else
359 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
360
361 r_type = (enum reloc_type) ELF32_R_TYPE (rel->r_info);
362 switch (r_type)
363 {
364 default:
365 case R_V850_NONE:
366 case R_V850_9_PCREL:
8988d935 367 case R_V850_16_PCREL:
de224d6a
MM
368 case R_V850_22_PCREL:
369 case R_V850_HI16_S:
370 case R_V850_HI16:
371 case R_V850_LO16:
372 case R_V850_32:
373 case R_V850_16:
374 case R_V850_8:
375 break;
376
377 case R_V850_SDA_OFFSET:
378 other = V850_OTHER_SDA;
379 common = ".scommon";
380 goto small_data_common;
381
382 case R_V850_ZDA_OFFSET:
383 other = V850_OTHER_ZDA;
384 common = ".zcommon";
385 goto small_data_common;
386
387 case R_V850_TDA_OFFSET:
388 other = V850_OTHER_TDA;
389 common = ".tcommon";
390 /* fall through */
391
392#define V850_OTHER_MASK (V850_OTHER_TDA | V850_OTHER_SDA | V850_OTHER_ZDA)
393
394 small_data_common:
395 if (h)
396 {
397 h->other |= other; /* flag which type of relocation was used */
398 if ((h->other & V850_OTHER_MASK) != (other & V850_OTHER_MASK)
399 && (h->other & V850_OTHER_ERROR) == 0)
400 {
401 const char *msg;
402
403 switch (h->other & V850_OTHER_MASK)
404 {
405 default:
406 msg = "Variable cannot occupy in multiple small data regions";
407 break;
408 case V850_OTHER_SDA | V850_OTHER_ZDA | V850_OTHER_TDA:
409 msg = "Variable can only be in one of the small, zero, and tiny data regions";
410 break;
411 case V850_OTHER_SDA | V850_OTHER_ZDA:
412 msg = "Variable cannot be in both small and zero data regions simultaneously";
413 break;
414 case V850_OTHER_SDA | V850_OTHER_TDA:
415 msg = "Variable cannot be in both small and tiny data regions simultaneously";
416 break;
417 case V850_OTHER_ZDA | V850_OTHER_TDA:
418 msg = "Variable cannot be in both zero and tiny data regions simultaneously";
419 break;
420 }
421
422 (*info->callbacks->warning) (info, msg, h->root.root.string,
423 abfd, h->root.u.def.section, 0);
424
425 bfd_set_error (bfd_error_bad_value);
426 h->other |= V850_OTHER_ERROR;
427 ret = false;
428 }
429 }
430
8988d935 431 if (h && h->root.type == bfd_link_hash_common
de224d6a
MM
432 && h->root.u.c.p
433 && !strcmp (bfd_get_section_name (abfd, h->root.u.c.p->section), "COMMON"))
434 {
435 asection *section = h->root.u.c.p->section = bfd_make_section_old_way (abfd, common);
436 section->flags |= SEC_IS_COMMON;
437 }
438
439#ifdef DEBUG
440 fprintf (stderr, "v850_elf_check_relocs, found %s relocation for %s%s\n",
441 v850_elf_howto_table[ (int)r_type ].name,
442 (h && h->root.root.string) ? h->root.root.string : "<unknown>",
443 (h->root.type == bfd_link_hash_common) ? ", symbol is common" : "");
444#endif
445 break;
446 }
447 }
448
449 return ret;
01b49cb3
C
450}
451
de224d6a 452\f
e73b6ae6 453static bfd_reloc_status_type
de224d6a 454v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
e73b6ae6
JL
455 bfd *abfd;
456 arelent *reloc;
457 asymbol *symbol;
458 PTR data;
459 asection *isection;
460 bfd *obfd;
461 char **err;
462{
463 if (obfd != (bfd *) NULL
464 && (symbol->flags & BSF_SECTION_SYM) == 0
465 && (! reloc->howto->partial_inplace
466 || reloc->addend == 0))
467 {
468 reloc->address += isection->output_offset;
469 return bfd_reloc_ok;
470 }
471 else if (obfd != NULL)
472 {
473 return bfd_reloc_continue;
474 }
475
05f1baaa
JL
476 /* Catch relocs involving undefined symbols. */
477 if (bfd_is_und_section (symbol->section)
478 && (symbol->flags & BSF_WEAK) == 0
479 && obfd == NULL)
480 return bfd_reloc_undefined;
481
e73b6ae6
JL
482 /* We handle final linking of some relocs ourselves. */
483 {
484 long relocation, insn;
485
486 /* Is the address of the relocation really within the section? */
487 if (reloc->address > isection->_cooked_size)
488 return bfd_reloc_outofrange;
489
490 /* Work out which section the relocation is targetted at and the
491 initial relocation command value. */
492
493 /* Get symbol value. (Common symbols are special.) */
494 if (bfd_is_com_section (symbol->section))
495 relocation = 0;
496 else
497 relocation = symbol->value;
498
499 /* Convert input-section-relative symbol value to absolute + addend. */
500 relocation += symbol->section->output_section->vma;
501 relocation += symbol->section->output_offset;
502 relocation += reloc->addend;
503
504 if (reloc->howto->pc_relative == true)
505 {
506 /* Here the variable relocation holds the final address of the
507 symbol we are relocating against, plus any addend. */
508 relocation -= isection->output_section->vma + isection->output_offset;
509
510 /* Deal with pcrel_offset */
511 relocation -= reloc->address;
512 }
513
514 /* I've got no clue... */
515 reloc->addend = 0;
516
8988d935 517 switch (reloc->howto->type)
e73b6ae6 518 {
8988d935
NC
519 default:
520 return bfd_reloc_notsupported;
521
522 case R_V850_22_PCREL:
e73b6ae6
JL
523 if (relocation > 0x1ffff || relocation < -0x200000)
524 return bfd_reloc_overflow;
525
526 if ((relocation % 2) != 0)
527 return bfd_reloc_dangerous;
528
529 insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
e1d98a0a 530 insn &= ~0xfffe003f;
e73b6ae6
JL
531 insn |= (((relocation & 0xfffe) << 16)
532 | ((relocation & 0x3f0000) >> 16));
533 bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
534 return bfd_reloc_ok;
8988d935
NC
535
536 case R_V850_16_PCREL:
537 if (relocation > 0x7fff || relocation < -0x10000)
538 return bfd_reloc_overflow;
539
540 if ((relocation % 2) != 0)
541 return bfd_reloc_dangerous;
542
543 insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
544 insn &= 0x1ffff;
545 insn |= ((relocation & 0xfffe) << 16);
546 bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc->address);
547 return bfd_reloc_ok;
548
549 case R_V850_9_PCREL:
e73b6ae6
JL
550 if (relocation > 0xff || relocation < -0x100)
551 return bfd_reloc_overflow;
552
553 if ((relocation % 2) != 0)
554 return bfd_reloc_dangerous;
555
556 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
8988d935 557 insn &= ~ 0xf870;
e73b6ae6
JL
558 insn |= ((relocation & 0x1f0) << 7) | ((relocation & 0x0e) << 3);
559 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
560 return bfd_reloc_ok;
8988d935
NC
561
562 case R_V850_HI16_S:
1336da39 563 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
e73b6ae6
JL
564 relocation = (relocation >> 16) + ((relocation & 0x8000) != 0);
565 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
566 return bfd_reloc_ok;
8988d935
NC
567
568 case R_V850_HI16:
1336da39 569 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
e73b6ae6
JL
570 relocation = (relocation >> 16);
571 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
572 return bfd_reloc_ok;
8988d935
NC
573
574 case R_V850_16:
575 case R_V850_ZDA_OFFSET:
576 relocation += (short)bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
577
578 if ((long)relocation > 0x7fff || (long)relocation < -0x8000)
579 return bfd_reloc_overflow;
580
581 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
582 return bfd_reloc_ok;
583
584#if 0
585 case R_V850_SDA_OFFSET:
586 {
587 unsigned long gp;
588 struct bfd_link_hash_entry *h;
589
590 relocation += (short)bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
591
592 /* Get the value of __gp. */
593 h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
594 if (h == (struct bfd_link_hash_entry *) NULL
595 || h->type != bfd_link_hash_defined)
596 return bfd_reloc_undefined;
597
598 gp = (h->u.def.value
599 + h->u.def.section->output_section->vma
600 + h->u.def.section->output_offset);
601 relocation -= gp;
602
603 if ((long)relocation > 0x7fff || (long)relocation < -0x8000)
604 return bfd_reloc_overflow;
605
606 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
607 return bfd_reloc_ok;
608 }
609#endif
e73b6ae6
JL
610 }
611 }
612
613 return bfd_reloc_continue;
614}
615
de224d6a 616\f
1336da39
SG
617/*ARGSUSED*/
618static boolean
8988d935 619v850_elf_is_local_label_name (abfd, name)
1336da39 620 bfd *abfd;
8988d935 621 const char *name;
1336da39 622{
8988d935
NC
623 return ((name[0] == '.' && (name[1] == 'L' || name[1] == '.'))
624 || (name[0] == '_' && name[1] == '.' && name[2] == 'L'
625 && name[3] == '_'));
1336da39
SG
626}
627
de224d6a 628\f
725b96f5
JL
629/* Perform a relocation as part of a final link. */
630static bfd_reloc_status_type
de224d6a 631v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
725b96f5
JL
632 input_section, contents, offset, value,
633 addend, info, sym_sec, is_local)
634 reloc_howto_type *howto;
635 bfd *input_bfd;
636 bfd *output_bfd;
637 asection *input_section;
638 bfd_byte *contents;
639 bfd_vma offset;
640 bfd_vma value;
641 bfd_vma addend;
642 struct bfd_link_info *info;
643 asection *sym_sec;
644 int is_local;
645{
646 unsigned long insn;
647 unsigned long r_type = howto->type;
725b96f5 648 bfd_byte *hit_data = contents + offset;
725b96f5
JL
649
650 switch (r_type)
651 {
652 case R_V850_9_PCREL:
653 value -= (input_section->output_section->vma
654 + input_section->output_offset);
655 value -= offset;
656
657 if ((long)value > 0xff || (long)value < -0x100)
658 return bfd_reloc_overflow;
659
660 if ((value % 2) != 0)
661 return bfd_reloc_dangerous;
662
663 insn = bfd_get_16 (input_bfd, hit_data);
c322f1b5 664 insn &= 0x078f;
725b96f5
JL
665 insn |= ((value & 0x1f0) << 7) | ((value & 0x0e) << 3);
666 bfd_put_16 (input_bfd, insn, hit_data);
667 return bfd_reloc_ok;
668
8988d935
NC
669 case R_V850_16_PCREL:
670 value -= (input_section->output_section->vma + input_section->output_offset);
671 value -= offset;
672
673 if ((long)value > 0x7fff || (long)value < -0x10000)
674 return bfd_reloc_overflow;
675
676 if ((value % 2) != 0)
677 return bfd_reloc_dangerous;
678
679 insn = bfd_get_32 (input_bfd, hit_data);
680 insn &= 0x1ffff;
681 insn |= ((value & 0xfffe) << 16);
682 bfd_put_32 (input_bfd, insn, hit_data);
683 return bfd_reloc_ok;
684
725b96f5
JL
685 case R_V850_22_PCREL:
686 value -= (input_section->output_section->vma
687 + input_section->output_offset);
688 value -= offset;
689
690 if ((long)value > 0x1ffff || (long)value < -0x200000)
691 return bfd_reloc_overflow;
692
693 if ((value % 2) != 0)
694 return bfd_reloc_dangerous;
695
696 insn = bfd_get_32 (input_bfd, hit_data);
c322f1b5 697 insn &= 0x1ffc0;
725b96f5
JL
698 insn |= (((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16));
699 bfd_put_32 (input_bfd, insn, hit_data);
700 return bfd_reloc_ok;
701
702 case R_V850_HI16_S:
90ffe48b 703 value += (short)bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
704 value = (value >> 16) + ((value & 0x8000) != 0);
705
706 if ((long)value > 0x7fff || (long)value < -0x8000)
707 return bfd_reloc_overflow;
708
709 bfd_put_16 (input_bfd, value, hit_data);
710 return bfd_reloc_ok;
711
712 case R_V850_HI16:
90ffe48b 713 value += (short)bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
714 value >>= 16;
715
716 if ((long)value > 0x7fff || (long)value < -0x8000)
717 return bfd_reloc_overflow;
718
719 bfd_put_16 (input_bfd, value, hit_data);
720 return bfd_reloc_ok;
721
722 case R_V850_LO16:
90ffe48b 723 value += (short)bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
724 value &= 0xffff;
725
726 bfd_put_16 (input_bfd, value, hit_data);
727 return bfd_reloc_ok;
728
729 case R_V850_16:
730 case R_V850_ZDA_OFFSET:
90ffe48b 731 value += (short)bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
732
733 if ((long)value > 0x7fff || (long)value < -0x8000)
734 return bfd_reloc_overflow;
735
736 bfd_put_16 (input_bfd, value, hit_data);
737 return bfd_reloc_ok;
738
739 case R_V850_32:
740 value += bfd_get_32 (input_bfd, hit_data);
741 bfd_put_32 (input_bfd, value, hit_data);
742 return bfd_reloc_ok;
743
744 case R_V850_8:
90ffe48b 745 value += (char)bfd_get_8 (input_bfd, hit_data);
725b96f5
JL
746
747 if ((long)value > 0x7f || (long)value < -0x80)
748 return bfd_reloc_overflow;
749
750 bfd_put_8 (input_bfd, value, hit_data);
751 return bfd_reloc_ok;
752
753 case R_V850_SDA_OFFSET:
754 {
755 unsigned long gp;
756 struct bfd_link_hash_entry *h;
757
90ffe48b 758 value += (short)bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
759
760 /* Get the value of __gp. */
761 h = bfd_link_hash_lookup (info->hash, "__gp", false,
762 false, true);
763 if (h == (struct bfd_link_hash_entry *) NULL
764 || h->type != bfd_link_hash_defined)
765 return bfd_reloc_undefined;
766
767 gp = (h->u.def.value
768 + h->u.def.section->output_section->vma
769 + h->u.def.section->output_offset);
770 value -= gp;
771
772 if ((long)value > 0x7fff || (long)value < -0x8000)
773 return bfd_reloc_overflow;
774
775 bfd_put_16 (input_bfd, value, hit_data);
776 return bfd_reloc_ok;
777 }
778
779 case R_V850_TDA_OFFSET:
780 {
781 unsigned long ep;
782 struct bfd_link_hash_entry *h;
783
c322f1b5 784 insn = bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
785
786 /* Get the value of __ep. */
787 h = bfd_link_hash_lookup (info->hash, "__ep", false,
788 false, true);
789 if (h == (struct bfd_link_hash_entry *) NULL
790 || h->type != bfd_link_hash_defined)
791 return bfd_reloc_undefined;
792
793 ep = (h->u.def.value
794 + h->u.def.section->output_section->vma
795 + h->u.def.section->output_offset);
796 value -= ep;
797
798
c322f1b5
JL
799 /* Overflow computation and operand insertion is complicated
800 by valid offsets and insertions changing depending on the
801 instruction being used! */
802 if ((insn & 0x0780) == 0x0500)
803 {
afaed5e9 804 value += ((insn & 0x7f) << 1);
c322f1b5
JL
805
806 /* Handle sld.w and sst.w -- 8 bit unsigned offset */
807 if ((long) value > 0xff || (long) value < 0)
808 return bfd_reloc_overflow;
809
afaed5e9 810 if ((value % 2) != 0)
c322f1b5
JL
811 return bfd_reloc_dangerous;
812
813 insn &= 0xff81;
814 insn |= (value >> 1);
815 bfd_put_16 (input_bfd, insn, hit_data);
816 return bfd_reloc_ok;
817 }
818
819 if ((insn & 0x0780) == 0x0400 || (insn & 0x0780) == 0x0480)
820 {
821 value += ((insn & 0x7f) << 1);
822
823 /* Handle sld.h and sst.h -- 8 bit unsigned offset */
824 if ((long) value > 0xff || (long) value < 0)
825 return bfd_reloc_overflow;
826
827 if ((value % 2) != 0)
828 return bfd_reloc_dangerous;
829
830 insn &= 0xff80;
831 insn |= (value >> 1);
832 bfd_put_16 (input_bfd, insn, hit_data);
833 return bfd_reloc_ok;
834 }
835
836 if ((insn & 0x0780) == 0x0300 || (insn & 0x0780) == 0x0380)
837 {
838 value += (insn & 0x7f);
839
840 /* Handle sld.b and sst.b -- 7 bit unsigned offset */
841 if ((long) value > 0x7f || (long) value < 0)
842 return bfd_reloc_overflow;
843 insn &= 0xff80;
844 insn |= value;
845 bfd_put_16 (input_bfd, insn, hit_data);
846 return bfd_reloc_ok;
847 }
848
849 /* Guess (XXX) that it's a movea instruction or something
850 similar. */
90ffe48b 851 value += (short)insn;
c322f1b5
JL
852 if ((long)value > 0x7fff || (long)value < -0x8000)
853 return bfd_reloc_overflow;
854
855 bfd_put_16 (input_bfd, value, hit_data);
856 return bfd_reloc_ok;
725b96f5
JL
857 }
858
859 case R_V850_NONE:
8988d935
NC
860 return bfd_reloc_ok;
861
725b96f5 862 default:
8988d935 863 return bfd_reloc_notsupported;
725b96f5 864 }
725b96f5
JL
865}
866
de224d6a 867\f
725b96f5 868/* Relocate an V850 ELF section. */
725b96f5
JL
869static boolean
870v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
de224d6a 871 contents, relocs, local_syms, local_sections)
725b96f5
JL
872 bfd *output_bfd;
873 struct bfd_link_info *info;
874 bfd *input_bfd;
875 asection *input_section;
876 bfd_byte *contents;
877 Elf_Internal_Rela *relocs;
878 Elf_Internal_Sym *local_syms;
879 asection **local_sections;
880{
881 Elf_Internal_Shdr *symtab_hdr;
882 struct elf_link_hash_entry **sym_hashes;
883 Elf_Internal_Rela *rel, *relend;
884
885 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
886 sym_hashes = elf_sym_hashes (input_bfd);
887
888 rel = relocs;
889 relend = relocs + input_section->reloc_count;
890 for (; rel < relend; rel++)
891 {
892 int r_type;
893 reloc_howto_type *howto;
894 unsigned long r_symndx;
895 Elf_Internal_Sym *sym;
896 asection *sec;
897 struct elf_link_hash_entry *h;
898 bfd_vma relocation;
899 bfd_reloc_status_type r;
900
8988d935
NC
901 r_symndx = ELF32_R_SYM (rel->r_info);
902 r_type = ELF32_R_TYPE (rel->r_info);
903 howto = v850_elf_howto_table + r_type;
904
725b96f5
JL
905 if (info->relocateable)
906 {
907 /* This is a relocateable link. We don't have to change
908 anything, unless the reloc is against a section symbol,
909 in which case we have to adjust according to where the
910 section symbol winds up in the output section. */
911 if (r_symndx < symtab_hdr->sh_info)
912 {
913 sym = local_syms + r_symndx;
914 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
915 {
916 sec = local_sections[r_symndx];
917 rel->r_addend += sec->output_offset + sym->st_value;
918 }
919 }
920
921 continue;
922 }
923
725b96f5
JL
924 /* This is a final link. */
925 h = NULL;
926 sym = NULL;
927 sec = NULL;
928 if (r_symndx < symtab_hdr->sh_info)
929 {
930 sym = local_syms + r_symndx;
931 sec = local_sections[r_symndx];
932 relocation = (sec->output_section->vma
933 + sec->output_offset
934 + sym->st_value);
935 }
936 else
937 {
938 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
939 while (h->root.type == bfd_link_hash_indirect
940 || h->root.type == bfd_link_hash_warning)
941 h = (struct elf_link_hash_entry *) h->root.u.i.link;
942 if (h->root.type == bfd_link_hash_defined
943 || h->root.type == bfd_link_hash_defweak)
944 {
945 sec = h->root.u.def.section;
946 relocation = (h->root.u.def.value
947 + sec->output_section->vma
948 + sec->output_offset);
949 }
950 else if (h->root.type == bfd_link_hash_undefweak)
951 relocation = 0;
952 else
953 {
954 if (! ((*info->callbacks->undefined_symbol)
955 (info, h->root.root.string, input_bfd,
956 input_section, rel->r_offset)))
957 return false;
958 relocation = 0;
959 }
960 }
961
962 /* FIXME: We should use the addend, but the COFF relocations
963 don't. */
de224d6a
MM
964 r = v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
965 input_section,
966 contents, rel->r_offset,
967 relocation, rel->r_addend,
968 info, sec, h == NULL);
725b96f5
JL
969
970 if (r != bfd_reloc_ok)
971 {
8988d935
NC
972 const char *name;
973 const char *msg = (const char *)0;
974
975 if (h != NULL)
976 name = h->root.root.string;
977 else
978 {
979 name = (bfd_elf_string_from_elf_section
980 (input_bfd, symtab_hdr->sh_link, sym->st_name));
981 if (name == NULL || *name == '\0')
982 name = bfd_section_name (input_bfd, sec);
983 }
984
725b96f5
JL
985 switch (r)
986 {
725b96f5 987 case bfd_reloc_overflow:
8988d935
NC
988 if (! ((*info->callbacks->reloc_overflow)
989 (info, name, howto->name, (bfd_vma) 0,
990 input_bfd, input_section, rel->r_offset)))
991 return false;
992 break;
993
994 case bfd_reloc_undefined:
995 if (! ((*info->callbacks->undefined_symbol)
996 (info, name, input_bfd, input_section,
997 rel->r_offset)))
998 return false;
999 break;
1000
1001 case bfd_reloc_outofrange:
1002 msg = "internal error: out of range error";
1003 goto common_error;
1004
1005 case bfd_reloc_notsupported:
1006 msg = "internal error: unsupported relocation error";
1007 goto common_error;
1008
1009 case bfd_reloc_dangerous:
1010 msg = "internal error: dangerous error";
1011 goto common_error;
1012
1013 default:
1014 msg = "internal error: unknown error";
1015 /* fall through */
1016
1017 common_error:
1018 if (!((*info->callbacks->warning)
1019 (info, msg, name, input_bfd, input_section,
1020 rel->r_offset)))
1021 return false;
725b96f5
JL
1022 break;
1023 }
1024 }
1025 }
1026
1027 return true;
1028}
01b49cb3 1029
8988d935
NC
1030/* Set the right machine number. */
1031
1032static boolean
1033v850_elf_object_p (abfd)
1034 bfd *abfd;
1035{
1036 switch (get_elf_backend_data (abfd) -> elf_machine_code)
1037 {
1038 default:
1039 case EM_CYGNUS_V850: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, 0); break;
1040/* start-sanitize-v850e */
1041 case EM_CYGNUS_V850E: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e); break;
1042/* end-sanitize-v850e */
1043/* start-sanitize-v850eq */
1044 case EM_CYGNUS_V850EQ: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850eq); break;
1045/* start-sanitize-v850eq */
1046 }
1047}
1048
de224d6a
MM
1049\f
1050#define TARGET_LITTLE_SYM bfd_elf32_v850_vec
1051#define TARGET_LITTLE_NAME "elf32-v850"
1052#define ELF_ARCH bfd_arch_v850
1053#define ELF_MACHINE_CODE EM_CYGNUS_V850
8988d935
NC
1054/* start-sanitize-v850e */
1055#undef ELF_MACHINE_CODE
1056#define ELF_MACHINE_CODE EM_CYGNUS_V850E
1057/* end-sanitize-v850e */
1058/* start-sanitize-v850eq */
1059#undef ELF_MACHINE_CODE
1060#define ELF_MACHINE_CODE EM_CYGNUS_V850EQ
1061/* end-sanitize-v850eq */
1062
de224d6a
MM
1063#define ELF_MAXPAGESIZE 0x1000
1064
1065#define elf_info_to_howto 0
1066#define elf_info_to_howto_rel v850_elf_info_to_howto_rel
1067#define elf_backend_check_relocs v850_elf_check_relocs
1068#define elf_backend_relocate_section v850_elf_relocate_section
8988d935
NC
1069#define elf_backend_object_p v850_elf_object_p
1070#define bfd_elf32_bfd_is_local_label_name v850_elf_is_local_label_name
de224d6a
MM
1071#define bfd_elf32_bfd_reloc_type_lookup v850_elf_reloc_type_lookup
1072
1073#define elf_symbol_leading_char '_'
1336da39 1074
01b49cb3 1075#include "elf32-target.h"
This page took 0.147872 seconds and 4 git commands to generate.