1fddef416Sniklas /* Matsushita 10200 specific support for 32-bit ELF
2*cf2f2c56Smiod Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
35f210c2aSfgsch Free Software Foundation, Inc.
4fddef416Sniklas
5fddef416Sniklas This file is part of BFD, the Binary File Descriptor library.
6fddef416Sniklas
7fddef416Sniklas This program is free software; you can redistribute it and/or modify
8fddef416Sniklas it under the terms of the GNU General Public License as published by
9fddef416Sniklas the Free Software Foundation; either version 2 of the License, or
10fddef416Sniklas (at your option) any later version.
11fddef416Sniklas
12fddef416Sniklas This program is distributed in the hope that it will be useful,
13fddef416Sniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
14fddef416Sniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15fddef416Sniklas GNU General Public License for more details.
16fddef416Sniklas
17fddef416Sniklas You should have received a copy of the GNU General Public License
18fddef416Sniklas along with this program; if not, write to the Free Software
19fddef416Sniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20fddef416Sniklas
21fddef416Sniklas #include "bfd.h"
22fddef416Sniklas #include "sysdep.h"
23fddef416Sniklas #include "libbfd.h"
24fddef416Sniklas #include "elf-bfd.h"
25fddef416Sniklas
26fddef416Sniklas static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
27fddef416Sniklas PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
28fddef416Sniklas static void mn10200_info_to_howto
29d2201f2fSdrahn PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
30d2201f2fSdrahn static bfd_boolean mn10200_elf_relax_delete_bytes
31fddef416Sniklas PARAMS ((bfd *, asection *, bfd_vma, int));
32d2201f2fSdrahn static bfd_boolean mn10200_elf_symbol_address_p
33d2201f2fSdrahn PARAMS ((bfd *, asection *, Elf_Internal_Sym *, bfd_vma));
34d2201f2fSdrahn static bfd_reloc_status_type mn10200_elf_final_link_relocate
35d2201f2fSdrahn PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *,
36d2201f2fSdrahn bfd_byte *, bfd_vma, bfd_vma, bfd_vma,
37d2201f2fSdrahn struct bfd_link_info *, asection *, int));
38d2201f2fSdrahn static bfd_boolean mn10200_elf_relocate_section
39d2201f2fSdrahn PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
40d2201f2fSdrahn bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *,
41d2201f2fSdrahn asection **));
42d2201f2fSdrahn static bfd_boolean mn10200_elf_relax_section
43d2201f2fSdrahn PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
44d2201f2fSdrahn static bfd_byte * mn10200_elf_get_relocated_section_contents
45d2201f2fSdrahn PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
46d2201f2fSdrahn bfd_byte *, bfd_boolean, asymbol **));
47fddef416Sniklas
485f210c2aSfgsch enum reloc_type {
49fddef416Sniklas R_MN10200_NONE = 0,
50fddef416Sniklas R_MN10200_32,
51fddef416Sniklas R_MN10200_16,
52fddef416Sniklas R_MN10200_8,
53fddef416Sniklas R_MN10200_24,
54fddef416Sniklas R_MN10200_PCREL8,
55fddef416Sniklas R_MN10200_PCREL16,
56fddef416Sniklas R_MN10200_PCREL24,
57fddef416Sniklas R_MN10200_MAX
58fddef416Sniklas };
59fddef416Sniklas
605f210c2aSfgsch static reloc_howto_type elf_mn10200_howto_table[] = {
61fddef416Sniklas /* Dummy relocation. Does nothing. */
62fddef416Sniklas HOWTO (R_MN10200_NONE,
63fddef416Sniklas 0,
64fddef416Sniklas 2,
65fddef416Sniklas 16,
66d2201f2fSdrahn FALSE,
67fddef416Sniklas 0,
68fddef416Sniklas complain_overflow_bitfield,
69fddef416Sniklas bfd_elf_generic_reloc,
70fddef416Sniklas "R_MN10200_NONE",
71d2201f2fSdrahn FALSE,
72fddef416Sniklas 0,
73fddef416Sniklas 0,
74d2201f2fSdrahn FALSE),
75fddef416Sniklas /* Standard 32 bit reloc. */
76fddef416Sniklas HOWTO (R_MN10200_32,
77fddef416Sniklas 0,
78fddef416Sniklas 2,
79fddef416Sniklas 32,
80d2201f2fSdrahn FALSE,
81fddef416Sniklas 0,
82fddef416Sniklas complain_overflow_bitfield,
83fddef416Sniklas bfd_elf_generic_reloc,
84fddef416Sniklas "R_MN10200_32",
85d2201f2fSdrahn FALSE,
86fddef416Sniklas 0xffffffff,
87fddef416Sniklas 0xffffffff,
88d2201f2fSdrahn FALSE),
89fddef416Sniklas /* Standard 16 bit reloc. */
90fddef416Sniklas HOWTO (R_MN10200_16,
91fddef416Sniklas 0,
92fddef416Sniklas 1,
93fddef416Sniklas 16,
94d2201f2fSdrahn FALSE,
95fddef416Sniklas 0,
96fddef416Sniklas complain_overflow_bitfield,
97fddef416Sniklas bfd_elf_generic_reloc,
98fddef416Sniklas "R_MN10200_16",
99d2201f2fSdrahn FALSE,
100fddef416Sniklas 0xffff,
101fddef416Sniklas 0xffff,
102d2201f2fSdrahn FALSE),
103fddef416Sniklas /* Standard 8 bit reloc. */
104fddef416Sniklas HOWTO (R_MN10200_8,
105fddef416Sniklas 0,
106fddef416Sniklas 0,
107fddef416Sniklas 8,
108d2201f2fSdrahn FALSE,
109fddef416Sniklas 0,
110fddef416Sniklas complain_overflow_bitfield,
111fddef416Sniklas bfd_elf_generic_reloc,
112fddef416Sniklas "R_MN10200_8",
113d2201f2fSdrahn FALSE,
114fddef416Sniklas 0xff,
115fddef416Sniklas 0xff,
116d2201f2fSdrahn FALSE),
117fddef416Sniklas /* Standard 24 bit reloc. */
118fddef416Sniklas HOWTO (R_MN10200_24,
119fddef416Sniklas 0,
120fddef416Sniklas 2,
121fddef416Sniklas 24,
122d2201f2fSdrahn FALSE,
123fddef416Sniklas 0,
124fddef416Sniklas complain_overflow_bitfield,
125fddef416Sniklas bfd_elf_generic_reloc,
126fddef416Sniklas "R_MN10200_24",
127d2201f2fSdrahn FALSE,
128fddef416Sniklas 0xffffff,
129fddef416Sniklas 0xffffff,
130d2201f2fSdrahn FALSE),
131fddef416Sniklas /* Simple 8 pc-relative reloc. */
132fddef416Sniklas HOWTO (R_MN10200_PCREL8,
133fddef416Sniklas 0,
134fddef416Sniklas 0,
135fddef416Sniklas 8,
136d2201f2fSdrahn TRUE,
137fddef416Sniklas 0,
138fddef416Sniklas complain_overflow_bitfield,
139fddef416Sniklas bfd_elf_generic_reloc,
140fddef416Sniklas "R_MN10200_PCREL8",
141d2201f2fSdrahn FALSE,
142fddef416Sniklas 0xff,
143fddef416Sniklas 0xff,
144d2201f2fSdrahn TRUE),
145fddef416Sniklas /* Simple 16 pc-relative reloc. */
146fddef416Sniklas HOWTO (R_MN10200_PCREL16,
147fddef416Sniklas 0,
148fddef416Sniklas 1,
149fddef416Sniklas 16,
150d2201f2fSdrahn TRUE,
151fddef416Sniklas 0,
152fddef416Sniklas complain_overflow_bitfield,
153fddef416Sniklas bfd_elf_generic_reloc,
154fddef416Sniklas "R_MN10200_PCREL16",
155d2201f2fSdrahn FALSE,
156fddef416Sniklas 0xffff,
157fddef416Sniklas 0xffff,
158d2201f2fSdrahn TRUE),
159fddef416Sniklas /* Simple 32bit pc-relative reloc with a 1 byte adjustment
160fddef416Sniklas to get the pc-relative offset correct. */
161fddef416Sniklas HOWTO (R_MN10200_PCREL24,
162fddef416Sniklas 0,
163fddef416Sniklas 2,
164fddef416Sniklas 24,
165d2201f2fSdrahn TRUE,
166fddef416Sniklas 0,
167fddef416Sniklas complain_overflow_bitfield,
168fddef416Sniklas bfd_elf_generic_reloc,
169fddef416Sniklas "R_MN10200_PCREL24",
170d2201f2fSdrahn FALSE,
171fddef416Sniklas 0xffffff,
172fddef416Sniklas 0xffffff,
173d2201f2fSdrahn TRUE),
174fddef416Sniklas };
175fddef416Sniklas
1765f210c2aSfgsch struct mn10200_reloc_map {
177f7cc78ecSespie bfd_reloc_code_real_type bfd_reloc_val;
178fddef416Sniklas unsigned char elf_reloc_val;
179fddef416Sniklas };
180fddef416Sniklas
1815f210c2aSfgsch static const struct mn10200_reloc_map mn10200_reloc_map[] = {
182fddef416Sniklas { BFD_RELOC_NONE , R_MN10200_NONE , },
183fddef416Sniklas { BFD_RELOC_32 , R_MN10200_32 , },
184fddef416Sniklas { BFD_RELOC_16 , R_MN10200_16 , },
185fddef416Sniklas { BFD_RELOC_8 , R_MN10200_8 , },
186fddef416Sniklas { BFD_RELOC_24 , R_MN10200_24 , },
187fddef416Sniklas { BFD_RELOC_8_PCREL , R_MN10200_PCREL8 , },
188fddef416Sniklas { BFD_RELOC_16_PCREL, R_MN10200_PCREL16, },
189fddef416Sniklas { BFD_RELOC_24_PCREL, R_MN10200_PCREL24, },
190fddef416Sniklas };
191fddef416Sniklas
192fddef416Sniklas static reloc_howto_type *
bfd_elf32_bfd_reloc_type_lookup(abfd,code)193fddef416Sniklas bfd_elf32_bfd_reloc_type_lookup (abfd, code)
194f7cc78ecSespie bfd *abfd ATTRIBUTE_UNUSED;
195fddef416Sniklas bfd_reloc_code_real_type code;
196fddef416Sniklas {
197fddef416Sniklas unsigned int i;
198fddef416Sniklas
199fddef416Sniklas for (i = 0;
200fddef416Sniklas i < sizeof (mn10200_reloc_map) / sizeof (struct mn10200_reloc_map);
201fddef416Sniklas i++)
202fddef416Sniklas {
203fddef416Sniklas if (mn10200_reloc_map[i].bfd_reloc_val == code)
204fddef416Sniklas return &elf_mn10200_howto_table[mn10200_reloc_map[i].elf_reloc_val];
205fddef416Sniklas }
206fddef416Sniklas
207fddef416Sniklas return NULL;
208fddef416Sniklas }
209fddef416Sniklas
210fddef416Sniklas /* Set the howto pointer for an MN10200 ELF reloc. */
211fddef416Sniklas
212fddef416Sniklas static void
mn10200_info_to_howto(abfd,cache_ptr,dst)213fddef416Sniklas mn10200_info_to_howto (abfd, cache_ptr, dst)
214f7cc78ecSespie bfd *abfd ATTRIBUTE_UNUSED;
215fddef416Sniklas arelent *cache_ptr;
216d2201f2fSdrahn Elf_Internal_Rela *dst;
217fddef416Sniklas {
218fddef416Sniklas unsigned int r_type;
219fddef416Sniklas
220fddef416Sniklas r_type = ELF32_R_TYPE (dst->r_info);
221fddef416Sniklas BFD_ASSERT (r_type < (unsigned int) R_MN10200_MAX);
222fddef416Sniklas cache_ptr->howto = &elf_mn10200_howto_table[r_type];
223fddef416Sniklas }
224fddef416Sniklas
225fddef416Sniklas /* Perform a relocation as part of a final link. */
226d2201f2fSdrahn
227fddef416Sniklas static bfd_reloc_status_type
mn10200_elf_final_link_relocate(howto,input_bfd,output_bfd,input_section,contents,offset,value,addend,info,sym_sec,is_local)228fddef416Sniklas mn10200_elf_final_link_relocate (howto, input_bfd, output_bfd,
229fddef416Sniklas input_section, contents, offset, value,
230fddef416Sniklas addend, info, sym_sec, is_local)
231fddef416Sniklas reloc_howto_type *howto;
232fddef416Sniklas bfd *input_bfd;
233f7cc78ecSespie bfd *output_bfd ATTRIBUTE_UNUSED;
234fddef416Sniklas asection *input_section;
235fddef416Sniklas bfd_byte *contents;
236fddef416Sniklas bfd_vma offset;
237fddef416Sniklas bfd_vma value;
238fddef416Sniklas bfd_vma addend;
239f7cc78ecSespie struct bfd_link_info *info ATTRIBUTE_UNUSED;
240f7cc78ecSespie asection *sym_sec ATTRIBUTE_UNUSED;
241f7cc78ecSespie int is_local ATTRIBUTE_UNUSED;
242fddef416Sniklas {
243fddef416Sniklas unsigned long r_type = howto->type;
244fddef416Sniklas bfd_byte *hit_data = contents + offset;
245fddef416Sniklas
246fddef416Sniklas switch (r_type)
247fddef416Sniklas {
248fddef416Sniklas
249fddef416Sniklas case R_MN10200_NONE:
250fddef416Sniklas return bfd_reloc_ok;
251fddef416Sniklas
252fddef416Sniklas case R_MN10200_32:
253fddef416Sniklas value += addend;
254fddef416Sniklas bfd_put_32 (input_bfd, value, hit_data);
255fddef416Sniklas return bfd_reloc_ok;
256fddef416Sniklas
257fddef416Sniklas case R_MN10200_16:
258fddef416Sniklas value += addend;
259fddef416Sniklas
260fddef416Sniklas if ((long) value > 0x7fff || (long) value < -0x8000)
261fddef416Sniklas return bfd_reloc_overflow;
262fddef416Sniklas
263fddef416Sniklas bfd_put_16 (input_bfd, value, hit_data);
264fddef416Sniklas return bfd_reloc_ok;
265fddef416Sniklas
266fddef416Sniklas case R_MN10200_8:
267fddef416Sniklas value += addend;
268fddef416Sniklas
269f7cc78ecSespie if ((long) value > 0x7f || (long) value < -0x80)
270fddef416Sniklas return bfd_reloc_overflow;
271fddef416Sniklas
272fddef416Sniklas bfd_put_8 (input_bfd, value, hit_data);
273fddef416Sniklas return bfd_reloc_ok;
274fddef416Sniklas
275fddef416Sniklas case R_MN10200_24:
276fddef416Sniklas value += addend;
277fddef416Sniklas
278fddef416Sniklas if ((long) value > 0x7fffff || (long) value < -0x800000)
279fddef416Sniklas return bfd_reloc_overflow;
280fddef416Sniklas
281fddef416Sniklas value &= 0xffffff;
282fddef416Sniklas value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000);
283fddef416Sniklas bfd_put_32 (input_bfd, value, hit_data);
284fddef416Sniklas return bfd_reloc_ok;
285fddef416Sniklas
286fddef416Sniklas case R_MN10200_PCREL8:
287fddef416Sniklas value -= (input_section->output_section->vma
288fddef416Sniklas + input_section->output_offset);
289f7cc78ecSespie value -= (offset + 1);
290fddef416Sniklas value += addend;
291fddef416Sniklas
292fddef416Sniklas if ((long) value > 0xff || (long) value < -0x100)
293fddef416Sniklas return bfd_reloc_overflow;
294fddef416Sniklas
295fddef416Sniklas bfd_put_8 (input_bfd, value, hit_data);
296fddef416Sniklas return bfd_reloc_ok;
297fddef416Sniklas
298fddef416Sniklas case R_MN10200_PCREL16:
299fddef416Sniklas value -= (input_section->output_section->vma
300fddef416Sniklas + input_section->output_offset);
301f7cc78ecSespie value -= (offset + 2);
302fddef416Sniklas value += addend;
303fddef416Sniklas
304fddef416Sniklas if ((long) value > 0xffff || (long) value < -0x10000)
305fddef416Sniklas return bfd_reloc_overflow;
306fddef416Sniklas
307fddef416Sniklas bfd_put_16 (input_bfd, value, hit_data);
308fddef416Sniklas return bfd_reloc_ok;
309fddef416Sniklas
310fddef416Sniklas case R_MN10200_PCREL24:
311fddef416Sniklas value -= (input_section->output_section->vma
312fddef416Sniklas + input_section->output_offset);
313f7cc78ecSespie value -= (offset + 3);
314fddef416Sniklas value += addend;
315fddef416Sniklas
316fddef416Sniklas if ((long) value > 0xffffff || (long) value < -0x1000000)
317fddef416Sniklas return bfd_reloc_overflow;
318fddef416Sniklas
319fddef416Sniklas value &= 0xffffff;
320fddef416Sniklas value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000);
321fddef416Sniklas bfd_put_32 (input_bfd, value, hit_data);
322fddef416Sniklas return bfd_reloc_ok;
323fddef416Sniklas
324fddef416Sniklas default:
325fddef416Sniklas return bfd_reloc_notsupported;
326fddef416Sniklas }
327fddef416Sniklas }
328fddef416Sniklas
329fddef416Sniklas /* Relocate an MN10200 ELF section. */
330d2201f2fSdrahn static bfd_boolean
mn10200_elf_relocate_section(output_bfd,info,input_bfd,input_section,contents,relocs,local_syms,local_sections)331fddef416Sniklas mn10200_elf_relocate_section (output_bfd, info, input_bfd, input_section,
332fddef416Sniklas contents, relocs, local_syms, local_sections)
333fddef416Sniklas bfd *output_bfd;
334fddef416Sniklas struct bfd_link_info *info;
335fddef416Sniklas bfd *input_bfd;
336fddef416Sniklas asection *input_section;
337fddef416Sniklas bfd_byte *contents;
338fddef416Sniklas Elf_Internal_Rela *relocs;
339fddef416Sniklas Elf_Internal_Sym *local_syms;
340fddef416Sniklas asection **local_sections;
341fddef416Sniklas {
342fddef416Sniklas Elf_Internal_Shdr *symtab_hdr;
343fddef416Sniklas struct elf_link_hash_entry **sym_hashes;
344fddef416Sniklas Elf_Internal_Rela *rel, *relend;
345fddef416Sniklas
346*cf2f2c56Smiod if (info->relocatable)
347d2201f2fSdrahn return TRUE;
348d2201f2fSdrahn
349fddef416Sniklas symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
350fddef416Sniklas sym_hashes = elf_sym_hashes (input_bfd);
351fddef416Sniklas
352fddef416Sniklas rel = relocs;
353fddef416Sniklas relend = relocs + input_section->reloc_count;
354fddef416Sniklas for (; rel < relend; rel++)
355fddef416Sniklas {
356fddef416Sniklas int r_type;
357fddef416Sniklas reloc_howto_type *howto;
358fddef416Sniklas unsigned long r_symndx;
359fddef416Sniklas Elf_Internal_Sym *sym;
360fddef416Sniklas asection *sec;
361fddef416Sniklas struct elf_link_hash_entry *h;
362fddef416Sniklas bfd_vma relocation;
363fddef416Sniklas bfd_reloc_status_type r;
364fddef416Sniklas
365fddef416Sniklas r_symndx = ELF32_R_SYM (rel->r_info);
366fddef416Sniklas r_type = ELF32_R_TYPE (rel->r_info);
367fddef416Sniklas howto = elf_mn10200_howto_table + r_type;
368fddef416Sniklas
369fddef416Sniklas h = NULL;
370fddef416Sniklas sym = NULL;
371fddef416Sniklas sec = NULL;
372fddef416Sniklas if (r_symndx < symtab_hdr->sh_info)
373fddef416Sniklas {
374fddef416Sniklas sym = local_syms + r_symndx;
375fddef416Sniklas sec = local_sections[r_symndx];
376*cf2f2c56Smiod relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
377fddef416Sniklas }
378fddef416Sniklas else
379fddef416Sniklas {
380*cf2f2c56Smiod bfd_boolean unresolved_reloc, warned;
381*cf2f2c56Smiod
382*cf2f2c56Smiod RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
383*cf2f2c56Smiod r_symndx, symtab_hdr, sym_hashes,
384*cf2f2c56Smiod h, sec, relocation,
385*cf2f2c56Smiod unresolved_reloc, warned);
386fddef416Sniklas }
387fddef416Sniklas
388fddef416Sniklas r = mn10200_elf_final_link_relocate (howto, input_bfd, output_bfd,
389fddef416Sniklas input_section,
390fddef416Sniklas contents, rel->r_offset,
391fddef416Sniklas relocation, rel->r_addend,
392fddef416Sniklas info, sec, h == NULL);
393fddef416Sniklas
394fddef416Sniklas if (r != bfd_reloc_ok)
395fddef416Sniklas {
396fddef416Sniklas const char *name;
397fddef416Sniklas const char *msg = (const char *) 0;
398fddef416Sniklas
399fddef416Sniklas if (h != NULL)
400fddef416Sniklas name = h->root.root.string;
401fddef416Sniklas else
402fddef416Sniklas {
403fddef416Sniklas name = (bfd_elf_string_from_elf_section
404fddef416Sniklas (input_bfd, symtab_hdr->sh_link, sym->st_name));
405fddef416Sniklas if (name == NULL || *name == '\0')
406fddef416Sniklas name = bfd_section_name (input_bfd, sec);
407fddef416Sniklas }
408fddef416Sniklas
409fddef416Sniklas switch (r)
410fddef416Sniklas {
411fddef416Sniklas case bfd_reloc_overflow:
412fddef416Sniklas if (! ((*info->callbacks->reloc_overflow)
413fddef416Sniklas (info, name, howto->name, (bfd_vma) 0,
414fddef416Sniklas input_bfd, input_section, rel->r_offset)))
415d2201f2fSdrahn return FALSE;
416fddef416Sniklas break;
417fddef416Sniklas
418fddef416Sniklas case bfd_reloc_undefined:
419fddef416Sniklas if (! ((*info->callbacks->undefined_symbol)
420fddef416Sniklas (info, name, input_bfd, input_section,
421d2201f2fSdrahn rel->r_offset, TRUE)))
422d2201f2fSdrahn return FALSE;
423fddef416Sniklas break;
424fddef416Sniklas
425fddef416Sniklas case bfd_reloc_outofrange:
426f7cc78ecSespie msg = _("internal error: out of range error");
427fddef416Sniklas goto common_error;
428fddef416Sniklas
429fddef416Sniklas case bfd_reloc_notsupported:
430f7cc78ecSespie msg = _("internal error: unsupported relocation error");
431fddef416Sniklas goto common_error;
432fddef416Sniklas
433fddef416Sniklas case bfd_reloc_dangerous:
434f7cc78ecSespie msg = _("internal error: dangerous error");
435fddef416Sniklas goto common_error;
436fddef416Sniklas
437fddef416Sniklas default:
438f7cc78ecSespie msg = _("internal error: unknown error");
439fddef416Sniklas /* fall through */
440fddef416Sniklas
441fddef416Sniklas common_error:
442fddef416Sniklas if (!((*info->callbacks->warning)
443fddef416Sniklas (info, msg, name, input_bfd, input_section,
444fddef416Sniklas rel->r_offset)))
445d2201f2fSdrahn return FALSE;
446fddef416Sniklas break;
447fddef416Sniklas }
448fddef416Sniklas }
449fddef416Sniklas }
450fddef416Sniklas
451d2201f2fSdrahn return TRUE;
452fddef416Sniklas }
453fddef416Sniklas
454fddef416Sniklas /* This function handles relaxing for the mn10200.
455fddef416Sniklas
456*cf2f2c56Smiod There are quite a few relaxing opportunities available on the mn10200:
457fddef416Sniklas
458fddef416Sniklas * jsr:24 -> jsr:16 2 bytes
459fddef416Sniklas
460fddef416Sniklas * jmp:24 -> jmp:16 2 bytes
461fddef416Sniklas * jmp:16 -> bra:8 1 byte
462fddef416Sniklas
463fddef416Sniklas * If the previous instruction is a conditional branch
464fddef416Sniklas around the jump/bra, we may be able to reverse its condition
465fddef416Sniklas and change its target to the jump's target. The jump/bra
466fddef416Sniklas can then be deleted. 2 bytes
467fddef416Sniklas
468fddef416Sniklas * mov abs24 -> mov abs16 2 byte savings
469fddef416Sniklas
470fddef416Sniklas * Most instructions which accept imm24 can relax to imm16 2 bytes
471fddef416Sniklas - Most instructions which accept imm16 can relax to imm8 1 byte
472fddef416Sniklas
473fddef416Sniklas * Most instructions which accept d24 can relax to d16 2 bytes
474fddef416Sniklas - Most instructions which accept d16 can relax to d8 1 byte
475fddef416Sniklas
476fddef416Sniklas abs24, imm24, d24 all look the same at the reloc level. It
477fddef416Sniklas might make the code simpler if we had different relocs for
478fddef416Sniklas the various relaxable operand types.
479fddef416Sniklas
480fddef416Sniklas We don't handle imm16->imm8 or d16->d8 as they're very rare
481fddef416Sniklas and somewhat more difficult to support. */
482fddef416Sniklas
483d2201f2fSdrahn static bfd_boolean
mn10200_elf_relax_section(abfd,sec,link_info,again)484fddef416Sniklas mn10200_elf_relax_section (abfd, sec, link_info, again)
485fddef416Sniklas bfd *abfd;
486fddef416Sniklas asection *sec;
487fddef416Sniklas struct bfd_link_info *link_info;
488d2201f2fSdrahn bfd_boolean *again;
489fddef416Sniklas {
490fddef416Sniklas Elf_Internal_Shdr *symtab_hdr;
491fddef416Sniklas Elf_Internal_Rela *internal_relocs;
492fddef416Sniklas Elf_Internal_Rela *irel, *irelend;
493fddef416Sniklas bfd_byte *contents = NULL;
494d2201f2fSdrahn Elf_Internal_Sym *isymbuf = NULL;
495fddef416Sniklas
496fddef416Sniklas /* Assume nothing changes. */
497d2201f2fSdrahn *again = FALSE;
498fddef416Sniklas
499*cf2f2c56Smiod /* We don't have to do anything for a relocatable link, if
500fddef416Sniklas this section does not have relocs, or if this is not a
501fddef416Sniklas code section. */
502*cf2f2c56Smiod if (link_info->relocatable
503fddef416Sniklas || (sec->flags & SEC_RELOC) == 0
504fddef416Sniklas || sec->reloc_count == 0
505fddef416Sniklas || (sec->flags & SEC_CODE) == 0)
506d2201f2fSdrahn return TRUE;
507fddef416Sniklas
508fddef416Sniklas /* If this is the first time we have been called for this section,
509fddef416Sniklas initialize the cooked size. */
510fddef416Sniklas if (sec->_cooked_size == 0)
511fddef416Sniklas sec->_cooked_size = sec->_raw_size;
512fddef416Sniklas
513fddef416Sniklas symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
514fddef416Sniklas
515fddef416Sniklas /* Get a copy of the native relocations. */
516*cf2f2c56Smiod internal_relocs = (_bfd_elf_link_read_relocs
517fddef416Sniklas (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
518fddef416Sniklas link_info->keep_memory));
519fddef416Sniklas if (internal_relocs == NULL)
520fddef416Sniklas goto error_return;
521fddef416Sniklas
522fddef416Sniklas /* Walk through them looking for relaxing opportunities. */
523fddef416Sniklas irelend = internal_relocs + sec->reloc_count;
524fddef416Sniklas for (irel = internal_relocs; irel < irelend; irel++)
525fddef416Sniklas {
526fddef416Sniklas bfd_vma symval;
527fddef416Sniklas
528fddef416Sniklas /* If this isn't something that can be relaxed, then ignore
529fddef416Sniklas this reloc. */
530fddef416Sniklas if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10200_NONE
531fddef416Sniklas || ELF32_R_TYPE (irel->r_info) == (int) R_MN10200_8
532fddef416Sniklas || ELF32_R_TYPE (irel->r_info) == (int) R_MN10200_MAX)
533fddef416Sniklas continue;
534fddef416Sniklas
535fddef416Sniklas /* Get the section contents if we haven't done so already. */
536fddef416Sniklas if (contents == NULL)
537fddef416Sniklas {
538fddef416Sniklas /* Get cached copy if it exists. */
539fddef416Sniklas if (elf_section_data (sec)->this_hdr.contents != NULL)
540fddef416Sniklas contents = elf_section_data (sec)->this_hdr.contents;
541fddef416Sniklas else
542fddef416Sniklas {
543fddef416Sniklas /* Go get them off disk. */
544fddef416Sniklas contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
545fddef416Sniklas if (contents == NULL)
546fddef416Sniklas goto error_return;
547fddef416Sniklas
548fddef416Sniklas if (! bfd_get_section_contents (abfd, sec, contents,
549fddef416Sniklas (file_ptr) 0, sec->_raw_size))
550fddef416Sniklas goto error_return;
551fddef416Sniklas }
552fddef416Sniklas }
553fddef416Sniklas
554d2201f2fSdrahn /* Read this BFD's local symbols if we haven't done so already. */
555d2201f2fSdrahn if (isymbuf == NULL && symtab_hdr->sh_info != 0)
556fddef416Sniklas {
557d2201f2fSdrahn isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
558d2201f2fSdrahn if (isymbuf == NULL)
559d2201f2fSdrahn isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
560d2201f2fSdrahn symtab_hdr->sh_info, 0,
561d2201f2fSdrahn NULL, NULL, NULL);
562d2201f2fSdrahn if (isymbuf == NULL)
563fddef416Sniklas goto error_return;
564fddef416Sniklas }
565fddef416Sniklas
566fddef416Sniklas /* Get the value of the symbol referred to by the reloc. */
567fddef416Sniklas if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
568fddef416Sniklas {
569d2201f2fSdrahn /* A local symbol. */
570d2201f2fSdrahn Elf_Internal_Sym *isym;
571fddef416Sniklas asection *sym_sec;
572fddef416Sniklas
573d2201f2fSdrahn isym = isymbuf + ELF32_R_SYM (irel->r_info);
574d2201f2fSdrahn if (isym->st_shndx == SHN_UNDEF)
575d2201f2fSdrahn sym_sec = bfd_und_section_ptr;
576d2201f2fSdrahn else if (isym->st_shndx == SHN_ABS)
577d2201f2fSdrahn sym_sec = bfd_abs_section_ptr;
578d2201f2fSdrahn else if (isym->st_shndx == SHN_COMMON)
579d2201f2fSdrahn sym_sec = bfd_com_section_ptr;
580d2201f2fSdrahn else
581d2201f2fSdrahn sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
582d2201f2fSdrahn symval = (isym->st_value
583fddef416Sniklas + sym_sec->output_section->vma
584fddef416Sniklas + sym_sec->output_offset);
585fddef416Sniklas }
586fddef416Sniklas else
587fddef416Sniklas {
588fddef416Sniklas unsigned long indx;
589fddef416Sniklas struct elf_link_hash_entry *h;
590fddef416Sniklas
591fddef416Sniklas /* An external symbol. */
592fddef416Sniklas indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
593fddef416Sniklas h = elf_sym_hashes (abfd)[indx];
594fddef416Sniklas BFD_ASSERT (h != NULL);
595fddef416Sniklas if (h->root.type != bfd_link_hash_defined
596fddef416Sniklas && h->root.type != bfd_link_hash_defweak)
597fddef416Sniklas {
598fddef416Sniklas /* This appears to be a reference to an undefined
599fddef416Sniklas symbol. Just ignore it--it will be caught by the
600fddef416Sniklas regular reloc processing. */
601fddef416Sniklas continue;
602fddef416Sniklas }
603fddef416Sniklas
604fddef416Sniklas symval = (h->root.u.def.value
605fddef416Sniklas + h->root.u.def.section->output_section->vma
606fddef416Sniklas + h->root.u.def.section->output_offset);
607fddef416Sniklas }
608fddef416Sniklas
609fddef416Sniklas /* For simplicity of coding, we are going to modify the section
610fddef416Sniklas contents, the section relocs, and the BFD symbol table. We
611fddef416Sniklas must tell the rest of the code not to free up this
612fddef416Sniklas information. It would be possible to instead create a table
613fddef416Sniklas of changes which have to be made, as is done in coff-mips.c;
614fddef416Sniklas that would be more work, but would require less memory when
615fddef416Sniklas the linker is run. */
616fddef416Sniklas
617fddef416Sniklas /* Try to turn a 24bit pc-relative branch/call into a 16bit pc-relative
618fddef416Sniklas branch/call. */
619fddef416Sniklas if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10200_PCREL24)
620fddef416Sniklas {
621fddef416Sniklas bfd_vma value = symval;
622fddef416Sniklas
623fddef416Sniklas /* Deal with pc-relative gunk. */
624fddef416Sniklas value -= (sec->output_section->vma + sec->output_offset);
625f7cc78ecSespie value -= (irel->r_offset + 3);
626fddef416Sniklas value += irel->r_addend;
627fddef416Sniklas
628fddef416Sniklas /* See if the value will fit in 16 bits, note the high value is
629fddef416Sniklas 0x7fff + 2 as the target will be two bytes closer if we are
630fddef416Sniklas able to relax. */
631fddef416Sniklas if ((long) value < 0x8001 && (long) value > -0x8000)
632fddef416Sniklas {
633fddef416Sniklas unsigned char code;
634fddef416Sniklas
635fddef416Sniklas /* Get the opcode. */
636fddef416Sniklas code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
637fddef416Sniklas
638fddef416Sniklas if (code != 0xe0 && code != 0xe1)
639fddef416Sniklas continue;
640fddef416Sniklas
641fddef416Sniklas /* Note that we've changed the relocs, section contents, etc. */
642fddef416Sniklas elf_section_data (sec)->relocs = internal_relocs;
643fddef416Sniklas elf_section_data (sec)->this_hdr.contents = contents;
644d2201f2fSdrahn symtab_hdr->contents = (unsigned char *) isymbuf;
645fddef416Sniklas
646fddef416Sniklas /* Fix the opcode. */
647fddef416Sniklas if (code == 0xe0)
648fddef416Sniklas bfd_put_8 (abfd, 0xfc, contents + irel->r_offset - 2);
649fddef416Sniklas else if (code == 0xe1)
650fddef416Sniklas bfd_put_8 (abfd, 0xfd, contents + irel->r_offset - 2);
651fddef416Sniklas
652fddef416Sniklas /* Fix the relocation's type. */
653fddef416Sniklas irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
654fddef416Sniklas R_MN10200_PCREL16);
655fddef416Sniklas
656f7cc78ecSespie /* The opcode got shorter too, so we have to fix the offset. */
657fddef416Sniklas irel->r_offset -= 1;
658fddef416Sniklas
659fddef416Sniklas /* Delete two bytes of data. */
660fddef416Sniklas if (!mn10200_elf_relax_delete_bytes (abfd, sec,
661fddef416Sniklas irel->r_offset + 1, 2))
662fddef416Sniklas goto error_return;
663fddef416Sniklas
664fddef416Sniklas /* That will change things, so, we should relax again.
665fddef416Sniklas Note that this is not required, and it may be slow. */
666d2201f2fSdrahn *again = TRUE;
667fddef416Sniklas }
668fddef416Sniklas }
669fddef416Sniklas
670fddef416Sniklas /* Try to turn a 16bit pc-relative branch into a 8bit pc-relative
671fddef416Sniklas branch. */
672fddef416Sniklas if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10200_PCREL16)
673fddef416Sniklas {
674fddef416Sniklas bfd_vma value = symval;
675fddef416Sniklas
676fddef416Sniklas /* Deal with pc-relative gunk. */
677fddef416Sniklas value -= (sec->output_section->vma + sec->output_offset);
678f7cc78ecSespie value -= (irel->r_offset + 2);
679fddef416Sniklas value += irel->r_addend;
680fddef416Sniklas
681fddef416Sniklas /* See if the value will fit in 8 bits, note the high value is
682fddef416Sniklas 0x7f + 1 as the target will be one bytes closer if we are
683fddef416Sniklas able to relax. */
684fddef416Sniklas if ((long) value < 0x80 && (long) value > -0x80)
685fddef416Sniklas {
686fddef416Sniklas unsigned char code;
687fddef416Sniklas
688fddef416Sniklas /* Get the opcode. */
689fddef416Sniklas code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
690fddef416Sniklas
691fddef416Sniklas if (code != 0xfc)
692fddef416Sniklas continue;
693fddef416Sniklas
694fddef416Sniklas /* Note that we've changed the relocs, section contents, etc. */
695fddef416Sniklas elf_section_data (sec)->relocs = internal_relocs;
696fddef416Sniklas elf_section_data (sec)->this_hdr.contents = contents;
697d2201f2fSdrahn symtab_hdr->contents = (unsigned char *) isymbuf;
698fddef416Sniklas
699fddef416Sniklas /* Fix the opcode. */
700fddef416Sniklas bfd_put_8 (abfd, 0xea, contents + irel->r_offset - 1);
701fddef416Sniklas
702fddef416Sniklas /* Fix the relocation's type. */
703fddef416Sniklas irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
704fddef416Sniklas R_MN10200_PCREL8);
705fddef416Sniklas
706fddef416Sniklas /* Delete one byte of data. */
707fddef416Sniklas if (!mn10200_elf_relax_delete_bytes (abfd, sec,
708fddef416Sniklas irel->r_offset + 1, 1))
709fddef416Sniklas goto error_return;
710fddef416Sniklas
711fddef416Sniklas /* That will change things, so, we should relax again.
712fddef416Sniklas Note that this is not required, and it may be slow. */
713d2201f2fSdrahn *again = TRUE;
714fddef416Sniklas }
715fddef416Sniklas }
716fddef416Sniklas
717fddef416Sniklas /* Try to eliminate an unconditional 8 bit pc-relative branch
718fddef416Sniklas which immediately follows a conditional 8 bit pc-relative
719fddef416Sniklas branch around the unconditional branch.
720fddef416Sniklas
721fddef416Sniklas original: new:
722fddef416Sniklas bCC lab1 bCC' lab2
723fddef416Sniklas bra lab2
724fddef416Sniklas lab1: lab1:
725fddef416Sniklas
726fddef416Sniklas This happens when the bCC can't reach lab2 at assembly time,
727fddef416Sniklas but due to other relaxations it can reach at link time. */
728fddef416Sniklas if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10200_PCREL8)
729fddef416Sniklas {
730fddef416Sniklas Elf_Internal_Rela *nrel;
731fddef416Sniklas bfd_vma value = symval;
732fddef416Sniklas unsigned char code;
733fddef416Sniklas
734fddef416Sniklas /* Deal with pc-relative gunk. */
735fddef416Sniklas value -= (sec->output_section->vma + sec->output_offset);
736f7cc78ecSespie value -= (irel->r_offset + 1);
737fddef416Sniklas value += irel->r_addend;
738fddef416Sniklas
739fddef416Sniklas /* Do nothing if this reloc is the last byte in the section. */
740fddef416Sniklas if (irel->r_offset == sec->_cooked_size)
741fddef416Sniklas continue;
742fddef416Sniklas
743fddef416Sniklas /* See if the next instruction is an unconditional pc-relative
744fddef416Sniklas branch, more often than not this test will fail, so we
745fddef416Sniklas test it first to speed things up. */
746fddef416Sniklas code = bfd_get_8 (abfd, contents + irel->r_offset + 1);
747fddef416Sniklas if (code != 0xea)
748fddef416Sniklas continue;
749fddef416Sniklas
750fddef416Sniklas /* Also make sure the next relocation applies to the next
751fddef416Sniklas instruction and that it's a pc-relative 8 bit branch. */
752fddef416Sniklas nrel = irel + 1;
753fddef416Sniklas if (nrel == irelend
754fddef416Sniklas || irel->r_offset + 2 != nrel->r_offset
755fddef416Sniklas || ELF32_R_TYPE (nrel->r_info) != (int) R_MN10200_PCREL8)
756fddef416Sniklas continue;
757fddef416Sniklas
758fddef416Sniklas /* Make sure our destination immediately follows the
759fddef416Sniklas unconditional branch. */
760fddef416Sniklas if (symval != (sec->output_section->vma + sec->output_offset
761fddef416Sniklas + irel->r_offset + 3))
762fddef416Sniklas continue;
763fddef416Sniklas
764fddef416Sniklas /* Now make sure we are a conditional branch. This may not
765fddef416Sniklas be necessary, but why take the chance.
766fddef416Sniklas
767fddef416Sniklas Note these checks assume that R_MN10200_PCREL8 relocs
768fddef416Sniklas only occur on bCC and bCCx insns. If they occured
769fddef416Sniklas elsewhere, we'd need to know the start of this insn
770fddef416Sniklas for this check to be accurate. */
771fddef416Sniklas code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
772fddef416Sniklas if (code != 0xe0 && code != 0xe1 && code != 0xe2
773fddef416Sniklas && code != 0xe3 && code != 0xe4 && code != 0xe5
774fddef416Sniklas && code != 0xe6 && code != 0xe7 && code != 0xe8
775fddef416Sniklas && code != 0xe9 && code != 0xec && code != 0xed
776fddef416Sniklas && code != 0xee && code != 0xef && code != 0xfc
777fddef416Sniklas && code != 0xfd && code != 0xfe && code != 0xff)
778fddef416Sniklas continue;
779fddef416Sniklas
780fddef416Sniklas /* We also have to be sure there is no symbol/label
781fddef416Sniklas at the unconditional branch. */
782d2201f2fSdrahn if (mn10200_elf_symbol_address_p (abfd, sec, isymbuf,
783fddef416Sniklas irel->r_offset + 1))
784fddef416Sniklas continue;
785fddef416Sniklas
786fddef416Sniklas /* Note that we've changed the relocs, section contents, etc. */
787fddef416Sniklas elf_section_data (sec)->relocs = internal_relocs;
788fddef416Sniklas elf_section_data (sec)->this_hdr.contents = contents;
789d2201f2fSdrahn symtab_hdr->contents = (unsigned char *) isymbuf;
790fddef416Sniklas
791fddef416Sniklas /* Reverse the condition of the first branch. */
792fddef416Sniklas switch (code)
793fddef416Sniklas {
794fddef416Sniklas case 0xfc:
795fddef416Sniklas code = 0xfd;
796fddef416Sniklas break;
797fddef416Sniklas case 0xfd:
798fddef416Sniklas code = 0xfc;
799fddef416Sniklas break;
800fddef416Sniklas case 0xfe:
801fddef416Sniklas code = 0xff;
802fddef416Sniklas break;
803fddef416Sniklas case 0xff:
804fddef416Sniklas code = 0xfe;
805fddef416Sniklas break;
806fddef416Sniklas case 0xe8:
807fddef416Sniklas code = 0xe9;
808fddef416Sniklas break;
809fddef416Sniklas case 0xe9:
810fddef416Sniklas code = 0xe8;
811fddef416Sniklas break;
812fddef416Sniklas case 0xe0:
813fddef416Sniklas code = 0xe2;
814fddef416Sniklas break;
815fddef416Sniklas case 0xe2:
816fddef416Sniklas code = 0xe0;
817fddef416Sniklas break;
818fddef416Sniklas case 0xe3:
819fddef416Sniklas code = 0xe1;
820fddef416Sniklas break;
821fddef416Sniklas case 0xe1:
822fddef416Sniklas code = 0xe3;
823fddef416Sniklas break;
824fddef416Sniklas case 0xe4:
825fddef416Sniklas code = 0xe6;
826fddef416Sniklas break;
827fddef416Sniklas case 0xe6:
828fddef416Sniklas code = 0xe4;
829fddef416Sniklas break;
830fddef416Sniklas case 0xe7:
831fddef416Sniklas code = 0xe5;
832fddef416Sniklas break;
833fddef416Sniklas case 0xe5:
834fddef416Sniklas code = 0xe7;
835fddef416Sniklas break;
836fddef416Sniklas case 0xec:
837fddef416Sniklas code = 0xed;
838fddef416Sniklas break;
839fddef416Sniklas case 0xed:
840fddef416Sniklas code = 0xec;
841fddef416Sniklas break;
842fddef416Sniklas case 0xee:
843fddef416Sniklas code = 0xef;
844fddef416Sniklas break;
845fddef416Sniklas case 0xef:
846fddef416Sniklas code = 0xee;
847fddef416Sniklas break;
848fddef416Sniklas }
849fddef416Sniklas bfd_put_8 (abfd, code, contents + irel->r_offset - 1);
850fddef416Sniklas
851fddef416Sniklas /* Set the reloc type and symbol for the first branch
852fddef416Sniklas from the second branch. */
853fddef416Sniklas irel->r_info = nrel->r_info;
854fddef416Sniklas
855fddef416Sniklas /* Make the reloc for the second branch a null reloc. */
856fddef416Sniklas nrel->r_info = ELF32_R_INFO (ELF32_R_SYM (nrel->r_info),
857fddef416Sniklas R_MN10200_NONE);
858fddef416Sniklas
859fddef416Sniklas /* Delete two bytes of data. */
860fddef416Sniklas if (!mn10200_elf_relax_delete_bytes (abfd, sec,
861fddef416Sniklas irel->r_offset + 1, 2))
862fddef416Sniklas goto error_return;
863fddef416Sniklas
864fddef416Sniklas /* That will change things, so, we should relax again.
865fddef416Sniklas Note that this is not required, and it may be slow. */
866d2201f2fSdrahn *again = TRUE;
867fddef416Sniklas }
868fddef416Sniklas
869fddef416Sniklas /* Try to turn a 24bit immediate, displacement or absolute address
870fddef416Sniklas into a 16bit immediate, displacement or absolute address. */
871fddef416Sniklas if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10200_24)
872fddef416Sniklas {
873fddef416Sniklas bfd_vma value = symval;
874fddef416Sniklas
875fddef416Sniklas /* See if the value will fit in 16 bits.
876fddef416Sniklas We allow any 16bit match here. We prune those we can't
877fddef416Sniklas handle below. */
878fddef416Sniklas if ((long) value < 0x7fff && (long) value > -0x8000)
879fddef416Sniklas {
880fddef416Sniklas unsigned char code;
881fddef416Sniklas
882fddef416Sniklas /* All insns which have 24bit operands are 5 bytes long,
883fddef416Sniklas the first byte will always be 0xf4, but we double check
884fddef416Sniklas it just in case. */
885fddef416Sniklas
886fddef416Sniklas /* Get the first opcode. */
887fddef416Sniklas code = bfd_get_8 (abfd, contents + irel->r_offset - 2);
888fddef416Sniklas
889fddef416Sniklas if (code != 0xf4)
890fddef416Sniklas continue;
891fddef416Sniklas
892fddef416Sniklas /* Get the second opcode. */
893fddef416Sniklas code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
894fddef416Sniklas
895fddef416Sniklas switch (code & 0xfc)
896fddef416Sniklas {
897fddef416Sniklas /* mov imm24,dn -> mov imm16,dn */
898fddef416Sniklas case 0x70:
899fddef416Sniklas /* Not safe if the high bit is on as relaxing may
900fddef416Sniklas move the value out of high mem and thus not fit
901fddef416Sniklas in a signed 16bit value. */
902fddef416Sniklas if (value & 0x8000)
903fddef416Sniklas continue;
904fddef416Sniklas
905*cf2f2c56Smiod /* Note that we've changed the relocation contents, etc. */
906fddef416Sniklas elf_section_data (sec)->relocs = internal_relocs;
907fddef416Sniklas elf_section_data (sec)->this_hdr.contents = contents;
908d2201f2fSdrahn symtab_hdr->contents = (unsigned char *) isymbuf;
909fddef416Sniklas
910fddef416Sniklas /* Fix the opcode. */
911fddef416Sniklas bfd_put_8 (abfd, 0xf8 + (code & 0x03),
912fddef416Sniklas contents + irel->r_offset - 2);
913fddef416Sniklas
914fddef416Sniklas /* Fix the relocation's type. */
915fddef416Sniklas irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
916fddef416Sniklas R_MN10200_16);
917fddef416Sniklas
918fddef416Sniklas /* The opcode got shorter too, so we have to fix the
919f7cc78ecSespie offset. */
920fddef416Sniklas irel->r_offset -= 1;
921fddef416Sniklas
922fddef416Sniklas /* Delete two bytes of data. */
923fddef416Sniklas if (!mn10200_elf_relax_delete_bytes (abfd, sec,
924fddef416Sniklas irel->r_offset + 1, 2))
925fddef416Sniklas goto error_return;
926fddef416Sniklas
927fddef416Sniklas /* That will change things, so, we should relax again.
928fddef416Sniklas Note that this is not required, and it may be slow. */
929d2201f2fSdrahn *again = TRUE;
930fddef416Sniklas break;
931fddef416Sniklas
932fddef416Sniklas /* mov imm24,an -> mov imm16,an
933fddef416Sniklas cmp imm24,an -> cmp imm16,an
934fddef416Sniklas mov (abs24),dn -> mov (abs16),dn
935fddef416Sniklas mov dn,(abs24) -> mov dn,(abs16)
936fddef416Sniklas movb dn,(abs24) -> movb dn,(abs16)
937fddef416Sniklas movbu (abs24),dn -> movbu (abs16),dn */
938fddef416Sniklas case 0x74:
939fddef416Sniklas case 0x7c:
940fddef416Sniklas case 0xc0:
941fddef416Sniklas case 0x40:
942fddef416Sniklas case 0x44:
943fddef416Sniklas case 0xc8:
944*cf2f2c56Smiod /* Note that we've changed the relocation contents, etc. */
945fddef416Sniklas elf_section_data (sec)->relocs = internal_relocs;
946fddef416Sniklas elf_section_data (sec)->this_hdr.contents = contents;
947d2201f2fSdrahn symtab_hdr->contents = (unsigned char *) isymbuf;
948fddef416Sniklas
949fddef416Sniklas if ((code & 0xfc) == 0x74)
950fddef416Sniklas code = 0xdc + (code & 0x03);
951fddef416Sniklas else if ((code & 0xfc) == 0x7c)
952fddef416Sniklas code = 0xec + (code & 0x03);
953fddef416Sniklas else if ((code & 0xfc) == 0xc0)
954fddef416Sniklas code = 0xc8 + (code & 0x03);
955fddef416Sniklas else if ((code & 0xfc) == 0x40)
956fddef416Sniklas code = 0xc0 + (code & 0x03);
957fddef416Sniklas else if ((code & 0xfc) == 0x44)
958fddef416Sniklas code = 0xc4 + (code & 0x03);
959fddef416Sniklas else if ((code & 0xfc) == 0xc8)
960fddef416Sniklas code = 0xcc + (code & 0x03);
961fddef416Sniklas
962fddef416Sniklas /* Fix the opcode. */
963fddef416Sniklas bfd_put_8 (abfd, code, contents + irel->r_offset - 2);
964fddef416Sniklas
965fddef416Sniklas /* Fix the relocation's type. */
966fddef416Sniklas irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
967fddef416Sniklas R_MN10200_16);
968fddef416Sniklas
969fddef416Sniklas /* The opcode got shorter too, so we have to fix the
970f7cc78ecSespie offset. */
971fddef416Sniklas irel->r_offset -= 1;
972fddef416Sniklas
973fddef416Sniklas /* Delete two bytes of data. */
974fddef416Sniklas if (!mn10200_elf_relax_delete_bytes (abfd, sec,
975fddef416Sniklas irel->r_offset + 1, 2))
976fddef416Sniklas goto error_return;
977fddef416Sniklas
978fddef416Sniklas /* That will change things, so, we should relax again.
979fddef416Sniklas Note that this is not required, and it may be slow. */
980d2201f2fSdrahn *again = TRUE;
981fddef416Sniklas break;
982fddef416Sniklas
983fddef416Sniklas /* cmp imm24,dn -> cmp imm16,dn
984fddef416Sniklas mov (abs24),an -> mov (abs16),an
985fddef416Sniklas mov an,(abs24) -> mov an,(abs16)
986fddef416Sniklas add imm24,dn -> add imm16,dn
987fddef416Sniklas add imm24,an -> add imm16,an
988fddef416Sniklas sub imm24,dn -> sub imm16,dn
989fddef416Sniklas sub imm24,an -> sub imm16,an
990fddef416Sniklas And all d24->d16 in memory ops. */
991fddef416Sniklas case 0x78:
992fddef416Sniklas case 0xd0:
993fddef416Sniklas case 0x50:
994fddef416Sniklas case 0x60:
995fddef416Sniklas case 0x64:
996fddef416Sniklas case 0x68:
997fddef416Sniklas case 0x6c:
998fddef416Sniklas case 0x80:
999fddef416Sniklas case 0xf0:
1000fddef416Sniklas case 0x00:
1001fddef416Sniklas case 0x10:
1002fddef416Sniklas case 0xb0:
1003fddef416Sniklas case 0x30:
1004fddef416Sniklas case 0xa0:
1005fddef416Sniklas case 0x20:
1006fddef416Sniklas case 0x90:
1007fddef416Sniklas /* Not safe if the high bit is on as relaxing may
1008fddef416Sniklas move the value out of high mem and thus not fit
1009fddef416Sniklas in a signed 16bit value. */
1010fddef416Sniklas if (((code & 0xfc) == 0x78
1011fddef416Sniklas || (code & 0xfc) == 0x60
1012fddef416Sniklas || (code & 0xfc) == 0x64
1013fddef416Sniklas || (code & 0xfc) == 0x68
1014fddef416Sniklas || (code & 0xfc) == 0x6c
1015fddef416Sniklas || (code & 0xfc) == 0x80
1016fddef416Sniklas || (code & 0xfc) == 0xf0
1017fddef416Sniklas || (code & 0xfc) == 0x00
1018fddef416Sniklas || (code & 0xfc) == 0x10
1019fddef416Sniklas || (code & 0xfc) == 0xb0
1020fddef416Sniklas || (code & 0xfc) == 0x30
1021fddef416Sniklas || (code & 0xfc) == 0xa0
1022fddef416Sniklas || (code & 0xfc) == 0x20
1023fddef416Sniklas || (code & 0xfc) == 0x90)
1024fddef416Sniklas && (value & 0x8000) != 0)
1025fddef416Sniklas continue;
1026fddef416Sniklas
1027*cf2f2c56Smiod /* Note that we've changed the relocation contents, etc. */
1028fddef416Sniklas elf_section_data (sec)->relocs = internal_relocs;
1029fddef416Sniklas elf_section_data (sec)->this_hdr.contents = contents;
1030d2201f2fSdrahn symtab_hdr->contents = (unsigned char *) isymbuf;
1031fddef416Sniklas
1032fddef416Sniklas /* Fix the opcode. */
1033fddef416Sniklas bfd_put_8 (abfd, 0xf7, contents + irel->r_offset - 2);
1034fddef416Sniklas
1035fddef416Sniklas if ((code & 0xfc) == 0x78)
1036fddef416Sniklas code = 0x48 + (code & 0x03);
1037fddef416Sniklas else if ((code & 0xfc) == 0xd0)
1038fddef416Sniklas code = 0x30 + (code & 0x03);
1039fddef416Sniklas else if ((code & 0xfc) == 0x50)
1040fddef416Sniklas code = 0x20 + (code & 0x03);
1041fddef416Sniklas else if ((code & 0xfc) == 0x60)
1042fddef416Sniklas code = 0x18 + (code & 0x03);
1043fddef416Sniklas else if ((code & 0xfc) == 0x64)
1044fddef416Sniklas code = 0x08 + (code & 0x03);
1045fddef416Sniklas else if ((code & 0xfc) == 0x68)
1046fddef416Sniklas code = 0x1c + (code & 0x03);
1047fddef416Sniklas else if ((code & 0xfc) == 0x6c)
1048fddef416Sniklas code = 0x0c + (code & 0x03);
1049fddef416Sniklas else if ((code & 0xfc) == 0x80)
1050fddef416Sniklas code = 0xc0 + (code & 0x07);
1051fddef416Sniklas else if ((code & 0xfc) == 0xf0)
1052fddef416Sniklas code = 0xb0 + (code & 0x07);
1053fddef416Sniklas else if ((code & 0xfc) == 0x00)
1054fddef416Sniklas code = 0x80 + (code & 0x07);
1055fddef416Sniklas else if ((code & 0xfc) == 0x10)
1056fddef416Sniklas code = 0xa0 + (code & 0x07);
1057fddef416Sniklas else if ((code & 0xfc) == 0xb0)
1058fddef416Sniklas code = 0x70 + (code & 0x07);
1059fddef416Sniklas else if ((code & 0xfc) == 0x30)
1060fddef416Sniklas code = 0x60 + (code & 0x07);
1061fddef416Sniklas else if ((code & 0xfc) == 0xa0)
1062fddef416Sniklas code = 0xd0 + (code & 0x07);
1063fddef416Sniklas else if ((code & 0xfc) == 0x20)
1064fddef416Sniklas code = 0x90 + (code & 0x07);
1065fddef416Sniklas else if ((code & 0xfc) == 0x90)
1066fddef416Sniklas code = 0x50 + (code & 0x07);
1067fddef416Sniklas
1068fddef416Sniklas bfd_put_8 (abfd, code, contents + irel->r_offset - 1);
1069fddef416Sniklas
1070fddef416Sniklas /* Fix the relocation's type. */
1071fddef416Sniklas irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1072fddef416Sniklas R_MN10200_16);
1073fddef416Sniklas
1074fddef416Sniklas /* Delete one bytes of data. */
1075fddef416Sniklas if (!mn10200_elf_relax_delete_bytes (abfd, sec,
1076fddef416Sniklas irel->r_offset + 2, 1))
1077fddef416Sniklas goto error_return;
1078fddef416Sniklas
1079fddef416Sniklas /* That will change things, so, we should relax again.
1080fddef416Sniklas Note that this is not required, and it may be slow. */
1081d2201f2fSdrahn *again = TRUE;
1082fddef416Sniklas break;
1083fddef416Sniklas
1084fddef416Sniklas /* movb (abs24),dn ->movbu (abs16),dn extxb bn */
1085fddef416Sniklas case 0xc4:
1086fddef416Sniklas /* Note that we've changed the reldection contents, etc. */
1087fddef416Sniklas elf_section_data (sec)->relocs = internal_relocs;
1088fddef416Sniklas elf_section_data (sec)->this_hdr.contents = contents;
1089d2201f2fSdrahn symtab_hdr->contents = (unsigned char *) isymbuf;
1090fddef416Sniklas
1091fddef416Sniklas bfd_put_8 (abfd, 0xcc + (code & 0x03),
1092fddef416Sniklas contents + irel->r_offset - 2);
1093fddef416Sniklas
1094fddef416Sniklas bfd_put_8 (abfd, 0xb8 + (code & 0x03),
1095fddef416Sniklas contents + irel->r_offset - 1);
1096fddef416Sniklas
1097fddef416Sniklas /* Fix the relocation's type. */
1098fddef416Sniklas irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1099fddef416Sniklas R_MN10200_16);
1100fddef416Sniklas
1101fddef416Sniklas /* The reloc will be applied one byte in front of its
1102fddef416Sniklas current location. */
1103fddef416Sniklas irel->r_offset -= 1;
1104fddef416Sniklas
1105fddef416Sniklas /* Delete one bytes of data. */
1106fddef416Sniklas if (!mn10200_elf_relax_delete_bytes (abfd, sec,
1107fddef416Sniklas irel->r_offset + 2, 1))
1108fddef416Sniklas goto error_return;
1109fddef416Sniklas
1110fddef416Sniklas /* That will change things, so, we should relax again.
1111fddef416Sniklas Note that this is not required, and it may be slow. */
1112d2201f2fSdrahn *again = TRUE;
1113fddef416Sniklas break;
1114fddef416Sniklas }
1115fddef416Sniklas }
1116fddef416Sniklas }
1117fddef416Sniklas }
1118fddef416Sniklas
1119d2201f2fSdrahn if (isymbuf != NULL
1120d2201f2fSdrahn && symtab_hdr->contents != (unsigned char *) isymbuf)
1121fddef416Sniklas {
1122fddef416Sniklas if (! link_info->keep_memory)
1123d2201f2fSdrahn free (isymbuf);
1124d2201f2fSdrahn else
1125d2201f2fSdrahn {
1126d2201f2fSdrahn /* Cache the symbols for elf_link_input_bfd. */
1127d2201f2fSdrahn symtab_hdr->contents = (unsigned char *) isymbuf;
1128d2201f2fSdrahn }
1129d2201f2fSdrahn }
1130d2201f2fSdrahn
1131d2201f2fSdrahn if (contents != NULL
1132d2201f2fSdrahn && elf_section_data (sec)->this_hdr.contents != contents)
1133d2201f2fSdrahn {
1134d2201f2fSdrahn if (! link_info->keep_memory)
1135d2201f2fSdrahn free (contents);
1136fddef416Sniklas else
1137fddef416Sniklas {
1138fddef416Sniklas /* Cache the section contents for elf_link_input_bfd. */
1139fddef416Sniklas elf_section_data (sec)->this_hdr.contents = contents;
1140fddef416Sniklas }
1141fddef416Sniklas }
1142fddef416Sniklas
1143d2201f2fSdrahn if (internal_relocs != NULL
1144d2201f2fSdrahn && elf_section_data (sec)->relocs != internal_relocs)
1145d2201f2fSdrahn free (internal_relocs);
1146fddef416Sniklas
1147d2201f2fSdrahn return TRUE;
1148fddef416Sniklas
1149fddef416Sniklas error_return:
1150d2201f2fSdrahn if (isymbuf != NULL
1151d2201f2fSdrahn && symtab_hdr->contents != (unsigned char *) isymbuf)
1152d2201f2fSdrahn free (isymbuf);
1153d2201f2fSdrahn if (contents != NULL
1154d2201f2fSdrahn && elf_section_data (sec)->this_hdr.contents != contents)
1155d2201f2fSdrahn free (contents);
1156d2201f2fSdrahn if (internal_relocs != NULL
1157d2201f2fSdrahn && elf_section_data (sec)->relocs != internal_relocs)
1158d2201f2fSdrahn free (internal_relocs);
1159d2201f2fSdrahn
1160d2201f2fSdrahn return FALSE;
1161fddef416Sniklas }
1162fddef416Sniklas
1163fddef416Sniklas /* Delete some bytes from a section while relaxing. */
1164fddef416Sniklas
1165d2201f2fSdrahn static bfd_boolean
mn10200_elf_relax_delete_bytes(abfd,sec,addr,count)1166fddef416Sniklas mn10200_elf_relax_delete_bytes (abfd, sec, addr, count)
1167fddef416Sniklas bfd *abfd;
1168fddef416Sniklas asection *sec;
1169fddef416Sniklas bfd_vma addr;
1170fddef416Sniklas int count;
1171fddef416Sniklas {
1172fddef416Sniklas Elf_Internal_Shdr *symtab_hdr;
1173d2201f2fSdrahn unsigned int sec_shndx;
1174fddef416Sniklas bfd_byte *contents;
1175fddef416Sniklas Elf_Internal_Rela *irel, *irelend;
1176fddef416Sniklas Elf_Internal_Rela *irelalign;
1177fddef416Sniklas bfd_vma toaddr;
1178d2201f2fSdrahn Elf_Internal_Sym *isym;
1179d2201f2fSdrahn Elf_Internal_Sym *isymend;
1180d2201f2fSdrahn struct elf_link_hash_entry **sym_hashes;
1181d2201f2fSdrahn struct elf_link_hash_entry **end_hashes;
1182d2201f2fSdrahn unsigned int symcount;
1183fddef416Sniklas
1184d2201f2fSdrahn sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1185fddef416Sniklas
1186fddef416Sniklas contents = elf_section_data (sec)->this_hdr.contents;
1187fddef416Sniklas
1188fddef416Sniklas /* The deletion must stop at the next ALIGN reloc for an aligment
1189fddef416Sniklas power larger than the number of bytes we are deleting. */
1190fddef416Sniklas
1191fddef416Sniklas irelalign = NULL;
1192fddef416Sniklas toaddr = sec->_cooked_size;
1193fddef416Sniklas
1194fddef416Sniklas irel = elf_section_data (sec)->relocs;
1195fddef416Sniklas irelend = irel + sec->reloc_count;
1196fddef416Sniklas
1197fddef416Sniklas /* Actually delete the bytes. */
1198d2201f2fSdrahn memmove (contents + addr, contents + addr + count,
1199d2201f2fSdrahn (size_t) (toaddr - addr - count));
1200fddef416Sniklas sec->_cooked_size -= count;
1201fddef416Sniklas
1202fddef416Sniklas /* Adjust all the relocs. */
1203fddef416Sniklas for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1204fddef416Sniklas {
1205fddef416Sniklas /* Get the new reloc address. */
1206fddef416Sniklas if ((irel->r_offset > addr
1207fddef416Sniklas && irel->r_offset < toaddr))
1208fddef416Sniklas irel->r_offset -= count;
1209fddef416Sniklas }
1210fddef416Sniklas
1211f7cc78ecSespie /* Adjust the local symbols defined in this section. */
1212d2201f2fSdrahn symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1213d2201f2fSdrahn isym = (Elf_Internal_Sym *) symtab_hdr->contents;
1214d2201f2fSdrahn for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
1215fddef416Sniklas {
1216d2201f2fSdrahn if (isym->st_shndx == sec_shndx
1217d2201f2fSdrahn && isym->st_value > addr
1218d2201f2fSdrahn && isym->st_value < toaddr)
1219d2201f2fSdrahn isym->st_value -= count;
1220fddef416Sniklas }
1221fddef416Sniklas
1222f7cc78ecSespie /* Now adjust the global symbols defined in this section. */
1223d2201f2fSdrahn symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1224d2201f2fSdrahn - symtab_hdr->sh_info);
1225d2201f2fSdrahn sym_hashes = elf_sym_hashes (abfd);
1226d2201f2fSdrahn end_hashes = sym_hashes + symcount;
1227d2201f2fSdrahn for (; sym_hashes < end_hashes; sym_hashes++)
1228fddef416Sniklas {
1229d2201f2fSdrahn struct elf_link_hash_entry *sym_hash = *sym_hashes;
1230d2201f2fSdrahn if ((sym_hash->root.type == bfd_link_hash_defined
1231d2201f2fSdrahn || sym_hash->root.type == bfd_link_hash_defweak)
1232d2201f2fSdrahn && sym_hash->root.u.def.section == sec
1233d2201f2fSdrahn && sym_hash->root.u.def.value > addr
1234d2201f2fSdrahn && sym_hash->root.u.def.value < toaddr)
1235fddef416Sniklas {
1236d2201f2fSdrahn sym_hash->root.u.def.value -= count;
1237fddef416Sniklas }
1238fddef416Sniklas }
1239fddef416Sniklas
1240d2201f2fSdrahn return TRUE;
1241fddef416Sniklas }
1242fddef416Sniklas
1243d2201f2fSdrahn /* Return TRUE if a symbol exists at the given address, else return
1244d2201f2fSdrahn FALSE. */
1245d2201f2fSdrahn static bfd_boolean
mn10200_elf_symbol_address_p(abfd,sec,isym,addr)1246d2201f2fSdrahn mn10200_elf_symbol_address_p (abfd, sec, isym, addr)
1247fddef416Sniklas bfd *abfd;
1248fddef416Sniklas asection *sec;
1249d2201f2fSdrahn Elf_Internal_Sym *isym;
1250fddef416Sniklas bfd_vma addr;
1251fddef416Sniklas {
1252fddef416Sniklas Elf_Internal_Shdr *symtab_hdr;
1253d2201f2fSdrahn unsigned int sec_shndx;
1254d2201f2fSdrahn Elf_Internal_Sym *isymend;
1255d2201f2fSdrahn struct elf_link_hash_entry **sym_hashes;
1256d2201f2fSdrahn struct elf_link_hash_entry **end_hashes;
1257d2201f2fSdrahn unsigned int symcount;
1258fddef416Sniklas
1259d2201f2fSdrahn sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1260d2201f2fSdrahn
1261d2201f2fSdrahn /* Examine all the local symbols. */
1262fddef416Sniklas symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1263d2201f2fSdrahn for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
1264fddef416Sniklas {
1265d2201f2fSdrahn if (isym->st_shndx == sec_shndx
1266d2201f2fSdrahn && isym->st_value == addr)
1267d2201f2fSdrahn return TRUE;
1268fddef416Sniklas }
1269fddef416Sniklas
1270d2201f2fSdrahn symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1271d2201f2fSdrahn - symtab_hdr->sh_info);
1272d2201f2fSdrahn sym_hashes = elf_sym_hashes (abfd);
1273d2201f2fSdrahn end_hashes = sym_hashes + symcount;
1274d2201f2fSdrahn for (; sym_hashes < end_hashes; sym_hashes++)
1275fddef416Sniklas {
1276d2201f2fSdrahn struct elf_link_hash_entry *sym_hash = *sym_hashes;
1277d2201f2fSdrahn if ((sym_hash->root.type == bfd_link_hash_defined
1278d2201f2fSdrahn || sym_hash->root.type == bfd_link_hash_defweak)
1279d2201f2fSdrahn && sym_hash->root.u.def.section == sec
1280d2201f2fSdrahn && sym_hash->root.u.def.value == addr)
1281d2201f2fSdrahn return TRUE;
1282fddef416Sniklas }
1283d2201f2fSdrahn
1284d2201f2fSdrahn return FALSE;
1285fddef416Sniklas }
1286fddef416Sniklas
1287fddef416Sniklas /* This is a version of bfd_generic_get_relocated_section_contents
1288fddef416Sniklas which uses mn10200_elf_relocate_section. */
1289fddef416Sniklas
1290fddef416Sniklas static bfd_byte *
mn10200_elf_get_relocated_section_contents(output_bfd,link_info,link_order,data,relocatable,symbols)1291fddef416Sniklas mn10200_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
1292*cf2f2c56Smiod data, relocatable, symbols)
1293fddef416Sniklas bfd *output_bfd;
1294fddef416Sniklas struct bfd_link_info *link_info;
1295fddef416Sniklas struct bfd_link_order *link_order;
1296fddef416Sniklas bfd_byte *data;
1297*cf2f2c56Smiod bfd_boolean relocatable;
1298fddef416Sniklas asymbol **symbols;
1299fddef416Sniklas {
1300fddef416Sniklas Elf_Internal_Shdr *symtab_hdr;
1301fddef416Sniklas asection *input_section = link_order->u.indirect.section;
1302fddef416Sniklas bfd *input_bfd = input_section->owner;
1303fddef416Sniklas asection **sections = NULL;
1304fddef416Sniklas Elf_Internal_Rela *internal_relocs = NULL;
1305d2201f2fSdrahn Elf_Internal_Sym *isymbuf = NULL;
1306fddef416Sniklas
1307fddef416Sniklas /* We only need to handle the case of relaxing, or of having a
1308fddef416Sniklas particular set of section contents, specially. */
1309*cf2f2c56Smiod if (relocatable
1310fddef416Sniklas || elf_section_data (input_section)->this_hdr.contents == NULL)
1311fddef416Sniklas return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
1312fddef416Sniklas link_order, data,
1313*cf2f2c56Smiod relocatable,
1314fddef416Sniklas symbols);
1315fddef416Sniklas
1316fddef416Sniklas symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
1317fddef416Sniklas
1318fddef416Sniklas memcpy (data, elf_section_data (input_section)->this_hdr.contents,
1319d2201f2fSdrahn (size_t) input_section->_raw_size);
1320fddef416Sniklas
1321fddef416Sniklas if ((input_section->flags & SEC_RELOC) != 0
1322fddef416Sniklas && input_section->reloc_count > 0)
1323fddef416Sniklas {
1324d2201f2fSdrahn Elf_Internal_Sym *isym;
1325d2201f2fSdrahn Elf_Internal_Sym *isymend;
1326fddef416Sniklas asection **secpp;
1327d2201f2fSdrahn bfd_size_type amt;
1328fddef416Sniklas
1329*cf2f2c56Smiod internal_relocs = (_bfd_elf_link_read_relocs
1330fddef416Sniklas (input_bfd, input_section, (PTR) NULL,
1331d2201f2fSdrahn (Elf_Internal_Rela *) NULL, FALSE));
1332fddef416Sniklas if (internal_relocs == NULL)
1333fddef416Sniklas goto error_return;
1334fddef416Sniklas
1335d2201f2fSdrahn if (symtab_hdr->sh_info != 0)
1336d2201f2fSdrahn {
1337d2201f2fSdrahn isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1338d2201f2fSdrahn if (isymbuf == NULL)
1339d2201f2fSdrahn isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
1340d2201f2fSdrahn symtab_hdr->sh_info, 0,
1341d2201f2fSdrahn NULL, NULL, NULL);
1342d2201f2fSdrahn if (isymbuf == NULL)
1343d2201f2fSdrahn goto error_return;
1344d2201f2fSdrahn }
1345d2201f2fSdrahn
1346d2201f2fSdrahn amt = symtab_hdr->sh_info;
1347d2201f2fSdrahn amt *= sizeof (asection *);
1348d2201f2fSdrahn sections = (asection **) bfd_malloc (amt);
1349d2201f2fSdrahn if (sections == NULL && amt != 0)
1350fddef416Sniklas goto error_return;
1351fddef416Sniklas
1352d2201f2fSdrahn isymend = isymbuf + symtab_hdr->sh_info;
1353d2201f2fSdrahn for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
1354fddef416Sniklas {
1355fddef416Sniklas asection *isec;
1356fddef416Sniklas
1357d2201f2fSdrahn if (isym->st_shndx == SHN_UNDEF)
1358fddef416Sniklas isec = bfd_und_section_ptr;
1359d2201f2fSdrahn else if (isym->st_shndx == SHN_ABS)
1360fddef416Sniklas isec = bfd_abs_section_ptr;
1361d2201f2fSdrahn else if (isym->st_shndx == SHN_COMMON)
1362fddef416Sniklas isec = bfd_com_section_ptr;
1363fddef416Sniklas else
1364d2201f2fSdrahn isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
1365fddef416Sniklas
1366fddef416Sniklas *secpp = isec;
1367fddef416Sniklas }
1368fddef416Sniklas
1369fddef416Sniklas if (! mn10200_elf_relocate_section (output_bfd, link_info, input_bfd,
1370fddef416Sniklas input_section, data, internal_relocs,
1371d2201f2fSdrahn isymbuf, sections))
1372fddef416Sniklas goto error_return;
1373fddef416Sniklas
1374fddef416Sniklas if (sections != NULL)
1375fddef416Sniklas free (sections);
1376d2201f2fSdrahn if (isymbuf != NULL
1377d2201f2fSdrahn && symtab_hdr->contents != (unsigned char *) isymbuf)
1378d2201f2fSdrahn free (isymbuf);
1379d2201f2fSdrahn if (elf_section_data (input_section)->relocs != internal_relocs)
1380fddef416Sniklas free (internal_relocs);
1381fddef416Sniklas }
1382fddef416Sniklas
1383fddef416Sniklas return data;
1384fddef416Sniklas
1385fddef416Sniklas error_return:
1386fddef416Sniklas if (sections != NULL)
1387fddef416Sniklas free (sections);
1388d2201f2fSdrahn if (isymbuf != NULL
1389d2201f2fSdrahn && symtab_hdr->contents != (unsigned char *) isymbuf)
1390d2201f2fSdrahn free (isymbuf);
1391d2201f2fSdrahn if (internal_relocs != NULL
1392d2201f2fSdrahn && elf_section_data (input_section)->relocs != internal_relocs)
1393d2201f2fSdrahn free (internal_relocs);
1394fddef416Sniklas return NULL;
1395fddef416Sniklas }
1396fddef416Sniklas
1397fddef416Sniklas #define TARGET_LITTLE_SYM bfd_elf32_mn10200_vec
1398fddef416Sniklas #define TARGET_LITTLE_NAME "elf32-mn10200"
1399fddef416Sniklas #define ELF_ARCH bfd_arch_mn10200
1400d2201f2fSdrahn #define ELF_MACHINE_CODE EM_MN10200
1401d2201f2fSdrahn #define ELF_MACHINE_ALT1 EM_CYGNUS_MN10200
1402fddef416Sniklas #define ELF_MAXPAGESIZE 0x1000
1403fddef416Sniklas
1404d2201f2fSdrahn #define elf_backend_rela_normal 1
1405fddef416Sniklas #define elf_info_to_howto mn10200_info_to_howto
1406fddef416Sniklas #define elf_info_to_howto_rel 0
1407fddef416Sniklas #define elf_backend_relocate_section mn10200_elf_relocate_section
1408fddef416Sniklas #define bfd_elf32_bfd_relax_section mn10200_elf_relax_section
1409fddef416Sniklas #define bfd_elf32_bfd_get_relocated_section_contents \
1410fddef416Sniklas mn10200_elf_get_relocated_section_contents
1411fddef416Sniklas
1412fddef416Sniklas #define elf_symbol_leading_char '_'
1413fddef416Sniklas
1414fddef416Sniklas #include "elf32-target.h"
1415