OSDN Git Service

2004-07-09 H.J. Lu <hongjiu.lu@intel.com>
[pf3gnuchains/sourceware.git] / bfd / elf32-crx.c
1 /* BFD back-end for National Semiconductor's CRX ELF
2    Copyright 2004 Free Software Foundation, Inc.
3    Written by Tomer Levi, NSC, Israel.
4
5    This file is part of BFD, the Binary File Descriptor library.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "bfdlink.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/crx.h"
27
28 static reloc_howto_type *elf_crx_reloc_type_lookup
29   (bfd *, bfd_reloc_code_real_type);
30 static void elf_crx_info_to_howto
31   (bfd *, arelent *, Elf_Internal_Rela *);
32 static bfd_boolean elf32_crx_relax_delete_bytes
33   (bfd *, asection *, bfd_vma, int);
34 static bfd_reloc_status_type crx_elf_final_link_relocate
35   (reloc_howto_type *, bfd *, bfd *, asection *,
36    bfd_byte *, bfd_vma, bfd_vma, bfd_vma,
37    struct bfd_link_info *, asection *, int);
38 static bfd_boolean elf32_crx_relocate_section
39   (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
40    Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
41 static asection * elf32_crx_gc_mark_hook
42   (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
43    struct elf_link_hash_entry *, Elf_Internal_Sym *);
44 static bfd_boolean elf32_crx_gc_sweep_hook
45   (bfd *, struct bfd_link_info *, asection *,
46    const Elf_Internal_Rela *);
47 static bfd_boolean elf32_crx_relax_section
48   (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
49 static bfd_byte * elf32_crx_get_relocated_section_contents
50   (bfd *, struct bfd_link_info *, struct bfd_link_order *,
51    bfd_byte *, bfd_boolean, asymbol **);
52
53 /* crx_reloc_map array maps BFD relocation enum into a CRGAS relocation type.  */
54
55 struct crx_reloc_map
56 {
57   bfd_reloc_code_real_type bfd_reloc_enum; /* BFD relocation enum.  */
58   unsigned short crx_reloc_type;           /* CRX relocation type.  */
59 };
60
61 static const struct crx_reloc_map crx_reloc_map[R_CRX_MAX] =
62 {
63   {BFD_RELOC_NONE,          R_CRX_NONE},
64   {BFD_RELOC_CRX_REL4,      R_CRX_REL4},
65   {BFD_RELOC_CRX_REL8,      R_CRX_REL8},
66   {BFD_RELOC_CRX_REL8_CMP,  R_CRX_REL8_CMP},
67   {BFD_RELOC_CRX_REL16,     R_CRX_REL16},
68   {BFD_RELOC_CRX_REL24,     R_CRX_REL24},
69   {BFD_RELOC_CRX_REL32,     R_CRX_REL32},
70   {BFD_RELOC_CRX_REGREL12,  R_CRX_REGREL12},
71   {BFD_RELOC_CRX_REGREL22,  R_CRX_REGREL22},
72   {BFD_RELOC_CRX_REGREL28,  R_CRX_REGREL28},
73   {BFD_RELOC_CRX_REGREL32,  R_CRX_REGREL32},
74   {BFD_RELOC_CRX_ABS16,     R_CRX_ABS16},
75   {BFD_RELOC_CRX_ABS32,     R_CRX_ABS32},
76   {BFD_RELOC_CRX_NUM8,      R_CRX_NUM8},
77   {BFD_RELOC_CRX_NUM16,     R_CRX_NUM16},
78   {BFD_RELOC_CRX_NUM32,     R_CRX_NUM32},
79   {BFD_RELOC_CRX_IMM16,     R_CRX_IMM16},
80   {BFD_RELOC_CRX_IMM32,     R_CRX_IMM32}
81 };
82
83 static reloc_howto_type crx_elf_howto_table[] =
84 {
85   HOWTO (R_CRX_NONE,            /* type */
86          0,                     /* rightshift */
87          2,                     /* size */
88          32,                    /* bitsize */
89          FALSE,                 /* pc_relative */
90          0,                     /* bitpos */
91          complain_overflow_dont,/* complain_on_overflow */
92          bfd_elf_generic_reloc, /* special_function */
93          "R_CRX_NONE",          /* name */
94          FALSE,                 /* partial_inplace */
95          0,                     /* src_mask */
96          0,                     /* dst_mask */
97          FALSE),                /* pcrel_offset */
98
99   HOWTO (R_CRX_REL4,            /* type */
100          1,                     /* rightshift */
101          0,                     /* size */
102          4,                     /* bitsize */
103          TRUE,                  /* pc_relative */
104          0,                     /* bitpos */
105          complain_overflow_bitfield,/* complain_on_overflow */
106          bfd_elf_generic_reloc, /* special_function */
107          "R_CRX_REL4",          /* name */
108          FALSE,                 /* partial_inplace */
109          0xf,                   /* src_mask */
110          0xf,                   /* dst_mask */
111          FALSE),                /* pcrel_offset */
112
113   HOWTO (R_CRX_REL8,            /* type */
114          1,                     /* rightshift */
115          0,                     /* size */
116          8,                     /* bitsize */
117          TRUE,                  /* pc_relative */
118          0,                     /* bitpos */
119          complain_overflow_bitfield,/* complain_on_overflow */
120          bfd_elf_generic_reloc, /* special_function */
121          "R_CRX_REL8",          /* name */
122          FALSE,                 /* partial_inplace */
123          0xff,                  /* src_mask */
124          0xff,                  /* dst_mask */
125          FALSE),                /* pcrel_offset */
126
127   HOWTO (R_CRX_REL8_CMP,        /* type */
128          1,                     /* rightshift */
129          0,                     /* size */
130          8,                     /* bitsize */
131          TRUE,                  /* pc_relative */
132          0,                     /* bitpos */
133          complain_overflow_bitfield,/* complain_on_overflow */
134          bfd_elf_generic_reloc, /* special_function */
135          "R_CRX_REL8_CMP",      /* name */
136          FALSE,                 /* partial_inplace */
137          0xff,                  /* src_mask */
138          0xff,                  /* dst_mask */
139          FALSE),                /* pcrel_offset */
140
141   HOWTO (R_CRX_REL16,           /* type */
142          1,                     /* rightshift */
143          1,                     /* size */
144          16,                    /* bitsize */
145          TRUE,                  /* pc_relative */
146          0,                     /* bitpos */
147          complain_overflow_bitfield,/* complain_on_overflow */
148          bfd_elf_generic_reloc, /* special_function */
149          "R_CRX_REL16",         /* name */
150          FALSE,                 /* partial_inplace */
151          0xffff,                /* src_mask */
152          0xffff,                /* dst_mask */
153          FALSE),                /* pcrel_offset */
154
155   HOWTO (R_CRX_REL24,           /* type */
156          1,                     /* rightshift */
157          2,                     /* size */
158          24,                    /* bitsize */
159          TRUE,                  /* pc_relative */
160          0,                     /* bitpos */
161          complain_overflow_bitfield,/* complain_on_overflow */
162          bfd_elf_generic_reloc, /* special_function */
163          "R_CRX_REL24",         /* name */
164          FALSE,                 /* partial_inplace */
165          0xffffff,              /* src_mask */
166          0xffffff,              /* dst_mask */
167          FALSE),                /* pcrel_offset */
168
169   HOWTO (R_CRX_REL32,           /* type */
170          1,                     /* rightshift */
171          2,                     /* size */
172          32,                    /* bitsize */
173          TRUE,                  /* pc_relative */
174          0,                     /* bitpos */
175          complain_overflow_bitfield,/* complain_on_overflow */
176          bfd_elf_generic_reloc, /* special_function */
177          "R_CRX_REL32",         /* name */
178          FALSE,                 /* partial_inplace */
179          0xffffffff,            /* src_mask */
180          0xffffffff,            /* dst_mask */
181          FALSE),                /* pcrel_offset */
182
183   HOWTO (R_CRX_REGREL12,        /* type */
184          0,                     /* rightshift */
185          1,                     /* size */
186          12,                    /* bitsize */
187          FALSE,                 /* pc_relative */
188          0,                     /* bitpos */
189          complain_overflow_bitfield,/* complain_on_overflow */
190          bfd_elf_generic_reloc, /* special_function */
191          "R_CRX_REGREL12",      /* name */
192          FALSE,                 /* partial_inplace */
193          0xfff,                 /* src_mask */
194          0xfff,                 /* dst_mask */
195          FALSE),                /* pcrel_offset */
196
197   HOWTO (R_CRX_REGREL22,        /* type */
198          0,                     /* rightshift */
199          2,                     /* size */
200          22,                    /* bitsize */
201          FALSE,                 /* pc_relative */
202          0,                     /* bitpos */
203          complain_overflow_bitfield,/* complain_on_overflow */
204          bfd_elf_generic_reloc, /* special_function */
205          "R_CRX_REGREL22",      /* name */
206          FALSE,                 /* partial_inplace */
207          0x3fffff,              /* src_mask */
208          0x3fffff,              /* dst_mask */
209          FALSE),                /* pcrel_offset */
210
211   HOWTO (R_CRX_REGREL28,        /* type */
212          0,                     /* rightshift */
213          2,                     /* size */
214          28,                    /* bitsize */
215          FALSE,                 /* pc_relative */
216          0,                     /* bitpos */
217          complain_overflow_bitfield,/* complain_on_overflow */
218          bfd_elf_generic_reloc, /* special_function */
219          "R_CRX_REGREL28",      /* name */
220          FALSE,                 /* partial_inplace */
221          0xfffffff,             /* src_mask */
222          0xfffffff,             /* dst_mask */
223          FALSE),                /* pcrel_offset */
224
225   HOWTO (R_CRX_REGREL32,        /* type */
226          0,                     /* rightshift */
227          2,                     /* size */
228          32,                    /* bitsize */
229          FALSE,                 /* pc_relative */
230          0,                     /* bitpos */
231          complain_overflow_bitfield,/* complain_on_overflow */
232          bfd_elf_generic_reloc, /* special_function */
233          "R_CRX_REGREL32",      /* name */
234          FALSE,                 /* partial_inplace */
235          0xffffffff,            /* src_mask */
236          0xffffffff,            /* dst_mask */
237          FALSE),                /* pcrel_offset */
238
239   HOWTO (R_CRX_ABS16,           /* type */
240          0,                     /* rightshift */
241          1,                     /* size */
242          16,                    /* bitsize */
243          FALSE,                 /* pc_relative */
244          0,                     /* bitpos */
245          complain_overflow_bitfield,/* complain_on_overflow */
246          bfd_elf_generic_reloc, /* special_function */
247          "R_CRX_ABS16",         /* name */
248          FALSE,                 /* partial_inplace */
249          0xffff,                /* src_mask */
250          0xffff,                /* dst_mask */
251          FALSE),                /* pcrel_offset */
252
253   HOWTO (R_CRX_ABS32,           /* type */
254          0,                     /* rightshift */
255          2,                     /* size */
256          32,                    /* bitsize */
257          FALSE,                 /* pc_relative */
258          0,                     /* bitpos */
259          complain_overflow_bitfield,/* complain_on_overflow */
260          bfd_elf_generic_reloc, /* special_function */
261          "R_CRX_ABS32",         /* name */
262          FALSE,                 /* partial_inplace */
263          0xffffffff,            /* src_mask */
264          0xffffffff,            /* dst_mask */
265          FALSE),                /* pcrel_offset */
266
267   HOWTO (R_CRX_NUM8,            /* type */
268          0,                     /* rightshift */
269          0,                     /* size */
270          8,                     /* bitsize */
271          FALSE,                 /* pc_relative */
272          0,                     /* bitpos */
273          complain_overflow_bitfield,/* complain_on_overflow */
274          bfd_elf_generic_reloc, /* special_function */
275          "R_CRX_NUM8",          /* name */
276          FALSE,                 /* partial_inplace */
277          0xff,                  /* src_mask */
278          0xff,                  /* dst_mask */
279          FALSE),                /* pcrel_offset */
280
281   HOWTO (R_CRX_NUM16,           /* type */
282          0,                     /* rightshift */
283          1,                     /* size */
284          16,                    /* bitsize */
285          FALSE,                 /* pc_relative */
286          0,                     /* bitpos */
287          complain_overflow_bitfield,/* complain_on_overflow */
288          bfd_elf_generic_reloc, /* special_function */
289          "R_CRX_NUM16",         /* name */
290          FALSE,                 /* partial_inplace */
291          0xffff,                /* src_mask */
292          0xffff,                /* dst_mask */
293          FALSE),                /* pcrel_offset */
294
295   HOWTO (R_CRX_NUM32,           /* type */
296          0,                     /* rightshift */
297          2,                     /* size */
298          32,                    /* bitsize */
299          FALSE,                 /* pc_relative */
300          0,                     /* bitpos */
301          complain_overflow_bitfield,/* complain_on_overflow */
302          bfd_elf_generic_reloc, /* special_function */
303          "R_CRX_NUM32",         /* name */
304          FALSE,                 /* partial_inplace */
305          0xffffffff,            /* src_mask */
306          0xffffffff,            /* dst_mask */
307          FALSE),                /* pcrel_offset */
308
309   HOWTO (R_CRX_IMM16,           /* type */
310          0,                     /* rightshift */
311          1,                     /* size */
312          16,                    /* bitsize */
313          FALSE,                 /* pc_relative */
314          0,                     /* bitpos */
315          complain_overflow_bitfield,/* complain_on_overflow */
316          bfd_elf_generic_reloc, /* special_function */
317          "R_CRX_IMM16",         /* name */
318          FALSE,                 /* partial_inplace */
319          0xffff,                /* src_mask */
320          0xffff,                /* dst_mask */
321          FALSE),                /* pcrel_offset */
322
323   HOWTO (R_CRX_IMM32,           /* type */
324          0,                     /* rightshift */
325          2,                     /* size */
326          32,                    /* bitsize */
327          FALSE,                 /* pc_relative */
328          0,                     /* bitpos */
329          complain_overflow_bitfield,/* complain_on_overflow */
330          bfd_elf_generic_reloc, /* special_function */
331          "R_CRX_IMM32",         /* name */
332          FALSE,                 /* partial_inplace */
333          0xffffffff,            /* src_mask */
334          0xffffffff,            /* dst_mask */
335          FALSE)                 /* pcrel_offset */
336 };
337
338 /* Retrieve a howto ptr using a BFD reloc_code.  */
339
340 static reloc_howto_type *
341 elf_crx_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
342                            bfd_reloc_code_real_type code)
343 {
344   unsigned int i;
345
346   for (i = 0; i < R_CRX_MAX; i++)
347     if (code == crx_reloc_map[i].bfd_reloc_enum)
348       return &crx_elf_howto_table[crx_reloc_map[i].crx_reloc_type];
349
350   printf ("This relocation Type is not supported -0x%x\n", code);
351   return 0;
352 }
353
354 /* Retrieve a howto ptr using an internal relocation entry.  */
355
356 static void
357 elf_crx_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
358                        Elf_Internal_Rela *dst)
359 {
360   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
361   BFD_ASSERT (r_type < (unsigned int) R_CRX_MAX);
362   cache_ptr->howto = &crx_elf_howto_table[r_type];
363 }
364
365 /* Perform a relocation as part of a final link.  */
366
367 static bfd_reloc_status_type
368 crx_elf_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd,
369                              bfd *output_bfd ATTRIBUTE_UNUSED,
370                              asection *input_section, bfd_byte *contents,
371                              bfd_vma offset, bfd_vma Rvalue, bfd_vma addend,
372                              struct bfd_link_info *info ATTRIBUTE_UNUSED,
373                              asection *sec ATTRIBUTE_UNUSED,
374                              int is_local ATTRIBUTE_UNUSED)
375 {
376   unsigned short r_type = howto->type;
377   bfd_byte *hit_data = contents + offset;
378   bfd_vma reloc_bits, check;
379
380   switch (r_type)
381     {
382      case R_CRX_IMM16:
383      case R_CRX_IMM32:
384      case R_CRX_ABS16:
385      case R_CRX_ABS32:
386      case R_CRX_REL8_CMP:
387      case R_CRX_REL16:
388      case R_CRX_REL24:
389      case R_CRX_REL32:
390      case R_CRX_REGREL12:
391      case R_CRX_REGREL22:
392      case R_CRX_REGREL28:
393      case R_CRX_REGREL32:
394        /* 'hit_data' is relative to the start of the instruction, not the
395           relocation offset. Advance it to account for the exact offset.  */
396        hit_data += 2;
397        break;
398
399      case R_CRX_REL4:
400        /* This relocation type is used only in 'Branch if Equal to 0'
401           instructions and requires special handling.  */
402        Rvalue -= 1;
403        break;
404
405      case R_CRX_NONE:
406        return bfd_reloc_ok;
407        break;
408
409      default:
410        break;
411     }
412
413   if (howto->pc_relative)
414     {
415       /* Subtract the address of the section containing the location.  */
416       Rvalue -= (input_section->output_section->vma
417                  + input_section->output_offset);
418       /* Subtract the position of the location within the section.  */
419       Rvalue -= offset;
420     }
421
422   /* Add in supplied addend.  */
423   Rvalue += addend;
424
425   /* Complain if the bitfield overflows, whether it is considered
426      as signed or unsigned.  */
427   check = Rvalue >> howto->rightshift;
428
429   /* Assumes two's complement.  This expression avoids
430      overflow if howto->bitsize is the number of bits in
431      bfd_vma.  */
432   reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
433
434   if (((bfd_vma) check & ~reloc_bits) != 0
435       && (((bfd_vma) check & ~reloc_bits)
436           != (-(bfd_vma) 1 & ~reloc_bits)))
437     {
438       /* The above right shift is incorrect for a signed
439          value.  See if turning on the upper bits fixes the
440          overflow.  */
441       if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
442         {
443           check |= ((bfd_vma) - 1
444                     & ~((bfd_vma) - 1
445                         >> howto->rightshift));
446           if (((bfd_vma) check & ~reloc_bits)
447               != (-(bfd_vma) 1 & ~reloc_bits))
448             return bfd_reloc_overflow;
449         }
450       else
451         return bfd_reloc_overflow;
452     }
453
454   /* Drop unwanted bits from the value we are relocating to.  */
455   Rvalue >>= (bfd_vma) howto->rightshift;
456
457   /* Apply dst_mask to select only relocatable part of the insn.  */
458   Rvalue &= howto->dst_mask;
459
460   switch (howto->size)
461     {
462      case 0:
463        if (r_type == R_CRX_REL4)
464          {
465            Rvalue <<= 4;
466            Rvalue |= (bfd_get_8 (input_bfd, hit_data) & 0x0f);
467          }
468
469        bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
470        break;
471
472      case 1:
473        if (r_type == R_CRX_REGREL12)
474          Rvalue |= (bfd_get_16 (input_bfd, hit_data) & 0xf000);
475
476        bfd_put_16 (input_bfd, Rvalue, hit_data);
477        break;
478
479      case 2:
480        if (r_type == R_CRX_REL24
481            || r_type == R_CRX_REGREL22
482            || r_type == R_CRX_REGREL28)
483          Rvalue |= (((bfd_get_16 (input_bfd, hit_data) << 16) |
484                       bfd_get_16 (input_bfd, hit_data + 2)) & ~howto->dst_mask);
485
486        if (r_type == R_CRX_NUM32)
487          /* Relocation on DATA is purely little-endian, that is, for a
488             multi-byte datum, the lowest address in memory contains the
489             little end of the datum, that is, the least significant byte.
490             Therefore we use BFD's byte Putting functions.  */
491          bfd_put_32 (input_bfd, Rvalue, hit_data);
492        else
493          /* Relocation on INSTRUCTIONS is different : Instructions are
494             word-addressable, that is, each word itself is arranged according
495             to little-endian convention, whereas the words are arranged with
496             respect to one another in BIG ENDIAN fashion.
497             When there is an immediate value that spans a word boundary, it is
498             split in a big-endian way with respect to the words.  */
499          {
500            bfd_put_16 (input_bfd, (Rvalue >> 16) & 0xffff, hit_data);
501            bfd_put_16 (input_bfd, Rvalue & 0xffff, hit_data + 2);
502          }
503      break;
504
505      default:
506        return bfd_reloc_notsupported;
507     }
508
509   return bfd_reloc_ok;
510 }
511
512 /* Delete some bytes from a section while relaxing.  */
513
514 static bfd_boolean
515 elf32_crx_relax_delete_bytes (bfd *abfd, asection *sec,
516                               bfd_vma addr, int count)
517 {
518   Elf_Internal_Shdr *symtab_hdr;
519   unsigned int sec_shndx;
520   bfd_byte *contents;
521   Elf_Internal_Rela *irel, *irelend;
522   Elf_Internal_Rela *irelalign;
523   bfd_vma toaddr;
524   Elf_Internal_Sym *isym;
525   Elf_Internal_Sym *isymend;
526   struct elf_link_hash_entry **sym_hashes;
527   struct elf_link_hash_entry **end_hashes;
528   unsigned int symcount;
529
530   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
531
532   contents = elf_section_data (sec)->this_hdr.contents;
533
534   /* The deletion must stop at the next ALIGN reloc for an aligment
535      power larger than the number of bytes we are deleting.  */
536
537   irelalign = NULL;
538   toaddr = sec->size;
539
540   irel = elf_section_data (sec)->relocs;
541   irelend = irel + sec->reloc_count;
542
543   /* Actually delete the bytes.  */
544   memmove (contents + addr, contents + addr + count,
545            (size_t) (toaddr - addr - count));
546   sec->size -= count;
547
548   /* Adjust all the relocs.  */
549   for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
550     {
551       /* Get the new reloc address.  */
552       if ((irel->r_offset > addr
553            && irel->r_offset < toaddr))
554         irel->r_offset -= count;
555     }
556
557   /* Adjust the local symbols defined in this section.  */
558   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
559   isym = (Elf_Internal_Sym *) symtab_hdr->contents;
560   for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
561     {
562       if (isym->st_shndx == sec_shndx
563           && isym->st_value > addr
564           && isym->st_value < toaddr)
565         isym->st_value -= count;
566     }
567
568   /* Now adjust the global symbols defined in this section.  */
569   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
570               - symtab_hdr->sh_info);
571   sym_hashes = elf_sym_hashes (abfd);
572   end_hashes = sym_hashes + symcount;
573
574   for (; sym_hashes < end_hashes; sym_hashes++)
575     {
576       struct elf_link_hash_entry *sym_hash = *sym_hashes;
577
578       if ((sym_hash->root.type == bfd_link_hash_defined
579            || sym_hash->root.type == bfd_link_hash_defweak)
580           && sym_hash->root.u.def.section == sec
581           && sym_hash->root.u.def.value > addr
582           && sym_hash->root.u.def.value < toaddr)
583         sym_hash->root.u.def.value -= count;
584     }
585
586   return TRUE;
587 }
588
589 /* This is a version of bfd_generic_get_relocated_section_contents
590    which uses elf32_crx_relocate_section.  */
591
592 static bfd_byte *
593 elf32_crx_get_relocated_section_contents (bfd *output_bfd,
594                                           struct bfd_link_info *link_info,
595                                           struct bfd_link_order *link_order,
596                                           bfd_byte *data,
597                                           bfd_boolean relocatable,
598                                           asymbol **symbols)
599 {
600   Elf_Internal_Shdr *symtab_hdr;
601   asection *input_section = link_order->u.indirect.section;
602   bfd *input_bfd = input_section->owner;
603   asection **sections = NULL;
604   Elf_Internal_Rela *internal_relocs = NULL;
605   Elf_Internal_Sym *isymbuf = NULL;
606
607   /* We only need to handle the case of relaxing, or of having a
608      particular set of section contents, specially.  */
609   if (relocatable
610       || elf_section_data (input_section)->this_hdr.contents == NULL)
611     return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
612                                                        link_order, data,
613                                                        relocatable,
614                                                        symbols);
615
616   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
617
618   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
619           (size_t) input_section->size);
620
621   if ((input_section->flags & SEC_RELOC) != 0
622       && input_section->reloc_count > 0)
623     {
624       Elf_Internal_Sym *isym;
625       Elf_Internal_Sym *isymend;
626       asection **secpp;
627       bfd_size_type amt;
628
629       internal_relocs = (_bfd_elf_link_read_relocs
630                          (input_bfd, input_section, (PTR) NULL,
631                           (Elf_Internal_Rela *) NULL, FALSE));
632       if (internal_relocs == NULL)
633         goto error_return;
634
635       if (symtab_hdr->sh_info != 0)
636         {
637           isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
638           if (isymbuf == NULL)
639             isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
640                                             symtab_hdr->sh_info, 0,
641                                             NULL, NULL, NULL);
642           if (isymbuf == NULL)
643             goto error_return;
644         }
645
646       amt = symtab_hdr->sh_info;
647       amt *= sizeof (asection *);
648       sections = bfd_malloc (amt);
649       if (sections == NULL && amt != 0)
650         goto error_return;
651
652       isymend = isymbuf + symtab_hdr->sh_info;
653       for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
654         {
655           asection *isec;
656
657           if (isym->st_shndx == SHN_UNDEF)
658             isec = bfd_und_section_ptr;
659           else if (isym->st_shndx == SHN_ABS)
660             isec = bfd_abs_section_ptr;
661           else if (isym->st_shndx == SHN_COMMON)
662             isec = bfd_com_section_ptr;
663           else
664             isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
665
666           *secpp = isec;
667         }
668
669       if (! elf32_crx_relocate_section (output_bfd, link_info, input_bfd,
670                                      input_section, data, internal_relocs,
671                                      isymbuf, sections))
672         goto error_return;
673
674       if (sections != NULL)
675         free (sections);
676       if (isymbuf != NULL
677           && symtab_hdr->contents != (unsigned char *) isymbuf)
678         free (isymbuf);
679       if (elf_section_data (input_section)->relocs != internal_relocs)
680         free (internal_relocs);
681     }
682
683   return data;
684
685  error_return:
686   if (sections != NULL)
687     free (sections);
688   if (isymbuf != NULL
689       && symtab_hdr->contents != (unsigned char *) isymbuf)
690     free (isymbuf);
691   if (internal_relocs != NULL
692       && elf_section_data (input_section)->relocs != internal_relocs)
693     free (internal_relocs);
694   return NULL;
695 }
696
697 /* Relocate a CRX ELF section.  */
698
699 static bfd_boolean
700 elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
701                             bfd *input_bfd, asection *input_section,
702                             bfd_byte *contents, Elf_Internal_Rela *relocs,
703                             Elf_Internal_Sym *local_syms,
704                             asection **local_sections)
705 {
706   Elf_Internal_Shdr *symtab_hdr;
707   struct elf_link_hash_entry **sym_hashes;
708   Elf_Internal_Rela *rel, *relend;
709
710   if (info->relocatable)
711     return TRUE;
712
713   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
714   sym_hashes = elf_sym_hashes (input_bfd);
715
716   rel = relocs;
717   relend = relocs + input_section->reloc_count;
718   for (; rel < relend; rel++)
719     {
720       int r_type;
721       reloc_howto_type *howto;
722       unsigned long r_symndx;
723       Elf_Internal_Sym *sym;
724       asection *sec;
725       struct elf_link_hash_entry *h;
726       bfd_vma relocation;
727       bfd_reloc_status_type r;
728
729       r_symndx = ELF32_R_SYM (rel->r_info);
730       r_type = ELF32_R_TYPE (rel->r_info);
731       howto = crx_elf_howto_table + (r_type);
732
733       h = NULL;
734       sym = NULL;
735       sec = NULL;
736       if (r_symndx < symtab_hdr->sh_info)
737         {
738           sym = local_syms + r_symndx;
739           sec = local_sections[r_symndx];
740           relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
741         }
742       else
743         {
744           bfd_boolean unresolved_reloc, warned;
745
746           RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
747                                    r_symndx, symtab_hdr, sym_hashes,
748                                    h, sec, relocation,
749                                    unresolved_reloc, warned);
750         }
751
752       r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd,
753                                         input_section,
754                                         contents, rel->r_offset,
755                                         relocation, rel->r_addend,
756                                         info, sec, h == NULL);
757
758       if (r != bfd_reloc_ok)
759         {
760           const char *name;
761           const char *msg = (const char *) 0;
762
763           if (h != NULL)
764             name = h->root.root.string;
765           else
766             {
767               name = (bfd_elf_string_from_elf_section
768                       (input_bfd, symtab_hdr->sh_link, sym->st_name));
769               if (name == NULL || *name == '\0')
770                 name = bfd_section_name (input_bfd, sec);
771             }
772
773           switch (r)
774             {
775              case bfd_reloc_overflow:
776                if (!((*info->callbacks->reloc_overflow)
777                      (info, name, howto->name, (bfd_vma) 0,
778                       input_bfd, input_section, rel->r_offset)))
779                  return FALSE;
780                break;
781
782              case bfd_reloc_undefined:
783                if (!((*info->callbacks->undefined_symbol)
784                      (info, name, input_bfd, input_section,
785                       rel->r_offset, TRUE)))
786                  return FALSE;
787                break;
788
789              case bfd_reloc_outofrange:
790                msg = _("internal error: out of range error");
791                goto common_error;
792
793              case bfd_reloc_notsupported:
794                msg = _("internal error: unsupported relocation error");
795                goto common_error;
796
797              case bfd_reloc_dangerous:
798                msg = _("internal error: dangerous error");
799                goto common_error;
800
801              default:
802                msg = _("internal error: unknown error");
803                /* Fall through.  */
804
805              common_error:
806                if (!((*info->callbacks->warning)
807                      (info, msg, name, input_bfd, input_section,
808                       rel->r_offset)))
809                  return FALSE;
810                break;
811             }
812         }
813     }
814
815   return TRUE;
816 }
817
818 /* This function handles relaxing for the CRX.
819
820    There's quite a few relaxing opportunites available on the CRX:
821
822         * bal/bcond:32 -> bal/bcond:16                             2 bytes
823         * bcond:16 -> bcond:8                                      2 bytes
824         * cmpbcond:24 -> cmpbcond:8                                2 bytes
825         * arithmetic imm32 -> arithmetic imm16                     2 bytes
826
827    Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
828
829 static bfd_boolean
830 elf32_crx_relax_section (bfd *abfd, asection *sec,
831                          struct bfd_link_info *link_info, bfd_boolean *again)
832 {
833   Elf_Internal_Shdr *symtab_hdr;
834   Elf_Internal_Rela *internal_relocs;
835   Elf_Internal_Rela *irel, *irelend;
836   bfd_byte *contents = NULL;
837   Elf_Internal_Sym *isymbuf = NULL;
838
839   /* Assume nothing changes.  */
840   *again = FALSE;
841
842   /* We don't have to do anything for a relocatable link, if
843      this section does not have relocs, or if this is not a
844      code section.  */
845   if (link_info->relocatable
846       || (sec->flags & SEC_RELOC) == 0
847       || sec->reloc_count == 0
848       || (sec->flags & SEC_CODE) == 0)
849     return TRUE;
850
851   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
852
853   /* Get a copy of the native relocations.  */
854   internal_relocs = (_bfd_elf_link_read_relocs
855                      (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
856                       link_info->keep_memory));
857   if (internal_relocs == NULL)
858     goto error_return;
859
860   /* Walk through them looking for relaxing opportunities.  */
861   irelend = internal_relocs + sec->reloc_count;
862   for (irel = internal_relocs; irel < irelend; irel++)
863     {
864       bfd_vma symval;
865
866       /* If this isn't something that can be relaxed, then ignore
867          this reloc.  */
868       if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL32
869           && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL16
870           && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL24
871           && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_IMM32)
872         continue;
873
874       /* Get the section contents if we haven't done so already.  */
875       if (contents == NULL)
876         {
877           /* Get cached copy if it exists.  */
878           if (elf_section_data (sec)->this_hdr.contents != NULL)
879             contents = elf_section_data (sec)->this_hdr.contents;
880           /* Go get them off disk.  */
881           else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
882             goto error_return;
883         }
884
885       /* Read this BFD's local symbols if we haven't done so already.  */
886       if (isymbuf == NULL && symtab_hdr->sh_info != 0)
887         {
888           isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
889           if (isymbuf == NULL)
890             isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
891                                             symtab_hdr->sh_info, 0,
892                                             NULL, NULL, NULL);
893           if (isymbuf == NULL)
894             goto error_return;
895         }
896
897       /* Get the value of the symbol referred to by the reloc.  */
898       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
899         {
900           /* A local symbol.  */
901           Elf_Internal_Sym *isym;
902           asection *sym_sec;
903
904           isym = isymbuf + ELF32_R_SYM (irel->r_info);
905           if (isym->st_shndx == SHN_UNDEF)
906             sym_sec = bfd_und_section_ptr;
907           else if (isym->st_shndx == SHN_ABS)
908             sym_sec = bfd_abs_section_ptr;
909           else if (isym->st_shndx == SHN_COMMON)
910             sym_sec = bfd_com_section_ptr;
911           else
912             sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
913           symval = (isym->st_value
914                     + sym_sec->output_section->vma
915                     + sym_sec->output_offset);
916         }
917       else
918         {
919           unsigned long indx;
920           struct elf_link_hash_entry *h;
921
922           /* An external symbol.  */
923           indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
924           h = elf_sym_hashes (abfd)[indx];
925           BFD_ASSERT (h != NULL);
926
927           if (h->root.type != bfd_link_hash_defined
928               && h->root.type != bfd_link_hash_defweak)
929             /* This appears to be a reference to an undefined
930                symbol.  Just ignore it--it will be caught by the
931                regular reloc processing.  */
932             continue;
933
934           symval = (h->root.u.def.value
935                     + h->root.u.def.section->output_section->vma
936                     + h->root.u.def.section->output_offset);
937         }
938
939       /* For simplicity of coding, we are going to modify the section
940          contents, the section relocs, and the BFD symbol table.  We
941          must tell the rest of the code not to free up this
942          information.  It would be possible to instead create a table
943          of changes which have to be made, as is done in coff-mips.c;
944          that would be more work, but would require less memory when
945          the linker is run.  */
946
947       /* Try to turn a 32bit pc-relative branch/call into
948          a 16bit pc-relative branch/call.  */
949       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL32)
950         {
951           bfd_vma value = symval;
952
953           /* Deal with pc-relative gunk.  */
954           value -= (sec->output_section->vma + sec->output_offset);
955           value -= irel->r_offset;
956           value += irel->r_addend;
957
958           /* See if the value will fit in 16 bits, note the high value is
959              0xfffe + 2 as the target will be two bytes closer if we are
960              able to relax.  */
961           if ((long) value < 0x10000 && (long) value > -0x10002)
962             {
963               unsigned short code;
964
965               /* Get the opcode.  */
966               code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
967
968               /* Verify it's a 'bal'/'bcond' and fix the opcode.  */
969               if ((code & 0xfff0) == 0x3170)
970                 bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
971               else if ((code & 0xf0ff) == 0x707f)
972                 bfd_put_8 (abfd, 0x7e, contents + irel->r_offset);
973               else
974                 continue;
975
976               /* Note that we've changed the relocs, section contents, etc.  */
977               elf_section_data (sec)->relocs = internal_relocs;
978               elf_section_data (sec)->this_hdr.contents = contents;
979               symtab_hdr->contents = (unsigned char *) isymbuf;
980
981               /* Fix the relocation's type.  */
982               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
983                                            R_CRX_REL16);
984
985               /* Delete two bytes of data.  */
986               if (!elf32_crx_relax_delete_bytes (abfd, sec,
987                                                    irel->r_offset + 2, 2))
988                 goto error_return;
989
990               /* That will change things, so, we should relax again.
991                  Note that this is not required, and it may be slow.  */
992               *again = TRUE;
993             }
994         }
995
996       /* Try to turn a 16bit pc-relative branch into an
997          8bit pc-relative branch.  */
998       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL16)
999         {
1000           bfd_vma value = symval;
1001
1002           /* Deal with pc-relative gunk.  */
1003           value -= (sec->output_section->vma + sec->output_offset);
1004           value -= irel->r_offset;
1005           value += irel->r_addend;
1006
1007           /* See if the value will fit in 8 bits, note the high value is
1008              0xfc + 2 as the target will be two bytes closer if we are
1009              able to relax.  */
1010           if ((long) value < 0xfe && (long) value > -0x100)
1011             {
1012               unsigned short code;
1013
1014               /* Get the opcode.  */
1015               code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1016
1017               /* Verify it's a 'bcond' opcode.  */
1018               if ((code & 0xf0ff) != 0x707e)
1019                 continue;
1020
1021               /* Note that we've changed the relocs, section contents, etc.  */
1022               elf_section_data (sec)->relocs = internal_relocs;
1023               elf_section_data (sec)->this_hdr.contents = contents;
1024               symtab_hdr->contents = (unsigned char *) isymbuf;
1025
1026               /* Fix the relocation's type.  */
1027               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1028                                            R_CRX_REL8);
1029
1030               /* Delete two bytes of data.  */
1031               if (!elf32_crx_relax_delete_bytes (abfd, sec,
1032                                                    irel->r_offset + 2, 2))
1033                 goto error_return;
1034
1035               /* That will change things, so, we should relax again.
1036                  Note that this is not required, and it may be slow.  */
1037               *again = TRUE;
1038             }
1039         }
1040
1041       /* Try to turn a 24bit pc-relative cmp&branch into
1042          an 8bit pc-relative cmp&branch.  */
1043       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL24)
1044         {
1045           bfd_vma value = symval;
1046
1047           /* Deal with pc-relative gunk.  */
1048           value -= (sec->output_section->vma + sec->output_offset);
1049           value -= irel->r_offset;
1050           value += irel->r_addend;
1051
1052           /* See if the value will fit in 8 bits, note the high value is
1053              0x7e + 2 as the target will be two bytes closer if we are
1054              able to relax.  */
1055           if ((long) value < 0x100 && (long) value > -0x100)
1056             {
1057               unsigned short code;
1058
1059               /* Get the opcode.  */
1060               code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1061
1062               /* Verify it's a 'cmp&branch' opcode.  */
1063               if ((code & 0xfff0) != 0x3180 && (code & 0xfff0) != 0x3190
1064                && (code & 0xfff0) != 0x31a0 && (code & 0xfff0) != 0x31c0
1065                && (code & 0xfff0) != 0x31d0 && (code & 0xfff0) != 0x31e0)
1066                 continue;
1067
1068               /* Note that we've changed the relocs, section contents, etc.  */
1069               elf_section_data (sec)->relocs = internal_relocs;
1070               elf_section_data (sec)->this_hdr.contents = contents;
1071               symtab_hdr->contents = (unsigned char *) isymbuf;
1072
1073               /* Fix the opcode.  */
1074               bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1075
1076               /* Fix the relocation's type.  */
1077               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1078                                            R_CRX_REL8_CMP);
1079
1080               /* Delete two bytes of data.  */
1081               if (!elf32_crx_relax_delete_bytes (abfd, sec,
1082                                                    irel->r_offset + 4, 2))
1083                 goto error_return;
1084
1085               /* That will change things, so, we should relax again.
1086                  Note that this is not required, and it may be slow.  */
1087               *again = TRUE;
1088             }
1089         }
1090
1091       /* Try to turn a 32bit immediate address into
1092          a 16bit immediate address.  */
1093       if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_IMM32)
1094         {
1095           bfd_vma value = symval;
1096
1097           /* See if the value will fit in 16 bits.  */
1098           if ((long) value < 0x7fff && (long) value > -0x8000)
1099             {
1100               unsigned short code;
1101
1102               /* Get the opcode.  */
1103               code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1104
1105               /* Verify it's a 'arithmetic double'.  */
1106               if ((code & 0xf0f0) != 0x20f0)
1107                 continue;
1108
1109               /* Note that we've changed the relocs, section contents, etc.  */
1110               elf_section_data (sec)->relocs = internal_relocs;
1111               elf_section_data (sec)->this_hdr.contents = contents;
1112               symtab_hdr->contents = (unsigned char *) isymbuf;
1113
1114               /* Fix the opcode.  */
1115               bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
1116
1117               /* Fix the relocation's type.  */
1118               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1119                                            R_CRX_IMM16);
1120
1121               /* Delete two bytes of data.  */
1122               if (!elf32_crx_relax_delete_bytes (abfd, sec,
1123                                                    irel->r_offset + 2, 2))
1124                 goto error_return;
1125
1126               /* That will change things, so, we should relax again.
1127                  Note that this is not required, and it may be slow.  */
1128               *again = TRUE;
1129             }
1130         }
1131     }
1132
1133   if (isymbuf != NULL
1134       && symtab_hdr->contents != (unsigned char *) isymbuf)
1135     {
1136       if (! link_info->keep_memory)
1137         free (isymbuf);
1138       else
1139         {
1140           /* Cache the symbols for elf_link_input_bfd.  */
1141           symtab_hdr->contents = (unsigned char *) isymbuf;
1142         }
1143     }
1144
1145   if (contents != NULL
1146       && elf_section_data (sec)->this_hdr.contents != contents)
1147     {
1148       if (! link_info->keep_memory)
1149         free (contents);
1150       else
1151         {
1152           /* Cache the section contents for elf_link_input_bfd.  */
1153           elf_section_data (sec)->this_hdr.contents = contents;
1154         }
1155     }
1156
1157   if (internal_relocs != NULL
1158       && elf_section_data (sec)->relocs != internal_relocs)
1159     free (internal_relocs);
1160
1161   return TRUE;
1162
1163  error_return:
1164   if (isymbuf != NULL
1165       && symtab_hdr->contents != (unsigned char *) isymbuf)
1166     free (isymbuf);
1167   if (contents != NULL
1168       && elf_section_data (sec)->this_hdr.contents != contents)
1169     free (contents);
1170   if (internal_relocs != NULL
1171       && elf_section_data (sec)->relocs != internal_relocs)
1172     free (internal_relocs);
1173
1174   return FALSE;
1175 }
1176
1177 static asection *
1178 elf32_crx_gc_mark_hook (asection *sec,
1179                         struct bfd_link_info *info ATTRIBUTE_UNUSED,
1180                         Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
1181                         struct elf_link_hash_entry *h,
1182                         Elf_Internal_Sym *sym)
1183 {
1184   if (h == NULL)
1185     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
1186
1187   switch (h->root.type)
1188     {
1189     case bfd_link_hash_defined:
1190     case bfd_link_hash_defweak:
1191       return h->root.u.def.section;
1192
1193     case bfd_link_hash_common:
1194       return h->root.u.c.p->section;
1195
1196     default:
1197       return NULL;
1198     }
1199 }
1200
1201 /* Update the got entry reference counts for the section being removed.  */
1202
1203 static bfd_boolean
1204 elf32_crx_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
1205                          struct bfd_link_info *info ATTRIBUTE_UNUSED,
1206                          asection *sec ATTRIBUTE_UNUSED,
1207                          const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
1208 {
1209   /* We don't support garbage collection of GOT and PLT relocs yet.  */
1210   return TRUE;
1211 }
1212
1213 /* Definitions for setting CRX target vector.  */
1214 #define TARGET_LITTLE_SYM               bfd_elf32_crx_vec
1215 #define TARGET_LITTLE_NAME              "elf32-crx"
1216 #define ELF_ARCH                        bfd_arch_crx
1217 #define ELF_MACHINE_CODE                EM_CRX
1218 #define ELF_MAXPAGESIZE                 0x1
1219 #define elf_symbol_leading_char         '_'
1220
1221 #define bfd_elf32_bfd_reloc_type_lookup elf_crx_reloc_type_lookup
1222 #define elf_info_to_howto               elf_crx_info_to_howto
1223 #define elf_info_to_howto_rel           0
1224 #define elf_backend_relocate_section    elf32_crx_relocate_section
1225 #define bfd_elf32_bfd_relax_section     elf32_crx_relax_section
1226 #define bfd_elf32_bfd_get_relocated_section_contents \
1227                                 elf32_crx_get_relocated_section_contents
1228 #define elf_backend_gc_mark_hook        elf32_crx_gc_mark_hook
1229 #define elf_backend_gc_sweep_hook       elf32_crx_gc_sweep_hook
1230 #define elf_backend_can_gc_sections     1
1231 #define elf_backend_rela_normal         1
1232
1233 #include "elf32-target.h"