Fix sanitization.
[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       bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
711       return bfd_reloc_ok;
712
713     case R_V850_16:
714       relocation += (short)bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
715       /* drop through */
716       
717     case R_V850_SDA_16_16_OFFSET:
718     case R_V850_ZDA_16_16_OFFSET:
719       if ((long)relocation > 0x7fff || (long)relocation < -0x8000)
720         return bfd_reloc_overflow;
721       bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
722       return bfd_reloc_ok;
723       
724     case R_V850_SDA_15_16_OFFSET:
725     case R_V850_ZDA_15_16_OFFSET:
726       if ((long)relocation > 0x7ffe || (long)relocation < -0x8000)
727         return bfd_reloc_overflow;
728       
729       if (relocation & 1)
730         return bfd_reloc_dangerous;
731       
732       insn  = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
733       insn &= 1;
734       insn |= (relocation >> 1) & ~1;
735       
736       bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
737       return bfd_reloc_ok;
738       
739     case R_V850_TDA_6_8_OFFSET:
740       if ((long) relocation > 0xfc || (long) relocation < 0)
741         return bfd_reloc_overflow;
742       
743       if (relocation & 3)
744         return bfd_reloc_dangerous;
745       
746       insn  = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
747       insn &= 0xff81;
748       insn |= (relocation >> 1);
749       
750       bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
751       return bfd_reloc_ok;
752       
753     case R_V850_TDA_7_8_OFFSET:
754       if ((long) relocation > 0xfe || (long) relocation < 0)
755         return bfd_reloc_overflow;
756       
757       if (relocation & 1)
758         return bfd_reloc_dangerous;
759       
760       insn  = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
761       insn &= 0xff80;
762       insn |= (relocation >> 1);
763       
764       bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
765       return bfd_reloc_ok;
766       
767     case R_V850_TDA_7_7_OFFSET:
768       if ((long) relocation > 0x7f || (long) relocation < 0)
769         return bfd_reloc_overflow;
770       
771       insn  = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
772       insn &= 0xff80;
773       insn |= relocation;
774       
775       bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
776       return bfd_reloc_ok;
777       
778 /* start-sanitize-v850e */
779     case R_V850_TDA_4_5_OFFSET:
780       if ((long) relocation > 0x1e || (long) relocation < 0)
781         return bfd_reloc_overflow;
782       
783       if (relocation & 1)
784         return bfd_reloc_dangerous;
785       
786       insn  = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
787       insn &= 0xfff0;
788       insn |= (relocation >> 1);
789       
790       bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
791       return bfd_reloc_ok;
792       
793     case R_V850_TDA_4_4_OFFSET:
794       if ((long) relocation > 0xf || (long) relocation < 0)
795         return bfd_reloc_overflow;
796       
797       insn  = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
798       insn &= 0xfff0;
799       insn |= relocation;
800       
801       bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
802       return bfd_reloc_ok;
803       
804     case R_V850_ZDA_16_16_SPLIT_OFFSET:
805     case R_V850_SDA_16_16_SPLIT_OFFSET:
806       if ((long) relocation > 0xffff || (long) relocation < 0)
807         return bfd_reloc_overflow;
808       
809       insn  = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
810       
811       insn &= 0x0001ffdf;
812       insn |= (relocation & 1) << 5;
813       insn |= (relocation & ~1) << 16;
814       
815       bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
816       return bfd_reloc_ok;
817 /* end-sanitize-v850e */
818     }
819
820   return bfd_reloc_continue;
821 }
822
823 \f
824 /*ARGSUSED*/
825 static boolean
826 v850_elf_is_local_label_name (abfd, name)
827      bfd *abfd;
828      const char *name;
829 {
830   return ((name[0] == '.' && (name[1] == 'L' || name[1] == '.'))
831           || (name[0] == '_' && name[1] == '.' && name[2] == 'L'
832               && name[3] == '_'));
833 }
834
835 \f
836 /* Perform a relocation as part of a final link.  */
837 static bfd_reloc_status_type
838 v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
839                                     input_section, contents, offset, value,
840                                     addend, info, sym_sec, is_local)
841      reloc_howto_type *      howto;
842      bfd *                   input_bfd;
843      bfd *                   output_bfd;
844      asection *              input_section;
845      bfd_byte *              contents;
846      bfd_vma                 offset;
847      bfd_vma                 value;
848      bfd_vma                 addend;
849      struct bfd_link_info *  info;
850      asection *              sym_sec;
851      int                     is_local;
852 {
853   unsigned long  insn;
854   unsigned long  r_type   = howto->type;
855   bfd_byte *     hit_data = contents + offset;
856
857   switch (r_type)
858     {
859     case R_V850_9_PCREL:
860       value -= (input_section->output_section->vma
861                 + input_section->output_offset);
862       value -= offset;
863
864       if ((long)value > 0xff || (long)value < -0x100)
865         return bfd_reloc_overflow;
866
867       if ((value % 2) != 0)
868         return bfd_reloc_dangerous;
869
870       insn = bfd_get_16 (input_bfd, hit_data);
871       insn &= 0x078f;
872       insn |= ((value & 0x1f0) << 7) | ((value & 0x0e) << 3);
873       bfd_put_16 (input_bfd, insn, hit_data);
874       return bfd_reloc_ok;
875     
876     case R_V850_22_PCREL:
877       value -= (input_section->output_section->vma
878                 + input_section->output_offset);
879       value -= offset;
880     
881       if ((long)value > 0x1ffff || (long)value < -0x200000)
882         return bfd_reloc_overflow;
883
884       if ((value % 2) != 0)
885         return bfd_reloc_dangerous;
886
887       insn = bfd_get_32 (input_bfd, hit_data);
888       insn &= 0x1ffc0;
889       insn |= (((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16));
890       bfd_put_32 (input_bfd, insn, hit_data);
891       return bfd_reloc_ok;
892       
893     case R_V850_HI16_S:
894       value += (short)bfd_get_16 (input_bfd, hit_data);
895       value = (value >> 16) + ((value & 0x8000) != 0);
896
897       if ((long)value > 0x7fff || (long)value < -0x8000)
898         return bfd_reloc_overflow;
899
900       bfd_put_16 (input_bfd, value, hit_data);
901       return bfd_reloc_ok;
902
903     case R_V850_HI16:
904       value += (short)bfd_get_16 (input_bfd, hit_data);
905       value >>= 16;
906
907       if ((long)value > 0x7fff || (long)value < -0x8000)
908         return bfd_reloc_overflow;
909
910       bfd_put_16 (input_bfd, value, hit_data);
911       return bfd_reloc_ok;
912
913     case R_V850_LO16:
914       value += (short)bfd_get_16 (input_bfd, hit_data);
915       value &= 0xffff;
916
917       bfd_put_16 (input_bfd, value, hit_data);
918       return bfd_reloc_ok;
919
920     case R_V850_16:
921       value += (short) bfd_get_16 (input_bfd, hit_data);
922
923       if ((long) value > 0x7fff || (long) value < -0x8000)
924         return bfd_reloc_overflow;
925
926       bfd_put_16 (input_bfd, value, hit_data);
927       return bfd_reloc_ok;
928
929     case R_V850_ZDA_16_16_OFFSET:
930       value -= sym_sec->output_section->vma;
931       value += (short) bfd_get_16 (input_bfd, hit_data);
932
933       if ((long) value > 0x7fff || (long) value < -0x8000)
934         return bfd_reloc_overflow;
935
936       bfd_put_16 (input_bfd, value, hit_data);
937       return bfd_reloc_ok;
938
939     case R_V850_ZDA_15_16_OFFSET:       
940       insn = bfd_get_16 (input_bfd, hit_data);
941
942       value -= sym_sec->output_section->vma;
943       value += ((insn & 0xfffe) << 1);
944       
945       if ((long) value > 0x7ffe || (long) value < -0x8000)
946         return bfd_reloc_overflow;
947
948       value &= ~1;
949       value |= (insn & 1);
950       
951       bfd_put_16 (input_bfd, value, hit_data);
952       return bfd_reloc_ok;
953
954     case R_V850_32:
955       value += bfd_get_32 (input_bfd, hit_data);
956       bfd_put_32 (input_bfd, value, hit_data);
957       return bfd_reloc_ok;
958
959     case R_V850_8:
960       value += (char)bfd_get_8 (input_bfd, hit_data);
961
962       if ((long)value > 0x7f || (long)value < -0x80)
963         return bfd_reloc_overflow;
964
965       bfd_put_8 (input_bfd, value, hit_data);
966       return bfd_reloc_ok;
967
968     case R_V850_SDA_16_16_OFFSET:
969       {
970         unsigned long                gp;
971         struct bfd_link_hash_entry * h;
972
973         /* Get the value of __gp.  */
974         h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
975         if (h == (struct bfd_link_hash_entry *) NULL
976             || h->type != bfd_link_hash_defined)
977           return bfd_reloc_other;
978
979         gp = (h->u.def.value
980               + h->u.def.section->output_section->vma
981               + h->u.def.section->output_offset);
982
983         value -= sym_sec->output_section->vma;
984         value -= (gp - sym_sec->output_section->vma);
985         value += (short) bfd_get_16 (input_bfd, hit_data);
986
987         if ((long)value > 0x7fff || (long)value < -0x8000)
988           return bfd_reloc_overflow;
989
990         bfd_put_16 (input_bfd, value, hit_data);
991         return bfd_reloc_ok;
992       }
993
994     case R_V850_SDA_15_16_OFFSET:
995       {
996         unsigned long                gp;
997         struct bfd_link_hash_entry * h;
998
999         /* Get the value of __gp.  */
1000         h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
1001         if (h == (struct bfd_link_hash_entry *) NULL
1002             || h->type != bfd_link_hash_defined)
1003           return bfd_reloc_other;
1004
1005         gp = (h->u.def.value
1006               + h->u.def.section->output_section->vma
1007               + h->u.def.section->output_offset);
1008         
1009         value -= sym_sec->output_section->vma;
1010         value -= (gp - sym_sec->output_section->vma);
1011
1012         insn = bfd_get_16 (input_bfd, hit_data);
1013         
1014         value += ((insn & 0xfffe) << 1);
1015         
1016         if ((long)value > 0x7ffe || (long)value < -0x8000)
1017           return bfd_reloc_overflow;
1018
1019         value &= ~1;
1020         value |= (insn & 1);
1021         
1022         bfd_put_16 (input_bfd, value, hit_data);
1023         return bfd_reloc_ok;
1024       }
1025
1026     case R_V850_TDA_6_8_OFFSET:
1027       {
1028         unsigned long                ep;
1029         struct bfd_link_hash_entry * h;
1030         
1031         insn = bfd_get_16 (input_bfd, hit_data);
1032
1033         /* Get the value of __ep.  */
1034         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1035         if (h == (struct bfd_link_hash_entry *) NULL
1036             || h->type != bfd_link_hash_defined)
1037           return bfd_reloc_continue;  /* Actually this indicates that __ep could not be found. */
1038
1039         ep = (h->u.def.value
1040               + h->u.def.section->output_section->vma
1041               + h->u.def.section->output_offset);
1042
1043         value -= ep;
1044         value += ((insn & 0x7e) << 2);
1045         
1046         if ((long) value > 0xfc || (long) value < 0)
1047           return bfd_reloc_overflow;
1048         
1049         if ((value % 2) != 0)
1050           return bfd_reloc_dangerous;
1051         
1052         insn &= 0xff81;
1053         insn |= (value >> 1);
1054
1055         bfd_put_16 (input_bfd, insn, hit_data);
1056         return bfd_reloc_ok;
1057       }
1058     
1059     case R_V850_TDA_7_8_OFFSET:
1060       {
1061         unsigned long                ep;
1062         struct bfd_link_hash_entry * h;
1063         
1064         insn = bfd_get_16 (input_bfd, hit_data);
1065
1066         /* Get the value of __ep.  */
1067         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1068         if (h == (struct bfd_link_hash_entry *) NULL
1069             || h->type != bfd_link_hash_defined)
1070           return bfd_reloc_continue;    /* Actually this indicates that __ep could not be found. */
1071
1072         ep = (h->u.def.value
1073               + h->u.def.section->output_section->vma
1074               + h->u.def.section->output_offset);
1075         
1076         value -= ep;
1077         value += ((insn & 0x7f) << 1);
1078         
1079         if ((long) value > 0xfe || (long) value < 0)
1080           return bfd_reloc_overflow;
1081         
1082         insn &= 0xff80;
1083         insn |= (value >> 1);
1084         
1085         bfd_put_16 (input_bfd, insn, hit_data);
1086         return bfd_reloc_ok;
1087       }
1088     
1089     case R_V850_TDA_7_7_OFFSET:
1090       {
1091         unsigned long                ep;
1092         struct bfd_link_hash_entry * h;
1093         
1094         insn = bfd_get_16 (input_bfd, hit_data);
1095
1096         /* Get the value of __ep.  */
1097         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1098         if (h == (struct bfd_link_hash_entry *) NULL
1099             || h->type != bfd_link_hash_defined)
1100           return bfd_reloc_continue;  /* Actually this indicates that __ep could not be found. */
1101
1102         ep = (h->u.def.value
1103               + h->u.def.section->output_section->vma
1104               + h->u.def.section->output_offset);
1105         value -= ep;
1106         
1107         value += insn & 0x7f;
1108         
1109         if ((long) value > 0x7f || (long) value < 0)
1110           return bfd_reloc_overflow;
1111         
1112         insn &= 0xff80;
1113         insn |= value;
1114         bfd_put_16 (input_bfd, insn, hit_data);
1115         return bfd_reloc_ok;
1116       }
1117     
1118 /* start-sanitize-v850e */
1119     case R_V850_TDA_4_5_OFFSET:
1120       {
1121         unsigned long                ep;
1122         struct bfd_link_hash_entry * h;
1123         
1124         /* Get the value of __ep.  */
1125         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1126         if (h == (struct bfd_link_hash_entry *) NULL
1127             || h->type != bfd_link_hash_defined)
1128           return bfd_reloc_continue;  /* Actually this indicates that __ep could not be found. */
1129
1130         ep = (h->u.def.value
1131               + h->u.def.section->output_section->vma
1132               + h->u.def.section->output_offset);
1133         value -= ep;
1134         
1135         insn = bfd_get_16 (input_bfd, hit_data);
1136
1137         value += ((insn & 0xf) << 1);
1138         
1139         if ((long) value > 0x1e || (long) value < 0)
1140           return bfd_reloc_overflow;
1141         
1142         insn &= 0xfff0;
1143         insn |= (value >> 1);
1144         bfd_put_16 (input_bfd, insn, hit_data);
1145         return bfd_reloc_ok;
1146       }
1147     
1148     case R_V850_TDA_4_4_OFFSET:
1149       {
1150         unsigned long                ep;
1151         struct bfd_link_hash_entry * h;
1152         
1153         /* Get the value of __ep.  */
1154         h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true);
1155         if (h == (struct bfd_link_hash_entry *) NULL
1156             || h->type != bfd_link_hash_defined)
1157           return bfd_reloc_continue;  /* Actually this indicates that __ep could not be found. */
1158
1159         ep = (h->u.def.value
1160               + h->u.def.section->output_section->vma
1161               + h->u.def.section->output_offset);
1162         value -= ep;
1163         
1164         insn = bfd_get_16 (input_bfd, hit_data);
1165
1166         value += insn & 0xf;
1167         
1168         if ((long) value > 0xf || (long) value < 0)
1169           return bfd_reloc_overflow;
1170         
1171         insn &= 0xfff0;
1172         insn |= value;
1173         bfd_put_16 (input_bfd, insn, hit_data);
1174         return bfd_reloc_ok;
1175       }
1176     
1177     case R_V850_SDA_16_16_SPLIT_OFFSET:
1178       {
1179         unsigned long                gp;
1180         struct bfd_link_hash_entry * h;
1181
1182         /* Get the value of __gp.  */
1183         h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true);
1184         if (h == (struct bfd_link_hash_entry *) NULL
1185             || h->type != bfd_link_hash_defined)
1186           return bfd_reloc_other;
1187
1188         gp = (h->u.def.value
1189               + h->u.def.section->output_section->vma
1190               + h->u.def.section->output_offset);
1191         
1192         value -= sym_sec->output_section->vma;
1193         value -= (gp - sym_sec->output_section->vma);
1194
1195         insn = bfd_get_32 (input_bfd, hit_data);
1196         
1197         value += ((insn & 0xfffe0000) >> 16);
1198         value += ((insn & 0x20) >> 5);
1199           
1200         if ((long)value > 0x7fff || (long)value < -0x8000)
1201           return bfd_reloc_overflow;
1202
1203         insn &= 0x0001ffdf;
1204         insn |= (value & 1) << 5;
1205         insn |= (value & ~1) << 16;
1206         
1207         bfd_put_32 (input_bfd, insn, hit_data);
1208         return bfd_reloc_ok;
1209       }
1210
1211     case R_V850_ZDA_16_16_SPLIT_OFFSET:
1212       insn = bfd_get_32 (input_bfd, hit_data);
1213         
1214       value -= sym_sec->output_section->vma;
1215       value += ((insn & 0xfffe0000) >> 16);
1216       value += ((insn & 0x20) >> 5);
1217           
1218       if ((long)value > 0x7fff || (long)value < -0x8000)
1219         return bfd_reloc_overflow;
1220       
1221       insn &= 0x0001ffdf;
1222       insn |= (value & 1) << 5;
1223       insn |= (value & ~1) << 16;
1224       
1225       bfd_put_32 (input_bfd, insn, hit_data);
1226       return bfd_reloc_ok;
1227
1228 /* end-sanitize-v850e */
1229     
1230     
1231     case R_V850_NONE:
1232       return bfd_reloc_ok;
1233
1234     default:
1235       return bfd_reloc_notsupported;
1236     }
1237 }
1238
1239 \f
1240 /* Relocate an V850 ELF section.  */
1241 static boolean
1242 v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
1243                            contents, relocs, local_syms, local_sections)
1244      bfd *                  output_bfd;
1245      struct bfd_link_info * info;
1246      bfd *                  input_bfd;
1247      asection *             input_section;
1248      bfd_byte *             contents;
1249      Elf_Internal_Rela *    relocs;
1250      Elf_Internal_Sym *     local_syms;
1251      asection **            local_sections;
1252 {
1253   Elf_Internal_Shdr *           symtab_hdr;
1254   struct elf_link_hash_entry ** sym_hashes;
1255   Elf_Internal_Rela *           rel;
1256   Elf_Internal_Rela *           relend;
1257
1258   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
1259   sym_hashes = elf_sym_hashes (input_bfd);
1260
1261   rel    = relocs;
1262   relend = relocs + input_section->reloc_count;
1263   for (; rel < relend; rel++)
1264     {
1265       int                          r_type;
1266       reloc_howto_type *           howto;
1267       unsigned long                r_symndx;
1268       Elf_Internal_Sym *           sym;
1269       asection *                   sec;
1270       struct elf_link_hash_entry * h;
1271       bfd_vma                      relocation;
1272       bfd_reloc_status_type        r;
1273
1274       r_symndx = ELF32_R_SYM (rel->r_info);
1275       r_type   = ELF32_R_TYPE (rel->r_info);
1276       howto    = v850_elf_howto_table + r_type;
1277
1278       if (info->relocateable)
1279         {
1280           /* This is a relocateable link.  We don't have to change
1281              anything, unless the reloc is against a section symbol,
1282              in which case we have to adjust according to where the
1283              section symbol winds up in the output section.  */
1284           if (r_symndx < symtab_hdr->sh_info)
1285             {
1286               sym = local_syms + r_symndx;
1287               if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
1288                 {
1289                   sec = local_sections[r_symndx];
1290                   rel->r_addend += sec->output_offset + sym->st_value;
1291                 }
1292             }
1293
1294           continue;
1295         }
1296
1297       /* This is a final link.  */
1298       h = NULL;
1299       sym = NULL;
1300       sec = NULL;
1301       if (r_symndx < symtab_hdr->sh_info)
1302         {
1303           sym = local_syms + r_symndx;
1304           sec = local_sections[r_symndx];
1305           relocation = (sec->output_section->vma
1306                         + sec->output_offset
1307                         + sym->st_value);
1308 #if 0
1309           {
1310             char * name;
1311             name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name);
1312             name = (name == NULL) ? "<none>" : name;
1313 fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x rel %x\n", sec->name, name, sym->st_name,
1314          sec->output_section->vma, sec->output_offset, sym->st_value, rel->r_addend, rel);
1315           }
1316 #endif
1317         }
1318       else
1319         {
1320           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
1321           
1322           while (h->root.type == bfd_link_hash_indirect
1323                  || h->root.type == bfd_link_hash_warning)
1324             h = (struct elf_link_hash_entry *) h->root.u.i.link;
1325           
1326           if (h->root.type == bfd_link_hash_defined
1327               || h->root.type == bfd_link_hash_defweak)
1328             {
1329               sec = h->root.u.def.section;
1330               relocation = (h->root.u.def.value
1331                             + sec->output_section->vma
1332                             + sec->output_offset);
1333             }
1334           else if (h->root.type == bfd_link_hash_undefweak)
1335             relocation = 0;
1336           else
1337             {
1338               if (! ((*info->callbacks->undefined_symbol)
1339                      (info, h->root.root.string, input_bfd,
1340                       input_section, rel->r_offset)))
1341                 return false;
1342               relocation = 0;
1343             }
1344         }
1345
1346       /* FIXME: We should use the addend, but the COFF relocations
1347          don't.  */
1348       r = v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
1349                                         input_section,
1350                                         contents, rel->r_offset,
1351                                         relocation, rel->r_addend,
1352                                         info, sec, h == NULL);
1353
1354       if (r != bfd_reloc_ok)
1355         {
1356           const char * name;
1357           const char * msg = (const char *)0;
1358
1359           if (h != NULL)
1360             name = h->root.root.string;
1361           else
1362             {
1363               name = (bfd_elf_string_from_elf_section
1364                       (input_bfd, symtab_hdr->sh_link, sym->st_name));
1365               if (name == NULL || *name == '\0')
1366                 name = bfd_section_name (input_bfd, sec);
1367             }
1368
1369           switch (r)
1370             {
1371             case bfd_reloc_overflow:
1372               if (! ((*info->callbacks->reloc_overflow)
1373                      (info, name, howto->name, (bfd_vma) 0,
1374                       input_bfd, input_section, rel->r_offset)))
1375                 return false;
1376               break;
1377
1378             case bfd_reloc_undefined:
1379               fprintf (stderr, "undef2 %s\n", name );
1380               if (! ((*info->callbacks->undefined_symbol)
1381                      (info, name, input_bfd, input_section,
1382                       rel->r_offset)))
1383                 return false;
1384               break;
1385
1386             case bfd_reloc_outofrange:
1387               msg = "internal error: out of range error";
1388               goto common_error;
1389
1390             case bfd_reloc_notsupported:
1391               msg = "internal error: unsupported relocation error";
1392               goto common_error;
1393
1394             case bfd_reloc_dangerous:
1395               msg = "internal error: dangerous relocation";
1396               goto common_error;
1397
1398             case bfd_reloc_other:
1399               msg = "could not locate special linker symbol __gp";
1400               goto common_error;
1401
1402             case bfd_reloc_continue:
1403               msg = "could not locate special linker symbol __ep";
1404               goto common_error;
1405
1406             default:
1407               msg = "internal error: unknown error";
1408               /* fall through */
1409
1410             common_error:
1411               if (!((*info->callbacks->warning)
1412                     (info, msg, name, input_bfd, input_section,
1413                      rel->r_offset)))
1414                 return false;
1415               break;
1416             }
1417         }
1418     }
1419
1420   return true;
1421 }
1422
1423 /* Set the right machine number.  */
1424 static boolean
1425 v850_elf_object_p (abfd)
1426      bfd *abfd;
1427 {
1428   switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
1429     {
1430     default:
1431     case E_V850_ARCH:   (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, 0); break;
1432 /* start-sanitize-v850e */
1433     case E_V850E_ARCH:  (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e); break;
1434 /* end-sanitize-v850e */
1435 /* start-sanitize-v850eq */
1436     case E_V850EQ_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850eq); break;
1437 /* end-sanitize-v850eq */
1438     }
1439 }
1440
1441 /* Store the machine number in the flags field.  */
1442 void
1443 v850_elf_final_write_processing (abfd, linker)
1444      bfd *   abfd;
1445      boolean linker;
1446 {
1447   unsigned long val;
1448
1449   switch (bfd_get_mach (abfd))
1450     {
1451     default:
1452     case 0: val = E_V850_ARCH; break;
1453 /* start-sanitize-v850e */
1454     case bfd_mach_v850e: val = E_V850E_ARCH; break;
1455 /* end-sanitize-v850e */
1456 /* start-sanitize-v850eq */
1457     case bfd_mach_v850eq: val = E_V850EQ_ARCH;  break;
1458 /* end-sanitize-v850eq */
1459     }
1460
1461   elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH;
1462   elf_elfheader (abfd)->e_flags |= val;
1463 }
1464
1465 /* Function to keep V850 specific file flags. */
1466 boolean
1467 v850_elf_set_private_flags (abfd, flags)
1468      bfd *    abfd;
1469      flagword flags;
1470 {
1471   BFD_ASSERT (!elf_flags_init (abfd)
1472               || elf_elfheader (abfd)->e_flags == flags);
1473
1474   elf_elfheader (abfd)->e_flags = flags;
1475   elf_flags_init (abfd) = true;
1476   return true;
1477 }
1478
1479 /* Copy backend specific data from one object module to another */
1480 boolean
1481 v850_elf_copy_private_bfd_data (ibfd, obfd)
1482      bfd * ibfd;
1483      bfd * obfd;
1484 {
1485   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1486       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1487     return true;
1488
1489   BFD_ASSERT (!elf_flags_init (obfd)
1490               || (elf_elfheader (obfd)->e_flags
1491                   == elf_elfheader (ibfd)->e_flags));
1492
1493   elf_gp (obfd) = elf_gp (ibfd);
1494   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
1495   elf_flags_init (obfd) = true;
1496   return true;
1497 }
1498
1499 /* Merge backend specific data from an object file to the output
1500    object file when linking.  */
1501 boolean
1502 v850_elf_merge_private_bfd_data (ibfd, obfd)
1503      bfd * ibfd;
1504      bfd * obfd;
1505 {
1506   flagword old_flags;
1507   flagword new_flags;
1508
1509   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1510       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1511     return true;
1512
1513   new_flags = elf_elfheader (ibfd)->e_flags;
1514   old_flags = elf_elfheader (obfd)->e_flags;
1515
1516   if (! elf_flags_init (obfd))
1517     {
1518       elf_flags_init (obfd) = true;
1519       elf_elfheader (obfd)->e_flags = new_flags;
1520
1521       if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
1522           && bfd_get_arch_info (obfd)->the_default)
1523         {
1524           return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
1525         }
1526
1527       return true;
1528     }
1529
1530   /* Check flag compatibility.  */
1531
1532   if (new_flags == old_flags)
1533     return true;
1534
1535   if ((new_flags & EF_V850_ARCH) != (old_flags & EF_V850_ARCH))
1536     {
1537       _bfd_error_handler ("%s: Architecture mismatch with previous modules",
1538              bfd_get_filename (ibfd));
1539       bfd_set_error (bfd_error_bad_value);
1540       return false;
1541     }
1542
1543   return true;
1544 }
1545 /* Display the flags field */
1546
1547 static boolean
1548 v850_elf_print_private_bfd_data (abfd, ptr)
1549      bfd *   abfd;
1550      PTR     ptr;
1551 {
1552   FILE * file = (FILE *) ptr;
1553   
1554   BFD_ASSERT (abfd != NULL && ptr != NULL)
1555   
1556   fprintf (file, "private flags = %x", elf_elfheader (abfd)->e_flags);
1557   
1558   switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
1559     {
1560     default:
1561     case E_V850_ARCH: fprintf (file, ": v850 architecture"); break;
1562 /* start-sanitize-v850e */
1563     case E_V850E_ARCH: fprintf (file, ": v850e architecture"); break;
1564 /* end-sanitize-v850e */
1565 /* start-sanitize-v850eq */
1566     case E_V850EQ_ARCH: fprintf (file, ": v850eq architecture"); break;
1567 /* end-sanitize-v850eq */
1568     }
1569   
1570   fputc ('\n', file);
1571   
1572   return true;
1573 }
1574 \f
1575 #define TARGET_LITTLE_SYM                       bfd_elf32_v850_vec
1576 #define TARGET_LITTLE_NAME                      "elf32-v850"
1577 #define ELF_ARCH                                bfd_arch_v850
1578 #define ELF_MACHINE_CODE                        EM_CYGNUS_V850
1579 #define ELF_MAXPAGESIZE                         0x1000
1580         
1581 #define elf_info_to_howto                       0
1582 #define elf_info_to_howto_rel                   v850_elf_info_to_howto_rel
1583 #define elf_backend_check_relocs                v850_elf_check_relocs
1584 #define elf_backend_relocate_section            v850_elf_relocate_section
1585 #define elf_backend_object_p                    v850_elf_object_p
1586 #define elf_backend_final_write_processing      v850_elf_final_write_processing
1587 #define bfd_elf32_bfd_is_local_label_name       v850_elf_is_local_label_name
1588 #define bfd_elf32_bfd_reloc_type_lookup         v850_elf_reloc_type_lookup
1589 #define bfd_elf32_bfd_copy_private_bfd_data     v850_elf_copy_private_bfd_data
1590 #define bfd_elf32_bfd_merge_private_bfd_data    v850_elf_merge_private_bfd_data
1591 #define bfd_elf32_bfd_set_private_flags         v850_elf_set_private_flags
1592 #define bfd_elf32_bfd_print_private_bfd_data    v850_elf_print_private_bfd_data
1593
1594 #define elf_symbol_leading_char                 '_'
1595
1596 #include "elf32-target.h"