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