xref: /openbsd/gnu/usr.bin/binutils/bfd/elf32-h8300.c (revision cf2f2c56)
1d2201f2fSdrahn /* BFD back-end for Renesas H8/300 ELF binaries.
2*cf2f2c56Smiod    Copyright 1993, 1995, 1998, 1999, 2001, 2002, 2003, 2004
3d2201f2fSdrahn    Free Software Foundation, Inc.
4d2201f2fSdrahn 
5d2201f2fSdrahn    This file is part of BFD, the Binary File Descriptor library.
6d2201f2fSdrahn 
7d2201f2fSdrahn    This program is free software; you can redistribute it and/or modify
8d2201f2fSdrahn    it under the terms of the GNU General Public License as published by
9d2201f2fSdrahn    the Free Software Foundation; either version 2 of the License, or
10d2201f2fSdrahn    (at your option) any later version.
11d2201f2fSdrahn 
12d2201f2fSdrahn    This program is distributed in the hope that it will be useful,
13d2201f2fSdrahn    but WITHOUT ANY WARRANTY; without even the implied warranty of
14d2201f2fSdrahn    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15d2201f2fSdrahn    GNU General Public License for more details.
16d2201f2fSdrahn 
17d2201f2fSdrahn    You should have received a copy of the GNU General Public License
18d2201f2fSdrahn    along with this program; if not, write to the Free Software
19d2201f2fSdrahn    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20d2201f2fSdrahn 
21d2201f2fSdrahn #include "bfd.h"
22d2201f2fSdrahn #include "sysdep.h"
23d2201f2fSdrahn #include "libbfd.h"
24d2201f2fSdrahn #include "elf-bfd.h"
25d2201f2fSdrahn #include "elf/h8.h"
26d2201f2fSdrahn 
27d2201f2fSdrahn static reloc_howto_type *elf32_h8_reloc_type_lookup
28*cf2f2c56Smiod   (bfd *abfd, bfd_reloc_code_real_type code);
29d2201f2fSdrahn static void elf32_h8_info_to_howto
30*cf2f2c56Smiod   (bfd *, arelent *, Elf_Internal_Rela *);
31d2201f2fSdrahn static void elf32_h8_info_to_howto_rel
32*cf2f2c56Smiod   (bfd *, arelent *, Elf_Internal_Rela *);
33*cf2f2c56Smiod static unsigned long elf32_h8_mach (flagword);
34*cf2f2c56Smiod static void elf32_h8_final_write_processing (bfd *, bfd_boolean);
35*cf2f2c56Smiod static bfd_boolean elf32_h8_object_p (bfd *);
36*cf2f2c56Smiod static bfd_boolean elf32_h8_merge_private_bfd_data (bfd *, bfd *);
37d2201f2fSdrahn static bfd_boolean elf32_h8_relax_section
38*cf2f2c56Smiod   (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
39d2201f2fSdrahn static bfd_boolean elf32_h8_relax_delete_bytes
40*cf2f2c56Smiod   (bfd *, asection *, bfd_vma, int);
41*cf2f2c56Smiod static bfd_boolean elf32_h8_symbol_address_p (bfd *, asection *, bfd_vma);
42d2201f2fSdrahn static bfd_byte *elf32_h8_get_relocated_section_contents
43*cf2f2c56Smiod   (bfd *, struct bfd_link_info *, struct bfd_link_order *,
44*cf2f2c56Smiod    bfd_byte *, bfd_boolean, asymbol **);
45*cf2f2c56Smiod static asection *elf32_h8_gc_mark_hook
46*cf2f2c56Smiod   (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
47*cf2f2c56Smiod    struct elf_link_hash_entry *, Elf_Internal_Sym *);
48*cf2f2c56Smiod static bfd_boolean elf32_h8_gc_sweep_hook
49*cf2f2c56Smiod   (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
50d2201f2fSdrahn static bfd_reloc_status_type elf32_h8_final_link_relocate
51*cf2f2c56Smiod   (unsigned long, bfd *, bfd *, asection *,
52d2201f2fSdrahn    bfd_byte *, bfd_vma, bfd_vma, bfd_vma,
53*cf2f2c56Smiod    struct bfd_link_info *, asection *, int);
54d2201f2fSdrahn static bfd_boolean elf32_h8_relocate_section
55*cf2f2c56Smiod   (bfd *, struct bfd_link_info *, bfd *, asection *,
56d2201f2fSdrahn    bfd_byte *, Elf_Internal_Rela *,
57*cf2f2c56Smiod    Elf_Internal_Sym *, asection **);
58d2201f2fSdrahn static bfd_reloc_status_type special
59*cf2f2c56Smiod   (bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **);
60d2201f2fSdrahn 
61d2201f2fSdrahn /* This does not include any relocation information, but should be
62d2201f2fSdrahn    good enough for GDB or objdump to read the file.  */
63d2201f2fSdrahn 
64d2201f2fSdrahn static reloc_howto_type h8_elf_howto_table[] = {
65d2201f2fSdrahn #define R_H8_NONE_X 0
66d2201f2fSdrahn   HOWTO (R_H8_NONE,		/* type */
67d2201f2fSdrahn 	 0,			/* rightshift */
68d2201f2fSdrahn 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
69d2201f2fSdrahn 	 0,			/* bitsize */
70d2201f2fSdrahn 	 FALSE,			/* pc_relative */
71d2201f2fSdrahn 	 0,			/* bitpos */
72d2201f2fSdrahn 	 complain_overflow_dont,/* complain_on_overflow */
73d2201f2fSdrahn 	 special,		/* special_function */
74d2201f2fSdrahn 	 "R_H8_NONE",		/* name */
75d2201f2fSdrahn 	 FALSE,			/* partial_inplace */
76d2201f2fSdrahn 	 0,			/* src_mask */
77d2201f2fSdrahn 	 0,			/* dst_mask */
78d2201f2fSdrahn 	 FALSE),		/* pcrel_offset */
79d2201f2fSdrahn #define R_H8_DIR32_X (R_H8_NONE_X + 1)
80d2201f2fSdrahn   HOWTO (R_H8_DIR32,		/* type */
81d2201f2fSdrahn 	 0,			/* rightshift */
82d2201f2fSdrahn 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
83d2201f2fSdrahn 	 32,			/* bitsize */
84d2201f2fSdrahn 	 FALSE,			/* pc_relative */
85d2201f2fSdrahn 	 0,			/* bitpos */
86d2201f2fSdrahn 	 complain_overflow_dont,/* complain_on_overflow */
87d2201f2fSdrahn 	 special,		/* special_function */
88d2201f2fSdrahn 	 "R_H8_DIR32",		/* name */
89d2201f2fSdrahn 	 FALSE,			/* partial_inplace */
90d2201f2fSdrahn 	 0,			/* src_mask */
91d2201f2fSdrahn 	 0xffffffff,		/* dst_mask */
92d2201f2fSdrahn 	 FALSE),		/* pcrel_offset */
93d2201f2fSdrahn #define R_H8_DIR16_X (R_H8_DIR32_X + 1)
94d2201f2fSdrahn   HOWTO (R_H8_DIR16,		/* type */
95d2201f2fSdrahn 	 0,			/* rightshift */
96d2201f2fSdrahn 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
97d2201f2fSdrahn 	 16,			/* bitsize */
98d2201f2fSdrahn 	 FALSE,			/* pc_relative */
99d2201f2fSdrahn 	 0,			/* bitpos */
100d2201f2fSdrahn 	 complain_overflow_dont,/* complain_on_overflow */
101d2201f2fSdrahn 	 special,		/* special_function */
102d2201f2fSdrahn 	 "R_H8_DIR16",		/* name */
103d2201f2fSdrahn 	 FALSE,			/* partial_inplace */
104d2201f2fSdrahn 	 0,			/* src_mask */
105d2201f2fSdrahn 	 0x0000ffff,		/* dst_mask */
106d2201f2fSdrahn 	 FALSE),		/* pcrel_offset */
107d2201f2fSdrahn #define R_H8_DIR8_X (R_H8_DIR16_X + 1)
108d2201f2fSdrahn   HOWTO (R_H8_DIR8,		/* type */
109d2201f2fSdrahn 	 0,			/* rightshift */
110d2201f2fSdrahn 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
111d2201f2fSdrahn 	 8,			/* bitsize */
112d2201f2fSdrahn 	 FALSE,			/* pc_relative */
113d2201f2fSdrahn 	 0,			/* bitpos */
114d2201f2fSdrahn 	 complain_overflow_dont,/* complain_on_overflow */
115d2201f2fSdrahn 	 special,		/* special_function */
116*cf2f2c56Smiod 	 "R_H8_DIR8",		/* name */
117d2201f2fSdrahn 	 FALSE,			/* partial_inplace */
118d2201f2fSdrahn 	 0,			/* src_mask */
119d2201f2fSdrahn 	 0x000000ff,		/* dst_mask */
120d2201f2fSdrahn 	 FALSE),		/* pcrel_offset */
121d2201f2fSdrahn #define R_H8_DIR16A8_X (R_H8_DIR8_X + 1)
122d2201f2fSdrahn   HOWTO (R_H8_DIR16A8,		/* type */
123d2201f2fSdrahn 	 0,			/* rightshift */
124d2201f2fSdrahn 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
125d2201f2fSdrahn 	 16,			/* bitsize */
126d2201f2fSdrahn 	 FALSE,			/* pc_relative */
127d2201f2fSdrahn 	 0,			/* bitpos */
128d2201f2fSdrahn 	 complain_overflow_bitfield, /* complain_on_overflow */
129d2201f2fSdrahn 	 special,		/* special_function */
130d2201f2fSdrahn 	 "R_H8_DIR16A8",	/* name */
131d2201f2fSdrahn 	 FALSE,			/* partial_inplace */
132d2201f2fSdrahn 	 0,			/* src_mask */
133d2201f2fSdrahn 	 0x0000ffff,		/* dst_mask */
134d2201f2fSdrahn 	 FALSE),		/* pcrel_offset */
135d2201f2fSdrahn #define R_H8_DIR16R8_X (R_H8_DIR16A8_X + 1)
136d2201f2fSdrahn   HOWTO (R_H8_DIR16R8,		/* type */
137d2201f2fSdrahn 	 0,			/* rightshift */
138d2201f2fSdrahn 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
139d2201f2fSdrahn 	 16,			/* bitsize */
140d2201f2fSdrahn 	 FALSE,			/* pc_relative */
141d2201f2fSdrahn 	 0,			/* bitpos */
142d2201f2fSdrahn 	 complain_overflow_bitfield, /* complain_on_overflow */
143d2201f2fSdrahn 	 special,		/* special_function */
144d2201f2fSdrahn 	 "R_H8_DIR16R8",	/* name */
145d2201f2fSdrahn 	 FALSE,			/* partial_inplace */
146d2201f2fSdrahn 	 0,			/* src_mask */
147d2201f2fSdrahn 	 0x0000ffff,		/* dst_mask */
148d2201f2fSdrahn 	 FALSE),		/* pcrel_offset */
149d2201f2fSdrahn #define R_H8_DIR24A8_X (R_H8_DIR16R8_X + 1)
150d2201f2fSdrahn   HOWTO (R_H8_DIR24A8,		/* type */
151d2201f2fSdrahn 	 0,			/* rightshift */
152d2201f2fSdrahn 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
153d2201f2fSdrahn 	 24,			/* bitsize */
154d2201f2fSdrahn 	 FALSE,			/* pc_relative */
155d2201f2fSdrahn 	 0,			/* bitpos */
156d2201f2fSdrahn 	 complain_overflow_bitfield, /* complain_on_overflow */
157d2201f2fSdrahn 	 special,		/* special_function */
158d2201f2fSdrahn 	 "R_H8_DIR24A8",	/* name */
159d2201f2fSdrahn 	 TRUE,			/* partial_inplace */
160d2201f2fSdrahn 	 0xff000000,		/* src_mask */
161d2201f2fSdrahn 	 0x00ffffff,		/* dst_mask */
162d2201f2fSdrahn 	 FALSE),		/* pcrel_offset */
163d2201f2fSdrahn #define R_H8_DIR24R8_X (R_H8_DIR24A8_X + 1)
164d2201f2fSdrahn   HOWTO (R_H8_DIR24R8,		/* type */
165d2201f2fSdrahn 	 0,			/* rightshift */
166d2201f2fSdrahn 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
167d2201f2fSdrahn 	 24,			/* bitsize */
168d2201f2fSdrahn 	 FALSE,			/* pc_relative */
169d2201f2fSdrahn 	 0,			/* bitpos */
170d2201f2fSdrahn 	 complain_overflow_bitfield, /* complain_on_overflow */
171d2201f2fSdrahn 	 special,		/* special_function */
172d2201f2fSdrahn 	 "R_H8_DIR24R8",	/* name */
173d2201f2fSdrahn 	 TRUE,			/* partial_inplace */
174d2201f2fSdrahn 	 0xff000000,		/* src_mask */
175d2201f2fSdrahn 	 0x00ffffff,		/* dst_mask */
176d2201f2fSdrahn 	 FALSE),		/* pcrel_offset */
177d2201f2fSdrahn #define R_H8_DIR32A16_X (R_H8_DIR24R8_X + 1)
178d2201f2fSdrahn   HOWTO (R_H8_DIR32A16,		/* type */
179d2201f2fSdrahn 	 0,			/* rightshift */
180d2201f2fSdrahn 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
181d2201f2fSdrahn 	 32,			/* bitsize */
182d2201f2fSdrahn 	 FALSE,			/* pc_relative */
183d2201f2fSdrahn 	 0,			/* bitpos */
184d2201f2fSdrahn 	 complain_overflow_dont,/* complain_on_overflow */
185d2201f2fSdrahn 	 special,		/* special_function */
186*cf2f2c56Smiod 	 "R_H8_DIR32A16",	/* name */
187d2201f2fSdrahn 	 FALSE,			/* partial_inplace */
188d2201f2fSdrahn 	 0,			/* src_mask */
189d2201f2fSdrahn 	 0xffffffff,		/* dst_mask */
190d2201f2fSdrahn 	 FALSE),		/* pcrel_offset */
191d2201f2fSdrahn #define R_H8_PCREL16_X (R_H8_DIR32A16_X + 1)
192d2201f2fSdrahn   HOWTO (R_H8_PCREL16,		/* type */
193d2201f2fSdrahn 	 0,			/* rightshift */
194d2201f2fSdrahn 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
195d2201f2fSdrahn 	 16,			/* bitsize */
196d2201f2fSdrahn 	 TRUE,			/* pc_relative */
197d2201f2fSdrahn 	 0,			/* bitpos */
198d2201f2fSdrahn 	 complain_overflow_signed,/* complain_on_overflow */
199d2201f2fSdrahn 	 special,		/* special_function */
200d2201f2fSdrahn 	 "R_H8_PCREL16",	/* name */
201d2201f2fSdrahn 	 FALSE,			/* partial_inplace */
202d2201f2fSdrahn 	 0xffff,		/* src_mask */
203d2201f2fSdrahn 	 0xffff,		/* dst_mask */
204d2201f2fSdrahn 	 TRUE),			/* pcrel_offset */
205d2201f2fSdrahn #define R_H8_PCREL8_X (R_H8_PCREL16_X + 1)
206d2201f2fSdrahn   HOWTO (R_H8_PCREL8,		/* type */
207d2201f2fSdrahn 	 0,			/* rightshift */
208d2201f2fSdrahn 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
209d2201f2fSdrahn 	 8,			/* bitsize */
210d2201f2fSdrahn 	 TRUE,			/* pc_relative */
211d2201f2fSdrahn 	 0,			/* bitpos */
212d2201f2fSdrahn 	 complain_overflow_signed,/* complain_on_overflow */
213d2201f2fSdrahn 	 special,		/* special_function */
214d2201f2fSdrahn 	 "R_H8_PCREL8",		/* name */
215d2201f2fSdrahn 	 FALSE,			/* partial_inplace */
216d2201f2fSdrahn 	 0xff,			/* src_mask */
217d2201f2fSdrahn 	 0xff,			/* dst_mask */
218d2201f2fSdrahn 	 TRUE),			/* pcrel_offset */
219d2201f2fSdrahn };
220d2201f2fSdrahn 
221d2201f2fSdrahn /* This structure is used to map BFD reloc codes to H8 ELF relocs.  */
222d2201f2fSdrahn 
223d2201f2fSdrahn struct elf_reloc_map {
224d2201f2fSdrahn   bfd_reloc_code_real_type bfd_reloc_val;
225d2201f2fSdrahn   unsigned char howto_index;
226d2201f2fSdrahn };
227d2201f2fSdrahn 
228*cf2f2c56Smiod /* An array mapping BFD reloc codes to H8 ELF relocs.  */
229d2201f2fSdrahn 
230d2201f2fSdrahn static const struct elf_reloc_map h8_reloc_map[] = {
231d2201f2fSdrahn   { BFD_RELOC_NONE, R_H8_NONE_X },
232d2201f2fSdrahn   { BFD_RELOC_32, R_H8_DIR32_X },
233d2201f2fSdrahn   { BFD_RELOC_16, R_H8_DIR16_X },
234d2201f2fSdrahn   { BFD_RELOC_8, R_H8_DIR8_X },
235d2201f2fSdrahn   { BFD_RELOC_H8_DIR16A8, R_H8_DIR16A8_X },
236d2201f2fSdrahn   { BFD_RELOC_H8_DIR16R8, R_H8_DIR16R8_X },
237d2201f2fSdrahn   { BFD_RELOC_H8_DIR24A8, R_H8_DIR24A8_X },
238d2201f2fSdrahn   { BFD_RELOC_H8_DIR24R8, R_H8_DIR24R8_X },
239d2201f2fSdrahn   { BFD_RELOC_H8_DIR32A16, R_H8_DIR32A16_X },
240d2201f2fSdrahn   { BFD_RELOC_16_PCREL, R_H8_PCREL16_X },
241d2201f2fSdrahn   { BFD_RELOC_8_PCREL, R_H8_PCREL8_X },
242d2201f2fSdrahn };
243d2201f2fSdrahn 
244d2201f2fSdrahn 
245d2201f2fSdrahn static reloc_howto_type *
elf32_h8_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)246*cf2f2c56Smiod elf32_h8_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
247*cf2f2c56Smiod 			    bfd_reloc_code_real_type code)
248d2201f2fSdrahn {
249d2201f2fSdrahn   unsigned int i;
250d2201f2fSdrahn 
251d2201f2fSdrahn   for (i = 0; i < sizeof (h8_reloc_map) / sizeof (struct elf_reloc_map); i++)
252d2201f2fSdrahn     {
253d2201f2fSdrahn       if (h8_reloc_map[i].bfd_reloc_val == code)
254d2201f2fSdrahn 	return &h8_elf_howto_table[(int) h8_reloc_map[i].howto_index];
255d2201f2fSdrahn     }
256d2201f2fSdrahn   return NULL;
257d2201f2fSdrahn }
258d2201f2fSdrahn 
259d2201f2fSdrahn static void
elf32_h8_info_to_howto(bfd * abfd ATTRIBUTE_UNUSED,arelent * bfd_reloc,Elf_Internal_Rela * elf_reloc)260*cf2f2c56Smiod elf32_h8_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *bfd_reloc,
261*cf2f2c56Smiod 			Elf_Internal_Rela *elf_reloc)
262d2201f2fSdrahn {
263d2201f2fSdrahn   unsigned int r;
264d2201f2fSdrahn   unsigned int i;
265d2201f2fSdrahn 
266d2201f2fSdrahn   r = ELF32_R_TYPE (elf_reloc->r_info);
267d2201f2fSdrahn   for (i = 0; i < sizeof (h8_elf_howto_table) / sizeof (reloc_howto_type); i++)
268d2201f2fSdrahn     if (h8_elf_howto_table[i].type == r)
269d2201f2fSdrahn       {
270d2201f2fSdrahn 	bfd_reloc->howto = &h8_elf_howto_table[i];
271d2201f2fSdrahn 	return;
272d2201f2fSdrahn       }
273d2201f2fSdrahn   abort ();
274d2201f2fSdrahn }
275d2201f2fSdrahn 
276d2201f2fSdrahn static void
elf32_h8_info_to_howto_rel(bfd * abfd ATTRIBUTE_UNUSED,arelent * bfd_reloc,Elf_Internal_Rela * elf_reloc ATTRIBUTE_UNUSED)277*cf2f2c56Smiod elf32_h8_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED, arelent *bfd_reloc,
278*cf2f2c56Smiod 			    Elf_Internal_Rela *elf_reloc ATTRIBUTE_UNUSED)
279d2201f2fSdrahn {
280d2201f2fSdrahn   unsigned int r;
281d2201f2fSdrahn 
282d2201f2fSdrahn   abort ();
283d2201f2fSdrahn   r = ELF32_R_TYPE (elf_reloc->r_info);
284d2201f2fSdrahn   bfd_reloc->howto = &h8_elf_howto_table[r];
285d2201f2fSdrahn }
286d2201f2fSdrahn 
287d2201f2fSdrahn /* Special handling for H8/300 relocs.
288d2201f2fSdrahn    We only come here for pcrel stuff and return normally if not an -r link.
289d2201f2fSdrahn    When doing -r, we can't do any arithmetic for the pcrel stuff, because
290d2201f2fSdrahn    we support relaxing on the H8/300 series chips.  */
291d2201f2fSdrahn static bfd_reloc_status_type
special(bfd * abfd ATTRIBUTE_UNUSED,arelent * reloc_entry ATTRIBUTE_UNUSED,asymbol * symbol ATTRIBUTE_UNUSED,PTR data ATTRIBUTE_UNUSED,asection * input_section ATTRIBUTE_UNUSED,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)292*cf2f2c56Smiod special (bfd *abfd ATTRIBUTE_UNUSED,
293*cf2f2c56Smiod 	 arelent *reloc_entry ATTRIBUTE_UNUSED,
294*cf2f2c56Smiod 	 asymbol *symbol ATTRIBUTE_UNUSED,
295*cf2f2c56Smiod 	 PTR data ATTRIBUTE_UNUSED,
296*cf2f2c56Smiod 	 asection *input_section ATTRIBUTE_UNUSED,
297*cf2f2c56Smiod 	 bfd *output_bfd,
298*cf2f2c56Smiod 	 char **error_message ATTRIBUTE_UNUSED)
299d2201f2fSdrahn {
300d2201f2fSdrahn   if (output_bfd == (bfd *) NULL)
301d2201f2fSdrahn     return bfd_reloc_continue;
302d2201f2fSdrahn 
303d2201f2fSdrahn   /* Adjust the reloc address to that in the output section.  */
304d2201f2fSdrahn   reloc_entry->address += input_section->output_offset;
305d2201f2fSdrahn   return bfd_reloc_ok;
306d2201f2fSdrahn }
307d2201f2fSdrahn 
308d2201f2fSdrahn /* Perform a relocation as part of a final link.  */
309d2201f2fSdrahn static bfd_reloc_status_type
elf32_h8_final_link_relocate(unsigned long r_type,bfd * input_bfd,bfd * output_bfd ATTRIBUTE_UNUSED,asection * input_section ATTRIBUTE_UNUSED,bfd_byte * contents,bfd_vma offset,bfd_vma value,bfd_vma addend,struct bfd_link_info * info ATTRIBUTE_UNUSED,asection * sym_sec ATTRIBUTE_UNUSED,int is_local ATTRIBUTE_UNUSED)310*cf2f2c56Smiod elf32_h8_final_link_relocate (unsigned long r_type, bfd *input_bfd,
311*cf2f2c56Smiod 			      bfd *output_bfd ATTRIBUTE_UNUSED,
312*cf2f2c56Smiod 			      asection *input_section ATTRIBUTE_UNUSED,
313*cf2f2c56Smiod 			      bfd_byte *contents, bfd_vma offset,
314*cf2f2c56Smiod 			      bfd_vma value, bfd_vma addend,
315*cf2f2c56Smiod 			      struct bfd_link_info *info ATTRIBUTE_UNUSED,
316*cf2f2c56Smiod 			      asection *sym_sec ATTRIBUTE_UNUSED,
317*cf2f2c56Smiod 			      int is_local ATTRIBUTE_UNUSED)
318d2201f2fSdrahn {
319d2201f2fSdrahn   bfd_byte *hit_data = contents + offset;
320d2201f2fSdrahn 
321d2201f2fSdrahn   switch (r_type)
322d2201f2fSdrahn     {
323d2201f2fSdrahn     case R_H8_NONE:
324d2201f2fSdrahn       return bfd_reloc_ok;
325d2201f2fSdrahn 
326d2201f2fSdrahn     case R_H8_DIR32:
327d2201f2fSdrahn     case R_H8_DIR32A16:
328d2201f2fSdrahn     case R_H8_DIR24A8:
329d2201f2fSdrahn       value += addend;
330d2201f2fSdrahn       bfd_put_32 (input_bfd, value, hit_data);
331d2201f2fSdrahn       return bfd_reloc_ok;
332d2201f2fSdrahn 
333d2201f2fSdrahn     case R_H8_DIR16:
334d2201f2fSdrahn     case R_H8_DIR16A8:
335d2201f2fSdrahn     case R_H8_DIR16R8:
336d2201f2fSdrahn       value += addend;
337d2201f2fSdrahn       bfd_put_16 (input_bfd, value, hit_data);
338d2201f2fSdrahn       return bfd_reloc_ok;
339d2201f2fSdrahn 
340d2201f2fSdrahn     /* AKA R_RELBYTE */
341d2201f2fSdrahn     case R_H8_DIR8:
342d2201f2fSdrahn       value += addend;
343d2201f2fSdrahn 
344d2201f2fSdrahn       bfd_put_8 (input_bfd, value, hit_data);
345d2201f2fSdrahn       return bfd_reloc_ok;
346d2201f2fSdrahn 
347d2201f2fSdrahn     case R_H8_DIR24R8:
348d2201f2fSdrahn       value += addend;
349d2201f2fSdrahn 
350d2201f2fSdrahn       /* HIT_DATA is the address for the first byte for the relocated
351*cf2f2c56Smiod 	 value.  Subtract 1 so that we can manipulate the data in 32-bit
352d2201f2fSdrahn 	 hunks.  */
353d2201f2fSdrahn       hit_data--;
354d2201f2fSdrahn 
355d2201f2fSdrahn       /* Clear out the top byte in value.  */
356d2201f2fSdrahn       value &= 0xffffff;
357d2201f2fSdrahn 
358d2201f2fSdrahn       /* Retrieve the type byte for value from the section contents.  */
359d2201f2fSdrahn       value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000);
360d2201f2fSdrahn 
361*cf2f2c56Smiod       /* Now scribble it out in one 32-bit hunk.  */
362d2201f2fSdrahn       bfd_put_32 (input_bfd, value, hit_data);
363d2201f2fSdrahn       return bfd_reloc_ok;
364d2201f2fSdrahn 
365d2201f2fSdrahn     case R_H8_PCREL16:
366d2201f2fSdrahn       value -= (input_section->output_section->vma
367d2201f2fSdrahn 		+ input_section->output_offset);
368d2201f2fSdrahn       value -= offset;
369d2201f2fSdrahn       value += addend;
370d2201f2fSdrahn 
371d2201f2fSdrahn       /* The value is relative to the start of the instruction,
372d2201f2fSdrahn 	 not the relocation offset.  Subtract 2 to account for
373d2201f2fSdrahn 	 this minor issue.  */
374d2201f2fSdrahn       value -= 2;
375d2201f2fSdrahn 
376d2201f2fSdrahn       bfd_put_16 (input_bfd, value, hit_data);
377d2201f2fSdrahn       return bfd_reloc_ok;
378d2201f2fSdrahn 
379d2201f2fSdrahn     case R_H8_PCREL8:
380d2201f2fSdrahn       value -= (input_section->output_section->vma
381d2201f2fSdrahn 		+ input_section->output_offset);
382d2201f2fSdrahn       value -= offset;
383d2201f2fSdrahn       value += addend;
384d2201f2fSdrahn 
385d2201f2fSdrahn       /* The value is relative to the start of the instruction,
386d2201f2fSdrahn 	 not the relocation offset.  Subtract 1 to account for
387d2201f2fSdrahn 	 this minor issue.  */
388d2201f2fSdrahn       value -= 1;
389d2201f2fSdrahn 
390d2201f2fSdrahn       bfd_put_8 (input_bfd, value, hit_data);
391d2201f2fSdrahn       return bfd_reloc_ok;
392d2201f2fSdrahn 
393d2201f2fSdrahn     default:
394d2201f2fSdrahn       return bfd_reloc_notsupported;
395d2201f2fSdrahn     }
396d2201f2fSdrahn }
397d2201f2fSdrahn 
398d2201f2fSdrahn /* Relocate an H8 ELF section.  */
399d2201f2fSdrahn static bfd_boolean
elf32_h8_relocate_section(bfd * output_bfd,struct bfd_link_info * info,bfd * input_bfd,asection * input_section,bfd_byte * contents,Elf_Internal_Rela * relocs,Elf_Internal_Sym * local_syms,asection ** local_sections)400*cf2f2c56Smiod elf32_h8_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
401*cf2f2c56Smiod 			   bfd *input_bfd, asection *input_section,
402*cf2f2c56Smiod 			   bfd_byte *contents, Elf_Internal_Rela *relocs,
403*cf2f2c56Smiod 			   Elf_Internal_Sym *local_syms,
404*cf2f2c56Smiod 			   asection **local_sections)
405d2201f2fSdrahn {
406d2201f2fSdrahn   Elf_Internal_Shdr *symtab_hdr;
407d2201f2fSdrahn   struct elf_link_hash_entry **sym_hashes;
408d2201f2fSdrahn   Elf_Internal_Rela *rel, *relend;
409d2201f2fSdrahn 
410*cf2f2c56Smiod   if (info->relocatable)
411d2201f2fSdrahn     return TRUE;
412d2201f2fSdrahn 
413d2201f2fSdrahn   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
414d2201f2fSdrahn   sym_hashes = elf_sym_hashes (input_bfd);
415d2201f2fSdrahn 
416d2201f2fSdrahn   rel = relocs;
417d2201f2fSdrahn   relend = relocs + input_section->reloc_count;
418d2201f2fSdrahn   for (; rel < relend; rel++)
419d2201f2fSdrahn     {
420d2201f2fSdrahn       unsigned int r_type;
421d2201f2fSdrahn       unsigned long r_symndx;
422d2201f2fSdrahn       Elf_Internal_Sym *sym;
423d2201f2fSdrahn       asection *sec;
424d2201f2fSdrahn       struct elf_link_hash_entry *h;
425d2201f2fSdrahn       bfd_vma relocation;
426d2201f2fSdrahn       bfd_reloc_status_type r;
427d2201f2fSdrahn 
428d2201f2fSdrahn       /* This is a final link.  */
429d2201f2fSdrahn       r_symndx = ELF32_R_SYM (rel->r_info);
430d2201f2fSdrahn       r_type = ELF32_R_TYPE (rel->r_info);
431d2201f2fSdrahn       h = NULL;
432d2201f2fSdrahn       sym = NULL;
433d2201f2fSdrahn       sec = NULL;
434d2201f2fSdrahn       if (r_symndx < symtab_hdr->sh_info)
435d2201f2fSdrahn 	{
436d2201f2fSdrahn 	  sym = local_syms + r_symndx;
437d2201f2fSdrahn 	  sec = local_sections[r_symndx];
438*cf2f2c56Smiod 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
439d2201f2fSdrahn 	}
440d2201f2fSdrahn       else
441d2201f2fSdrahn 	{
442*cf2f2c56Smiod 	  bfd_boolean unresolved_reloc, warned;
443*cf2f2c56Smiod 
444*cf2f2c56Smiod 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
445*cf2f2c56Smiod 				   r_symndx, symtab_hdr, sym_hashes,
446*cf2f2c56Smiod 				   h, sec, relocation,
447*cf2f2c56Smiod 				   unresolved_reloc, warned);
448d2201f2fSdrahn 	}
449d2201f2fSdrahn 
450d2201f2fSdrahn       r = elf32_h8_final_link_relocate (r_type, input_bfd, output_bfd,
451d2201f2fSdrahn 					input_section,
452d2201f2fSdrahn 					contents, rel->r_offset,
453d2201f2fSdrahn 					relocation, rel->r_addend,
454d2201f2fSdrahn 					info, sec, h == NULL);
455d2201f2fSdrahn 
456d2201f2fSdrahn       if (r != bfd_reloc_ok)
457d2201f2fSdrahn 	{
458d2201f2fSdrahn 	  const char *name;
459d2201f2fSdrahn 	  const char *msg = (const char *) 0;
460d2201f2fSdrahn 	  arelent bfd_reloc;
461d2201f2fSdrahn 	  reloc_howto_type *howto;
462d2201f2fSdrahn 
463d2201f2fSdrahn 	  elf32_h8_info_to_howto (input_bfd, &bfd_reloc, rel);
464d2201f2fSdrahn 	  howto = bfd_reloc.howto;
465d2201f2fSdrahn 
466d2201f2fSdrahn 	  if (h != NULL)
467d2201f2fSdrahn 	    name = h->root.root.string;
468d2201f2fSdrahn 	  else
469d2201f2fSdrahn 	    {
470d2201f2fSdrahn 	      name = (bfd_elf_string_from_elf_section
471d2201f2fSdrahn 		      (input_bfd, symtab_hdr->sh_link, sym->st_name));
472d2201f2fSdrahn 	      if (name == NULL || *name == '\0')
473d2201f2fSdrahn 		name = bfd_section_name (input_bfd, sec);
474d2201f2fSdrahn 	    }
475d2201f2fSdrahn 
476d2201f2fSdrahn 	  switch (r)
477d2201f2fSdrahn 	    {
478d2201f2fSdrahn 	    case bfd_reloc_overflow:
479d2201f2fSdrahn 	      if (! ((*info->callbacks->reloc_overflow)
480d2201f2fSdrahn 		     (info, name, howto->name, (bfd_vma) 0,
481d2201f2fSdrahn 		      input_bfd, input_section, rel->r_offset)))
482d2201f2fSdrahn 		return FALSE;
483d2201f2fSdrahn 	      break;
484d2201f2fSdrahn 
485d2201f2fSdrahn 	    case bfd_reloc_undefined:
486d2201f2fSdrahn 	      if (! ((*info->callbacks->undefined_symbol)
487d2201f2fSdrahn 		     (info, name, input_bfd, input_section,
488d2201f2fSdrahn 		      rel->r_offset, TRUE)))
489d2201f2fSdrahn 		return FALSE;
490d2201f2fSdrahn 	      break;
491d2201f2fSdrahn 
492d2201f2fSdrahn 	    case bfd_reloc_outofrange:
493d2201f2fSdrahn 	      msg = _("internal error: out of range error");
494d2201f2fSdrahn 	      goto common_error;
495d2201f2fSdrahn 
496d2201f2fSdrahn 	    case bfd_reloc_notsupported:
497d2201f2fSdrahn 	      msg = _("internal error: unsupported relocation error");
498d2201f2fSdrahn 	      goto common_error;
499d2201f2fSdrahn 
500d2201f2fSdrahn 	    case bfd_reloc_dangerous:
501d2201f2fSdrahn 	      msg = _("internal error: dangerous error");
502d2201f2fSdrahn 	      goto common_error;
503d2201f2fSdrahn 
504d2201f2fSdrahn 	    default:
505d2201f2fSdrahn 	      msg = _("internal error: unknown error");
506d2201f2fSdrahn 	      /* fall through */
507d2201f2fSdrahn 
508d2201f2fSdrahn 	    common_error:
509d2201f2fSdrahn 	      if (!((*info->callbacks->warning)
510d2201f2fSdrahn 		    (info, msg, name, input_bfd, input_section,
511d2201f2fSdrahn 		     rel->r_offset)))
512d2201f2fSdrahn 		return FALSE;
513d2201f2fSdrahn 	      break;
514d2201f2fSdrahn 	    }
515d2201f2fSdrahn 	}
516d2201f2fSdrahn     }
517d2201f2fSdrahn 
518d2201f2fSdrahn   return TRUE;
519d2201f2fSdrahn }
520d2201f2fSdrahn 
521d2201f2fSdrahn /* Object files encode the specific H8 model they were compiled
522d2201f2fSdrahn    for in the ELF flags field.
523d2201f2fSdrahn 
524d2201f2fSdrahn    Examine that field and return the proper BFD machine type for
525d2201f2fSdrahn    the object file.  */
526d2201f2fSdrahn static unsigned long
elf32_h8_mach(flagword flags)527*cf2f2c56Smiod elf32_h8_mach (flagword flags)
528d2201f2fSdrahn {
529d2201f2fSdrahn   switch (flags & EF_H8_MACH)
530d2201f2fSdrahn     {
531d2201f2fSdrahn     case E_H8_MACH_H8300:
532d2201f2fSdrahn     default:
533d2201f2fSdrahn       return bfd_mach_h8300;
534d2201f2fSdrahn 
535d2201f2fSdrahn     case E_H8_MACH_H8300H:
536d2201f2fSdrahn       return bfd_mach_h8300h;
537d2201f2fSdrahn 
538d2201f2fSdrahn     case E_H8_MACH_H8300S:
539d2201f2fSdrahn       return bfd_mach_h8300s;
540d2201f2fSdrahn 
541d2201f2fSdrahn     case E_H8_MACH_H8300HN:
542d2201f2fSdrahn       return bfd_mach_h8300hn;
543d2201f2fSdrahn 
544d2201f2fSdrahn     case E_H8_MACH_H8300SN:
545d2201f2fSdrahn       return bfd_mach_h8300sn;
546*cf2f2c56Smiod 
547*cf2f2c56Smiod     case E_H8_MACH_H8300SX:
548*cf2f2c56Smiod       return bfd_mach_h8300sx;
549*cf2f2c56Smiod 
550*cf2f2c56Smiod     case E_H8_MACH_H8300SXN:
551*cf2f2c56Smiod       return bfd_mach_h8300sxn;
552d2201f2fSdrahn     }
553d2201f2fSdrahn }
554d2201f2fSdrahn 
555d2201f2fSdrahn /* The final processing done just before writing out a H8 ELF object
556d2201f2fSdrahn    file.  We use this opportunity to encode the BFD machine type
557d2201f2fSdrahn    into the flags field in the object file.  */
558d2201f2fSdrahn 
559d2201f2fSdrahn static void
elf32_h8_final_write_processing(bfd * abfd,bfd_boolean linker ATTRIBUTE_UNUSED)560*cf2f2c56Smiod elf32_h8_final_write_processing (bfd *abfd,
561*cf2f2c56Smiod 				 bfd_boolean linker ATTRIBUTE_UNUSED)
562d2201f2fSdrahn {
563d2201f2fSdrahn   unsigned long val;
564d2201f2fSdrahn 
565d2201f2fSdrahn   switch (bfd_get_mach (abfd))
566d2201f2fSdrahn     {
567d2201f2fSdrahn     default:
568d2201f2fSdrahn     case bfd_mach_h8300:
569d2201f2fSdrahn       val = E_H8_MACH_H8300;
570d2201f2fSdrahn       break;
571d2201f2fSdrahn 
572d2201f2fSdrahn     case bfd_mach_h8300h:
573d2201f2fSdrahn       val = E_H8_MACH_H8300H;
574d2201f2fSdrahn       break;
575d2201f2fSdrahn 
576d2201f2fSdrahn     case bfd_mach_h8300s:
577d2201f2fSdrahn       val = E_H8_MACH_H8300S;
578d2201f2fSdrahn       break;
579d2201f2fSdrahn 
580d2201f2fSdrahn     case bfd_mach_h8300hn:
581d2201f2fSdrahn       val = E_H8_MACH_H8300HN;
582d2201f2fSdrahn       break;
583d2201f2fSdrahn 
584d2201f2fSdrahn     case bfd_mach_h8300sn:
585d2201f2fSdrahn       val = E_H8_MACH_H8300SN;
586d2201f2fSdrahn       break;
587*cf2f2c56Smiod 
588*cf2f2c56Smiod     case bfd_mach_h8300sx:
589*cf2f2c56Smiod       val = E_H8_MACH_H8300SX;
590*cf2f2c56Smiod       break;
591*cf2f2c56Smiod 
592*cf2f2c56Smiod     case bfd_mach_h8300sxn:
593*cf2f2c56Smiod       val = E_H8_MACH_H8300SXN;
594*cf2f2c56Smiod       break;
595d2201f2fSdrahn     }
596d2201f2fSdrahn 
597d2201f2fSdrahn   elf_elfheader (abfd)->e_flags &= ~ (EF_H8_MACH);
598d2201f2fSdrahn   elf_elfheader (abfd)->e_flags |= val;
599d2201f2fSdrahn }
600d2201f2fSdrahn 
601d2201f2fSdrahn /* Return nonzero if ABFD represents a valid H8 ELF object file; also
602d2201f2fSdrahn    record the encoded machine type found in the ELF flags.  */
603d2201f2fSdrahn 
604d2201f2fSdrahn static bfd_boolean
elf32_h8_object_p(bfd * abfd)605*cf2f2c56Smiod elf32_h8_object_p (bfd *abfd)
606d2201f2fSdrahn {
607d2201f2fSdrahn   bfd_default_set_arch_mach (abfd, bfd_arch_h8300,
608d2201f2fSdrahn 			     elf32_h8_mach (elf_elfheader (abfd)->e_flags));
609d2201f2fSdrahn   return TRUE;
610d2201f2fSdrahn }
611d2201f2fSdrahn 
612d2201f2fSdrahn /* Merge backend specific data from an object file to the output
613d2201f2fSdrahn    object file when linking.  The only data we need to copy at this
614d2201f2fSdrahn    time is the architecture/machine information.  */
615d2201f2fSdrahn 
616d2201f2fSdrahn static bfd_boolean
elf32_h8_merge_private_bfd_data(bfd * ibfd,bfd * obfd)617*cf2f2c56Smiod elf32_h8_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
618d2201f2fSdrahn {
619d2201f2fSdrahn   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
620d2201f2fSdrahn       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
621d2201f2fSdrahn     return TRUE;
622d2201f2fSdrahn 
623d2201f2fSdrahn   if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
624d2201f2fSdrahn       && bfd_get_mach (obfd) < bfd_get_mach (ibfd))
625d2201f2fSdrahn     {
626d2201f2fSdrahn       if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
627d2201f2fSdrahn 			       bfd_get_mach (ibfd)))
628d2201f2fSdrahn 	return FALSE;
629d2201f2fSdrahn     }
630d2201f2fSdrahn 
631d2201f2fSdrahn   return TRUE;
632d2201f2fSdrahn }
633d2201f2fSdrahn 
634d2201f2fSdrahn /* This function handles relaxing for the H8..
635d2201f2fSdrahn 
636*cf2f2c56Smiod    There are a few relaxing opportunities available on the H8:
637d2201f2fSdrahn 
638d2201f2fSdrahn      jmp/jsr:24    ->    bra/bsr:8		2 bytes
639d2201f2fSdrahn      The jmp may be completely eliminated if the previous insn is a
640d2201f2fSdrahn      conditional branch to the insn after the jump.  In that case
641d2201f2fSdrahn      we invert the branch and delete the jump and save 4 bytes.
642d2201f2fSdrahn 
643d2201f2fSdrahn      bCC:16          ->    bCC:8                  2 bytes
644d2201f2fSdrahn      bsr:16          ->    bsr:8                  2 bytes
645d2201f2fSdrahn 
646*cf2f2c56Smiod      bset:16	     ->    bset:8                 2 bytes
647*cf2f2c56Smiod      bset:24/32	     ->    bset:8                 4 bytes
648*cf2f2c56Smiod      (also applicable to other bit manipulation instructions)
649*cf2f2c56Smiod 
650d2201f2fSdrahn      mov.b:16	     ->    mov.b:8                2 bytes
651d2201f2fSdrahn      mov.b:24/32     ->    mov.b:8                4 bytes
652d2201f2fSdrahn 
653*cf2f2c56Smiod      bset:24/32	     ->    bset:16                2 bytes
654*cf2f2c56Smiod      (also applicable to other bit manipulation instructions)
655*cf2f2c56Smiod 
656d2201f2fSdrahn      mov.[bwl]:24/32 ->    mov.[bwl]:16           2 bytes */
657d2201f2fSdrahn 
658d2201f2fSdrahn static bfd_boolean
elf32_h8_relax_section(bfd * abfd,asection * sec,struct bfd_link_info * link_info,bfd_boolean * again)659*cf2f2c56Smiod elf32_h8_relax_section (bfd *abfd, asection *sec,
660*cf2f2c56Smiod 			struct bfd_link_info *link_info, bfd_boolean *again)
661d2201f2fSdrahn {
662d2201f2fSdrahn   Elf_Internal_Shdr *symtab_hdr;
663d2201f2fSdrahn   Elf_Internal_Rela *internal_relocs;
664d2201f2fSdrahn   Elf_Internal_Rela *irel, *irelend;
665d2201f2fSdrahn   bfd_byte *contents = NULL;
666d2201f2fSdrahn   Elf_Internal_Sym *isymbuf = NULL;
667d2201f2fSdrahn   static asection *last_input_section = NULL;
668d2201f2fSdrahn   static Elf_Internal_Rela *last_reloc = NULL;
669d2201f2fSdrahn 
670d2201f2fSdrahn   /* Assume nothing changes.  */
671d2201f2fSdrahn   *again = FALSE;
672d2201f2fSdrahn 
673*cf2f2c56Smiod   /* We don't have to do anything for a relocatable link, if
674d2201f2fSdrahn      this section does not have relocs, or if this is not a
675d2201f2fSdrahn      code section.  */
676*cf2f2c56Smiod   if (link_info->relocatable
677d2201f2fSdrahn       || (sec->flags & SEC_RELOC) == 0
678d2201f2fSdrahn       || sec->reloc_count == 0
679d2201f2fSdrahn       || (sec->flags & SEC_CODE) == 0)
680d2201f2fSdrahn     return TRUE;
681d2201f2fSdrahn 
682d2201f2fSdrahn   /* If this is the first time we have been called for this section,
683d2201f2fSdrahn      initialize the cooked size.  */
684d2201f2fSdrahn   if (sec->_cooked_size == 0)
685d2201f2fSdrahn     sec->_cooked_size = sec->_raw_size;
686d2201f2fSdrahn 
687d2201f2fSdrahn   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
688d2201f2fSdrahn 
689d2201f2fSdrahn   /* Get a copy of the native relocations.  */
690*cf2f2c56Smiod   internal_relocs = (_bfd_elf_link_read_relocs
691d2201f2fSdrahn 		     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
692d2201f2fSdrahn 		      link_info->keep_memory));
693d2201f2fSdrahn   if (internal_relocs == NULL)
694d2201f2fSdrahn     goto error_return;
695d2201f2fSdrahn 
696d2201f2fSdrahn   if (sec != last_input_section)
697d2201f2fSdrahn     last_reloc = NULL;
698d2201f2fSdrahn 
699d2201f2fSdrahn   last_input_section = sec;
700d2201f2fSdrahn 
701d2201f2fSdrahn   /* Walk through the relocs looking for relaxing opportunities.  */
702d2201f2fSdrahn   irelend = internal_relocs + sec->reloc_count;
703d2201f2fSdrahn   for (irel = internal_relocs; irel < irelend; irel++)
704d2201f2fSdrahn     {
705d2201f2fSdrahn       bfd_vma symval;
706d2201f2fSdrahn 
707d2201f2fSdrahn       /* Keep track of the previous reloc so that we can delete
708d2201f2fSdrahn 	 some long jumps created by the compiler.  */
709d2201f2fSdrahn       if (irel != internal_relocs)
710d2201f2fSdrahn 	last_reloc = irel - 1;
711d2201f2fSdrahn 
712d2201f2fSdrahn       if (ELF32_R_TYPE (irel->r_info) != R_H8_DIR24R8
713d2201f2fSdrahn 	  && ELF32_R_TYPE (irel->r_info) != R_H8_PCREL16
714d2201f2fSdrahn 	  && ELF32_R_TYPE (irel->r_info) != R_H8_DIR16A8
715d2201f2fSdrahn 	  && ELF32_R_TYPE (irel->r_info) != R_H8_DIR24A8
716d2201f2fSdrahn 	  && ELF32_R_TYPE (irel->r_info) != R_H8_DIR32A16)
717d2201f2fSdrahn 	continue;
718d2201f2fSdrahn 
719d2201f2fSdrahn       /* Get the section contents if we haven't done so already.  */
720d2201f2fSdrahn       if (contents == NULL)
721d2201f2fSdrahn 	{
722d2201f2fSdrahn 	  /* Get cached copy if it exists.  */
723d2201f2fSdrahn 	  if (elf_section_data (sec)->this_hdr.contents != NULL)
724d2201f2fSdrahn 	    contents = elf_section_data (sec)->this_hdr.contents;
725d2201f2fSdrahn 	  else
726d2201f2fSdrahn 	    {
727d2201f2fSdrahn 	      /* Go get them off disk.  */
728d2201f2fSdrahn 	      contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
729d2201f2fSdrahn 	      if (contents == NULL)
730d2201f2fSdrahn 		goto error_return;
731d2201f2fSdrahn 
732d2201f2fSdrahn 	      if (! bfd_get_section_contents (abfd, sec, contents,
733d2201f2fSdrahn 					      (file_ptr) 0, sec->_raw_size))
734d2201f2fSdrahn 		goto error_return;
735d2201f2fSdrahn 	    }
736d2201f2fSdrahn 	}
737d2201f2fSdrahn 
738d2201f2fSdrahn       /* Read this BFD's local symbols if we haven't done so already.  */
739d2201f2fSdrahn       if (isymbuf == NULL && symtab_hdr->sh_info != 0)
740d2201f2fSdrahn 	{
741d2201f2fSdrahn 	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
742d2201f2fSdrahn 	  if (isymbuf == NULL)
743d2201f2fSdrahn 	    isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
744d2201f2fSdrahn 					    symtab_hdr->sh_info, 0,
745d2201f2fSdrahn 					    NULL, NULL, NULL);
746d2201f2fSdrahn 	  if (isymbuf == NULL)
747d2201f2fSdrahn 	    goto error_return;
748d2201f2fSdrahn 	}
749d2201f2fSdrahn 
750d2201f2fSdrahn       /* Get the value of the symbol referred to by the reloc.  */
751d2201f2fSdrahn       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
752d2201f2fSdrahn 	{
753d2201f2fSdrahn 	  /* A local symbol.  */
754d2201f2fSdrahn 	  Elf_Internal_Sym *isym;
755d2201f2fSdrahn 	  asection *sym_sec;
756d2201f2fSdrahn 
757d2201f2fSdrahn 	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
758d2201f2fSdrahn 	  sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
759*cf2f2c56Smiod 	  symval = isym->st_value;
760*cf2f2c56Smiod 	  /* If the reloc is absolute, it will not have
761*cf2f2c56Smiod 	     a symbol or section associated with it.  */
762*cf2f2c56Smiod 	  if (sym_sec)
763*cf2f2c56Smiod 	    symval += sym_sec->output_section->vma
764*cf2f2c56Smiod 	      + sym_sec->output_offset;
765d2201f2fSdrahn 	}
766d2201f2fSdrahn       else
767d2201f2fSdrahn 	{
768d2201f2fSdrahn 	  unsigned long indx;
769d2201f2fSdrahn 	  struct elf_link_hash_entry *h;
770d2201f2fSdrahn 
771d2201f2fSdrahn 	  /* An external symbol.  */
772d2201f2fSdrahn 	  indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
773d2201f2fSdrahn 	  h = elf_sym_hashes (abfd)[indx];
774d2201f2fSdrahn 	  BFD_ASSERT (h != NULL);
775d2201f2fSdrahn 	  if (h->root.type != bfd_link_hash_defined
776d2201f2fSdrahn 	      && h->root.type != bfd_link_hash_defweak)
777d2201f2fSdrahn 	    {
778d2201f2fSdrahn 	      /* This appears to be a reference to an undefined
779d2201f2fSdrahn                  symbol.  Just ignore it--it will be caught by the
780d2201f2fSdrahn                  regular reloc processing.  */
781d2201f2fSdrahn 	      continue;
782d2201f2fSdrahn 	    }
783d2201f2fSdrahn 
784d2201f2fSdrahn 	  symval = (h->root.u.def.value
785d2201f2fSdrahn 		    + h->root.u.def.section->output_section->vma
786d2201f2fSdrahn 		    + h->root.u.def.section->output_offset);
787d2201f2fSdrahn 	}
788d2201f2fSdrahn 
789d2201f2fSdrahn       /* For simplicity of coding, we are going to modify the section
790d2201f2fSdrahn 	 contents, the section relocs, and the BFD symbol table.  We
791d2201f2fSdrahn 	 must tell the rest of the code not to free up this
792d2201f2fSdrahn 	 information.  It would be possible to instead create a table
793d2201f2fSdrahn 	 of changes which have to be made, as is done in coff-mips.c;
794d2201f2fSdrahn 	 that would be more work, but would require less memory when
795d2201f2fSdrahn 	 the linker is run.  */
796d2201f2fSdrahn       switch (ELF32_R_TYPE (irel->r_info))
797d2201f2fSdrahn 	{
798*cf2f2c56Smiod         /* Try to turn a 24-bit absolute branch/call into an 8-bit
799d2201f2fSdrahn 	   pc-relative branch/call.  */
800d2201f2fSdrahn 	case R_H8_DIR24R8:
801d2201f2fSdrahn 	  {
802d2201f2fSdrahn 	    bfd_vma value = symval + irel->r_addend;
803d2201f2fSdrahn 	    bfd_vma dot, gap;
804d2201f2fSdrahn 
805d2201f2fSdrahn 	    /* Get the address of this instruction.  */
806d2201f2fSdrahn 	    dot = (sec->output_section->vma
807d2201f2fSdrahn 		   + sec->output_offset + irel->r_offset - 1);
808d2201f2fSdrahn 
809d2201f2fSdrahn 	    /* Compute the distance from this insn to the branch target.  */
810d2201f2fSdrahn 	    gap = value - dot;
811d2201f2fSdrahn 
812d2201f2fSdrahn 	    /* If the distance is within -126..+130 inclusive, then we can
813d2201f2fSdrahn 	       relax this jump.  +130 is valid since the target will move
814d2201f2fSdrahn 	       two bytes closer if we do relax this branch.  */
815d2201f2fSdrahn 	    if ((int) gap >= -126 && (int) gap <= 130)
816d2201f2fSdrahn 	      {
817d2201f2fSdrahn 		unsigned char code;
818d2201f2fSdrahn 
819d2201f2fSdrahn 		/* Note that we've changed the relocs, section contents,
820d2201f2fSdrahn 		   etc.  */
821d2201f2fSdrahn 		elf_section_data (sec)->relocs = internal_relocs;
822d2201f2fSdrahn 		elf_section_data (sec)->this_hdr.contents = contents;
823d2201f2fSdrahn 		symtab_hdr->contents = (unsigned char *) isymbuf;
824d2201f2fSdrahn 
825d2201f2fSdrahn 		/* Get the instruction code being relaxed.  */
826d2201f2fSdrahn 		code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
827d2201f2fSdrahn 
828d2201f2fSdrahn 		/* If the previous instruction conditionally jumped around
829d2201f2fSdrahn 		   this instruction, we may be able to reverse the condition
830d2201f2fSdrahn 		   and redirect the previous instruction to the target of
831d2201f2fSdrahn 		   this instruction.
832d2201f2fSdrahn 
833d2201f2fSdrahn 		   Such sequences are used by the compiler to deal with
834d2201f2fSdrahn 		   long conditional branches.
835d2201f2fSdrahn 
836d2201f2fSdrahn 		   Only perform this optimisation for jumps (code 0x5a) not
837d2201f2fSdrahn 		   subroutine calls, as otherwise it could transform:
838d2201f2fSdrahn 
839d2201f2fSdrahn 		   	             mov.w   r0,r0
840d2201f2fSdrahn 		   	             beq     .L1
841d2201f2fSdrahn 		         	     jsr     @_bar
842d2201f2fSdrahn 		              .L1:   rts
843d2201f2fSdrahn 		              _bar:  rts
844d2201f2fSdrahn 		   into:
845d2201f2fSdrahn 		   	             mov.w   r0,r0
846d2201f2fSdrahn 			             bne     _bar
847d2201f2fSdrahn 			             rts
848d2201f2fSdrahn 			      _bar:  rts
849d2201f2fSdrahn 
850d2201f2fSdrahn 		   which changes the call (jsr) into a branch (bne).  */
851d2201f2fSdrahn 		if (code == 0x5a
852d2201f2fSdrahn 		    && (int) gap <= 130
853d2201f2fSdrahn 		    && (int) gap >= -128
854d2201f2fSdrahn 		    && last_reloc
855d2201f2fSdrahn 		    && ELF32_R_TYPE (last_reloc->r_info) == R_H8_PCREL8
856d2201f2fSdrahn 		    && ELF32_R_SYM (last_reloc->r_info) < symtab_hdr->sh_info)
857d2201f2fSdrahn 		  {
858d2201f2fSdrahn 		    bfd_vma last_value;
859d2201f2fSdrahn 		    asection *last_sym_sec;
860d2201f2fSdrahn 		    Elf_Internal_Sym *last_sym;
861d2201f2fSdrahn 
862d2201f2fSdrahn 		    /* We will need to examine the symbol used by the
863d2201f2fSdrahn 		       previous relocation.  */
864d2201f2fSdrahn 
865d2201f2fSdrahn 		    last_sym = isymbuf + ELF32_R_SYM (last_reloc->r_info);
866d2201f2fSdrahn 		    last_sym_sec
867d2201f2fSdrahn 		      = bfd_section_from_elf_index (abfd, last_sym->st_shndx);
868d2201f2fSdrahn 		    last_value = (last_sym->st_value
869d2201f2fSdrahn 				  + last_sym_sec->output_section->vma
870d2201f2fSdrahn 				  + last_sym_sec->output_offset);
871d2201f2fSdrahn 
872d2201f2fSdrahn 		    /* Verify that the previous relocation was for a
873d2201f2fSdrahn 		       branch around this instruction and that no symbol
874d2201f2fSdrahn 		       exists at the current location.  */
875d2201f2fSdrahn 		    if (last_value == dot + 4
876d2201f2fSdrahn 			&& last_reloc->r_offset + 2 == irel->r_offset
877d2201f2fSdrahn 			&& ! elf32_h8_symbol_address_p (abfd, sec, dot))
878d2201f2fSdrahn 		      {
879d2201f2fSdrahn 			/* We can eliminate this jump.  Twiddle the
880d2201f2fSdrahn 			   previous relocation as necessary.  */
881d2201f2fSdrahn 			irel->r_info
882d2201f2fSdrahn 			  = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
883d2201f2fSdrahn 					  ELF32_R_TYPE (R_H8_NONE));
884d2201f2fSdrahn 
885d2201f2fSdrahn 			last_reloc->r_info
886d2201f2fSdrahn 			  = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
887d2201f2fSdrahn 					  ELF32_R_TYPE (R_H8_PCREL8));
888d2201f2fSdrahn 			last_reloc->r_addend = irel->r_addend;
889d2201f2fSdrahn 
890d2201f2fSdrahn 			code = bfd_get_8 (abfd,
891d2201f2fSdrahn 					  contents + last_reloc->r_offset - 1);
892d2201f2fSdrahn 			code ^= 1;
893d2201f2fSdrahn 			bfd_put_8 (abfd,
894d2201f2fSdrahn 				   code,
895d2201f2fSdrahn 			contents + last_reloc->r_offset - 1);
896d2201f2fSdrahn 
897d2201f2fSdrahn 			/* Delete four bytes of data.  */
898d2201f2fSdrahn 			if (!elf32_h8_relax_delete_bytes (abfd, sec,
899d2201f2fSdrahn 							  irel->r_offset - 1,
900d2201f2fSdrahn 							  4))
901d2201f2fSdrahn 			  goto error_return;
902d2201f2fSdrahn 
903d2201f2fSdrahn 			*again = TRUE;
904d2201f2fSdrahn 			break;
905d2201f2fSdrahn 		      }
906d2201f2fSdrahn 		  }
907d2201f2fSdrahn 
908d2201f2fSdrahn 		if (code == 0x5e)
909*cf2f2c56Smiod 		  /* This is jsr.  */
910d2201f2fSdrahn 		  bfd_put_8 (abfd, 0x55, contents + irel->r_offset - 1);
911d2201f2fSdrahn 		else if (code == 0x5a)
912*cf2f2c56Smiod 		  /* This is jmp.  */
913d2201f2fSdrahn 		  bfd_put_8 (abfd, 0x40, contents + irel->r_offset - 1);
914d2201f2fSdrahn 		else
915d2201f2fSdrahn 		  abort ();
916d2201f2fSdrahn 
917d2201f2fSdrahn 		/* Fix the relocation's type.  */
918d2201f2fSdrahn 		irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
919d2201f2fSdrahn 					     R_H8_PCREL8);
920d2201f2fSdrahn 
921d2201f2fSdrahn 		/* Delete two bytes of data.  */
922d2201f2fSdrahn 		if (!elf32_h8_relax_delete_bytes (abfd, sec,
923d2201f2fSdrahn 						  irel->r_offset + 1, 2))
924d2201f2fSdrahn 		  goto error_return;
925d2201f2fSdrahn 
926d2201f2fSdrahn 		/* That will change things, so, we should relax again.
927d2201f2fSdrahn 		   Note that this is not required, and it may be slow.  */
928d2201f2fSdrahn 		*again = TRUE;
929d2201f2fSdrahn 	      }
930d2201f2fSdrahn 	    break;
931d2201f2fSdrahn 	  }
932d2201f2fSdrahn 
933*cf2f2c56Smiod 	/* Try to turn a 16-bit pc-relative branch into a 8-bit pc-relative
934d2201f2fSdrahn 	   branch.  */
935d2201f2fSdrahn 	case R_H8_PCREL16:
936d2201f2fSdrahn 	  {
937d2201f2fSdrahn 	    bfd_vma value = symval + irel->r_addend;
938d2201f2fSdrahn 	    bfd_vma dot;
939d2201f2fSdrahn 	    bfd_vma gap;
940d2201f2fSdrahn 
941d2201f2fSdrahn 	    /* Get the address of this instruction.  */
942d2201f2fSdrahn 	    dot = (sec->output_section->vma
943d2201f2fSdrahn 		   + sec->output_offset
944d2201f2fSdrahn 		   + irel->r_offset - 2);
945d2201f2fSdrahn 
946d2201f2fSdrahn 	    gap = value - dot;
947d2201f2fSdrahn 
948d2201f2fSdrahn 	    /* If the distance is within -126..+130 inclusive, then we can
949d2201f2fSdrahn 	       relax this jump.  +130 is valid since the target will move
950d2201f2fSdrahn 	       two bytes closer if we do relax this branch.  */
951d2201f2fSdrahn 	    if ((int) gap >= -126 && (int) gap <= 130)
952d2201f2fSdrahn 	      {
953d2201f2fSdrahn 		unsigned char code;
954d2201f2fSdrahn 
955d2201f2fSdrahn 		/* Note that we've changed the relocs, section contents,
956d2201f2fSdrahn 		   etc.  */
957d2201f2fSdrahn 		elf_section_data (sec)->relocs = internal_relocs;
958d2201f2fSdrahn 		elf_section_data (sec)->this_hdr.contents = contents;
959d2201f2fSdrahn 		symtab_hdr->contents = (unsigned char *) isymbuf;
960d2201f2fSdrahn 
961d2201f2fSdrahn 		/* Get the opcode.  */
962d2201f2fSdrahn 		code = bfd_get_8 (abfd, contents + irel->r_offset - 2);
963d2201f2fSdrahn 
964d2201f2fSdrahn 		if (code == 0x58)
965d2201f2fSdrahn 		  {
966d2201f2fSdrahn 		    /* bCC:16 -> bCC:8 */
967*cf2f2c56Smiod 		    /* Get the second byte of the original insn, which
968*cf2f2c56Smiod 		       contains the condition code.  */
969d2201f2fSdrahn 		    code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
970*cf2f2c56Smiod 
971*cf2f2c56Smiod 		    /* Compute the fisrt byte of the relaxed
972*cf2f2c56Smiod 		       instruction.  The original sequence 0x58 0xX0
973*cf2f2c56Smiod 		       is relaxed to 0x4X, where X represents the
974*cf2f2c56Smiod 		       condition code.  */
975d2201f2fSdrahn 		    code &= 0xf0;
976d2201f2fSdrahn 		    code >>= 4;
977d2201f2fSdrahn 		    code |= 0x40;
978d2201f2fSdrahn 		    bfd_put_8 (abfd, code, contents + irel->r_offset - 2);
979d2201f2fSdrahn 		  }
980d2201f2fSdrahn 		else if (code == 0x5c)
981*cf2f2c56Smiod 		  /* This is bsr.  */
982d2201f2fSdrahn 		  bfd_put_8 (abfd, 0x55, contents + irel->r_offset - 2);
983d2201f2fSdrahn 		else
984d2201f2fSdrahn 		  abort ();
985d2201f2fSdrahn 
986d2201f2fSdrahn 		/* Fix the relocation's type.  */
987d2201f2fSdrahn 		irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
988d2201f2fSdrahn 					     R_H8_PCREL8);
989d2201f2fSdrahn 		irel->r_offset--;
990d2201f2fSdrahn 
991d2201f2fSdrahn 		/* Delete two bytes of data.  */
992d2201f2fSdrahn 		if (!elf32_h8_relax_delete_bytes (abfd, sec,
993d2201f2fSdrahn 						  irel->r_offset + 1, 2))
994d2201f2fSdrahn 		  goto error_return;
995d2201f2fSdrahn 
996d2201f2fSdrahn 		/* That will change things, so, we should relax again.
997d2201f2fSdrahn 		   Note that this is not required, and it may be slow.  */
998d2201f2fSdrahn 		*again = TRUE;
999d2201f2fSdrahn 	      }
1000d2201f2fSdrahn 	    break;
1001d2201f2fSdrahn 	  }
1002d2201f2fSdrahn 
1003*cf2f2c56Smiod 	/* This is a 16-bit absolute address in one of the following
1004*cf2f2c56Smiod 	   instructions:
1005*cf2f2c56Smiod 
1006*cf2f2c56Smiod 	     "band", "bclr", "biand", "bild", "bior", "bist", "bixor",
1007*cf2f2c56Smiod 	     "bld", "bnot", "bor", "bset", "bst", "btst", "bxor", and
1008*cf2f2c56Smiod 	     "mov.b"
1009*cf2f2c56Smiod 
1010*cf2f2c56Smiod 	   We may relax this into an 8-bit absolute address if it's in
1011*cf2f2c56Smiod 	   the right range.  */
1012d2201f2fSdrahn 	case R_H8_DIR16A8:
1013d2201f2fSdrahn 	  {
1014*cf2f2c56Smiod 	    bfd_vma value;
1015d2201f2fSdrahn 
1016*cf2f2c56Smiod 	    value = bfd_h8300_pad_address (abfd, symval + irel->r_addend);
1017*cf2f2c56Smiod 	    if (value >= 0xffffff00u)
1018d2201f2fSdrahn 	      {
1019d2201f2fSdrahn 		unsigned char code;
1020*cf2f2c56Smiod 		unsigned char temp_code;
1021d2201f2fSdrahn 
1022d2201f2fSdrahn 		/* Note that we've changed the relocs, section contents,
1023d2201f2fSdrahn 		   etc.  */
1024d2201f2fSdrahn 		elf_section_data (sec)->relocs = internal_relocs;
1025d2201f2fSdrahn 		elf_section_data (sec)->this_hdr.contents = contents;
1026d2201f2fSdrahn 		symtab_hdr->contents = (unsigned char *) isymbuf;
1027d2201f2fSdrahn 
1028d2201f2fSdrahn 		/* Get the opcode.  */
1029d2201f2fSdrahn 		code = bfd_get_8 (abfd, contents + irel->r_offset - 2);
1030d2201f2fSdrahn 
1031*cf2f2c56Smiod 		/* All instructions with R_H8_DIR16A8 start with
1032*cf2f2c56Smiod 		   0x6a.  */
1033d2201f2fSdrahn 		if (code != 0x6a)
1034d2201f2fSdrahn 		  abort ();
1035d2201f2fSdrahn 
1036*cf2f2c56Smiod 		temp_code = code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
1037*cf2f2c56Smiod 		/* If this is a mov.b instruction, clear the lower
1038*cf2f2c56Smiod 		   nibble, which contains the source/destination
1039*cf2f2c56Smiod 		   register number.  */
1040*cf2f2c56Smiod 		if ((temp_code & 0x10) != 0x10)
1041*cf2f2c56Smiod 		  temp_code &= 0xf0;
1042d2201f2fSdrahn 
1043*cf2f2c56Smiod 		switch (temp_code)
1044*cf2f2c56Smiod 		  {
1045*cf2f2c56Smiod 		  case 0x00:
1046*cf2f2c56Smiod 		    /* This is mov.b @aa:16,Rd.  */
1047*cf2f2c56Smiod 		    bfd_put_8 (abfd, (code & 0xf) | 0x20,
1048d2201f2fSdrahn 			       contents + irel->r_offset - 2);
1049*cf2f2c56Smiod 		    break;
1050*cf2f2c56Smiod 		  case 0x80:
1051*cf2f2c56Smiod 		    /* This is mov.b Rs,@aa:16.  */
1052*cf2f2c56Smiod 		    bfd_put_8 (abfd, (code & 0xf) | 0x30,
1053d2201f2fSdrahn 			       contents + irel->r_offset - 2);
1054*cf2f2c56Smiod 		    break;
1055*cf2f2c56Smiod 		  case 0x18:
1056*cf2f2c56Smiod 		    /* This is a bit-maniputation instruction that
1057*cf2f2c56Smiod 		       stores one bit into memory, one of "bclr",
1058*cf2f2c56Smiod 		       "bist", "bnot", "bset", and "bst".  */
1059*cf2f2c56Smiod 		    bfd_put_8 (abfd, 0x7f, contents + irel->r_offset - 2);
1060*cf2f2c56Smiod 		    break;
1061*cf2f2c56Smiod 		  case 0x10:
1062*cf2f2c56Smiod 		    /* This is a bit-maniputation instruction that
1063*cf2f2c56Smiod 		       loads one bit from memory, one of "band",
1064*cf2f2c56Smiod 		       "biand", "bild", "bior", "bixor", "bld", "bor",
1065*cf2f2c56Smiod 		       "btst", and "bxor".  */
1066*cf2f2c56Smiod 		    bfd_put_8 (abfd, 0x7e, contents + irel->r_offset - 2);
1067*cf2f2c56Smiod 		    break;
1068*cf2f2c56Smiod 		  default:
1069d2201f2fSdrahn 		    abort ();
1070*cf2f2c56Smiod 		  }
1071d2201f2fSdrahn 
1072d2201f2fSdrahn 		/* Fix the relocation's type.  */
1073d2201f2fSdrahn 		irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1074d2201f2fSdrahn 					     R_H8_DIR8);
1075d2201f2fSdrahn 
1076*cf2f2c56Smiod 		/* Move the relocation.  */
1077*cf2f2c56Smiod 		irel->r_offset--;
1078*cf2f2c56Smiod 
1079d2201f2fSdrahn 		/* Delete two bytes of data.  */
1080d2201f2fSdrahn 		if (!elf32_h8_relax_delete_bytes (abfd, sec,
1081d2201f2fSdrahn 						  irel->r_offset + 1, 2))
1082d2201f2fSdrahn 		  goto error_return;
1083d2201f2fSdrahn 
1084d2201f2fSdrahn 		/* That will change things, so, we should relax again.
1085d2201f2fSdrahn 		   Note that this is not required, and it may be slow.  */
1086d2201f2fSdrahn 		*again = TRUE;
1087d2201f2fSdrahn 	      }
1088d2201f2fSdrahn 	    break;
1089d2201f2fSdrahn 	  }
1090d2201f2fSdrahn 
1091*cf2f2c56Smiod 	/* This is a 24-bit absolute address in one of the following
1092*cf2f2c56Smiod 	   instructions:
1093*cf2f2c56Smiod 
1094*cf2f2c56Smiod 	     "band", "bclr", "biand", "bild", "bior", "bist", "bixor",
1095*cf2f2c56Smiod 	     "bld", "bnot", "bor", "bset", "bst", "btst", "bxor", and
1096*cf2f2c56Smiod 	     "mov.b"
1097*cf2f2c56Smiod 
1098*cf2f2c56Smiod 	   We may relax this into an 8-bit absolute address if it's in
1099*cf2f2c56Smiod 	   the right range.  */
1100d2201f2fSdrahn 	case R_H8_DIR24A8:
1101d2201f2fSdrahn 	  {
1102*cf2f2c56Smiod 	    bfd_vma value;
1103d2201f2fSdrahn 
1104*cf2f2c56Smiod 	    value = bfd_h8300_pad_address (abfd, symval + irel->r_addend);
1105*cf2f2c56Smiod 	    if (value >= 0xffffff00u)
1106d2201f2fSdrahn 	      {
1107d2201f2fSdrahn 		unsigned char code;
1108*cf2f2c56Smiod 		unsigned char temp_code;
1109d2201f2fSdrahn 
1110d2201f2fSdrahn 		/* Note that we've changed the relocs, section contents,
1111d2201f2fSdrahn 		   etc.  */
1112d2201f2fSdrahn 		elf_section_data (sec)->relocs = internal_relocs;
1113d2201f2fSdrahn 		elf_section_data (sec)->this_hdr.contents = contents;
1114d2201f2fSdrahn 		symtab_hdr->contents = (unsigned char *) isymbuf;
1115d2201f2fSdrahn 
1116d2201f2fSdrahn 		/* Get the opcode.  */
1117d2201f2fSdrahn 		code = bfd_get_8 (abfd, contents + irel->r_offset - 2);
1118d2201f2fSdrahn 
1119*cf2f2c56Smiod 		/* All instructions with R_H8_DIR24A8 start with
1120*cf2f2c56Smiod 		   0x6a.  */
1121d2201f2fSdrahn 		if (code != 0x6a)
1122d2201f2fSdrahn 		  abort ();
1123d2201f2fSdrahn 
1124*cf2f2c56Smiod 		temp_code = code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
1125d2201f2fSdrahn 
1126*cf2f2c56Smiod 		/* If this is a mov.b instruction, clear the lower
1127*cf2f2c56Smiod 		   nibble, which contains the source/destination
1128*cf2f2c56Smiod 		   register number.  */
1129*cf2f2c56Smiod 		if ((temp_code & 0x30) != 0x30)
1130*cf2f2c56Smiod 		  temp_code &= 0xf0;
1131*cf2f2c56Smiod 
1132*cf2f2c56Smiod 		switch (temp_code)
1133*cf2f2c56Smiod 		  {
1134*cf2f2c56Smiod 		  case 0x20:
1135*cf2f2c56Smiod 		    /* This is mov.b @aa:24/32,Rd.  */
1136*cf2f2c56Smiod 		    bfd_put_8 (abfd, (code & 0xf) | 0x20,
1137d2201f2fSdrahn 			       contents + irel->r_offset - 2);
1138*cf2f2c56Smiod 		    break;
1139*cf2f2c56Smiod 		  case 0xa0:
1140*cf2f2c56Smiod 		    /* This is mov.b Rs,@aa:24/32.  */
1141*cf2f2c56Smiod 		    bfd_put_8 (abfd, (code & 0xf) | 0x30,
1142d2201f2fSdrahn 			       contents + irel->r_offset - 2);
1143*cf2f2c56Smiod 		    break;
1144*cf2f2c56Smiod 		  case 0x38:
1145*cf2f2c56Smiod 		    /* This is a bit-maniputation instruction that
1146*cf2f2c56Smiod 		       stores one bit into memory, one of "bclr",
1147*cf2f2c56Smiod 		       "bist", "bnot", "bset", and "bst".  */
1148*cf2f2c56Smiod 		    bfd_put_8 (abfd, 0x7f, contents + irel->r_offset - 2);
1149*cf2f2c56Smiod 		    break;
1150*cf2f2c56Smiod 		  case 0x30:
1151*cf2f2c56Smiod 		    /* This is a bit-maniputation instruction that
1152*cf2f2c56Smiod 		       loads one bit from memory, one of "band",
1153*cf2f2c56Smiod 		       "biand", "bild", "bior", "bixor", "bld", "bor",
1154*cf2f2c56Smiod 		       "btst", and "bxor".  */
1155*cf2f2c56Smiod 		    bfd_put_8 (abfd, 0x7e, contents + irel->r_offset - 2);
1156*cf2f2c56Smiod 		    break;
1157*cf2f2c56Smiod 		  default:
1158d2201f2fSdrahn 		    abort();
1159*cf2f2c56Smiod 		  }
1160d2201f2fSdrahn 
1161d2201f2fSdrahn 		/* Fix the relocation's type.  */
1162d2201f2fSdrahn 		irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1163d2201f2fSdrahn 					     R_H8_DIR8);
1164*cf2f2c56Smiod 		irel->r_offset--;
1165d2201f2fSdrahn 
1166d2201f2fSdrahn 		/* Delete two bytes of data.  */
1167*cf2f2c56Smiod 		if (!elf32_h8_relax_delete_bytes (abfd, sec,
1168*cf2f2c56Smiod 						  irel->r_offset + 1, 4))
1169d2201f2fSdrahn 		  goto error_return;
1170d2201f2fSdrahn 
1171d2201f2fSdrahn 		/* That will change things, so, we should relax again.
1172d2201f2fSdrahn 		   Note that this is not required, and it may be slow.  */
1173d2201f2fSdrahn 		*again = TRUE;
1174*cf2f2c56Smiod 		break;
1175d2201f2fSdrahn 	      }
1176d2201f2fSdrahn 	  }
1177d2201f2fSdrahn 
1178*cf2f2c56Smiod 	  /* Fall through.  */
1179d2201f2fSdrahn 
1180*cf2f2c56Smiod 	  /* This is a 24-/32-bit absolute address in one of the
1181*cf2f2c56Smiod 	     following instructions:
1182*cf2f2c56Smiod 
1183*cf2f2c56Smiod 	       "band", "bclr", "biand", "bild", "bior", "bist",
1184*cf2f2c56Smiod 	       "bixor", "bld", "bnot", "bor", "bset", "bst", "btst",
1185*cf2f2c56Smiod 	       "bxor", "ldc.w", "stc.w" and "mov.[bwl]"
1186*cf2f2c56Smiod 
1187*cf2f2c56Smiod 	     We may relax this into an 16-bit absolute address if it's
1188*cf2f2c56Smiod 	     in the right range.  */
1189d2201f2fSdrahn 	case R_H8_DIR32A16:
1190d2201f2fSdrahn 	  {
1191*cf2f2c56Smiod 	    bfd_vma value;
1192d2201f2fSdrahn 
1193*cf2f2c56Smiod 	    value = bfd_h8300_pad_address (abfd, symval + irel->r_addend);
1194*cf2f2c56Smiod 	    if (value <= 0x7fff || value >= 0xffff8000u)
1195d2201f2fSdrahn 	      {
1196d2201f2fSdrahn 		unsigned char code;
1197d2201f2fSdrahn 
1198d2201f2fSdrahn 		/* Note that we've changed the relocs, section contents,
1199d2201f2fSdrahn 		   etc.  */
1200d2201f2fSdrahn 		elf_section_data (sec)->relocs = internal_relocs;
1201d2201f2fSdrahn 		elf_section_data (sec)->this_hdr.contents = contents;
1202d2201f2fSdrahn 		symtab_hdr->contents = (unsigned char *) isymbuf;
1203d2201f2fSdrahn 
1204d2201f2fSdrahn 		/* Get the opcode.  */
1205d2201f2fSdrahn 		code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
1206d2201f2fSdrahn 
1207*cf2f2c56Smiod 		/* Fix the opcode.  For all the instructions that
1208*cf2f2c56Smiod 		   belong to this relaxation, we simply need to turn
1209*cf2f2c56Smiod 		   off bit 0x20 in the previous byte.  */
1210d2201f2fSdrahn 		code &= ~0x20;
1211d2201f2fSdrahn 
1212d2201f2fSdrahn 		bfd_put_8 (abfd, code, contents + irel->r_offset - 1);
1213d2201f2fSdrahn 
1214d2201f2fSdrahn 		/* Fix the relocation's type.  */
1215d2201f2fSdrahn 		irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1216*cf2f2c56Smiod 					     R_H8_DIR16);
1217d2201f2fSdrahn 
1218d2201f2fSdrahn 		/* Delete two bytes of data.  */
1219d2201f2fSdrahn 		if (!elf32_h8_relax_delete_bytes (abfd, sec,
1220d2201f2fSdrahn 						  irel->r_offset + 1, 2))
1221d2201f2fSdrahn 		  goto error_return;
1222d2201f2fSdrahn 
1223d2201f2fSdrahn 		/* That will change things, so, we should relax again.
1224d2201f2fSdrahn 		   Note that this is not required, and it may be slow.  */
1225d2201f2fSdrahn 		*again = TRUE;
1226d2201f2fSdrahn 	      }
1227d2201f2fSdrahn 	    break;
1228d2201f2fSdrahn 	  }
1229d2201f2fSdrahn 
1230d2201f2fSdrahn 	default:
1231d2201f2fSdrahn 	  break;
1232d2201f2fSdrahn 	}
1233d2201f2fSdrahn     }
1234d2201f2fSdrahn 
1235d2201f2fSdrahn   if (isymbuf != NULL
1236d2201f2fSdrahn       && symtab_hdr->contents != (unsigned char *) isymbuf)
1237d2201f2fSdrahn     {
1238d2201f2fSdrahn       if (! link_info->keep_memory)
1239d2201f2fSdrahn 	free (isymbuf);
1240d2201f2fSdrahn       else
1241d2201f2fSdrahn 	symtab_hdr->contents = (unsigned char *) isymbuf;
1242d2201f2fSdrahn     }
1243d2201f2fSdrahn 
1244d2201f2fSdrahn   if (contents != NULL
1245d2201f2fSdrahn       && elf_section_data (sec)->this_hdr.contents != contents)
1246d2201f2fSdrahn     {
1247d2201f2fSdrahn       if (! link_info->keep_memory)
1248d2201f2fSdrahn 	free (contents);
1249d2201f2fSdrahn       else
1250d2201f2fSdrahn 	{
1251d2201f2fSdrahn 	  /* Cache the section contents for elf_link_input_bfd.  */
1252d2201f2fSdrahn 	  elf_section_data (sec)->this_hdr.contents = contents;
1253d2201f2fSdrahn 	}
1254d2201f2fSdrahn     }
1255d2201f2fSdrahn 
1256d2201f2fSdrahn   if (internal_relocs != NULL
1257d2201f2fSdrahn       && elf_section_data (sec)->relocs != internal_relocs)
1258d2201f2fSdrahn     free (internal_relocs);
1259d2201f2fSdrahn 
1260d2201f2fSdrahn   return TRUE;
1261d2201f2fSdrahn 
1262d2201f2fSdrahn  error_return:
1263d2201f2fSdrahn   if (isymbuf != NULL
1264d2201f2fSdrahn       && symtab_hdr->contents != (unsigned char *) isymbuf)
1265d2201f2fSdrahn     free (isymbuf);
1266d2201f2fSdrahn   if (contents != NULL
1267d2201f2fSdrahn       && elf_section_data (sec)->this_hdr.contents != contents)
1268d2201f2fSdrahn     free (contents);
1269d2201f2fSdrahn   if (internal_relocs != NULL
1270d2201f2fSdrahn       && elf_section_data (sec)->relocs != internal_relocs)
1271d2201f2fSdrahn     free (internal_relocs);
1272d2201f2fSdrahn   return FALSE;
1273d2201f2fSdrahn }
1274d2201f2fSdrahn 
1275d2201f2fSdrahn /* Delete some bytes from a section while relaxing.  */
1276d2201f2fSdrahn 
1277d2201f2fSdrahn static bfd_boolean
elf32_h8_relax_delete_bytes(bfd * abfd,asection * sec,bfd_vma addr,int count)1278*cf2f2c56Smiod elf32_h8_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count)
1279d2201f2fSdrahn {
1280d2201f2fSdrahn   Elf_Internal_Shdr *symtab_hdr;
1281d2201f2fSdrahn   unsigned int sec_shndx;
1282d2201f2fSdrahn   bfd_byte *contents;
1283d2201f2fSdrahn   Elf_Internal_Rela *irel, *irelend;
1284d2201f2fSdrahn   Elf_Internal_Rela *irelalign;
1285d2201f2fSdrahn   Elf_Internal_Sym *isym;
1286d2201f2fSdrahn   Elf_Internal_Sym *isymend;
1287d2201f2fSdrahn   bfd_vma toaddr;
1288d2201f2fSdrahn   struct elf_link_hash_entry **sym_hashes;
1289d2201f2fSdrahn   struct elf_link_hash_entry **end_hashes;
1290d2201f2fSdrahn   unsigned int symcount;
1291d2201f2fSdrahn 
1292d2201f2fSdrahn   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1293d2201f2fSdrahn 
1294d2201f2fSdrahn   contents = elf_section_data (sec)->this_hdr.contents;
1295d2201f2fSdrahn 
1296d2201f2fSdrahn   /* The deletion must stop at the next ALIGN reloc for an aligment
1297d2201f2fSdrahn      power larger than the number of bytes we are deleting.  */
1298d2201f2fSdrahn 
1299d2201f2fSdrahn   irelalign = NULL;
1300d2201f2fSdrahn   toaddr = sec->_cooked_size;
1301d2201f2fSdrahn 
1302d2201f2fSdrahn   irel = elf_section_data (sec)->relocs;
1303d2201f2fSdrahn   irelend = irel + sec->reloc_count;
1304d2201f2fSdrahn 
1305d2201f2fSdrahn   /* Actually delete the bytes.  */
1306d2201f2fSdrahn   memmove (contents + addr, contents + addr + count,
1307d2201f2fSdrahn 	   (size_t) (toaddr - addr - count));
1308d2201f2fSdrahn   sec->_cooked_size -= count;
1309d2201f2fSdrahn 
1310d2201f2fSdrahn   /* Adjust all the relocs.  */
1311d2201f2fSdrahn   for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1312d2201f2fSdrahn     {
1313d2201f2fSdrahn       /* Get the new reloc address.  */
1314d2201f2fSdrahn       if ((irel->r_offset > addr
1315d2201f2fSdrahn 	   && irel->r_offset < toaddr))
1316d2201f2fSdrahn 	irel->r_offset -= count;
1317d2201f2fSdrahn     }
1318d2201f2fSdrahn 
1319d2201f2fSdrahn   /* Adjust the local symbols defined in this section.  */
1320d2201f2fSdrahn   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1321d2201f2fSdrahn   isym = (Elf_Internal_Sym *) symtab_hdr->contents;
1322d2201f2fSdrahn   isymend = isym + symtab_hdr->sh_info;
1323d2201f2fSdrahn   for (; isym < isymend; isym++)
1324d2201f2fSdrahn     {
1325d2201f2fSdrahn       if (isym->st_shndx == sec_shndx
1326d2201f2fSdrahn 	  && isym->st_value > addr
1327d2201f2fSdrahn 	  && isym->st_value < toaddr)
1328d2201f2fSdrahn 	isym->st_value -= count;
1329d2201f2fSdrahn     }
1330d2201f2fSdrahn 
1331d2201f2fSdrahn   /* Now adjust the global symbols defined in this section.  */
1332d2201f2fSdrahn   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1333d2201f2fSdrahn 	      - symtab_hdr->sh_info);
1334d2201f2fSdrahn   sym_hashes = elf_sym_hashes (abfd);
1335d2201f2fSdrahn   end_hashes = sym_hashes + symcount;
1336d2201f2fSdrahn   for (; sym_hashes < end_hashes; sym_hashes++)
1337d2201f2fSdrahn     {
1338d2201f2fSdrahn       struct elf_link_hash_entry *sym_hash = *sym_hashes;
1339d2201f2fSdrahn       if ((sym_hash->root.type == bfd_link_hash_defined
1340d2201f2fSdrahn 	   || sym_hash->root.type == bfd_link_hash_defweak)
1341d2201f2fSdrahn 	  && sym_hash->root.u.def.section == sec
1342d2201f2fSdrahn 	  && sym_hash->root.u.def.value > addr
1343d2201f2fSdrahn 	  && sym_hash->root.u.def.value < toaddr)
1344d2201f2fSdrahn 	{
1345d2201f2fSdrahn 	  sym_hash->root.u.def.value -= count;
1346d2201f2fSdrahn 	}
1347d2201f2fSdrahn     }
1348d2201f2fSdrahn 
1349d2201f2fSdrahn   return TRUE;
1350d2201f2fSdrahn }
1351d2201f2fSdrahn 
1352d2201f2fSdrahn /* Return TRUE if a symbol exists at the given address, else return
1353d2201f2fSdrahn    FALSE.  */
1354d2201f2fSdrahn static bfd_boolean
elf32_h8_symbol_address_p(bfd * abfd,asection * sec,bfd_vma addr)1355*cf2f2c56Smiod elf32_h8_symbol_address_p (bfd *abfd, asection *sec, bfd_vma addr)
1356d2201f2fSdrahn {
1357d2201f2fSdrahn   Elf_Internal_Shdr *symtab_hdr;
1358d2201f2fSdrahn   unsigned int sec_shndx;
1359d2201f2fSdrahn   Elf_Internal_Sym *isym;
1360d2201f2fSdrahn   Elf_Internal_Sym *isymend;
1361d2201f2fSdrahn   struct elf_link_hash_entry **sym_hashes;
1362d2201f2fSdrahn   struct elf_link_hash_entry **end_hashes;
1363d2201f2fSdrahn   unsigned int symcount;
1364d2201f2fSdrahn 
1365d2201f2fSdrahn   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1366d2201f2fSdrahn 
1367d2201f2fSdrahn   /* Examine all the symbols.  */
1368d2201f2fSdrahn   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1369d2201f2fSdrahn   isym = (Elf_Internal_Sym *) symtab_hdr->contents;
1370d2201f2fSdrahn   isymend = isym + symtab_hdr->sh_info;
1371d2201f2fSdrahn   for (; isym < isymend; isym++)
1372d2201f2fSdrahn     {
1373d2201f2fSdrahn       if (isym->st_shndx == sec_shndx
1374d2201f2fSdrahn 	  && isym->st_value == addr)
1375d2201f2fSdrahn 	return TRUE;
1376d2201f2fSdrahn     }
1377d2201f2fSdrahn 
1378d2201f2fSdrahn   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1379d2201f2fSdrahn 	      - symtab_hdr->sh_info);
1380d2201f2fSdrahn   sym_hashes = elf_sym_hashes (abfd);
1381d2201f2fSdrahn   end_hashes = sym_hashes + symcount;
1382d2201f2fSdrahn   for (; sym_hashes < end_hashes; sym_hashes++)
1383d2201f2fSdrahn     {
1384d2201f2fSdrahn       struct elf_link_hash_entry *sym_hash = *sym_hashes;
1385d2201f2fSdrahn       if ((sym_hash->root.type == bfd_link_hash_defined
1386d2201f2fSdrahn 	   || sym_hash->root.type == bfd_link_hash_defweak)
1387d2201f2fSdrahn 	  && sym_hash->root.u.def.section == sec
1388d2201f2fSdrahn 	  && sym_hash->root.u.def.value == addr)
1389d2201f2fSdrahn 	return TRUE;
1390d2201f2fSdrahn     }
1391d2201f2fSdrahn 
1392d2201f2fSdrahn   return FALSE;
1393d2201f2fSdrahn }
1394d2201f2fSdrahn 
1395d2201f2fSdrahn /* This is a version of bfd_generic_get_relocated_section_contents
1396d2201f2fSdrahn    which uses elf32_h8_relocate_section.  */
1397d2201f2fSdrahn 
1398d2201f2fSdrahn static bfd_byte *
elf32_h8_get_relocated_section_contents(bfd * output_bfd,struct bfd_link_info * link_info,struct bfd_link_order * link_order,bfd_byte * data,bfd_boolean relocatable,asymbol ** symbols)1399*cf2f2c56Smiod elf32_h8_get_relocated_section_contents (bfd *output_bfd,
1400*cf2f2c56Smiod 					 struct bfd_link_info *link_info,
1401*cf2f2c56Smiod 					 struct bfd_link_order *link_order,
1402*cf2f2c56Smiod 					 bfd_byte *data,
1403*cf2f2c56Smiod 					 bfd_boolean relocatable,
1404*cf2f2c56Smiod 					 asymbol **symbols)
1405d2201f2fSdrahn {
1406d2201f2fSdrahn   Elf_Internal_Shdr *symtab_hdr;
1407d2201f2fSdrahn   asection *input_section = link_order->u.indirect.section;
1408d2201f2fSdrahn   bfd *input_bfd = input_section->owner;
1409d2201f2fSdrahn   asection **sections = NULL;
1410d2201f2fSdrahn   Elf_Internal_Rela *internal_relocs = NULL;
1411d2201f2fSdrahn   Elf_Internal_Sym *isymbuf = NULL;
1412d2201f2fSdrahn 
1413d2201f2fSdrahn   /* We only need to handle the case of relaxing, or of having a
1414d2201f2fSdrahn      particular set of section contents, specially.  */
1415*cf2f2c56Smiod   if (relocatable
1416d2201f2fSdrahn       || elf_section_data (input_section)->this_hdr.contents == NULL)
1417d2201f2fSdrahn     return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
1418d2201f2fSdrahn 						       link_order, data,
1419*cf2f2c56Smiod 						       relocatable,
1420d2201f2fSdrahn 						       symbols);
1421d2201f2fSdrahn 
1422d2201f2fSdrahn   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
1423d2201f2fSdrahn 
1424d2201f2fSdrahn   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
1425d2201f2fSdrahn 	  (size_t) input_section->_raw_size);
1426d2201f2fSdrahn 
1427d2201f2fSdrahn   if ((input_section->flags & SEC_RELOC) != 0
1428d2201f2fSdrahn       && input_section->reloc_count > 0)
1429d2201f2fSdrahn     {
1430d2201f2fSdrahn       asection **secpp;
1431d2201f2fSdrahn       Elf_Internal_Sym *isym, *isymend;
1432d2201f2fSdrahn       bfd_size_type amt;
1433d2201f2fSdrahn 
1434*cf2f2c56Smiod       internal_relocs = (_bfd_elf_link_read_relocs
1435d2201f2fSdrahn 			 (input_bfd, input_section, (PTR) NULL,
1436d2201f2fSdrahn 			  (Elf_Internal_Rela *) NULL, FALSE));
1437d2201f2fSdrahn       if (internal_relocs == NULL)
1438d2201f2fSdrahn 	goto error_return;
1439d2201f2fSdrahn 
1440d2201f2fSdrahn       if (symtab_hdr->sh_info != 0)
1441d2201f2fSdrahn 	{
1442d2201f2fSdrahn 	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1443d2201f2fSdrahn 	  if (isymbuf == NULL)
1444d2201f2fSdrahn 	    isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
1445d2201f2fSdrahn 					    symtab_hdr->sh_info, 0,
1446d2201f2fSdrahn 					    NULL, NULL, NULL);
1447d2201f2fSdrahn 	  if (isymbuf == NULL)
1448d2201f2fSdrahn 	    goto error_return;
1449d2201f2fSdrahn 	}
1450d2201f2fSdrahn 
1451d2201f2fSdrahn       amt = symtab_hdr->sh_info;
1452d2201f2fSdrahn       amt *= sizeof (asection *);
1453d2201f2fSdrahn       sections = (asection **) bfd_malloc (amt);
1454d2201f2fSdrahn       if (sections == NULL && amt != 0)
1455d2201f2fSdrahn 	goto error_return;
1456d2201f2fSdrahn 
1457d2201f2fSdrahn       isymend = isymbuf + symtab_hdr->sh_info;
1458d2201f2fSdrahn       for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
1459d2201f2fSdrahn 	{
1460d2201f2fSdrahn 	  asection *isec;
1461d2201f2fSdrahn 
1462d2201f2fSdrahn 	  if (isym->st_shndx == SHN_UNDEF)
1463d2201f2fSdrahn 	    isec = bfd_und_section_ptr;
1464d2201f2fSdrahn 	  else if (isym->st_shndx == SHN_ABS)
1465d2201f2fSdrahn 	    isec = bfd_abs_section_ptr;
1466d2201f2fSdrahn 	  else if (isym->st_shndx == SHN_COMMON)
1467d2201f2fSdrahn 	    isec = bfd_com_section_ptr;
1468d2201f2fSdrahn 	  else
1469d2201f2fSdrahn 	    isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
1470d2201f2fSdrahn 
1471d2201f2fSdrahn 	  *secpp = isec;
1472d2201f2fSdrahn 	}
1473d2201f2fSdrahn 
1474d2201f2fSdrahn       if (! elf32_h8_relocate_section (output_bfd, link_info, input_bfd,
1475d2201f2fSdrahn 				       input_section, data, internal_relocs,
1476d2201f2fSdrahn 				       isymbuf, sections))
1477d2201f2fSdrahn 	goto error_return;
1478d2201f2fSdrahn 
1479d2201f2fSdrahn       if (sections != NULL)
1480d2201f2fSdrahn 	free (sections);
1481d2201f2fSdrahn       if (isymbuf != NULL
1482d2201f2fSdrahn 	  && symtab_hdr->contents != (unsigned char *) isymbuf)
1483d2201f2fSdrahn 	free (isymbuf);
1484d2201f2fSdrahn       if (elf_section_data (input_section)->relocs != internal_relocs)
1485d2201f2fSdrahn 	free (internal_relocs);
1486d2201f2fSdrahn     }
1487d2201f2fSdrahn 
1488d2201f2fSdrahn   return data;
1489d2201f2fSdrahn 
1490d2201f2fSdrahn  error_return:
1491d2201f2fSdrahn   if (sections != NULL)
1492d2201f2fSdrahn     free (sections);
1493d2201f2fSdrahn   if (isymbuf != NULL
1494d2201f2fSdrahn       && symtab_hdr->contents != (unsigned char *) isymbuf)
1495d2201f2fSdrahn     free (isymbuf);
1496d2201f2fSdrahn   if (internal_relocs != NULL
1497d2201f2fSdrahn       && elf_section_data (input_section)->relocs != internal_relocs)
1498d2201f2fSdrahn     free (internal_relocs);
1499d2201f2fSdrahn   return NULL;
1500d2201f2fSdrahn }
1501d2201f2fSdrahn 
1502*cf2f2c56Smiod static asection *
elf32_h8_gc_mark_hook(asection * sec,struct bfd_link_info * info ATTRIBUTE_UNUSED,Elf_Internal_Rela * rel ATTRIBUTE_UNUSED,struct elf_link_hash_entry * h,Elf_Internal_Sym * sym)1503*cf2f2c56Smiod elf32_h8_gc_mark_hook (asection *sec,
1504*cf2f2c56Smiod 		       struct bfd_link_info *info ATTRIBUTE_UNUSED,
1505*cf2f2c56Smiod 		       Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
1506*cf2f2c56Smiod 		       struct elf_link_hash_entry *h,
1507*cf2f2c56Smiod 		       Elf_Internal_Sym *sym)
1508*cf2f2c56Smiod {
1509*cf2f2c56Smiod   if (h != NULL)
1510*cf2f2c56Smiod     {
1511*cf2f2c56Smiod       switch (h->root.type)
1512*cf2f2c56Smiod         {
1513*cf2f2c56Smiod 	case bfd_link_hash_defined:
1514*cf2f2c56Smiod 	case bfd_link_hash_defweak:
1515*cf2f2c56Smiod           return h->root.u.def.section;
1516*cf2f2c56Smiod 
1517*cf2f2c56Smiod 	case bfd_link_hash_common:
1518*cf2f2c56Smiod           return h->root.u.c.p->section;
1519*cf2f2c56Smiod 
1520*cf2f2c56Smiod 	default:
1521*cf2f2c56Smiod           break;
1522*cf2f2c56Smiod         }
1523*cf2f2c56Smiod     }
1524*cf2f2c56Smiod   else
1525*cf2f2c56Smiod     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
1526*cf2f2c56Smiod   return NULL;
1527*cf2f2c56Smiod }
1528*cf2f2c56Smiod 
1529*cf2f2c56Smiod static bfd_boolean
elf32_h8_gc_sweep_hook(bfd * abfd ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED,asection * sec ATTRIBUTE_UNUSED,const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)1530*cf2f2c56Smiod elf32_h8_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
1531*cf2f2c56Smiod 			struct bfd_link_info *info ATTRIBUTE_UNUSED,
1532*cf2f2c56Smiod 			asection *sec ATTRIBUTE_UNUSED,
1533*cf2f2c56Smiod 			const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
1534*cf2f2c56Smiod {
1535*cf2f2c56Smiod   return TRUE;
1536*cf2f2c56Smiod }
1537*cf2f2c56Smiod 
1538d2201f2fSdrahn 
1539d2201f2fSdrahn #define TARGET_BIG_SYM			bfd_elf32_h8300_vec
1540d2201f2fSdrahn #define TARGET_BIG_NAME			"elf32-h8300"
1541d2201f2fSdrahn #define ELF_ARCH			bfd_arch_h8300
1542d2201f2fSdrahn #define ELF_MACHINE_CODE		EM_H8_300
1543d2201f2fSdrahn #define ELF_MAXPAGESIZE			0x1
1544d2201f2fSdrahn #define bfd_elf32_bfd_reloc_type_lookup elf32_h8_reloc_type_lookup
1545d2201f2fSdrahn #define elf_info_to_howto		elf32_h8_info_to_howto
1546d2201f2fSdrahn #define elf_info_to_howto_rel		elf32_h8_info_to_howto_rel
1547d2201f2fSdrahn 
1548d2201f2fSdrahn /* So we can set/examine bits in e_flags to get the specific
1549d2201f2fSdrahn    H8 architecture in use.  */
1550d2201f2fSdrahn #define elf_backend_final_write_processing \
1551d2201f2fSdrahn   elf32_h8_final_write_processing
1552d2201f2fSdrahn #define elf_backend_object_p \
1553d2201f2fSdrahn   elf32_h8_object_p
1554d2201f2fSdrahn #define bfd_elf32_bfd_merge_private_bfd_data \
1555d2201f2fSdrahn   elf32_h8_merge_private_bfd_data
1556*cf2f2c56Smiod #define elf_backend_gc_mark_hook        elf32_h8_gc_mark_hook
1557*cf2f2c56Smiod #define elf_backend_gc_sweep_hook       elf32_h8_gc_sweep_hook
1558d2201f2fSdrahn 
1559d2201f2fSdrahn /* ??? when elf_backend_relocate_section is not defined, elf32-target.h
1560d2201f2fSdrahn    defaults to using _bfd_generic_link_hash_table_create, but
1561*cf2f2c56Smiod    bfd_elf_size_dynamic_sections uses
1562d2201f2fSdrahn    dynobj = elf_hash_table (info)->dynobj;
1563d2201f2fSdrahn    and thus requires an elf hash table.  */
1564d2201f2fSdrahn #define bfd_elf32_bfd_link_hash_table_create _bfd_elf_link_hash_table_create
1565d2201f2fSdrahn 
1566d2201f2fSdrahn /* Use an H8 specific linker, not the ELF generic linker.  */
1567d2201f2fSdrahn #define elf_backend_relocate_section elf32_h8_relocate_section
1568d2201f2fSdrahn #define elf_backend_rela_normal		1
1569*cf2f2c56Smiod #define elf_backend_can_gc_sections	1
1570d2201f2fSdrahn 
1571d2201f2fSdrahn /* And relaxing stuff.  */
1572d2201f2fSdrahn #define bfd_elf32_bfd_relax_section     elf32_h8_relax_section
1573d2201f2fSdrahn #define bfd_elf32_bfd_get_relocated_section_contents \
1574d2201f2fSdrahn                                 elf32_h8_get_relocated_section_contents
1575d2201f2fSdrahn 
1576d2201f2fSdrahn 
1577d2201f2fSdrahn #include "elf32-target.h"
1578