]> Git Repo - binutils.git/blob - bfd/elf32-m32r.c
* elf32-i386.c (elf_i386_adjust_dynamic_symbol): Generate a COPY
[binutils.git] / bfd / elf32-m32r.c
1 /* M32R-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 #include "bfd.h"
21 #include "sysdep.h"
22 #include "libbfd.h"
23 #include "elf-bfd.h"
24 #include "elf/m32r.h"
25
26 static bfd_reloc_status_type m32r_elf_10_pcrel_reloc
27   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
28 static bfd_reloc_status_type m32r_elf_hi16_slo_reloc
29   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
30 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
31   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
32 static void m32r_info_to_howto_rel
33   PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
34
35 /* Use REL instead of RELA to save space.  */
36 #define USE_REL
37
38 static reloc_howto_type elf_m32r_howto_table[] =
39 {
40   /* This reloc does nothing.  */
41   HOWTO (R_M32R_NONE,           /* type */
42          0,                     /* rightshift */
43          2,                     /* size (0 = byte, 1 = short, 2 = long) */
44          32,                    /* bitsize */
45          false,                 /* pc_relative */
46          0,                     /* bitpos */
47          complain_overflow_bitfield, /* complain_on_overflow */
48          bfd_elf_generic_reloc, /* special_function */
49          "R_M32R_NONE",         /* name */
50          false,                 /* partial_inplace */
51          0,                     /* src_mask */
52          0,                     /* dst_mask */
53          false),                /* pcrel_offset */
54
55   /* A 16 bit absolute relocation.  */
56   HOWTO (R_M32R_16,             /* type */
57          0,                     /* rightshift */
58          1,                     /* size (0 = byte, 1 = short, 2 = long) */
59          16,                    /* bitsize */
60          false,                 /* pc_relative */
61          0,                     /* bitpos */
62          complain_overflow_bitfield, /* complain_on_overflow */
63          bfd_elf_generic_reloc, /* special_function */
64          "R_M32R_16",           /* name */
65          true,                  /* partial_inplace */
66          0xffff,                /* src_mask */
67          0xffff,                /* dst_mask */
68          false),                /* pcrel_offset */
69
70   /* A 32 bit absolute relocation.  */
71   HOWTO (R_M32R_32,             /* type */
72          0,                     /* rightshift */
73          2,                     /* size (0 = byte, 1 = short, 2 = long) */
74          32,                    /* bitsize */
75          false,                 /* pc_relative */
76          0,                     /* bitpos */
77          complain_overflow_bitfield, /* complain_on_overflow */
78          bfd_elf_generic_reloc, /* special_function */
79          "R_M32R_32",           /* name */
80          true,                  /* partial_inplace */
81          0xffffffff,            /* src_mask */
82          0xffffffff,            /* dst_mask */
83          false),                /* pcrel_offset */
84
85   /* A 24 bit address.  */
86   HOWTO (R_M32R_24,             /* type */
87          0,                     /* rightshift */
88          2,                     /* size (0 = byte, 1 = short, 2 = long) */
89          24,                    /* bitsize */
90          false,                 /* pc_relative */
91          0,                     /* bitpos */
92          complain_overflow_unsigned, /* complain_on_overflow */
93          bfd_elf_generic_reloc, /* special_function */
94          "R_M32R_24",           /* name */
95          true,                  /* partial_inplace */
96          0xffffff,              /* src_mask */
97          0xffffff,              /* dst_mask */
98          false),                /* pcrel_offset */
99
100   /* An PC Relative 10-bit relocation, shifted by 2.
101      This reloc is complicated because relocations are relative to pc & -4.
102      i.e. branches in the right insn slot use the address of the left insn
103      slot for pc.  */
104   HOWTO (R_M32R_10_PCREL,       /* type */
105          2,                     /* rightshift */
106          1,                     /* size (0 = byte, 1 = short, 2 = long) */
107          10,                    /* bitsize */
108          true,                  /* pc_relative */
109          0,                     /* bitpos */
110          complain_overflow_signed, /* complain_on_overflow */
111          m32r_elf_10_pcrel_reloc, /* special_function */
112          "R_M32R_10_PCREL",     /* name */
113          false,                 /* partial_inplace */
114          0xff,                  /* src_mask */
115          0xff,                  /* dst_mask */
116          true),                 /* pcrel_offset */
117
118   /* A relative 18 bit relocation, right shifted by 2.  */
119   HOWTO (R_M32R_18_PCREL,       /* type */
120          2,                     /* rightshift */
121          2,                     /* size (0 = byte, 1 = short, 2 = long) */
122          18,                    /* bitsize */
123          true,                  /* pc_relative */
124          0,                     /* bitpos */
125          complain_overflow_signed, /* complain_on_overflow */
126          bfd_elf_generic_reloc, /* special_function */
127          "R_M32R_18_PCREL",     /* name */
128          false,                 /* partial_inplace */
129          0xffff,                /* src_mask */
130          0xffff,                /* dst_mask */
131          true),                 /* pcrel_offset */
132
133   /* A relative 26 bit relocation, right shifted by 2.  */
134   HOWTO (R_M32R_26_PCREL,       /* type */
135          2,                     /* rightshift */
136          2,                     /* size (0 = byte, 1 = short, 2 = long) */
137          26,                    /* bitsize */
138          true,                  /* pc_relative */
139          0,                     /* bitpos */
140          complain_overflow_signed, /* complain_on_overflow */
141          bfd_elf_generic_reloc, /* special_function */
142          "R_M32R_26_PCREL",     /* name */
143          false,                 /* partial_inplace */
144          0xffffff,              /* src_mask */
145          0xffffff,              /* dst_mask */
146          true),                 /* pcrel_offset */
147
148   /* High 16 bits of address when lower 16 is or'd in.  */
149   HOWTO (R_M32R_HI16_ULO,       /* type */
150          16,                    /* rightshift */
151          2,                     /* size (0 = byte, 1 = short, 2 = long) */
152          16,                    /* bitsize */
153          false,                 /* pc_relative */
154          0,                     /* bitpos */
155          complain_overflow_dont, /* complain_on_overflow */
156          bfd_elf_generic_reloc, /* special_function */
157          "R_M32R_HI16_ULO",     /* name */
158          true,                  /* partial_inplace */
159          0x0000ffff,            /* src_mask */
160          0x0000ffff,            /* dst_mask */
161          false),                /* pcrel_offset */
162
163   /* High 16 bits of address when lower 16 is added in.  */
164   HOWTO (R_M32R_HI16_SLO,       /* type */
165          16,                    /* rightshift */
166          2,                     /* size (0 = byte, 1 = short, 2 = long) */
167          16,                    /* bitsize */
168          false,                 /* pc_relative */
169          0,                     /* bitpos */
170          complain_overflow_dont, /* complain_on_overflow */
171          m32r_elf_hi16_slo_reloc, /* special_function */
172          "R_M32R_HI16_SLO",     /* name */
173          true,                  /* partial_inplace */
174          0x0000ffff,            /* src_mask */
175          0x0000ffff,            /* dst_mask */
176          false),                /* pcrel_offset */
177
178   /* Lower 16 bits of address.  */
179   HOWTO (R_M32R_LO16,           /* type */
180          0,                     /* rightshift */
181          2,                     /* size (0 = byte, 1 = short, 2 = long) */
182          16,                    /* bitsize */
183          false,                 /* pc_relative */
184          0,                     /* bitpos */
185          complain_overflow_dont, /* complain_on_overflow */
186          bfd_elf_generic_reloc, /* special_function */
187          "R_M32R_LO16",         /* name */
188          true,                  /* partial_inplace */
189          0x0000ffff,            /* src_mask */
190          0x0000ffff,            /* dst_mask */
191          false),                /* pcrel_offset */
192 };
193
194 /* Handle the R_M32R_10_PCREL reloc.  */
195
196 static bfd_reloc_status_type
197 m32r_elf_10_pcrel_reloc (abfd, reloc_entry, symbol, data,
198                          input_section, output_bfd, error_message)
199      bfd *abfd;
200      arelent *reloc_entry;
201      asymbol *symbol;
202      PTR data;
203      asection *input_section;
204      bfd *output_bfd;
205      char **error_message;
206 {
207   bfd_vma relocation;
208   bfd_vma x;
209   reloc_howto_type *howto;
210
211   /* This part if from bfd_elf_generic_reloc.  */
212   if (output_bfd != (bfd *) NULL
213       && (symbol->flags & BSF_SECTION_SYM) == 0
214       && (! reloc_entry->howto->partial_inplace
215           || reloc_entry->addend == 0))
216     {
217       reloc_entry->address += input_section->output_offset;
218       return bfd_reloc_ok;
219     }
220
221   if (output_bfd != NULL)
222     {
223       /* FIXME: See bfd_perform_relocation.  Is this right?  */
224       return bfd_reloc_continue;
225     }
226
227   /* The rest is copied from bfd_perform_relocation, modified to suit us.  */
228
229   if (reloc_entry->address > input_section->_cooked_size)
230     return bfd_reloc_outofrange;
231
232   relocation = (symbol->value
233                 + symbol->section->output_section->vma
234                 + symbol->section->output_offset);
235   relocation += reloc_entry->addend;
236   relocation -= (input_section->output_section->vma
237                  + input_section->output_offset);
238   relocation -= (reloc_entry->address & -4L);
239
240   howto = reloc_entry->howto;
241   x = bfd_get_16 (abfd, (char *) data + reloc_entry->address);
242   relocation >>= howto->rightshift;
243   relocation <<= howto->bitpos;
244   x = (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask);
245   bfd_put_16 (abfd, x, (char *) data + reloc_entry->address);
246
247   if ((bfd_signed_vma) relocation < - 0x80
248       || (bfd_signed_vma) relocation > 0x7f)
249     return bfd_reloc_overflow;
250   else
251     return bfd_reloc_ok;
252 }
253
254 /* Handle the R_M32R_HI16_SLO reloc.
255    This reloc is used in load/store with displacement instructions.
256    The lower 16 bits are sign extended when added to the high 16 bytes
257    so if the lower 16 bits are negative (bit 15 == 1) then we must add one
258    to the high 16 bytes (which will get subtracted off when the low 16 bits
259    are added.  */
260
261 static bfd_reloc_status_type
262 m32r_elf_hi16_slo_reloc (abfd, reloc_entry, symbol, data,
263                          input_section, output_bfd, error_message)
264      bfd *abfd;
265      arelent *reloc_entry;
266      asymbol *symbol;
267      PTR data;
268      asection *input_section;
269      bfd *output_bfd;
270      char **error_message;
271 {
272   bfd_vma relocation;
273   unsigned long x;
274   int bit15;
275   reloc_howto_type *howto;
276
277   /* This part if from bfd_elf_generic_reloc.  */
278   if (output_bfd != (bfd *) NULL
279       && (symbol->flags & BSF_SECTION_SYM) == 0
280       && (! reloc_entry->howto->partial_inplace
281           || reloc_entry->addend == 0))
282     {
283       reloc_entry->address += input_section->output_offset;
284       return bfd_reloc_ok;
285     }
286
287   if (output_bfd != NULL)
288     {
289       /* FIXME: See bfd_perform_relocation.  Is this right?  */
290       return bfd_reloc_continue;
291     }
292
293   /* The rest is copied from bfd_perform_relocation, modified to suit us.  */
294
295   if (reloc_entry->address > input_section->_cooked_size)
296     return bfd_reloc_outofrange;
297
298   relocation = (symbol->value
299                 + symbol->section->output_section->vma
300                 + symbol->section->output_offset);
301   relocation += reloc_entry->addend;
302
303   howto = reloc_entry->howto;
304   x = bfd_get_32 (abfd, (char *) data + reloc_entry->address);
305   bit15 = relocation & 0x8000;
306   relocation >>= howto->rightshift;
307   if (bit15)
308     relocation += 1;
309   relocation <<= howto->bitpos;
310   x = (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask);
311   bfd_put_32 (abfd, x, (char *) data + reloc_entry->address);
312
313   return bfd_reloc_ok;
314 }
315
316 /* Map BFD reloc types to M32R ELF reloc types.  */
317
318 struct m32r_reloc_map
319 {
320   unsigned char bfd_reloc_val;
321   unsigned char elf_reloc_val;
322 };
323
324 static const struct m32r_reloc_map m32r_reloc_map[] =
325 {
326   { BFD_RELOC_NONE, R_M32R_NONE },
327   { BFD_RELOC_16, R_M32R_16 },
328   { BFD_RELOC_32, R_M32R_32 },
329   { BFD_RELOC_M32R_24, R_M32R_24 },
330   { BFD_RELOC_M32R_10_PCREL, R_M32R_10_PCREL },
331   { BFD_RELOC_M32R_18_PCREL, R_M32R_18_PCREL },
332   { BFD_RELOC_M32R_26_PCREL, R_M32R_26_PCREL },
333   { BFD_RELOC_M32R_HI16_ULO, R_M32R_HI16_ULO },
334   { BFD_RELOC_M32R_HI16_SLO, R_M32R_HI16_SLO },
335   { BFD_RELOC_M32R_LO16, R_M32R_LO16 },
336 };
337
338 static reloc_howto_type *
339 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
340      bfd *abfd;
341      bfd_reloc_code_real_type code;
342 {
343   unsigned int i;
344
345   for (i = 0;
346        i < sizeof (m32r_reloc_map) / sizeof (struct m32r_reloc_map);
347        i++)
348     {
349       if (m32r_reloc_map[i].bfd_reloc_val == code)
350         return &elf_m32r_howto_table[m32r_reloc_map[i].elf_reloc_val];
351     }
352
353   return NULL;
354 }
355
356 /* Set the howto pointer for an M32R ELF reloc.  */
357
358 static void
359 m32r_info_to_howto_rel (abfd, cache_ptr, dst)
360      bfd *abfd;
361      arelent *cache_ptr;
362      Elf32_Internal_Rel *dst;
363 {
364   unsigned int r_type;
365
366   r_type = ELF32_R_TYPE (dst->r_info);
367   BFD_ASSERT (r_type < (unsigned int) R_M32R_max);
368   cache_ptr->howto = &elf_m32r_howto_table[r_type];
369 }
370
371 #define ELF_ARCH                bfd_arch_m32r
372 #define ELF_MACHINE_CODE        EM_CYGNUS_M32R
373 #define ELF_MAXPAGESIZE         0x1000
374
375 #define TARGET_BIG_SYM          bfd_elf32_m32r_vec
376 #define TARGET_BIG_NAME         "elf32-m32r"
377
378 #define elf_info_to_howto       0
379 #define elf_info_to_howto_rel   m32r_info_to_howto_rel
380 #define elf_backend_object_p    0
381 #define elf_backend_final_write_processing      0
382
383 #include "elf32-target.h"
This page took 0.046768 seconds and 4 git commands to generate.