* cpu-h8300.c (h8300_scan, compatible): Prototype.
[platform/upstream/binutils.git] / bfd / elf32-h8300.c
1 /* Generic support for 32-bit ELF
2    Copyright 1993, 1995, 1998, 1999 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/h8.h"
25
26 static reloc_howto_type *elf32_h8_reloc_type_lookup
27   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
28 static void elf32_h8_info_to_howto
29   PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
30
31 /* This does not include any relocation information, but should be
32    good enough for GDB or objdump to read the file.  */
33
34 static reloc_howto_type h8_elf_howto_table[] =
35 {
36 #define R_H8_NONE_X 0
37   HOWTO (R_H8_NONE,             /* type */
38          0,                     /* rightshift */
39          0,                     /* size (0 = byte, 1 = short, 2 = long) */
40          0,                     /* bitsize */
41          false,                 /* pc_relative */
42          0,                     /* bitpos */
43          complain_overflow_dont, /* complain_on_overflow */
44          NULL,                  /* special_function */
45          "R_H8_NONE",           /* name */
46          false,                 /* partial_inplace */
47          0,                     /* src_mask */
48          0,                     /* dst_mask */
49          false),                /* pcrel_offset */
50 #define R_H8_DIR32_X (R_H8_NONE_X + 1)
51   HOWTO (R_H8_DIR32,            /* type */
52          0,                     /* rightshift */
53          2,                     /* size (0 = byte, 1 = short, 2 = long) */
54          32,                    /* bitsize */
55          false,                 /* pc_relative */
56          0,                     /* bitpos */
57          complain_overflow_dont, /* complain_on_overflow */
58          NULL,                  /* special_function */
59          "R_H8_DIR32",          /* name */
60          false,                 /* partial_inplace */
61          0,                     /* src_mask */
62          0xffffffff,            /* dst_mask */
63          false),                /* pcrel_offset */
64 #define R_H8_DIR16_X (R_H8_DIR32_X + 1)
65   HOWTO (R_H8_DIR16,            /* type */
66          0,                     /* rightshift */
67          1,                     /* size (0 = byte, 1 = short, 2 = long) */
68          16,                    /* bitsize */
69          false,                 /* pc_relative */
70          0,                     /* bitpos */
71          complain_overflow_dont, /* complain_on_overflow */
72          NULL,                  /* special_function */
73          "R_H8_DIR16",          /* name */
74          false,                 /* partial_inplace */
75          0,                     /* src_mask */
76          0x0000ffff,            /* dst_mask */
77          false),                /* pcrel_offset */
78 #define R_H8_DIR8_X (R_H8_DIR16_X + 1)
79   HOWTO (R_H8_DIR8,             /* type */
80          0,                     /* rightshift */
81          0,                     /* size (0 = byte, 1 = short, 2 = long) */
82          8,                     /* bitsize */
83          false,                 /* pc_relative */
84          0,                     /* bitpos */
85          complain_overflow_dont, /* complain_on_overflow */
86          NULL,                  /* special_function */
87          "R_H8_DIR16",          /* name */
88          false,                 /* partial_inplace */
89          0,                     /* src_mask */
90          0x000000ff,            /* dst_mask */
91          false),                /* pcrel_offset */
92 #define R_H8_DIR16A8_X (R_H8_DIR8_X + 1)
93   HOWTO (R_H8_DIR16A8,          /* type */
94          0,                     /* rightshift */
95          1,                     /* size (0 = byte, 1 = short, 2 = long) */
96          16,                    /* bitsize */
97          false,                 /* pc_relative */
98          0,                     /* bitpos */
99          complain_overflow_bitfield, /* complain_on_overflow */
100          NULL,                  /* special_function */
101          "R_H8_DIR16A8",        /* name */
102          false,                 /* partial_inplace */
103          0,                     /* src_mask */
104          0x0000ffff,            /* dst_mask */
105          false),                /* pcrel_offset */
106 #define R_H8_DIR16R8_X (R_H8_DIR16A8_X + 1)
107   HOWTO (R_H8_DIR16R8,          /* type */
108          0,                     /* rightshift */
109          1,                     /* size (0 = byte, 1 = short, 2 = long) */
110          16,                    /* bitsize */
111          false,                 /* pc_relative */
112          0,                     /* bitpos */
113          complain_overflow_bitfield, /* complain_on_overflow */
114          NULL,                  /* special_function */
115          "R_H8_DIR16R8",        /* name */
116          false,                 /* partial_inplace */
117          0,                     /* src_mask */
118          0x0000ffff,            /* dst_mask */
119          false),                /* pcrel_offset */
120 #define R_H8_DIR24A8_X (R_H8_DIR16R8_X + 1)
121   HOWTO (R_H8_DIR24A8,          /* type */
122          0,                     /* rightshift */
123          2,                     /* size (0 = byte, 1 = short, 2 = long) */
124          24,                    /* bitsize */
125          false,                 /* pc_relative */
126          0,                     /* bitpos */
127          complain_overflow_bitfield, /* complain_on_overflow */
128          NULL,                  /* special_function */
129          "R_H8_DIR24A8",        /* name */
130          true,                  /* partial_inplace */
131          0xff000000,            /* src_mask */
132          0x00ffffff,            /* dst_mask */
133          false),                /* pcrel_offset */
134 #define R_H8_DIR24R8_X (R_H8_DIR24A8_X + 1)
135   HOWTO (R_H8_DIR24R8,          /* type */
136          0,                     /* rightshift */
137          2,                     /* size (0 = byte, 1 = short, 2 = long) */
138          24,                    /* bitsize */
139          false,                 /* pc_relative */
140          0,                     /* bitpos */
141          complain_overflow_bitfield, /* complain_on_overflow */
142          NULL,                  /* special_function */
143          "R_H8_DIR24R8",        /* name */
144          true,                  /* partial_inplace */
145          0xff000000,            /* src_mask */
146          0x00ffffff,            /* dst_mask */
147          false),                /* pcrel_offset */
148 #define R_H8_DIR32A16_X (R_H8_DIR24R8_X + 1)
149   HOWTO (R_H8_DIR32A16,         /* type */
150          0,                     /* rightshift */
151          2,                     /* size (0 = byte, 1 = short, 2 = long) */
152          32,                    /* bitsize */
153          false,                 /* pc_relative */
154          0,                     /* bitpos */
155          complain_overflow_dont, /* complain_on_overflow */
156          NULL,                  /* special_function */
157          "R_H8_DIR32",          /* name */
158          false,                 /* partial_inplace */
159          0,                     /* src_mask */
160          0xffffffff,            /* dst_mask */
161          false),                /* pcrel_offset */
162 };
163
164 /* This structure is used to map BFD reloc codes to H8 ELF relocs.  */
165
166 struct elf_reloc_map
167 {
168   bfd_reloc_code_real_type bfd_reloc_val;
169   unsigned char howto_index;
170 };
171
172 /* An array mapping BFD reloc codes to SH ELF relocs.  */
173
174 static const struct elf_reloc_map h8_reloc_map[] =
175 {
176   { BFD_RELOC_NONE, R_H8_NONE_X },
177   { BFD_RELOC_32, R_H8_DIR32_X },
178   { BFD_RELOC_16, R_H8_DIR16_X },
179   { BFD_RELOC_8, R_H8_DIR8_X },
180   { BFD_RELOC_H8_DIR16A8, R_H8_DIR16A8_X },
181   { BFD_RELOC_H8_DIR16R8, R_H8_DIR16R8_X },
182   { BFD_RELOC_H8_DIR24A8, R_H8_DIR24A8_X },
183   { BFD_RELOC_H8_DIR24R8, R_H8_DIR24R8_X },
184   { BFD_RELOC_H8_DIR32A16, R_H8_DIR32A16_X },
185 };
186
187 static reloc_howto_type *elf32_h8_reloc_type_lookup
188   PARAMS ((bfd *, bfd_reloc_code_real_type));
189 static void elf32_h8_info_to_howto
190   PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
191 static void elf32_h8_info_to_howto_rel
192   PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
193 static int elf32_h8_mach
194   PARAMS ((flagword));
195
196 static reloc_howto_type *
197 elf32_h8_reloc_type_lookup (abfd, code)
198      bfd *abfd ATTRIBUTE_UNUSED;
199      bfd_reloc_code_real_type code;
200 {
201   unsigned int i;
202
203   for (i = 0; i < sizeof (h8_reloc_map) / sizeof (struct elf_reloc_map); i++)
204     {
205       if (h8_reloc_map[i].bfd_reloc_val == code)
206         return &h8_elf_howto_table[(int) h8_reloc_map[i].howto_index];
207     }
208   return NULL;
209 }
210
211 static void
212 elf32_h8_info_to_howto (abfd, bfd_reloc, elf_reloc)
213      bfd *abfd ATTRIBUTE_UNUSED;
214      arelent *bfd_reloc;
215      Elf32_Internal_Rela *elf_reloc ATTRIBUTE_UNUSED;
216 {
217   unsigned int r;
218   unsigned int i;
219
220   r = ELF32_R_TYPE (elf_reloc->r_info);
221   for (i = 0; i < sizeof (h8_elf_howto_table) / sizeof (reloc_howto_type); i++)
222     if (h8_elf_howto_table[i].type== r)
223       {
224         bfd_reloc->howto = &h8_elf_howto_table[i];
225         return;
226       }
227   abort ();
228 }
229
230 static void
231 elf32_h8_info_to_howto_rel (abfd, bfd_reloc, elf_reloc)
232      bfd *abfd ATTRIBUTE_UNUSED;
233      arelent *bfd_reloc;
234      Elf32_Internal_Rel *elf_reloc ATTRIBUTE_UNUSED;
235 {
236   unsigned int r;
237
238   abort ();
239   r = ELF32_R_TYPE (elf_reloc->r_info);
240   bfd_reloc->howto = &h8_elf_howto_table[r];
241 }
242
243 /* Object files encode the specific H8 model they were compiled
244    for in the ELF flags field.
245
246    Examine that field and return the proper BFD machine type for
247    the object file.  */
248 static int
249 elf32_h8_mach (flags)
250      flagword flags;
251 {
252   switch (flags & EF_H8_MACH)
253     {
254     case E_H8_MACH_H8300:
255     default:
256       return bfd_mach_h8300;
257
258     case E_H8_MACH_H8300H:
259       return bfd_mach_h8300h;
260
261     case E_H8_MACH_H8300S:
262       return bfd_mach_h8300s;
263     }
264 }
265
266 /* The final processing done just before writing out a H8 ELF object
267    file.  We use this opportunity to encode the BFD machine type
268    into the flags field in the object file.  */
269
270 void
271 elf32_h8_final_write_processing (abfd, linker)
272      bfd *abfd;
273      boolean linker ATTRIBUTE_UNUSED;
274 {
275   unsigned long val;
276
277   switch (bfd_get_mach (abfd))
278     {
279     default:
280     case bfd_mach_h8300:
281       val = E_H8_MACH_H8300;
282       break;
283
284     case bfd_mach_h8300h:
285       val = E_H8_MACH_H8300H;
286       break;
287
288     case bfd_mach_h8300s:
289       val = E_H8_MACH_H8300S;
290       break;
291     }
292
293   elf_elfheader (abfd)->e_flags &= ~ (EF_H8_MACH);
294   elf_elfheader (abfd)->e_flags |= val;
295 }
296
297 /* Return nonzero if ABFD represents a valid H8 ELF object file; also
298    record the encoded machine type found in the ELF flags.  */
299
300 boolean
301 elf32_h8_object_p (abfd)
302      bfd *abfd;
303 {
304   bfd_default_set_arch_mach (abfd, bfd_arch_h8300,
305                              elf32_h8_mach (elf_elfheader (abfd)->e_flags));
306   return true;
307 }
308
309 /* Merge backend specific data from an object file to the output
310    object file when linking.  The only data we need to copy at this
311    time is the architecture/machine information.  */
312
313 boolean
314 elf32_h8_merge_private_bfd_data (ibfd, obfd)
315      bfd *ibfd;
316      bfd *obfd;
317 {
318   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
319       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
320     return true;
321
322   if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
323       && bfd_get_mach (obfd) < bfd_get_mach (ibfd))
324     {
325       if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
326                                bfd_get_mach (ibfd)))
327         return false;
328     }
329
330   return true;
331 }
332
333
334 #define TARGET_BIG_SYM                  bfd_elf32_h8300_vec
335 #define TARGET_BIG_NAME                 "elf32-h8300"
336 #define ELF_ARCH                        bfd_arch_h8300
337 #define ELF_MACHINE_CODE                EM_H8_300
338 #define ELF_MAXPAGESIZE                 0x1
339 #define bfd_elf32_bfd_reloc_type_lookup elf32_h8_reloc_type_lookup
340 #define elf_info_to_howto               elf32_h8_info_to_howto
341 #define elf_info_to_howto_rel           elf32_h8_info_to_howto_rel
342
343 /* So we can set/examine bits in e_flags to get the specific
344    H8 architecture in use.  */
345 #define elf_backend_final_write_processing \
346   elf32_h8_final_write_processing
347 #define elf_backend_object_p \
348   elf32_h8_object_p
349 #define bfd_elf32_bfd_merge_private_bfd_data \
350   elf32_h8_merge_private_bfd_data
351
352 /* ??? when elf_backend_relocate_section is not defined, elf32-target.h
353    defaults to using _bfd_generic_link_hash_table_create, but
354    elflink.h:bfd_elf32_size_dynamic_sections uses
355    dynobj = elf_hash_table (info)->dynobj;
356    and thus requires an elf hash table.  */
357 #define bfd_elf32_bfd_link_hash_table_create _bfd_elf_link_hash_table_create
358
359 #include "elf32-target.h"