Do not complain if an R_V850_LO16 reloc has bit 15 set.
[external/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 /* start-sanitize-v850e */
297   
298   /* 5 bit offset from the tiny data area pointer.  */
299   HOWTO (R_V850_TDA_4_5_OFFSET,         /* type */
300          1,                             /* rightshift */
301          1,                             /* size (0 = byte, 1 = short, 2 = long) */
302          5,                             /* bitsize */
303          false,                         /* pc_relative */
304          0,                             /* bitpos */
305          complain_overflow_dont,        /* complain_on_overflow */
306          v850_elf_reloc,                /* special_function */
307          "R_V850_TDA_4_5_OFFSET",       /* name */
308          false,                         /* partial_inplace */
309          0x0f,                          /* src_mask */
310          0x0f,                          /* dst_mask */
311          false),                        /* pcrel_offset */
312
313   /* 4 bit offset from the tiny data area pointer.  */
314   HOWTO (R_V850_TDA_4_4_OFFSET,         /* type */
315          0,                             /* rightshift */
316          1,                             /* size (0 = byte, 1 = short, 2 = long) */
317          4,                             /* 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_4_OFFSET",       /* name */
323          false,                         /* partial_inplace */
324          0x0f,                          /* src_mask */
325          0x0f,                          /* dst_mask */
326          false),                        /* pcrel_offset */
327
328   /* 16 bit offset from the short data area pointer.  */
329   HOWTO (R_V850_SDA_16_16_SPLIT_OFFSET, /* type */
330          0,                             /* rightshift */
331          2,                             /* size (0 = byte, 1 = short, 2 = long) */
332          16,                            /* bitsize */
333          false,                         /* pc_relative */
334          0,                             /* bitpos */
335          complain_overflow_dont,        /* complain_on_overflow */
336          v850_elf_reloc,                /* special_function */
337          "R_V850_SDA_16_16_SPLIT_OFFSET",/* name */
338          false,                         /* partial_inplace */
339          0xfffe0020,                    /* src_mask */
340          0xfffe0020,                    /* dst_mask */
341          false),                        /* pcrel_offset */
342
343   /* 16 bit offset from the zero data area pointer.  */
344   HOWTO (R_V850_ZDA_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_ZDA_16_16_SPLIT_OFFSET",/* name */
353          false,                         /* partial_inplace */
354          0xfffe0020,                    /* src_mask */
355          0xfffe0020,                    /* dst_mask */
356          false),                        /* pcrel_offset */
357
358 /* end-sanitize-v850e */
359 };
360
361 /* Map BFD reloc types to V850 ELF reloc types.  */
362
363 struct v850_elf_reloc_map
364 {
365   unsigned char bfd_reloc_val;
366   unsigned char elf_reloc_val;
367 };
368
369 static const struct v850_elf_reloc_map v850_elf_reloc_map[] =
370 {
371   { BFD_RELOC_NONE,             R_V850_NONE },
372   { BFD_RELOC_V850_9_PCREL,     R_V850_9_PCREL },
373   { BFD_RELOC_V850_22_PCREL,    R_V850_22_PCREL },
374   { BFD_RELOC_HI16_S,           R_V850_HI16_S },
375   { BFD_RELOC_HI16,             R_V850_HI16 },
376   { BFD_RELOC_LO16,             R_V850_LO16 },
377   { BFD_RELOC_32,               R_V850_32 },
378   { BFD_RELOC_16,               R_V850_16 },
379   { BFD_RELOC_8,                R_V850_8 },
380   { BFD_RELOC_V850_SDA_16_16_OFFSET, R_V850_SDA_16_16_OFFSET },
381   { BFD_RELOC_V850_SDA_15_16_OFFSET, R_V850_SDA_15_16_OFFSET },
382   { BFD_RELOC_V850_ZDA_16_16_OFFSET, R_V850_ZDA_16_16_OFFSET },
383   { BFD_RELOC_V850_ZDA_15_16_OFFSET, R_V850_ZDA_15_16_OFFSET },
384   { BFD_RELOC_V850_TDA_6_8_OFFSET,   R_V850_TDA_6_8_OFFSET },
385   { BFD_RELOC_V850_TDA_7_8_OFFSET,   R_V850_TDA_7_8_OFFSET },
386   { BFD_RELOC_V850_TDA_7_7_OFFSET,   R_V850_TDA_7_7_OFFSET },
387 /* start-sanitize-v850e */
388   { BFD_RELOC_V850_TDA_4_5_OFFSET,         R_V850_TDA_4_5_OFFSET },
389   { BFD_RELOC_V850_TDA_4_4_OFFSET,         R_V850_TDA_4_4_OFFSET },
390   { BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET, R_V850_SDA_16_16_SPLIT_OFFSET },
391   { BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET, R_V850_ZDA_16_16_SPLIT_OFFSET },
392 /* end-sanitize-v850e */
393 };
394
395 \f
396 /* Map a bfd relocation into the appropriate howto structure */
397 static reloc_howto_type *
398 v850_elf_reloc_type_lookup (abfd, code)
399      bfd *abfd;
400      bfd_reloc_code_real_type code;
401 {
402   unsigned int i;
403
404   for (i = 0;
405        i < sizeof (v850_elf_reloc_map) / sizeof (struct v850_elf_reloc_map);
406        i++)
407     {
408       if (v850_elf_reloc_map[i].bfd_reloc_val == code)
409         {
410           BFD_ASSERT (v850_elf_howto_table[v850_elf_reloc_map[i].elf_reloc_val].type == v850_elf_reloc_map[i].elf_reloc_val);
411           
412           return & v850_elf_howto_table[v850_elf_reloc_map[i].elf_reloc_val];
413         }
414     }
415
416   return NULL;
417 }
418
419 \f
420 /* Set the howto pointer for an V850 ELF reloc.  */
421 static void
422 v850_elf_info_to_howto_rel (abfd, cache_ptr, dst)
423      bfd *abfd;
424      arelent *cache_ptr;
425      Elf32_Internal_Rel *dst;
426 {
427   unsigned int r_type;
428
429   r_type = ELF32_R_TYPE (dst->r_info);
430   BFD_ASSERT (r_type < (unsigned int) R_V850_max);
431   cache_ptr->howto = &v850_elf_howto_table[r_type];
432 }
433
434 \f
435 /* Look through the relocs for a section during the first phase, and
436    allocate space in the global offset table or procedure linkage
437    table.  */
438
439 static boolean
440 v850_elf_check_relocs (abfd, info, sec, relocs)
441      bfd *abfd;
442      struct bfd_link_info *info;
443      asection *sec;
444      const Elf_Internal_Rela *relocs;
445 {
446   boolean ret = true;
447   bfd *dynobj;
448   Elf_Internal_Shdr *symtab_hdr;
449   struct elf_link_hash_entry **sym_hashes;
450   const Elf_Internal_Rela *rel;
451   const Elf_Internal_Rela *rel_end;
452   asection *sreloc;
453   enum reloc_type r_type;
454   int other = 0;
455   const char *common = (const char *)0;
456
457   if (info->relocateable)
458     return true;
459
460 #ifdef DEBUG
461   fprintf (stderr, "v850_elf_check_relocs called for section %s in %s\n",
462            bfd_get_section_name (abfd, sec),
463            bfd_get_filename (abfd));
464 #endif
465
466   dynobj = elf_hash_table (info)->dynobj;
467   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
468   sym_hashes = elf_sym_hashes (abfd);
469   sreloc = NULL;
470
471   rel_end = relocs + sec->reloc_count;
472   for (rel = relocs; rel < rel_end; rel++)
473     {
474       unsigned long r_symndx;
475       struct elf_link_hash_entry *h;
476
477       r_symndx = ELF32_R_SYM (rel->r_info);
478       if (r_symndx < symtab_hdr->sh_info)
479         h = NULL;
480       else
481         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
482
483       r_type = (enum reloc_type) ELF32_R_TYPE (rel->r_info);
484       switch (r_type)
485         {
486         default:
487         case R_V850_NONE:
488         case R_V850_9_PCREL:
489         case R_V850_22_PCREL:
490         case R_V850_HI16_S:
491         case R_V850_HI16:
492         case R_V850_LO16:
493         case R_V850_32:
494         case R_V850_16:
495         case R_V850_8:
496           break;
497
498 /* start-sanitize-v850e */
499         case R_V850_SDA_16_16_SPLIT_OFFSET:
500 /* end-sanitize-v850e */
501         case R_V850_SDA_16_16_OFFSET:
502         case R_V850_SDA_15_16_OFFSET:
503           other = V850_OTHER_SDA;
504           common = ".scommon";
505           goto small_data_common;
506           
507 /* start-sanitize-v850e */
508         case R_V850_ZDA_16_16_SPLIT_OFFSET:
509 /* end-sanitize-v850e */
510         case R_V850_ZDA_16_16_OFFSET:
511         case R_V850_ZDA_15_16_OFFSET:
512           other = V850_OTHER_ZDA;
513           common = ".zcommon";
514           goto small_data_common;
515           
516 /* start-sanitize-v850e */
517         case R_V850_TDA_4_5_OFFSET:
518         case R_V850_TDA_4_4_OFFSET:
519 /* end-sanitize-v850e */          
520         case R_V850_TDA_6_8_OFFSET:
521         case R_V850_TDA_7_8_OFFSET:
522         case R_V850_TDA_7_7_OFFSET:
523           other = V850_OTHER_TDA;
524           common = ".tcommon";
525           /* fall through */
526
527 #define V850_OTHER_MASK (V850_OTHER_TDA | V850_OTHER_SDA | V850_OTHER_ZDA)
528
529         small_data_common:
530           if (h)
531             {
532               h->other |= other;        /* flag which type of relocation was used */
533               if ((h->other & V850_OTHER_MASK) != (other & V850_OTHER_MASK)
534                   && (h->other & V850_OTHER_ERROR) == 0)
535                 {
536                   const char *msg;
537
538                   switch (h->other & V850_OTHER_MASK)
539                     {
540                     default:
541                       msg = "Variable cannot occupy in multiple small data regions";
542                       break;
543                     case V850_OTHER_SDA | V850_OTHER_ZDA | V850_OTHER_TDA:
544                       msg = "Variable can only be in one of the small, zero, and tiny data regions";
545                       break;
546                     case V850_OTHER_SDA | V850_OTHER_ZDA:
547                       msg = "Variable cannot be in both small and zero data regions simultaneously";
548                       break;
549                     case V850_OTHER_SDA | V850_OTHER_TDA:
550                       msg = "Variable cannot be in both small and tiny data regions simultaneously";
551                       break;
552                     case V850_OTHER_ZDA | V850_OTHER_TDA:
553                       msg = "Variable cannot be in both zero and tiny data regions simultaneously";
554                       break;
555                     }
556
557                   (*info->callbacks->warning) (info, msg, h->root.root.string,
558                                                abfd, h->root.u.def.section, 0);
559
560                   bfd_set_error (bfd_error_bad_value);
561                   h->other |= V850_OTHER_ERROR;
562                   ret = false;
563                 }
564             }
565
566           if (h && h->root.type == bfd_link_hash_common
567               && h->root.u.c.p
568               && !strcmp (bfd_get_section_name (abfd, h->root.u.c.p->section), "COMMON"))
569             {
570               asection *section = h->root.u.c.p->section = bfd_make_section_old_way (abfd, common);
571               section->flags |= SEC_IS_COMMON;
572             }
573
574 #ifdef DEBUG
575           fprintf (stderr, "v850_elf_check_relocs, found %s relocation for %s%s\n",
576                    v850_elf_howto_table[ (int)r_type ].name,
577                    (h && h->root.root.string) ? h->root.root.string : "<unknown>",
578                    (h->root.type == bfd_link_hash_common) ? ", symbol is common" : "");
579 #endif
580           break;
581         }
582     }
583
584   return ret;
585 }
586
587 \f
588 /* Insert the addend into the instruction.  */
589 static bfd_reloc_status_type
590 v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
591      bfd *       abfd;
592      arelent *   reloc;
593      asymbol *   symbol;
594      PTR         data;
595      asection *  isection;
596      bfd *       obfd;
597      char **     err;
598 {
599   long relocation;
600   long insn;
601
602   
603   /* If there is an output BFD,
604      and the symbol is not a section name (which is only defined at final link time),
605      and either we are not putting the addend into the instruction
606          or the addend is zero, so there is nothing to add into the instruction
607      then just fixup the address and return.  */
608   if (obfd != (bfd *) NULL
609       && (symbol->flags & BSF_SECTION_SYM) == 0
610       && (! reloc->howto->partial_inplace
611           || reloc->addend == 0))
612     {
613       reloc->address += isection->output_offset;
614       return bfd_reloc_ok;
615     }
616 #if 0  
617   else if (obfd != NULL)
618     {
619       return bfd_reloc_continue;
620     }
621 #endif
622   
623   /* Catch relocs involving undefined symbols.  */
624   if (bfd_is_und_section (symbol->section)
625       && (symbol->flags & BSF_WEAK) == 0
626       && obfd == NULL)
627     return bfd_reloc_undefined;
628
629   /* We handle final linking of some relocs ourselves.  */
630
631   /* Is the address of the relocation really within the section?  */
632   if (reloc->address > isection->_cooked_size)
633     return bfd_reloc_outofrange;
634   
635   /* Work out which section the relocation is targetted at and the
636      initial relocation command value.  */
637   
638   /* Get symbol value.  (Common symbols are special.)  */
639   if (bfd_is_com_section (symbol->section))
640     relocation = 0;
641   else
642     relocation = symbol->value;
643   
644   /* Convert input-section-relative symbol value to absolute + addend.  */
645   relocation += symbol->section->output_section->vma;
646   relocation += symbol->section->output_offset;
647   relocation += reloc->addend;
648   
649   if (reloc->howto->pc_relative == true)
650     {
651       /* Here the variable relocation holds the final address of the
652          symbol we are relocating against, plus any addend.  */
653       relocation -= isection->output_section->vma + isection->output_offset;
654       
655       /* Deal with pcrel_offset */
656       relocation -= reloc->address;
657     }
658   
659   /* I've got no clue... */
660   reloc->addend = 0;    
661   
662   switch (reloc->howto->type)
663     {
664     default:
665       /* fprintf (stderr, "reloc type %d not SUPPORTED\n", reloc->howto->type ); */
666       return bfd_reloc_notsupported;
667       
668     case R_V850_22_PCREL:
669       if (relocation > 0x1ffff || relocation < -0x200000)
670         return bfd_reloc_overflow;
671       
672       if ((relocation % 2) != 0)
673         return bfd_reloc_dangerous;
674       
675       insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
676       insn &= ~0xfffe003f;
677       insn |= (((relocation & 0xfffe) << 16)
678                | ((relocation & 0x3f0000) >> 16));
679       bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
680       return bfd_reloc_ok;
681       
682     case R_V850_9_PCREL:
683       if (relocation > 0xff || relocation < -0x100)
684         return bfd_reloc_overflow;
685       
686       if ((relocation % 2) != 0)
687         return bfd_reloc_dangerous;
688       
689       insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
690       insn &= ~ 0xf870;
691       insn |= ((relocation & 0x1f0) << 7) | ((relocation & 0x0e) << 3);
692       bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
693       return bfd_reloc_ok;
694       
695     case R_V850_HI16_S:
696       relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
697       relocation = (relocation >> 16) + ((relocation & 0x8000) != 0);
698       bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
699       return bfd_reloc_ok;
700       
701     case R_V850_HI16:
702       relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
703       relocation = (relocation >> 16);
704       bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
705       return bfd_reloc_ok;
706       
707     case R_V850_LO16:
708       relocation += (short)bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
709       /* Do not complain if value has top bit set, as this has been anticipated.  */
710       if ((unsigned long)relocation > 0xffff)
711         return bfd_reloc_overflow;
712       bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
713       return bfd_reloc_ok;
714
715     case R_V850_16:
716       relocation += (short)bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
717       /* drop through */
718       
719     case R_V850_SDA_16_16_OFFSET:
720     case R_V850_ZDA_16_16_OFFSET:
721       if ((long)relocation > 0x7fff || (long)relocation < -0x8000)
722         return bfd_reloc_overflow;
723       bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
724       return bfd_reloc_ok;
725       
726     case R_V850_SDA_15_16_OFFSET:
727     case R_V850_ZDA_15_16_OFFSET:
728       if ((long)relocation > 0x7ffe || (long)relocation < -0x8000)
729         return bfd_reloc_overflow;
730       
731       if (relocation & 1)
732         return bfd_reloc_dangerous;
733       
734       insn  = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
735       insn &= 1;
736       insn |= (relocation >> 1) & ~1;
737       
738       bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
739       return bfd_reloc_ok;
740       
741     case R_V850_TDA_6_8_OFFSET:
742       if ((long) relocation > 0xfc || (long) relocation < 0)
743         return bfd_reloc_overflow;
744       
745       if (relocation & 3)
746         return bfd_reloc_dangerous;
747       
748       insn  = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
749       insn &= 0xff81;
750       insn |= (relocation >> 1);
751       
752       bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
753       return bfd_reloc_ok;
754       
755     case R_V850_TDA_7_8_OFFSET:
756       if ((long) relocation > 0xfe || (long) relocation < 0)
757         return bfd_reloc_overflow;
758       
759       if (relocation & 1)
760         return bfd_reloc_dangerous;
761       
762       insn  = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
763       insn &= 0xff80;
764       insn |= (relocation >> 1);
765       
766       bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
767       return bfd_reloc_ok;
768       
769     case R_V850_TDA_7_7_OFFSET:
770       if ((long) relocation > 0x7f || (long) relocation < 0)
771         return bfd_reloc_overflow;
772       
773       insn  = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
774       insn &= 0xff80;
775       insn |= relocation;
776       
777       bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
778       return bfd_reloc_ok;
779       
780 /* start-sanitize-v850e */
781     case R_V850_TDA_4_5_OFFSET:
782       if ((long) relocation > 0x1e || (long) relocation < 0)
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 &= 0xfff0;
790       insn |= (relocation >> 1);
791       
792       bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
793       return bfd_reloc_ok;
794       
795     case R_V850_TDA_4_4_OFFSET:
796       if ((long) relocation > 0xf || (long) relocation < 0)
797         return bfd_reloc_overflow;
798       
799       insn  = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
800       insn &= 0xfff0;
801       insn |= relocation;
802       
803       bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
804       return bfd_reloc_ok;
805       
806     case R_V850_ZDA_16_16_SPLIT_OFFSET:
807     case R_V850_SDA_16_16_SPLIT_OFFSET:
808       if ((long) relocation > 0xffff || (long) relocation < 0)
809         return bfd_reloc_overflow;
810       
811       insn  = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
812       
813       insn &= 0x0001ffdf;
814       insn |= (relocation & 1) << 5;
815       insn |= (relocation & ~1) << 16;
816       
817       bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
818       return bfd_reloc_ok;
819 /* end-sanitize-v850e */
820     }
821
822   return bfd_reloc_continue;
823 }
824
825 \f
826 /*ARGSUSED*/
827 static boolean
828 v850_elf_is_local_label_name (abfd, name)
829      bfd *abfd;
830      const char *name;
831 {
832   return ((name[0] == '.' && (name[1] == 'L' || name[1] == '.'))
833           || (name[0] == '_' && name[1] == '.' && name[2] == 'L'
834               && name[3] == '_'));
835 }
836
837 \f
838 /* Perform a relocation as part of a final link.  */
839 static bfd_reloc_status_type
840 v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
841                                     input_section, contents, offset, value,
842                                     addend, info, sym_sec, is_local)
843      reloc_howto_type *      howto;
844      bfd *                   input_bfd;
845      bfd *                   output_bfd;
846      asection *              input_section;
847      bfd_byte *              contents;
848      bfd_vma                 offset;
849      bfd_vma                 value;
850      bfd_vma                 addend;
851      struct bfd_link_info *  info;
852      asection *              sym_sec;
853      int                     is_local;
854 {
855   unsigned long  insn;
856   unsigned long  r_type   = howto->type;
857   bfd_byte *     hit_data = contents + offset;
858
859   switch (r_type)
860     {
861     case R_V850_9_PCREL:
862       value -= (input_section->output_section->vma
863                 + input_section->output_offset);
864       value -= offset;
865
866       if ((long)value > 0xff || (long)value < -0x100)
867         return bfd_reloc_overflow;
868
869       if ((value % 2) != 0)
870         return bfd_reloc_dangerous;
871
872       insn = bfd_get_16 (input_bfd, hit_data);
873       insn &= 0x078f;
874       insn |= ((value & 0x1f0) << 7) | ((value & 0x0e) << 3);
875       bfd_put_16 (input_bfd, insn, hit_data);
876       return bfd_reloc_ok;
877     
878     case R_V850_22_PCREL:
879       value -= (input_section->output_section->vma
880                 + input_section->output_offset);
881       value -= offset;
882     
883       if ((long)value > 0x1ffff || (long)value < -0x200000)
884         return bfd_reloc_overflow;
885
886       if ((value % 2) != 0)
887         return bfd_reloc_dangerous;
888
889       insn = bfd_get_32 (input_bfd, hit_data);
890       insn &= 0x1ffc0;
891       insn |= (((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16));
892       bfd_put_32 (input_bfd, insn, hit_data);
893       return bfd_reloc_ok;
894       
895     case R_V850_HI16_S:
896       value += (short)bfd_get_16 (input_bfd, hit_data);
897       value = (value >> 16) + ((value & 0x8000) != 0);
898
899       if ((long)value > 0x7fff || (long)value < -0x8000)
900         return bfd_reloc_overflow;
901
902       bfd_put_16 (input_bfd, value, hit_data);
903       return bfd_reloc_ok;
904
905     case R_V850_HI16:
906       value += (short)bfd_get_16 (input_bfd, hit_data);
907       value >>= 16;
908
909       if ((long)value > 0x7fff || (long)value < -0x8000)
910         return bfd_reloc_overflow;
911
912       bfd_put_16 (input_bfd, value, hit_data);
913       return bfd_reloc_ok;
914
915     case R_V850_LO16:
916       value += (short)bfd_get_16 (input_bfd, hit_data);
917       value &= 0xffff;
918
919       bfd_put_16 (input_bfd, value, hit_data);
920       return bfd_reloc_ok;
921
922     case R_V850_16:
923       value += (short) bfd_get_16 (input_bfd, hit_data);
924
925       if ((long) value > 0x7fff || (long) value < -0x8000)
926         return bfd_reloc_overflow;
927
928       bfd_put_16 (input_bfd, value, hit_data);
929       return bfd_reloc_ok;
930
931     case R_V850_ZDA_16_16_OFFSET:
932       value -= sym_sec->output_section->vma;
933       value += (short) bfd_get_16 (input_bfd, hit_data);
934
935       if ((long) value > 0x7fff || (long) value < -0x8000)
936         return bfd_reloc_overflow;
937
938       bfd_put_16 (input_bfd, value, hit_data);
939       return bfd_reloc_ok;
940
941     case R_V850_ZDA_15_16_OFFSET:       
942       insn = bfd_get_16 (input_bfd, hit_data);
943
944       value -= sym_sec->output_section->vma;
945       value += ((insn & 0xfffe) << 1);
946       
947       if ((long) value > 0x7ffe || (long) value < -0x8000)
948         return bfd_reloc_overflow;
949
950       value &= ~1;
951       value |= (insn & 1);
952       
953       bfd_put_16 (input_bfd, value, hit_data);
954       return bfd_reloc_ok;
955
956     case R_V850_32:
957       value += bfd_get_32 (input_bfd, hit_data);
958       bfd_put_32 (input_bfd, value, hit_data);
959       return bfd_reloc_ok;
960
961     case R_V850_8:
962       value += (char)bfd_get_8 (input_bfd, hit_data);
963
964       if ((long)value > 0x7f || (long)value < -0x80)
965         return bfd_reloc_overflow;
966
967       bfd_put_8 (input_bfd, value, hit_data);
968       return bfd_reloc_ok;
969
970     case R_V850_SDA_16_16_OFFSET:
971       {
972         unsigned long                gp;
973         struct bfd_link_hash_entry * h;
974
975         /* Get the value of __gp.  */
976         h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
977         if (h == (struct bfd_link_hash_entry *) NULL
978             || h->type != bfd_link_hash_defined)
979           return bfd_reloc_other;
980
981         gp = (h->u.def.value
982               + h->u.def.section->output_section->vma
983               + h->u.def.section->output_offset);
984
985         value -= sym_sec->output_section->vma;
986         value -= (gp - sym_sec->output_section->vma);
987         value += (short) bfd_get_16 (input_bfd, hit_data);
988
989         if ((long)value > 0x7fff || (long)value < -0x8000)
990           return bfd_reloc_overflow;
991
992         bfd_put_16 (input_bfd, value, hit_data);
993         return bfd_reloc_ok;
994       }
995
996     case R_V850_SDA_15_16_OFFSET:
997       {
998         unsigned long                gp;
999         struct bfd_link_hash_entry * h;
1000
1001         /* Get the value of __gp.  */
1002         h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
1003         if (h == (struct bfd_link_hash_entry *) NULL
1004             || h->type != bfd_link_hash_defined)
1005           return bfd_reloc_other;
1006
1007         gp = (h->u.def.value
1008               + h->u.def.section->output_section->vma
1009               + h->u.def.section->output_offset);
1010         
1011         value -= sym_sec->output_section->vma;
1012         value -= (gp - sym_sec->output_section->vma);
1013
1014         insn = bfd_get_16 (input_bfd, hit_data);
1015         
1016         value += ((insn & 0xfffe) << 1);
1017         
1018         if ((long)value > 0x7ffe || (long)value < -0x8000)
1019           return bfd_reloc_overflow;
1020
1021         value &= ~1;
1022         value |= (insn & 1);
1023         
1024         bfd_put_16 (input_bfd, value, hit_data);
1025         return bfd_reloc_ok;
1026       }
1027
1028     case R_V850_TDA_6_8_OFFSET:
1029       {
1030         unsigned long                ep;
1031         struct bfd_link_hash_entry * h;
1032         
1033         insn = bfd_get_16 (input_bfd, hit_data);
1034
1035         /* Get the value of __ep.  */
1036         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1037         if (h == (struct bfd_link_hash_entry *) NULL
1038             || h->type != bfd_link_hash_defined)
1039           return bfd_reloc_continue;  /* Actually this indicates that __ep could not be found. */
1040
1041         ep = (h->u.def.value
1042               + h->u.def.section->output_section->vma
1043               + h->u.def.section->output_offset);
1044
1045         value -= ep;
1046         value += ((insn & 0x7e) << 2);
1047         
1048         if ((long) value > 0xfc || (long) value < 0)
1049           return bfd_reloc_overflow;
1050         
1051         if ((value % 2) != 0)
1052           return bfd_reloc_dangerous;
1053         
1054         insn &= 0xff81;
1055         insn |= (value >> 1);
1056
1057         bfd_put_16 (input_bfd, insn, hit_data);
1058         return bfd_reloc_ok;
1059       }
1060     
1061     case R_V850_TDA_7_8_OFFSET:
1062       {
1063         unsigned long                ep;
1064         struct bfd_link_hash_entry * h;
1065         
1066         insn = bfd_get_16 (input_bfd, hit_data);
1067
1068         /* Get the value of __ep.  */
1069         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1070         if (h == (struct bfd_link_hash_entry *) NULL
1071             || h->type != bfd_link_hash_defined)
1072           return bfd_reloc_continue;    /* Actually this indicates that __ep could not be found. */
1073
1074         ep = (h->u.def.value
1075               + h->u.def.section->output_section->vma
1076               + h->u.def.section->output_offset);
1077         
1078         value -= ep;
1079         value += ((insn & 0x7f) << 1);
1080         
1081         if ((long) value > 0xfe || (long) value < 0)
1082           return bfd_reloc_overflow;
1083         
1084         insn &= 0xff80;
1085         insn |= (value >> 1);
1086         
1087         bfd_put_16 (input_bfd, insn, hit_data);
1088         return bfd_reloc_ok;
1089       }
1090     
1091     case R_V850_TDA_7_7_OFFSET:
1092       {
1093         unsigned long                ep;
1094         struct bfd_link_hash_entry * h;
1095         
1096         insn = bfd_get_16 (input_bfd, hit_data);
1097
1098         /* Get the value of __ep.  */
1099         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1100         if (h == (struct bfd_link_hash_entry *) NULL
1101             || h->type != bfd_link_hash_defined)
1102           return bfd_reloc_continue;  /* Actually this indicates that __ep could not be found. */
1103
1104         ep = (h->u.def.value
1105               + h->u.def.section->output_section->vma
1106               + h->u.def.section->output_offset);
1107         value -= ep;
1108         
1109         value += insn & 0x7f;
1110         
1111         if ((long) value > 0x7f || (long) value < 0)
1112           return bfd_reloc_overflow;
1113         
1114         insn &= 0xff80;
1115         insn |= value;
1116         bfd_put_16 (input_bfd, insn, hit_data);
1117         return bfd_reloc_ok;
1118       }
1119     
1120 /* start-sanitize-v850e */
1121     case R_V850_TDA_4_5_OFFSET:
1122       {
1123         unsigned long                ep;
1124         struct bfd_link_hash_entry * h;
1125         
1126         /* Get the value of __ep.  */
1127         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1128         if (h == (struct bfd_link_hash_entry *) NULL
1129             || h->type != bfd_link_hash_defined)
1130           return bfd_reloc_continue;  /* Actually this indicates that __ep could not be found. */
1131
1132         ep = (h->u.def.value
1133               + h->u.def.section->output_section->vma
1134               + h->u.def.section->output_offset);
1135         value -= ep;
1136         
1137         insn = bfd_get_16 (input_bfd, hit_data);
1138
1139         value += ((insn & 0xf) << 1);
1140         
1141         if ((long) value > 0x1e || (long) value < 0)
1142           return bfd_reloc_overflow;
1143         
1144         insn &= 0xfff0;
1145         insn |= (value >> 1);
1146         bfd_put_16 (input_bfd, insn, hit_data);
1147         return bfd_reloc_ok;
1148       }
1149     
1150     case R_V850_TDA_4_4_OFFSET:
1151       {
1152         unsigned long                ep;
1153         struct bfd_link_hash_entry * h;
1154         
1155         /* Get the value of __ep.  */
1156         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1157         if (h == (struct bfd_link_hash_entry *) NULL
1158             || h->type != bfd_link_hash_defined)
1159           return bfd_reloc_continue;  /* Actually this indicates that __ep could not be found. */
1160
1161         ep = (h->u.def.value
1162               + h->u.def.section->output_section->vma
1163               + h->u.def.section->output_offset);
1164         value -= ep;
1165         
1166         insn = bfd_get_16 (input_bfd, hit_data);
1167
1168         value += insn & 0xf;
1169         
1170         if ((long) value > 0xf || (long) value < 0)
1171           return bfd_reloc_overflow;
1172         
1173         insn &= 0xfff0;
1174         insn |= value;
1175         bfd_put_16 (input_bfd, insn, hit_data);
1176         return bfd_reloc_ok;
1177       }
1178     
1179     case R_V850_SDA_16_16_SPLIT_OFFSET:
1180       {
1181         unsigned long                gp;
1182         struct bfd_link_hash_entry * h;
1183
1184         /* Get the value of __gp.  */
1185         h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
1186         if (h == (struct bfd_link_hash_entry *) NULL
1187             || h->type != bfd_link_hash_defined)
1188           return bfd_reloc_other;
1189
1190         gp = (h->u.def.value
1191               + h->u.def.section->output_section->vma
1192               + h->u.def.section->output_offset);
1193         
1194         value -= sym_sec->output_section->vma;
1195         value -= (gp - sym_sec->output_section->vma);
1196
1197         insn = bfd_get_32 (input_bfd, hit_data);
1198         
1199         value += ((insn & 0xfffe0000) >> 16);
1200         value += ((insn & 0x20) >> 5);
1201           
1202         if ((long)value > 0x7fff || (long)value < -0x8000)
1203           return bfd_reloc_overflow;
1204
1205         insn &= 0x0001ffdf;
1206         insn |= (value & 1) << 5;
1207         insn |= (value & ~1) << 16;
1208         
1209         bfd_put_32 (input_bfd, insn, hit_data);
1210         return bfd_reloc_ok;
1211       }
1212
1213     case R_V850_ZDA_16_16_SPLIT_OFFSET:
1214       insn = bfd_get_32 (input_bfd, hit_data);
1215         
1216       value -= sym_sec->output_section->vma;
1217       value += ((insn & 0xfffe0000) >> 16);
1218       value += ((insn & 0x20) >> 5);
1219           
1220       if ((long)value > 0x7fff || (long)value < -0x8000)
1221         return bfd_reloc_overflow;
1222       
1223       insn &= 0x0001ffdf;
1224       insn |= (value & 1) << 5;
1225       insn |= (value & ~1) << 16;
1226       
1227       bfd_put_32 (input_bfd, insn, hit_data);
1228       return bfd_reloc_ok;
1229
1230 /* end-sanitize-v850e */
1231     
1232     
1233     case R_V850_NONE:
1234       return bfd_reloc_ok;
1235
1236     default:
1237       return bfd_reloc_notsupported;
1238     }
1239 }
1240
1241 \f
1242 /* Relocate an V850 ELF section.  */
1243 static boolean
1244 v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
1245                            contents, relocs, local_syms, local_sections)
1246      bfd *                  output_bfd;
1247      struct bfd_link_info * info;
1248      bfd *                  input_bfd;
1249      asection *             input_section;
1250      bfd_byte *             contents;
1251      Elf_Internal_Rela *    relocs;
1252      Elf_Internal_Sym *     local_syms;
1253      asection **            local_sections;
1254 {
1255   Elf_Internal_Shdr *           symtab_hdr;
1256   struct elf_link_hash_entry ** sym_hashes;
1257   Elf_Internal_Rela *           rel;
1258   Elf_Internal_Rela *           relend;
1259
1260   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
1261   sym_hashes = elf_sym_hashes (input_bfd);
1262
1263   rel    = relocs;
1264   relend = relocs + input_section->reloc_count;
1265   for (; rel < relend; rel++)
1266     {
1267       int                          r_type;
1268       reloc_howto_type *           howto;
1269       unsigned long                r_symndx;
1270       Elf_Internal_Sym *           sym;
1271       asection *                   sec;
1272       struct elf_link_hash_entry * h;
1273       bfd_vma                      relocation;
1274       bfd_reloc_status_type        r;
1275
1276       r_symndx = ELF32_R_SYM (rel->r_info);
1277       r_type   = ELF32_R_TYPE (rel->r_info);
1278       howto    = v850_elf_howto_table + r_type;
1279
1280       if (info->relocateable)
1281         {
1282           /* This is a relocateable link.  We don't have to change
1283              anything, unless the reloc is against a section symbol,
1284              in which case we have to adjust according to where the
1285              section symbol winds up in the output section.  */
1286           if (r_symndx < symtab_hdr->sh_info)
1287             {
1288               sym = local_syms + r_symndx;
1289               if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
1290                 {
1291                   sec = local_sections[r_symndx];
1292                   rel->r_addend += sec->output_offset + sym->st_value;
1293                 }
1294             }
1295
1296           continue;
1297         }
1298
1299       /* This is a final link.  */
1300       h = NULL;
1301       sym = NULL;
1302       sec = NULL;
1303       if (r_symndx < symtab_hdr->sh_info)
1304         {
1305           sym = local_syms + r_symndx;
1306           sec = local_sections[r_symndx];
1307           relocation = (sec->output_section->vma
1308                         + sec->output_offset
1309                         + sym->st_value);
1310 #if 0
1311           {
1312             char * name;
1313             name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name);
1314             name = (name == NULL) ? "<none>" : name;
1315 fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x rel %x\n", sec->name, name, sym->st_name,
1316          sec->output_section->vma, sec->output_offset, sym->st_value, rel->r_addend, rel);
1317           }
1318 #endif
1319         }
1320       else
1321         {
1322           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
1323           
1324           while (h->root.type == bfd_link_hash_indirect
1325                  || h->root.type == bfd_link_hash_warning)
1326             h = (struct elf_link_hash_entry *) h->root.u.i.link;
1327           
1328           if (h->root.type == bfd_link_hash_defined
1329               || h->root.type == bfd_link_hash_defweak)
1330             {
1331               sec = h->root.u.def.section;
1332               relocation = (h->root.u.def.value
1333                             + sec->output_section->vma
1334                             + sec->output_offset);
1335             }
1336           else if (h->root.type == bfd_link_hash_undefweak)
1337             relocation = 0;
1338           else
1339             {
1340               if (! ((*info->callbacks->undefined_symbol)
1341                      (info, h->root.root.string, input_bfd,
1342                       input_section, rel->r_offset)))
1343                 return false;
1344               relocation = 0;
1345             }
1346         }
1347
1348       /* FIXME: We should use the addend, but the COFF relocations
1349          don't.  */
1350       r = v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
1351                                         input_section,
1352                                         contents, rel->r_offset,
1353                                         relocation, rel->r_addend,
1354                                         info, sec, h == NULL);
1355
1356       if (r != bfd_reloc_ok)
1357         {
1358           const char * name;
1359           const char * msg = (const char *)0;
1360
1361           if (h != NULL)
1362             name = h->root.root.string;
1363           else
1364             {
1365               name = (bfd_elf_string_from_elf_section
1366                       (input_bfd, symtab_hdr->sh_link, sym->st_name));
1367               if (name == NULL || *name == '\0')
1368                 name = bfd_section_name (input_bfd, sec);
1369             }
1370
1371           switch (r)
1372             {
1373             case bfd_reloc_overflow:
1374               if (! ((*info->callbacks->reloc_overflow)
1375                      (info, name, howto->name, (bfd_vma) 0,
1376                       input_bfd, input_section, rel->r_offset)))
1377                 return false;
1378               break;
1379
1380             case bfd_reloc_undefined:
1381               fprintf (stderr, "undef2 %s\n", name );
1382               if (! ((*info->callbacks->undefined_symbol)
1383                      (info, name, input_bfd, input_section,
1384                       rel->r_offset)))
1385                 return false;
1386               break;
1387
1388             case bfd_reloc_outofrange:
1389               msg = "internal error: out of range error";
1390               goto common_error;
1391
1392             case bfd_reloc_notsupported:
1393               msg = "internal error: unsupported relocation error";
1394               goto common_error;
1395
1396             case bfd_reloc_dangerous:
1397               msg = "internal error: dangerous relocation";
1398               goto common_error;
1399
1400             case bfd_reloc_other:
1401               msg = "could not locate special linker symbol __gp";
1402               goto common_error;
1403
1404             case bfd_reloc_continue:
1405               msg = "could not locate special linker symbol __ep";
1406               goto common_error;
1407
1408             default:
1409               msg = "internal error: unknown error";
1410               /* fall through */
1411
1412             common_error:
1413               if (!((*info->callbacks->warning)
1414                     (info, msg, name, input_bfd, input_section,
1415                      rel->r_offset)))
1416                 return false;
1417               break;
1418             }
1419         }
1420     }
1421
1422   return true;
1423 }
1424
1425 /* Set the right machine number.  */
1426 static boolean
1427 v850_elf_object_p (abfd)
1428      bfd *abfd;
1429 {
1430   switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
1431     {
1432     default:
1433     case E_V850_ARCH:   (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, 0); break;
1434 /* start-sanitize-v850e */
1435     case E_V850E_ARCH:  (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e); break;
1436 /* end-sanitize-v850e */
1437 /* start-sanitize-v850eq */
1438     case E_V850EQ_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850eq); break;
1439 /* start-sanitize-v850eq */
1440     }
1441 }
1442
1443 /* Store the machine number in the flags field.  */
1444 void
1445 v850_elf_final_write_processing (abfd, linker)
1446      bfd *   abfd;
1447      boolean linker;
1448 {
1449   unsigned long val;
1450
1451   switch (bfd_get_mach (abfd))
1452     {
1453     default:
1454     case 0: val = E_V850_ARCH; break;
1455 /* start-sanitize-v850e */
1456     case bfd_mach_v850e: val = E_V850E_ARCH; break;
1457 /* end-sanitize-v850e */
1458 /* start-sanitize-v850eq */
1459     case bfd_mach_v850eq: val = E_V850EQ_ARCH;  break;
1460 /* end-sanitize-v850eq */
1461     }
1462
1463   elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH;
1464   elf_elfheader (abfd)->e_flags |= val;
1465 }
1466
1467 /* Function to keep V850 specific file flags. */
1468 boolean
1469 v850_elf_set_private_flags (abfd, flags)
1470      bfd *    abfd;
1471      flagword flags;
1472 {
1473   BFD_ASSERT (!elf_flags_init (abfd)
1474               || elf_elfheader (abfd)->e_flags == flags);
1475
1476   elf_elfheader (abfd)->e_flags = flags;
1477   elf_flags_init (abfd) = true;
1478   return true;
1479 }
1480
1481 /* Copy backend specific data from one object module to another */
1482 boolean
1483 v850_elf_copy_private_bfd_data (ibfd, obfd)
1484      bfd * ibfd;
1485      bfd * obfd;
1486 {
1487   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1488       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1489     return true;
1490
1491   BFD_ASSERT (!elf_flags_init (obfd)
1492               || (elf_elfheader (obfd)->e_flags
1493                   == elf_elfheader (ibfd)->e_flags));
1494
1495   elf_gp (obfd) = elf_gp (ibfd);
1496   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
1497   elf_flags_init (obfd) = true;
1498   return true;
1499 }
1500
1501 /* Merge backend specific data from an object file to the output
1502    object file when linking.  */
1503 boolean
1504 v850_elf_merge_private_bfd_data (ibfd, obfd)
1505      bfd * ibfd;
1506      bfd * obfd;
1507 {
1508   flagword old_flags;
1509   flagword new_flags;
1510
1511   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1512       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1513     return true;
1514
1515   new_flags = elf_elfheader (ibfd)->e_flags;
1516   old_flags = elf_elfheader (obfd)->e_flags;
1517
1518   if (! elf_flags_init (obfd))
1519     {
1520       elf_flags_init (obfd) = true;
1521       elf_elfheader (obfd)->e_flags = new_flags;
1522
1523       if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
1524           && bfd_get_arch_info (obfd)->the_default)
1525         {
1526           return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
1527         }
1528
1529       return true;
1530     }
1531
1532   /* Check flag compatibility.  */
1533
1534   if (new_flags == old_flags)
1535     return true;
1536
1537   if ((new_flags & EF_V850_ARCH) != (old_flags & EF_V850_ARCH))
1538     {
1539       _bfd_error_handler ("%s: Architecture mismatch with previous modules",
1540              bfd_get_filename (ibfd));
1541       bfd_set_error (bfd_error_bad_value);
1542       return false;
1543     }
1544
1545   return true;
1546 }
1547 /* Display the flags field */
1548
1549 static boolean
1550 v850_elf_print_private_bfd_data (abfd, ptr)
1551      bfd *   abfd;
1552      PTR     ptr;
1553 {
1554   FILE * file = (FILE *) ptr;
1555   
1556   BFD_ASSERT (abfd != NULL && ptr != NULL)
1557   
1558   fprintf (file, "private flags = %x", elf_elfheader (abfd)->e_flags);
1559   
1560   switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
1561     {
1562     default:
1563     case E_V850_ARCH: fprintf (file, ": v850 architecture"); break;
1564 /* start-sanitize-v850e */
1565     case E_V850E_ARCH: fprintf (file, ": v850e architecture"); break;
1566 /* end-sanitize-v850e */
1567 /* start-sanitize-v850eq */
1568     case E_V850EQ_ARCH: fprintf (file, ": v850eq architecture"); break;
1569 /* end-sanitize-v850eq */
1570     }
1571   
1572   fputc ('\n', file);
1573   
1574   return true;
1575 }
1576 \f
1577 #define TARGET_LITTLE_SYM                       bfd_elf32_v850_vec
1578 #define TARGET_LITTLE_NAME                      "elf32-v850"
1579 #define ELF_ARCH                                bfd_arch_v850
1580 #define ELF_MACHINE_CODE                        EM_CYGNUS_V850
1581 #define ELF_MAXPAGESIZE                         0x1000
1582         
1583 #define elf_info_to_howto                       0
1584 #define elf_info_to_howto_rel                   v850_elf_info_to_howto_rel
1585 #define elf_backend_check_relocs                v850_elf_check_relocs
1586 #define elf_backend_relocate_section            v850_elf_relocate_section
1587 #define elf_backend_object_p                    v850_elf_object_p
1588 #define elf_backend_final_write_processing      v850_elf_final_write_processing
1589 #define bfd_elf32_bfd_is_local_label_name       v850_elf_is_local_label_name
1590 #define bfd_elf32_bfd_reloc_type_lookup         v850_elf_reloc_type_lookup
1591 #define bfd_elf32_bfd_copy_private_bfd_data     v850_elf_copy_private_bfd_data
1592 #define bfd_elf32_bfd_merge_private_bfd_data    v850_elf_merge_private_bfd_data
1593 #define bfd_elf32_bfd_set_private_flags         v850_elf_set_private_flags
1594 #define bfd_elf32_bfd_print_private_bfd_data    v850_elf_print_private_bfd_data
1595
1596 #define elf_symbol_leading_char                 '_'
1597
1598 #include "elf32-target.h"