]> Git Repo - binutils.git/blob - bfd/elf32-v850.c
* config/m68k/sun3os4.mh (MMALLOC_CFLAGS): Define MMCHECK_FORCE to 1.
[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
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
26 #include "bfd.h"
27 #include "sysdep.h"
28 #include "bfdlink.h"
29 #include "libbfd.h"
30 #include "elf-bfd.h"
31
32 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
33   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
34 static void v850_info_to_howto_rel
35   PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
36 static bfd_reloc_status_type bfd_elf32_v850_reloc
37   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
38
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
45 enum 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,
53   R_V850_32,
54   R_V850_16,
55   R_V850_8,
56   R_V850_SDA_OFFSET,
57   R_V850_ZDA_OFFSET,
58   R_V850_TDA_OFFSET,
59   R_V850_max
60 };
61
62 static 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 */
87          bfd_elf32_v850_reloc,  /* special_function */
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 */
102          bfd_elf32_v850_reloc,  /* special_function */
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.  */
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 */
123
124   /* High 16 bits of symbol value.  */
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 */
138
139   /* Low 16 bits of symbol value.  */
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 */
153
154   /* Simple 32bit reloc.  */
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 */
168
169   /* Simple 16bit reloc.  */
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 */
198
199   /* Offset from the short data area pointer.  */
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 */
213
214   /* Offset from the zero data area pointer.  */
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 */
228
229   /* Offset from the tiny data area pointer.  */
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 */
243
244 };
245
246 /* Map BFD reloc types to V850 ELF reloc types.  */
247
248 struct v850_reloc_map
249 {
250   unsigned char bfd_reloc_val;
251   unsigned char elf_reloc_val;
252 };
253
254 static 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, },
262   { BFD_RELOC_32, R_V850_32, },
263   { BFD_RELOC_16, R_V850_16, },
264   { BFD_RELOC_8, R_V850_8, },
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, },
268 };
269
270 static reloc_howto_type *
271 bfd_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
290 static void
291 v850_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
303 static bfd_reloc_status_type
304 bfd_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
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
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);
376           insn &= ~0xfffe003f;
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);
391           insn &= 0xf870;
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         {
398           relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
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         {
405           relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
406           relocation = (relocation >> 16);
407           bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
408           return bfd_reloc_ok;
409         }
410       else
411         return bfd_reloc_notsupported;
412     }
413
414   return bfd_reloc_continue;
415 }
416
417 static boolean bfd_elf32_v850_is_local_label PARAMS ((bfd *, asymbol *));
418
419 /*ARGSUSED*/
420 static boolean
421 bfd_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
430 /* Perform a relocation as part of a final link.  */
431 static bfd_reloc_status_type
432 elf32_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);
467       insn &= 0x078f;
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);
484       insn &= 0x1ffc0;
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:
490       value += (short)bfd_get_16 (input_bfd, hit_data);
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:
500       value += (short)bfd_get_16 (input_bfd, hit_data);
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:
510       value += (short)bfd_get_16 (input_bfd, hit_data);
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:
518       value += (short)bfd_get_16 (input_bfd, hit_data);
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:
532       value += (char)bfd_get_8 (input_bfd, hit_data);
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
545         value += (short)bfd_get_16 (input_bfd, hit_data);
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
571         insn = bfd_get_16 (input_bfd, hit_data);
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
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           {
591             value += ((insn & 0x7f) << 2);
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
597             if ((value % 4) != 0)
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.  */
638         value += (short)insn;
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;
644       }
645     
646     case R_V850_NONE:
647     default:
648       break;
649     }
650
651 }
652
653 /* Relocate an V850 ELF section.  */
654
655 static boolean
656 v850_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 }
792 #define bfd_elf32_bfd_is_local_label    bfd_elf32_v850_is_local_label
793
794 #define TARGET_LITTLE_SYM               bfd_elf32_v850_vec
795 #define TARGET_LITTLE_NAME              "elf32-v850"
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
802 #define elf_backend_relocate_section    v850_elf_relocate_section
803
804
805 #define elf_symbol_leading_char '_'
806
807 #include "elf32-target.h"
This page took 0.068388 seconds and 4 git commands to generate.