]> Git Repo - binutils.git/blob - bfd/elf32-v850.c
* cpu-mips.c (arch_info_struct): Make r5900 pointer size 32bits.
[binutils.git] / bfd / elf32-v850.c
1 /* V850-specific support for 32-bit ELF
2    Copyright (C) 1996, 1997 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 #include "elf/v850.h"
32
33 /* sign-extend a 24-bit number */
34 #define SEXT24(x)       ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
35       
36 static reloc_howto_type *v850_elf_reloc_type_lookup
37   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
38 static void v850_elf_info_to_howto_rel
39   PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
40 static bfd_reloc_status_type v850_elf_reloc
41   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
42 static boolean v850_elf_is_local_label_name PARAMS ((bfd *, const char *));
43 static boolean v850_elf_relocate_section PARAMS((bfd *,
44                                                  struct bfd_link_info *,
45                                                  bfd *,
46                                                  asection *,
47                                                  bfd_byte *,
48                                                  Elf_Internal_Rela *,
49                                                  Elf_Internal_Sym *,
50                                                  asection **));
51 /* Try to minimize the amount of space occupied by relocation tables
52    on the ROM (not that the ROM won't be swamped by other ELF overhead).  */
53 #define USE_REL
54
55 /* Note: It is REQUIRED that the 'type' value of each entry in this array
56    match the index of the entry in the array.  */
57 static reloc_howto_type v850_elf_howto_table[] =
58 {
59   /* This reloc does nothing.  */
60   HOWTO (R_V850_NONE,                   /* type */
61          0,                             /* rightshift */
62          2,                             /* size (0 = byte, 1 = short, 2 = long) */
63          32,                            /* bitsize */
64          false,                         /* pc_relative */
65          0,                             /* bitpos */
66          complain_overflow_bitfield,    /* complain_on_overflow */
67          bfd_elf_generic_reloc,         /* special_function */
68          "R_V850_NONE",                 /* name */
69          false,                         /* partial_inplace */
70          0,                             /* src_mask */
71          0,                             /* dst_mask */
72          false),                        /* pcrel_offset */
73
74   /* A PC relative 9 bit branch. */
75   HOWTO (R_V850_9_PCREL,                /* type */
76          2,                             /* rightshift */
77          2,                             /* size (0 = byte, 1 = short, 2 = long) */
78          26,                            /* bitsize */
79          true,                          /* pc_relative */
80          0,                             /* bitpos */
81          complain_overflow_bitfield,    /* complain_on_overflow */
82          v850_elf_reloc,                /* special_function */
83          "R_V850_9_PCREL",              /* name */
84          false,                         /* partial_inplace */
85          0x00ffffff,                    /* src_mask */
86          0x00ffffff,                    /* dst_mask */
87          true),                         /* pcrel_offset */
88
89   /* A PC relative 22 bit branch. */
90   HOWTO (R_V850_22_PCREL,               /* type */
91          2,                             /* rightshift */
92          2,                             /* size (0 = byte, 1 = short, 2 = long) */
93          22,                            /* bitsize */
94          true,                          /* pc_relative */
95          7,                             /* bitpos */
96          complain_overflow_signed,      /* complain_on_overflow */
97          v850_elf_reloc,                /* special_function */
98          "R_V850_22_PCREL",             /* name */
99          false,                         /* partial_inplace */
100          0x07ffff80,                    /* src_mask */
101          0x07ffff80,                    /* dst_mask */
102          true),                         /* pcrel_offset */
103
104   /* High 16 bits of symbol value.  */
105   HOWTO (R_V850_HI16_S,                 /* type */
106          0,                             /* rightshift */
107          1,                             /* size (0 = byte, 1 = short, 2 = long) */
108          16,                            /* bitsize */
109          false,                         /* pc_relative */
110          0,                             /* bitpos */
111          complain_overflow_dont,        /* complain_on_overflow */
112          v850_elf_reloc,                /* special_function */
113          "R_V850_HI16_S",               /* name */
114          true,                          /* partial_inplace */
115          0xffff,                        /* src_mask */
116          0xffff,                        /* dst_mask */
117          false),                        /* pcrel_offset */
118
119   /* High 16 bits of symbol value.  */
120   HOWTO (R_V850_HI16,                   /* type */
121          0,                             /* rightshift */
122          1,                             /* size (0 = byte, 1 = short, 2 = long) */
123          16,                            /* bitsize */
124          false,                         /* pc_relative */
125          0,                             /* bitpos */
126          complain_overflow_dont,        /* complain_on_overflow */
127          v850_elf_reloc,                /* special_function */
128          "R_V850_HI16",                 /* name */
129          true,                          /* partial_inplace */
130          0xffff,                        /* src_mask */
131          0xffff,                        /* dst_mask */
132          false),                        /* pcrel_offset */
133
134   /* Low 16 bits of symbol value.  */
135   HOWTO (R_V850_LO16,                   /* type */
136          0,                             /* rightshift */
137          1,                             /* size (0 = byte, 1 = short, 2 = long) */
138          16,                            /* bitsize */
139          false,                         /* pc_relative */
140          0,                             /* bitpos */
141          complain_overflow_dont,        /* complain_on_overflow */
142          v850_elf_reloc,                /* special_function */
143          "R_V850_LO16",                 /* name */
144          true,                          /* partial_inplace */
145          0xffff,                        /* src_mask */
146          0xffff,                        /* dst_mask */
147          false),                        /* pcrel_offset */
148
149   /* Simple 32bit reloc.  */
150   HOWTO (R_V850_32,                     /* type */
151          0,                             /* rightshift */
152          2,                             /* size (0 = byte, 1 = short, 2 = long) */
153          32,                            /* bitsize */
154          false,                         /* pc_relative */
155          0,                             /* bitpos */
156          complain_overflow_dont,        /* complain_on_overflow */
157          v850_elf_reloc,                /* special_function */
158          "R_V850_32",                   /* name */
159          true,                          /* partial_inplace */
160          0xffffffff,                    /* src_mask */
161          0xffffffff,                    /* dst_mask */
162          false),                        /* pcrel_offset */
163
164   /* Simple 16bit reloc.  */
165   HOWTO (R_V850_16,                     /* type */
166          0,                             /* rightshift */
167          1,                             /* size (0 = byte, 1 = short, 2 = long) */
168          16,                            /* bitsize */
169          false,                         /* pc_relative */
170          0,                             /* bitpos */
171          complain_overflow_dont,        /* complain_on_overflow */
172          bfd_elf_generic_reloc,         /* special_function */
173          "R_V850_16",                   /* name */
174          true,                          /* partial_inplace */
175          0xffff,                        /* src_mask */
176          0xffff,                        /* dst_mask */
177          false),                        /* pcrel_offset */
178
179   /* Simple 8bit reloc.  */
180   HOWTO (R_V850_8,                      /* type */
181          0,                             /* rightshift */
182          0,                             /* size (0 = byte, 1 = short, 2 = long) */
183          8,                             /* bitsize */
184          false,                         /* pc_relative */
185          0,                             /* bitpos */
186          complain_overflow_dont,        /* complain_on_overflow */
187          bfd_elf_generic_reloc,         /* special_function */
188          "R_V850_8",                    /* name */
189          true,                          /* partial_inplace */
190          0xff,                          /* src_mask */
191          0xff,                          /* dst_mask */
192          false),                        /* pcrel_offset */
193
194   /* 16 bit offset from the short data area pointer.  */
195   HOWTO (R_V850_SDA_16_16_OFFSET,       /* type */
196          0,                             /* rightshift */
197          1,                             /* size (0 = byte, 1 = short, 2 = long) */
198          16,                            /* bitsize */
199          false,                         /* pc_relative */
200          0,                             /* bitpos */
201          complain_overflow_dont,        /* complain_on_overflow */
202          v850_elf_reloc,                /* special_function */
203          "R_V850_SDA_16_16_OFFSET",     /* name */
204          false,                         /* partial_inplace */
205          0xffff,                        /* src_mask */
206          0xffff,                        /* dst_mask */
207          false),                        /* pcrel_offset */
208
209   /* 15 bit offset from the short data area pointer.  */
210   HOWTO (R_V850_SDA_15_16_OFFSET,       /* type */
211          1,                             /* rightshift */
212          1,                             /* size (0 = byte, 1 = short, 2 = long) */
213          16,                            /* bitsize */
214          false,                         /* pc_relative */
215          1,                             /* bitpos */
216          complain_overflow_dont,        /* complain_on_overflow */
217          v850_elf_reloc,                /* special_function */
218          "R_V850_SDA_15_16_OFFSET",     /* name */
219          false,                         /* partial_inplace */
220          0xfffe,                        /* src_mask */
221          0xfffe,                        /* dst_mask */
222          false),                        /* pcrel_offset */
223
224   /* 16 bit offset from the zero data area pointer.  */
225   HOWTO (R_V850_ZDA_16_16_OFFSET,       /* type */
226          0,                             /* rightshift */
227          1,                             /* size (0 = byte, 1 = short, 2 = long) */
228          16,                            /* bitsize */
229          false,                         /* pc_relative */
230          0,                             /* bitpos */
231          complain_overflow_dont,        /* complain_on_overflow */
232          v850_elf_reloc,                /* special_function */
233          "R_V850_ZDA_16_16_OFFSET",     /* name */
234          false,                         /* partial_inplace */
235          0xffff,                        /* src_mask */
236          0xffff,                        /* dst_mask */
237          false),                        /* pcrel_offset */
238
239   /* 15 bit offset from the zero data area pointer.  */
240   HOWTO (R_V850_ZDA_15_16_OFFSET,       /* type */
241          1,                             /* rightshift */
242          1,                             /* size (0 = byte, 1 = short, 2 = long) */
243          16,                            /* bitsize */
244          false,                         /* pc_relative */
245          1,                             /* bitpos */
246          complain_overflow_dont,        /* complain_on_overflow */
247          v850_elf_reloc,                /* special_function */
248          "R_V850_ZDA_15_16_OFFSET",     /* name */
249          false,                         /* partial_inplace */
250          0xfffe,                        /* src_mask */
251          0xfffe,                        /* dst_mask */
252          false),                        /* pcrel_offset */
253
254   /* 6 bit offset from the tiny data area pointer.  */
255   HOWTO (R_V850_TDA_6_8_OFFSET,         /* type */
256          2,                             /* rightshift */
257          1,                             /* size (0 = byte, 1 = short, 2 = long) */
258          8,                             /* bitsize */
259          false,                         /* pc_relative */
260          1,                             /* bitpos */
261          complain_overflow_dont,        /* complain_on_overflow */
262          v850_elf_reloc,                /* special_function */
263          "R_V850_TDA_6_8_OFFSET",       /* name */
264          false,                         /* partial_inplace */
265          0x7e,                          /* src_mask */
266          0x7e,                          /* dst_mask */
267          false),                        /* pcrel_offset */
268
269   /* 8 bit offset from the tiny data area pointer.  */
270   HOWTO (R_V850_TDA_7_8_OFFSET,         /* type */
271          1,                             /* rightshift */
272          1,                             /* size (0 = byte, 1 = short, 2 = long) */
273          8,                             /* bitsize */
274          false,                         /* pc_relative */
275          0,                             /* bitpos */
276          complain_overflow_dont,        /* complain_on_overflow */
277          v850_elf_reloc,                /* special_function */
278          "R_V850_TDA_7_8_OFFSET",       /* name */
279          false,                         /* partial_inplace */
280          0x7f,                          /* src_mask */
281          0x7f,                          /* dst_mask */
282          false),                        /* pcrel_offset */
283   
284   /* 7 bit offset from the tiny data area pointer.  */
285   HOWTO (R_V850_TDA_7_7_OFFSET,         /* type */
286          0,                             /* rightshift */
287          1,                             /* size (0 = byte, 1 = short, 2 = long) */
288          7,                             /* bitsize */
289          false,                         /* pc_relative */
290          0,                             /* bitpos */
291          complain_overflow_dont,        /* complain_on_overflow */
292          v850_elf_reloc,                /* special_function */
293          "R_V850_TDA_7_7_OFFSET",       /* name */
294          false,                         /* partial_inplace */
295          0x7f,                          /* src_mask */
296          0x7f,                          /* dst_mask */
297          false),                        /* pcrel_offset */
298
299   /* 16 bit offset from the tiny data area pointer!  */
300   HOWTO (R_V850_TDA_16_16_OFFSET,       /* type */
301          0,                             /* rightshift */
302          1,                             /* size (0 = byte, 1 = short, 2 = long) */
303          16,                            /* bitsize */
304          false,                         /* pc_relative */
305          0,                             /* bitpos */
306          complain_overflow_dont,        /* complain_on_overflow */
307          v850_elf_reloc,                /* special_function */
308          "R_V850_TDA_16_16_OFFSET",     /* name */
309          false,                         /* partial_inplace */
310          0xffff,                        /* src_mask */
311          0xfff,                         /* dst_mask */
312          false),                        /* pcrel_offset */
313
314 /* start-sanitize-v850e */
315   
316   /* 5 bit offset from the tiny data area pointer.  */
317   HOWTO (R_V850_TDA_4_5_OFFSET,         /* type */
318          1,                             /* rightshift */
319          1,                             /* size (0 = byte, 1 = short, 2 = long) */
320          5,                             /* bitsize */
321          false,                         /* pc_relative */
322          0,                             /* bitpos */
323          complain_overflow_dont,        /* complain_on_overflow */
324          v850_elf_reloc,                /* special_function */
325          "R_V850_TDA_4_5_OFFSET",       /* name */
326          false,                         /* partial_inplace */
327          0x0f,                          /* src_mask */
328          0x0f,                          /* dst_mask */
329          false),                        /* pcrel_offset */
330
331   /* 4 bit offset from the tiny data area pointer.  */
332   HOWTO (R_V850_TDA_4_4_OFFSET,         /* type */
333          0,                             /* rightshift */
334          1,                             /* size (0 = byte, 1 = short, 2 = long) */
335          4,                             /* bitsize */
336          false,                         /* pc_relative */
337          0,                             /* bitpos */
338          complain_overflow_dont,        /* complain_on_overflow */
339          v850_elf_reloc,                /* special_function */
340          "R_V850_TDA_4_4_OFFSET",       /* name */
341          false,                         /* partial_inplace */
342          0x0f,                          /* src_mask */
343          0x0f,                          /* dst_mask */
344          false),                        /* pcrel_offset */
345
346   /* 16 bit offset from the short data area pointer.  */
347   HOWTO (R_V850_SDA_16_16_SPLIT_OFFSET, /* type */
348          0,                             /* rightshift */
349          2,                             /* size (0 = byte, 1 = short, 2 = long) */
350          16,                            /* bitsize */
351          false,                         /* pc_relative */
352          0,                             /* bitpos */
353          complain_overflow_dont,        /* complain_on_overflow */
354          v850_elf_reloc,                /* special_function */
355          "R_V850_SDA_16_16_SPLIT_OFFSET",/* name */
356          false,                         /* partial_inplace */
357          0xfffe0020,                    /* src_mask */
358          0xfffe0020,                    /* dst_mask */
359          false),                        /* pcrel_offset */
360
361   /* 16 bit offset from the zero data area pointer.  */
362   HOWTO (R_V850_ZDA_16_16_SPLIT_OFFSET, /* type */
363          0,                             /* rightshift */
364          2,                             /* size (0 = byte, 1 = short, 2 = long) */
365          16,                            /* bitsize */
366          false,                         /* pc_relative */
367          0,                             /* bitpos */
368          complain_overflow_dont,        /* complain_on_overflow */
369          v850_elf_reloc,                /* special_function */
370          "R_V850_ZDA_16_16_SPLIT_OFFSET",/* name */
371          false,                         /* partial_inplace */
372          0xfffe0020,                    /* src_mask */
373          0xfffe0020,                    /* dst_mask */
374          false),                        /* pcrel_offset */
375
376   /* 6 bit offset from the call table base pointer.  */
377   HOWTO (R_V850_CALLT_6_7_OFFSET,       /* type */
378          0,                             /* rightshift */
379          1,                             /* size (0 = byte, 1 = short, 2 = long) */
380          7,                             /* bitsize */
381          false,                         /* pc_relative */
382          0,                             /* bitpos */
383          complain_overflow_dont,        /* complain_on_overflow */
384          v850_elf_reloc,                /* special_function */
385          "R_V850_CALLT_6_7_OFFSET",     /* name */
386          false,                         /* partial_inplace */
387          0x3f,                          /* src_mask */
388          0x3f,                          /* dst_mask */
389          false),                        /* pcrel_offset */
390
391   /* 16 bit offset from the call table base pointer.  */
392   HOWTO (R_V850_CALLT_16_16_OFFSET,     /* type */
393          0,                             /* rightshift */
394          1,                             /* size (0 = byte, 1 = short, 2 = long) */
395          16,                            /* bitsize */
396          false,                         /* pc_relative */
397          0,                             /* bitpos */
398          complain_overflow_dont,        /* complain_on_overflow */
399          v850_elf_reloc,                /* special_function */
400          "R_V850_CALLT_16_16_OFFSET",   /* name */
401          false,                         /* partial_inplace */
402          0xffff,                        /* src_mask */
403          0xffff,                        /* dst_mask */
404          false),                        /* pcrel_offset */
405
406 /* end-sanitize-v850e */
407 };
408
409 /* Map BFD reloc types to V850 ELF reloc types.  */
410
411 struct v850_elf_reloc_map
412 {
413   unsigned char bfd_reloc_val;
414   unsigned char elf_reloc_val;
415 };
416
417 static const struct v850_elf_reloc_map v850_elf_reloc_map[] =
418 {
419   { BFD_RELOC_NONE,             R_V850_NONE },
420   { BFD_RELOC_V850_9_PCREL,     R_V850_9_PCREL },
421   { BFD_RELOC_V850_22_PCREL,    R_V850_22_PCREL },
422   { BFD_RELOC_HI16_S,           R_V850_HI16_S },
423   { BFD_RELOC_HI16,             R_V850_HI16 },
424   { BFD_RELOC_LO16,             R_V850_LO16 },
425   { BFD_RELOC_32,               R_V850_32 },
426   { BFD_RELOC_16,               R_V850_16 },
427   { BFD_RELOC_8,                R_V850_8 },
428   { BFD_RELOC_V850_SDA_16_16_OFFSET, R_V850_SDA_16_16_OFFSET },
429   { BFD_RELOC_V850_SDA_15_16_OFFSET, R_V850_SDA_15_16_OFFSET },
430   { BFD_RELOC_V850_ZDA_16_16_OFFSET, R_V850_ZDA_16_16_OFFSET },
431   { BFD_RELOC_V850_ZDA_15_16_OFFSET, R_V850_ZDA_15_16_OFFSET },
432   { BFD_RELOC_V850_TDA_6_8_OFFSET,   R_V850_TDA_6_8_OFFSET   },
433   { BFD_RELOC_V850_TDA_7_8_OFFSET,   R_V850_TDA_7_8_OFFSET   },
434   { BFD_RELOC_V850_TDA_7_7_OFFSET,   R_V850_TDA_7_7_OFFSET   },
435   { BFD_RELOC_V850_TDA_16_16_OFFSET, R_V850_TDA_16_16_OFFSET },
436 /* start-sanitize-v850e */
437   { BFD_RELOC_V850_TDA_4_5_OFFSET,         R_V850_TDA_4_5_OFFSET         },
438   { BFD_RELOC_V850_TDA_4_4_OFFSET,         R_V850_TDA_4_4_OFFSET         },
439   { BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET, R_V850_SDA_16_16_SPLIT_OFFSET },
440   { BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET, R_V850_ZDA_16_16_SPLIT_OFFSET },
441   { BFD_RELOC_V850_CALLT_6_7_OFFSET,       R_V850_CALLT_6_7_OFFSET       },
442   { BFD_RELOC_V850_CALLT_16_16_OFFSET,     R_V850_CALLT_16_16_OFFSET     },
443 /* end-sanitize-v850e */
444 };
445
446 \f
447 /* Map a bfd relocation into the appropriate howto structure */
448 static reloc_howto_type *
449 v850_elf_reloc_type_lookup (abfd, code)
450      bfd *                     abfd;
451      bfd_reloc_code_real_type  code;
452 {
453   unsigned int i;
454
455   for (i = 0;
456        i < sizeof (v850_elf_reloc_map) / sizeof (struct v850_elf_reloc_map);
457        i++)
458     {
459       if (v850_elf_reloc_map[i].bfd_reloc_val == code)
460         {
461           BFD_ASSERT (v850_elf_howto_table[v850_elf_reloc_map[i].elf_reloc_val].type == v850_elf_reloc_map[i].elf_reloc_val);
462           
463           return & v850_elf_howto_table[v850_elf_reloc_map[i].elf_reloc_val];
464         }
465     }
466
467   return NULL;
468 }
469
470 \f
471 /* Set the howto pointer for an V850 ELF reloc.  */
472 static void
473 v850_elf_info_to_howto_rel (abfd, cache_ptr, dst)
474      bfd *                 abfd;
475      arelent *             cache_ptr;
476      Elf32_Internal_Rel *  dst;
477 {
478   unsigned int r_type;
479
480   r_type = ELF32_R_TYPE (dst->r_info);
481   BFD_ASSERT (r_type < (unsigned int) R_V850_max);
482   cache_ptr->howto = &v850_elf_howto_table[r_type];
483 }
484
485 \f
486 /* Look through the relocs for a section during the first phase, and
487    allocate space in the global offset table or procedure linkage
488    table.  */
489
490 static boolean
491 v850_elf_check_relocs (abfd, info, sec, relocs)
492      bfd *                      abfd;
493      struct bfd_link_info *     info;
494      asection *                 sec;
495      const Elf_Internal_Rela *  relocs;
496 {
497   boolean ret = true;
498   bfd *dynobj;
499   Elf_Internal_Shdr *symtab_hdr;
500   struct elf_link_hash_entry **sym_hashes;
501   const Elf_Internal_Rela *rel;
502   const Elf_Internal_Rela *rel_end;
503   asection *sreloc;
504   enum v850_reloc_type r_type;
505   int other = 0;
506   const char *common = (const char *)0;
507
508   if (info->relocateable)
509     return true;
510
511 #ifdef DEBUG
512   fprintf (stderr, "v850_elf_check_relocs called for section %s in %s\n",
513            bfd_get_section_name (abfd, sec),
514            bfd_get_filename (abfd));
515 #endif
516
517   dynobj = elf_hash_table (info)->dynobj;
518   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
519   sym_hashes = elf_sym_hashes (abfd);
520   sreloc = NULL;
521
522   rel_end = relocs + sec->reloc_count;
523   for (rel = relocs; rel < rel_end; rel++)
524     {
525       unsigned long r_symndx;
526       struct elf_link_hash_entry *h;
527
528       r_symndx = ELF32_R_SYM (rel->r_info);
529       if (r_symndx < symtab_hdr->sh_info)
530         h = NULL;
531       else
532         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
533
534       r_type = (enum v850_reloc_type) ELF32_R_TYPE (rel->r_info);
535       switch (r_type)
536         {
537         default:
538         case R_V850_NONE:
539         case R_V850_9_PCREL:
540         case R_V850_22_PCREL:
541         case R_V850_HI16_S:
542         case R_V850_HI16:
543         case R_V850_LO16:
544         case R_V850_32:
545         case R_V850_16:
546         case R_V850_8:
547 /* start-sanitize-v850e */
548         case R_V850_CALLT_6_7_OFFSET:
549         case R_V850_CALLT_16_16_OFFSET:
550 /* end-sanitize-v850e */
551           break;
552
553 /* start-sanitize-v850e */
554         case R_V850_SDA_16_16_SPLIT_OFFSET:
555 /* end-sanitize-v850e */
556         case R_V850_SDA_16_16_OFFSET:
557         case R_V850_SDA_15_16_OFFSET:
558           other = V850_OTHER_SDA;
559           common = ".scommon";
560           goto small_data_common;
561           
562 /* start-sanitize-v850e */
563         case R_V850_ZDA_16_16_SPLIT_OFFSET:
564 /* end-sanitize-v850e */
565         case R_V850_ZDA_16_16_OFFSET:
566         case R_V850_ZDA_15_16_OFFSET:
567           other = V850_OTHER_ZDA;
568           common = ".zcommon";
569           goto small_data_common;
570           
571 /* start-sanitize-v850e */
572         case R_V850_TDA_4_5_OFFSET:
573         case R_V850_TDA_4_4_OFFSET:
574 /* end-sanitize-v850e */          
575         case R_V850_TDA_6_8_OFFSET:
576         case R_V850_TDA_7_8_OFFSET:
577         case R_V850_TDA_7_7_OFFSET:
578         case R_V850_TDA_16_16_OFFSET:
579           other = V850_OTHER_TDA;
580           common = ".tcommon";
581           /* fall through */
582
583 #define V850_OTHER_MASK (V850_OTHER_TDA | V850_OTHER_SDA | V850_OTHER_ZDA)
584
585         small_data_common:
586           if (h)
587             {
588               h->other |= other;        /* flag which type of relocation was used */
589               if ((h->other & V850_OTHER_MASK) != (other & V850_OTHER_MASK)
590                   && (h->other & V850_OTHER_ERROR) == 0)
591                 {
592                   const char * msg;
593                   static char  buff[100]; /* XXX */
594                   
595                   switch (h->other & V850_OTHER_MASK)
596                     {
597                     default:
598                       msg = "cannot occupy in multiple small data regions";
599                       break;
600                     case V850_OTHER_SDA | V850_OTHER_ZDA | V850_OTHER_TDA:
601                       msg = "can only be in one of the small, zero, and tiny data regions";
602                       break;
603                     case V850_OTHER_SDA | V850_OTHER_ZDA:
604                       msg = "cannot be in both small and zero data regions simultaneously";
605                       break;
606                     case V850_OTHER_SDA | V850_OTHER_TDA:
607                       msg = "cannot be in both small and tiny data regions simultaneously";
608                       break;
609                     case V850_OTHER_ZDA | V850_OTHER_TDA:
610                       msg = "cannot be in both zero and tiny data regions simultaneously";
611                       break;
612                     }
613
614                   sprintf (buff, "Variable '%s' %s", h->root.root.string, msg );
615                   info->callbacks->warning (info, buff, h->root.root.string,
616                                             abfd, h->root.u.def.section, 0);
617
618                   bfd_set_error (bfd_error_bad_value);
619                   h->other |= V850_OTHER_ERROR;
620                   ret = false;
621                 }
622             }
623
624           if (h && h->root.type == bfd_link_hash_common
625               && h->root.u.c.p
626               && !strcmp (bfd_get_section_name (abfd, h->root.u.c.p->section), "COMMON"))
627             {
628               asection *section = h->root.u.c.p->section = bfd_make_section_old_way (abfd, common);
629               section->flags |= SEC_IS_COMMON;
630             }
631
632 #ifdef DEBUG
633           fprintf (stderr, "v850_elf_check_relocs, found %s relocation for %s%s\n",
634                    v850_elf_howto_table[ (int)r_type ].name,
635                    (h && h->root.root.string) ? h->root.root.string : "<unknown>",
636                    (h->root.type == bfd_link_hash_common) ? ", symbol is common" : "");
637 #endif
638           break;
639         }
640     }
641
642   return ret;
643 }
644
645 static bfd_reloc_status_type
646 v850_elf_store_addend_in_insn (abfd, r_type, addend, address, replace)
647      bfd *      abfd;
648      int        r_type;
649      long       addend;
650      bfd_byte * address;
651      boolean    replace;
652 {
653   unsigned long insn;
654   
655   switch (r_type)
656     {
657     default:
658       /* fprintf (stderr, "reloc type %d not SUPPORTED\n", r_type ); */
659       return bfd_reloc_notsupported;
660       
661     case R_V850_32:
662       if (! replace)
663         addend += bfd_get_32 (abfd, address);
664
665       bfd_put_32 (abfd, addend, address);
666       return bfd_reloc_ok;
667       
668     case R_V850_22_PCREL:
669       if (addend > 0x1fffff || addend < -0x200000)
670         return bfd_reloc_overflow;
671       
672       if ((addend % 2) != 0)
673         return bfd_reloc_dangerous;
674       
675       insn  = bfd_get_32 (abfd, address);
676       insn &= ~0xfffe003f;
677       insn |= (((addend & 0xfffe) << 16) | ((addend & 0x3f0000) >> 16));
678       bfd_put_32 (abfd, insn, address);
679       return bfd_reloc_ok;
680       
681     case R_V850_9_PCREL:
682       if (addend > 0xff || addend < -0x100)
683         return bfd_reloc_overflow;
684       
685       if ((addend % 2) != 0)
686         return bfd_reloc_dangerous;
687       
688       insn  = bfd_get_16 (abfd, address);
689       insn &= ~ 0xf870;
690       insn |= ((addend & 0x1f0) << 7) | ((addend & 0x0e) << 3);
691       break;
692       
693     case R_V850_HI16_S:
694       addend += (bfd_get_16 (abfd, address) << 16);
695       addend = (addend >> 16) + ((addend & 0x8000) != 0);
696       insn = addend;
697       break;
698       
699     case R_V850_HI16:
700       addend += (bfd_get_16 (abfd, address) << 16);
701       addend = (addend >> 16);
702       insn = addend;
703       break;
704       
705     case R_V850_LO16:
706       addend += (short) bfd_get_16 (abfd, address);
707       /* Do not complain if value has top bit set, as this has been anticipated.  */
708       insn = addend;
709       break;
710
711     case R_V850_16:
712       replace = false;
713       /* drop through */
714             
715 /* start-sanitize-v850e */
716     case R_V850_CALLT_16_16_OFFSET:
717 /* end-sanitize-v850e */
718     case R_V850_SDA_16_16_OFFSET:
719     case R_V850_ZDA_16_16_OFFSET:
720     case R_V850_TDA_16_16_OFFSET:
721       if (! replace)
722         addend += bfd_get_16 (abfd, address);
723       
724       if (addend > 0x7fff || addend < -0x8000)
725         return bfd_reloc_overflow;
726
727       insn = addend;
728       break;
729       
730     case R_V850_SDA_15_16_OFFSET:
731     case R_V850_ZDA_15_16_OFFSET:
732       insn = bfd_get_16 (abfd, address);
733
734       if (! replace)
735         addend += ((insn & 0xfffe) << 1);
736       
737       if (addend > 0x7ffe || addend < -0x8000)
738         return bfd_reloc_overflow;
739       
740       if (addend & 1)
741         return bfd_reloc_dangerous;
742       
743       insn &= 1;
744       insn |= (addend >> 1) & ~1;
745       break;
746       
747     case R_V850_TDA_6_8_OFFSET:
748       insn = bfd_get_16 (abfd, address);
749
750       if (! replace)
751         addend += ((insn & 0x7e) << 1);
752       
753       if (addend > 0xfc || addend < 0)
754         return bfd_reloc_overflow;
755       
756       if (addend & 3)
757         return bfd_reloc_dangerous;
758       
759       insn &= 0xff81;
760       insn |= (addend >> 1);
761       break;
762       
763     case R_V850_TDA_7_8_OFFSET:
764       insn = bfd_get_16 (abfd, address);
765
766       if (! replace)
767         addend += ((insn & 0x7f) << 1);
768       
769       if (addend > 0xfe || addend < 0)
770         return bfd_reloc_overflow;
771       
772       if (addend & 1)
773         return bfd_reloc_dangerous;
774       
775       insn &= 0xff80;
776       insn |= (addend >> 1);
777       break;
778       
779     case R_V850_TDA_7_7_OFFSET:
780       insn = bfd_get_16 (abfd, address);
781
782       if (! replace)
783         addend += insn & 0x7f;
784         
785       if (addend > 0x7f || addend < 0)
786         return bfd_reloc_overflow;
787       
788       insn &= 0xff80;
789       insn |= addend;
790       break;
791       
792 /* start-sanitize-v850e */
793     case R_V850_TDA_4_5_OFFSET:
794       insn = bfd_get_16 (abfd, address);
795
796       if (! replace)
797         addend += ((insn & 0xf) << 1);
798       
799       if (addend > 0x1e || addend < 0)
800         return bfd_reloc_overflow;
801       
802       if (addend & 1)
803         return bfd_reloc_dangerous;
804       
805       insn &= 0xfff0;
806       insn |= (addend >> 1);
807       break;
808       
809     case R_V850_TDA_4_4_OFFSET:
810       insn = bfd_get_16 (abfd, address);
811
812       if (! replace)
813         addend += insn & 0xf;
814       
815       if (addend > 0xf || addend < 0)
816         return bfd_reloc_overflow;
817       
818       insn &= 0xfff0;
819       insn |= addend;
820       break;
821       
822     case R_V850_ZDA_16_16_SPLIT_OFFSET:
823     case R_V850_SDA_16_16_SPLIT_OFFSET:
824       insn = bfd_get_32 (abfd, address);
825
826       if (! replace)
827         addend += ((insn & 0xfffe0000) >> 16) + ((insn & 0x20) >> 5);
828       
829       if (addend > 0xffff || addend < 0)
830         return bfd_reloc_overflow;
831       
832       insn &= 0x0001ffdf;
833       insn |= (addend & 1) << 5;
834       insn |= (addend & ~1) << 16;
835       
836       bfd_put_32 (abfd, insn, address);
837       return bfd_reloc_ok;
838       
839     case R_V850_CALLT_6_7_OFFSET:
840       insn = bfd_get_16 (abfd, address);
841
842       if (! replace)
843         addend += ((insn & 0x3f) << 1);
844       
845       if (addend > 0x7e || addend < 0)
846         return bfd_reloc_overflow;
847       
848       if (addend & 1)
849         return bfd_reloc_dangerous;
850       
851       insn &= 0xff80;
852       insn |= (addend >> 1);
853       break;
854 /* end-sanitize-v850e */
855     }
856
857   bfd_put_16 (abfd, insn, address);
858   return bfd_reloc_ok;
859 }
860
861 \f
862 /* Insert the addend into the instruction.  */
863 static bfd_reloc_status_type
864 v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
865      bfd *       abfd;
866      arelent *   reloc;
867      asymbol *   symbol;
868      PTR         data;
869      asection *  isection;
870      bfd *       obfd;
871      char **     err;
872 {
873   long relocation;
874   long insn;
875
876   
877   /* If there is an output BFD,
878      and the symbol is not a section name (which is only defined at final link time),
879      and either we are not putting the addend into the instruction
880          or the addend is zero, so there is nothing to add into the instruction
881      then just fixup the address and return.  */
882   if (obfd != (bfd *) NULL
883       && (symbol->flags & BSF_SECTION_SYM) == 0
884       && (! reloc->howto->partial_inplace
885           || reloc->addend == 0))
886     {
887       reloc->address += isection->output_offset;
888       return bfd_reloc_ok;
889     }
890 #if 0  
891   else if (obfd != NULL)
892     {
893       return bfd_reloc_continue;
894     }
895 #endif
896   
897   /* Catch relocs involving undefined symbols.  */
898   if (bfd_is_und_section (symbol->section)
899       && (symbol->flags & BSF_WEAK) == 0
900       && obfd == NULL)
901     return bfd_reloc_undefined;
902
903   /* We handle final linking of some relocs ourselves.  */
904
905   /* Is the address of the relocation really within the section?  */
906   if (reloc->address > isection->_cooked_size)
907     return bfd_reloc_outofrange;
908   
909   /* Work out which section the relocation is targetted at and the
910      initial relocation command value.  */
911   
912   /* Get symbol value.  (Common symbols are special.)  */
913   if (bfd_is_com_section (symbol->section))
914     relocation = 0;
915   else
916     relocation = symbol->value;
917   
918   /* Convert input-section-relative symbol value to absolute + addend.  */
919   relocation += symbol->section->output_section->vma;
920   relocation += symbol->section->output_offset;
921   relocation += reloc->addend;
922   
923   if (reloc->howto->pc_relative == true)
924     {
925       /* Here the variable relocation holds the final address of the
926          symbol we are relocating against, plus any addend.  */
927       relocation -= isection->output_section->vma + isection->output_offset;
928       
929       /* Deal with pcrel_offset */
930       relocation -= reloc->address;
931     }
932
933   /* I've got no clue... */
934   reloc->addend = 0;    
935
936   return v850_elf_store_addend_in_insn (abfd, reloc->howto->type, relocation,
937                                         (bfd_byte *) data + reloc->address, true);
938 }
939
940 \f
941 /*ARGSUSED*/
942 static boolean
943 v850_elf_is_local_label_name (abfd, name)
944      bfd *         abfd;
945      const char *  name;
946 {
947   return (   (name[0] == '.' && (name[1] == 'L' || name[1] == '.'))
948           || (name[0] == '_' &&  name[1] == '.' && name[2] == 'L' && name[3] == '_'));
949 }
950
951 \f
952 /* Perform a relocation as part of a final link.  */
953 static bfd_reloc_status_type
954 v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
955                                     input_section, contents, offset, value,
956                                     addend, info, sym_sec, is_local)
957      reloc_howto_type *      howto;
958      bfd *                   input_bfd;
959      bfd *                   output_bfd;
960      asection *              input_section;
961      bfd_byte *              contents;
962      bfd_vma                 offset;
963      bfd_vma                 value;
964      bfd_vma                 addend;
965      struct bfd_link_info *  info;
966      asection *              sym_sec;
967      int                     is_local;
968 {
969   unsigned long  insn;
970   unsigned long  r_type   = howto->type;
971   bfd_byte *     hit_data = contents + offset;
972
973   switch (r_type)
974     {
975     case R_V850_9_PCREL:
976       value -= (input_section->output_section->vma
977                 + input_section->output_offset);
978       value -= offset;
979
980       if ((long)value > 0xff || (long)value < -0x100)
981         return bfd_reloc_overflow;
982
983       if ((value % 2) != 0)
984         return bfd_reloc_dangerous;
985
986       insn = bfd_get_16 (input_bfd, hit_data);
987       insn &= 0x078f;
988       insn |= ((value & 0x1f0) << 7) | ((value & 0x0e) << 3);
989       bfd_put_16 (input_bfd, insn, hit_data);
990       return bfd_reloc_ok;
991     
992     case R_V850_22_PCREL:
993       value -= (input_section->output_section->vma
994                 + input_section->output_offset
995                 + offset);
996
997       value = SEXT24 (value);  /* Only the bottom 24 bits of the PC are valid */
998       
999       if ((long)value > 0x1fffff || (long)value < -0x200000)
1000         return bfd_reloc_overflow;
1001
1002       if ((value % 2) != 0)
1003         return bfd_reloc_dangerous;
1004
1005       insn = bfd_get_32 (input_bfd, hit_data);
1006       insn &= 0x1ffc0;
1007       insn |= (((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16));
1008       bfd_put_32 (input_bfd, insn, hit_data);
1009       return bfd_reloc_ok;
1010       
1011     case R_V850_HI16_S:
1012       value += (bfd_get_16 (input_bfd, hit_data) << 16);
1013       value = (value >> 16) + ((value & 0x8000) != 0);
1014
1015       if ((long)value > 0x7fff || (long)value < -0x8000)
1016         {
1017           /* This relocation cannot overflow. */
1018           
1019           value = 0;
1020         }
1021
1022       bfd_put_16 (input_bfd, value, hit_data);
1023       return bfd_reloc_ok;
1024
1025     case R_V850_HI16:
1026       value += (bfd_get_16 (input_bfd, hit_data) << 16);
1027       value >>= 16;
1028
1029       bfd_put_16 (input_bfd, value, hit_data);
1030       return bfd_reloc_ok;
1031
1032     case R_V850_LO16:
1033       value += (short)bfd_get_16 (input_bfd, hit_data);
1034       value &= 0xffff;
1035
1036       bfd_put_16 (input_bfd, value, hit_data);
1037       return bfd_reloc_ok;
1038
1039     case R_V850_16:
1040       value += (short) bfd_get_16 (input_bfd, hit_data);
1041
1042       if ((long) value > 0x7fff || (long) value < -0x8000)
1043         return bfd_reloc_overflow;
1044
1045       bfd_put_16 (input_bfd, value, hit_data);
1046       return bfd_reloc_ok;
1047
1048     case R_V850_ZDA_16_16_OFFSET:
1049       if (sym_sec == NULL)
1050         return bfd_reloc_undefined;
1051       
1052       value -= sym_sec->output_section->vma;
1053       value += (short) bfd_get_16 (input_bfd, hit_data);
1054
1055       if ((long) value > 0x7fff || (long) value < -0x8000)
1056         return bfd_reloc_overflow;
1057
1058       bfd_put_16 (input_bfd, value, hit_data);
1059       return bfd_reloc_ok;
1060
1061     case R_V850_ZDA_15_16_OFFSET:       
1062       if (sym_sec == NULL)
1063         return bfd_reloc_undefined;
1064           
1065       insn = bfd_get_16 (input_bfd, hit_data);
1066
1067       value -= sym_sec->output_section->vma;
1068       value += ((insn & 0xfffe) << 1);
1069       
1070       if ((long) value > 0x7ffe || (long) value < -0x8000)
1071         return bfd_reloc_overflow;
1072
1073       value &= ~1;
1074       value |= (insn & 1);
1075       
1076       bfd_put_16 (input_bfd, value, hit_data);
1077       return bfd_reloc_ok;
1078
1079     case R_V850_32:
1080       value += bfd_get_32 (input_bfd, hit_data);
1081       bfd_put_32 (input_bfd, value, hit_data);
1082       return bfd_reloc_ok;
1083
1084     case R_V850_8:
1085       value += (char)bfd_get_8 (input_bfd, hit_data);
1086
1087       if ((long)value > 0x7f || (long)value < -0x80)
1088         return bfd_reloc_overflow;
1089
1090       bfd_put_8 (input_bfd, value, hit_data);
1091       return bfd_reloc_ok;
1092
1093     case R_V850_SDA_16_16_OFFSET:
1094       if (sym_sec == NULL)
1095         return bfd_reloc_undefined;
1096           
1097       {
1098         unsigned long                gp;
1099         struct bfd_link_hash_entry * h;
1100
1101         /* Get the value of __gp.  */
1102         h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
1103         if (h == (struct bfd_link_hash_entry *) NULL
1104             || h->type != bfd_link_hash_defined)
1105           return bfd_reloc_other;
1106
1107         gp = (h->u.def.value
1108               + h->u.def.section->output_section->vma
1109               + h->u.def.section->output_offset);
1110
1111         value -= sym_sec->output_section->vma;
1112         value -= (gp - sym_sec->output_section->vma);
1113         value += (short) bfd_get_16 (input_bfd, hit_data);
1114
1115         if ((long)value > 0x7fff || (long)value < -0x8000)
1116           return bfd_reloc_overflow;
1117
1118         bfd_put_16 (input_bfd, value, hit_data);
1119         return bfd_reloc_ok;
1120       }
1121
1122     case R_V850_SDA_15_16_OFFSET:
1123       if (sym_sec == NULL)
1124         return bfd_reloc_undefined;
1125           
1126       {
1127         unsigned long                gp;
1128         struct bfd_link_hash_entry * h;
1129
1130         /* Get the value of __gp.  */
1131         h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
1132         if (h == (struct bfd_link_hash_entry *) NULL
1133             || h->type != bfd_link_hash_defined)
1134           return bfd_reloc_other;
1135
1136         gp = (h->u.def.value
1137               + h->u.def.section->output_section->vma
1138               + h->u.def.section->output_offset);
1139         
1140         value -= sym_sec->output_section->vma;
1141         value -= (gp - sym_sec->output_section->vma);
1142
1143         insn = bfd_get_16 (input_bfd, hit_data);
1144         
1145         value += ((insn & 0xfffe) << 1);
1146         
1147         if ((long)value > 0x7ffe || (long)value < -0x8000)
1148           return bfd_reloc_overflow;
1149
1150         value &= ~1;
1151         value |= (insn & 1);
1152         
1153         bfd_put_16 (input_bfd, value, hit_data);
1154         return bfd_reloc_ok;
1155       }
1156
1157     case R_V850_TDA_6_8_OFFSET:
1158       {
1159         unsigned long                ep;
1160         struct bfd_link_hash_entry * h;
1161         
1162         insn = bfd_get_16 (input_bfd, hit_data);
1163
1164         /* Get the value of __ep.  */
1165         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1166         if (h == (struct bfd_link_hash_entry *) NULL
1167             || h->type != bfd_link_hash_defined)
1168           return bfd_reloc_continue;  /* Actually this indicates that __ep could not be found. */
1169
1170         ep = (h->u.def.value
1171               + h->u.def.section->output_section->vma
1172               + h->u.def.section->output_offset);
1173
1174         value -= ep;
1175         value += ((insn & 0x7e) << 1);
1176         
1177         if ((long) value > 0xfc || (long) value < 0)
1178           return bfd_reloc_overflow;
1179         
1180         if ((value % 2) != 0)
1181           return bfd_reloc_dangerous;
1182         
1183         insn &= 0xff81;
1184         insn |= (value >> 1);
1185
1186         bfd_put_16 (input_bfd, insn, hit_data);
1187         return bfd_reloc_ok;
1188       }
1189     
1190     case R_V850_TDA_7_8_OFFSET:
1191       {
1192         unsigned long                ep;
1193         struct bfd_link_hash_entry * h;
1194         
1195         insn = bfd_get_16 (input_bfd, hit_data);
1196
1197         /* Get the value of __ep.  */
1198         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1199         if (h == (struct bfd_link_hash_entry *) NULL
1200             || h->type != bfd_link_hash_defined)
1201           return bfd_reloc_continue;    /* Actually this indicates that __ep could not be found. */
1202
1203         ep = (h->u.def.value
1204               + h->u.def.section->output_section->vma
1205               + h->u.def.section->output_offset);
1206         
1207         value -= ep;
1208         value += ((insn & 0x7f) << 1);
1209         
1210         if ((long) value > 0xfe || (long) value < 0)
1211           return bfd_reloc_overflow;
1212         
1213         insn &= 0xff80;
1214         insn |= (value >> 1);
1215         
1216         bfd_put_16 (input_bfd, insn, hit_data);
1217         return bfd_reloc_ok;
1218       }
1219     
1220     case R_V850_TDA_7_7_OFFSET:
1221       {
1222         unsigned long                ep;
1223         struct bfd_link_hash_entry * h;
1224         
1225         insn = bfd_get_16 (input_bfd, hit_data);
1226
1227         /* Get the value of __ep.  */
1228         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1229         if (h == (struct bfd_link_hash_entry *) NULL
1230             || h->type != bfd_link_hash_defined)
1231           return bfd_reloc_continue;  /* Actually this indicates that __ep could not be found. */
1232
1233         ep = (h->u.def.value
1234               + h->u.def.section->output_section->vma
1235               + h->u.def.section->output_offset);
1236         value -= ep;
1237         
1238         value += insn & 0x7f;
1239         
1240         if ((long) value > 0x7f || (long) value < 0)
1241           return bfd_reloc_overflow;
1242         
1243         insn &= 0xff80;
1244         insn |= value;
1245         bfd_put_16 (input_bfd, insn, hit_data);
1246         return bfd_reloc_ok;
1247       }
1248     
1249     case R_V850_TDA_16_16_OFFSET:
1250       {
1251         unsigned long                ep;
1252         struct bfd_link_hash_entry * h;
1253
1254         /* Get the value of __ep.  */
1255         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1256         if (h == (struct bfd_link_hash_entry *) NULL
1257             || h->type != bfd_link_hash_defined)
1258           return bfd_reloc_other;
1259
1260         ep = (h->u.def.value
1261               + h->u.def.section->output_section->vma
1262               + h->u.def.section->output_offset);
1263         value -= ep;
1264         
1265         value += (short) bfd_get_16 (input_bfd, hit_data);
1266
1267         if ((long)value > 0x7fff || (long)value < -0x8000)
1268           return bfd_reloc_overflow;
1269
1270         bfd_put_16 (input_bfd, value, hit_data);
1271         return bfd_reloc_ok;
1272       }
1273
1274 /* start-sanitize-v850e */
1275     case R_V850_TDA_4_5_OFFSET:
1276       {
1277         unsigned long                ep;
1278         struct bfd_link_hash_entry * h;
1279         
1280         /* Get the value of __ep.  */
1281         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1282         if (h == (struct bfd_link_hash_entry *) NULL
1283             || h->type != bfd_link_hash_defined)
1284           return bfd_reloc_continue;  /* Actually this indicates that __ep could not be found. */
1285
1286         ep = (h->u.def.value
1287               + h->u.def.section->output_section->vma
1288               + h->u.def.section->output_offset);
1289         value -= ep;
1290         
1291         insn = bfd_get_16 (input_bfd, hit_data);
1292
1293         value += ((insn & 0xf) << 1);
1294         
1295         if ((long) value > 0x1e || (long) value < 0)
1296           return bfd_reloc_overflow;
1297         
1298         insn &= 0xfff0;
1299         insn |= (value >> 1);
1300         bfd_put_16 (input_bfd, insn, hit_data);
1301         return bfd_reloc_ok;
1302       }
1303     
1304     case R_V850_TDA_4_4_OFFSET:
1305       {
1306         unsigned long                ep;
1307         struct bfd_link_hash_entry * h;
1308         
1309         /* Get the value of __ep.  */
1310         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1311         if (h == (struct bfd_link_hash_entry *) NULL
1312             || h->type != bfd_link_hash_defined)
1313           return bfd_reloc_continue;  /* Actually this indicates that __ep could not be found. */
1314
1315         ep = (h->u.def.value
1316               + h->u.def.section->output_section->vma
1317               + h->u.def.section->output_offset);
1318         value -= ep;
1319         
1320         insn = bfd_get_16 (input_bfd, hit_data);
1321
1322         value += insn & 0xf;
1323         
1324         if ((long) value > 0xf || (long) value < 0)
1325           return bfd_reloc_overflow;
1326         
1327         insn &= 0xfff0;
1328         insn |= value;
1329         bfd_put_16 (input_bfd, insn, hit_data);
1330         return bfd_reloc_ok;
1331       }
1332     
1333     case R_V850_SDA_16_16_SPLIT_OFFSET:
1334       if (sym_sec == NULL)
1335         return bfd_reloc_undefined;
1336           
1337       {
1338         unsigned long                gp;
1339         struct bfd_link_hash_entry * h;
1340
1341         /* Get the value of __gp.  */
1342         h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
1343         if (h == (struct bfd_link_hash_entry *) NULL
1344             || h->type != bfd_link_hash_defined)
1345           return bfd_reloc_other;
1346
1347         gp = (h->u.def.value
1348               + h->u.def.section->output_section->vma
1349               + h->u.def.section->output_offset);
1350         
1351         value -= sym_sec->output_section->vma;
1352         value -= (gp - sym_sec->output_section->vma);
1353
1354         insn = bfd_get_32 (input_bfd, hit_data);
1355         
1356         value += ((insn & 0xfffe0000) >> 16);
1357         value += ((insn & 0x20) >> 5);
1358           
1359         if ((long)value > 0x7fff || (long)value < -0x8000)
1360           return bfd_reloc_overflow;
1361
1362         insn &= 0x0001ffdf;
1363         insn |= (value & 1) << 5;
1364         insn |= (value & ~1) << 16;
1365         
1366         bfd_put_32 (input_bfd, insn, hit_data);
1367         return bfd_reloc_ok;
1368       }
1369
1370     case R_V850_ZDA_16_16_SPLIT_OFFSET:
1371       if (sym_sec == NULL)
1372         return bfd_reloc_undefined;
1373           
1374       insn = bfd_get_32 (input_bfd, hit_data);
1375         
1376       value -= sym_sec->output_section->vma;
1377       value += ((insn & 0xfffe0000) >> 16);
1378       value += ((insn & 0x20) >> 5);
1379           
1380       if ((long)value > 0x7fff || (long)value < -0x8000)
1381         return bfd_reloc_overflow;
1382       
1383       insn &= 0x0001ffdf;
1384       insn |= (value & 1) << 5;
1385       insn |= (value & ~1) << 16;
1386       
1387       bfd_put_32 (input_bfd, insn, hit_data);
1388       return bfd_reloc_ok;
1389
1390     case R_V850_CALLT_6_7_OFFSET:
1391       {
1392         unsigned long                ctbp;
1393         struct bfd_link_hash_entry * h;
1394         
1395         /* Get the value of __ctbp.  */
1396         h = bfd_link_hash_lookup (info->hash, "__ctbp", false, false, true);
1397         if (h == (struct bfd_link_hash_entry *) NULL
1398             || h->type != bfd_link_hash_defined)
1399           return (bfd_reloc_dangerous + 1);  /* Actually this indicates that __ctbp could not be found. */
1400
1401         ctbp = (h->u.def.value
1402               + h->u.def.section->output_section->vma
1403               + h->u.def.section->output_offset);
1404         value -= ctbp;
1405         
1406         insn = bfd_get_16 (input_bfd, hit_data);
1407
1408         value += ((insn & 0x3f) << 1);
1409         
1410         if ((long) value > 0x7e || (long) value < 0)
1411           return bfd_reloc_overflow;
1412         
1413         insn &= 0xff80;
1414         insn |= (value >> 1);
1415         bfd_put_16 (input_bfd, insn, hit_data);
1416         return bfd_reloc_ok;
1417       }
1418     
1419     case R_V850_CALLT_16_16_OFFSET:
1420       if (sym_sec == NULL)
1421         return bfd_reloc_undefined;
1422           
1423       {
1424         unsigned long                ctbp;
1425         struct bfd_link_hash_entry * h;
1426
1427         /* Get the value of __ctbp.  */
1428         h = bfd_link_hash_lookup (info->hash, "__ctbp", false, false, true);
1429         if (h == (struct bfd_link_hash_entry *) NULL
1430             || h->type != bfd_link_hash_defined)
1431           return (bfd_reloc_dangerous + 1);
1432
1433         ctbp = (h->u.def.value
1434               + h->u.def.section->output_section->vma
1435               + h->u.def.section->output_offset);
1436
1437         value -= sym_sec->output_section->vma;
1438         value -= (ctbp - sym_sec->output_section->vma);
1439         value += (short) bfd_get_16 (input_bfd, hit_data);
1440
1441         if ((long) value > 0xffff || (long) value < 0)
1442           return bfd_reloc_overflow;
1443
1444         bfd_put_16 (input_bfd, value, hit_data);
1445         return bfd_reloc_ok;
1446       }
1447
1448 /* end-sanitize-v850e */
1449     
1450     case R_V850_NONE:
1451       return bfd_reloc_ok;
1452
1453     default:
1454       return bfd_reloc_notsupported;
1455     }
1456 }
1457
1458 \f
1459 /* Relocate an V850 ELF section.  */
1460 static boolean
1461 v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
1462                            contents, relocs, local_syms, local_sections)
1463      bfd *                  output_bfd;
1464      struct bfd_link_info * info;
1465      bfd *                  input_bfd;
1466      asection *             input_section;
1467      bfd_byte *             contents;
1468      Elf_Internal_Rela *    relocs;
1469      Elf_Internal_Sym *     local_syms;
1470      asection **            local_sections;
1471 {
1472   Elf_Internal_Shdr *           symtab_hdr;
1473   struct elf_link_hash_entry ** sym_hashes;
1474   Elf_Internal_Rela *           rel;
1475   Elf_Internal_Rela *           relend;
1476
1477   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
1478   sym_hashes = elf_sym_hashes (input_bfd);
1479
1480   rel    = relocs;
1481   relend = relocs + input_section->reloc_count;
1482   for (; rel < relend; rel++)
1483     {
1484       int                          r_type;
1485       reloc_howto_type *           howto;
1486       unsigned long                r_symndx;
1487       Elf_Internal_Sym *           sym;
1488       asection *                   sec;
1489       struct elf_link_hash_entry * h;
1490       bfd_vma                      relocation;
1491       bfd_reloc_status_type        r;
1492
1493       r_symndx = ELF32_R_SYM (rel->r_info);
1494       r_type   = ELF32_R_TYPE (rel->r_info);
1495       howto    = v850_elf_howto_table + r_type;
1496
1497       if (info->relocateable)
1498         {
1499           /* This is a relocateable link.  We don't have to change
1500              anything, unless the reloc is against a section symbol,
1501              in which case we have to adjust according to where the
1502              section symbol winds up in the output section.  */
1503           if (r_symndx < symtab_hdr->sh_info)
1504             {
1505               sym = local_syms + r_symndx;
1506               if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
1507                 {
1508                   sec = local_sections[r_symndx];
1509 #ifdef USE_REL
1510                   /* The Elf_Internal_Rel structure does not have space for the
1511                      modified addend value, so we store it in the instruction
1512                      instead. */
1513
1514                   if (sec->output_offset + sym->st_value != 0)
1515                     {
1516                       if (v850_elf_store_addend_in_insn (input_bfd, r_type,
1517                                                          sec->output_offset +
1518                                                          sym->st_value,
1519                                                          contents + rel->r_offset,
1520                                                          false)
1521                           != bfd_reloc_ok)
1522                         {
1523                           info->callbacks->warning
1524                             (info,
1525                              "Unable to handle relocation during incremental link",
1526                              NULL, input_bfd, input_section, rel->r_offset);
1527                         }
1528                     }
1529 #else
1530                   rel->r_addend += sec->output_offset + sym->st_value;
1531 #endif
1532                 }
1533             }
1534
1535           continue;
1536         }
1537
1538       /* This is a final link.  */
1539       h = NULL;
1540       sym = NULL;
1541       sec = NULL;
1542       if (r_symndx < symtab_hdr->sh_info)
1543         {
1544           sym = local_syms + r_symndx;
1545           sec = local_sections[r_symndx];
1546           relocation = (sec->output_section->vma
1547                         + sec->output_offset
1548                         + sym->st_value);
1549 #if 0
1550           {
1551             char * name;
1552             name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name);
1553             name = (name == NULL) ? "<none>" : name;
1554 fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x rel %x\n", sec->name, name, sym->st_name,
1555          sec->output_section->vma, sec->output_offset, sym->st_value, rel->r_addend, rel);
1556           }
1557 #endif
1558         }
1559       else
1560         {
1561           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
1562           
1563           while (h->root.type == bfd_link_hash_indirect
1564                  || h->root.type == bfd_link_hash_warning)
1565             h = (struct elf_link_hash_entry *) h->root.u.i.link;
1566           
1567           if (h->root.type == bfd_link_hash_defined
1568               || h->root.type == bfd_link_hash_defweak)
1569             {
1570               sec = h->root.u.def.section;
1571               relocation = (h->root.u.def.value
1572                             + sec->output_section->vma
1573                             + sec->output_offset);
1574 #if 0
1575 fprintf (stderr, "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
1576          sec->name, h->root.root.string, h->root.u.def.value, sec->output_section->vma, sec->output_offset, relocation);
1577 #endif
1578             }
1579           else if (h->root.type == bfd_link_hash_undefweak)
1580             {
1581 #if 0
1582 fprintf (stderr, "undefined: sec: %s, name: %s\n",
1583          sec->name, h->root.root.string);
1584 #endif
1585               relocation = 0;
1586             }
1587           else
1588             {
1589               if (! ((*info->callbacks->undefined_symbol)
1590                      (info, h->root.root.string, input_bfd,
1591                       input_section, rel->r_offset)))
1592                 return false;
1593 #if 0
1594 fprintf (stderr, "unknown: name: %s\n", h->root.root.string);
1595 #endif
1596               relocation = 0;
1597             }
1598         }
1599
1600       /* FIXME: We should use the addend, but the COFF relocations
1601          don't.  */
1602       r = v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
1603                                         input_section,
1604                                         contents, rel->r_offset,
1605                                         relocation, rel->r_addend,
1606                                         info, sec, h == NULL);
1607
1608       if (r != bfd_reloc_ok)
1609         {
1610           const char * name;
1611           const char * msg = (const char *)0;
1612
1613           if (h != NULL)
1614             name = h->root.root.string;
1615           else
1616             {
1617               name = (bfd_elf_string_from_elf_section
1618                       (input_bfd, symtab_hdr->sh_link, sym->st_name));
1619               if (name == NULL || *name == '\0')
1620                 name = bfd_section_name (input_bfd, sec);
1621             }
1622
1623           switch (r)
1624             {
1625             case bfd_reloc_overflow:
1626               if (! ((*info->callbacks->reloc_overflow)
1627                      (info, name, howto->name, (bfd_vma) 0,
1628                       input_bfd, input_section, rel->r_offset)))
1629                 return false;
1630               break;
1631
1632             case bfd_reloc_undefined:
1633               if (! ((*info->callbacks->undefined_symbol)
1634                      (info, name, input_bfd, input_section,
1635                       rel->r_offset)))
1636                 return false;
1637               break;
1638
1639             case bfd_reloc_outofrange:
1640               msg = "internal error: out of range error";
1641               goto common_error;
1642
1643             case bfd_reloc_notsupported:
1644               msg = "internal error: unsupported relocation error";
1645               goto common_error;
1646
1647             case bfd_reloc_dangerous:
1648               msg = "internal error: dangerous relocation";
1649               goto common_error;
1650
1651             case bfd_reloc_other:
1652               msg = "could not locate special linker symbol __gp";
1653               goto common_error;
1654
1655             case bfd_reloc_continue:
1656               msg = "could not locate special linker symbol __ep";
1657               goto common_error;
1658
1659             case (bfd_reloc_dangerous + 1):
1660               msg = "could not locate special linker symbol __ctbp";
1661               goto common_error;
1662               
1663             default:
1664               msg = "internal error: unknown error";
1665               /* fall through */
1666
1667             common_error:
1668               if (!((*info->callbacks->warning)
1669                     (info, msg, name, input_bfd, input_section,
1670                      rel->r_offset)))
1671                 return false;
1672               break;
1673             }
1674         }
1675     }
1676
1677   return true;
1678 }
1679
1680 /* Set the right machine number.  */
1681 static boolean
1682 v850_elf_object_p (abfd)
1683      bfd *abfd;
1684 {
1685   switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
1686     {
1687     default:
1688     case E_V850_ARCH:   (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, 0); break;
1689 /* start-sanitize-v850e */
1690     case E_V850E_ARCH:  (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e); break;
1691     case E_V850EQ_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850eq); break;
1692 /* end-sanitize-v850e */
1693     }
1694 }
1695
1696 /* Store the machine number in the flags field.  */
1697 void
1698 v850_elf_final_write_processing (abfd, linker)
1699      bfd *   abfd;
1700      boolean linker;
1701 {
1702   unsigned long val;
1703
1704   switch (bfd_get_mach (abfd))
1705     {
1706     default:
1707     case 0: val = E_V850_ARCH; break;
1708 /* start-sanitize-v850e */
1709     case bfd_mach_v850e:  val = E_V850E_ARCH; break;
1710     case bfd_mach_v850eq: val = E_V850EQ_ARCH;  break;
1711 /* end-sanitize-v850e */
1712     }
1713
1714   elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH;
1715   elf_elfheader (abfd)->e_flags |= val;
1716 }
1717
1718 /* Function to keep V850 specific file flags. */
1719 boolean
1720 v850_elf_set_private_flags (abfd, flags)
1721      bfd *    abfd;
1722      flagword flags;
1723 {
1724   BFD_ASSERT (!elf_flags_init (abfd)
1725               || elf_elfheader (abfd)->e_flags == flags);
1726
1727   elf_elfheader (abfd)->e_flags = flags;
1728   elf_flags_init (abfd) = true;
1729   return true;
1730 }
1731
1732 /* Copy backend specific data from one object module to another */
1733 boolean
1734 v850_elf_copy_private_bfd_data (ibfd, obfd)
1735      bfd * ibfd;
1736      bfd * obfd;
1737 {
1738   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1739       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1740     return true;
1741
1742   BFD_ASSERT (!elf_flags_init (obfd)
1743               || (elf_elfheader (obfd)->e_flags
1744                   == elf_elfheader (ibfd)->e_flags));
1745
1746   elf_gp (obfd) = elf_gp (ibfd);
1747   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
1748   elf_flags_init (obfd) = true;
1749   return true;
1750 }
1751
1752 /* Merge backend specific data from an object file to the output
1753    object file when linking.  */
1754 boolean
1755 v850_elf_merge_private_bfd_data (ibfd, obfd)
1756      bfd * ibfd;
1757      bfd * obfd;
1758 {
1759   flagword old_flags;
1760   flagword new_flags;
1761
1762   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1763       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1764     return true;
1765
1766   new_flags = elf_elfheader (ibfd)->e_flags;
1767   old_flags = elf_elfheader (obfd)->e_flags;
1768
1769   if (! elf_flags_init (obfd))
1770     {
1771       elf_flags_init (obfd) = true;
1772       elf_elfheader (obfd)->e_flags = new_flags;
1773
1774       if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
1775           && bfd_get_arch_info (obfd)->the_default)
1776         {
1777           return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
1778         }
1779
1780       return true;
1781     }
1782
1783   /* Check flag compatibility.  */
1784
1785   if (new_flags == old_flags)
1786     return true;
1787
1788   if ((new_flags & EF_V850_ARCH) != (old_flags & EF_V850_ARCH))
1789     {
1790       _bfd_error_handler ("%s: Architecture mismatch with previous modules",
1791              bfd_get_filename (ibfd));
1792 #if 0
1793       bfd_set_error (bfd_error_bad_value);
1794       return false;
1795 #else
1796       return true;
1797 #endif
1798     }
1799
1800   return true;
1801 }
1802 /* Display the flags field */
1803
1804 static boolean
1805 v850_elf_print_private_bfd_data (abfd, ptr)
1806      bfd *   abfd;
1807      PTR     ptr;
1808 {
1809   FILE * file = (FILE *) ptr;
1810   
1811   BFD_ASSERT (abfd != NULL && ptr != NULL)
1812   
1813   fprintf (file, "private flags = %x", elf_elfheader (abfd)->e_flags);
1814   
1815   switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
1816     {
1817     default:
1818     case E_V850_ARCH: fprintf (file, ": v850 architecture"); break;
1819 /* start-sanitize-v850e */
1820     case E_V850E_ARCH:  fprintf (file, ": v850e architecture"); break;
1821     case E_V850EQ_ARCH: fprintf (file, ": v850eq architecture"); break;
1822 /* end-sanitize-v850e */
1823     }
1824   
1825   fputc ('\n', file);
1826   
1827   return true;
1828 }
1829
1830 /* V850 ELF uses four common sections.  One is the usual one, and the
1831    others are for (small) objects in one of the special data areas:
1832    small, tiny and zero.  All the objects are kept together, and then
1833    referenced via the gp register, the ep register or the r0 register
1834    respectively, which yields smaller, faster assembler code.  This
1835    approach is copied from elf32-mips.c.  */
1836
1837 static asection  v850_elf_scom_section;
1838 static asymbol   v850_elf_scom_symbol;
1839 static asymbol * v850_elf_scom_symbol_ptr;
1840 static asection  v850_elf_tcom_section;
1841 static asymbol   v850_elf_tcom_symbol;
1842 static asymbol * v850_elf_tcom_symbol_ptr;
1843 static asection  v850_elf_zcom_section;
1844 static asymbol   v850_elf_zcom_symbol;
1845 static asymbol * v850_elf_zcom_symbol_ptr;
1846
1847
1848 /* Given a BFD section, try to locate the corresponding ELF section
1849    index.  */
1850
1851 static boolean
1852 v850_elf_section_from_bfd_section (abfd, hdr, sec, retval)
1853      bfd *                 abfd;
1854      Elf32_Internal_Shdr * hdr;
1855      asection *            sec;
1856      int *                 retval;
1857 {
1858   if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0)
1859     {
1860       *retval = SHN_V850_SCOMMON;
1861       return true;
1862     }
1863   if (strcmp (bfd_get_section_name (abfd, sec), ".tcommon") == 0)
1864     {
1865       *retval = SHN_V850_TCOMMON;
1866       return true;
1867     }
1868   if (strcmp (bfd_get_section_name (abfd, sec), ".zcommon") == 0)
1869     {
1870       *retval = SHN_V850_ZCOMMON;
1871       return true;
1872     }
1873   return false;
1874 }
1875
1876 /* Handle the special V850 section numbers that a symbol may use.  */
1877
1878 static void
1879 v850_elf_symbol_processing (abfd, asym)
1880      bfd *     abfd;
1881      asymbol * asym;
1882 {
1883   elf_symbol_type * elfsym = (elf_symbol_type *) asym;
1884
1885   switch (elfsym->internal_elf_sym.st_shndx)
1886     {
1887     case SHN_V850_SCOMMON:
1888       if (v850_elf_scom_section.name == NULL)
1889         {
1890           /* Initialize the small common section.  */
1891           v850_elf_scom_section.name           = ".scommon";
1892           v850_elf_scom_section.flags          = SEC_IS_COMMON | SEC_ALLOC | SEC_DATA;
1893           v850_elf_scom_section.output_section = & v850_elf_scom_section;
1894           v850_elf_scom_section.symbol         = & v850_elf_scom_symbol;
1895           v850_elf_scom_section.symbol_ptr_ptr = & v850_elf_scom_symbol_ptr;
1896           v850_elf_scom_symbol.name            = ".scommon";
1897           v850_elf_scom_symbol.flags           = BSF_SECTION_SYM;
1898           v850_elf_scom_symbol.section         = & v850_elf_scom_section;
1899           v850_elf_scom_symbol_ptr             = & v850_elf_scom_symbol;
1900         }
1901       asym->section = & v850_elf_scom_section;
1902       asym->value = elfsym->internal_elf_sym.st_size;
1903       break;
1904       
1905     case SHN_V850_TCOMMON:
1906       if (v850_elf_tcom_section.name == NULL)
1907         {
1908           /* Initialize the tcommon section.  */
1909           v850_elf_tcom_section.name           = ".tcommon";
1910           v850_elf_tcom_section.flags          = SEC_IS_COMMON;
1911           v850_elf_tcom_section.output_section = & v850_elf_tcom_section;
1912           v850_elf_tcom_section.symbol         = & v850_elf_tcom_symbol;
1913           v850_elf_tcom_section.symbol_ptr_ptr = & v850_elf_tcom_symbol_ptr;
1914           v850_elf_tcom_symbol.name            = ".tcommon";
1915           v850_elf_tcom_symbol.flags           = BSF_SECTION_SYM;
1916           v850_elf_tcom_symbol.section         = & v850_elf_tcom_section;
1917           v850_elf_tcom_symbol_ptr             = & v850_elf_tcom_symbol;
1918         }
1919       asym->section = & v850_elf_tcom_section;
1920       asym->value = elfsym->internal_elf_sym.st_size;
1921       break;
1922
1923     case SHN_V850_ZCOMMON:
1924       if (v850_elf_zcom_section.name == NULL)
1925         {
1926           /* Initialize the zcommon section.  */
1927           v850_elf_zcom_section.name           = ".zcommon";
1928           v850_elf_zcom_section.flags          = SEC_IS_COMMON;
1929           v850_elf_zcom_section.output_section = & v850_elf_zcom_section;
1930           v850_elf_zcom_section.symbol         = & v850_elf_zcom_symbol;
1931           v850_elf_zcom_section.symbol_ptr_ptr = & v850_elf_zcom_symbol_ptr;
1932           v850_elf_zcom_symbol.name            = ".zcommon";
1933           v850_elf_zcom_symbol.flags           = BSF_SECTION_SYM;
1934           v850_elf_zcom_symbol.section         = & v850_elf_zcom_section;
1935           v850_elf_zcom_symbol_ptr             = & v850_elf_zcom_symbol;
1936         }
1937       asym->section = & v850_elf_zcom_section;
1938       asym->value = elfsym->internal_elf_sym.st_size;
1939       break;
1940     }
1941 }
1942
1943 /* Hook called by the linker routine which adds symbols from an object
1944    file.  We must handle the special MIPS section numbers here.  */
1945
1946 /*ARGSUSED*/
1947 static boolean
1948 v850_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
1949      bfd *                    abfd;
1950      struct bfd_link_info *   info;
1951      const Elf_Internal_Sym * sym;
1952      const char **            namep;
1953      flagword *               flagsp;
1954      asection **              secp;
1955      bfd_vma *                valp;
1956 {
1957   switch (sym->st_shndx)
1958     {
1959     case SHN_V850_SCOMMON:
1960       *secp = bfd_make_section_old_way (abfd, ".scommon");
1961       (*secp)->flags |= SEC_IS_COMMON;
1962       *valp = sym->st_size;
1963       break;
1964       
1965     case SHN_V850_TCOMMON:
1966       *secp = bfd_make_section_old_way (abfd, ".tcommon");
1967       (*secp)->flags |= SEC_IS_COMMON;
1968       *valp = sym->st_size;
1969       break;
1970       
1971     case SHN_V850_ZCOMMON:
1972       *secp = bfd_make_section_old_way (abfd, ".zcommon");
1973       (*secp)->flags |= SEC_IS_COMMON;
1974       *valp = sym->st_size;
1975       break;
1976     }
1977
1978   return true;
1979 }
1980
1981 /*ARGSIGNORED*/
1982 static boolean
1983 v850_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec)
1984      bfd *                  abfd;
1985      struct bfd_link_info * info;
1986      const char *           name;
1987      Elf_Internal_Sym *     sym;
1988      asection *             input_sec;
1989 {
1990   /* If we see a common symbol, which implies a relocatable link, then
1991      if a symbol was in a special common section in an input file, mark
1992      it as a special common in the output file.  */
1993   
1994   if (sym->st_shndx == SHN_COMMON)
1995     {
1996       if (strcmp (input_sec->name, ".scommon") == 0)
1997         sym->st_shndx = SHN_V850_SCOMMON;
1998       else if (strcmp (input_sec->name, ".tcommon") == 0)
1999         sym->st_shndx = SHN_V850_TCOMMON;
2000       else if (strcmp (input_sec->name, ".zcommon") == 0)
2001         sym->st_shndx = SHN_V850_ZCOMMON;
2002     }
2003
2004   return true;
2005 }
2006
2007 static boolean
2008 v850_elf_section_from_shdr (abfd, hdr, name)
2009      bfd *               abfd;
2010      Elf_Internal_Shdr * hdr;
2011      char *              name;
2012 {
2013   /* There ought to be a place to keep ELF backend specific flags, but
2014      at the moment there isn't one.  We just keep track of the
2015      sections by their name, instead.  */
2016
2017   if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
2018     return false;
2019
2020   switch (hdr->sh_type)
2021     {
2022     case SHT_V850_SCOMMON:
2023     case SHT_V850_TCOMMON:
2024     case SHT_V850_ZCOMMON:
2025       if (! bfd_set_section_flags (abfd, hdr->bfd_section,
2026                                    (bfd_get_section_flags (abfd,
2027                                                            hdr->bfd_section)
2028                                     | SEC_IS_COMMON)))
2029         return false;
2030     }
2031
2032   return true;
2033 }
2034
2035 /* Set the correct type for a V850 ELF section.  We do this by the
2036    section name, which is a hack, but ought to work.  */
2037 static boolean
2038 v850_elf_fake_sections (abfd, hdr, sec)
2039      bfd *                 abfd;
2040      Elf32_Internal_Shdr * hdr;
2041      asection *            sec;
2042 {
2043   register const char * name;
2044
2045   name = bfd_get_section_name (abfd, sec);
2046
2047   if (strcmp (name, ".scommon") == 0)
2048     {
2049       hdr->sh_type = SHT_V850_SCOMMON;
2050     }
2051   else if (strcmp (name, ".tcommon") == 0)
2052     {
2053       hdr->sh_type = SHT_V850_TCOMMON;
2054     }
2055   else if (strcmp (name, ".zcommon") == 0)
2056     hdr->sh_type = SHT_V850_ZCOMMON;
2057   
2058   return true;
2059 }
2060
2061
2062 \f
2063 #define TARGET_LITTLE_SYM                       bfd_elf32_v850_vec
2064 #define TARGET_LITTLE_NAME                      "elf32-v850"
2065 #define ELF_ARCH                                bfd_arch_v850
2066 #define ELF_MACHINE_CODE                        EM_CYGNUS_V850
2067 #define ELF_MAXPAGESIZE                         0x1000
2068         
2069 #define elf_info_to_howto                       0
2070 #define elf_info_to_howto_rel                   v850_elf_info_to_howto_rel
2071
2072 #define elf_backend_check_relocs                v850_elf_check_relocs
2073 #define elf_backend_relocate_section            v850_elf_relocate_section
2074 #define elf_backend_object_p                    v850_elf_object_p
2075 #define elf_backend_final_write_processing      v850_elf_final_write_processing
2076 #define elf_backend_section_from_bfd_section    v850_elf_section_from_bfd_section
2077 #define elf_backend_symbol_processing           v850_elf_symbol_processing
2078 #define elf_backend_add_symbol_hook             v850_elf_add_symbol_hook
2079 #define elf_backend_link_output_symbol_hook     v850_elf_link_output_symbol_hook
2080 #define elf_backend_section_from_shdr           v850_elf_section_from_shdr
2081 #define elf_backend_fake_sections               v850_elf_fake_sections
2082
2083 #define bfd_elf32_bfd_is_local_label_name       v850_elf_is_local_label_name
2084 #define bfd_elf32_bfd_reloc_type_lookup         v850_elf_reloc_type_lookup
2085 #define bfd_elf32_bfd_copy_private_bfd_data     v850_elf_copy_private_bfd_data
2086 #define bfd_elf32_bfd_merge_private_bfd_data    v850_elf_merge_private_bfd_data
2087 #define bfd_elf32_bfd_set_private_flags         v850_elf_set_private_flags
2088 #define bfd_elf32_bfd_print_private_bfd_data    v850_elf_print_private_bfd_data
2089
2090 #define elf_symbol_leading_char                 '_'
2091
2092 #include "elf32-target.h"
This page took 0.147358 seconds and 4 git commands to generate.