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