1*3d8817e4Smiod /* M16C/M32C specific support for 32-bit ELF.
2*3d8817e4Smiod Copyright (C) 2005, 2006
3*3d8817e4Smiod Free Software Foundation, Inc.
4*3d8817e4Smiod
5*3d8817e4Smiod This file is part of BFD, the Binary File Descriptor library.
6*3d8817e4Smiod
7*3d8817e4Smiod This program is free software; you can redistribute it and/or modify
8*3d8817e4Smiod it under the terms of the GNU General Public License as published by
9*3d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
10*3d8817e4Smiod (at your option) any later version.
11*3d8817e4Smiod
12*3d8817e4Smiod This program is distributed in the hope that it will be useful,
13*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
14*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*3d8817e4Smiod GNU General Public License for more details.
16*3d8817e4Smiod
17*3d8817e4Smiod You should have received a copy of the GNU General Public License
18*3d8817e4Smiod along with this program; if not, write to the Free Software
19*3d8817e4Smiod Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20*3d8817e4Smiod
21*3d8817e4Smiod #include "bfd.h"
22*3d8817e4Smiod #include "sysdep.h"
23*3d8817e4Smiod #include "libbfd.h"
24*3d8817e4Smiod #include "elf-bfd.h"
25*3d8817e4Smiod #include "elf/m32c.h"
26*3d8817e4Smiod #include "libiberty.h"
27*3d8817e4Smiod
28*3d8817e4Smiod /* Forward declarations. */
29*3d8817e4Smiod static reloc_howto_type * m32c_reloc_type_lookup
30*3d8817e4Smiod (bfd *, bfd_reloc_code_real_type);
31*3d8817e4Smiod static void m32c_info_to_howto_rela
32*3d8817e4Smiod (bfd *, arelent *, Elf_Internal_Rela *);
33*3d8817e4Smiod static bfd_boolean m32c_elf_relocate_section
34*3d8817e4Smiod (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
35*3d8817e4Smiod static bfd_boolean m32c_elf_gc_sweep_hook
36*3d8817e4Smiod (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
37*3d8817e4Smiod static asection * m32c_elf_gc_mark_hook
38*3d8817e4Smiod (asection *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *);
39*3d8817e4Smiod static bfd_boolean m32c_elf_check_relocs
40*3d8817e4Smiod (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
41*3d8817e4Smiod static bfd_boolean m32c_elf_relax_delete_bytes (bfd *, asection *, bfd_vma, int);
42*3d8817e4Smiod #ifdef DEBUG
43*3d8817e4Smiod static char * m32c_get_reloc (long reloc);
44*3d8817e4Smiod #endif
45*3d8817e4Smiod static bfd_boolean m32c_elf_relax_section
46*3d8817e4Smiod (bfd *abfd, asection *sec, struct bfd_link_info *link_info, bfd_boolean *again);
47*3d8817e4Smiod
48*3d8817e4Smiod
49*3d8817e4Smiod static reloc_howto_type m32c_elf_howto_table [] =
50*3d8817e4Smiod {
51*3d8817e4Smiod /* This reloc does nothing. */
52*3d8817e4Smiod HOWTO (R_M32C_NONE, /* type */
53*3d8817e4Smiod 0, /* rightshift */
54*3d8817e4Smiod 0, /* size (0 = byte, 1 = short, 2 = long) */
55*3d8817e4Smiod 32, /* bitsize */
56*3d8817e4Smiod FALSE, /* pc_relative */
57*3d8817e4Smiod 0, /* bitpos */
58*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
59*3d8817e4Smiod bfd_elf_generic_reloc, /* special_function */
60*3d8817e4Smiod "R_M32C_NONE", /* name */
61*3d8817e4Smiod FALSE, /* partial_inplace */
62*3d8817e4Smiod 0, /* src_mask */
63*3d8817e4Smiod 0, /* dst_mask */
64*3d8817e4Smiod FALSE), /* pcrel_offset */
65*3d8817e4Smiod
66*3d8817e4Smiod HOWTO (R_M32C_16, /* type */
67*3d8817e4Smiod 0, /* rightshift */
68*3d8817e4Smiod 1, /* size (0 = byte, 1 = short, 2 = long) */
69*3d8817e4Smiod 16, /* bitsize */
70*3d8817e4Smiod FALSE, /* pc_relative */
71*3d8817e4Smiod 0, /* bitpos */
72*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
73*3d8817e4Smiod bfd_elf_generic_reloc, /* special_function */
74*3d8817e4Smiod "R_M32C_16", /* name */
75*3d8817e4Smiod FALSE, /* partial_inplace */
76*3d8817e4Smiod 0, /* src_mask */
77*3d8817e4Smiod 0xffff, /* dst_mask */
78*3d8817e4Smiod FALSE), /* pcrel_offset */
79*3d8817e4Smiod
80*3d8817e4Smiod HOWTO (R_M32C_24, /* type */
81*3d8817e4Smiod 0, /* rightshift */
82*3d8817e4Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
83*3d8817e4Smiod 24, /* bitsize */
84*3d8817e4Smiod FALSE, /* pc_relative */
85*3d8817e4Smiod 0, /* bitpos */
86*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
87*3d8817e4Smiod bfd_elf_generic_reloc, /* special_function */
88*3d8817e4Smiod "R_M32C_24", /* name */
89*3d8817e4Smiod FALSE, /* partial_inplace */
90*3d8817e4Smiod 0, /* src_mask */
91*3d8817e4Smiod 0xffffff, /* dst_mask */
92*3d8817e4Smiod FALSE), /* pcrel_offset */
93*3d8817e4Smiod
94*3d8817e4Smiod HOWTO (R_M32C_32, /* type */
95*3d8817e4Smiod 0, /* rightshift */
96*3d8817e4Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
97*3d8817e4Smiod 32, /* bitsize */
98*3d8817e4Smiod FALSE, /* pc_relative */
99*3d8817e4Smiod 0, /* bitpos */
100*3d8817e4Smiod complain_overflow_bitfield, /* complain_on_overflow */
101*3d8817e4Smiod bfd_elf_generic_reloc, /* special_function */
102*3d8817e4Smiod "R_M32C_32", /* name */
103*3d8817e4Smiod FALSE, /* partial_inplace */
104*3d8817e4Smiod 0, /* src_mask */
105*3d8817e4Smiod 0xffffffff, /* dst_mask */
106*3d8817e4Smiod FALSE), /* pcrel_offset */
107*3d8817e4Smiod
108*3d8817e4Smiod HOWTO (R_M32C_8_PCREL, /* type */
109*3d8817e4Smiod 0, /* rightshift */
110*3d8817e4Smiod 0, /* size (0 = byte, 1 = short, 2 = long) */
111*3d8817e4Smiod 8, /* bitsize */
112*3d8817e4Smiod TRUE, /* pc_relative */
113*3d8817e4Smiod 0, /* bitpos */
114*3d8817e4Smiod complain_overflow_signed, /* complain_on_overflow */
115*3d8817e4Smiod bfd_elf_generic_reloc, /* special_function */
116*3d8817e4Smiod "R_M32C_8_PCREL", /* name */
117*3d8817e4Smiod FALSE, /* partial_inplace */
118*3d8817e4Smiod 0, /* src_mask */
119*3d8817e4Smiod 0xff, /* dst_mask */
120*3d8817e4Smiod TRUE), /* pcrel_offset */
121*3d8817e4Smiod
122*3d8817e4Smiod HOWTO (R_M32C_16_PCREL, /* type */
123*3d8817e4Smiod 0, /* rightshift */
124*3d8817e4Smiod 1, /* size (0 = byte, 1 = short, 2 = long) */
125*3d8817e4Smiod 16, /* bitsize */
126*3d8817e4Smiod TRUE, /* pc_relative */
127*3d8817e4Smiod 0, /* bitpos */
128*3d8817e4Smiod complain_overflow_signed, /* complain_on_overflow */
129*3d8817e4Smiod bfd_elf_generic_reloc, /* special_function */
130*3d8817e4Smiod "R_M32C_16_PCREL", /* name */
131*3d8817e4Smiod FALSE, /* partial_inplace */
132*3d8817e4Smiod 0, /* src_mask */
133*3d8817e4Smiod 0xffff, /* dst_mask */
134*3d8817e4Smiod TRUE), /* pcrel_offset */
135*3d8817e4Smiod
136*3d8817e4Smiod HOWTO (R_M32C_8, /* type */
137*3d8817e4Smiod 0, /* rightshift */
138*3d8817e4Smiod 0, /* size (0 = byte, 1 = short, 2 = long) */
139*3d8817e4Smiod 8, /* bitsize */
140*3d8817e4Smiod FALSE, /* pc_relative */
141*3d8817e4Smiod 0, /* bitpos */
142*3d8817e4Smiod complain_overflow_unsigned, /* complain_on_overflow */
143*3d8817e4Smiod bfd_elf_generic_reloc, /* special_function */
144*3d8817e4Smiod "R_M32C_8", /* name */
145*3d8817e4Smiod FALSE, /* partial_inplace */
146*3d8817e4Smiod 0, /* src_mask */
147*3d8817e4Smiod 0xff, /* dst_mask */
148*3d8817e4Smiod FALSE), /* pcrel_offset */
149*3d8817e4Smiod
150*3d8817e4Smiod HOWTO (R_M32C_LO16, /* type */
151*3d8817e4Smiod 0, /* rightshift */
152*3d8817e4Smiod 1, /* size (0 = byte, 1 = short, 2 = long) */
153*3d8817e4Smiod 16, /* bitsize */
154*3d8817e4Smiod FALSE, /* pc_relative */
155*3d8817e4Smiod 0, /* bitpos */
156*3d8817e4Smiod complain_overflow_dont, /* complain_on_overflow */
157*3d8817e4Smiod bfd_elf_generic_reloc, /* special_function */
158*3d8817e4Smiod "R_M32C_LO16", /* name */
159*3d8817e4Smiod FALSE, /* partial_inplace */
160*3d8817e4Smiod 0, /* src_mask */
161*3d8817e4Smiod 0xffff, /* dst_mask */
162*3d8817e4Smiod FALSE), /* pcrel_offset */
163*3d8817e4Smiod
164*3d8817e4Smiod HOWTO (R_M32C_HI8, /* type */
165*3d8817e4Smiod 0, /* rightshift */
166*3d8817e4Smiod 0, /* size (0 = byte, 1 = short, 2 = long) */
167*3d8817e4Smiod 8, /* bitsize */
168*3d8817e4Smiod FALSE, /* pc_relative */
169*3d8817e4Smiod 0, /* bitpos */
170*3d8817e4Smiod complain_overflow_dont, /* complain_on_overflow */
171*3d8817e4Smiod bfd_elf_generic_reloc, /* special_function */
172*3d8817e4Smiod "R_M32C_HI8", /* name */
173*3d8817e4Smiod FALSE, /* partial_inplace */
174*3d8817e4Smiod 0, /* src_mask */
175*3d8817e4Smiod 0xff, /* dst_mask */
176*3d8817e4Smiod FALSE), /* pcrel_offset */
177*3d8817e4Smiod
178*3d8817e4Smiod HOWTO (R_M32C_HI16, /* type */
179*3d8817e4Smiod 0, /* rightshift */
180*3d8817e4Smiod 1, /* size (0 = byte, 1 = short, 2 = long) */
181*3d8817e4Smiod 16, /* bitsize */
182*3d8817e4Smiod FALSE, /* pc_relative */
183*3d8817e4Smiod 0, /* bitpos */
184*3d8817e4Smiod complain_overflow_dont, /* complain_on_overflow */
185*3d8817e4Smiod bfd_elf_generic_reloc, /* special_function */
186*3d8817e4Smiod "R_M32C_HI16", /* name */
187*3d8817e4Smiod FALSE, /* partial_inplace */
188*3d8817e4Smiod 0, /* src_mask */
189*3d8817e4Smiod 0xffff, /* dst_mask */
190*3d8817e4Smiod FALSE), /* pcrel_offset */
191*3d8817e4Smiod
192*3d8817e4Smiod HOWTO (R_M32C_RL_JUMP, /* type */
193*3d8817e4Smiod 0, /* rightshift */
194*3d8817e4Smiod 0, /* size (0 = byte, 1 = short, 2 = long) */
195*3d8817e4Smiod 0, /* bitsize */
196*3d8817e4Smiod FALSE, /* pc_relative */
197*3d8817e4Smiod 0, /* bitpos */
198*3d8817e4Smiod complain_overflow_signed, /* complain_on_overflow */
199*3d8817e4Smiod bfd_elf_generic_reloc, /* special_function */
200*3d8817e4Smiod "R_M32C_RL_JUMP", /* name */
201*3d8817e4Smiod FALSE, /* partial_inplace */
202*3d8817e4Smiod 0, /* src_mask */
203*3d8817e4Smiod 0, /* dst_mask */
204*3d8817e4Smiod FALSE), /* pcrel_offset */
205*3d8817e4Smiod
206*3d8817e4Smiod HOWTO (R_M32C_RL_1ADDR, /* type */
207*3d8817e4Smiod 0, /* rightshift */
208*3d8817e4Smiod 0, /* size (0 = byte, 1 = short, 2 = long) */
209*3d8817e4Smiod 0, /* bitsize */
210*3d8817e4Smiod FALSE, /* pc_relative */
211*3d8817e4Smiod 0, /* bitpos */
212*3d8817e4Smiod complain_overflow_signed, /* complain_on_overflow */
213*3d8817e4Smiod bfd_elf_generic_reloc, /* special_function */
214*3d8817e4Smiod "R_M32C_RL_1ADDR", /* name */
215*3d8817e4Smiod FALSE, /* partial_inplace */
216*3d8817e4Smiod 0, /* src_mask */
217*3d8817e4Smiod 0, /* dst_mask */
218*3d8817e4Smiod FALSE), /* pcrel_offset */
219*3d8817e4Smiod
220*3d8817e4Smiod HOWTO (R_M32C_RL_2ADDR, /* type */
221*3d8817e4Smiod 0, /* rightshift */
222*3d8817e4Smiod 0, /* size (0 = byte, 1 = short, 2 = long) */
223*3d8817e4Smiod 0, /* bitsize */
224*3d8817e4Smiod FALSE, /* pc_relative */
225*3d8817e4Smiod 0, /* bitpos */
226*3d8817e4Smiod complain_overflow_signed, /* complain_on_overflow */
227*3d8817e4Smiod bfd_elf_generic_reloc, /* special_function */
228*3d8817e4Smiod "R_M32C_RL_2ADDR", /* name */
229*3d8817e4Smiod FALSE, /* partial_inplace */
230*3d8817e4Smiod 0, /* src_mask */
231*3d8817e4Smiod 0, /* dst_mask */
232*3d8817e4Smiod FALSE), /* pcrel_offset */
233*3d8817e4Smiod
234*3d8817e4Smiod };
235*3d8817e4Smiod
236*3d8817e4Smiod /* Map BFD reloc types to M32C ELF reloc types. */
237*3d8817e4Smiod
238*3d8817e4Smiod struct m32c_reloc_map
239*3d8817e4Smiod {
240*3d8817e4Smiod bfd_reloc_code_real_type bfd_reloc_val;
241*3d8817e4Smiod unsigned int m32c_reloc_val;
242*3d8817e4Smiod };
243*3d8817e4Smiod
244*3d8817e4Smiod static const struct m32c_reloc_map m32c_reloc_map [] =
245*3d8817e4Smiod {
246*3d8817e4Smiod { BFD_RELOC_NONE, R_M32C_NONE },
247*3d8817e4Smiod { BFD_RELOC_16, R_M32C_16 },
248*3d8817e4Smiod { BFD_RELOC_24, R_M32C_24 },
249*3d8817e4Smiod { BFD_RELOC_32, R_M32C_32 },
250*3d8817e4Smiod { BFD_RELOC_8_PCREL, R_M32C_8_PCREL },
251*3d8817e4Smiod { BFD_RELOC_16_PCREL, R_M32C_16_PCREL },
252*3d8817e4Smiod { BFD_RELOC_8, R_M32C_8 },
253*3d8817e4Smiod { BFD_RELOC_LO16, R_M32C_LO16 },
254*3d8817e4Smiod { BFD_RELOC_HI16, R_M32C_HI16 },
255*3d8817e4Smiod { BFD_RELOC_M32C_HI8, R_M32C_HI8 },
256*3d8817e4Smiod { BFD_RELOC_M32C_RL_JUMP, R_M32C_RL_JUMP },
257*3d8817e4Smiod { BFD_RELOC_M32C_RL_1ADDR, R_M32C_RL_1ADDR },
258*3d8817e4Smiod { BFD_RELOC_M32C_RL_2ADDR, R_M32C_RL_2ADDR }
259*3d8817e4Smiod };
260*3d8817e4Smiod
261*3d8817e4Smiod static reloc_howto_type *
m32c_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)262*3d8817e4Smiod m32c_reloc_type_lookup
263*3d8817e4Smiod (bfd * abfd ATTRIBUTE_UNUSED,
264*3d8817e4Smiod bfd_reloc_code_real_type code)
265*3d8817e4Smiod {
266*3d8817e4Smiod unsigned int i;
267*3d8817e4Smiod
268*3d8817e4Smiod for (i = ARRAY_SIZE (m32c_reloc_map); --i;)
269*3d8817e4Smiod if (m32c_reloc_map [i].bfd_reloc_val == code)
270*3d8817e4Smiod return & m32c_elf_howto_table [m32c_reloc_map[i].m32c_reloc_val];
271*3d8817e4Smiod
272*3d8817e4Smiod return NULL;
273*3d8817e4Smiod }
274*3d8817e4Smiod
275*3d8817e4Smiod /* Set the howto pointer for an M32C ELF reloc. */
276*3d8817e4Smiod
277*3d8817e4Smiod static void
m32c_info_to_howto_rela(bfd * abfd ATTRIBUTE_UNUSED,arelent * cache_ptr,Elf_Internal_Rela * dst)278*3d8817e4Smiod m32c_info_to_howto_rela
279*3d8817e4Smiod (bfd * abfd ATTRIBUTE_UNUSED,
280*3d8817e4Smiod arelent * cache_ptr,
281*3d8817e4Smiod Elf_Internal_Rela * dst)
282*3d8817e4Smiod {
283*3d8817e4Smiod unsigned int r_type;
284*3d8817e4Smiod
285*3d8817e4Smiod r_type = ELF32_R_TYPE (dst->r_info);
286*3d8817e4Smiod BFD_ASSERT (r_type < (unsigned int) R_M32C_max);
287*3d8817e4Smiod cache_ptr->howto = & m32c_elf_howto_table [r_type];
288*3d8817e4Smiod }
289*3d8817e4Smiod
290*3d8817e4Smiod
291*3d8817e4Smiod
292*3d8817e4Smiod /* Relocate an M32C ELF section.
293*3d8817e4Smiod There is some attempt to make this function usable for many architectures,
294*3d8817e4Smiod both USE_REL and USE_RELA ['twould be nice if such a critter existed],
295*3d8817e4Smiod if only to serve as a learning tool.
296*3d8817e4Smiod
297*3d8817e4Smiod The RELOCATE_SECTION function is called by the new ELF backend linker
298*3d8817e4Smiod to handle the relocations for a section.
299*3d8817e4Smiod
300*3d8817e4Smiod The relocs are always passed as Rela structures; if the section
301*3d8817e4Smiod actually uses Rel structures, the r_addend field will always be
302*3d8817e4Smiod zero.
303*3d8817e4Smiod
304*3d8817e4Smiod This function is responsible for adjusting the section contents as
305*3d8817e4Smiod necessary, and (if using Rela relocs and generating a relocatable
306*3d8817e4Smiod output file) adjusting the reloc addend as necessary.
307*3d8817e4Smiod
308*3d8817e4Smiod This function does not have to worry about setting the reloc
309*3d8817e4Smiod address or the reloc symbol index.
310*3d8817e4Smiod
311*3d8817e4Smiod LOCAL_SYMS is a pointer to the swapped in local symbols.
312*3d8817e4Smiod
313*3d8817e4Smiod LOCAL_SECTIONS is an array giving the section in the input file
314*3d8817e4Smiod corresponding to the st_shndx field of each local symbol.
315*3d8817e4Smiod
316*3d8817e4Smiod The global hash table entry for the global symbols can be found
317*3d8817e4Smiod via elf_sym_hashes (input_bfd).
318*3d8817e4Smiod
319*3d8817e4Smiod When generating relocatable output, this function must handle
320*3d8817e4Smiod STB_LOCAL/STT_SECTION symbols specially. The output symbol is
321*3d8817e4Smiod going to be the section symbol corresponding to the output
322*3d8817e4Smiod section, which means that the addend must be adjusted
323*3d8817e4Smiod accordingly. */
324*3d8817e4Smiod
325*3d8817e4Smiod static bfd_boolean
m32c_elf_relocate_section(bfd * output_bfd ATTRIBUTE_UNUSED,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)326*3d8817e4Smiod m32c_elf_relocate_section
327*3d8817e4Smiod (bfd * output_bfd ATTRIBUTE_UNUSED,
328*3d8817e4Smiod struct bfd_link_info * info,
329*3d8817e4Smiod bfd * input_bfd,
330*3d8817e4Smiod asection * input_section,
331*3d8817e4Smiod bfd_byte * contents,
332*3d8817e4Smiod Elf_Internal_Rela * relocs,
333*3d8817e4Smiod Elf_Internal_Sym * local_syms,
334*3d8817e4Smiod asection ** local_sections)
335*3d8817e4Smiod {
336*3d8817e4Smiod Elf_Internal_Shdr * symtab_hdr;
337*3d8817e4Smiod struct elf_link_hash_entry ** sym_hashes;
338*3d8817e4Smiod Elf_Internal_Rela * rel;
339*3d8817e4Smiod Elf_Internal_Rela * relend;
340*3d8817e4Smiod bfd *dynobj;
341*3d8817e4Smiod asection *splt;
342*3d8817e4Smiod
343*3d8817e4Smiod symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
344*3d8817e4Smiod sym_hashes = elf_sym_hashes (input_bfd);
345*3d8817e4Smiod relend = relocs + input_section->reloc_count;
346*3d8817e4Smiod
347*3d8817e4Smiod dynobj = elf_hash_table (info)->dynobj;
348*3d8817e4Smiod splt = NULL;
349*3d8817e4Smiod if (dynobj != NULL)
350*3d8817e4Smiod splt = bfd_get_section_by_name (dynobj, ".plt");
351*3d8817e4Smiod
352*3d8817e4Smiod for (rel = relocs; rel < relend; rel ++)
353*3d8817e4Smiod {
354*3d8817e4Smiod reloc_howto_type * howto;
355*3d8817e4Smiod unsigned long r_symndx;
356*3d8817e4Smiod Elf_Internal_Sym * sym;
357*3d8817e4Smiod asection * sec;
358*3d8817e4Smiod struct elf_link_hash_entry * h;
359*3d8817e4Smiod bfd_vma relocation;
360*3d8817e4Smiod bfd_reloc_status_type r;
361*3d8817e4Smiod const char * name = NULL;
362*3d8817e4Smiod int r_type;
363*3d8817e4Smiod
364*3d8817e4Smiod r_type = ELF32_R_TYPE (rel->r_info);
365*3d8817e4Smiod
366*3d8817e4Smiod /* These are only used for relaxing; we don't actually relocate
367*3d8817e4Smiod anything with them, so skip them. */
368*3d8817e4Smiod if (r_type == R_M32C_RL_JUMP
369*3d8817e4Smiod || r_type == R_M32C_RL_1ADDR
370*3d8817e4Smiod || r_type == R_M32C_RL_2ADDR)
371*3d8817e4Smiod continue;
372*3d8817e4Smiod
373*3d8817e4Smiod r_symndx = ELF32_R_SYM (rel->r_info);
374*3d8817e4Smiod
375*3d8817e4Smiod if (info->relocatable)
376*3d8817e4Smiod {
377*3d8817e4Smiod /* This is a relocatable link. We don't have to change
378*3d8817e4Smiod anything, unless the reloc is against a section symbol,
379*3d8817e4Smiod in which case we have to adjust according to where the
380*3d8817e4Smiod section symbol winds up in the output section. */
381*3d8817e4Smiod if (r_symndx < symtab_hdr->sh_info)
382*3d8817e4Smiod {
383*3d8817e4Smiod sym = local_syms + r_symndx;
384*3d8817e4Smiod
385*3d8817e4Smiod if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
386*3d8817e4Smiod {
387*3d8817e4Smiod sec = local_sections [r_symndx];
388*3d8817e4Smiod rel->r_addend += sec->output_offset + sym->st_value;
389*3d8817e4Smiod }
390*3d8817e4Smiod }
391*3d8817e4Smiod
392*3d8817e4Smiod continue;
393*3d8817e4Smiod }
394*3d8817e4Smiod
395*3d8817e4Smiod /* This is a final link. */
396*3d8817e4Smiod howto = m32c_elf_howto_table + ELF32_R_TYPE (rel->r_info);
397*3d8817e4Smiod h = NULL;
398*3d8817e4Smiod sym = NULL;
399*3d8817e4Smiod sec = NULL;
400*3d8817e4Smiod
401*3d8817e4Smiod if (r_symndx < symtab_hdr->sh_info)
402*3d8817e4Smiod {
403*3d8817e4Smiod sym = local_syms + r_symndx;
404*3d8817e4Smiod sec = local_sections [r_symndx];
405*3d8817e4Smiod relocation = (sec->output_section->vma
406*3d8817e4Smiod + sec->output_offset
407*3d8817e4Smiod + sym->st_value);
408*3d8817e4Smiod
409*3d8817e4Smiod name = bfd_elf_string_from_elf_section
410*3d8817e4Smiod (input_bfd, symtab_hdr->sh_link, sym->st_name);
411*3d8817e4Smiod name = (sym->st_name == 0) ? bfd_section_name (input_bfd, sec) : name;
412*3d8817e4Smiod }
413*3d8817e4Smiod else
414*3d8817e4Smiod {
415*3d8817e4Smiod h = sym_hashes [r_symndx - symtab_hdr->sh_info];
416*3d8817e4Smiod
417*3d8817e4Smiod while (h->root.type == bfd_link_hash_indirect
418*3d8817e4Smiod || h->root.type == bfd_link_hash_warning)
419*3d8817e4Smiod h = (struct elf_link_hash_entry *) h->root.u.i.link;
420*3d8817e4Smiod
421*3d8817e4Smiod name = h->root.root.string;
422*3d8817e4Smiod
423*3d8817e4Smiod if (h->root.type == bfd_link_hash_defined
424*3d8817e4Smiod || h->root.type == bfd_link_hash_defweak)
425*3d8817e4Smiod {
426*3d8817e4Smiod sec = h->root.u.def.section;
427*3d8817e4Smiod relocation = (h->root.u.def.value
428*3d8817e4Smiod + sec->output_section->vma
429*3d8817e4Smiod + sec->output_offset);
430*3d8817e4Smiod }
431*3d8817e4Smiod else if (h->root.type == bfd_link_hash_undefweak)
432*3d8817e4Smiod {
433*3d8817e4Smiod relocation = 0;
434*3d8817e4Smiod }
435*3d8817e4Smiod else
436*3d8817e4Smiod {
437*3d8817e4Smiod if (! ((*info->callbacks->undefined_symbol)
438*3d8817e4Smiod (info, h->root.root.string, input_bfd,
439*3d8817e4Smiod input_section, rel->r_offset, TRUE)))
440*3d8817e4Smiod return FALSE;
441*3d8817e4Smiod relocation = 0;
442*3d8817e4Smiod }
443*3d8817e4Smiod }
444*3d8817e4Smiod
445*3d8817e4Smiod switch (ELF32_R_TYPE (rel->r_info))
446*3d8817e4Smiod {
447*3d8817e4Smiod case R_M32C_16:
448*3d8817e4Smiod {
449*3d8817e4Smiod bfd_vma *plt_offset;
450*3d8817e4Smiod
451*3d8817e4Smiod if (h != NULL)
452*3d8817e4Smiod plt_offset = &h->plt.offset;
453*3d8817e4Smiod else
454*3d8817e4Smiod plt_offset = elf_local_got_offsets (input_bfd) + r_symndx;
455*3d8817e4Smiod
456*3d8817e4Smiod /* printf("%s: rel %x plt %d\n", h ? h->root.root.string : "(none)",
457*3d8817e4Smiod relocation, *plt_offset);*/
458*3d8817e4Smiod if (relocation <= 0xffff)
459*3d8817e4Smiod {
460*3d8817e4Smiod /* If the symbol is in range for a 16-bit address, we should
461*3d8817e4Smiod have deallocated the plt entry in relax_section. */
462*3d8817e4Smiod BFD_ASSERT (*plt_offset == (bfd_vma) -1);
463*3d8817e4Smiod }
464*3d8817e4Smiod else
465*3d8817e4Smiod {
466*3d8817e4Smiod /* If the symbol is out of range for a 16-bit address,
467*3d8817e4Smiod we must have allocated a plt entry. */
468*3d8817e4Smiod BFD_ASSERT (*plt_offset != (bfd_vma) -1);
469*3d8817e4Smiod
470*3d8817e4Smiod /* If this is the first time we've processed this symbol,
471*3d8817e4Smiod fill in the plt entry with the correct symbol address. */
472*3d8817e4Smiod if ((*plt_offset & 1) == 0)
473*3d8817e4Smiod {
474*3d8817e4Smiod unsigned int x;
475*3d8817e4Smiod
476*3d8817e4Smiod x = 0x000000fc; /* jmpf */
477*3d8817e4Smiod x |= (relocation << 8) & 0xffffff00;
478*3d8817e4Smiod bfd_put_32 (input_bfd, x, splt->contents + *plt_offset);
479*3d8817e4Smiod *plt_offset |= 1;
480*3d8817e4Smiod }
481*3d8817e4Smiod
482*3d8817e4Smiod relocation = (splt->output_section->vma
483*3d8817e4Smiod + splt->output_offset
484*3d8817e4Smiod + (*plt_offset & -2));
485*3d8817e4Smiod if (name)
486*3d8817e4Smiod {
487*3d8817e4Smiod char *newname = bfd_malloc (strlen(name)+5);
488*3d8817e4Smiod strcpy (newname, name);
489*3d8817e4Smiod strcat(newname, ".plt");
490*3d8817e4Smiod _bfd_generic_link_add_one_symbol (info,
491*3d8817e4Smiod input_bfd,
492*3d8817e4Smiod newname,
493*3d8817e4Smiod BSF_FUNCTION | BSF_WEAK,
494*3d8817e4Smiod splt,
495*3d8817e4Smiod (*plt_offset & -2),
496*3d8817e4Smiod 0,
497*3d8817e4Smiod 1,
498*3d8817e4Smiod 0,
499*3d8817e4Smiod 0);
500*3d8817e4Smiod }
501*3d8817e4Smiod }
502*3d8817e4Smiod }
503*3d8817e4Smiod break;
504*3d8817e4Smiod
505*3d8817e4Smiod case R_M32C_HI8:
506*3d8817e4Smiod case R_M32C_HI16:
507*3d8817e4Smiod relocation >>= 16;
508*3d8817e4Smiod break;
509*3d8817e4Smiod }
510*3d8817e4Smiod
511*3d8817e4Smiod #if 0
512*3d8817e4Smiod printf ("relocate %s at %06lx relocation %06lx addend %ld ",
513*3d8817e4Smiod m32c_elf_howto_table[ELF32_R_TYPE(rel->r_info)].name,
514*3d8817e4Smiod rel->r_offset + input_section->output_section->vma + input_section->output_offset,
515*3d8817e4Smiod relocation, rel->r_addend);
516*3d8817e4Smiod {
517*3d8817e4Smiod int i;
518*3d8817e4Smiod for (i=0; i<4; i++)
519*3d8817e4Smiod printf (" %02x", contents[rel->r_offset+i]);
520*3d8817e4Smiod printf ("\n");
521*3d8817e4Smiod }
522*3d8817e4Smiod #endif
523*3d8817e4Smiod r = _bfd_final_link_relocate (howto, input_bfd, input_section,
524*3d8817e4Smiod contents, rel->r_offset, relocation,
525*3d8817e4Smiod rel->r_addend);
526*3d8817e4Smiod
527*3d8817e4Smiod if (r != bfd_reloc_ok)
528*3d8817e4Smiod {
529*3d8817e4Smiod const char * msg = (const char *) NULL;
530*3d8817e4Smiod
531*3d8817e4Smiod switch (r)
532*3d8817e4Smiod {
533*3d8817e4Smiod case bfd_reloc_overflow:
534*3d8817e4Smiod r = info->callbacks->reloc_overflow
535*3d8817e4Smiod (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
536*3d8817e4Smiod input_bfd, input_section, rel->r_offset);
537*3d8817e4Smiod break;
538*3d8817e4Smiod
539*3d8817e4Smiod case bfd_reloc_undefined:
540*3d8817e4Smiod r = info->callbacks->undefined_symbol
541*3d8817e4Smiod (info, name, input_bfd, input_section, rel->r_offset,
542*3d8817e4Smiod TRUE);
543*3d8817e4Smiod break;
544*3d8817e4Smiod
545*3d8817e4Smiod case bfd_reloc_outofrange:
546*3d8817e4Smiod msg = _("internal error: out of range error");
547*3d8817e4Smiod break;
548*3d8817e4Smiod
549*3d8817e4Smiod case bfd_reloc_notsupported:
550*3d8817e4Smiod msg = _("internal error: unsupported relocation error");
551*3d8817e4Smiod break;
552*3d8817e4Smiod
553*3d8817e4Smiod case bfd_reloc_dangerous:
554*3d8817e4Smiod msg = _("internal error: dangerous relocation");
555*3d8817e4Smiod break;
556*3d8817e4Smiod
557*3d8817e4Smiod default:
558*3d8817e4Smiod msg = _("internal error: unknown error");
559*3d8817e4Smiod break;
560*3d8817e4Smiod }
561*3d8817e4Smiod
562*3d8817e4Smiod if (msg)
563*3d8817e4Smiod r = info->callbacks->warning
564*3d8817e4Smiod (info, msg, name, input_bfd, input_section, rel->r_offset);
565*3d8817e4Smiod
566*3d8817e4Smiod if (! r)
567*3d8817e4Smiod return FALSE;
568*3d8817e4Smiod }
569*3d8817e4Smiod }
570*3d8817e4Smiod
571*3d8817e4Smiod return TRUE;
572*3d8817e4Smiod }
573*3d8817e4Smiod
574*3d8817e4Smiod /* Return the section that should be marked against GC for a given
575*3d8817e4Smiod relocation. */
576*3d8817e4Smiod
577*3d8817e4Smiod static asection *
m32c_elf_gc_mark_hook(asection * sec,struct bfd_link_info * info ATTRIBUTE_UNUSED,Elf_Internal_Rela * rel,struct elf_link_hash_entry * h,Elf_Internal_Sym * sym)578*3d8817e4Smiod m32c_elf_gc_mark_hook
579*3d8817e4Smiod (asection * sec,
580*3d8817e4Smiod struct bfd_link_info * info ATTRIBUTE_UNUSED,
581*3d8817e4Smiod Elf_Internal_Rela * rel,
582*3d8817e4Smiod struct elf_link_hash_entry * h,
583*3d8817e4Smiod Elf_Internal_Sym * sym)
584*3d8817e4Smiod {
585*3d8817e4Smiod if (h != NULL)
586*3d8817e4Smiod {
587*3d8817e4Smiod switch (ELF32_R_TYPE (rel->r_info))
588*3d8817e4Smiod {
589*3d8817e4Smiod default:
590*3d8817e4Smiod switch (h->root.type)
591*3d8817e4Smiod {
592*3d8817e4Smiod case bfd_link_hash_defined:
593*3d8817e4Smiod case bfd_link_hash_defweak:
594*3d8817e4Smiod return h->root.u.def.section;
595*3d8817e4Smiod
596*3d8817e4Smiod case bfd_link_hash_common:
597*3d8817e4Smiod return h->root.u.c.p->section;
598*3d8817e4Smiod
599*3d8817e4Smiod default:
600*3d8817e4Smiod break;
601*3d8817e4Smiod }
602*3d8817e4Smiod }
603*3d8817e4Smiod }
604*3d8817e4Smiod else
605*3d8817e4Smiod {
606*3d8817e4Smiod if (!(elf_bad_symtab (sec->owner)
607*3d8817e4Smiod && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
608*3d8817e4Smiod && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
609*3d8817e4Smiod && sym->st_shndx != SHN_COMMON))
610*3d8817e4Smiod {
611*3d8817e4Smiod return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
612*3d8817e4Smiod }
613*3d8817e4Smiod }
614*3d8817e4Smiod
615*3d8817e4Smiod return NULL;
616*3d8817e4Smiod }
617*3d8817e4Smiod
618*3d8817e4Smiod /* Update the got entry reference counts for the section being removed. */
619*3d8817e4Smiod
620*3d8817e4Smiod static bfd_boolean
m32c_elf_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)621*3d8817e4Smiod m32c_elf_gc_sweep_hook
622*3d8817e4Smiod (bfd * abfd ATTRIBUTE_UNUSED,
623*3d8817e4Smiod struct bfd_link_info * info ATTRIBUTE_UNUSED,
624*3d8817e4Smiod asection * sec ATTRIBUTE_UNUSED,
625*3d8817e4Smiod const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)
626*3d8817e4Smiod {
627*3d8817e4Smiod return TRUE;
628*3d8817e4Smiod }
629*3d8817e4Smiod
630*3d8817e4Smiod /* We support 16-bit pointers to code above 64k by generating a thunk
631*3d8817e4Smiod below 64k containing a JMP instruction to the final address. */
632*3d8817e4Smiod
633*3d8817e4Smiod static bfd_boolean
m32c_elf_check_relocs(bfd * abfd,struct bfd_link_info * info,asection * sec,const Elf_Internal_Rela * relocs)634*3d8817e4Smiod m32c_elf_check_relocs
635*3d8817e4Smiod (bfd * abfd,
636*3d8817e4Smiod struct bfd_link_info * info,
637*3d8817e4Smiod asection * sec,
638*3d8817e4Smiod const Elf_Internal_Rela * relocs)
639*3d8817e4Smiod {
640*3d8817e4Smiod Elf_Internal_Shdr * symtab_hdr;
641*3d8817e4Smiod struct elf_link_hash_entry ** sym_hashes;
642*3d8817e4Smiod struct elf_link_hash_entry ** sym_hashes_end;
643*3d8817e4Smiod const Elf_Internal_Rela * rel;
644*3d8817e4Smiod const Elf_Internal_Rela * rel_end;
645*3d8817e4Smiod bfd_vma *local_plt_offsets;
646*3d8817e4Smiod asection *splt;
647*3d8817e4Smiod bfd *dynobj;
648*3d8817e4Smiod
649*3d8817e4Smiod if (info->relocatable)
650*3d8817e4Smiod return TRUE;
651*3d8817e4Smiod
652*3d8817e4Smiod symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
653*3d8817e4Smiod sym_hashes = elf_sym_hashes (abfd);
654*3d8817e4Smiod local_plt_offsets = elf_local_got_offsets (abfd);
655*3d8817e4Smiod splt = NULL;
656*3d8817e4Smiod dynobj = elf_hash_table(info)->dynobj;
657*3d8817e4Smiod
658*3d8817e4Smiod sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
659*3d8817e4Smiod if (!elf_bad_symtab (abfd))
660*3d8817e4Smiod sym_hashes_end -= symtab_hdr->sh_info;
661*3d8817e4Smiod
662*3d8817e4Smiod rel_end = relocs + sec->reloc_count;
663*3d8817e4Smiod for (rel = relocs; rel < rel_end; rel++)
664*3d8817e4Smiod {
665*3d8817e4Smiod struct elf_link_hash_entry *h;
666*3d8817e4Smiod unsigned long r_symndx;
667*3d8817e4Smiod bfd_vma *offset;
668*3d8817e4Smiod
669*3d8817e4Smiod r_symndx = ELF32_R_SYM (rel->r_info);
670*3d8817e4Smiod if (r_symndx < symtab_hdr->sh_info)
671*3d8817e4Smiod h = NULL;
672*3d8817e4Smiod else
673*3d8817e4Smiod {
674*3d8817e4Smiod h = sym_hashes[r_symndx - symtab_hdr->sh_info];
675*3d8817e4Smiod while (h->root.type == bfd_link_hash_indirect
676*3d8817e4Smiod || h->root.type == bfd_link_hash_warning)
677*3d8817e4Smiod h = (struct elf_link_hash_entry *) h->root.u.i.link;
678*3d8817e4Smiod }
679*3d8817e4Smiod
680*3d8817e4Smiod switch (ELF32_R_TYPE (rel->r_info))
681*3d8817e4Smiod {
682*3d8817e4Smiod /* This relocation describes a 16-bit pointer to a function.
683*3d8817e4Smiod We may need to allocate a thunk in low memory; reserve memory
684*3d8817e4Smiod for it now. */
685*3d8817e4Smiod case R_M32C_16:
686*3d8817e4Smiod if (dynobj == NULL)
687*3d8817e4Smiod elf_hash_table (info)->dynobj = dynobj = abfd;
688*3d8817e4Smiod if (splt == NULL)
689*3d8817e4Smiod {
690*3d8817e4Smiod splt = bfd_get_section_by_name (dynobj, ".plt");
691*3d8817e4Smiod if (splt == NULL)
692*3d8817e4Smiod {
693*3d8817e4Smiod splt = bfd_make_section (dynobj, ".plt");
694*3d8817e4Smiod if (splt == NULL
695*3d8817e4Smiod || ! bfd_set_section_flags (dynobj, splt,
696*3d8817e4Smiod (SEC_ALLOC
697*3d8817e4Smiod | SEC_LOAD
698*3d8817e4Smiod | SEC_HAS_CONTENTS
699*3d8817e4Smiod | SEC_IN_MEMORY
700*3d8817e4Smiod | SEC_LINKER_CREATED
701*3d8817e4Smiod | SEC_READONLY
702*3d8817e4Smiod | SEC_CODE))
703*3d8817e4Smiod || ! bfd_set_section_alignment (dynobj, splt, 1))
704*3d8817e4Smiod return FALSE;
705*3d8817e4Smiod }
706*3d8817e4Smiod }
707*3d8817e4Smiod
708*3d8817e4Smiod if (h != NULL)
709*3d8817e4Smiod offset = &h->plt.offset;
710*3d8817e4Smiod else
711*3d8817e4Smiod {
712*3d8817e4Smiod if (local_plt_offsets == NULL)
713*3d8817e4Smiod {
714*3d8817e4Smiod size_t size;
715*3d8817e4Smiod unsigned int i;
716*3d8817e4Smiod
717*3d8817e4Smiod size = symtab_hdr->sh_info * sizeof (bfd_vma);
718*3d8817e4Smiod local_plt_offsets = (bfd_vma *) bfd_alloc (abfd, size);
719*3d8817e4Smiod if (local_plt_offsets == NULL)
720*3d8817e4Smiod return FALSE;
721*3d8817e4Smiod elf_local_got_offsets (abfd) = local_plt_offsets;
722*3d8817e4Smiod
723*3d8817e4Smiod for (i = 0; i < symtab_hdr->sh_info; i++)
724*3d8817e4Smiod local_plt_offsets[i] = (bfd_vma) -1;
725*3d8817e4Smiod }
726*3d8817e4Smiod offset = &local_plt_offsets[r_symndx];
727*3d8817e4Smiod }
728*3d8817e4Smiod
729*3d8817e4Smiod if (*offset == (bfd_vma) -1)
730*3d8817e4Smiod {
731*3d8817e4Smiod *offset = splt->size;
732*3d8817e4Smiod splt->size += 4;
733*3d8817e4Smiod }
734*3d8817e4Smiod break;
735*3d8817e4Smiod }
736*3d8817e4Smiod }
737*3d8817e4Smiod
738*3d8817e4Smiod return TRUE;
739*3d8817e4Smiod }
740*3d8817e4Smiod
741*3d8817e4Smiod /* This must exist if dynobj is ever set. */
742*3d8817e4Smiod
743*3d8817e4Smiod static bfd_boolean
m32c_elf_finish_dynamic_sections(bfd * abfd ATTRIBUTE_UNUSED,struct bfd_link_info * info)744*3d8817e4Smiod m32c_elf_finish_dynamic_sections (bfd *abfd ATTRIBUTE_UNUSED,
745*3d8817e4Smiod struct bfd_link_info *info)
746*3d8817e4Smiod {
747*3d8817e4Smiod bfd *dynobj;
748*3d8817e4Smiod asection *splt;
749*3d8817e4Smiod
750*3d8817e4Smiod /* As an extra sanity check, verify that all plt entries have
751*3d8817e4Smiod been filled in. */
752*3d8817e4Smiod
753*3d8817e4Smiod if ((dynobj = elf_hash_table (info)->dynobj) != NULL
754*3d8817e4Smiod && (splt = bfd_get_section_by_name (dynobj, ".plt")) != NULL)
755*3d8817e4Smiod {
756*3d8817e4Smiod bfd_byte *contents = splt->contents;
757*3d8817e4Smiod unsigned int i, size = splt->size;
758*3d8817e4Smiod for (i = 0; i < size; i += 4)
759*3d8817e4Smiod {
760*3d8817e4Smiod unsigned int x = bfd_get_32 (dynobj, contents + i);
761*3d8817e4Smiod BFD_ASSERT (x != 0);
762*3d8817e4Smiod }
763*3d8817e4Smiod }
764*3d8817e4Smiod
765*3d8817e4Smiod return TRUE;
766*3d8817e4Smiod }
767*3d8817e4Smiod
768*3d8817e4Smiod static bfd_boolean
m32c_elf_always_size_sections(bfd * output_bfd ATTRIBUTE_UNUSED,struct bfd_link_info * info)769*3d8817e4Smiod m32c_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
770*3d8817e4Smiod struct bfd_link_info *info)
771*3d8817e4Smiod {
772*3d8817e4Smiod bfd *dynobj;
773*3d8817e4Smiod asection *splt;
774*3d8817e4Smiod
775*3d8817e4Smiod if (info->relocatable)
776*3d8817e4Smiod return TRUE;
777*3d8817e4Smiod
778*3d8817e4Smiod dynobj = elf_hash_table (info)->dynobj;
779*3d8817e4Smiod if (dynobj == NULL)
780*3d8817e4Smiod return TRUE;
781*3d8817e4Smiod
782*3d8817e4Smiod splt = bfd_get_section_by_name (dynobj, ".plt");
783*3d8817e4Smiod BFD_ASSERT (splt != NULL);
784*3d8817e4Smiod
785*3d8817e4Smiod splt->contents = (bfd_byte *) bfd_zalloc (dynobj, splt->size);
786*3d8817e4Smiod if (splt->contents == NULL)
787*3d8817e4Smiod return FALSE;
788*3d8817e4Smiod
789*3d8817e4Smiod return TRUE;
790*3d8817e4Smiod }
791*3d8817e4Smiod
792*3d8817e4Smiod /* Function to set the ELF flag bits. */
793*3d8817e4Smiod
794*3d8817e4Smiod static bfd_boolean
m32c_elf_set_private_flags(bfd * abfd,flagword flags)795*3d8817e4Smiod m32c_elf_set_private_flags (bfd *abfd, flagword flags)
796*3d8817e4Smiod {
797*3d8817e4Smiod elf_elfheader (abfd)->e_flags = flags;
798*3d8817e4Smiod elf_flags_init (abfd) = TRUE;
799*3d8817e4Smiod return TRUE;
800*3d8817e4Smiod }
801*3d8817e4Smiod
802*3d8817e4Smiod /* Merge backend specific data from an object file to the output
803*3d8817e4Smiod object file when linking. */
804*3d8817e4Smiod
805*3d8817e4Smiod static bfd_boolean
m32c_elf_merge_private_bfd_data(bfd * ibfd,bfd * obfd)806*3d8817e4Smiod m32c_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
807*3d8817e4Smiod {
808*3d8817e4Smiod flagword old_flags, old_partial;
809*3d8817e4Smiod flagword new_flags, new_partial;
810*3d8817e4Smiod bfd_boolean error = FALSE;
811*3d8817e4Smiod char new_opt[80];
812*3d8817e4Smiod char old_opt[80];
813*3d8817e4Smiod
814*3d8817e4Smiod new_opt[0] = old_opt[0] = '\0';
815*3d8817e4Smiod new_flags = elf_elfheader (ibfd)->e_flags;
816*3d8817e4Smiod old_flags = elf_elfheader (obfd)->e_flags;
817*3d8817e4Smiod
818*3d8817e4Smiod #ifdef DEBUG
819*3d8817e4Smiod (*_bfd_error_handler) ("old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s, filename = %s",
820*3d8817e4Smiod old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no",
821*3d8817e4Smiod bfd_get_filename (ibfd));
822*3d8817e4Smiod #endif
823*3d8817e4Smiod
824*3d8817e4Smiod if (!elf_flags_init (obfd))
825*3d8817e4Smiod {
826*3d8817e4Smiod /* First call, no flags set. */
827*3d8817e4Smiod elf_flags_init (obfd) = TRUE;
828*3d8817e4Smiod elf_elfheader (obfd)->e_flags = new_flags;
829*3d8817e4Smiod }
830*3d8817e4Smiod
831*3d8817e4Smiod else if (new_flags == old_flags)
832*3d8817e4Smiod /* Compatible flags are ok. */
833*3d8817e4Smiod ;
834*3d8817e4Smiod
835*3d8817e4Smiod else /* Possibly incompatible flags. */
836*3d8817e4Smiod {
837*3d8817e4Smiod /* Warn if different cpu is used (allow a specific cpu to override
838*3d8817e4Smiod the generic cpu). */
839*3d8817e4Smiod new_partial = (new_flags & EF_M32C_CPU_MASK);
840*3d8817e4Smiod old_partial = (old_flags & EF_M32C_CPU_MASK);
841*3d8817e4Smiod if (new_partial == old_partial)
842*3d8817e4Smiod ;
843*3d8817e4Smiod
844*3d8817e4Smiod else
845*3d8817e4Smiod {
846*3d8817e4Smiod switch (new_partial)
847*3d8817e4Smiod {
848*3d8817e4Smiod default: strcat (new_opt, " -m16c"); break;
849*3d8817e4Smiod case EF_M32C_CPU_M16C: strcat (new_opt, " -m16c"); break;
850*3d8817e4Smiod case EF_M32C_CPU_M32C: strcat (new_opt, " -m32c"); break;
851*3d8817e4Smiod }
852*3d8817e4Smiod
853*3d8817e4Smiod switch (old_partial)
854*3d8817e4Smiod {
855*3d8817e4Smiod default: strcat (old_opt, " -m16c"); break;
856*3d8817e4Smiod case EF_M32C_CPU_M16C: strcat (old_opt, " -m16c"); break;
857*3d8817e4Smiod case EF_M32C_CPU_M32C: strcat (old_opt, " -m32c"); break;
858*3d8817e4Smiod }
859*3d8817e4Smiod }
860*3d8817e4Smiod
861*3d8817e4Smiod /* Print out any mismatches from above. */
862*3d8817e4Smiod if (new_opt[0])
863*3d8817e4Smiod {
864*3d8817e4Smiod error = TRUE;
865*3d8817e4Smiod (*_bfd_error_handler)
866*3d8817e4Smiod (_("%s: compiled with %s and linked with modules compiled with %s"),
867*3d8817e4Smiod bfd_get_filename (ibfd), new_opt, old_opt);
868*3d8817e4Smiod }
869*3d8817e4Smiod
870*3d8817e4Smiod new_flags &= ~ EF_M32C_ALL_FLAGS;
871*3d8817e4Smiod old_flags &= ~ EF_M32C_ALL_FLAGS;
872*3d8817e4Smiod
873*3d8817e4Smiod /* Warn about any other mismatches. */
874*3d8817e4Smiod if (new_flags != old_flags)
875*3d8817e4Smiod {
876*3d8817e4Smiod error = TRUE;
877*3d8817e4Smiod (*_bfd_error_handler)
878*3d8817e4Smiod (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
879*3d8817e4Smiod bfd_get_filename (ibfd), (long)new_flags, (long)old_flags);
880*3d8817e4Smiod }
881*3d8817e4Smiod }
882*3d8817e4Smiod
883*3d8817e4Smiod if (error)
884*3d8817e4Smiod bfd_set_error (bfd_error_bad_value);
885*3d8817e4Smiod
886*3d8817e4Smiod return !error;
887*3d8817e4Smiod }
888*3d8817e4Smiod
889*3d8817e4Smiod
890*3d8817e4Smiod static bfd_boolean
m32c_elf_print_private_bfd_data(bfd * abfd,PTR ptr)891*3d8817e4Smiod m32c_elf_print_private_bfd_data (bfd *abfd, PTR ptr)
892*3d8817e4Smiod {
893*3d8817e4Smiod FILE *file = (FILE *) ptr;
894*3d8817e4Smiod flagword flags;
895*3d8817e4Smiod
896*3d8817e4Smiod BFD_ASSERT (abfd != NULL && ptr != NULL);
897*3d8817e4Smiod
898*3d8817e4Smiod /* Print normal ELF private data. */
899*3d8817e4Smiod _bfd_elf_print_private_bfd_data (abfd, ptr);
900*3d8817e4Smiod
901*3d8817e4Smiod flags = elf_elfheader (abfd)->e_flags;
902*3d8817e4Smiod fprintf (file, _("private flags = 0x%lx:"), (long)flags);
903*3d8817e4Smiod
904*3d8817e4Smiod switch (flags & EF_M32C_CPU_MASK)
905*3d8817e4Smiod {
906*3d8817e4Smiod default: break;
907*3d8817e4Smiod case EF_M32C_CPU_M16C: fprintf (file, " -m16c"); break;
908*3d8817e4Smiod case EF_M32C_CPU_M32C: fprintf (file, " -m32c"); break;
909*3d8817e4Smiod }
910*3d8817e4Smiod
911*3d8817e4Smiod fputc ('\n', file);
912*3d8817e4Smiod return TRUE;
913*3d8817e4Smiod }
914*3d8817e4Smiod
915*3d8817e4Smiod /* Return the MACH for an e_flags value. */
916*3d8817e4Smiod
917*3d8817e4Smiod static int
elf32_m32c_machine(bfd * abfd)918*3d8817e4Smiod elf32_m32c_machine (bfd *abfd)
919*3d8817e4Smiod {
920*3d8817e4Smiod switch (elf_elfheader (abfd)->e_flags & EF_M32C_CPU_MASK)
921*3d8817e4Smiod {
922*3d8817e4Smiod case EF_M32C_CPU_M16C: return bfd_mach_m16c;
923*3d8817e4Smiod case EF_M32C_CPU_M32C: return bfd_mach_m32c;
924*3d8817e4Smiod }
925*3d8817e4Smiod
926*3d8817e4Smiod return bfd_mach_m16c;
927*3d8817e4Smiod }
928*3d8817e4Smiod
929*3d8817e4Smiod static bfd_boolean
m32c_elf_object_p(bfd * abfd)930*3d8817e4Smiod m32c_elf_object_p (bfd *abfd)
931*3d8817e4Smiod {
932*3d8817e4Smiod bfd_default_set_arch_mach (abfd, bfd_arch_m32c,
933*3d8817e4Smiod elf32_m32c_machine (abfd));
934*3d8817e4Smiod return TRUE;
935*3d8817e4Smiod }
936*3d8817e4Smiod
937*3d8817e4Smiod
938*3d8817e4Smiod #ifdef DEBUG
939*3d8817e4Smiod static void
dump_symtab(bfd * abfd,void * internal_syms,void * external_syms)940*3d8817e4Smiod dump_symtab (bfd * abfd, void *internal_syms, void *external_syms)
941*3d8817e4Smiod {
942*3d8817e4Smiod size_t locsymcount;
943*3d8817e4Smiod Elf_Internal_Sym *isymbuf;
944*3d8817e4Smiod Elf_Internal_Sym *isymend;
945*3d8817e4Smiod Elf_Internal_Sym *isym;
946*3d8817e4Smiod Elf_Internal_Shdr *symtab_hdr;
947*3d8817e4Smiod bfd_boolean free_internal = 0, free_external = 0;
948*3d8817e4Smiod char * st_info_str;
949*3d8817e4Smiod char * st_info_stb_str;
950*3d8817e4Smiod char * st_other_str;
951*3d8817e4Smiod char * st_shndx_str;
952*3d8817e4Smiod
953*3d8817e4Smiod if (! internal_syms)
954*3d8817e4Smiod {
955*3d8817e4Smiod internal_syms = bfd_malloc (1000);
956*3d8817e4Smiod free_internal = 1;
957*3d8817e4Smiod }
958*3d8817e4Smiod if (! external_syms)
959*3d8817e4Smiod {
960*3d8817e4Smiod external_syms = bfd_malloc (1000);
961*3d8817e4Smiod free_external = 1;
962*3d8817e4Smiod }
963*3d8817e4Smiod
964*3d8817e4Smiod symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
965*3d8817e4Smiod locsymcount = symtab_hdr->sh_size / get_elf_backend_data(abfd)->s->sizeof_sym;
966*3d8817e4Smiod if (free_internal)
967*3d8817e4Smiod isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
968*3d8817e4Smiod symtab_hdr->sh_info, 0,
969*3d8817e4Smiod internal_syms, external_syms, NULL);
970*3d8817e4Smiod else
971*3d8817e4Smiod isymbuf = internal_syms;
972*3d8817e4Smiod isymend = isymbuf + locsymcount;
973*3d8817e4Smiod
974*3d8817e4Smiod for (isym = isymbuf ; isym < isymend ; isym++)
975*3d8817e4Smiod {
976*3d8817e4Smiod switch (ELF_ST_TYPE (isym->st_info))
977*3d8817e4Smiod {
978*3d8817e4Smiod case STT_FUNC: st_info_str = "STT_FUNC";
979*3d8817e4Smiod case STT_SECTION: st_info_str = "STT_SECTION";
980*3d8817e4Smiod case STT_SRELC: st_info_str = "STT_SRELC";
981*3d8817e4Smiod case STT_FILE: st_info_str = "STT_FILE";
982*3d8817e4Smiod case STT_OBJECT: st_info_str = "STT_OBJECT";
983*3d8817e4Smiod case STT_TLS: st_info_str = "STT_TLS";
984*3d8817e4Smiod default: st_info_str = "";
985*3d8817e4Smiod }
986*3d8817e4Smiod switch (ELF_ST_BIND (isym->st_info))
987*3d8817e4Smiod {
988*3d8817e4Smiod case STB_LOCAL: st_info_stb_str = "STB_LOCAL";
989*3d8817e4Smiod case STB_GLOBAL: st_info_stb_str = "STB_GLOBAL";
990*3d8817e4Smiod default: st_info_stb_str = "";
991*3d8817e4Smiod }
992*3d8817e4Smiod switch (ELF_ST_VISIBILITY (isym->st_other))
993*3d8817e4Smiod {
994*3d8817e4Smiod case STV_DEFAULT: st_other_str = "STV_DEFAULT";
995*3d8817e4Smiod case STV_INTERNAL: st_other_str = "STV_INTERNAL";
996*3d8817e4Smiod case STV_PROTECTED: st_other_str = "STV_PROTECTED";
997*3d8817e4Smiod default: st_other_str = "";
998*3d8817e4Smiod }
999*3d8817e4Smiod switch (isym->st_shndx)
1000*3d8817e4Smiod {
1001*3d8817e4Smiod case SHN_ABS: st_shndx_str = "SHN_ABS";
1002*3d8817e4Smiod case SHN_COMMON: st_shndx_str = "SHN_COMMON";
1003*3d8817e4Smiod case SHN_UNDEF: st_shndx_str = "SHN_UNDEF";
1004*3d8817e4Smiod default: st_shndx_str = "";
1005*3d8817e4Smiod }
1006*3d8817e4Smiod
1007*3d8817e4Smiod printf ("isym = %p st_value = %lx st_size = %lx st_name = (%lu) %s "
1008*3d8817e4Smiod "st_info = (%d) %s %s st_other = (%d) %s st_shndx = (%d) %s\n",
1009*3d8817e4Smiod isym,
1010*3d8817e4Smiod (unsigned long) isym->st_value,
1011*3d8817e4Smiod (unsigned long) isym->st_size,
1012*3d8817e4Smiod isym->st_name,
1013*3d8817e4Smiod bfd_elf_string_from_elf_section (abfd, symtab_hdr->sh_link,
1014*3d8817e4Smiod isym->st_name),
1015*3d8817e4Smiod isym->st_info, st_info_str, st_info_stb_str,
1016*3d8817e4Smiod isym->st_other, st_other_str,
1017*3d8817e4Smiod isym->st_shndx, st_shndx_str);
1018*3d8817e4Smiod }
1019*3d8817e4Smiod if (free_internal)
1020*3d8817e4Smiod free (internal_syms);
1021*3d8817e4Smiod if (free_external)
1022*3d8817e4Smiod free (external_syms);
1023*3d8817e4Smiod }
1024*3d8817e4Smiod
1025*3d8817e4Smiod static char *
m32c_get_reloc(long reloc)1026*3d8817e4Smiod m32c_get_reloc (long reloc)
1027*3d8817e4Smiod {
1028*3d8817e4Smiod if (0 <= reloc && reloc < R_M32C_max)
1029*3d8817e4Smiod return m32c_elf_howto_table[reloc].name;
1030*3d8817e4Smiod else
1031*3d8817e4Smiod return "";
1032*3d8817e4Smiod }
1033*3d8817e4Smiod #endif /* DEBUG */
1034*3d8817e4Smiod
1035*3d8817e4Smiod /* Handle relaxing. */
1036*3d8817e4Smiod
1037*3d8817e4Smiod /* A subroutine of m32c_elf_relax_section. If the global symbol H
1038*3d8817e4Smiod is within the low 64k, remove any entry for it in the plt. */
1039*3d8817e4Smiod
1040*3d8817e4Smiod struct relax_plt_data
1041*3d8817e4Smiod {
1042*3d8817e4Smiod asection *splt;
1043*3d8817e4Smiod bfd_boolean *again;
1044*3d8817e4Smiod };
1045*3d8817e4Smiod
1046*3d8817e4Smiod static bfd_boolean
m32c_relax_plt_check(struct elf_link_hash_entry * h,PTR xdata)1047*3d8817e4Smiod m32c_relax_plt_check (struct elf_link_hash_entry *h,
1048*3d8817e4Smiod PTR xdata)
1049*3d8817e4Smiod {
1050*3d8817e4Smiod struct relax_plt_data *data = (struct relax_plt_data *) xdata;
1051*3d8817e4Smiod
1052*3d8817e4Smiod if (h->root.type == bfd_link_hash_warning)
1053*3d8817e4Smiod h = (struct elf_link_hash_entry *) h->root.u.i.link;
1054*3d8817e4Smiod
1055*3d8817e4Smiod if (h->plt.offset != (bfd_vma) -1)
1056*3d8817e4Smiod {
1057*3d8817e4Smiod bfd_vma address;
1058*3d8817e4Smiod
1059*3d8817e4Smiod if (h->root.type == bfd_link_hash_undefined
1060*3d8817e4Smiod || h->root.type == bfd_link_hash_undefweak)
1061*3d8817e4Smiod address = 0;
1062*3d8817e4Smiod else
1063*3d8817e4Smiod address = (h->root.u.def.section->output_section->vma
1064*3d8817e4Smiod + h->root.u.def.section->output_offset
1065*3d8817e4Smiod + h->root.u.def.value);
1066*3d8817e4Smiod
1067*3d8817e4Smiod if (address <= 0xffff)
1068*3d8817e4Smiod {
1069*3d8817e4Smiod h->plt.offset = -1;
1070*3d8817e4Smiod data->splt->size -= 4;
1071*3d8817e4Smiod *data->again = TRUE;
1072*3d8817e4Smiod }
1073*3d8817e4Smiod }
1074*3d8817e4Smiod
1075*3d8817e4Smiod return TRUE;
1076*3d8817e4Smiod }
1077*3d8817e4Smiod
1078*3d8817e4Smiod /* A subroutine of m32c_elf_relax_section. If the global symbol H
1079*3d8817e4Smiod previously had a plt entry, give it a new entry offset. */
1080*3d8817e4Smiod
1081*3d8817e4Smiod static bfd_boolean
m32c_relax_plt_realloc(struct elf_link_hash_entry * h,PTR xdata)1082*3d8817e4Smiod m32c_relax_plt_realloc (struct elf_link_hash_entry *h,
1083*3d8817e4Smiod PTR xdata)
1084*3d8817e4Smiod {
1085*3d8817e4Smiod bfd_vma *entry = (bfd_vma *) xdata;
1086*3d8817e4Smiod
1087*3d8817e4Smiod if (h->root.type == bfd_link_hash_warning)
1088*3d8817e4Smiod h = (struct elf_link_hash_entry *) h->root.u.i.link;
1089*3d8817e4Smiod
1090*3d8817e4Smiod if (h->plt.offset != (bfd_vma) -1)
1091*3d8817e4Smiod {
1092*3d8817e4Smiod h->plt.offset = *entry;
1093*3d8817e4Smiod *entry += 4;
1094*3d8817e4Smiod }
1095*3d8817e4Smiod
1096*3d8817e4Smiod return TRUE;
1097*3d8817e4Smiod }
1098*3d8817e4Smiod
1099*3d8817e4Smiod static bfd_boolean
m32c_elf_relax_plt_section(bfd * dynobj,asection * splt,struct bfd_link_info * info,bfd_boolean * again)1100*3d8817e4Smiod m32c_elf_relax_plt_section (bfd *dynobj,
1101*3d8817e4Smiod asection *splt,
1102*3d8817e4Smiod struct bfd_link_info *info,
1103*3d8817e4Smiod bfd_boolean *again)
1104*3d8817e4Smiod {
1105*3d8817e4Smiod struct relax_plt_data relax_plt_data;
1106*3d8817e4Smiod bfd *ibfd;
1107*3d8817e4Smiod
1108*3d8817e4Smiod /* Assume nothing changes. */
1109*3d8817e4Smiod *again = FALSE;
1110*3d8817e4Smiod
1111*3d8817e4Smiod if (info->relocatable)
1112*3d8817e4Smiod return TRUE;
1113*3d8817e4Smiod
1114*3d8817e4Smiod /* We only relax the .plt section at the moment. */
1115*3d8817e4Smiod if (dynobj != elf_hash_table (info)->dynobj
1116*3d8817e4Smiod || strcmp (splt->name, ".plt") != 0)
1117*3d8817e4Smiod return TRUE;
1118*3d8817e4Smiod
1119*3d8817e4Smiod /* Quick check for an empty plt. */
1120*3d8817e4Smiod if (splt->size == 0)
1121*3d8817e4Smiod return TRUE;
1122*3d8817e4Smiod
1123*3d8817e4Smiod /* Map across all global symbols; see which ones happen to
1124*3d8817e4Smiod fall in the low 64k. */
1125*3d8817e4Smiod relax_plt_data.splt = splt;
1126*3d8817e4Smiod relax_plt_data.again = again;
1127*3d8817e4Smiod elf_link_hash_traverse (elf_hash_table (info), m32c_relax_plt_check,
1128*3d8817e4Smiod &relax_plt_data);
1129*3d8817e4Smiod
1130*3d8817e4Smiod /* Likewise for local symbols, though that's somewhat less convenient
1131*3d8817e4Smiod as we have to walk the list of input bfds and swap in symbol data. */
1132*3d8817e4Smiod for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
1133*3d8817e4Smiod {
1134*3d8817e4Smiod bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
1135*3d8817e4Smiod Elf_Internal_Shdr *symtab_hdr;
1136*3d8817e4Smiod Elf_Internal_Sym *isymbuf = NULL;
1137*3d8817e4Smiod unsigned int idx;
1138*3d8817e4Smiod
1139*3d8817e4Smiod if (! local_plt_offsets)
1140*3d8817e4Smiod continue;
1141*3d8817e4Smiod
1142*3d8817e4Smiod symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
1143*3d8817e4Smiod if (symtab_hdr->sh_info != 0)
1144*3d8817e4Smiod {
1145*3d8817e4Smiod isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1146*3d8817e4Smiod if (isymbuf == NULL)
1147*3d8817e4Smiod isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
1148*3d8817e4Smiod symtab_hdr->sh_info, 0,
1149*3d8817e4Smiod NULL, NULL, NULL);
1150*3d8817e4Smiod if (isymbuf == NULL)
1151*3d8817e4Smiod return FALSE;
1152*3d8817e4Smiod }
1153*3d8817e4Smiod
1154*3d8817e4Smiod for (idx = 0; idx < symtab_hdr->sh_info; ++idx)
1155*3d8817e4Smiod {
1156*3d8817e4Smiod Elf_Internal_Sym *isym;
1157*3d8817e4Smiod asection *tsec;
1158*3d8817e4Smiod bfd_vma address;
1159*3d8817e4Smiod
1160*3d8817e4Smiod if (local_plt_offsets[idx] == (bfd_vma) -1)
1161*3d8817e4Smiod continue;
1162*3d8817e4Smiod
1163*3d8817e4Smiod isym = &isymbuf[idx];
1164*3d8817e4Smiod if (isym->st_shndx == SHN_UNDEF)
1165*3d8817e4Smiod continue;
1166*3d8817e4Smiod else if (isym->st_shndx == SHN_ABS)
1167*3d8817e4Smiod tsec = bfd_abs_section_ptr;
1168*3d8817e4Smiod else if (isym->st_shndx == SHN_COMMON)
1169*3d8817e4Smiod tsec = bfd_com_section_ptr;
1170*3d8817e4Smiod else
1171*3d8817e4Smiod tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx);
1172*3d8817e4Smiod
1173*3d8817e4Smiod address = (tsec->output_section->vma
1174*3d8817e4Smiod + tsec->output_offset
1175*3d8817e4Smiod + isym->st_value);
1176*3d8817e4Smiod if (address <= 0xffff)
1177*3d8817e4Smiod {
1178*3d8817e4Smiod local_plt_offsets[idx] = -1;
1179*3d8817e4Smiod splt->size -= 4;
1180*3d8817e4Smiod *again = TRUE;
1181*3d8817e4Smiod }
1182*3d8817e4Smiod }
1183*3d8817e4Smiod
1184*3d8817e4Smiod if (isymbuf != NULL
1185*3d8817e4Smiod && symtab_hdr->contents != (unsigned char *) isymbuf)
1186*3d8817e4Smiod {
1187*3d8817e4Smiod if (! info->keep_memory)
1188*3d8817e4Smiod free (isymbuf);
1189*3d8817e4Smiod else
1190*3d8817e4Smiod {
1191*3d8817e4Smiod /* Cache the symbols for elf_link_input_bfd. */
1192*3d8817e4Smiod symtab_hdr->contents = (unsigned char *) isymbuf;
1193*3d8817e4Smiod }
1194*3d8817e4Smiod }
1195*3d8817e4Smiod }
1196*3d8817e4Smiod
1197*3d8817e4Smiod /* If we changed anything, walk the symbols again to reallocate
1198*3d8817e4Smiod .plt entry addresses. */
1199*3d8817e4Smiod if (*again && splt->size > 0)
1200*3d8817e4Smiod {
1201*3d8817e4Smiod bfd_vma entry = 0;
1202*3d8817e4Smiod
1203*3d8817e4Smiod elf_link_hash_traverse (elf_hash_table (info),
1204*3d8817e4Smiod m32c_relax_plt_realloc, &entry);
1205*3d8817e4Smiod
1206*3d8817e4Smiod for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
1207*3d8817e4Smiod {
1208*3d8817e4Smiod bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
1209*3d8817e4Smiod unsigned int nlocals = elf_tdata (ibfd)->symtab_hdr.sh_info;
1210*3d8817e4Smiod unsigned int idx;
1211*3d8817e4Smiod
1212*3d8817e4Smiod if (! local_plt_offsets)
1213*3d8817e4Smiod continue;
1214*3d8817e4Smiod
1215*3d8817e4Smiod for (idx = 0; idx < nlocals; ++idx)
1216*3d8817e4Smiod if (local_plt_offsets[idx] != (bfd_vma) -1)
1217*3d8817e4Smiod {
1218*3d8817e4Smiod local_plt_offsets[idx] = entry;
1219*3d8817e4Smiod entry += 4;
1220*3d8817e4Smiod }
1221*3d8817e4Smiod }
1222*3d8817e4Smiod }
1223*3d8817e4Smiod
1224*3d8817e4Smiod return TRUE;
1225*3d8817e4Smiod }
1226*3d8817e4Smiod
1227*3d8817e4Smiod static int
compare_reloc(const void * e1,const void * e2)1228*3d8817e4Smiod compare_reloc (const void *e1, const void *e2)
1229*3d8817e4Smiod {
1230*3d8817e4Smiod const Elf_Internal_Rela *i1 = (const Elf_Internal_Rela *) e1;
1231*3d8817e4Smiod const Elf_Internal_Rela *i2 = (const Elf_Internal_Rela *) e2;
1232*3d8817e4Smiod
1233*3d8817e4Smiod if (i1->r_offset == i2->r_offset)
1234*3d8817e4Smiod return 0;
1235*3d8817e4Smiod else
1236*3d8817e4Smiod return i1->r_offset < i2->r_offset ? -1 : 1;
1237*3d8817e4Smiod }
1238*3d8817e4Smiod
1239*3d8817e4Smiod #define OFFSET_FOR_RELOC(rel) m32c_offset_for_reloc (abfd, rel, symtab_hdr, shndx_buf, intsyms)
1240*3d8817e4Smiod static bfd_vma
m32c_offset_for_reloc(bfd * abfd,Elf_Internal_Rela * rel,Elf_Internal_Shdr * symtab_hdr,Elf_External_Sym_Shndx * shndx_buf,Elf_Internal_Sym * intsyms)1241*3d8817e4Smiod m32c_offset_for_reloc (bfd *abfd,
1242*3d8817e4Smiod Elf_Internal_Rela *rel,
1243*3d8817e4Smiod Elf_Internal_Shdr *symtab_hdr,
1244*3d8817e4Smiod Elf_External_Sym_Shndx *shndx_buf,
1245*3d8817e4Smiod Elf_Internal_Sym *intsyms)
1246*3d8817e4Smiod {
1247*3d8817e4Smiod bfd_vma symval;
1248*3d8817e4Smiod
1249*3d8817e4Smiod /* Get the value of the symbol referred to by the reloc. */
1250*3d8817e4Smiod if (ELF32_R_SYM (rel->r_info) < symtab_hdr->sh_info)
1251*3d8817e4Smiod {
1252*3d8817e4Smiod /* A local symbol. */
1253*3d8817e4Smiod Elf_Internal_Sym *isym;
1254*3d8817e4Smiod Elf_External_Sym_Shndx *shndx;
1255*3d8817e4Smiod asection *ssec;
1256*3d8817e4Smiod
1257*3d8817e4Smiod
1258*3d8817e4Smiod isym = intsyms + ELF32_R_SYM (rel->r_info);
1259*3d8817e4Smiod ssec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1260*3d8817e4Smiod shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (rel->r_info) : 0);
1261*3d8817e4Smiod
1262*3d8817e4Smiod symval = isym->st_value;
1263*3d8817e4Smiod if (ssec)
1264*3d8817e4Smiod symval += ssec->output_section->vma
1265*3d8817e4Smiod + ssec->output_offset;
1266*3d8817e4Smiod }
1267*3d8817e4Smiod else
1268*3d8817e4Smiod {
1269*3d8817e4Smiod unsigned long indx;
1270*3d8817e4Smiod struct elf_link_hash_entry *h;
1271*3d8817e4Smiod
1272*3d8817e4Smiod /* An external symbol. */
1273*3d8817e4Smiod indx = ELF32_R_SYM (rel->r_info) - symtab_hdr->sh_info;
1274*3d8817e4Smiod h = elf_sym_hashes (abfd)[indx];
1275*3d8817e4Smiod BFD_ASSERT (h != NULL);
1276*3d8817e4Smiod
1277*3d8817e4Smiod if (h->root.type != bfd_link_hash_defined
1278*3d8817e4Smiod && h->root.type != bfd_link_hash_defweak)
1279*3d8817e4Smiod /* This appears to be a reference to an undefined
1280*3d8817e4Smiod symbol. Just ignore it--it will be caught by the
1281*3d8817e4Smiod regular reloc processing. */
1282*3d8817e4Smiod return 0;
1283*3d8817e4Smiod
1284*3d8817e4Smiod symval = (h->root.u.def.value
1285*3d8817e4Smiod + h->root.u.def.section->output_section->vma
1286*3d8817e4Smiod + h->root.u.def.section->output_offset);
1287*3d8817e4Smiod }
1288*3d8817e4Smiod return symval;
1289*3d8817e4Smiod }
1290*3d8817e4Smiod
1291*3d8817e4Smiod static int bytes_saved = 0;
1292*3d8817e4Smiod
1293*3d8817e4Smiod static int bytes_to_reloc[] = {
1294*3d8817e4Smiod R_M32C_NONE,
1295*3d8817e4Smiod R_M32C_8,
1296*3d8817e4Smiod R_M32C_16,
1297*3d8817e4Smiod R_M32C_24,
1298*3d8817e4Smiod R_M32C_32
1299*3d8817e4Smiod };
1300*3d8817e4Smiod
1301*3d8817e4Smiod /* What we use the bits in a relax reloc addend (R_M32C_RL_*) for. */
1302*3d8817e4Smiod
1303*3d8817e4Smiod /* Mask for the number of relocs associated with this insn. */
1304*3d8817e4Smiod #define RLA_RELOCS 0x0000000f
1305*3d8817e4Smiod /* Number of bytes gas emitted (before gas's relaxing) */
1306*3d8817e4Smiod #define RLA_NBYTES 0x00000ff0
1307*3d8817e4Smiod
1308*3d8817e4Smiod /* If the displacement is within the given range and the new encoding
1309*3d8817e4Smiod differs from the old encoding (the index), then the insn can be
1310*3d8817e4Smiod relaxed to the new encoding. */
1311*3d8817e4Smiod typedef struct {
1312*3d8817e4Smiod int bytes;
1313*3d8817e4Smiod unsigned int max_disp;
1314*3d8817e4Smiod unsigned char new_encoding;
1315*3d8817e4Smiod } EncodingTable;
1316*3d8817e4Smiod
1317*3d8817e4Smiod static EncodingTable m16c_addr_encodings[] = {
1318*3d8817e4Smiod { 0, 0, 0 }, /* R0 */
1319*3d8817e4Smiod { 0, 0, 1 }, /* R1 */
1320*3d8817e4Smiod { 0, 0, 2 }, /* R2 */
1321*3d8817e4Smiod { 0, 0, 3 }, /* R3 */
1322*3d8817e4Smiod { 0, 0, 4 }, /* A0 */
1323*3d8817e4Smiod { 0, 0, 5 }, /* A1 */
1324*3d8817e4Smiod { 0, 0, 6 }, /* [A0] */
1325*3d8817e4Smiod { 0, 0, 7 }, /* [A1] */
1326*3d8817e4Smiod { 1, 0, 6 }, /* udsp:8[A0] */
1327*3d8817e4Smiod { 1, 0, 7 }, /* udsp:8[A1] */
1328*3d8817e4Smiod { 1, 0, 10 }, /* udsp:8[SB] */
1329*3d8817e4Smiod { 1, 0, 11 }, /* sdsp:8[FB] */
1330*3d8817e4Smiod { 2, 255, 8 }, /* udsp:16[A0] */
1331*3d8817e4Smiod { 2, 255, 9 }, /* udsp:16[A1] */
1332*3d8817e4Smiod { 2, 255, 10 }, /* udsp:16[SB] */
1333*3d8817e4Smiod { 2, 0, 15 }, /* abs:16 */
1334*3d8817e4Smiod };
1335*3d8817e4Smiod
1336*3d8817e4Smiod static EncodingTable m16c_jmpaddr_encodings[] = {
1337*3d8817e4Smiod { 0, 0, 0 }, /* R0 */
1338*3d8817e4Smiod { 0, 0, 1 }, /* R1 */
1339*3d8817e4Smiod { 0, 0, 2 }, /* R2 */
1340*3d8817e4Smiod { 0, 0, 3 }, /* R3 */
1341*3d8817e4Smiod { 0, 0, 4 }, /* A0 */
1342*3d8817e4Smiod { 0, 0, 5 }, /* A1 */
1343*3d8817e4Smiod { 0, 0, 6 }, /* [A0] */
1344*3d8817e4Smiod { 0, 0, 7 }, /* [A1] */
1345*3d8817e4Smiod { 1, 0, 6 }, /* udsp:8[A0] */
1346*3d8817e4Smiod { 1, 0, 7 }, /* udsp:8[A1] */
1347*3d8817e4Smiod { 1, 0, 10 }, /* udsp:8[SB] */
1348*3d8817e4Smiod { 1, 0, 11 }, /* sdsp:8[FB] */
1349*3d8817e4Smiod { 3, 255, 8 }, /* udsp:20[A0] */
1350*3d8817e4Smiod { 3, 255, 9 }, /* udsp:20[A1] */
1351*3d8817e4Smiod { 2, 255, 10 }, /* udsp:16[SB] */
1352*3d8817e4Smiod { 2, 0, 15 }, /* abs:16 */
1353*3d8817e4Smiod };
1354*3d8817e4Smiod
1355*3d8817e4Smiod static EncodingTable m32c_addr_encodings[] = {
1356*3d8817e4Smiod { 0, 0, 0 }, /* [A0] */
1357*3d8817e4Smiod { 0, 0, 1 }, /* [A1] */
1358*3d8817e4Smiod { 0, 0, 2 }, /* A0 */
1359*3d8817e4Smiod { 0, 0, 3 }, /* A1 */
1360*3d8817e4Smiod { 1, 0, 0 }, /* udsp:8[A0] */
1361*3d8817e4Smiod { 1, 0, 1 }, /* udsp:8[A1] */
1362*3d8817e4Smiod { 1, 0, 6 }, /* udsp:8[SB] */
1363*3d8817e4Smiod { 1, 0, 7 }, /* sdsp:8[FB] */
1364*3d8817e4Smiod { 2, 255, 4 }, /* udsp:16[A0] */
1365*3d8817e4Smiod { 2, 255, 5 }, /* udsp:16[A1] */
1366*3d8817e4Smiod { 2, 255, 6 }, /* udsp:16[SB] */
1367*3d8817e4Smiod { 2, 127, 7 }, /* sdsp:16[FB] */
1368*3d8817e4Smiod { 3, 65535, 8 }, /* udsp:24[A0] */
1369*3d8817e4Smiod { 3, 65535, 9 }, /* udsp:24[A1] */
1370*3d8817e4Smiod { 3, 65535, 15 }, /* abs24 */
1371*3d8817e4Smiod { 2, 0, 15 }, /* abs16 */
1372*3d8817e4Smiod { 0, 0, 16 }, /* R2 */
1373*3d8817e4Smiod { 0, 0, 17 }, /* R3 */
1374*3d8817e4Smiod { 0, 0, 18 }, /* R0 */
1375*3d8817e4Smiod { 0, 0, 19 }, /* R1 */
1376*3d8817e4Smiod { 0, 0, 20 }, /* */
1377*3d8817e4Smiod { 0, 0, 21 }, /* */
1378*3d8817e4Smiod { 0, 0, 22 }, /* */
1379*3d8817e4Smiod { 0, 0, 23 }, /* */
1380*3d8817e4Smiod { 0, 0, 24 }, /* */
1381*3d8817e4Smiod { 0, 0, 25 }, /* */
1382*3d8817e4Smiod { 0, 0, 26 }, /* */
1383*3d8817e4Smiod { 0, 0, 27 }, /* */
1384*3d8817e4Smiod { 0, 0, 28 }, /* */
1385*3d8817e4Smiod { 0, 0, 29 }, /* */
1386*3d8817e4Smiod { 0, 0, 30 }, /* */
1387*3d8817e4Smiod { 0, 0, 31 }, /* */
1388*3d8817e4Smiod };
1389*3d8817e4Smiod
1390*3d8817e4Smiod static bfd_boolean
m32c_elf_relax_section(bfd * abfd,asection * sec,struct bfd_link_info * link_info,bfd_boolean * again)1391*3d8817e4Smiod m32c_elf_relax_section
1392*3d8817e4Smiod (bfd * abfd,
1393*3d8817e4Smiod asection * sec,
1394*3d8817e4Smiod struct bfd_link_info * link_info,
1395*3d8817e4Smiod bfd_boolean * again)
1396*3d8817e4Smiod {
1397*3d8817e4Smiod Elf_Internal_Shdr *symtab_hdr;
1398*3d8817e4Smiod Elf_Internal_Shdr *shndx_hdr;
1399*3d8817e4Smiod Elf_Internal_Rela *internal_relocs;
1400*3d8817e4Smiod Elf_Internal_Rela *free_relocs = NULL;
1401*3d8817e4Smiod Elf_Internal_Rela *irel, *irelend, *srel;
1402*3d8817e4Smiod bfd_byte * contents = NULL;
1403*3d8817e4Smiod bfd_byte * free_contents = NULL;
1404*3d8817e4Smiod Elf_Internal_Sym *intsyms = NULL;
1405*3d8817e4Smiod Elf_Internal_Sym *free_intsyms = NULL;
1406*3d8817e4Smiod Elf_External_Sym_Shndx *shndx_buf = NULL;
1407*3d8817e4Smiod int machine;
1408*3d8817e4Smiod
1409*3d8817e4Smiod if (abfd == elf_hash_table (link_info)->dynobj
1410*3d8817e4Smiod && strcmp (sec->name, ".plt") == 0)
1411*3d8817e4Smiod return m32c_elf_relax_plt_section (abfd, sec, link_info, again);
1412*3d8817e4Smiod
1413*3d8817e4Smiod /* Assume nothing changes. */
1414*3d8817e4Smiod *again = FALSE;
1415*3d8817e4Smiod
1416*3d8817e4Smiod machine = elf32_m32c_machine (abfd);
1417*3d8817e4Smiod
1418*3d8817e4Smiod /* We don't have to do anything for a relocatable link, if
1419*3d8817e4Smiod this section does not have relocs, or if this is not a
1420*3d8817e4Smiod code section. */
1421*3d8817e4Smiod if (link_info->relocatable
1422*3d8817e4Smiod || (sec->flags & SEC_RELOC) == 0
1423*3d8817e4Smiod || sec->reloc_count == 0
1424*3d8817e4Smiod || (sec->flags & SEC_CODE) == 0)
1425*3d8817e4Smiod return TRUE;
1426*3d8817e4Smiod
1427*3d8817e4Smiod symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1428*3d8817e4Smiod shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
1429*3d8817e4Smiod
1430*3d8817e4Smiod /* Get the section contents. */
1431*3d8817e4Smiod if (elf_section_data (sec)->this_hdr.contents != NULL)
1432*3d8817e4Smiod contents = elf_section_data (sec)->this_hdr.contents;
1433*3d8817e4Smiod /* Go get them off disk. */
1434*3d8817e4Smiod else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
1435*3d8817e4Smiod goto error_return;
1436*3d8817e4Smiod
1437*3d8817e4Smiod /* Read this BFD's symbols. */
1438*3d8817e4Smiod /* Get cached copy if it exists. */
1439*3d8817e4Smiod if (symtab_hdr->contents != NULL)
1440*3d8817e4Smiod {
1441*3d8817e4Smiod intsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
1442*3d8817e4Smiod }
1443*3d8817e4Smiod else
1444*3d8817e4Smiod {
1445*3d8817e4Smiod intsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr, symtab_hdr->sh_info, 0, NULL, NULL, NULL);
1446*3d8817e4Smiod symtab_hdr->contents = (bfd_byte *) intsyms;
1447*3d8817e4Smiod }
1448*3d8817e4Smiod
1449*3d8817e4Smiod if (shndx_hdr->sh_size != 0)
1450*3d8817e4Smiod {
1451*3d8817e4Smiod bfd_size_type amt;
1452*3d8817e4Smiod
1453*3d8817e4Smiod amt = symtab_hdr->sh_info;
1454*3d8817e4Smiod amt *= sizeof (Elf_External_Sym_Shndx);
1455*3d8817e4Smiod shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
1456*3d8817e4Smiod if (shndx_buf == NULL)
1457*3d8817e4Smiod goto error_return;
1458*3d8817e4Smiod if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
1459*3d8817e4Smiod || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
1460*3d8817e4Smiod goto error_return;
1461*3d8817e4Smiod shndx_hdr->contents = (bfd_byte *) shndx_buf;
1462*3d8817e4Smiod }
1463*3d8817e4Smiod
1464*3d8817e4Smiod /* Get a copy of the native relocations. */
1465*3d8817e4Smiod internal_relocs = (_bfd_elf_link_read_relocs
1466*3d8817e4Smiod (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
1467*3d8817e4Smiod link_info->keep_memory));
1468*3d8817e4Smiod if (internal_relocs == NULL)
1469*3d8817e4Smiod goto error_return;
1470*3d8817e4Smiod if (! link_info->keep_memory)
1471*3d8817e4Smiod free_relocs = internal_relocs;
1472*3d8817e4Smiod
1473*3d8817e4Smiod /* The RL_ relocs must be just before the operand relocs they go
1474*3d8817e4Smiod with, so we must sort them to guarantee this. */
1475*3d8817e4Smiod qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
1476*3d8817e4Smiod compare_reloc);
1477*3d8817e4Smiod
1478*3d8817e4Smiod /* Walk through them looking for relaxing opportunities. */
1479*3d8817e4Smiod irelend = internal_relocs + sec->reloc_count;
1480*3d8817e4Smiod
1481*3d8817e4Smiod for (irel = internal_relocs; irel < irelend; irel++)
1482*3d8817e4Smiod {
1483*3d8817e4Smiod bfd_vma symval;
1484*3d8817e4Smiod unsigned char *insn, *gap, *einsn;
1485*3d8817e4Smiod bfd_vma pc;
1486*3d8817e4Smiod bfd_signed_vma pcrel;
1487*3d8817e4Smiod int relax_relocs;
1488*3d8817e4Smiod int gap_size;
1489*3d8817e4Smiod int new_type;
1490*3d8817e4Smiod int posn;
1491*3d8817e4Smiod int enc;
1492*3d8817e4Smiod EncodingTable *enctbl;
1493*3d8817e4Smiod EncodingTable *e;
1494*3d8817e4Smiod
1495*3d8817e4Smiod if (ELF32_R_TYPE(irel->r_info) != R_M32C_RL_JUMP
1496*3d8817e4Smiod && ELF32_R_TYPE(irel->r_info) != R_M32C_RL_1ADDR
1497*3d8817e4Smiod && ELF32_R_TYPE(irel->r_info) != R_M32C_RL_2ADDR)
1498*3d8817e4Smiod continue;
1499*3d8817e4Smiod
1500*3d8817e4Smiod srel = irel;
1501*3d8817e4Smiod
1502*3d8817e4Smiod /* There will always be room for the relaxed insn, since it is smaller
1503*3d8817e4Smiod than the one it would replace. */
1504*3d8817e4Smiod BFD_ASSERT (irel->r_offset < sec->size);
1505*3d8817e4Smiod
1506*3d8817e4Smiod insn = contents + irel->r_offset;
1507*3d8817e4Smiod relax_relocs = irel->r_addend % 16;
1508*3d8817e4Smiod
1509*3d8817e4Smiod /* Ok, we only have three relocs we care about, and they're all
1510*3d8817e4Smiod fake. The lower four bits of the addend is always the number
1511*3d8817e4Smiod of following relocs (hence the qsort above) that are assigned
1512*3d8817e4Smiod to this opcode. The next 8 bits of the addend indicates the
1513*3d8817e4Smiod number of bytes in the insn. We use the rest of them
1514*3d8817e4Smiod ourselves as flags for the more expensive operations (defines
1515*3d8817e4Smiod above). The three relocs are:
1516*3d8817e4Smiod
1517*3d8817e4Smiod RL_JUMP: This marks all direct jump insns. We check the
1518*3d8817e4Smiod displacement and replace them with shorter jumps if
1519*3d8817e4Smiod they're in range. We also use this to find JMP.S
1520*3d8817e4Smiod insns and manually shorten them when we delete bytes.
1521*3d8817e4Smiod We have to decode these insns to figure out what to
1522*3d8817e4Smiod do.
1523*3d8817e4Smiod
1524*3d8817e4Smiod RL_1ADDR: This is a :G or :Q insn, which has a single
1525*3d8817e4Smiod "standard" operand. We have to extract the type
1526*3d8817e4Smiod field, see if it's a wide displacement, then figure
1527*3d8817e4Smiod out if we can replace it with a narrow displacement.
1528*3d8817e4Smiod We don't have to decode these insns.
1529*3d8817e4Smiod
1530*3d8817e4Smiod RL_2ADDR: Similarly, but two "standard" operands. Note that
1531*3d8817e4Smiod r_addend may still be 1, as standard operands don't
1532*3d8817e4Smiod always have displacements. Gas shouldn't give us one
1533*3d8817e4Smiod with zero operands, but since we don't know which one
1534*3d8817e4Smiod has the displacement, we check them both anyway.
1535*3d8817e4Smiod
1536*3d8817e4Smiod These all point to the beginning of the insn itself, not the
1537*3d8817e4Smiod operands.
1538*3d8817e4Smiod
1539*3d8817e4Smiod Note that we only relax one step at a time, relying on the
1540*3d8817e4Smiod linker to call us repeatedly. Thus, there is no code for
1541*3d8817e4Smiod JMP.A->JMP.B although that will happen in two steps.
1542*3d8817e4Smiod Likewise, for 2ADDR relaxes, we do one operand per cycle.
1543*3d8817e4Smiod */
1544*3d8817e4Smiod
1545*3d8817e4Smiod /* Get the value of the symbol referred to by the reloc. Just
1546*3d8817e4Smiod in case this is the last reloc in the list, use the RL's
1547*3d8817e4Smiod addend to choose between this reloc (no addend) or the next
1548*3d8817e4Smiod (yes addend, which means at least one following reloc). */
1549*3d8817e4Smiod srel = irel + (relax_relocs ? 1 : 0);
1550*3d8817e4Smiod symval = OFFSET_FOR_RELOC (srel);
1551*3d8817e4Smiod
1552*3d8817e4Smiod /* Setting gap_size nonzero is the flag which means "something
1553*3d8817e4Smiod shrunk". */
1554*3d8817e4Smiod gap_size = 0;
1555*3d8817e4Smiod gap = NULL;
1556*3d8817e4Smiod new_type = ELF32_R_TYPE(srel->r_info);
1557*3d8817e4Smiod
1558*3d8817e4Smiod pc = sec->output_section->vma + sec->output_offset
1559*3d8817e4Smiod + srel->r_offset;
1560*3d8817e4Smiod pcrel = symval - pc + srel->r_addend;
1561*3d8817e4Smiod
1562*3d8817e4Smiod if (machine == bfd_mach_m16c)
1563*3d8817e4Smiod {
1564*3d8817e4Smiod /* R8C / M16C */
1565*3d8817e4Smiod
1566*3d8817e4Smiod switch (ELF32_R_TYPE(irel->r_info))
1567*3d8817e4Smiod {
1568*3d8817e4Smiod
1569*3d8817e4Smiod case R_M32C_RL_JUMP:
1570*3d8817e4Smiod switch (insn[0])
1571*3d8817e4Smiod {
1572*3d8817e4Smiod case 0xfe: /* jmp.b */
1573*3d8817e4Smiod if (pcrel >= 2 && pcrel <= 9)
1574*3d8817e4Smiod {
1575*3d8817e4Smiod /* Relax JMP.B -> JMP.S. We need to get rid of
1576*3d8817e4Smiod the following reloc though. */
1577*3d8817e4Smiod insn[0] = 0x60 | (pcrel - 2);
1578*3d8817e4Smiod new_type = R_M32C_NONE;
1579*3d8817e4Smiod irel->r_addend = 0x10;
1580*3d8817e4Smiod gap_size = 1;
1581*3d8817e4Smiod gap = insn + 1;
1582*3d8817e4Smiod }
1583*3d8817e4Smiod break;
1584*3d8817e4Smiod
1585*3d8817e4Smiod case 0xf4: /* jmp.w */
1586*3d8817e4Smiod /* 128 is allowed because it will be one byte closer
1587*3d8817e4Smiod after relaxing. Likewise for all other pc-rel
1588*3d8817e4Smiod jumps. */
1589*3d8817e4Smiod if (pcrel <= 128 && pcrel >= -128)
1590*3d8817e4Smiod {
1591*3d8817e4Smiod /* Relax JMP.W -> JMP.B */
1592*3d8817e4Smiod insn[0] = 0xfe;
1593*3d8817e4Smiod insn[1] = 0;
1594*3d8817e4Smiod new_type = R_M32C_8_PCREL;
1595*3d8817e4Smiod gap_size = 1;
1596*3d8817e4Smiod gap = insn + 2;
1597*3d8817e4Smiod }
1598*3d8817e4Smiod break;
1599*3d8817e4Smiod
1600*3d8817e4Smiod case 0xfc: /* jmp.a */
1601*3d8817e4Smiod if (pcrel <= 32768 && pcrel >= -32768)
1602*3d8817e4Smiod {
1603*3d8817e4Smiod /* Relax JMP.A -> JMP.W */
1604*3d8817e4Smiod insn[0] = 0xf4;
1605*3d8817e4Smiod insn[1] = 0;
1606*3d8817e4Smiod insn[2] = 0;
1607*3d8817e4Smiod new_type = R_M32C_16_PCREL;
1608*3d8817e4Smiod gap_size = 1;
1609*3d8817e4Smiod gap = insn + 3;
1610*3d8817e4Smiod }
1611*3d8817e4Smiod break;
1612*3d8817e4Smiod
1613*3d8817e4Smiod case 0xfd: /* jsr.a */
1614*3d8817e4Smiod if (pcrel <= 32768 && pcrel >= -32768)
1615*3d8817e4Smiod {
1616*3d8817e4Smiod /* Relax JSR.A -> JSR.W */
1617*3d8817e4Smiod insn[0] = 0xf5;
1618*3d8817e4Smiod insn[1] = 0;
1619*3d8817e4Smiod insn[2] = 0;
1620*3d8817e4Smiod new_type = R_M32C_16_PCREL;
1621*3d8817e4Smiod gap_size = 1;
1622*3d8817e4Smiod gap = insn + 3;
1623*3d8817e4Smiod }
1624*3d8817e4Smiod break;
1625*3d8817e4Smiod }
1626*3d8817e4Smiod break;
1627*3d8817e4Smiod
1628*3d8817e4Smiod case R_M32C_RL_2ADDR:
1629*3d8817e4Smiod /* xxxx xxxx srce dest [src-disp] [dest-disp]*/
1630*3d8817e4Smiod
1631*3d8817e4Smiod enctbl = m16c_addr_encodings;
1632*3d8817e4Smiod posn = 2;
1633*3d8817e4Smiod enc = (insn[1] >> 4) & 0x0f;
1634*3d8817e4Smiod e = & enctbl[enc];
1635*3d8817e4Smiod
1636*3d8817e4Smiod if (srel->r_offset == irel->r_offset + posn
1637*3d8817e4Smiod && e->new_encoding != enc
1638*3d8817e4Smiod && symval <= e->max_disp)
1639*3d8817e4Smiod {
1640*3d8817e4Smiod insn[1] &= 0x0f;
1641*3d8817e4Smiod insn[1] |= e->new_encoding << 4;
1642*3d8817e4Smiod gap_size = e->bytes - enctbl[e->new_encoding].bytes;
1643*3d8817e4Smiod gap = insn + posn + enctbl[e->new_encoding].bytes;
1644*3d8817e4Smiod new_type = bytes_to_reloc[enctbl[e->new_encoding].bytes];
1645*3d8817e4Smiod break;
1646*3d8817e4Smiod }
1647*3d8817e4Smiod if (relax_relocs == 2)
1648*3d8817e4Smiod srel ++;
1649*3d8817e4Smiod posn += e->bytes;
1650*3d8817e4Smiod
1651*3d8817e4Smiod goto try_1addr_16;
1652*3d8817e4Smiod
1653*3d8817e4Smiod case R_M32C_RL_1ADDR:
1654*3d8817e4Smiod /* xxxx xxxx xxxx dest [disp] */
1655*3d8817e4Smiod
1656*3d8817e4Smiod enctbl = m16c_addr_encodings;
1657*3d8817e4Smiod posn = 2;
1658*3d8817e4Smiod
1659*3d8817e4Smiod /* Check the opcode for jumps. We know it's safe to
1660*3d8817e4Smiod do this because all 2ADDR insns are at least two
1661*3d8817e4Smiod bytes long. */
1662*3d8817e4Smiod enc = insn[0] * 256 + insn[1];
1663*3d8817e4Smiod enc &= 0xfff0;
1664*3d8817e4Smiod if (enc == 0x7d20
1665*3d8817e4Smiod || enc == 0x7d00
1666*3d8817e4Smiod || enc == 0x7d30
1667*3d8817e4Smiod || enc == 0x7d10)
1668*3d8817e4Smiod {
1669*3d8817e4Smiod enctbl = m16c_jmpaddr_encodings;
1670*3d8817e4Smiod }
1671*3d8817e4Smiod
1672*3d8817e4Smiod try_1addr_16:
1673*3d8817e4Smiod /* srel, posn, and enc must be set here. */
1674*3d8817e4Smiod
1675*3d8817e4Smiod symval = OFFSET_FOR_RELOC (srel);
1676*3d8817e4Smiod enc = insn[1] & 0x0f;
1677*3d8817e4Smiod e = & enctbl[enc];
1678*3d8817e4Smiod
1679*3d8817e4Smiod if (srel->r_offset == irel->r_offset + posn
1680*3d8817e4Smiod && e->new_encoding != enc
1681*3d8817e4Smiod && symval <= e->max_disp)
1682*3d8817e4Smiod {
1683*3d8817e4Smiod insn[1] &= 0xf0;
1684*3d8817e4Smiod insn[1] |= e->new_encoding;
1685*3d8817e4Smiod gap_size = e->bytes - enctbl[e->new_encoding].bytes;
1686*3d8817e4Smiod gap = insn + posn + enctbl[e->new_encoding].bytes;
1687*3d8817e4Smiod new_type = bytes_to_reloc[enctbl[e->new_encoding].bytes];
1688*3d8817e4Smiod break;
1689*3d8817e4Smiod }
1690*3d8817e4Smiod
1691*3d8817e4Smiod break;
1692*3d8817e4Smiod
1693*3d8817e4Smiod } /* Ends switch (reloc type) for m16c. */
1694*3d8817e4Smiod }
1695*3d8817e4Smiod else /* machine == bfd_mach_m32c */
1696*3d8817e4Smiod {
1697*3d8817e4Smiod /* M32CM / M32C */
1698*3d8817e4Smiod
1699*3d8817e4Smiod switch (ELF32_R_TYPE(irel->r_info))
1700*3d8817e4Smiod {
1701*3d8817e4Smiod
1702*3d8817e4Smiod case R_M32C_RL_JUMP:
1703*3d8817e4Smiod switch (insn[0])
1704*3d8817e4Smiod {
1705*3d8817e4Smiod case 0xbb: /* jmp.b */
1706*3d8817e4Smiod if (pcrel >= 2 && pcrel <= 9)
1707*3d8817e4Smiod {
1708*3d8817e4Smiod int p = pcrel - 2;
1709*3d8817e4Smiod /* Relax JMP.B -> JMP.S. We need to get rid of
1710*3d8817e4Smiod the following reloc though. */
1711*3d8817e4Smiod insn[0] = 0x4a | ((p << 3) & 0x30) | (p & 1);
1712*3d8817e4Smiod new_type = R_M32C_NONE;
1713*3d8817e4Smiod irel->r_addend = 0x10;
1714*3d8817e4Smiod gap_size = 1;
1715*3d8817e4Smiod gap = insn + 1;
1716*3d8817e4Smiod }
1717*3d8817e4Smiod break;
1718*3d8817e4Smiod
1719*3d8817e4Smiod case 0xce: /* jmp.w */
1720*3d8817e4Smiod if (pcrel <= 128 && pcrel >= -128)
1721*3d8817e4Smiod {
1722*3d8817e4Smiod /* Relax JMP.W -> JMP.B */
1723*3d8817e4Smiod insn[0] = 0xbb;
1724*3d8817e4Smiod insn[1] = 0;
1725*3d8817e4Smiod new_type = R_M32C_8_PCREL;
1726*3d8817e4Smiod gap_size = 1;
1727*3d8817e4Smiod gap = insn + 2;
1728*3d8817e4Smiod }
1729*3d8817e4Smiod break;
1730*3d8817e4Smiod
1731*3d8817e4Smiod case 0xcc: /* jmp.a */
1732*3d8817e4Smiod if (pcrel <= 32768 && pcrel >= -32768)
1733*3d8817e4Smiod {
1734*3d8817e4Smiod /* Relax JMP.A -> JMP.W */
1735*3d8817e4Smiod insn[0] = 0xce;
1736*3d8817e4Smiod insn[1] = 0;
1737*3d8817e4Smiod insn[2] = 0;
1738*3d8817e4Smiod new_type = R_M32C_16_PCREL;
1739*3d8817e4Smiod gap_size = 1;
1740*3d8817e4Smiod gap = insn + 3;
1741*3d8817e4Smiod }
1742*3d8817e4Smiod break;
1743*3d8817e4Smiod
1744*3d8817e4Smiod case 0xcd: /* jsr.a */
1745*3d8817e4Smiod if (pcrel <= 32768 && pcrel >= -32768)
1746*3d8817e4Smiod {
1747*3d8817e4Smiod /* Relax JSR.A -> JSR.W */
1748*3d8817e4Smiod insn[0] = 0xcf;
1749*3d8817e4Smiod insn[1] = 0;
1750*3d8817e4Smiod insn[2] = 0;
1751*3d8817e4Smiod new_type = R_M32C_16_PCREL;
1752*3d8817e4Smiod gap_size = 1;
1753*3d8817e4Smiod gap = insn + 3;
1754*3d8817e4Smiod }
1755*3d8817e4Smiod break;
1756*3d8817e4Smiod }
1757*3d8817e4Smiod break;
1758*3d8817e4Smiod
1759*3d8817e4Smiod case R_M32C_RL_2ADDR:
1760*3d8817e4Smiod /* xSSS DDDx DDSS xxxx [src-disp] [dest-disp]*/
1761*3d8817e4Smiod
1762*3d8817e4Smiod einsn = insn;
1763*3d8817e4Smiod posn = 2;
1764*3d8817e4Smiod if (einsn[0] == 1)
1765*3d8817e4Smiod {
1766*3d8817e4Smiod /* prefix; remove it as far as the RL reloc is concerned. */
1767*3d8817e4Smiod einsn ++;
1768*3d8817e4Smiod posn ++;
1769*3d8817e4Smiod }
1770*3d8817e4Smiod
1771*3d8817e4Smiod enctbl = m32c_addr_encodings;
1772*3d8817e4Smiod enc = ((einsn[0] & 0x70) >> 2) | ((einsn[1] & 0x30) >> 4);
1773*3d8817e4Smiod e = & enctbl[enc];
1774*3d8817e4Smiod
1775*3d8817e4Smiod if (srel->r_offset == irel->r_offset + posn
1776*3d8817e4Smiod && e->new_encoding != enc
1777*3d8817e4Smiod && symval <= e->max_disp)
1778*3d8817e4Smiod {
1779*3d8817e4Smiod einsn[0] &= 0x8f;
1780*3d8817e4Smiod einsn[0] |= (e->new_encoding & 0x1c) << 2;
1781*3d8817e4Smiod einsn[1] &= 0xcf;
1782*3d8817e4Smiod einsn[1] |= (e->new_encoding & 0x03) << 4;
1783*3d8817e4Smiod gap_size = e->bytes - enctbl[e->new_encoding].bytes;
1784*3d8817e4Smiod gap = insn + posn + enctbl[e->new_encoding].bytes;
1785*3d8817e4Smiod new_type = bytes_to_reloc[enctbl[e->new_encoding].bytes];
1786*3d8817e4Smiod break;
1787*3d8817e4Smiod }
1788*3d8817e4Smiod if (relax_relocs == 2)
1789*3d8817e4Smiod srel ++;
1790*3d8817e4Smiod posn += e->bytes;
1791*3d8817e4Smiod
1792*3d8817e4Smiod goto try_1addr_32;
1793*3d8817e4Smiod
1794*3d8817e4Smiod case R_M32C_RL_1ADDR:
1795*3d8817e4Smiod /* xxxx DDDx DDxx xxxx [disp] */
1796*3d8817e4Smiod
1797*3d8817e4Smiod einsn = insn;
1798*3d8817e4Smiod posn = 2;
1799*3d8817e4Smiod if (einsn[0] == 1)
1800*3d8817e4Smiod {
1801*3d8817e4Smiod /* prefix; remove it as far as the RL reloc is concerned. */
1802*3d8817e4Smiod einsn ++;
1803*3d8817e4Smiod posn ++;
1804*3d8817e4Smiod }
1805*3d8817e4Smiod
1806*3d8817e4Smiod enctbl = m32c_addr_encodings;
1807*3d8817e4Smiod
1808*3d8817e4Smiod try_1addr_32:
1809*3d8817e4Smiod /* srel, posn, and enc must be set here. */
1810*3d8817e4Smiod
1811*3d8817e4Smiod symval = OFFSET_FOR_RELOC (srel);
1812*3d8817e4Smiod enc = ((einsn[0] & 0x0e) << 1) | ((einsn[1] & 0xc0) >> 6);
1813*3d8817e4Smiod e = & enctbl[enc];
1814*3d8817e4Smiod
1815*3d8817e4Smiod if (srel->r_offset == irel->r_offset + posn
1816*3d8817e4Smiod && e->new_encoding != enc
1817*3d8817e4Smiod && symval <= e->max_disp)
1818*3d8817e4Smiod {
1819*3d8817e4Smiod einsn[0] &= 0xf1;
1820*3d8817e4Smiod einsn[0] |= (e->new_encoding & 0x1c) >> 1;
1821*3d8817e4Smiod einsn[1] &= 0x3f;
1822*3d8817e4Smiod einsn[1] |= (e->new_encoding & 0x03) << 6;
1823*3d8817e4Smiod gap_size = e->bytes - enctbl[e->new_encoding].bytes;
1824*3d8817e4Smiod gap = insn + posn + enctbl[e->new_encoding].bytes;
1825*3d8817e4Smiod new_type = bytes_to_reloc[enctbl[e->new_encoding].bytes];
1826*3d8817e4Smiod break;
1827*3d8817e4Smiod }
1828*3d8817e4Smiod
1829*3d8817e4Smiod break;
1830*3d8817e4Smiod
1831*3d8817e4Smiod } /* Ends switch (reloc type) for m32c. */
1832*3d8817e4Smiod }
1833*3d8817e4Smiod
1834*3d8817e4Smiod if (gap_size == 0)
1835*3d8817e4Smiod continue;
1836*3d8817e4Smiod
1837*3d8817e4Smiod *again = TRUE;
1838*3d8817e4Smiod
1839*3d8817e4Smiod srel->r_info = ELF32_R_INFO (ELF32_R_SYM (srel->r_info), new_type);
1840*3d8817e4Smiod
1841*3d8817e4Smiod /* Note that we've changed the relocs, section contents, etc. */
1842*3d8817e4Smiod elf_section_data (sec)->relocs = internal_relocs;
1843*3d8817e4Smiod free_relocs = NULL;
1844*3d8817e4Smiod
1845*3d8817e4Smiod elf_section_data (sec)->this_hdr.contents = contents;
1846*3d8817e4Smiod free_contents = NULL;
1847*3d8817e4Smiod
1848*3d8817e4Smiod symtab_hdr->contents = (bfd_byte *) intsyms;
1849*3d8817e4Smiod free_intsyms = NULL;
1850*3d8817e4Smiod
1851*3d8817e4Smiod bytes_saved += gap_size;
1852*3d8817e4Smiod
1853*3d8817e4Smiod if (! m32c_elf_relax_delete_bytes(abfd, sec, gap - contents, gap_size))
1854*3d8817e4Smiod goto error_return;
1855*3d8817e4Smiod
1856*3d8817e4Smiod } /* next relocation */
1857*3d8817e4Smiod
1858*3d8817e4Smiod if (free_relocs != NULL)
1859*3d8817e4Smiod {
1860*3d8817e4Smiod free (free_relocs);
1861*3d8817e4Smiod free_relocs = NULL;
1862*3d8817e4Smiod }
1863*3d8817e4Smiod
1864*3d8817e4Smiod if (free_contents != NULL)
1865*3d8817e4Smiod {
1866*3d8817e4Smiod if (! link_info->keep_memory)
1867*3d8817e4Smiod free (free_contents);
1868*3d8817e4Smiod /* Cache the section contents for elf_link_input_bfd. */
1869*3d8817e4Smiod else
1870*3d8817e4Smiod elf_section_data (sec)->this_hdr.contents = contents;
1871*3d8817e4Smiod
1872*3d8817e4Smiod free_contents = NULL;
1873*3d8817e4Smiod }
1874*3d8817e4Smiod
1875*3d8817e4Smiod if (shndx_buf != NULL)
1876*3d8817e4Smiod {
1877*3d8817e4Smiod shndx_hdr->contents = NULL;
1878*3d8817e4Smiod free (shndx_buf);
1879*3d8817e4Smiod }
1880*3d8817e4Smiod
1881*3d8817e4Smiod if (free_intsyms != NULL)
1882*3d8817e4Smiod {
1883*3d8817e4Smiod if (! link_info->keep_memory)
1884*3d8817e4Smiod free (free_intsyms);
1885*3d8817e4Smiod /* Cache the symbols for elf_link_input_bfd. */
1886*3d8817e4Smiod else
1887*3d8817e4Smiod {
1888*3d8817e4Smiod symtab_hdr->contents = NULL /* (unsigned char *) intsyms*/;
1889*3d8817e4Smiod }
1890*3d8817e4Smiod
1891*3d8817e4Smiod free_intsyms = NULL;
1892*3d8817e4Smiod }
1893*3d8817e4Smiod
1894*3d8817e4Smiod return TRUE;
1895*3d8817e4Smiod
1896*3d8817e4Smiod error_return:
1897*3d8817e4Smiod if (free_relocs != NULL)
1898*3d8817e4Smiod free (free_relocs);
1899*3d8817e4Smiod if (free_contents != NULL)
1900*3d8817e4Smiod free (free_contents);
1901*3d8817e4Smiod if (shndx_buf != NULL)
1902*3d8817e4Smiod {
1903*3d8817e4Smiod shndx_hdr->contents = NULL;
1904*3d8817e4Smiod free (shndx_buf);
1905*3d8817e4Smiod }
1906*3d8817e4Smiod if (free_intsyms != NULL)
1907*3d8817e4Smiod free (free_intsyms);
1908*3d8817e4Smiod return FALSE;
1909*3d8817e4Smiod }
1910*3d8817e4Smiod
1911*3d8817e4Smiod /* Delete some bytes from a section while relaxing. */
1912*3d8817e4Smiod
1913*3d8817e4Smiod static bfd_boolean
m32c_elf_relax_delete_bytes(bfd * abfd,asection * sec,bfd_vma addr,int count)1914*3d8817e4Smiod m32c_elf_relax_delete_bytes
1915*3d8817e4Smiod (bfd * abfd,
1916*3d8817e4Smiod asection * sec,
1917*3d8817e4Smiod bfd_vma addr,
1918*3d8817e4Smiod int count)
1919*3d8817e4Smiod {
1920*3d8817e4Smiod Elf_Internal_Shdr *symtab_hdr;
1921*3d8817e4Smiod Elf_Internal_Shdr *shndx_hdr;
1922*3d8817e4Smiod int sec_shndx;
1923*3d8817e4Smiod bfd_byte *contents;
1924*3d8817e4Smiod Elf_Internal_Rela *irel;
1925*3d8817e4Smiod Elf_Internal_Rela *irelend;
1926*3d8817e4Smiod Elf_Internal_Rela *irelalign;
1927*3d8817e4Smiod bfd_vma toaddr;
1928*3d8817e4Smiod Elf_Internal_Sym *isym;
1929*3d8817e4Smiod Elf_Internal_Sym *isymend;
1930*3d8817e4Smiod Elf_Internal_Sym *intsyms;
1931*3d8817e4Smiod Elf_External_Sym_Shndx *shndx_buf;
1932*3d8817e4Smiod Elf_External_Sym_Shndx *shndx;
1933*3d8817e4Smiod struct elf_link_hash_entry ** sym_hashes;
1934*3d8817e4Smiod struct elf_link_hash_entry ** end_hashes;
1935*3d8817e4Smiod unsigned int symcount;
1936*3d8817e4Smiod
1937*3d8817e4Smiod contents = elf_section_data (sec)->this_hdr.contents;
1938*3d8817e4Smiod
1939*3d8817e4Smiod /* The deletion must stop at the next ALIGN reloc for an aligment
1940*3d8817e4Smiod power larger than the number of bytes we are deleting. */
1941*3d8817e4Smiod irelalign = NULL;
1942*3d8817e4Smiod toaddr = sec->size;
1943*3d8817e4Smiod
1944*3d8817e4Smiod irel = elf_section_data (sec)->relocs;
1945*3d8817e4Smiod irelend = irel + sec->reloc_count;
1946*3d8817e4Smiod
1947*3d8817e4Smiod /* Actually delete the bytes. */
1948*3d8817e4Smiod memmove (contents + addr, contents + addr + count, (size_t) (toaddr - addr - count));
1949*3d8817e4Smiod sec->size -= count;
1950*3d8817e4Smiod
1951*3d8817e4Smiod /* Adjust all the relocs. */
1952*3d8817e4Smiod for (irel = elf_section_data (sec)->relocs; irel < irelend; irel ++)
1953*3d8817e4Smiod {
1954*3d8817e4Smiod /* Get the new reloc address. */
1955*3d8817e4Smiod if (irel->r_offset > addr && irel->r_offset < toaddr)
1956*3d8817e4Smiod irel->r_offset -= count;
1957*3d8817e4Smiod
1958*3d8817e4Smiod if (ELF32_R_TYPE(irel->r_info) == R_M32C_RL_JUMP
1959*3d8817e4Smiod && irel->r_addend == 0x10 /* one byte insn, no relocs */
1960*3d8817e4Smiod && irel->r_offset + 1 < addr
1961*3d8817e4Smiod && irel->r_offset + 7 > addr)
1962*3d8817e4Smiod {
1963*3d8817e4Smiod bfd_vma disp;
1964*3d8817e4Smiod unsigned char *insn = &contents[irel->r_offset];
1965*3d8817e4Smiod disp = *insn;
1966*3d8817e4Smiod /* This is a JMP.S, which we have to manually update. */
1967*3d8817e4Smiod if (elf32_m32c_machine (abfd) == bfd_mach_m16c)
1968*3d8817e4Smiod {
1969*3d8817e4Smiod if ((*insn & 0xf8) != 0x60)
1970*3d8817e4Smiod continue;
1971*3d8817e4Smiod disp = (disp & 7);
1972*3d8817e4Smiod }
1973*3d8817e4Smiod else
1974*3d8817e4Smiod {
1975*3d8817e4Smiod if ((*insn & 0xce) != 0x4a)
1976*3d8817e4Smiod continue;
1977*3d8817e4Smiod disp = ((disp & 0x30) >> 3) | (disp & 1);
1978*3d8817e4Smiod }
1979*3d8817e4Smiod if (irel->r_offset + disp + 2 >= addr+count)
1980*3d8817e4Smiod {
1981*3d8817e4Smiod disp -= count;
1982*3d8817e4Smiod if (elf32_m32c_machine (abfd) == bfd_mach_m16c)
1983*3d8817e4Smiod {
1984*3d8817e4Smiod *insn = (*insn & 0xf8) | disp;
1985*3d8817e4Smiod }
1986*3d8817e4Smiod else
1987*3d8817e4Smiod {
1988*3d8817e4Smiod *insn = (*insn & 0xce) | ((disp & 6) << 3) | (disp & 1);
1989*3d8817e4Smiod }
1990*3d8817e4Smiod }
1991*3d8817e4Smiod }
1992*3d8817e4Smiod }
1993*3d8817e4Smiod
1994*3d8817e4Smiod /* Adjust the local symbols defined in this section. */
1995*3d8817e4Smiod symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
1996*3d8817e4Smiod intsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
1997*3d8817e4Smiod isym = intsyms;
1998*3d8817e4Smiod isymend = isym + symtab_hdr->sh_info;
1999*3d8817e4Smiod
2000*3d8817e4Smiod sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
2001*3d8817e4Smiod shndx_hdr = & elf_tdata (abfd)->symtab_shndx_hdr;
2002*3d8817e4Smiod shndx_buf = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
2003*3d8817e4Smiod shndx = shndx_buf;
2004*3d8817e4Smiod
2005*3d8817e4Smiod for (; isym < isymend; isym++, shndx = (shndx ? shndx + 1 : NULL))
2006*3d8817e4Smiod {
2007*3d8817e4Smiod
2008*3d8817e4Smiod if ((int) isym->st_shndx == sec_shndx
2009*3d8817e4Smiod && isym->st_value > addr
2010*3d8817e4Smiod && isym->st_value < toaddr)
2011*3d8817e4Smiod {
2012*3d8817e4Smiod isym->st_value -= count;
2013*3d8817e4Smiod }
2014*3d8817e4Smiod }
2015*3d8817e4Smiod
2016*3d8817e4Smiod /* Now adjust the global symbols defined in this section. */
2017*3d8817e4Smiod symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
2018*3d8817e4Smiod - symtab_hdr->sh_info);
2019*3d8817e4Smiod sym_hashes = elf_sym_hashes (abfd);
2020*3d8817e4Smiod // sym_hashes += symtab_hdr->sh_info;
2021*3d8817e4Smiod end_hashes = sym_hashes + symcount;
2022*3d8817e4Smiod
2023*3d8817e4Smiod for (; sym_hashes < end_hashes; sym_hashes ++)
2024*3d8817e4Smiod {
2025*3d8817e4Smiod struct elf_link_hash_entry * sym_hash = * sym_hashes;
2026*3d8817e4Smiod
2027*3d8817e4Smiod if (sym_hash &&
2028*3d8817e4Smiod ( sym_hash->root.type == bfd_link_hash_defined
2029*3d8817e4Smiod || sym_hash->root.type == bfd_link_hash_defweak)
2030*3d8817e4Smiod && sym_hash->root.u.def.section == sec
2031*3d8817e4Smiod && sym_hash->root.u.def.value > addr
2032*3d8817e4Smiod && sym_hash->root.u.def.value < toaddr)
2033*3d8817e4Smiod {
2034*3d8817e4Smiod sym_hash->root.u.def.value -= count;
2035*3d8817e4Smiod }
2036*3d8817e4Smiod }
2037*3d8817e4Smiod
2038*3d8817e4Smiod return TRUE;
2039*3d8817e4Smiod }
2040*3d8817e4Smiod
2041*3d8817e4Smiod
2042*3d8817e4Smiod #define ELF_ARCH bfd_arch_m32c
2043*3d8817e4Smiod #define ELF_MACHINE_CODE EM_M32C
2044*3d8817e4Smiod #define ELF_MAXPAGESIZE 0x1000
2045*3d8817e4Smiod
2046*3d8817e4Smiod #if 0
2047*3d8817e4Smiod #define TARGET_BIG_SYM bfd_elf32_m32c_vec
2048*3d8817e4Smiod #define TARGET_BIG_NAME "elf32-m32c"
2049*3d8817e4Smiod #else
2050*3d8817e4Smiod #define TARGET_LITTLE_SYM bfd_elf32_m32c_vec
2051*3d8817e4Smiod #define TARGET_LITTLE_NAME "elf32-m32c"
2052*3d8817e4Smiod #endif
2053*3d8817e4Smiod
2054*3d8817e4Smiod #define elf_info_to_howto_rel NULL
2055*3d8817e4Smiod #define elf_info_to_howto m32c_info_to_howto_rela
2056*3d8817e4Smiod #define elf_backend_object_p m32c_elf_object_p
2057*3d8817e4Smiod #define elf_backend_relocate_section m32c_elf_relocate_section
2058*3d8817e4Smiod #define elf_backend_gc_mark_hook m32c_elf_gc_mark_hook
2059*3d8817e4Smiod #define elf_backend_gc_sweep_hook m32c_elf_gc_sweep_hook
2060*3d8817e4Smiod #define elf_backend_check_relocs m32c_elf_check_relocs
2061*3d8817e4Smiod #define elf_backend_object_p m32c_elf_object_p
2062*3d8817e4Smiod #define elf_symbol_leading_char ('_')
2063*3d8817e4Smiod #define elf_backend_always_size_sections \
2064*3d8817e4Smiod m32c_elf_always_size_sections
2065*3d8817e4Smiod #define elf_backend_finish_dynamic_sections \
2066*3d8817e4Smiod m32c_elf_finish_dynamic_sections
2067*3d8817e4Smiod
2068*3d8817e4Smiod #define elf_backend_can_gc_sections 1
2069*3d8817e4Smiod
2070*3d8817e4Smiod #define bfd_elf32_bfd_reloc_type_lookup m32c_reloc_type_lookup
2071*3d8817e4Smiod #define bfd_elf32_bfd_relax_section m32c_elf_relax_section
2072*3d8817e4Smiod #define bfd_elf32_bfd_set_private_flags m32c_elf_set_private_flags
2073*3d8817e4Smiod #define bfd_elf32_bfd_merge_private_bfd_data m32c_elf_merge_private_bfd_data
2074*3d8817e4Smiod #define bfd_elf32_bfd_print_private_bfd_data m32c_elf_print_private_bfd_data
2075*3d8817e4Smiod
2076*3d8817e4Smiod #include "elf32-target.h"
2077