Add new st_other bits; Remove v850 section indexes
[deliverable/binutils-gdb.git] / bfd / elf32-v850.c
CommitLineData
01b49cb3
C
1/* V850-specific support for 32-bit ELF
2 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
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"
31
32static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
33 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
34static void v850_info_to_howto_rel
35 PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
e73b6ae6
JL
36static bfd_reloc_status_type bfd_elf32_v850_reloc
37 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
38
01b49cb3
C
39
40
41/* Try to minimize the amount of space occupied by relocation tables
42 on the ROM (not that the ROM won't be swamped by other ELF overhead). */
43#define USE_REL
44
45enum reloc_type
46{
47 R_V850_NONE = 0,
48 R_V850_9_PCREL,
49 R_V850_22_PCREL,
50 R_V850_HI16_S,
51 R_V850_HI16,
52 R_V850_LO16,
237b5c4c
JL
53 R_V850_32,
54 R_V850_16,
55 R_V850_8,
b6d08fce
JL
56 R_V850_SDA_OFFSET,
57 R_V850_ZDA_OFFSET,
58 R_V850_TDA_OFFSET,
01b49cb3
C
59 R_V850_max
60};
61
62static reloc_howto_type elf_v850_howto_table[] =
63{
64 /* This reloc does nothing. */
65 HOWTO (R_V850_NONE, /* type */
66 0, /* rightshift */
67 2, /* size (0 = byte, 1 = short, 2 = long) */
68 32, /* bitsize */
69 false, /* pc_relative */
70 0, /* bitpos */
71 complain_overflow_bitfield, /* complain_on_overflow */
72 bfd_elf_generic_reloc, /* special_function */
73 "R_V850_NONE", /* name */
74 false, /* partial_inplace */
75 0, /* src_mask */
76 0, /* dst_mask */
77 false), /* pcrel_offset */
78
79 /* A PC relative 9 bit branch. */
80 HOWTO (R_V850_9_PCREL, /* type */
81 2, /* rightshift */
82 2, /* size (0 = byte, 1 = short, 2 = long) */
83 26, /* bitsize */
84 true, /* pc_relative */
85 0, /* bitpos */
86 complain_overflow_bitfield, /* complain_on_overflow */
e73b6ae6 87 bfd_elf32_v850_reloc, /* special_function */
01b49cb3
C
88 "R_V850_9_PCREL", /* name */
89 false, /* partial_inplace */
90 0x00ffffff, /* src_mask */
91 0x00ffffff, /* dst_mask */
92 true), /* pcrel_offset */
93
94 /* A PC relative 22 bit branch. */
95 HOWTO (R_V850_22_PCREL, /* type */
96 2, /* rightshift */
97 2, /* size (0 = byte, 1 = short, 2 = long) */
98 22, /* bitsize */
99 true, /* pc_relative */
100 7, /* bitpos */
101 complain_overflow_signed, /* complain_on_overflow */
e73b6ae6 102 bfd_elf32_v850_reloc, /* special_function */
01b49cb3
C
103 "R_V850_22_PCREL", /* name */
104 false, /* partial_inplace */
105 0x07ffff80, /* src_mask */
106 0x07ffff80, /* dst_mask */
107 true), /* pcrel_offset */
108
109 /* High 16 bits of symbol value. */
afaed5e9
MM
110 HOWTO (R_V850_HI16_S, /* type */
111 0, /* rightshift */
112 1, /* size (0 = byte, 1 = short, 2 = long) */
113 16, /* bitsize */
114 false, /* pc_relative */
115 0, /* bitpos */
116 complain_overflow_dont,/* complain_on_overflow */
117 bfd_elf32_v850_reloc, /* special_function */
118 "R_V850_HI16_S", /* name */
119 true, /* partial_inplace */
120 0xffff, /* src_mask */
121 0xffff, /* dst_mask */
122 false), /* pcrel_offset */
01b49cb3
C
123
124 /* High 16 bits of symbol value. */
afaed5e9
MM
125 HOWTO (R_V850_HI16, /* type */
126 0, /* rightshift */
127 1, /* size (0 = byte, 1 = short, 2 = long) */
128 16, /* bitsize */
129 false, /* pc_relative */
130 0, /* bitpos */
131 complain_overflow_dont,/* complain_on_overflow */
132 bfd_elf32_v850_reloc, /* special_function */
133 "R_V850_HI16", /* name */
134 true, /* partial_inplace */
135 0xffff, /* src_mask */
136 0xffff, /* dst_mask */
137 false), /* pcrel_offset */
01b49cb3
C
138
139 /* Low 16 bits of symbol value. */
afaed5e9
MM
140 HOWTO (R_V850_LO16, /* type */
141 0, /* rightshift */
142 1, /* size (0 = byte, 1 = short, 2 = long) */
143 16, /* bitsize */
144 false, /* pc_relative */
145 0, /* bitpos */
146 complain_overflow_dont,/* complain_on_overflow */
147 bfd_elf_generic_reloc, /* special_function */
148 "R_V850_LO16", /* name */
149 true, /* partial_inplace */
150 0xffff, /* src_mask */
151 0xffff, /* dst_mask */
152 false), /* pcrel_offset */
237b5c4c
JL
153
154 /* Simple 32bit reloc. */
afaed5e9
MM
155 HOWTO (R_V850_32, /* type */
156 0, /* rightshift */
157 2, /* size (0 = byte, 1 = short, 2 = long) */
158 32, /* bitsize */
159 false, /* pc_relative */
160 0, /* bitpos */
161 complain_overflow_dont,/* complain_on_overflow */
162 bfd_elf_generic_reloc, /* special_function */
163 "R_V850_32", /* name */
164 true, /* partial_inplace */
165 0xffffffff, /* src_mask */
166 0xffffffff, /* dst_mask */
167 false), /* pcrel_offset */
237b5c4c
JL
168
169 /* Simple 16bit reloc. */
afaed5e9
MM
170 HOWTO (R_V850_16, /* type */
171 0, /* rightshift */
172 1, /* size (0 = byte, 1 = short, 2 = long) */
173 16, /* bitsize */
174 false, /* pc_relative */
175 0, /* bitpos */
176 complain_overflow_dont,/* complain_on_overflow */
177 bfd_elf_generic_reloc, /* special_function */
178 "R_V850_16", /* name */
179 true, /* partial_inplace */
180 0xffff, /* src_mask */
181 0xffff, /* dst_mask */
182 false), /* pcrel_offset */
183
184 /* Simple 8bit reloc. */
185 HOWTO (R_V850_8, /* type */
186 0, /* rightshift */
187 0, /* size (0 = byte, 1 = short, 2 = long) */
188 8, /* bitsize */
189 false, /* pc_relative */
190 0, /* bitpos */
191 complain_overflow_dont,/* complain_on_overflow */
192 bfd_elf_generic_reloc, /* special_function */
193 "R_V850_8", /* name */
194 true, /* partial_inplace */
195 0xff, /* src_mask */
196 0xff, /* dst_mask */
197 false), /* pcrel_offset */
b6d08fce
JL
198
199 /* Offset from the short data area pointer. */
afaed5e9
MM
200 HOWTO (R_V850_SDA_OFFSET, /* type */
201 0, /* rightshift */
202 1, /* size (0 = byte, 1 = short, 2 = long) */
203 16, /* bitsize */
204 false, /* pc_relative */
205 0, /* bitpos */
206 complain_overflow_dont,/* complain_on_overflow */
207 bfd_elf_generic_reloc, /* special_function */
208 "R_V850_SDA_OFFSET", /* name */
209 true, /* partial_inplace */
210 0xffff, /* src_mask */
211 0xffff, /* dst_mask */
212 false), /* pcrel_offset */
b6d08fce 213
c322f1b5 214 /* Offset from the zero data area pointer. */
afaed5e9
MM
215 HOWTO (R_V850_ZDA_OFFSET, /* type */
216 0, /* rightshift */
217 1, /* size (0 = byte, 1 = short, 2 = long) */
218 16, /* bitsize */
219 false, /* pc_relative */
220 0, /* bitpos */
221 complain_overflow_dont,/* complain_on_overflow */
222 bfd_elf_generic_reloc, /* special_function */
223 "R_V850_ZDA_OFFSET", /* name */
224 true, /* partial_inplace */
225 0xffff, /* src_mask */
226 0xffff, /* dst_mask */
227 false), /* pcrel_offset */
b6d08fce 228
c322f1b5 229 /* Offset from the tiny data area pointer. */
afaed5e9
MM
230 HOWTO (R_V850_TDA_OFFSET, /* type */
231 0, /* rightshift */
232 2, /* size (0 = byte, 1 = short, 2 = long) */
233 8, /* bitsize */
234 false, /* pc_relative */
235 0, /* bitpos */
236 complain_overflow_dont,/* complain_on_overflow */
237 bfd_elf_generic_reloc, /* special_function */
238 "R_V850_TDA_OFFSET", /* name */
239 true, /* partial_inplace */
240 0xff, /* src_mask */
241 0xff, /* dst_mask */
242 false), /* pcrel_offset */
b6d08fce 243
01b49cb3
C
244};
245
246/* Map BFD reloc types to V850 ELF reloc types. */
247
248struct v850_reloc_map
249{
250 unsigned char bfd_reloc_val;
251 unsigned char elf_reloc_val;
252};
253
254static const struct v850_reloc_map v850_reloc_map[] =
255{
256 { BFD_RELOC_NONE, R_V850_NONE, },
257 { BFD_RELOC_V850_9_PCREL, R_V850_9_PCREL, },
258 { BFD_RELOC_V850_22_PCREL, R_V850_22_PCREL, },
259 { BFD_RELOC_HI16_S, R_V850_HI16_S, },
260 { BFD_RELOC_HI16, R_V850_HI16, },
261 { BFD_RELOC_LO16, R_V850_LO16, },
237b5c4c
JL
262 { BFD_RELOC_32, R_V850_32, },
263 { BFD_RELOC_16, R_V850_16, },
264 { BFD_RELOC_8, R_V850_8, },
b6d08fce
JL
265 { BFD_RELOC_V850_TDA_OFFSET, R_V850_TDA_OFFSET, },
266 { BFD_RELOC_V850_SDA_OFFSET, R_V850_SDA_OFFSET, },
267 { BFD_RELOC_V850_ZDA_OFFSET, R_V850_ZDA_OFFSET, },
01b49cb3
C
268};
269
270static reloc_howto_type *
271bfd_elf32_bfd_reloc_type_lookup (abfd, code)
272 bfd *abfd;
273 bfd_reloc_code_real_type code;
274{
275 unsigned int i;
276
277 for (i = 0;
278 i < sizeof (v850_reloc_map) / sizeof (struct v850_reloc_map);
279 i++)
280 {
281 if (v850_reloc_map[i].bfd_reloc_val == code)
282 return &elf_v850_howto_table[v850_reloc_map[i].elf_reloc_val];
283 }
284
285 return NULL;
286}
287
288/* Set the howto pointer for an V850 ELF reloc. */
289
290static void
291v850_info_to_howto_rel (abfd, cache_ptr, dst)
292 bfd *abfd;
293 arelent *cache_ptr;
294 Elf32_Internal_Rel *dst;
295{
296 unsigned int r_type;
297
298 r_type = ELF32_R_TYPE (dst->r_info);
299 BFD_ASSERT (r_type < (unsigned int) R_V850_max);
300 cache_ptr->howto = &elf_v850_howto_table[r_type];
301}
302
e73b6ae6
JL
303static bfd_reloc_status_type
304bfd_elf32_v850_reloc (abfd, reloc, symbol, data, isection, obfd, err)
305 bfd *abfd;
306 arelent *reloc;
307 asymbol *symbol;
308 PTR data;
309 asection *isection;
310 bfd *obfd;
311 char **err;
312{
313 if (obfd != (bfd *) NULL
314 && (symbol->flags & BSF_SECTION_SYM) == 0
315 && (! reloc->howto->partial_inplace
316 || reloc->addend == 0))
317 {
318 reloc->address += isection->output_offset;
319 return bfd_reloc_ok;
320 }
321 else if (obfd != NULL)
322 {
323 return bfd_reloc_continue;
324 }
325
05f1baaa
JL
326 /* Catch relocs involving undefined symbols. */
327 if (bfd_is_und_section (symbol->section)
328 && (symbol->flags & BSF_WEAK) == 0
329 && obfd == NULL)
330 return bfd_reloc_undefined;
331
e73b6ae6
JL
332 /* We handle final linking of some relocs ourselves. */
333 {
334 long relocation, insn;
335
336 /* Is the address of the relocation really within the section? */
337 if (reloc->address > isection->_cooked_size)
338 return bfd_reloc_outofrange;
339
340 /* Work out which section the relocation is targetted at and the
341 initial relocation command value. */
342
343 /* Get symbol value. (Common symbols are special.) */
344 if (bfd_is_com_section (symbol->section))
345 relocation = 0;
346 else
347 relocation = symbol->value;
348
349 /* Convert input-section-relative symbol value to absolute + addend. */
350 relocation += symbol->section->output_section->vma;
351 relocation += symbol->section->output_offset;
352 relocation += reloc->addend;
353
354 if (reloc->howto->pc_relative == true)
355 {
356 /* Here the variable relocation holds the final address of the
357 symbol we are relocating against, plus any addend. */
358 relocation -= isection->output_section->vma + isection->output_offset;
359
360 /* Deal with pcrel_offset */
361 relocation -= reloc->address;
362 }
363
364 /* I've got no clue... */
365 reloc->addend = 0;
366
367 if (reloc->howto->type == R_V850_22_PCREL)
368 {
369 if (relocation > 0x1ffff || relocation < -0x200000)
370 return bfd_reloc_overflow;
371
372 if ((relocation % 2) != 0)
373 return bfd_reloc_dangerous;
374
375 insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
e1d98a0a 376 insn &= ~0xfffe003f;
e73b6ae6
JL
377 insn |= (((relocation & 0xfffe) << 16)
378 | ((relocation & 0x3f0000) >> 16));
379 bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
380 return bfd_reloc_ok;
381 }
382 else if (reloc->howto->type == R_V850_9_PCREL)
383 {
384 if (relocation > 0xff || relocation < -0x100)
385 return bfd_reloc_overflow;
386
387 if ((relocation % 2) != 0)
388 return bfd_reloc_dangerous;
389
390 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
e1d98a0a 391 insn &= 0xf870;
e73b6ae6
JL
392 insn |= ((relocation & 0x1f0) << 7) | ((relocation & 0x0e) << 3);
393 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
394 return bfd_reloc_ok;
395 }
396 else if (reloc->howto->type == R_V850_HI16_S)
397 {
1336da39 398 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
e73b6ae6
JL
399 relocation = (relocation >> 16) + ((relocation & 0x8000) != 0);
400 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
401 return bfd_reloc_ok;
402 }
403 else if (reloc->howto->type == R_V850_HI16)
404 {
1336da39 405 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
e73b6ae6
JL
406 relocation = (relocation >> 16);
407 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
408 return bfd_reloc_ok;
409 }
725b96f5
JL
410 else
411 return bfd_reloc_notsupported;
e73b6ae6
JL
412 }
413
414 return bfd_reloc_continue;
415}
416
1336da39
SG
417static boolean bfd_elf32_v850_is_local_label PARAMS ((bfd *, asymbol *));
418
419/*ARGSUSED*/
420static boolean
421bfd_elf32_v850_is_local_label (abfd, symbol)
422 bfd *abfd;
423 asymbol *symbol;
424{
425 return ((symbol->name[0] == '.' && (symbol->name[1] == 'L' || symbol->name[1] == '.'))
426 || (symbol->name[0] == '_' && symbol->name[1] == '.' && symbol->name[2] == 'L'
427 && symbol->name[3] == '_'));
428}
429
725b96f5
JL
430/* Perform a relocation as part of a final link. */
431static bfd_reloc_status_type
432elf32_v850_bfd_final_link_relocate (howto, input_bfd, output_bfd,
433 input_section, contents, offset, value,
434 addend, info, sym_sec, is_local)
435 reloc_howto_type *howto;
436 bfd *input_bfd;
437 bfd *output_bfd;
438 asection *input_section;
439 bfd_byte *contents;
440 bfd_vma offset;
441 bfd_vma value;
442 bfd_vma addend;
443 struct bfd_link_info *info;
444 asection *sym_sec;
445 int is_local;
446{
447 unsigned long insn;
448 unsigned long r_type = howto->type;
449 unsigned long r_format = howto->bitsize;
450 bfd_byte *hit_data = contents + offset;
451 boolean r_pcrel = howto->pc_relative;
452
453 switch (r_type)
454 {
455 case R_V850_9_PCREL:
456 value -= (input_section->output_section->vma
457 + input_section->output_offset);
458 value -= offset;
459
460 if ((long)value > 0xff || (long)value < -0x100)
461 return bfd_reloc_overflow;
462
463 if ((value % 2) != 0)
464 return bfd_reloc_dangerous;
465
466 insn = bfd_get_16 (input_bfd, hit_data);
c322f1b5 467 insn &= 0x078f;
725b96f5
JL
468 insn |= ((value & 0x1f0) << 7) | ((value & 0x0e) << 3);
469 bfd_put_16 (input_bfd, insn, hit_data);
470 return bfd_reloc_ok;
471
472 case R_V850_22_PCREL:
473 value -= (input_section->output_section->vma
474 + input_section->output_offset);
475 value -= offset;
476
477 if ((long)value > 0x1ffff || (long)value < -0x200000)
478 return bfd_reloc_overflow;
479
480 if ((value % 2) != 0)
481 return bfd_reloc_dangerous;
482
483 insn = bfd_get_32 (input_bfd, hit_data);
c322f1b5 484 insn &= 0x1ffc0;
725b96f5
JL
485 insn |= (((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16));
486 bfd_put_32 (input_bfd, insn, hit_data);
487 return bfd_reloc_ok;
488
489 case R_V850_HI16_S:
90ffe48b 490 value += (short)bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
491 value = (value >> 16) + ((value & 0x8000) != 0);
492
493 if ((long)value > 0x7fff || (long)value < -0x8000)
494 return bfd_reloc_overflow;
495
496 bfd_put_16 (input_bfd, value, hit_data);
497 return bfd_reloc_ok;
498
499 case R_V850_HI16:
90ffe48b 500 value += (short)bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
501 value >>= 16;
502
503 if ((long)value > 0x7fff || (long)value < -0x8000)
504 return bfd_reloc_overflow;
505
506 bfd_put_16 (input_bfd, value, hit_data);
507 return bfd_reloc_ok;
508
509 case R_V850_LO16:
90ffe48b 510 value += (short)bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
511 value &= 0xffff;
512
513 bfd_put_16 (input_bfd, value, hit_data);
514 return bfd_reloc_ok;
515
516 case R_V850_16:
517 case R_V850_ZDA_OFFSET:
90ffe48b 518 value += (short)bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
519
520 if ((long)value > 0x7fff || (long)value < -0x8000)
521 return bfd_reloc_overflow;
522
523 bfd_put_16 (input_bfd, value, hit_data);
524 return bfd_reloc_ok;
525
526 case R_V850_32:
527 value += bfd_get_32 (input_bfd, hit_data);
528 bfd_put_32 (input_bfd, value, hit_data);
529 return bfd_reloc_ok;
530
531 case R_V850_8:
90ffe48b 532 value += (char)bfd_get_8 (input_bfd, hit_data);
725b96f5
JL
533
534 if ((long)value > 0x7f || (long)value < -0x80)
535 return bfd_reloc_overflow;
536
537 bfd_put_8 (input_bfd, value, hit_data);
538 return bfd_reloc_ok;
539
540 case R_V850_SDA_OFFSET:
541 {
542 unsigned long gp;
543 struct bfd_link_hash_entry *h;
544
90ffe48b 545 value += (short)bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
546
547 /* Get the value of __gp. */
548 h = bfd_link_hash_lookup (info->hash, "__gp", false,
549 false, true);
550 if (h == (struct bfd_link_hash_entry *) NULL
551 || h->type != bfd_link_hash_defined)
552 return bfd_reloc_undefined;
553
554 gp = (h->u.def.value
555 + h->u.def.section->output_section->vma
556 + h->u.def.section->output_offset);
557 value -= gp;
558
559 if ((long)value > 0x7fff || (long)value < -0x8000)
560 return bfd_reloc_overflow;
561
562 bfd_put_16 (input_bfd, value, hit_data);
563 return bfd_reloc_ok;
564 }
565
566 case R_V850_TDA_OFFSET:
567 {
568 unsigned long ep;
569 struct bfd_link_hash_entry *h;
570
c322f1b5 571 insn = bfd_get_16 (input_bfd, hit_data);
725b96f5
JL
572
573 /* Get the value of __ep. */
574 h = bfd_link_hash_lookup (info->hash, "__ep", false,
575 false, true);
576 if (h == (struct bfd_link_hash_entry *) NULL
577 || h->type != bfd_link_hash_defined)
578 return bfd_reloc_undefined;
579
580 ep = (h->u.def.value
581 + h->u.def.section->output_section->vma
582 + h->u.def.section->output_offset);
583 value -= ep;
584
585
c322f1b5
JL
586 /* Overflow computation and operand insertion is complicated
587 by valid offsets and insertions changing depending on the
588 instruction being used! */
589 if ((insn & 0x0780) == 0x0500)
590 {
afaed5e9 591 value += ((insn & 0x7f) << 1);
c322f1b5
JL
592
593 /* Handle sld.w and sst.w -- 8 bit unsigned offset */
594 if ((long) value > 0xff || (long) value < 0)
595 return bfd_reloc_overflow;
596
afaed5e9 597 if ((value % 2) != 0)
c322f1b5
JL
598 return bfd_reloc_dangerous;
599
600 insn &= 0xff81;
601 insn |= (value >> 1);
602 bfd_put_16 (input_bfd, insn, hit_data);
603 return bfd_reloc_ok;
604 }
605
606 if ((insn & 0x0780) == 0x0400 || (insn & 0x0780) == 0x0480)
607 {
608 value += ((insn & 0x7f) << 1);
609
610 /* Handle sld.h and sst.h -- 8 bit unsigned offset */
611 if ((long) value > 0xff || (long) value < 0)
612 return bfd_reloc_overflow;
613
614 if ((value % 2) != 0)
615 return bfd_reloc_dangerous;
616
617 insn &= 0xff80;
618 insn |= (value >> 1);
619 bfd_put_16 (input_bfd, insn, hit_data);
620 return bfd_reloc_ok;
621 }
622
623 if ((insn & 0x0780) == 0x0300 || (insn & 0x0780) == 0x0380)
624 {
625 value += (insn & 0x7f);
626
627 /* Handle sld.b and sst.b -- 7 bit unsigned offset */
628 if ((long) value > 0x7f || (long) value < 0)
629 return bfd_reloc_overflow;
630 insn &= 0xff80;
631 insn |= value;
632 bfd_put_16 (input_bfd, insn, hit_data);
633 return bfd_reloc_ok;
634 }
635
636 /* Guess (XXX) that it's a movea instruction or something
637 similar. */
90ffe48b 638 value += (short)insn;
c322f1b5
JL
639 if ((long)value > 0x7fff || (long)value < -0x8000)
640 return bfd_reloc_overflow;
641
642 bfd_put_16 (input_bfd, value, hit_data);
643 return bfd_reloc_ok;
725b96f5
JL
644 }
645
646 case R_V850_NONE:
647 default:
648 break;
649 }
650
651}
652
653/* Relocate an V850 ELF section. */
654
655static boolean
656v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
657 contents, relocs, local_syms, local_sections)
658 bfd *output_bfd;
659 struct bfd_link_info *info;
660 bfd *input_bfd;
661 asection *input_section;
662 bfd_byte *contents;
663 Elf_Internal_Rela *relocs;
664 Elf_Internal_Sym *local_syms;
665 asection **local_sections;
666{
667 Elf_Internal_Shdr *symtab_hdr;
668 struct elf_link_hash_entry **sym_hashes;
669 Elf_Internal_Rela *rel, *relend;
670
671 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
672 sym_hashes = elf_sym_hashes (input_bfd);
673
674 rel = relocs;
675 relend = relocs + input_section->reloc_count;
676 for (; rel < relend; rel++)
677 {
678 int r_type;
679 reloc_howto_type *howto;
680 unsigned long r_symndx;
681 Elf_Internal_Sym *sym;
682 asection *sec;
683 struct elf_link_hash_entry *h;
684 bfd_vma relocation;
685 bfd_reloc_status_type r;
686
687 if (info->relocateable)
688 {
689 /* This is a relocateable link. We don't have to change
690 anything, unless the reloc is against a section symbol,
691 in which case we have to adjust according to where the
692 section symbol winds up in the output section. */
693 if (r_symndx < symtab_hdr->sh_info)
694 {
695 sym = local_syms + r_symndx;
696 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
697 {
698 sec = local_sections[r_symndx];
699 rel->r_addend += sec->output_offset + sym->st_value;
700 }
701 }
702
703 continue;
704 }
705
706 r_type = ELF32_R_TYPE (rel->r_info);
707
708 howto = elf_v850_howto_table + r_type;
709
710 r_symndx = ELF32_R_SYM (rel->r_info);
711
712 /* This is a final link. */
713 h = NULL;
714 sym = NULL;
715 sec = NULL;
716 if (r_symndx < symtab_hdr->sh_info)
717 {
718 sym = local_syms + r_symndx;
719 sec = local_sections[r_symndx];
720 relocation = (sec->output_section->vma
721 + sec->output_offset
722 + sym->st_value);
723 }
724 else
725 {
726 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
727 while (h->root.type == bfd_link_hash_indirect
728 || h->root.type == bfd_link_hash_warning)
729 h = (struct elf_link_hash_entry *) h->root.u.i.link;
730 if (h->root.type == bfd_link_hash_defined
731 || h->root.type == bfd_link_hash_defweak)
732 {
733 sec = h->root.u.def.section;
734 relocation = (h->root.u.def.value
735 + sec->output_section->vma
736 + sec->output_offset);
737 }
738 else if (h->root.type == bfd_link_hash_undefweak)
739 relocation = 0;
740 else
741 {
742 if (! ((*info->callbacks->undefined_symbol)
743 (info, h->root.root.string, input_bfd,
744 input_section, rel->r_offset)))
745 return false;
746 relocation = 0;
747 }
748 }
749
750 /* FIXME: We should use the addend, but the COFF relocations
751 don't. */
752 r = elf32_v850_bfd_final_link_relocate (howto, input_bfd, output_bfd,
753 input_section,
754 contents, rel->r_offset,
755 relocation, rel->r_addend,
756 info, sec, h == NULL);
757
758 if (r != bfd_reloc_ok)
759 {
760 switch (r)
761 {
762 default:
763 case bfd_reloc_outofrange:
764 abort ();
765 case bfd_reloc_overflow:
766 {
767 const char *name;
768
769 if (h != NULL)
770 name = h->root.root.string;
771 else
772 {
773 name = (bfd_elf_string_from_elf_section
774 (input_bfd, symtab_hdr->sh_link, sym->st_name));
775 if (name == NULL)
776 return false;
777 if (*name == '\0')
778 name = bfd_section_name (input_bfd, sec);
779 }
780 if (! ((*info->callbacks->reloc_overflow)
781 (info, name, howto->name, (bfd_vma) 0,
782 input_bfd, input_section, rel->r_offset)))
783 return false;
784 }
785 break;
786 }
787 }
788 }
789
790 return true;
791}
1336da39
SG
792#define bfd_elf32_bfd_is_local_label bfd_elf32_v850_is_local_label
793
e73b6ae6
JL
794#define TARGET_LITTLE_SYM bfd_elf32_v850_vec
795#define TARGET_LITTLE_NAME "elf32-v850"
01b49cb3
C
796#define ELF_ARCH bfd_arch_v850
797#define ELF_MACHINE_CODE EM_CYGNUS_V850
798#define ELF_MAXPAGESIZE 0x1000
799
800#define elf_info_to_howto 0
801#define elf_info_to_howto_rel v850_info_to_howto_rel
725b96f5
JL
802#define elf_backend_relocate_section v850_elf_relocate_section
803
01b49cb3 804
1336da39
SG
805#define elf_symbol_leading_char '_'
806
01b49cb3 807#include "elf32-target.h"
This page took 0.066076 seconds and 4 git commands to generate.