1*3d8817e4Smiod /* BFD back-end for ARM COFF files.
2*3d8817e4Smiod Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3*3d8817e4Smiod 2000, 2001, 2002, 2003, 2004, 2005, 2006
4*3d8817e4Smiod Free Software Foundation, Inc.
5*3d8817e4Smiod Written by Cygnus Support.
6*3d8817e4Smiod
7*3d8817e4Smiod This file is part of BFD, the Binary File Descriptor library.
8*3d8817e4Smiod
9*3d8817e4Smiod This program is free software; you can redistribute it and/or modify
10*3d8817e4Smiod it under the terms of the GNU General Public License as published by
11*3d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
12*3d8817e4Smiod (at your option) any later version.
13*3d8817e4Smiod
14*3d8817e4Smiod This program is distributed in the hope that it will be useful,
15*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
16*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17*3d8817e4Smiod GNU General Public License for more details.
18*3d8817e4Smiod
19*3d8817e4Smiod You should have received a copy of the GNU General Public License
20*3d8817e4Smiod along with this program; if not, write to the Free Software
21*3d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
22*3d8817e4Smiod
23*3d8817e4Smiod #include "bfd.h"
24*3d8817e4Smiod #include "sysdep.h"
25*3d8817e4Smiod #include "libbfd.h"
26*3d8817e4Smiod #include "coff/arm.h"
27*3d8817e4Smiod #include "coff/internal.h"
28*3d8817e4Smiod
29*3d8817e4Smiod #ifdef COFF_WITH_PE
30*3d8817e4Smiod #include "coff/pe.h"
31*3d8817e4Smiod #endif
32*3d8817e4Smiod
33*3d8817e4Smiod #include "libcoff.h"
34*3d8817e4Smiod
35*3d8817e4Smiod /* Macros for manipulation the bits in the flags field of the coff data
36*3d8817e4Smiod structure. */
37*3d8817e4Smiod #define APCS_26_FLAG(abfd) \
38*3d8817e4Smiod (coff_data (abfd)->flags & F_APCS_26)
39*3d8817e4Smiod
40*3d8817e4Smiod #define APCS_FLOAT_FLAG(abfd) \
41*3d8817e4Smiod (coff_data (abfd)->flags & F_APCS_FLOAT)
42*3d8817e4Smiod
43*3d8817e4Smiod #define PIC_FLAG(abfd) \
44*3d8817e4Smiod (coff_data (abfd)->flags & F_PIC)
45*3d8817e4Smiod
46*3d8817e4Smiod #define APCS_SET(abfd) \
47*3d8817e4Smiod (coff_data (abfd)->flags & F_APCS_SET)
48*3d8817e4Smiod
49*3d8817e4Smiod #define SET_APCS_FLAGS(abfd, flgs) \
50*3d8817e4Smiod do \
51*3d8817e4Smiod { \
52*3d8817e4Smiod coff_data (abfd)->flags &= ~(F_APCS_26 | F_APCS_FLOAT | F_PIC); \
53*3d8817e4Smiod coff_data (abfd)->flags |= (flgs) | F_APCS_SET; \
54*3d8817e4Smiod } \
55*3d8817e4Smiod while (0)
56*3d8817e4Smiod
57*3d8817e4Smiod #define INTERWORK_FLAG(abfd) \
58*3d8817e4Smiod (coff_data (abfd)->flags & F_INTERWORK)
59*3d8817e4Smiod
60*3d8817e4Smiod #define INTERWORK_SET(abfd) \
61*3d8817e4Smiod (coff_data (abfd)->flags & F_INTERWORK_SET)
62*3d8817e4Smiod
63*3d8817e4Smiod #define SET_INTERWORK_FLAG(abfd, flg) \
64*3d8817e4Smiod do \
65*3d8817e4Smiod { \
66*3d8817e4Smiod coff_data (abfd)->flags &= ~F_INTERWORK; \
67*3d8817e4Smiod coff_data (abfd)->flags |= (flg) | F_INTERWORK_SET; \
68*3d8817e4Smiod } \
69*3d8817e4Smiod while (0)
70*3d8817e4Smiod
71*3d8817e4Smiod #ifndef NUM_ELEM
72*3d8817e4Smiod #define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))
73*3d8817e4Smiod #endif
74*3d8817e4Smiod
75*3d8817e4Smiod typedef enum {bunknown, b9, b12, b23} thumb_pcrel_branchtype;
76*3d8817e4Smiod /* Some typedefs for holding instructions. */
77*3d8817e4Smiod typedef unsigned long int insn32;
78*3d8817e4Smiod typedef unsigned short int insn16;
79*3d8817e4Smiod
80*3d8817e4Smiod /* The linker script knows the section names for placement.
81*3d8817e4Smiod The entry_names are used to do simple name mangling on the stubs.
82*3d8817e4Smiod Given a function name, and its type, the stub can be found. The
83*3d8817e4Smiod name can be changed. The only requirement is the %s be present. */
84*3d8817e4Smiod
85*3d8817e4Smiod #define THUMB2ARM_GLUE_SECTION_NAME ".glue_7t"
86*3d8817e4Smiod #define THUMB2ARM_GLUE_ENTRY_NAME "__%s_from_thumb"
87*3d8817e4Smiod
88*3d8817e4Smiod #define ARM2THUMB_GLUE_SECTION_NAME ".glue_7"
89*3d8817e4Smiod #define ARM2THUMB_GLUE_ENTRY_NAME "__%s_from_arm"
90*3d8817e4Smiod
91*3d8817e4Smiod /* Used by the assembler. */
92*3d8817e4Smiod
93*3d8817e4Smiod static bfd_reloc_status_type
coff_arm_reloc(bfd * abfd,arelent * reloc_entry,asymbol * symbol ATTRIBUTE_UNUSED,void * data,asection * input_section ATTRIBUTE_UNUSED,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)94*3d8817e4Smiod coff_arm_reloc (bfd *abfd,
95*3d8817e4Smiod arelent *reloc_entry,
96*3d8817e4Smiod asymbol *symbol ATTRIBUTE_UNUSED,
97*3d8817e4Smiod void * data,
98*3d8817e4Smiod asection *input_section ATTRIBUTE_UNUSED,
99*3d8817e4Smiod bfd *output_bfd,
100*3d8817e4Smiod char **error_message ATTRIBUTE_UNUSED)
101*3d8817e4Smiod {
102*3d8817e4Smiod symvalue diff;
103*3d8817e4Smiod
104*3d8817e4Smiod if (output_bfd == NULL)
105*3d8817e4Smiod return bfd_reloc_continue;
106*3d8817e4Smiod
107*3d8817e4Smiod diff = reloc_entry->addend;
108*3d8817e4Smiod
109*3d8817e4Smiod #define DOIT(x) \
110*3d8817e4Smiod x = ((x & ~howto->dst_mask) \
111*3d8817e4Smiod | (((x & howto->src_mask) + diff) & howto->dst_mask))
112*3d8817e4Smiod
113*3d8817e4Smiod if (diff != 0)
114*3d8817e4Smiod {
115*3d8817e4Smiod reloc_howto_type *howto = reloc_entry->howto;
116*3d8817e4Smiod unsigned char *addr = (unsigned char *) data + reloc_entry->address;
117*3d8817e4Smiod
118*3d8817e4Smiod switch (howto->size)
119*3d8817e4Smiod {
120*3d8817e4Smiod case 0:
121*3d8817e4Smiod {
122*3d8817e4Smiod char x = bfd_get_8 (abfd, addr);
123*3d8817e4Smiod DOIT (x);
124*3d8817e4Smiod bfd_put_8 (abfd, x, addr);
125*3d8817e4Smiod }
126*3d8817e4Smiod break;
127*3d8817e4Smiod
128*3d8817e4Smiod case 1:
129*3d8817e4Smiod {
130*3d8817e4Smiod short x = bfd_get_16 (abfd, addr);
131*3d8817e4Smiod DOIT (x);
132*3d8817e4Smiod bfd_put_16 (abfd, (bfd_vma) x, addr);
133*3d8817e4Smiod }
134*3d8817e4Smiod break;
135*3d8817e4Smiod
136*3d8817e4Smiod case 2:
137*3d8817e4Smiod {
138*3d8817e4Smiod long x = bfd_get_32 (abfd, addr);
139*3d8817e4Smiod DOIT (x);
140*3d8817e4Smiod bfd_put_32 (abfd, (bfd_vma) x, addr);
141*3d8817e4Smiod }
142*3d8817e4Smiod break;
143*3d8817e4Smiod
144*3d8817e4Smiod default:
145*3d8817e4Smiod abort ();
146*3d8817e4Smiod }
147*3d8817e4Smiod }
148*3d8817e4Smiod
149*3d8817e4Smiod /* Now let bfd_perform_relocation finish everything up. */
150*3d8817e4Smiod return bfd_reloc_continue;
151*3d8817e4Smiod }
152*3d8817e4Smiod
153*3d8817e4Smiod /* If USER_LABEL_PREFIX is defined as "_" (see coff_arm_is_local_label_name()
154*3d8817e4Smiod in this file), then TARGET_UNDERSCORE should be defined, otherwise it
155*3d8817e4Smiod should not. */
156*3d8817e4Smiod #ifndef TARGET_UNDERSCORE
157*3d8817e4Smiod #define TARGET_UNDERSCORE '_'
158*3d8817e4Smiod #endif
159*3d8817e4Smiod
160*3d8817e4Smiod #ifndef PCRELOFFSET
161*3d8817e4Smiod #define PCRELOFFSET TRUE
162*3d8817e4Smiod #endif
163*3d8817e4Smiod
164*3d8817e4Smiod /* These most certainly belong somewhere else. Just had to get rid of
165*3d8817e4Smiod the manifest constants in the code. */
166*3d8817e4Smiod #define ARM_8 0
167*3d8817e4Smiod #define ARM_16 1
168*3d8817e4Smiod #define ARM_32 2
169*3d8817e4Smiod #define ARM_26 3
170*3d8817e4Smiod #define ARM_DISP8 4
171*3d8817e4Smiod #define ARM_DISP16 5
172*3d8817e4Smiod #define ARM_DISP32 6
173*3d8817e4Smiod #define ARM_26D 7
174*3d8817e4Smiod /* 8 is unused. */
175*3d8817e4Smiod #define ARM_NEG16 9
176*3d8817e4Smiod #define ARM_NEG32 10
177*3d8817e4Smiod #define ARM_RVA32 11
178*3d8817e4Smiod #define ARM_THUMB9 12
179*3d8817e4Smiod #define ARM_THUMB12 13
180*3d8817e4Smiod #define ARM_THUMB23 14
181*3d8817e4Smiod
182*3d8817e4Smiod #ifdef ARM_WINCE
183*3d8817e4Smiod #undef ARM_32
184*3d8817e4Smiod #undef ARM_RVA32
185*3d8817e4Smiod #undef ARM_26
186*3d8817e4Smiod #undef ARM_THUMB12
187*3d8817e4Smiod #undef ARM_26D
188*3d8817e4Smiod
189*3d8817e4Smiod #define ARM_26D 0
190*3d8817e4Smiod #define ARM_32 1
191*3d8817e4Smiod #define ARM_RVA32 2
192*3d8817e4Smiod #define ARM_26 3
193*3d8817e4Smiod #define ARM_THUMB12 4
194*3d8817e4Smiod #define ARM_SECTION 14
195*3d8817e4Smiod #define ARM_SECREL 15
196*3d8817e4Smiod #endif
197*3d8817e4Smiod
198*3d8817e4Smiod static bfd_reloc_status_type aoutarm_fix_pcrel_26_done
199*3d8817e4Smiod (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
200*3d8817e4Smiod static bfd_reloc_status_type aoutarm_fix_pcrel_26
201*3d8817e4Smiod (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
202*3d8817e4Smiod static bfd_reloc_status_type coff_thumb_pcrel_12
203*3d8817e4Smiod (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
204*3d8817e4Smiod #ifndef ARM_WINCE
205*3d8817e4Smiod static bfd_reloc_status_type coff_thumb_pcrel_9
206*3d8817e4Smiod (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
207*3d8817e4Smiod static bfd_reloc_status_type coff_thumb_pcrel_23
208*3d8817e4Smiod (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
209*3d8817e4Smiod #endif
210*3d8817e4Smiod
211*3d8817e4Smiod static reloc_howto_type aoutarm_std_reloc_howto[] =
212*3d8817e4Smiod {
213*3d8817e4Smiod #ifdef ARM_WINCE
214*3d8817e4Smiod HOWTO (ARM_26D,
215*3d8817e4Smiod 2,
216*3d8817e4Smiod 2,
217*3d8817e4Smiod 24,
218*3d8817e4Smiod TRUE,
219*3d8817e4Smiod 0,
220*3d8817e4Smiod complain_overflow_dont,
221*3d8817e4Smiod aoutarm_fix_pcrel_26_done,
222*3d8817e4Smiod "ARM_26D",
223*3d8817e4Smiod FALSE,
224*3d8817e4Smiod 0x00ffffff,
225*3d8817e4Smiod 0x0,
226*3d8817e4Smiod PCRELOFFSET),
227*3d8817e4Smiod HOWTO (ARM_32,
228*3d8817e4Smiod 0,
229*3d8817e4Smiod 2,
230*3d8817e4Smiod 32,
231*3d8817e4Smiod FALSE,
232*3d8817e4Smiod 0,
233*3d8817e4Smiod complain_overflow_bitfield,
234*3d8817e4Smiod coff_arm_reloc,
235*3d8817e4Smiod "ARM_32",
236*3d8817e4Smiod FALSE,
237*3d8817e4Smiod 0xffffffff,
238*3d8817e4Smiod 0xffffffff,
239*3d8817e4Smiod PCRELOFFSET),
240*3d8817e4Smiod HOWTO (ARM_RVA32,
241*3d8817e4Smiod 0,
242*3d8817e4Smiod 2,
243*3d8817e4Smiod 32,
244*3d8817e4Smiod FALSE,
245*3d8817e4Smiod 0,
246*3d8817e4Smiod complain_overflow_bitfield,
247*3d8817e4Smiod coff_arm_reloc,
248*3d8817e4Smiod "ARM_RVA32",
249*3d8817e4Smiod FALSE,
250*3d8817e4Smiod 0xffffffff,
251*3d8817e4Smiod 0xffffffff,
252*3d8817e4Smiod PCRELOFFSET),
253*3d8817e4Smiod HOWTO (ARM_26,
254*3d8817e4Smiod 2,
255*3d8817e4Smiod 2,
256*3d8817e4Smiod 24,
257*3d8817e4Smiod TRUE,
258*3d8817e4Smiod 0,
259*3d8817e4Smiod complain_overflow_signed,
260*3d8817e4Smiod aoutarm_fix_pcrel_26 ,
261*3d8817e4Smiod "ARM_26",
262*3d8817e4Smiod FALSE,
263*3d8817e4Smiod 0x00ffffff,
264*3d8817e4Smiod 0x00ffffff,
265*3d8817e4Smiod PCRELOFFSET),
266*3d8817e4Smiod HOWTO (ARM_THUMB12,
267*3d8817e4Smiod 1,
268*3d8817e4Smiod 1,
269*3d8817e4Smiod 11,
270*3d8817e4Smiod TRUE,
271*3d8817e4Smiod 0,
272*3d8817e4Smiod complain_overflow_signed,
273*3d8817e4Smiod coff_thumb_pcrel_12 ,
274*3d8817e4Smiod "ARM_THUMB12",
275*3d8817e4Smiod FALSE,
276*3d8817e4Smiod 0x000007ff,
277*3d8817e4Smiod 0x000007ff,
278*3d8817e4Smiod PCRELOFFSET),
279*3d8817e4Smiod EMPTY_HOWTO (-1),
280*3d8817e4Smiod EMPTY_HOWTO (-1),
281*3d8817e4Smiod EMPTY_HOWTO (-1),
282*3d8817e4Smiod EMPTY_HOWTO (-1),
283*3d8817e4Smiod EMPTY_HOWTO (-1),
284*3d8817e4Smiod EMPTY_HOWTO (-1),
285*3d8817e4Smiod EMPTY_HOWTO (-1),
286*3d8817e4Smiod EMPTY_HOWTO (-1),
287*3d8817e4Smiod EMPTY_HOWTO (-1),
288*3d8817e4Smiod HOWTO (ARM_SECTION,
289*3d8817e4Smiod 0,
290*3d8817e4Smiod 1,
291*3d8817e4Smiod 16,
292*3d8817e4Smiod FALSE,
293*3d8817e4Smiod 0,
294*3d8817e4Smiod complain_overflow_bitfield,
295*3d8817e4Smiod coff_arm_reloc,
296*3d8817e4Smiod "ARM_SECTION",
297*3d8817e4Smiod FALSE,
298*3d8817e4Smiod 0x0000ffff,
299*3d8817e4Smiod 0x0000ffff,
300*3d8817e4Smiod PCRELOFFSET),
301*3d8817e4Smiod HOWTO (ARM_SECREL,
302*3d8817e4Smiod 0,
303*3d8817e4Smiod 2,
304*3d8817e4Smiod 32,
305*3d8817e4Smiod FALSE,
306*3d8817e4Smiod 0,
307*3d8817e4Smiod complain_overflow_bitfield,
308*3d8817e4Smiod coff_arm_reloc,
309*3d8817e4Smiod "ARM_SECREL",
310*3d8817e4Smiod FALSE,
311*3d8817e4Smiod 0xffffffff,
312*3d8817e4Smiod 0xffffffff,
313*3d8817e4Smiod PCRELOFFSET),
314*3d8817e4Smiod #else /* not ARM_WINCE */
315*3d8817e4Smiod HOWTO (ARM_8,
316*3d8817e4Smiod 0,
317*3d8817e4Smiod 0,
318*3d8817e4Smiod 8,
319*3d8817e4Smiod FALSE,
320*3d8817e4Smiod 0,
321*3d8817e4Smiod complain_overflow_bitfield,
322*3d8817e4Smiod coff_arm_reloc,
323*3d8817e4Smiod "ARM_8",
324*3d8817e4Smiod TRUE,
325*3d8817e4Smiod 0x000000ff,
326*3d8817e4Smiod 0x000000ff,
327*3d8817e4Smiod PCRELOFFSET),
328*3d8817e4Smiod HOWTO (ARM_16,
329*3d8817e4Smiod 0,
330*3d8817e4Smiod 1,
331*3d8817e4Smiod 16,
332*3d8817e4Smiod FALSE,
333*3d8817e4Smiod 0,
334*3d8817e4Smiod complain_overflow_bitfield,
335*3d8817e4Smiod coff_arm_reloc,
336*3d8817e4Smiod "ARM_16",
337*3d8817e4Smiod TRUE,
338*3d8817e4Smiod 0x0000ffff,
339*3d8817e4Smiod 0x0000ffff,
340*3d8817e4Smiod PCRELOFFSET),
341*3d8817e4Smiod HOWTO (ARM_32,
342*3d8817e4Smiod 0,
343*3d8817e4Smiod 2,
344*3d8817e4Smiod 32,
345*3d8817e4Smiod FALSE,
346*3d8817e4Smiod 0,
347*3d8817e4Smiod complain_overflow_bitfield,
348*3d8817e4Smiod coff_arm_reloc,
349*3d8817e4Smiod "ARM_32",
350*3d8817e4Smiod TRUE,
351*3d8817e4Smiod 0xffffffff,
352*3d8817e4Smiod 0xffffffff,
353*3d8817e4Smiod PCRELOFFSET),
354*3d8817e4Smiod HOWTO (ARM_26,
355*3d8817e4Smiod 2,
356*3d8817e4Smiod 2,
357*3d8817e4Smiod 24,
358*3d8817e4Smiod TRUE,
359*3d8817e4Smiod 0,
360*3d8817e4Smiod complain_overflow_signed,
361*3d8817e4Smiod aoutarm_fix_pcrel_26 ,
362*3d8817e4Smiod "ARM_26",
363*3d8817e4Smiod FALSE,
364*3d8817e4Smiod 0x00ffffff,
365*3d8817e4Smiod 0x00ffffff,
366*3d8817e4Smiod PCRELOFFSET),
367*3d8817e4Smiod HOWTO (ARM_DISP8,
368*3d8817e4Smiod 0,
369*3d8817e4Smiod 0,
370*3d8817e4Smiod 8,
371*3d8817e4Smiod TRUE,
372*3d8817e4Smiod 0,
373*3d8817e4Smiod complain_overflow_signed,
374*3d8817e4Smiod coff_arm_reloc,
375*3d8817e4Smiod "ARM_DISP8",
376*3d8817e4Smiod TRUE,
377*3d8817e4Smiod 0x000000ff,
378*3d8817e4Smiod 0x000000ff,
379*3d8817e4Smiod TRUE),
380*3d8817e4Smiod HOWTO (ARM_DISP16,
381*3d8817e4Smiod 0,
382*3d8817e4Smiod 1,
383*3d8817e4Smiod 16,
384*3d8817e4Smiod TRUE,
385*3d8817e4Smiod 0,
386*3d8817e4Smiod complain_overflow_signed,
387*3d8817e4Smiod coff_arm_reloc,
388*3d8817e4Smiod "ARM_DISP16",
389*3d8817e4Smiod TRUE,
390*3d8817e4Smiod 0x0000ffff,
391*3d8817e4Smiod 0x0000ffff,
392*3d8817e4Smiod TRUE),
393*3d8817e4Smiod HOWTO (ARM_DISP32,
394*3d8817e4Smiod 0,
395*3d8817e4Smiod 2,
396*3d8817e4Smiod 32,
397*3d8817e4Smiod TRUE,
398*3d8817e4Smiod 0,
399*3d8817e4Smiod complain_overflow_signed,
400*3d8817e4Smiod coff_arm_reloc,
401*3d8817e4Smiod "ARM_DISP32",
402*3d8817e4Smiod TRUE,
403*3d8817e4Smiod 0xffffffff,
404*3d8817e4Smiod 0xffffffff,
405*3d8817e4Smiod TRUE),
406*3d8817e4Smiod HOWTO (ARM_26D,
407*3d8817e4Smiod 2,
408*3d8817e4Smiod 2,
409*3d8817e4Smiod 24,
410*3d8817e4Smiod FALSE,
411*3d8817e4Smiod 0,
412*3d8817e4Smiod complain_overflow_dont,
413*3d8817e4Smiod aoutarm_fix_pcrel_26_done,
414*3d8817e4Smiod "ARM_26D",
415*3d8817e4Smiod TRUE,
416*3d8817e4Smiod 0x00ffffff,
417*3d8817e4Smiod 0x0,
418*3d8817e4Smiod FALSE),
419*3d8817e4Smiod /* 8 is unused */
420*3d8817e4Smiod EMPTY_HOWTO (-1),
421*3d8817e4Smiod HOWTO (ARM_NEG16,
422*3d8817e4Smiod 0,
423*3d8817e4Smiod -1,
424*3d8817e4Smiod 16,
425*3d8817e4Smiod FALSE,
426*3d8817e4Smiod 0,
427*3d8817e4Smiod complain_overflow_bitfield,
428*3d8817e4Smiod coff_arm_reloc,
429*3d8817e4Smiod "ARM_NEG16",
430*3d8817e4Smiod TRUE,
431*3d8817e4Smiod 0x0000ffff,
432*3d8817e4Smiod 0x0000ffff,
433*3d8817e4Smiod FALSE),
434*3d8817e4Smiod HOWTO (ARM_NEG32,
435*3d8817e4Smiod 0,
436*3d8817e4Smiod -2,
437*3d8817e4Smiod 32,
438*3d8817e4Smiod FALSE,
439*3d8817e4Smiod 0,
440*3d8817e4Smiod complain_overflow_bitfield,
441*3d8817e4Smiod coff_arm_reloc,
442*3d8817e4Smiod "ARM_NEG32",
443*3d8817e4Smiod TRUE,
444*3d8817e4Smiod 0xffffffff,
445*3d8817e4Smiod 0xffffffff,
446*3d8817e4Smiod FALSE),
447*3d8817e4Smiod HOWTO (ARM_RVA32,
448*3d8817e4Smiod 0,
449*3d8817e4Smiod 2,
450*3d8817e4Smiod 32,
451*3d8817e4Smiod FALSE,
452*3d8817e4Smiod 0,
453*3d8817e4Smiod complain_overflow_bitfield,
454*3d8817e4Smiod coff_arm_reloc,
455*3d8817e4Smiod "ARM_RVA32",
456*3d8817e4Smiod TRUE,
457*3d8817e4Smiod 0xffffffff,
458*3d8817e4Smiod 0xffffffff,
459*3d8817e4Smiod PCRELOFFSET),
460*3d8817e4Smiod HOWTO (ARM_THUMB9,
461*3d8817e4Smiod 1,
462*3d8817e4Smiod 1,
463*3d8817e4Smiod 8,
464*3d8817e4Smiod TRUE,
465*3d8817e4Smiod 0,
466*3d8817e4Smiod complain_overflow_signed,
467*3d8817e4Smiod coff_thumb_pcrel_9 ,
468*3d8817e4Smiod "ARM_THUMB9",
469*3d8817e4Smiod FALSE,
470*3d8817e4Smiod 0x000000ff,
471*3d8817e4Smiod 0x000000ff,
472*3d8817e4Smiod PCRELOFFSET),
473*3d8817e4Smiod HOWTO (ARM_THUMB12,
474*3d8817e4Smiod 1,
475*3d8817e4Smiod 1,
476*3d8817e4Smiod 11,
477*3d8817e4Smiod TRUE,
478*3d8817e4Smiod 0,
479*3d8817e4Smiod complain_overflow_signed,
480*3d8817e4Smiod coff_thumb_pcrel_12 ,
481*3d8817e4Smiod "ARM_THUMB12",
482*3d8817e4Smiod FALSE,
483*3d8817e4Smiod 0x000007ff,
484*3d8817e4Smiod 0x000007ff,
485*3d8817e4Smiod PCRELOFFSET),
486*3d8817e4Smiod HOWTO (ARM_THUMB23,
487*3d8817e4Smiod 1,
488*3d8817e4Smiod 2,
489*3d8817e4Smiod 22,
490*3d8817e4Smiod TRUE,
491*3d8817e4Smiod 0,
492*3d8817e4Smiod complain_overflow_signed,
493*3d8817e4Smiod coff_thumb_pcrel_23 ,
494*3d8817e4Smiod "ARM_THUMB23",
495*3d8817e4Smiod FALSE,
496*3d8817e4Smiod 0x07ff07ff,
497*3d8817e4Smiod 0x07ff07ff,
498*3d8817e4Smiod PCRELOFFSET)
499*3d8817e4Smiod #endif /* not ARM_WINCE */
500*3d8817e4Smiod };
501*3d8817e4Smiod
502*3d8817e4Smiod #define NUM_RELOCS NUM_ELEM (aoutarm_std_reloc_howto)
503*3d8817e4Smiod
504*3d8817e4Smiod #ifdef COFF_WITH_PE
505*3d8817e4Smiod /* Return TRUE if this relocation should
506*3d8817e4Smiod appear in the output .reloc section. */
507*3d8817e4Smiod
508*3d8817e4Smiod static bfd_boolean
in_reloc_p(bfd * abfd ATTRIBUTE_UNUSED,reloc_howto_type * howto)509*3d8817e4Smiod in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED,
510*3d8817e4Smiod reloc_howto_type * howto)
511*3d8817e4Smiod {
512*3d8817e4Smiod return !howto->pc_relative && howto->type != ARM_RVA32;
513*3d8817e4Smiod }
514*3d8817e4Smiod #endif
515*3d8817e4Smiod
516*3d8817e4Smiod #define RTYPE2HOWTO(cache_ptr, dst) \
517*3d8817e4Smiod (cache_ptr)->howto = \
518*3d8817e4Smiod (dst)->r_type < NUM_RELOCS \
519*3d8817e4Smiod ? aoutarm_std_reloc_howto + (dst)->r_type \
520*3d8817e4Smiod : NULL
521*3d8817e4Smiod
522*3d8817e4Smiod #define coff_rtype_to_howto coff_arm_rtype_to_howto
523*3d8817e4Smiod
524*3d8817e4Smiod static reloc_howto_type *
coff_arm_rtype_to_howto(bfd * abfd ATTRIBUTE_UNUSED,asection * sec,struct internal_reloc * rel,struct coff_link_hash_entry * h ATTRIBUTE_UNUSED,struct internal_syment * sym ATTRIBUTE_UNUSED,bfd_vma * addendp)525*3d8817e4Smiod coff_arm_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
526*3d8817e4Smiod asection *sec,
527*3d8817e4Smiod struct internal_reloc *rel,
528*3d8817e4Smiod struct coff_link_hash_entry *h ATTRIBUTE_UNUSED,
529*3d8817e4Smiod struct internal_syment *sym ATTRIBUTE_UNUSED,
530*3d8817e4Smiod bfd_vma *addendp)
531*3d8817e4Smiod {
532*3d8817e4Smiod reloc_howto_type * howto;
533*3d8817e4Smiod
534*3d8817e4Smiod if (rel->r_type >= NUM_RELOCS)
535*3d8817e4Smiod return NULL;
536*3d8817e4Smiod
537*3d8817e4Smiod howto = aoutarm_std_reloc_howto + rel->r_type;
538*3d8817e4Smiod
539*3d8817e4Smiod if (rel->r_type == ARM_RVA32)
540*3d8817e4Smiod *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
541*3d8817e4Smiod
542*3d8817e4Smiod return howto;
543*3d8817e4Smiod }
544*3d8817e4Smiod
545*3d8817e4Smiod /* Used by the assembler. */
546*3d8817e4Smiod
547*3d8817e4Smiod static bfd_reloc_status_type
aoutarm_fix_pcrel_26_done(bfd * abfd ATTRIBUTE_UNUSED,arelent * reloc_entry ATTRIBUTE_UNUSED,asymbol * symbol ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED,asection * input_section ATTRIBUTE_UNUSED,bfd * output_bfd ATTRIBUTE_UNUSED,char ** error_message ATTRIBUTE_UNUSED)548*3d8817e4Smiod aoutarm_fix_pcrel_26_done (bfd *abfd ATTRIBUTE_UNUSED,
549*3d8817e4Smiod arelent *reloc_entry ATTRIBUTE_UNUSED,
550*3d8817e4Smiod asymbol *symbol ATTRIBUTE_UNUSED,
551*3d8817e4Smiod void * data ATTRIBUTE_UNUSED,
552*3d8817e4Smiod asection *input_section ATTRIBUTE_UNUSED,
553*3d8817e4Smiod bfd *output_bfd ATTRIBUTE_UNUSED,
554*3d8817e4Smiod char **error_message ATTRIBUTE_UNUSED)
555*3d8817e4Smiod {
556*3d8817e4Smiod /* This is dead simple at present. */
557*3d8817e4Smiod return bfd_reloc_ok;
558*3d8817e4Smiod }
559*3d8817e4Smiod
560*3d8817e4Smiod /* Used by the assembler. */
561*3d8817e4Smiod
562*3d8817e4Smiod static bfd_reloc_status_type
aoutarm_fix_pcrel_26(bfd * abfd,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)563*3d8817e4Smiod aoutarm_fix_pcrel_26 (bfd *abfd,
564*3d8817e4Smiod arelent *reloc_entry,
565*3d8817e4Smiod asymbol *symbol,
566*3d8817e4Smiod void * data,
567*3d8817e4Smiod asection *input_section,
568*3d8817e4Smiod bfd *output_bfd,
569*3d8817e4Smiod char **error_message ATTRIBUTE_UNUSED)
570*3d8817e4Smiod {
571*3d8817e4Smiod bfd_vma relocation;
572*3d8817e4Smiod bfd_size_type addr = reloc_entry->address;
573*3d8817e4Smiod long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
574*3d8817e4Smiod bfd_reloc_status_type flag = bfd_reloc_ok;
575*3d8817e4Smiod
576*3d8817e4Smiod /* If this is an undefined symbol, return error. */
577*3d8817e4Smiod if (symbol->section == &bfd_und_section
578*3d8817e4Smiod && (symbol->flags & BSF_WEAK) == 0)
579*3d8817e4Smiod return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
580*3d8817e4Smiod
581*3d8817e4Smiod /* If the sections are different, and we are doing a partial relocation,
582*3d8817e4Smiod just ignore it for now. */
583*3d8817e4Smiod if (symbol->section->name != input_section->name
584*3d8817e4Smiod && output_bfd != (bfd *)NULL)
585*3d8817e4Smiod return bfd_reloc_continue;
586*3d8817e4Smiod
587*3d8817e4Smiod relocation = (target & 0x00ffffff) << 2;
588*3d8817e4Smiod relocation = (relocation ^ 0x02000000) - 0x02000000; /* Sign extend. */
589*3d8817e4Smiod relocation += symbol->value;
590*3d8817e4Smiod relocation += symbol->section->output_section->vma;
591*3d8817e4Smiod relocation += symbol->section->output_offset;
592*3d8817e4Smiod relocation += reloc_entry->addend;
593*3d8817e4Smiod relocation -= input_section->output_section->vma;
594*3d8817e4Smiod relocation -= input_section->output_offset;
595*3d8817e4Smiod relocation -= addr;
596*3d8817e4Smiod
597*3d8817e4Smiod if (relocation & 3)
598*3d8817e4Smiod return bfd_reloc_overflow;
599*3d8817e4Smiod
600*3d8817e4Smiod /* Check for overflow. */
601*3d8817e4Smiod if (relocation & 0x02000000)
602*3d8817e4Smiod {
603*3d8817e4Smiod if ((relocation & ~ (bfd_vma) 0x03ffffff) != ~ (bfd_vma) 0x03ffffff)
604*3d8817e4Smiod flag = bfd_reloc_overflow;
605*3d8817e4Smiod }
606*3d8817e4Smiod else if (relocation & ~(bfd_vma) 0x03ffffff)
607*3d8817e4Smiod flag = bfd_reloc_overflow;
608*3d8817e4Smiod
609*3d8817e4Smiod target &= ~0x00ffffff;
610*3d8817e4Smiod target |= (relocation >> 2) & 0x00ffffff;
611*3d8817e4Smiod bfd_put_32 (abfd, (bfd_vma) target, (bfd_byte *) data + addr);
612*3d8817e4Smiod
613*3d8817e4Smiod /* Now the ARM magic... Change the reloc type so that it is marked as done.
614*3d8817e4Smiod Strictly this is only necessary if we are doing a partial relocation. */
615*3d8817e4Smiod reloc_entry->howto = &aoutarm_std_reloc_howto[ARM_26D];
616*3d8817e4Smiod
617*3d8817e4Smiod return flag;
618*3d8817e4Smiod }
619*3d8817e4Smiod
620*3d8817e4Smiod static bfd_reloc_status_type
coff_thumb_pcrel_common(bfd * abfd,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED,thumb_pcrel_branchtype btype)621*3d8817e4Smiod coff_thumb_pcrel_common (bfd *abfd,
622*3d8817e4Smiod arelent *reloc_entry,
623*3d8817e4Smiod asymbol *symbol,
624*3d8817e4Smiod void * data,
625*3d8817e4Smiod asection *input_section,
626*3d8817e4Smiod bfd *output_bfd,
627*3d8817e4Smiod char **error_message ATTRIBUTE_UNUSED,
628*3d8817e4Smiod thumb_pcrel_branchtype btype)
629*3d8817e4Smiod {
630*3d8817e4Smiod bfd_vma relocation = 0;
631*3d8817e4Smiod bfd_size_type addr = reloc_entry->address;
632*3d8817e4Smiod long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
633*3d8817e4Smiod bfd_reloc_status_type flag = bfd_reloc_ok;
634*3d8817e4Smiod bfd_vma dstmsk;
635*3d8817e4Smiod bfd_vma offmsk;
636*3d8817e4Smiod bfd_vma signbit;
637*3d8817e4Smiod
638*3d8817e4Smiod /* NOTE: This routine is currently used by GAS, but not by the link
639*3d8817e4Smiod phase. */
640*3d8817e4Smiod switch (btype)
641*3d8817e4Smiod {
642*3d8817e4Smiod case b9:
643*3d8817e4Smiod dstmsk = 0x000000ff;
644*3d8817e4Smiod offmsk = 0x000001fe;
645*3d8817e4Smiod signbit = 0x00000100;
646*3d8817e4Smiod break;
647*3d8817e4Smiod
648*3d8817e4Smiod case b12:
649*3d8817e4Smiod dstmsk = 0x000007ff;
650*3d8817e4Smiod offmsk = 0x00000ffe;
651*3d8817e4Smiod signbit = 0x00000800;
652*3d8817e4Smiod break;
653*3d8817e4Smiod
654*3d8817e4Smiod case b23:
655*3d8817e4Smiod dstmsk = 0x07ff07ff;
656*3d8817e4Smiod offmsk = 0x007fffff;
657*3d8817e4Smiod signbit = 0x00400000;
658*3d8817e4Smiod break;
659*3d8817e4Smiod
660*3d8817e4Smiod default:
661*3d8817e4Smiod abort ();
662*3d8817e4Smiod }
663*3d8817e4Smiod
664*3d8817e4Smiod /* If this is an undefined symbol, return error. */
665*3d8817e4Smiod if (symbol->section == &bfd_und_section
666*3d8817e4Smiod && (symbol->flags & BSF_WEAK) == 0)
667*3d8817e4Smiod return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
668*3d8817e4Smiod
669*3d8817e4Smiod /* If the sections are different, and we are doing a partial relocation,
670*3d8817e4Smiod just ignore it for now. */
671*3d8817e4Smiod if (symbol->section->name != input_section->name
672*3d8817e4Smiod && output_bfd != (bfd *)NULL)
673*3d8817e4Smiod return bfd_reloc_continue;
674*3d8817e4Smiod
675*3d8817e4Smiod switch (btype)
676*3d8817e4Smiod {
677*3d8817e4Smiod case b9:
678*3d8817e4Smiod case b12:
679*3d8817e4Smiod relocation = ((target & dstmsk) << 1);
680*3d8817e4Smiod break;
681*3d8817e4Smiod
682*3d8817e4Smiod case b23:
683*3d8817e4Smiod if (bfd_big_endian (abfd))
684*3d8817e4Smiod relocation = ((target & 0x7ff) << 1) | ((target & 0x07ff0000) >> 4);
685*3d8817e4Smiod else
686*3d8817e4Smiod relocation = ((target & 0x7ff) << 12) | ((target & 0x07ff0000) >> 15);
687*3d8817e4Smiod break;
688*3d8817e4Smiod
689*3d8817e4Smiod default:
690*3d8817e4Smiod abort ();
691*3d8817e4Smiod }
692*3d8817e4Smiod
693*3d8817e4Smiod relocation = (relocation ^ signbit) - signbit; /* Sign extend. */
694*3d8817e4Smiod relocation += symbol->value;
695*3d8817e4Smiod relocation += symbol->section->output_section->vma;
696*3d8817e4Smiod relocation += symbol->section->output_offset;
697*3d8817e4Smiod relocation += reloc_entry->addend;
698*3d8817e4Smiod relocation -= input_section->output_section->vma;
699*3d8817e4Smiod relocation -= input_section->output_offset;
700*3d8817e4Smiod relocation -= addr;
701*3d8817e4Smiod
702*3d8817e4Smiod if (relocation & 1)
703*3d8817e4Smiod return bfd_reloc_overflow;
704*3d8817e4Smiod
705*3d8817e4Smiod /* Check for overflow. */
706*3d8817e4Smiod if (relocation & signbit)
707*3d8817e4Smiod {
708*3d8817e4Smiod if ((relocation & ~offmsk) != ~offmsk)
709*3d8817e4Smiod flag = bfd_reloc_overflow;
710*3d8817e4Smiod }
711*3d8817e4Smiod else if (relocation & ~offmsk)
712*3d8817e4Smiod flag = bfd_reloc_overflow;
713*3d8817e4Smiod
714*3d8817e4Smiod target &= ~dstmsk;
715*3d8817e4Smiod switch (btype)
716*3d8817e4Smiod {
717*3d8817e4Smiod case b9:
718*3d8817e4Smiod case b12:
719*3d8817e4Smiod target |= (relocation >> 1);
720*3d8817e4Smiod break;
721*3d8817e4Smiod
722*3d8817e4Smiod case b23:
723*3d8817e4Smiod if (bfd_big_endian (abfd))
724*3d8817e4Smiod target |= (((relocation & 0xfff) >> 1)
725*3d8817e4Smiod | ((relocation << 4) & 0x07ff0000));
726*3d8817e4Smiod else
727*3d8817e4Smiod target |= (((relocation & 0xffe) << 15)
728*3d8817e4Smiod | ((relocation >> 12) & 0x7ff));
729*3d8817e4Smiod break;
730*3d8817e4Smiod
731*3d8817e4Smiod default:
732*3d8817e4Smiod abort ();
733*3d8817e4Smiod }
734*3d8817e4Smiod
735*3d8817e4Smiod bfd_put_32 (abfd, (bfd_vma) target, (bfd_byte *) data + addr);
736*3d8817e4Smiod
737*3d8817e4Smiod /* Now the ARM magic... Change the reloc type so that it is marked as done.
738*3d8817e4Smiod Strictly this is only necessary if we are doing a partial relocation. */
739*3d8817e4Smiod reloc_entry->howto = & aoutarm_std_reloc_howto [ARM_26D];
740*3d8817e4Smiod
741*3d8817e4Smiod /* TODO: We should possibly have DONE entries for the THUMB PCREL relocations. */
742*3d8817e4Smiod return flag;
743*3d8817e4Smiod }
744*3d8817e4Smiod
745*3d8817e4Smiod #ifndef ARM_WINCE
746*3d8817e4Smiod static bfd_reloc_status_type
coff_thumb_pcrel_23(bfd * abfd,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section,bfd * output_bfd,char ** error_message)747*3d8817e4Smiod coff_thumb_pcrel_23 (bfd *abfd,
748*3d8817e4Smiod arelent *reloc_entry,
749*3d8817e4Smiod asymbol *symbol,
750*3d8817e4Smiod void * data,
751*3d8817e4Smiod asection *input_section,
752*3d8817e4Smiod bfd *output_bfd,
753*3d8817e4Smiod char **error_message)
754*3d8817e4Smiod {
755*3d8817e4Smiod return coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data,
756*3d8817e4Smiod input_section, output_bfd, error_message,
757*3d8817e4Smiod b23);
758*3d8817e4Smiod }
759*3d8817e4Smiod
760*3d8817e4Smiod static bfd_reloc_status_type
coff_thumb_pcrel_9(bfd * abfd,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section,bfd * output_bfd,char ** error_message)761*3d8817e4Smiod coff_thumb_pcrel_9 (bfd *abfd,
762*3d8817e4Smiod arelent *reloc_entry,
763*3d8817e4Smiod asymbol *symbol,
764*3d8817e4Smiod void * data,
765*3d8817e4Smiod asection *input_section,
766*3d8817e4Smiod bfd *output_bfd,
767*3d8817e4Smiod char **error_message)
768*3d8817e4Smiod {
769*3d8817e4Smiod return coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data,
770*3d8817e4Smiod input_section, output_bfd, error_message,
771*3d8817e4Smiod b9);
772*3d8817e4Smiod }
773*3d8817e4Smiod #endif /* not ARM_WINCE */
774*3d8817e4Smiod
775*3d8817e4Smiod static bfd_reloc_status_type
coff_thumb_pcrel_12(bfd * abfd,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section,bfd * output_bfd,char ** error_message)776*3d8817e4Smiod coff_thumb_pcrel_12 (bfd *abfd,
777*3d8817e4Smiod arelent *reloc_entry,
778*3d8817e4Smiod asymbol *symbol,
779*3d8817e4Smiod void * data,
780*3d8817e4Smiod asection *input_section,
781*3d8817e4Smiod bfd *output_bfd,
782*3d8817e4Smiod char **error_message)
783*3d8817e4Smiod {
784*3d8817e4Smiod return coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data,
785*3d8817e4Smiod input_section, output_bfd, error_message,
786*3d8817e4Smiod b12);
787*3d8817e4Smiod }
788*3d8817e4Smiod
789*3d8817e4Smiod static const struct reloc_howto_struct *
coff_arm_reloc_type_lookup(bfd * abfd,bfd_reloc_code_real_type code)790*3d8817e4Smiod coff_arm_reloc_type_lookup (bfd * abfd, bfd_reloc_code_real_type code)
791*3d8817e4Smiod {
792*3d8817e4Smiod #define ASTD(i,j) case i: return aoutarm_std_reloc_howto + j
793*3d8817e4Smiod
794*3d8817e4Smiod if (code == BFD_RELOC_CTOR)
795*3d8817e4Smiod switch (bfd_get_arch_info (abfd)->bits_per_address)
796*3d8817e4Smiod {
797*3d8817e4Smiod case 32:
798*3d8817e4Smiod code = BFD_RELOC_32;
799*3d8817e4Smiod break;
800*3d8817e4Smiod default:
801*3d8817e4Smiod return NULL;
802*3d8817e4Smiod }
803*3d8817e4Smiod
804*3d8817e4Smiod switch (code)
805*3d8817e4Smiod {
806*3d8817e4Smiod #ifdef ARM_WINCE
807*3d8817e4Smiod ASTD (BFD_RELOC_32, ARM_32);
808*3d8817e4Smiod ASTD (BFD_RELOC_RVA, ARM_RVA32);
809*3d8817e4Smiod ASTD (BFD_RELOC_ARM_PCREL_BRANCH, ARM_26);
810*3d8817e4Smiod ASTD (BFD_RELOC_THUMB_PCREL_BRANCH12, ARM_THUMB12);
811*3d8817e4Smiod #else
812*3d8817e4Smiod ASTD (BFD_RELOC_8, ARM_8);
813*3d8817e4Smiod ASTD (BFD_RELOC_16, ARM_16);
814*3d8817e4Smiod ASTD (BFD_RELOC_32, ARM_32);
815*3d8817e4Smiod ASTD (BFD_RELOC_ARM_PCREL_BRANCH, ARM_26);
816*3d8817e4Smiod ASTD (BFD_RELOC_ARM_PCREL_BLX, ARM_26);
817*3d8817e4Smiod ASTD (BFD_RELOC_8_PCREL, ARM_DISP8);
818*3d8817e4Smiod ASTD (BFD_RELOC_16_PCREL, ARM_DISP16);
819*3d8817e4Smiod ASTD (BFD_RELOC_32_PCREL, ARM_DISP32);
820*3d8817e4Smiod ASTD (BFD_RELOC_RVA, ARM_RVA32);
821*3d8817e4Smiod ASTD (BFD_RELOC_THUMB_PCREL_BRANCH9, ARM_THUMB9);
822*3d8817e4Smiod ASTD (BFD_RELOC_THUMB_PCREL_BRANCH12, ARM_THUMB12);
823*3d8817e4Smiod ASTD (BFD_RELOC_THUMB_PCREL_BRANCH23, ARM_THUMB23);
824*3d8817e4Smiod ASTD (BFD_RELOC_THUMB_PCREL_BLX, ARM_THUMB23);
825*3d8817e4Smiod #endif
826*3d8817e4Smiod default: return NULL;
827*3d8817e4Smiod }
828*3d8817e4Smiod }
829*3d8817e4Smiod
830*3d8817e4Smiod #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
831*3d8817e4Smiod #define COFF_PAGE_SIZE 0x1000
832*3d8817e4Smiod
833*3d8817e4Smiod /* Turn a howto into a reloc nunmber. */
834*3d8817e4Smiod #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
835*3d8817e4Smiod #define BADMAG(x) ARMBADMAG(x)
836*3d8817e4Smiod #define ARM 1 /* Customize coffcode.h. */
837*3d8817e4Smiod
838*3d8817e4Smiod #ifndef ARM_WINCE
839*3d8817e4Smiod /* Make sure that the 'r_offset' field is copied properly
840*3d8817e4Smiod so that identical binaries will compare the same. */
841*3d8817e4Smiod #define SWAP_IN_RELOC_OFFSET H_GET_32
842*3d8817e4Smiod #define SWAP_OUT_RELOC_OFFSET H_PUT_32
843*3d8817e4Smiod #endif
844*3d8817e4Smiod
845*3d8817e4Smiod /* Extend the coff_link_hash_table structure with a few ARM specific fields.
846*3d8817e4Smiod This allows us to store global data here without actually creating any
847*3d8817e4Smiod global variables, which is a no-no in the BFD world. */
848*3d8817e4Smiod struct coff_arm_link_hash_table
849*3d8817e4Smiod {
850*3d8817e4Smiod /* The original coff_link_hash_table structure. MUST be first field. */
851*3d8817e4Smiod struct coff_link_hash_table root;
852*3d8817e4Smiod
853*3d8817e4Smiod /* The size in bytes of the section containing the Thumb-to-ARM glue. */
854*3d8817e4Smiod bfd_size_type thumb_glue_size;
855*3d8817e4Smiod
856*3d8817e4Smiod /* The size in bytes of the section containing the ARM-to-Thumb glue. */
857*3d8817e4Smiod bfd_size_type arm_glue_size;
858*3d8817e4Smiod
859*3d8817e4Smiod /* An arbitrary input BFD chosen to hold the glue sections. */
860*3d8817e4Smiod bfd * bfd_of_glue_owner;
861*3d8817e4Smiod
862*3d8817e4Smiod /* Support interworking with old, non-interworking aware ARM code. */
863*3d8817e4Smiod int support_old_code;
864*3d8817e4Smiod };
865*3d8817e4Smiod
866*3d8817e4Smiod /* Get the ARM coff linker hash table from a link_info structure. */
867*3d8817e4Smiod #define coff_arm_hash_table(info) \
868*3d8817e4Smiod ((struct coff_arm_link_hash_table *) ((info)->hash))
869*3d8817e4Smiod
870*3d8817e4Smiod /* Create an ARM coff linker hash table. */
871*3d8817e4Smiod
872*3d8817e4Smiod static struct bfd_link_hash_table *
coff_arm_link_hash_table_create(bfd * abfd)873*3d8817e4Smiod coff_arm_link_hash_table_create (bfd * abfd)
874*3d8817e4Smiod {
875*3d8817e4Smiod struct coff_arm_link_hash_table * ret;
876*3d8817e4Smiod bfd_size_type amt = sizeof (struct coff_arm_link_hash_table);
877*3d8817e4Smiod
878*3d8817e4Smiod ret = bfd_malloc (amt);
879*3d8817e4Smiod if (ret == NULL)
880*3d8817e4Smiod return NULL;
881*3d8817e4Smiod
882*3d8817e4Smiod if (!_bfd_coff_link_hash_table_init (&ret->root,
883*3d8817e4Smiod abfd,
884*3d8817e4Smiod _bfd_coff_link_hash_newfunc,
885*3d8817e4Smiod sizeof (struct coff_link_hash_entry)))
886*3d8817e4Smiod {
887*3d8817e4Smiod free (ret);
888*3d8817e4Smiod return NULL;
889*3d8817e4Smiod }
890*3d8817e4Smiod
891*3d8817e4Smiod ret->thumb_glue_size = 0;
892*3d8817e4Smiod ret->arm_glue_size = 0;
893*3d8817e4Smiod ret->bfd_of_glue_owner = NULL;
894*3d8817e4Smiod
895*3d8817e4Smiod return & ret->root.root;
896*3d8817e4Smiod }
897*3d8817e4Smiod
898*3d8817e4Smiod static void
arm_emit_base_file_entry(struct bfd_link_info * info,bfd * output_bfd,asection * input_section,bfd_vma reloc_offset)899*3d8817e4Smiod arm_emit_base_file_entry (struct bfd_link_info *info,
900*3d8817e4Smiod bfd *output_bfd,
901*3d8817e4Smiod asection *input_section,
902*3d8817e4Smiod bfd_vma reloc_offset)
903*3d8817e4Smiod {
904*3d8817e4Smiod bfd_vma addr = reloc_offset
905*3d8817e4Smiod - input_section->vma
906*3d8817e4Smiod + input_section->output_offset
907*3d8817e4Smiod + input_section->output_section->vma;
908*3d8817e4Smiod
909*3d8817e4Smiod if (coff_data (output_bfd)->pe)
910*3d8817e4Smiod addr -= pe_data (output_bfd)->pe_opthdr.ImageBase;
911*3d8817e4Smiod fwrite (& addr, 1, sizeof (addr), (FILE *) info->base_file);
912*3d8817e4Smiod
913*3d8817e4Smiod }
914*3d8817e4Smiod
915*3d8817e4Smiod #ifndef ARM_WINCE
916*3d8817e4Smiod /* The thumb form of a long branch is a bit finicky, because the offset
917*3d8817e4Smiod encoding is split over two fields, each in it's own instruction. They
918*3d8817e4Smiod can occur in any order. So given a thumb form of long branch, and an
919*3d8817e4Smiod offset, insert the offset into the thumb branch and return finished
920*3d8817e4Smiod instruction.
921*3d8817e4Smiod
922*3d8817e4Smiod It takes two thumb instructions to encode the target address. Each has
923*3d8817e4Smiod 11 bits to invest. The upper 11 bits are stored in one (identified by
924*3d8817e4Smiod H-0.. see below), the lower 11 bits are stored in the other (identified
925*3d8817e4Smiod by H-1).
926*3d8817e4Smiod
927*3d8817e4Smiod Combine together and shifted left by 1 (it's a half word address) and
928*3d8817e4Smiod there you have it.
929*3d8817e4Smiod
930*3d8817e4Smiod Op: 1111 = F,
931*3d8817e4Smiod H-0, upper address-0 = 000
932*3d8817e4Smiod Op: 1111 = F,
933*3d8817e4Smiod H-1, lower address-0 = 800
934*3d8817e4Smiod
935*3d8817e4Smiod They can be ordered either way, but the arm tools I've seen always put
936*3d8817e4Smiod the lower one first. It probably doesn't matter. krk@cygnus.com
937*3d8817e4Smiod
938*3d8817e4Smiod XXX: Actually the order does matter. The second instruction (H-1)
939*3d8817e4Smiod moves the computed address into the PC, so it must be the second one
940*3d8817e4Smiod in the sequence. The problem, however is that whilst little endian code
941*3d8817e4Smiod stores the instructions in HI then LOW order, big endian code does the
942*3d8817e4Smiod reverse. nickc@cygnus.com. */
943*3d8817e4Smiod
944*3d8817e4Smiod #define LOW_HI_ORDER 0xF800F000
945*3d8817e4Smiod #define HI_LOW_ORDER 0xF000F800
946*3d8817e4Smiod
947*3d8817e4Smiod static insn32
insert_thumb_branch(insn32 br_insn,int rel_off)948*3d8817e4Smiod insert_thumb_branch (insn32 br_insn, int rel_off)
949*3d8817e4Smiod {
950*3d8817e4Smiod unsigned int low_bits;
951*3d8817e4Smiod unsigned int high_bits;
952*3d8817e4Smiod
953*3d8817e4Smiod BFD_ASSERT ((rel_off & 1) != 1);
954*3d8817e4Smiod
955*3d8817e4Smiod rel_off >>= 1; /* Half word aligned address. */
956*3d8817e4Smiod low_bits = rel_off & 0x000007FF; /* The bottom 11 bits. */
957*3d8817e4Smiod high_bits = (rel_off >> 11) & 0x000007FF; /* The top 11 bits. */
958*3d8817e4Smiod
959*3d8817e4Smiod if ((br_insn & LOW_HI_ORDER) == LOW_HI_ORDER)
960*3d8817e4Smiod br_insn = LOW_HI_ORDER | (low_bits << 16) | high_bits;
961*3d8817e4Smiod else if ((br_insn & HI_LOW_ORDER) == HI_LOW_ORDER)
962*3d8817e4Smiod br_insn = HI_LOW_ORDER | (high_bits << 16) | low_bits;
963*3d8817e4Smiod else
964*3d8817e4Smiod /* FIXME: the BFD library should never abort except for internal errors
965*3d8817e4Smiod - it should return an error status. */
966*3d8817e4Smiod abort (); /* Error - not a valid branch instruction form. */
967*3d8817e4Smiod
968*3d8817e4Smiod return br_insn;
969*3d8817e4Smiod }
970*3d8817e4Smiod
971*3d8817e4Smiod
972*3d8817e4Smiod static struct coff_link_hash_entry *
find_thumb_glue(struct bfd_link_info * info,const char * name,bfd * input_bfd)973*3d8817e4Smiod find_thumb_glue (struct bfd_link_info *info,
974*3d8817e4Smiod const char *name,
975*3d8817e4Smiod bfd *input_bfd)
976*3d8817e4Smiod {
977*3d8817e4Smiod char *tmp_name;
978*3d8817e4Smiod struct coff_link_hash_entry *myh;
979*3d8817e4Smiod bfd_size_type amt = strlen (name) + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1;
980*3d8817e4Smiod
981*3d8817e4Smiod tmp_name = bfd_malloc (amt);
982*3d8817e4Smiod
983*3d8817e4Smiod BFD_ASSERT (tmp_name);
984*3d8817e4Smiod
985*3d8817e4Smiod sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name);
986*3d8817e4Smiod
987*3d8817e4Smiod myh = coff_link_hash_lookup
988*3d8817e4Smiod (coff_hash_table (info), tmp_name, FALSE, FALSE, TRUE);
989*3d8817e4Smiod
990*3d8817e4Smiod if (myh == NULL)
991*3d8817e4Smiod /* xgettext:c-format */
992*3d8817e4Smiod _bfd_error_handler (_("%B: unable to find THUMB glue '%s' for `%s'"),
993*3d8817e4Smiod input_bfd, tmp_name, name);
994*3d8817e4Smiod
995*3d8817e4Smiod free (tmp_name);
996*3d8817e4Smiod
997*3d8817e4Smiod return myh;
998*3d8817e4Smiod }
999*3d8817e4Smiod #endif /* not ARM_WINCE */
1000*3d8817e4Smiod
1001*3d8817e4Smiod static struct coff_link_hash_entry *
find_arm_glue(struct bfd_link_info * info,const char * name,bfd * input_bfd)1002*3d8817e4Smiod find_arm_glue (struct bfd_link_info *info,
1003*3d8817e4Smiod const char *name,
1004*3d8817e4Smiod bfd *input_bfd)
1005*3d8817e4Smiod {
1006*3d8817e4Smiod char *tmp_name;
1007*3d8817e4Smiod struct coff_link_hash_entry * myh;
1008*3d8817e4Smiod bfd_size_type amt = strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1;
1009*3d8817e4Smiod
1010*3d8817e4Smiod tmp_name = bfd_malloc (amt);
1011*3d8817e4Smiod
1012*3d8817e4Smiod BFD_ASSERT (tmp_name);
1013*3d8817e4Smiod
1014*3d8817e4Smiod sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);
1015*3d8817e4Smiod
1016*3d8817e4Smiod myh = coff_link_hash_lookup
1017*3d8817e4Smiod (coff_hash_table (info), tmp_name, FALSE, FALSE, TRUE);
1018*3d8817e4Smiod
1019*3d8817e4Smiod if (myh == NULL)
1020*3d8817e4Smiod /* xgettext:c-format */
1021*3d8817e4Smiod _bfd_error_handler (_("%B: unable to find ARM glue '%s' for `%s'"),
1022*3d8817e4Smiod input_bfd, tmp_name, name);
1023*3d8817e4Smiod
1024*3d8817e4Smiod free (tmp_name);
1025*3d8817e4Smiod
1026*3d8817e4Smiod return myh;
1027*3d8817e4Smiod }
1028*3d8817e4Smiod
1029*3d8817e4Smiod /*
1030*3d8817e4Smiod ARM->Thumb glue:
1031*3d8817e4Smiod
1032*3d8817e4Smiod .arm
1033*3d8817e4Smiod __func_from_arm:
1034*3d8817e4Smiod ldr r12, __func_addr
1035*3d8817e4Smiod bx r12
1036*3d8817e4Smiod __func_addr:
1037*3d8817e4Smiod .word func @ behave as if you saw a ARM_32 reloc
1038*3d8817e4Smiod */
1039*3d8817e4Smiod
1040*3d8817e4Smiod #define ARM2THUMB_GLUE_SIZE 12
1041*3d8817e4Smiod static const insn32 a2t1_ldr_insn = 0xe59fc000;
1042*3d8817e4Smiod static const insn32 a2t2_bx_r12_insn = 0xe12fff1c;
1043*3d8817e4Smiod static const insn32 a2t3_func_addr_insn = 0x00000001;
1044*3d8817e4Smiod
1045*3d8817e4Smiod /*
1046*3d8817e4Smiod Thumb->ARM: Thumb->(non-interworking aware) ARM
1047*3d8817e4Smiod
1048*3d8817e4Smiod .thumb .thumb
1049*3d8817e4Smiod .align 2 .align 2
1050*3d8817e4Smiod __func_from_thumb: __func_from_thumb:
1051*3d8817e4Smiod bx pc push {r6, lr}
1052*3d8817e4Smiod nop ldr r6, __func_addr
1053*3d8817e4Smiod .arm mov lr, pc
1054*3d8817e4Smiod __func_change_to_arm: bx r6
1055*3d8817e4Smiod b func .arm
1056*3d8817e4Smiod __func_back_to_thumb:
1057*3d8817e4Smiod ldmia r13! {r6, lr}
1058*3d8817e4Smiod bx lr
1059*3d8817e4Smiod __func_addr:
1060*3d8817e4Smiod .word func
1061*3d8817e4Smiod */
1062*3d8817e4Smiod
1063*3d8817e4Smiod #define THUMB2ARM_GLUE_SIZE (globals->support_old_code ? 20 : 8)
1064*3d8817e4Smiod #ifndef ARM_WINCE
1065*3d8817e4Smiod static const insn16 t2a1_bx_pc_insn = 0x4778;
1066*3d8817e4Smiod static const insn16 t2a2_noop_insn = 0x46c0;
1067*3d8817e4Smiod static const insn32 t2a3_b_insn = 0xea000000;
1068*3d8817e4Smiod
1069*3d8817e4Smiod static const insn16 t2a1_push_insn = 0xb540;
1070*3d8817e4Smiod static const insn16 t2a2_ldr_insn = 0x4e03;
1071*3d8817e4Smiod static const insn16 t2a3_mov_insn = 0x46fe;
1072*3d8817e4Smiod static const insn16 t2a4_bx_insn = 0x4730;
1073*3d8817e4Smiod static const insn32 t2a5_pop_insn = 0xe8bd4040;
1074*3d8817e4Smiod static const insn32 t2a6_bx_insn = 0xe12fff1e;
1075*3d8817e4Smiod #endif
1076*3d8817e4Smiod
1077*3d8817e4Smiod /* TODO:
1078*3d8817e4Smiod We should really create new local (static) symbols in destination
1079*3d8817e4Smiod object for each stub we create. We should also create local
1080*3d8817e4Smiod (static) symbols within the stubs when switching between ARM and
1081*3d8817e4Smiod Thumb code. This will ensure that the debugger and disassembler
1082*3d8817e4Smiod can present a better view of stubs.
1083*3d8817e4Smiod
1084*3d8817e4Smiod We can treat stubs like literal sections, and for the THUMB9 ones
1085*3d8817e4Smiod (short addressing range) we should be able to insert the stubs
1086*3d8817e4Smiod between sections. i.e. the simplest approach (since relocations
1087*3d8817e4Smiod are done on a section basis) is to dump the stubs at the end of
1088*3d8817e4Smiod processing a section. That way we can always try and minimise the
1089*3d8817e4Smiod offset to and from a stub. However, this does not map well onto
1090*3d8817e4Smiod the way that the linker/BFD does its work: mapping all input
1091*3d8817e4Smiod sections to output sections via the linker script before doing
1092*3d8817e4Smiod all the processing.
1093*3d8817e4Smiod
1094*3d8817e4Smiod Unfortunately it may be easier to just to disallow short range
1095*3d8817e4Smiod Thumb->ARM stubs (i.e. no conditional inter-working branches,
1096*3d8817e4Smiod only branch-and-link (BL) calls. This will simplify the processing
1097*3d8817e4Smiod since we can then put all of the stubs into their own section.
1098*3d8817e4Smiod
1099*3d8817e4Smiod TODO:
1100*3d8817e4Smiod On a different subject, rather than complaining when a
1101*3d8817e4Smiod branch cannot fit in the number of bits available for the
1102*3d8817e4Smiod instruction we should generate a trampoline stub (needed to
1103*3d8817e4Smiod address the complete 32bit address space). */
1104*3d8817e4Smiod
1105*3d8817e4Smiod /* The standard COFF backend linker does not cope with the special
1106*3d8817e4Smiod Thumb BRANCH23 relocation. The alternative would be to split the
1107*3d8817e4Smiod BRANCH23 into seperate HI23 and LO23 relocations. However, it is a
1108*3d8817e4Smiod bit simpler simply providing our own relocation driver. */
1109*3d8817e4Smiod
1110*3d8817e4Smiod /* The reloc processing routine for the ARM/Thumb COFF linker. NOTE:
1111*3d8817e4Smiod This code is a very slightly modified copy of
1112*3d8817e4Smiod _bfd_coff_generic_relocate_section. It would be a much more
1113*3d8817e4Smiod maintainable solution to have a MACRO that could be expanded within
1114*3d8817e4Smiod _bfd_coff_generic_relocate_section that would only be provided for
1115*3d8817e4Smiod ARM/Thumb builds. It is only the code marked THUMBEXTENSION that
1116*3d8817e4Smiod is different from the original. */
1117*3d8817e4Smiod
1118*3d8817e4Smiod static bfd_boolean
coff_arm_relocate_section(bfd * output_bfd,struct bfd_link_info * info,bfd * input_bfd,asection * input_section,bfd_byte * contents,struct internal_reloc * relocs,struct internal_syment * syms,asection ** sections)1119*3d8817e4Smiod coff_arm_relocate_section (bfd *output_bfd,
1120*3d8817e4Smiod struct bfd_link_info *info,
1121*3d8817e4Smiod bfd *input_bfd,
1122*3d8817e4Smiod asection *input_section,
1123*3d8817e4Smiod bfd_byte *contents,
1124*3d8817e4Smiod struct internal_reloc *relocs,
1125*3d8817e4Smiod struct internal_syment *syms,
1126*3d8817e4Smiod asection **sections)
1127*3d8817e4Smiod {
1128*3d8817e4Smiod struct internal_reloc * rel;
1129*3d8817e4Smiod struct internal_reloc * relend;
1130*3d8817e4Smiod #ifndef ARM_WINCE
1131*3d8817e4Smiod bfd_vma high_address = bfd_get_section_limit (input_bfd, input_section);
1132*3d8817e4Smiod #endif
1133*3d8817e4Smiod
1134*3d8817e4Smiod rel = relocs;
1135*3d8817e4Smiod relend = rel + input_section->reloc_count;
1136*3d8817e4Smiod
1137*3d8817e4Smiod for (; rel < relend; rel++)
1138*3d8817e4Smiod {
1139*3d8817e4Smiod int done = 0;
1140*3d8817e4Smiod long symndx;
1141*3d8817e4Smiod struct coff_link_hash_entry * h;
1142*3d8817e4Smiod struct internal_syment * sym;
1143*3d8817e4Smiod bfd_vma addend;
1144*3d8817e4Smiod bfd_vma val;
1145*3d8817e4Smiod reloc_howto_type * howto;
1146*3d8817e4Smiod bfd_reloc_status_type rstat;
1147*3d8817e4Smiod bfd_vma h_val;
1148*3d8817e4Smiod
1149*3d8817e4Smiod symndx = rel->r_symndx;
1150*3d8817e4Smiod
1151*3d8817e4Smiod if (symndx == -1)
1152*3d8817e4Smiod {
1153*3d8817e4Smiod h = NULL;
1154*3d8817e4Smiod sym = NULL;
1155*3d8817e4Smiod }
1156*3d8817e4Smiod else
1157*3d8817e4Smiod {
1158*3d8817e4Smiod h = obj_coff_sym_hashes (input_bfd)[symndx];
1159*3d8817e4Smiod sym = syms + symndx;
1160*3d8817e4Smiod }
1161*3d8817e4Smiod
1162*3d8817e4Smiod /* COFF treats common symbols in one of two ways. Either the
1163*3d8817e4Smiod size of the symbol is included in the section contents, or it
1164*3d8817e4Smiod is not. We assume that the size is not included, and force
1165*3d8817e4Smiod the rtype_to_howto function to adjust the addend as needed. */
1166*3d8817e4Smiod
1167*3d8817e4Smiod if (sym != NULL && sym->n_scnum != 0)
1168*3d8817e4Smiod addend = - sym->n_value;
1169*3d8817e4Smiod else
1170*3d8817e4Smiod addend = 0;
1171*3d8817e4Smiod
1172*3d8817e4Smiod howto = coff_rtype_to_howto (input_bfd, input_section, rel, h,
1173*3d8817e4Smiod sym, &addend);
1174*3d8817e4Smiod if (howto == NULL)
1175*3d8817e4Smiod return FALSE;
1176*3d8817e4Smiod
1177*3d8817e4Smiod /* The relocation_section function will skip pcrel_offset relocs
1178*3d8817e4Smiod when doing a relocatable link. However, we want to convert
1179*3d8817e4Smiod ARM_26 to ARM_26D relocs if possible. We return a fake howto in
1180*3d8817e4Smiod this case without pcrel_offset set, and adjust the addend to
1181*3d8817e4Smiod compensate. 'partial_inplace' is also set, since we want 'done'
1182*3d8817e4Smiod relocations to be reflected in section's data. */
1183*3d8817e4Smiod if (rel->r_type == ARM_26
1184*3d8817e4Smiod && h != NULL
1185*3d8817e4Smiod && info->relocatable
1186*3d8817e4Smiod && (h->root.type == bfd_link_hash_defined
1187*3d8817e4Smiod || h->root.type == bfd_link_hash_defweak)
1188*3d8817e4Smiod && (h->root.u.def.section->output_section
1189*3d8817e4Smiod == input_section->output_section))
1190*3d8817e4Smiod {
1191*3d8817e4Smiod static reloc_howto_type fake_arm26_reloc =
1192*3d8817e4Smiod HOWTO (ARM_26,
1193*3d8817e4Smiod 2,
1194*3d8817e4Smiod 2,
1195*3d8817e4Smiod 24,
1196*3d8817e4Smiod TRUE,
1197*3d8817e4Smiod 0,
1198*3d8817e4Smiod complain_overflow_signed,
1199*3d8817e4Smiod aoutarm_fix_pcrel_26 ,
1200*3d8817e4Smiod "ARM_26",
1201*3d8817e4Smiod TRUE,
1202*3d8817e4Smiod 0x00ffffff,
1203*3d8817e4Smiod 0x00ffffff,
1204*3d8817e4Smiod FALSE);
1205*3d8817e4Smiod
1206*3d8817e4Smiod addend -= rel->r_vaddr - input_section->vma;
1207*3d8817e4Smiod #ifdef ARM_WINCE
1208*3d8817e4Smiod /* FIXME: I don't know why, but the hack is necessary for correct
1209*3d8817e4Smiod generation of bl's instruction offset. */
1210*3d8817e4Smiod addend -= 8;
1211*3d8817e4Smiod #endif
1212*3d8817e4Smiod howto = &fake_arm26_reloc;
1213*3d8817e4Smiod }
1214*3d8817e4Smiod
1215*3d8817e4Smiod #ifdef ARM_WINCE
1216*3d8817e4Smiod /* MS ARM-CE makes the reloc relative to the opcode's pc, not
1217*3d8817e4Smiod the next opcode's pc, so is off by one. */
1218*3d8817e4Smiod #endif
1219*3d8817e4Smiod
1220*3d8817e4Smiod /* If we are doing a relocatable link, then we can just ignore
1221*3d8817e4Smiod a PC relative reloc that is pcrel_offset. It will already
1222*3d8817e4Smiod have the correct value. If this is not a relocatable link,
1223*3d8817e4Smiod then we should ignore the symbol value. */
1224*3d8817e4Smiod if (howto->pc_relative && howto->pcrel_offset)
1225*3d8817e4Smiod {
1226*3d8817e4Smiod if (info->relocatable)
1227*3d8817e4Smiod continue;
1228*3d8817e4Smiod /* FIXME - it is not clear which targets need this next test
1229*3d8817e4Smiod and which do not. It is known that it is needed for the
1230*3d8817e4Smiod VxWorks and EPOC-PE targets, but it is also known that it
1231*3d8817e4Smiod was suppressed for other ARM targets. This ought to be
1232*3d8817e4Smiod sorted out one day. */
1233*3d8817e4Smiod #ifdef ARM_COFF_BUGFIX
1234*3d8817e4Smiod /* We must not ignore the symbol value. If the symbol is
1235*3d8817e4Smiod within the same section, the relocation should have already
1236*3d8817e4Smiod been fixed, but if it is not, we'll be handed a reloc into
1237*3d8817e4Smiod the beginning of the symbol's section, so we must not cancel
1238*3d8817e4Smiod out the symbol's value, otherwise we'll be adding it in
1239*3d8817e4Smiod twice. */
1240*3d8817e4Smiod if (sym != NULL && sym->n_scnum != 0)
1241*3d8817e4Smiod addend += sym->n_value;
1242*3d8817e4Smiod #endif
1243*3d8817e4Smiod }
1244*3d8817e4Smiod
1245*3d8817e4Smiod val = 0;
1246*3d8817e4Smiod
1247*3d8817e4Smiod if (h == NULL)
1248*3d8817e4Smiod {
1249*3d8817e4Smiod asection *sec;
1250*3d8817e4Smiod
1251*3d8817e4Smiod if (symndx == -1)
1252*3d8817e4Smiod {
1253*3d8817e4Smiod sec = bfd_abs_section_ptr;
1254*3d8817e4Smiod val = 0;
1255*3d8817e4Smiod }
1256*3d8817e4Smiod else
1257*3d8817e4Smiod {
1258*3d8817e4Smiod sec = sections[symndx];
1259*3d8817e4Smiod val = (sec->output_section->vma
1260*3d8817e4Smiod + sec->output_offset
1261*3d8817e4Smiod + sym->n_value
1262*3d8817e4Smiod - sec->vma);
1263*3d8817e4Smiod }
1264*3d8817e4Smiod }
1265*3d8817e4Smiod else
1266*3d8817e4Smiod {
1267*3d8817e4Smiod /* We don't output the stubs if we are generating a
1268*3d8817e4Smiod relocatable output file, since we may as well leave the
1269*3d8817e4Smiod stub generation to the final linker pass. If we fail to
1270*3d8817e4Smiod verify that the name is defined, we'll try to build stubs
1271*3d8817e4Smiod for an undefined name... */
1272*3d8817e4Smiod if (! info->relocatable
1273*3d8817e4Smiod && ( h->root.type == bfd_link_hash_defined
1274*3d8817e4Smiod || h->root.type == bfd_link_hash_defweak))
1275*3d8817e4Smiod {
1276*3d8817e4Smiod asection * h_sec = h->root.u.def.section;
1277*3d8817e4Smiod const char * name = h->root.root.string;
1278*3d8817e4Smiod
1279*3d8817e4Smiod /* h locates the symbol referenced in the reloc. */
1280*3d8817e4Smiod h_val = (h->root.u.def.value
1281*3d8817e4Smiod + h_sec->output_section->vma
1282*3d8817e4Smiod + h_sec->output_offset);
1283*3d8817e4Smiod
1284*3d8817e4Smiod if (howto->type == ARM_26)
1285*3d8817e4Smiod {
1286*3d8817e4Smiod if ( h->class == C_THUMBSTATFUNC
1287*3d8817e4Smiod || h->class == C_THUMBEXTFUNC)
1288*3d8817e4Smiod {
1289*3d8817e4Smiod /* Arm code calling a Thumb function. */
1290*3d8817e4Smiod unsigned long int tmp;
1291*3d8817e4Smiod bfd_vma my_offset;
1292*3d8817e4Smiod asection * s;
1293*3d8817e4Smiod long int ret_offset;
1294*3d8817e4Smiod struct coff_link_hash_entry * myh;
1295*3d8817e4Smiod struct coff_arm_link_hash_table * globals;
1296*3d8817e4Smiod
1297*3d8817e4Smiod myh = find_arm_glue (info, name, input_bfd);
1298*3d8817e4Smiod if (myh == NULL)
1299*3d8817e4Smiod return FALSE;
1300*3d8817e4Smiod
1301*3d8817e4Smiod globals = coff_arm_hash_table (info);
1302*3d8817e4Smiod
1303*3d8817e4Smiod BFD_ASSERT (globals != NULL);
1304*3d8817e4Smiod BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1305*3d8817e4Smiod
1306*3d8817e4Smiod my_offset = myh->root.u.def.value;
1307*3d8817e4Smiod
1308*3d8817e4Smiod s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
1309*3d8817e4Smiod ARM2THUMB_GLUE_SECTION_NAME);
1310*3d8817e4Smiod BFD_ASSERT (s != NULL);
1311*3d8817e4Smiod BFD_ASSERT (s->contents != NULL);
1312*3d8817e4Smiod BFD_ASSERT (s->output_section != NULL);
1313*3d8817e4Smiod
1314*3d8817e4Smiod if ((my_offset & 0x01) == 0x01)
1315*3d8817e4Smiod {
1316*3d8817e4Smiod if (h_sec->owner != NULL
1317*3d8817e4Smiod && INTERWORK_SET (h_sec->owner)
1318*3d8817e4Smiod && ! INTERWORK_FLAG (h_sec->owner))
1319*3d8817e4Smiod _bfd_error_handler
1320*3d8817e4Smiod /* xgettext:c-format */
1321*3d8817e4Smiod (_("%B(%s): warning: interworking not enabled.\n"
1322*3d8817e4Smiod " first occurrence: %B: arm call to thumb"),
1323*3d8817e4Smiod h_sec->owner, input_bfd, name);
1324*3d8817e4Smiod
1325*3d8817e4Smiod --my_offset;
1326*3d8817e4Smiod myh->root.u.def.value = my_offset;
1327*3d8817e4Smiod
1328*3d8817e4Smiod bfd_put_32 (output_bfd, (bfd_vma) a2t1_ldr_insn,
1329*3d8817e4Smiod s->contents + my_offset);
1330*3d8817e4Smiod
1331*3d8817e4Smiod bfd_put_32 (output_bfd, (bfd_vma) a2t2_bx_r12_insn,
1332*3d8817e4Smiod s->contents + my_offset + 4);
1333*3d8817e4Smiod
1334*3d8817e4Smiod /* It's a thumb address. Add the low order bit. */
1335*3d8817e4Smiod bfd_put_32 (output_bfd, h_val | a2t3_func_addr_insn,
1336*3d8817e4Smiod s->contents + my_offset + 8);
1337*3d8817e4Smiod
1338*3d8817e4Smiod if (info->base_file)
1339*3d8817e4Smiod arm_emit_base_file_entry (info, output_bfd, s,
1340*3d8817e4Smiod my_offset + 8);
1341*3d8817e4Smiod
1342*3d8817e4Smiod }
1343*3d8817e4Smiod
1344*3d8817e4Smiod BFD_ASSERT (my_offset <= globals->arm_glue_size);
1345*3d8817e4Smiod
1346*3d8817e4Smiod tmp = bfd_get_32 (input_bfd, contents + rel->r_vaddr
1347*3d8817e4Smiod - input_section->vma);
1348*3d8817e4Smiod
1349*3d8817e4Smiod tmp = tmp & 0xFF000000;
1350*3d8817e4Smiod
1351*3d8817e4Smiod /* Somehow these are both 4 too far, so subtract 8. */
1352*3d8817e4Smiod ret_offset =
1353*3d8817e4Smiod s->output_offset
1354*3d8817e4Smiod + my_offset
1355*3d8817e4Smiod + s->output_section->vma
1356*3d8817e4Smiod - (input_section->output_offset
1357*3d8817e4Smiod + input_section->output_section->vma
1358*3d8817e4Smiod + rel->r_vaddr)
1359*3d8817e4Smiod - 8;
1360*3d8817e4Smiod
1361*3d8817e4Smiod tmp = tmp | ((ret_offset >> 2) & 0x00FFFFFF);
1362*3d8817e4Smiod
1363*3d8817e4Smiod bfd_put_32 (output_bfd, (bfd_vma) tmp,
1364*3d8817e4Smiod contents + rel->r_vaddr - input_section->vma);
1365*3d8817e4Smiod done = 1;
1366*3d8817e4Smiod }
1367*3d8817e4Smiod }
1368*3d8817e4Smiod
1369*3d8817e4Smiod #ifndef ARM_WINCE
1370*3d8817e4Smiod /* Note: We used to check for ARM_THUMB9 and ARM_THUMB12. */
1371*3d8817e4Smiod else if (howto->type == ARM_THUMB23)
1372*3d8817e4Smiod {
1373*3d8817e4Smiod if ( h->class == C_EXT
1374*3d8817e4Smiod || h->class == C_STAT
1375*3d8817e4Smiod || h->class == C_LABEL)
1376*3d8817e4Smiod {
1377*3d8817e4Smiod /* Thumb code calling an ARM function. */
1378*3d8817e4Smiod asection * s = 0;
1379*3d8817e4Smiod bfd_vma my_offset;
1380*3d8817e4Smiod unsigned long int tmp;
1381*3d8817e4Smiod long int ret_offset;
1382*3d8817e4Smiod struct coff_link_hash_entry * myh;
1383*3d8817e4Smiod struct coff_arm_link_hash_table * globals;
1384*3d8817e4Smiod
1385*3d8817e4Smiod myh = find_thumb_glue (info, name, input_bfd);
1386*3d8817e4Smiod if (myh == NULL)
1387*3d8817e4Smiod return FALSE;
1388*3d8817e4Smiod
1389*3d8817e4Smiod globals = coff_arm_hash_table (info);
1390*3d8817e4Smiod
1391*3d8817e4Smiod BFD_ASSERT (globals != NULL);
1392*3d8817e4Smiod BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1393*3d8817e4Smiod
1394*3d8817e4Smiod my_offset = myh->root.u.def.value;
1395*3d8817e4Smiod
1396*3d8817e4Smiod s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
1397*3d8817e4Smiod THUMB2ARM_GLUE_SECTION_NAME);
1398*3d8817e4Smiod
1399*3d8817e4Smiod BFD_ASSERT (s != NULL);
1400*3d8817e4Smiod BFD_ASSERT (s->contents != NULL);
1401*3d8817e4Smiod BFD_ASSERT (s->output_section != NULL);
1402*3d8817e4Smiod
1403*3d8817e4Smiod if ((my_offset & 0x01) == 0x01)
1404*3d8817e4Smiod {
1405*3d8817e4Smiod if (h_sec->owner != NULL
1406*3d8817e4Smiod && INTERWORK_SET (h_sec->owner)
1407*3d8817e4Smiod && ! INTERWORK_FLAG (h_sec->owner)
1408*3d8817e4Smiod && ! globals->support_old_code)
1409*3d8817e4Smiod _bfd_error_handler
1410*3d8817e4Smiod /* xgettext:c-format */
1411*3d8817e4Smiod (_("%B(%s): warning: interworking not enabled.\n"
1412*3d8817e4Smiod " first occurrence: %B: thumb call to arm\n"
1413*3d8817e4Smiod " consider relinking with --support-old-code enabled"),
1414*3d8817e4Smiod h_sec->owner, input_bfd, name);
1415*3d8817e4Smiod
1416*3d8817e4Smiod -- my_offset;
1417*3d8817e4Smiod myh->root.u.def.value = my_offset;
1418*3d8817e4Smiod
1419*3d8817e4Smiod if (globals->support_old_code)
1420*3d8817e4Smiod {
1421*3d8817e4Smiod bfd_put_16 (output_bfd, (bfd_vma) t2a1_push_insn,
1422*3d8817e4Smiod s->contents + my_offset);
1423*3d8817e4Smiod
1424*3d8817e4Smiod bfd_put_16 (output_bfd, (bfd_vma) t2a2_ldr_insn,
1425*3d8817e4Smiod s->contents + my_offset + 2);
1426*3d8817e4Smiod
1427*3d8817e4Smiod bfd_put_16 (output_bfd, (bfd_vma) t2a3_mov_insn,
1428*3d8817e4Smiod s->contents + my_offset + 4);
1429*3d8817e4Smiod
1430*3d8817e4Smiod bfd_put_16 (output_bfd, (bfd_vma) t2a4_bx_insn,
1431*3d8817e4Smiod s->contents + my_offset + 6);
1432*3d8817e4Smiod
1433*3d8817e4Smiod bfd_put_32 (output_bfd, (bfd_vma) t2a5_pop_insn,
1434*3d8817e4Smiod s->contents + my_offset + 8);
1435*3d8817e4Smiod
1436*3d8817e4Smiod bfd_put_32 (output_bfd, (bfd_vma) t2a6_bx_insn,
1437*3d8817e4Smiod s->contents + my_offset + 12);
1438*3d8817e4Smiod
1439*3d8817e4Smiod /* Store the address of the function in the last word of the stub. */
1440*3d8817e4Smiod bfd_put_32 (output_bfd, h_val,
1441*3d8817e4Smiod s->contents + my_offset + 16);
1442*3d8817e4Smiod
1443*3d8817e4Smiod if (info->base_file)
1444*3d8817e4Smiod arm_emit_base_file_entry (info, output_bfd, s,
1445*3d8817e4Smiod my_offset + 16);
1446*3d8817e4Smiod }
1447*3d8817e4Smiod else
1448*3d8817e4Smiod {
1449*3d8817e4Smiod bfd_put_16 (output_bfd, (bfd_vma) t2a1_bx_pc_insn,
1450*3d8817e4Smiod s->contents + my_offset);
1451*3d8817e4Smiod
1452*3d8817e4Smiod bfd_put_16 (output_bfd, (bfd_vma) t2a2_noop_insn,
1453*3d8817e4Smiod s->contents + my_offset + 2);
1454*3d8817e4Smiod
1455*3d8817e4Smiod ret_offset =
1456*3d8817e4Smiod /* Address of destination of the stub. */
1457*3d8817e4Smiod ((bfd_signed_vma) h_val)
1458*3d8817e4Smiod - ((bfd_signed_vma)
1459*3d8817e4Smiod /* Offset from the start of the current section to the start of the stubs. */
1460*3d8817e4Smiod (s->output_offset
1461*3d8817e4Smiod /* Offset of the start of this stub from the start of the stubs. */
1462*3d8817e4Smiod + my_offset
1463*3d8817e4Smiod /* Address of the start of the current section. */
1464*3d8817e4Smiod + s->output_section->vma)
1465*3d8817e4Smiod /* The branch instruction is 4 bytes into the stub. */
1466*3d8817e4Smiod + 4
1467*3d8817e4Smiod /* ARM branches work from the pc of the instruction + 8. */
1468*3d8817e4Smiod + 8);
1469*3d8817e4Smiod
1470*3d8817e4Smiod bfd_put_32 (output_bfd,
1471*3d8817e4Smiod (bfd_vma) t2a3_b_insn | ((ret_offset >> 2) & 0x00FFFFFF),
1472*3d8817e4Smiod s->contents + my_offset + 4);
1473*3d8817e4Smiod
1474*3d8817e4Smiod }
1475*3d8817e4Smiod }
1476*3d8817e4Smiod
1477*3d8817e4Smiod BFD_ASSERT (my_offset <= globals->thumb_glue_size);
1478*3d8817e4Smiod
1479*3d8817e4Smiod /* Now go back and fix up the original BL insn to point
1480*3d8817e4Smiod to here. */
1481*3d8817e4Smiod ret_offset =
1482*3d8817e4Smiod s->output_offset
1483*3d8817e4Smiod + my_offset
1484*3d8817e4Smiod - (input_section->output_offset
1485*3d8817e4Smiod + rel->r_vaddr)
1486*3d8817e4Smiod -4;
1487*3d8817e4Smiod
1488*3d8817e4Smiod tmp = bfd_get_32 (input_bfd, contents + rel->r_vaddr
1489*3d8817e4Smiod - input_section->vma);
1490*3d8817e4Smiod
1491*3d8817e4Smiod bfd_put_32 (output_bfd,
1492*3d8817e4Smiod (bfd_vma) insert_thumb_branch (tmp,
1493*3d8817e4Smiod ret_offset),
1494*3d8817e4Smiod contents + rel->r_vaddr - input_section->vma);
1495*3d8817e4Smiod
1496*3d8817e4Smiod done = 1;
1497*3d8817e4Smiod }
1498*3d8817e4Smiod }
1499*3d8817e4Smiod #endif
1500*3d8817e4Smiod }
1501*3d8817e4Smiod
1502*3d8817e4Smiod /* If the relocation type and destination symbol does not
1503*3d8817e4Smiod fall into one of the above categories, then we can just
1504*3d8817e4Smiod perform a direct link. */
1505*3d8817e4Smiod
1506*3d8817e4Smiod if (done)
1507*3d8817e4Smiod rstat = bfd_reloc_ok;
1508*3d8817e4Smiod else
1509*3d8817e4Smiod if ( h->root.type == bfd_link_hash_defined
1510*3d8817e4Smiod || h->root.type == bfd_link_hash_defweak)
1511*3d8817e4Smiod {
1512*3d8817e4Smiod asection *sec;
1513*3d8817e4Smiod
1514*3d8817e4Smiod sec = h->root.u.def.section;
1515*3d8817e4Smiod val = (h->root.u.def.value
1516*3d8817e4Smiod + sec->output_section->vma
1517*3d8817e4Smiod + sec->output_offset);
1518*3d8817e4Smiod }
1519*3d8817e4Smiod
1520*3d8817e4Smiod else if (! info->relocatable)
1521*3d8817e4Smiod {
1522*3d8817e4Smiod if (! ((*info->callbacks->undefined_symbol)
1523*3d8817e4Smiod (info, h->root.root.string, input_bfd, input_section,
1524*3d8817e4Smiod rel->r_vaddr - input_section->vma, TRUE)))
1525*3d8817e4Smiod return FALSE;
1526*3d8817e4Smiod }
1527*3d8817e4Smiod }
1528*3d8817e4Smiod
1529*3d8817e4Smiod if (info->base_file)
1530*3d8817e4Smiod {
1531*3d8817e4Smiod /* Emit a reloc if the backend thinks it needs it. */
1532*3d8817e4Smiod if (sym && pe_data(output_bfd)->in_reloc_p(output_bfd, howto))
1533*3d8817e4Smiod arm_emit_base_file_entry (info, output_bfd, input_section,
1534*3d8817e4Smiod rel->r_vaddr);
1535*3d8817e4Smiod }
1536*3d8817e4Smiod
1537*3d8817e4Smiod if (done)
1538*3d8817e4Smiod rstat = bfd_reloc_ok;
1539*3d8817e4Smiod #ifndef ARM_WINCE
1540*3d8817e4Smiod /* Only perform this fix during the final link, not a relocatable link. */
1541*3d8817e4Smiod else if (! info->relocatable
1542*3d8817e4Smiod && howto->type == ARM_THUMB23)
1543*3d8817e4Smiod {
1544*3d8817e4Smiod /* This is pretty much a copy of what the default
1545*3d8817e4Smiod _bfd_final_link_relocate and _bfd_relocate_contents
1546*3d8817e4Smiod routines do to perform a relocation, with special
1547*3d8817e4Smiod processing for the split addressing of the Thumb BL
1548*3d8817e4Smiod instruction. Again, it would probably be simpler adding a
1549*3d8817e4Smiod ThumbBRANCH23 specific macro expansion into the default
1550*3d8817e4Smiod code. */
1551*3d8817e4Smiod
1552*3d8817e4Smiod bfd_vma address = rel->r_vaddr - input_section->vma;
1553*3d8817e4Smiod
1554*3d8817e4Smiod if (address > high_address)
1555*3d8817e4Smiod rstat = bfd_reloc_outofrange;
1556*3d8817e4Smiod else
1557*3d8817e4Smiod {
1558*3d8817e4Smiod bfd_vma relocation = val + addend;
1559*3d8817e4Smiod int size = bfd_get_reloc_size (howto);
1560*3d8817e4Smiod bfd_boolean overflow = FALSE;
1561*3d8817e4Smiod bfd_byte *location = contents + address;
1562*3d8817e4Smiod bfd_vma x = bfd_get_32 (input_bfd, location);
1563*3d8817e4Smiod bfd_vma src_mask = 0x007FFFFE;
1564*3d8817e4Smiod bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
1565*3d8817e4Smiod bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
1566*3d8817e4Smiod bfd_vma check;
1567*3d8817e4Smiod bfd_signed_vma signed_check;
1568*3d8817e4Smiod bfd_vma add;
1569*3d8817e4Smiod bfd_signed_vma signed_add;
1570*3d8817e4Smiod
1571*3d8817e4Smiod BFD_ASSERT (size == 4);
1572*3d8817e4Smiod
1573*3d8817e4Smiod /* howto->pc_relative should be TRUE for type 14 BRANCH23. */
1574*3d8817e4Smiod relocation -= (input_section->output_section->vma
1575*3d8817e4Smiod + input_section->output_offset);
1576*3d8817e4Smiod
1577*3d8817e4Smiod /* howto->pcrel_offset should be TRUE for type 14 BRANCH23. */
1578*3d8817e4Smiod relocation -= address;
1579*3d8817e4Smiod
1580*3d8817e4Smiod /* No need to negate the relocation with BRANCH23. */
1581*3d8817e4Smiod /* howto->complain_on_overflow == complain_overflow_signed for BRANCH23. */
1582*3d8817e4Smiod /* howto->rightshift == 1 */
1583*3d8817e4Smiod
1584*3d8817e4Smiod /* Drop unwanted bits from the value we are relocating to. */
1585*3d8817e4Smiod check = relocation >> howto->rightshift;
1586*3d8817e4Smiod
1587*3d8817e4Smiod /* If this is a signed value, the rightshift just dropped
1588*3d8817e4Smiod leading 1 bits (assuming twos complement). */
1589*3d8817e4Smiod if ((bfd_signed_vma) relocation >= 0)
1590*3d8817e4Smiod signed_check = check;
1591*3d8817e4Smiod else
1592*3d8817e4Smiod signed_check = (check
1593*3d8817e4Smiod | ((bfd_vma) - 1
1594*3d8817e4Smiod & ~((bfd_vma) - 1 >> howto->rightshift)));
1595*3d8817e4Smiod
1596*3d8817e4Smiod /* Get the value from the object file. */
1597*3d8817e4Smiod if (bfd_big_endian (input_bfd))
1598*3d8817e4Smiod add = (((x) & 0x07ff0000) >> 4) | (((x) & 0x7ff) << 1);
1599*3d8817e4Smiod else
1600*3d8817e4Smiod add = ((((x) & 0x7ff) << 12) | (((x) & 0x07ff0000) >> 15));
1601*3d8817e4Smiod
1602*3d8817e4Smiod /* Get the value from the object file with an appropriate sign.
1603*3d8817e4Smiod The expression involving howto->src_mask isolates the upper
1604*3d8817e4Smiod bit of src_mask. If that bit is set in the value we are
1605*3d8817e4Smiod adding, it is negative, and we subtract out that number times
1606*3d8817e4Smiod two. If src_mask includes the highest possible bit, then we
1607*3d8817e4Smiod can not get the upper bit, but that does not matter since
1608*3d8817e4Smiod signed_add needs no adjustment to become negative in that
1609*3d8817e4Smiod case. */
1610*3d8817e4Smiod signed_add = add;
1611*3d8817e4Smiod
1612*3d8817e4Smiod if ((add & (((~ src_mask) >> 1) & src_mask)) != 0)
1613*3d8817e4Smiod signed_add -= (((~ src_mask) >> 1) & src_mask) << 1;
1614*3d8817e4Smiod
1615*3d8817e4Smiod /* howto->bitpos == 0 */
1616*3d8817e4Smiod /* Add the value from the object file, shifted so that it is a
1617*3d8817e4Smiod straight number. */
1618*3d8817e4Smiod signed_check += signed_add;
1619*3d8817e4Smiod relocation += signed_add;
1620*3d8817e4Smiod
1621*3d8817e4Smiod BFD_ASSERT (howto->complain_on_overflow == complain_overflow_signed);
1622*3d8817e4Smiod
1623*3d8817e4Smiod /* Assumes two's complement. */
1624*3d8817e4Smiod if ( signed_check > reloc_signed_max
1625*3d8817e4Smiod || signed_check < reloc_signed_min)
1626*3d8817e4Smiod overflow = TRUE;
1627*3d8817e4Smiod
1628*3d8817e4Smiod /* Put the relocation into the correct bits.
1629*3d8817e4Smiod For a BLX instruction, make sure that the relocation is rounded up
1630*3d8817e4Smiod to a word boundary. This follows the semantics of the instruction
1631*3d8817e4Smiod which specifies that bit 1 of the target address will come from bit
1632*3d8817e4Smiod 1 of the base address. */
1633*3d8817e4Smiod if (bfd_big_endian (input_bfd))
1634*3d8817e4Smiod {
1635*3d8817e4Smiod if ((x & 0x1800) == 0x0800 && (relocation & 0x02))
1636*3d8817e4Smiod relocation += 2;
1637*3d8817e4Smiod relocation = (((relocation & 0xffe) >> 1) | ((relocation << 4) & 0x07ff0000));
1638*3d8817e4Smiod }
1639*3d8817e4Smiod else
1640*3d8817e4Smiod {
1641*3d8817e4Smiod if ((x & 0x18000000) == 0x08000000 && (relocation & 0x02))
1642*3d8817e4Smiod relocation += 2;
1643*3d8817e4Smiod relocation = (((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff));
1644*3d8817e4Smiod }
1645*3d8817e4Smiod
1646*3d8817e4Smiod /* Add the relocation to the correct bits of X. */
1647*3d8817e4Smiod x = ((x & ~howto->dst_mask) | relocation);
1648*3d8817e4Smiod
1649*3d8817e4Smiod /* Put the relocated value back in the object file. */
1650*3d8817e4Smiod bfd_put_32 (input_bfd, x, location);
1651*3d8817e4Smiod
1652*3d8817e4Smiod rstat = overflow ? bfd_reloc_overflow : bfd_reloc_ok;
1653*3d8817e4Smiod }
1654*3d8817e4Smiod }
1655*3d8817e4Smiod #endif
1656*3d8817e4Smiod else
1657*3d8817e4Smiod if (info->relocatable && ! howto->partial_inplace)
1658*3d8817e4Smiod rstat = bfd_reloc_ok;
1659*3d8817e4Smiod else
1660*3d8817e4Smiod rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
1661*3d8817e4Smiod contents,
1662*3d8817e4Smiod rel->r_vaddr - input_section->vma,
1663*3d8817e4Smiod val, addend);
1664*3d8817e4Smiod /* Only perform this fix during the final link, not a relocatable link. */
1665*3d8817e4Smiod if (! info->relocatable
1666*3d8817e4Smiod && (rel->r_type == ARM_32 || rel->r_type == ARM_RVA32))
1667*3d8817e4Smiod {
1668*3d8817e4Smiod /* Determine if we need to set the bottom bit of a relocated address
1669*3d8817e4Smiod because the address is the address of a Thumb code symbol. */
1670*3d8817e4Smiod int patchit = FALSE;
1671*3d8817e4Smiod
1672*3d8817e4Smiod if (h != NULL
1673*3d8817e4Smiod && ( h->class == C_THUMBSTATFUNC
1674*3d8817e4Smiod || h->class == C_THUMBEXTFUNC))
1675*3d8817e4Smiod {
1676*3d8817e4Smiod patchit = TRUE;
1677*3d8817e4Smiod }
1678*3d8817e4Smiod else if (sym != NULL
1679*3d8817e4Smiod && sym->n_scnum > N_UNDEF)
1680*3d8817e4Smiod {
1681*3d8817e4Smiod /* No hash entry - use the symbol instead. */
1682*3d8817e4Smiod if ( sym->n_sclass == C_THUMBSTATFUNC
1683*3d8817e4Smiod || sym->n_sclass == C_THUMBEXTFUNC)
1684*3d8817e4Smiod patchit = TRUE;
1685*3d8817e4Smiod }
1686*3d8817e4Smiod
1687*3d8817e4Smiod if (patchit)
1688*3d8817e4Smiod {
1689*3d8817e4Smiod bfd_byte * location = contents + rel->r_vaddr - input_section->vma;
1690*3d8817e4Smiod bfd_vma x = bfd_get_32 (input_bfd, location);
1691*3d8817e4Smiod
1692*3d8817e4Smiod bfd_put_32 (input_bfd, x | 1, location);
1693*3d8817e4Smiod }
1694*3d8817e4Smiod }
1695*3d8817e4Smiod
1696*3d8817e4Smiod switch (rstat)
1697*3d8817e4Smiod {
1698*3d8817e4Smiod default:
1699*3d8817e4Smiod abort ();
1700*3d8817e4Smiod case bfd_reloc_ok:
1701*3d8817e4Smiod break;
1702*3d8817e4Smiod case bfd_reloc_outofrange:
1703*3d8817e4Smiod (*_bfd_error_handler)
1704*3d8817e4Smiod (_("%B: bad reloc address 0x%lx in section `%A'"),
1705*3d8817e4Smiod input_bfd, input_section, (unsigned long) rel->r_vaddr);
1706*3d8817e4Smiod return FALSE;
1707*3d8817e4Smiod case bfd_reloc_overflow:
1708*3d8817e4Smiod {
1709*3d8817e4Smiod const char *name;
1710*3d8817e4Smiod char buf[SYMNMLEN + 1];
1711*3d8817e4Smiod
1712*3d8817e4Smiod if (symndx == -1)
1713*3d8817e4Smiod name = "*ABS*";
1714*3d8817e4Smiod else if (h != NULL)
1715*3d8817e4Smiod name = NULL;
1716*3d8817e4Smiod else
1717*3d8817e4Smiod {
1718*3d8817e4Smiod name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
1719*3d8817e4Smiod if (name == NULL)
1720*3d8817e4Smiod return FALSE;
1721*3d8817e4Smiod }
1722*3d8817e4Smiod
1723*3d8817e4Smiod if (! ((*info->callbacks->reloc_overflow)
1724*3d8817e4Smiod (info, (h ? &h->root : NULL), name, howto->name,
1725*3d8817e4Smiod (bfd_vma) 0, input_bfd, input_section,
1726*3d8817e4Smiod rel->r_vaddr - input_section->vma)))
1727*3d8817e4Smiod return FALSE;
1728*3d8817e4Smiod }
1729*3d8817e4Smiod }
1730*3d8817e4Smiod }
1731*3d8817e4Smiod
1732*3d8817e4Smiod return TRUE;
1733*3d8817e4Smiod }
1734*3d8817e4Smiod
1735*3d8817e4Smiod #ifndef COFF_IMAGE_WITH_PE
1736*3d8817e4Smiod
1737*3d8817e4Smiod bfd_boolean
bfd_arm_allocate_interworking_sections(struct bfd_link_info * info)1738*3d8817e4Smiod bfd_arm_allocate_interworking_sections (struct bfd_link_info * info)
1739*3d8817e4Smiod {
1740*3d8817e4Smiod asection * s;
1741*3d8817e4Smiod bfd_byte * foo;
1742*3d8817e4Smiod struct coff_arm_link_hash_table * globals;
1743*3d8817e4Smiod
1744*3d8817e4Smiod globals = coff_arm_hash_table (info);
1745*3d8817e4Smiod
1746*3d8817e4Smiod BFD_ASSERT (globals != NULL);
1747*3d8817e4Smiod
1748*3d8817e4Smiod if (globals->arm_glue_size != 0)
1749*3d8817e4Smiod {
1750*3d8817e4Smiod BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1751*3d8817e4Smiod
1752*3d8817e4Smiod s = bfd_get_section_by_name
1753*3d8817e4Smiod (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
1754*3d8817e4Smiod
1755*3d8817e4Smiod BFD_ASSERT (s != NULL);
1756*3d8817e4Smiod
1757*3d8817e4Smiod foo = bfd_alloc (globals->bfd_of_glue_owner, globals->arm_glue_size);
1758*3d8817e4Smiod
1759*3d8817e4Smiod s->size = globals->arm_glue_size;
1760*3d8817e4Smiod s->contents = foo;
1761*3d8817e4Smiod }
1762*3d8817e4Smiod
1763*3d8817e4Smiod if (globals->thumb_glue_size != 0)
1764*3d8817e4Smiod {
1765*3d8817e4Smiod BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1766*3d8817e4Smiod
1767*3d8817e4Smiod s = bfd_get_section_by_name
1768*3d8817e4Smiod (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
1769*3d8817e4Smiod
1770*3d8817e4Smiod BFD_ASSERT (s != NULL);
1771*3d8817e4Smiod
1772*3d8817e4Smiod foo = bfd_alloc (globals->bfd_of_glue_owner, globals->thumb_glue_size);
1773*3d8817e4Smiod
1774*3d8817e4Smiod s->size = globals->thumb_glue_size;
1775*3d8817e4Smiod s->contents = foo;
1776*3d8817e4Smiod }
1777*3d8817e4Smiod
1778*3d8817e4Smiod return TRUE;
1779*3d8817e4Smiod }
1780*3d8817e4Smiod
1781*3d8817e4Smiod static void
record_arm_to_thumb_glue(struct bfd_link_info * info,struct coff_link_hash_entry * h)1782*3d8817e4Smiod record_arm_to_thumb_glue (struct bfd_link_info * info,
1783*3d8817e4Smiod struct coff_link_hash_entry * h)
1784*3d8817e4Smiod {
1785*3d8817e4Smiod const char * name = h->root.root.string;
1786*3d8817e4Smiod register asection * s;
1787*3d8817e4Smiod char * tmp_name;
1788*3d8817e4Smiod struct coff_link_hash_entry * myh;
1789*3d8817e4Smiod struct bfd_link_hash_entry * bh;
1790*3d8817e4Smiod struct coff_arm_link_hash_table * globals;
1791*3d8817e4Smiod bfd_vma val;
1792*3d8817e4Smiod bfd_size_type amt;
1793*3d8817e4Smiod
1794*3d8817e4Smiod globals = coff_arm_hash_table (info);
1795*3d8817e4Smiod
1796*3d8817e4Smiod BFD_ASSERT (globals != NULL);
1797*3d8817e4Smiod BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1798*3d8817e4Smiod
1799*3d8817e4Smiod s = bfd_get_section_by_name
1800*3d8817e4Smiod (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
1801*3d8817e4Smiod
1802*3d8817e4Smiod BFD_ASSERT (s != NULL);
1803*3d8817e4Smiod
1804*3d8817e4Smiod amt = strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1;
1805*3d8817e4Smiod tmp_name = bfd_malloc (amt);
1806*3d8817e4Smiod
1807*3d8817e4Smiod BFD_ASSERT (tmp_name);
1808*3d8817e4Smiod
1809*3d8817e4Smiod sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);
1810*3d8817e4Smiod
1811*3d8817e4Smiod myh = coff_link_hash_lookup
1812*3d8817e4Smiod (coff_hash_table (info), tmp_name, FALSE, FALSE, TRUE);
1813*3d8817e4Smiod
1814*3d8817e4Smiod if (myh != NULL)
1815*3d8817e4Smiod {
1816*3d8817e4Smiod free (tmp_name);
1817*3d8817e4Smiod /* We've already seen this guy. */
1818*3d8817e4Smiod return;
1819*3d8817e4Smiod }
1820*3d8817e4Smiod
1821*3d8817e4Smiod /* The only trick here is using globals->arm_glue_size as the value. Even
1822*3d8817e4Smiod though the section isn't allocated yet, this is where we will be putting
1823*3d8817e4Smiod it. */
1824*3d8817e4Smiod bh = NULL;
1825*3d8817e4Smiod val = globals->arm_glue_size + 1;
1826*3d8817e4Smiod bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name,
1827*3d8817e4Smiod BSF_GLOBAL, s, val, NULL, TRUE, FALSE, &bh);
1828*3d8817e4Smiod
1829*3d8817e4Smiod free (tmp_name);
1830*3d8817e4Smiod
1831*3d8817e4Smiod globals->arm_glue_size += ARM2THUMB_GLUE_SIZE;
1832*3d8817e4Smiod
1833*3d8817e4Smiod return;
1834*3d8817e4Smiod }
1835*3d8817e4Smiod
1836*3d8817e4Smiod #ifndef ARM_WINCE
1837*3d8817e4Smiod static void
record_thumb_to_arm_glue(struct bfd_link_info * info,struct coff_link_hash_entry * h)1838*3d8817e4Smiod record_thumb_to_arm_glue (struct bfd_link_info * info,
1839*3d8817e4Smiod struct coff_link_hash_entry * h)
1840*3d8817e4Smiod {
1841*3d8817e4Smiod const char * name = h->root.root.string;
1842*3d8817e4Smiod asection * s;
1843*3d8817e4Smiod char * tmp_name;
1844*3d8817e4Smiod struct coff_link_hash_entry * myh;
1845*3d8817e4Smiod struct bfd_link_hash_entry * bh;
1846*3d8817e4Smiod struct coff_arm_link_hash_table * globals;
1847*3d8817e4Smiod bfd_vma val;
1848*3d8817e4Smiod bfd_size_type amt;
1849*3d8817e4Smiod
1850*3d8817e4Smiod globals = coff_arm_hash_table (info);
1851*3d8817e4Smiod
1852*3d8817e4Smiod BFD_ASSERT (globals != NULL);
1853*3d8817e4Smiod BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1854*3d8817e4Smiod
1855*3d8817e4Smiod s = bfd_get_section_by_name
1856*3d8817e4Smiod (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
1857*3d8817e4Smiod
1858*3d8817e4Smiod BFD_ASSERT (s != NULL);
1859*3d8817e4Smiod
1860*3d8817e4Smiod amt = strlen (name) + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1;
1861*3d8817e4Smiod tmp_name = bfd_malloc (amt);
1862*3d8817e4Smiod
1863*3d8817e4Smiod BFD_ASSERT (tmp_name);
1864*3d8817e4Smiod
1865*3d8817e4Smiod sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name);
1866*3d8817e4Smiod
1867*3d8817e4Smiod myh = coff_link_hash_lookup
1868*3d8817e4Smiod (coff_hash_table (info), tmp_name, FALSE, FALSE, TRUE);
1869*3d8817e4Smiod
1870*3d8817e4Smiod if (myh != NULL)
1871*3d8817e4Smiod {
1872*3d8817e4Smiod free (tmp_name);
1873*3d8817e4Smiod /* We've already seen this guy. */
1874*3d8817e4Smiod return;
1875*3d8817e4Smiod }
1876*3d8817e4Smiod
1877*3d8817e4Smiod bh = NULL;
1878*3d8817e4Smiod val = globals->thumb_glue_size + 1;
1879*3d8817e4Smiod bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name,
1880*3d8817e4Smiod BSF_GLOBAL, s, val, NULL, TRUE, FALSE, &bh);
1881*3d8817e4Smiod
1882*3d8817e4Smiod /* If we mark it 'thumb', the disassembler will do a better job. */
1883*3d8817e4Smiod myh = (struct coff_link_hash_entry *) bh;
1884*3d8817e4Smiod myh->class = C_THUMBEXTFUNC;
1885*3d8817e4Smiod
1886*3d8817e4Smiod free (tmp_name);
1887*3d8817e4Smiod
1888*3d8817e4Smiod /* Allocate another symbol to mark where we switch to arm mode. */
1889*3d8817e4Smiod
1890*3d8817e4Smiod #define CHANGE_TO_ARM "__%s_change_to_arm"
1891*3d8817e4Smiod #define BACK_FROM_ARM "__%s_back_from_arm"
1892*3d8817e4Smiod
1893*3d8817e4Smiod amt = strlen (name) + strlen (CHANGE_TO_ARM) + 1;
1894*3d8817e4Smiod tmp_name = bfd_malloc (amt);
1895*3d8817e4Smiod
1896*3d8817e4Smiod BFD_ASSERT (tmp_name);
1897*3d8817e4Smiod
1898*3d8817e4Smiod sprintf (tmp_name, globals->support_old_code ? BACK_FROM_ARM : CHANGE_TO_ARM, name);
1899*3d8817e4Smiod
1900*3d8817e4Smiod bh = NULL;
1901*3d8817e4Smiod val = globals->thumb_glue_size + (globals->support_old_code ? 8 : 4);
1902*3d8817e4Smiod bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name,
1903*3d8817e4Smiod BSF_LOCAL, s, val, NULL, TRUE, FALSE, &bh);
1904*3d8817e4Smiod
1905*3d8817e4Smiod free (tmp_name);
1906*3d8817e4Smiod
1907*3d8817e4Smiod globals->thumb_glue_size += THUMB2ARM_GLUE_SIZE;
1908*3d8817e4Smiod
1909*3d8817e4Smiod return;
1910*3d8817e4Smiod }
1911*3d8817e4Smiod #endif /* not ARM_WINCE */
1912*3d8817e4Smiod
1913*3d8817e4Smiod /* Select a BFD to be used to hold the sections used by the glue code.
1914*3d8817e4Smiod This function is called from the linker scripts in ld/emultempl/
1915*3d8817e4Smiod {armcoff/pe}.em */
1916*3d8817e4Smiod
1917*3d8817e4Smiod bfd_boolean
bfd_arm_get_bfd_for_interworking(bfd * abfd,struct bfd_link_info * info)1918*3d8817e4Smiod bfd_arm_get_bfd_for_interworking (bfd * abfd,
1919*3d8817e4Smiod struct bfd_link_info * info)
1920*3d8817e4Smiod {
1921*3d8817e4Smiod struct coff_arm_link_hash_table * globals;
1922*3d8817e4Smiod flagword flags;
1923*3d8817e4Smiod asection * sec;
1924*3d8817e4Smiod
1925*3d8817e4Smiod /* If we are only performing a partial link do not bother
1926*3d8817e4Smiod getting a bfd to hold the glue. */
1927*3d8817e4Smiod if (info->relocatable)
1928*3d8817e4Smiod return TRUE;
1929*3d8817e4Smiod
1930*3d8817e4Smiod globals = coff_arm_hash_table (info);
1931*3d8817e4Smiod
1932*3d8817e4Smiod BFD_ASSERT (globals != NULL);
1933*3d8817e4Smiod
1934*3d8817e4Smiod if (globals->bfd_of_glue_owner != NULL)
1935*3d8817e4Smiod return TRUE;
1936*3d8817e4Smiod
1937*3d8817e4Smiod sec = bfd_get_section_by_name (abfd, ARM2THUMB_GLUE_SECTION_NAME);
1938*3d8817e4Smiod
1939*3d8817e4Smiod if (sec == NULL)
1940*3d8817e4Smiod {
1941*3d8817e4Smiod flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_CODE | SEC_READONLY;
1942*3d8817e4Smiod
1943*3d8817e4Smiod sec = bfd_make_section (abfd, ARM2THUMB_GLUE_SECTION_NAME);
1944*3d8817e4Smiod
1945*3d8817e4Smiod if (sec == NULL
1946*3d8817e4Smiod || ! bfd_set_section_flags (abfd, sec, flags)
1947*3d8817e4Smiod || ! bfd_set_section_alignment (abfd, sec, 2))
1948*3d8817e4Smiod return FALSE;
1949*3d8817e4Smiod }
1950*3d8817e4Smiod
1951*3d8817e4Smiod sec = bfd_get_section_by_name (abfd, THUMB2ARM_GLUE_SECTION_NAME);
1952*3d8817e4Smiod
1953*3d8817e4Smiod if (sec == NULL)
1954*3d8817e4Smiod {
1955*3d8817e4Smiod flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_CODE | SEC_READONLY;
1956*3d8817e4Smiod
1957*3d8817e4Smiod sec = bfd_make_section (abfd, THUMB2ARM_GLUE_SECTION_NAME);
1958*3d8817e4Smiod
1959*3d8817e4Smiod if (sec == NULL
1960*3d8817e4Smiod || ! bfd_set_section_flags (abfd, sec, flags)
1961*3d8817e4Smiod || ! bfd_set_section_alignment (abfd, sec, 2))
1962*3d8817e4Smiod return FALSE;
1963*3d8817e4Smiod }
1964*3d8817e4Smiod
1965*3d8817e4Smiod /* Save the bfd for later use. */
1966*3d8817e4Smiod globals->bfd_of_glue_owner = abfd;
1967*3d8817e4Smiod
1968*3d8817e4Smiod return TRUE;
1969*3d8817e4Smiod }
1970*3d8817e4Smiod
1971*3d8817e4Smiod bfd_boolean
bfd_arm_process_before_allocation(bfd * abfd,struct bfd_link_info * info,int support_old_code)1972*3d8817e4Smiod bfd_arm_process_before_allocation (bfd * abfd,
1973*3d8817e4Smiod struct bfd_link_info * info,
1974*3d8817e4Smiod int support_old_code)
1975*3d8817e4Smiod {
1976*3d8817e4Smiod asection * sec;
1977*3d8817e4Smiod struct coff_arm_link_hash_table * globals;
1978*3d8817e4Smiod
1979*3d8817e4Smiod /* If we are only performing a partial link do not bother
1980*3d8817e4Smiod to construct any glue. */
1981*3d8817e4Smiod if (info->relocatable)
1982*3d8817e4Smiod return TRUE;
1983*3d8817e4Smiod
1984*3d8817e4Smiod /* Here we have a bfd that is to be included on the link. We have a hook
1985*3d8817e4Smiod to do reloc rummaging, before section sizes are nailed down. */
1986*3d8817e4Smiod _bfd_coff_get_external_symbols (abfd);
1987*3d8817e4Smiod
1988*3d8817e4Smiod globals = coff_arm_hash_table (info);
1989*3d8817e4Smiod
1990*3d8817e4Smiod BFD_ASSERT (globals != NULL);
1991*3d8817e4Smiod BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
1992*3d8817e4Smiod
1993*3d8817e4Smiod globals->support_old_code = support_old_code;
1994*3d8817e4Smiod
1995*3d8817e4Smiod /* Rummage around all the relocs and map the glue vectors. */
1996*3d8817e4Smiod sec = abfd->sections;
1997*3d8817e4Smiod
1998*3d8817e4Smiod if (sec == NULL)
1999*3d8817e4Smiod return TRUE;
2000*3d8817e4Smiod
2001*3d8817e4Smiod for (; sec != NULL; sec = sec->next)
2002*3d8817e4Smiod {
2003*3d8817e4Smiod struct internal_reloc * i;
2004*3d8817e4Smiod struct internal_reloc * rel;
2005*3d8817e4Smiod
2006*3d8817e4Smiod if (sec->reloc_count == 0)
2007*3d8817e4Smiod continue;
2008*3d8817e4Smiod
2009*3d8817e4Smiod /* Load the relocs. */
2010*3d8817e4Smiod /* FIXME: there may be a storage leak here. */
2011*3d8817e4Smiod i = _bfd_coff_read_internal_relocs (abfd, sec, 1, 0, 0, 0);
2012*3d8817e4Smiod
2013*3d8817e4Smiod BFD_ASSERT (i != 0);
2014*3d8817e4Smiod
2015*3d8817e4Smiod for (rel = i; rel < i + sec->reloc_count; ++rel)
2016*3d8817e4Smiod {
2017*3d8817e4Smiod unsigned short r_type = rel->r_type;
2018*3d8817e4Smiod long symndx;
2019*3d8817e4Smiod struct coff_link_hash_entry * h;
2020*3d8817e4Smiod
2021*3d8817e4Smiod symndx = rel->r_symndx;
2022*3d8817e4Smiod
2023*3d8817e4Smiod /* If the relocation is not against a symbol it cannot concern us. */
2024*3d8817e4Smiod if (symndx == -1)
2025*3d8817e4Smiod continue;
2026*3d8817e4Smiod
2027*3d8817e4Smiod /* If the index is outside of the range of our table, something has gone wrong. */
2028*3d8817e4Smiod if (symndx >= obj_conv_table_size (abfd))
2029*3d8817e4Smiod {
2030*3d8817e4Smiod _bfd_error_handler (_("%B: illegal symbol index in reloc: %d"),
2031*3d8817e4Smiod abfd, symndx);
2032*3d8817e4Smiod continue;
2033*3d8817e4Smiod }
2034*3d8817e4Smiod
2035*3d8817e4Smiod h = obj_coff_sym_hashes (abfd)[symndx];
2036*3d8817e4Smiod
2037*3d8817e4Smiod /* If the relocation is against a static symbol it must be within
2038*3d8817e4Smiod the current section and so cannot be a cross ARM/Thumb relocation. */
2039*3d8817e4Smiod if (h == NULL)
2040*3d8817e4Smiod continue;
2041*3d8817e4Smiod
2042*3d8817e4Smiod switch (r_type)
2043*3d8817e4Smiod {
2044*3d8817e4Smiod case ARM_26:
2045*3d8817e4Smiod /* This one is a call from arm code. We need to look up
2046*3d8817e4Smiod the target of the call. If it is a thumb target, we
2047*3d8817e4Smiod insert glue. */
2048*3d8817e4Smiod
2049*3d8817e4Smiod if (h->class == C_THUMBEXTFUNC)
2050*3d8817e4Smiod record_arm_to_thumb_glue (info, h);
2051*3d8817e4Smiod break;
2052*3d8817e4Smiod
2053*3d8817e4Smiod #ifndef ARM_WINCE
2054*3d8817e4Smiod case ARM_THUMB23:
2055*3d8817e4Smiod /* This one is a call from thumb code. We used to look
2056*3d8817e4Smiod for ARM_THUMB9 and ARM_THUMB12 as well. We need to look
2057*3d8817e4Smiod up the target of the call. If it is an arm target, we
2058*3d8817e4Smiod insert glue. If the symbol does not exist it will be
2059*3d8817e4Smiod given a class of C_EXT and so we will generate a stub
2060*3d8817e4Smiod for it. This is not really a problem, since the link
2061*3d8817e4Smiod is doomed anyway. */
2062*3d8817e4Smiod
2063*3d8817e4Smiod switch (h->class)
2064*3d8817e4Smiod {
2065*3d8817e4Smiod case C_EXT:
2066*3d8817e4Smiod case C_STAT:
2067*3d8817e4Smiod case C_LABEL:
2068*3d8817e4Smiod record_thumb_to_arm_glue (info, h);
2069*3d8817e4Smiod break;
2070*3d8817e4Smiod default:
2071*3d8817e4Smiod ;
2072*3d8817e4Smiod }
2073*3d8817e4Smiod break;
2074*3d8817e4Smiod #endif
2075*3d8817e4Smiod
2076*3d8817e4Smiod default:
2077*3d8817e4Smiod break;
2078*3d8817e4Smiod }
2079*3d8817e4Smiod }
2080*3d8817e4Smiod }
2081*3d8817e4Smiod
2082*3d8817e4Smiod return TRUE;
2083*3d8817e4Smiod }
2084*3d8817e4Smiod
2085*3d8817e4Smiod #endif /* ! defined (COFF_IMAGE_WITH_PE) */
2086*3d8817e4Smiod
2087*3d8817e4Smiod #define coff_bfd_reloc_type_lookup coff_arm_reloc_type_lookup
2088*3d8817e4Smiod #define coff_relocate_section coff_arm_relocate_section
2089*3d8817e4Smiod #define coff_bfd_is_local_label_name coff_arm_is_local_label_name
2090*3d8817e4Smiod #define coff_adjust_symndx coff_arm_adjust_symndx
2091*3d8817e4Smiod #define coff_link_output_has_begun coff_arm_link_output_has_begun
2092*3d8817e4Smiod #define coff_final_link_postscript coff_arm_final_link_postscript
2093*3d8817e4Smiod #define coff_bfd_merge_private_bfd_data coff_arm_merge_private_bfd_data
2094*3d8817e4Smiod #define coff_bfd_print_private_bfd_data coff_arm_print_private_bfd_data
2095*3d8817e4Smiod #define coff_bfd_set_private_flags _bfd_coff_arm_set_private_flags
2096*3d8817e4Smiod #define coff_bfd_copy_private_bfd_data coff_arm_copy_private_bfd_data
2097*3d8817e4Smiod #define coff_bfd_link_hash_table_create coff_arm_link_hash_table_create
2098*3d8817e4Smiod
2099*3d8817e4Smiod /* When doing a relocatable link, we want to convert ARM_26 relocs
2100*3d8817e4Smiod into ARM_26D relocs. */
2101*3d8817e4Smiod
2102*3d8817e4Smiod static bfd_boolean
coff_arm_adjust_symndx(bfd * obfd ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED,bfd * ibfd,asection * sec,struct internal_reloc * irel,bfd_boolean * adjustedp)2103*3d8817e4Smiod coff_arm_adjust_symndx (bfd *obfd ATTRIBUTE_UNUSED,
2104*3d8817e4Smiod struct bfd_link_info *info ATTRIBUTE_UNUSED,
2105*3d8817e4Smiod bfd *ibfd,
2106*3d8817e4Smiod asection *sec,
2107*3d8817e4Smiod struct internal_reloc *irel,
2108*3d8817e4Smiod bfd_boolean *adjustedp)
2109*3d8817e4Smiod {
2110*3d8817e4Smiod if (irel->r_type == ARM_26)
2111*3d8817e4Smiod {
2112*3d8817e4Smiod struct coff_link_hash_entry *h;
2113*3d8817e4Smiod
2114*3d8817e4Smiod h = obj_coff_sym_hashes (ibfd)[irel->r_symndx];
2115*3d8817e4Smiod if (h != NULL
2116*3d8817e4Smiod && (h->root.type == bfd_link_hash_defined
2117*3d8817e4Smiod || h->root.type == bfd_link_hash_defweak)
2118*3d8817e4Smiod && h->root.u.def.section->output_section == sec->output_section)
2119*3d8817e4Smiod irel->r_type = ARM_26D;
2120*3d8817e4Smiod }
2121*3d8817e4Smiod *adjustedp = FALSE;
2122*3d8817e4Smiod return TRUE;
2123*3d8817e4Smiod }
2124*3d8817e4Smiod
2125*3d8817e4Smiod /* Called when merging the private data areas of two BFDs.
2126*3d8817e4Smiod This is important as it allows us to detect if we are
2127*3d8817e4Smiod attempting to merge binaries compiled for different ARM
2128*3d8817e4Smiod targets, eg different CPUs or different APCS's. */
2129*3d8817e4Smiod
2130*3d8817e4Smiod static bfd_boolean
coff_arm_merge_private_bfd_data(bfd * ibfd,bfd * obfd)2131*3d8817e4Smiod coff_arm_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
2132*3d8817e4Smiod {
2133*3d8817e4Smiod BFD_ASSERT (ibfd != NULL && obfd != NULL);
2134*3d8817e4Smiod
2135*3d8817e4Smiod if (ibfd == obfd)
2136*3d8817e4Smiod return TRUE;
2137*3d8817e4Smiod
2138*3d8817e4Smiod /* If the two formats are different we cannot merge anything.
2139*3d8817e4Smiod This is not an error, since it is permissable to change the
2140*3d8817e4Smiod input and output formats. */
2141*3d8817e4Smiod if ( ibfd->xvec->flavour != bfd_target_coff_flavour
2142*3d8817e4Smiod || obfd->xvec->flavour != bfd_target_coff_flavour)
2143*3d8817e4Smiod return TRUE;
2144*3d8817e4Smiod
2145*3d8817e4Smiod /* Determine what should happen if the input ARM architecture
2146*3d8817e4Smiod does not match the output ARM architecture. */
2147*3d8817e4Smiod if (! bfd_arm_merge_machines (ibfd, obfd))
2148*3d8817e4Smiod return FALSE;
2149*3d8817e4Smiod
2150*3d8817e4Smiod /* Verify that the APCS is the same for the two BFDs. */
2151*3d8817e4Smiod if (APCS_SET (ibfd))
2152*3d8817e4Smiod {
2153*3d8817e4Smiod if (APCS_SET (obfd))
2154*3d8817e4Smiod {
2155*3d8817e4Smiod /* If the src and dest have different APCS flag bits set, fail. */
2156*3d8817e4Smiod if (APCS_26_FLAG (obfd) != APCS_26_FLAG (ibfd))
2157*3d8817e4Smiod {
2158*3d8817e4Smiod _bfd_error_handler
2159*3d8817e4Smiod /* xgettext: c-format */
2160*3d8817e4Smiod (_("ERROR: %B is compiled for APCS-%d, whereas %B is compiled for APCS-%d"),
2161*3d8817e4Smiod ibfd, obfd,
2162*3d8817e4Smiod APCS_26_FLAG (ibfd) ? 26 : 32,
2163*3d8817e4Smiod APCS_26_FLAG (obfd) ? 26 : 32
2164*3d8817e4Smiod );
2165*3d8817e4Smiod
2166*3d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
2167*3d8817e4Smiod return FALSE;
2168*3d8817e4Smiod }
2169*3d8817e4Smiod
2170*3d8817e4Smiod if (APCS_FLOAT_FLAG (obfd) != APCS_FLOAT_FLAG (ibfd))
2171*3d8817e4Smiod {
2172*3d8817e4Smiod const char *msg;
2173*3d8817e4Smiod
2174*3d8817e4Smiod if (APCS_FLOAT_FLAG (ibfd))
2175*3d8817e4Smiod /* xgettext: c-format */
2176*3d8817e4Smiod msg = _("ERROR: %B passes floats in float registers, whereas %B passes them in integer registers");
2177*3d8817e4Smiod else
2178*3d8817e4Smiod /* xgettext: c-format */
2179*3d8817e4Smiod msg = _("ERROR: %B passes floats in integer registers, whereas %B passes them in float registers");
2180*3d8817e4Smiod
2181*3d8817e4Smiod _bfd_error_handler (msg, ibfd, obfd);
2182*3d8817e4Smiod
2183*3d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
2184*3d8817e4Smiod return FALSE;
2185*3d8817e4Smiod }
2186*3d8817e4Smiod
2187*3d8817e4Smiod if (PIC_FLAG (obfd) != PIC_FLAG (ibfd))
2188*3d8817e4Smiod {
2189*3d8817e4Smiod const char * msg;
2190*3d8817e4Smiod
2191*3d8817e4Smiod if (PIC_FLAG (ibfd))
2192*3d8817e4Smiod /* xgettext: c-format */
2193*3d8817e4Smiod msg = _("ERROR: %B is compiled as position independent code, whereas target %B is absolute position");
2194*3d8817e4Smiod else
2195*3d8817e4Smiod /* xgettext: c-format */
2196*3d8817e4Smiod msg = _("ERROR: %B is compiled as absolute position code, whereas target %B is position independent");
2197*3d8817e4Smiod _bfd_error_handler (msg, ibfd, obfd);
2198*3d8817e4Smiod
2199*3d8817e4Smiod bfd_set_error (bfd_error_wrong_format);
2200*3d8817e4Smiod return FALSE;
2201*3d8817e4Smiod }
2202*3d8817e4Smiod }
2203*3d8817e4Smiod else
2204*3d8817e4Smiod {
2205*3d8817e4Smiod SET_APCS_FLAGS (obfd, APCS_26_FLAG (ibfd) | APCS_FLOAT_FLAG (ibfd) | PIC_FLAG (ibfd));
2206*3d8817e4Smiod
2207*3d8817e4Smiod /* Set up the arch and fields as well as these are probably wrong. */
2208*3d8817e4Smiod bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
2209*3d8817e4Smiod }
2210*3d8817e4Smiod }
2211*3d8817e4Smiod
2212*3d8817e4Smiod /* Check the interworking support. */
2213*3d8817e4Smiod if (INTERWORK_SET (ibfd))
2214*3d8817e4Smiod {
2215*3d8817e4Smiod if (INTERWORK_SET (obfd))
2216*3d8817e4Smiod {
2217*3d8817e4Smiod /* If the src and dest differ in their interworking issue a warning. */
2218*3d8817e4Smiod if (INTERWORK_FLAG (obfd) != INTERWORK_FLAG (ibfd))
2219*3d8817e4Smiod {
2220*3d8817e4Smiod const char * msg;
2221*3d8817e4Smiod
2222*3d8817e4Smiod if (INTERWORK_FLAG (ibfd))
2223*3d8817e4Smiod /* xgettext: c-format */
2224*3d8817e4Smiod msg = _("Warning: %B supports interworking, whereas %B does not");
2225*3d8817e4Smiod else
2226*3d8817e4Smiod /* xgettext: c-format */
2227*3d8817e4Smiod msg = _("Warning: %B does not support interworking, whereas %B does");
2228*3d8817e4Smiod
2229*3d8817e4Smiod _bfd_error_handler (msg, ibfd, obfd);
2230*3d8817e4Smiod }
2231*3d8817e4Smiod }
2232*3d8817e4Smiod else
2233*3d8817e4Smiod {
2234*3d8817e4Smiod SET_INTERWORK_FLAG (obfd, INTERWORK_FLAG (ibfd));
2235*3d8817e4Smiod }
2236*3d8817e4Smiod }
2237*3d8817e4Smiod
2238*3d8817e4Smiod return TRUE;
2239*3d8817e4Smiod }
2240*3d8817e4Smiod
2241*3d8817e4Smiod /* Display the flags field. */
2242*3d8817e4Smiod
2243*3d8817e4Smiod static bfd_boolean
coff_arm_print_private_bfd_data(bfd * abfd,void * ptr)2244*3d8817e4Smiod coff_arm_print_private_bfd_data (bfd * abfd, void * ptr)
2245*3d8817e4Smiod {
2246*3d8817e4Smiod FILE * file = (FILE *) ptr;
2247*3d8817e4Smiod
2248*3d8817e4Smiod BFD_ASSERT (abfd != NULL && ptr != NULL);
2249*3d8817e4Smiod
2250*3d8817e4Smiod /* xgettext:c-format */
2251*3d8817e4Smiod fprintf (file, _("private flags = %x:"), coff_data (abfd)->flags);
2252*3d8817e4Smiod
2253*3d8817e4Smiod if (APCS_SET (abfd))
2254*3d8817e4Smiod {
2255*3d8817e4Smiod /* xgettext: APCS is ARM Procedure Call Standard, it should not be translated. */
2256*3d8817e4Smiod fprintf (file, " [APCS-%d]", APCS_26_FLAG (abfd) ? 26 : 32);
2257*3d8817e4Smiod
2258*3d8817e4Smiod if (APCS_FLOAT_FLAG (abfd))
2259*3d8817e4Smiod fprintf (file, _(" [floats passed in float registers]"));
2260*3d8817e4Smiod else
2261*3d8817e4Smiod fprintf (file, _(" [floats passed in integer registers]"));
2262*3d8817e4Smiod
2263*3d8817e4Smiod if (PIC_FLAG (abfd))
2264*3d8817e4Smiod fprintf (file, _(" [position independent]"));
2265*3d8817e4Smiod else
2266*3d8817e4Smiod fprintf (file, _(" [absolute position]"));
2267*3d8817e4Smiod }
2268*3d8817e4Smiod
2269*3d8817e4Smiod if (! INTERWORK_SET (abfd))
2270*3d8817e4Smiod fprintf (file, _(" [interworking flag not initialised]"));
2271*3d8817e4Smiod else if (INTERWORK_FLAG (abfd))
2272*3d8817e4Smiod fprintf (file, _(" [interworking supported]"));
2273*3d8817e4Smiod else
2274*3d8817e4Smiod fprintf (file, _(" [interworking not supported]"));
2275*3d8817e4Smiod
2276*3d8817e4Smiod fputc ('\n', file);
2277*3d8817e4Smiod
2278*3d8817e4Smiod return TRUE;
2279*3d8817e4Smiod }
2280*3d8817e4Smiod
2281*3d8817e4Smiod /* Copies the given flags into the coff_tdata.flags field.
2282*3d8817e4Smiod Typically these flags come from the f_flags[] field of
2283*3d8817e4Smiod the COFF filehdr structure, which contains important,
2284*3d8817e4Smiod target specific information.
2285*3d8817e4Smiod Note: Although this function is static, it is explicitly
2286*3d8817e4Smiod called from both coffcode.h and peicode.h. */
2287*3d8817e4Smiod
2288*3d8817e4Smiod static bfd_boolean
_bfd_coff_arm_set_private_flags(bfd * abfd,flagword flags)2289*3d8817e4Smiod _bfd_coff_arm_set_private_flags (bfd * abfd, flagword flags)
2290*3d8817e4Smiod {
2291*3d8817e4Smiod flagword flag;
2292*3d8817e4Smiod
2293*3d8817e4Smiod BFD_ASSERT (abfd != NULL);
2294*3d8817e4Smiod
2295*3d8817e4Smiod flag = (flags & F_APCS26) ? F_APCS_26 : 0;
2296*3d8817e4Smiod
2297*3d8817e4Smiod /* Make sure that the APCS field has not been initialised to the opposite
2298*3d8817e4Smiod value. */
2299*3d8817e4Smiod if (APCS_SET (abfd)
2300*3d8817e4Smiod && ( (APCS_26_FLAG (abfd) != flag)
2301*3d8817e4Smiod || (APCS_FLOAT_FLAG (abfd) != (flags & F_APCS_FLOAT))
2302*3d8817e4Smiod || (PIC_FLAG (abfd) != (flags & F_PIC))
2303*3d8817e4Smiod ))
2304*3d8817e4Smiod return FALSE;
2305*3d8817e4Smiod
2306*3d8817e4Smiod flag |= (flags & (F_APCS_FLOAT | F_PIC));
2307*3d8817e4Smiod
2308*3d8817e4Smiod SET_APCS_FLAGS (abfd, flag);
2309*3d8817e4Smiod
2310*3d8817e4Smiod flag = (flags & F_INTERWORK);
2311*3d8817e4Smiod
2312*3d8817e4Smiod /* If the BFD has already had its interworking flag set, but it
2313*3d8817e4Smiod is different from the value that we have been asked to set,
2314*3d8817e4Smiod then assume that that merged code will not support interworking
2315*3d8817e4Smiod and set the flag accordingly. */
2316*3d8817e4Smiod if (INTERWORK_SET (abfd) && (INTERWORK_FLAG (abfd) != flag))
2317*3d8817e4Smiod {
2318*3d8817e4Smiod if (flag)
2319*3d8817e4Smiod /* xgettext: c-format */
2320*3d8817e4Smiod _bfd_error_handler (_("Warning: Not setting interworking flag of %B since it has already been specified as non-interworking"),
2321*3d8817e4Smiod abfd);
2322*3d8817e4Smiod else
2323*3d8817e4Smiod /* xgettext: c-format */
2324*3d8817e4Smiod _bfd_error_handler (_("Warning: Clearing the interworking flag of %B due to outside request"),
2325*3d8817e4Smiod abfd);
2326*3d8817e4Smiod flag = 0;
2327*3d8817e4Smiod }
2328*3d8817e4Smiod
2329*3d8817e4Smiod SET_INTERWORK_FLAG (abfd, flag);
2330*3d8817e4Smiod
2331*3d8817e4Smiod return TRUE;
2332*3d8817e4Smiod }
2333*3d8817e4Smiod
2334*3d8817e4Smiod /* Copy the important parts of the target specific data
2335*3d8817e4Smiod from one instance of a BFD to another. */
2336*3d8817e4Smiod
2337*3d8817e4Smiod static bfd_boolean
coff_arm_copy_private_bfd_data(bfd * src,bfd * dest)2338*3d8817e4Smiod coff_arm_copy_private_bfd_data (bfd * src, bfd * dest)
2339*3d8817e4Smiod {
2340*3d8817e4Smiod BFD_ASSERT (src != NULL && dest != NULL);
2341*3d8817e4Smiod
2342*3d8817e4Smiod if (src == dest)
2343*3d8817e4Smiod return TRUE;
2344*3d8817e4Smiod
2345*3d8817e4Smiod /* If the destination is not in the same format as the source, do not do
2346*3d8817e4Smiod the copy. */
2347*3d8817e4Smiod if (src->xvec != dest->xvec)
2348*3d8817e4Smiod return TRUE;
2349*3d8817e4Smiod
2350*3d8817e4Smiod /* Copy the flags field. */
2351*3d8817e4Smiod if (APCS_SET (src))
2352*3d8817e4Smiod {
2353*3d8817e4Smiod if (APCS_SET (dest))
2354*3d8817e4Smiod {
2355*3d8817e4Smiod /* If the src and dest have different APCS flag bits set, fail. */
2356*3d8817e4Smiod if (APCS_26_FLAG (dest) != APCS_26_FLAG (src))
2357*3d8817e4Smiod return FALSE;
2358*3d8817e4Smiod
2359*3d8817e4Smiod if (APCS_FLOAT_FLAG (dest) != APCS_FLOAT_FLAG (src))
2360*3d8817e4Smiod return FALSE;
2361*3d8817e4Smiod
2362*3d8817e4Smiod if (PIC_FLAG (dest) != PIC_FLAG (src))
2363*3d8817e4Smiod return FALSE;
2364*3d8817e4Smiod }
2365*3d8817e4Smiod else
2366*3d8817e4Smiod SET_APCS_FLAGS (dest, APCS_26_FLAG (src) | APCS_FLOAT_FLAG (src)
2367*3d8817e4Smiod | PIC_FLAG (src));
2368*3d8817e4Smiod }
2369*3d8817e4Smiod
2370*3d8817e4Smiod if (INTERWORK_SET (src))
2371*3d8817e4Smiod {
2372*3d8817e4Smiod if (INTERWORK_SET (dest))
2373*3d8817e4Smiod {
2374*3d8817e4Smiod /* If the src and dest have different interworking flags then turn
2375*3d8817e4Smiod off the interworking bit. */
2376*3d8817e4Smiod if (INTERWORK_FLAG (dest) != INTERWORK_FLAG (src))
2377*3d8817e4Smiod {
2378*3d8817e4Smiod if (INTERWORK_FLAG (dest))
2379*3d8817e4Smiod {
2380*3d8817e4Smiod /* xgettext:c-format */
2381*3d8817e4Smiod _bfd_error_handler (("\
2382*3d8817e4Smiod Warning: Clearing the interworking flag of %B because non-interworking code in %B has been linked with it"),
2383*3d8817e4Smiod dest, src);
2384*3d8817e4Smiod }
2385*3d8817e4Smiod
2386*3d8817e4Smiod SET_INTERWORK_FLAG (dest, 0);
2387*3d8817e4Smiod }
2388*3d8817e4Smiod }
2389*3d8817e4Smiod else
2390*3d8817e4Smiod {
2391*3d8817e4Smiod SET_INTERWORK_FLAG (dest, INTERWORK_FLAG (src));
2392*3d8817e4Smiod }
2393*3d8817e4Smiod }
2394*3d8817e4Smiod
2395*3d8817e4Smiod return TRUE;
2396*3d8817e4Smiod }
2397*3d8817e4Smiod
2398*3d8817e4Smiod /* Note: the definitions here of LOCAL_LABEL_PREFIX and USER_LABEL_PREIFX
2399*3d8817e4Smiod *must* match the definitions in gcc/config/arm/{coff|semi|aout}.h. */
2400*3d8817e4Smiod #define LOCAL_LABEL_PREFIX ""
2401*3d8817e4Smiod #ifndef USER_LABEL_PREFIX
2402*3d8817e4Smiod #define USER_LABEL_PREFIX "_"
2403*3d8817e4Smiod #endif
2404*3d8817e4Smiod
2405*3d8817e4Smiod /* Like _bfd_coff_is_local_label_name, but
2406*3d8817e4Smiod a) test against USER_LABEL_PREFIX, to avoid stripping labels known to be
2407*3d8817e4Smiod non-local.
2408*3d8817e4Smiod b) Allow other prefixes than ".", e.g. an empty prefix would cause all
2409*3d8817e4Smiod labels of the form Lxxx to be stripped. */
2410*3d8817e4Smiod
2411*3d8817e4Smiod static bfd_boolean
coff_arm_is_local_label_name(bfd * abfd ATTRIBUTE_UNUSED,const char * name)2412*3d8817e4Smiod coff_arm_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED,
2413*3d8817e4Smiod const char * name)
2414*3d8817e4Smiod {
2415*3d8817e4Smiod #ifdef USER_LABEL_PREFIX
2416*3d8817e4Smiod if (USER_LABEL_PREFIX[0] != 0)
2417*3d8817e4Smiod {
2418*3d8817e4Smiod size_t len = strlen (USER_LABEL_PREFIX);
2419*3d8817e4Smiod
2420*3d8817e4Smiod if (strncmp (name, USER_LABEL_PREFIX, len) == 0)
2421*3d8817e4Smiod return FALSE;
2422*3d8817e4Smiod }
2423*3d8817e4Smiod #endif
2424*3d8817e4Smiod
2425*3d8817e4Smiod #ifdef LOCAL_LABEL_PREFIX
2426*3d8817e4Smiod /* If there is a prefix for local labels then look for this.
2427*3d8817e4Smiod If the prefix exists, but it is empty, then ignore the test. */
2428*3d8817e4Smiod
2429*3d8817e4Smiod if (LOCAL_LABEL_PREFIX[0] != 0)
2430*3d8817e4Smiod {
2431*3d8817e4Smiod size_t len = strlen (LOCAL_LABEL_PREFIX);
2432*3d8817e4Smiod
2433*3d8817e4Smiod if (strncmp (name, LOCAL_LABEL_PREFIX, len) != 0)
2434*3d8817e4Smiod return FALSE;
2435*3d8817e4Smiod
2436*3d8817e4Smiod /* Perform the checks below for the rest of the name. */
2437*3d8817e4Smiod name += len;
2438*3d8817e4Smiod }
2439*3d8817e4Smiod #endif
2440*3d8817e4Smiod
2441*3d8817e4Smiod return name[0] == 'L';
2442*3d8817e4Smiod }
2443*3d8817e4Smiod
2444*3d8817e4Smiod /* This piece of machinery exists only to guarantee that the bfd that holds
2445*3d8817e4Smiod the glue section is written last.
2446*3d8817e4Smiod
2447*3d8817e4Smiod This does depend on bfd_make_section attaching a new section to the
2448*3d8817e4Smiod end of the section list for the bfd. */
2449*3d8817e4Smiod
2450*3d8817e4Smiod static bfd_boolean
coff_arm_link_output_has_begun(bfd * sub,struct coff_final_link_info * info)2451*3d8817e4Smiod coff_arm_link_output_has_begun (bfd * sub, struct coff_final_link_info * info)
2452*3d8817e4Smiod {
2453*3d8817e4Smiod return (sub->output_has_begun
2454*3d8817e4Smiod || sub == coff_arm_hash_table (info->info)->bfd_of_glue_owner);
2455*3d8817e4Smiod }
2456*3d8817e4Smiod
2457*3d8817e4Smiod static bfd_boolean
coff_arm_final_link_postscript(bfd * abfd ATTRIBUTE_UNUSED,struct coff_final_link_info * pfinfo)2458*3d8817e4Smiod coff_arm_final_link_postscript (bfd * abfd ATTRIBUTE_UNUSED,
2459*3d8817e4Smiod struct coff_final_link_info * pfinfo)
2460*3d8817e4Smiod {
2461*3d8817e4Smiod struct coff_arm_link_hash_table * globals;
2462*3d8817e4Smiod
2463*3d8817e4Smiod globals = coff_arm_hash_table (pfinfo->info);
2464*3d8817e4Smiod
2465*3d8817e4Smiod BFD_ASSERT (globals != NULL);
2466*3d8817e4Smiod
2467*3d8817e4Smiod if (globals->bfd_of_glue_owner != NULL)
2468*3d8817e4Smiod {
2469*3d8817e4Smiod if (! _bfd_coff_link_input_bfd (pfinfo, globals->bfd_of_glue_owner))
2470*3d8817e4Smiod return FALSE;
2471*3d8817e4Smiod
2472*3d8817e4Smiod globals->bfd_of_glue_owner->output_has_begun = TRUE;
2473*3d8817e4Smiod }
2474*3d8817e4Smiod
2475*3d8817e4Smiod return bfd_arm_update_notes (abfd, ARM_NOTE_SECTION);
2476*3d8817e4Smiod }
2477*3d8817e4Smiod
2478*3d8817e4Smiod #include "coffcode.h"
2479*3d8817e4Smiod
2480*3d8817e4Smiod #ifndef TARGET_LITTLE_SYM
2481*3d8817e4Smiod #define TARGET_LITTLE_SYM armcoff_little_vec
2482*3d8817e4Smiod #endif
2483*3d8817e4Smiod #ifndef TARGET_LITTLE_NAME
2484*3d8817e4Smiod #define TARGET_LITTLE_NAME "coff-arm-little"
2485*3d8817e4Smiod #endif
2486*3d8817e4Smiod #ifndef TARGET_BIG_SYM
2487*3d8817e4Smiod #define TARGET_BIG_SYM armcoff_big_vec
2488*3d8817e4Smiod #endif
2489*3d8817e4Smiod #ifndef TARGET_BIG_NAME
2490*3d8817e4Smiod #define TARGET_BIG_NAME "coff-arm-big"
2491*3d8817e4Smiod #endif
2492*3d8817e4Smiod
2493*3d8817e4Smiod #ifndef TARGET_UNDERSCORE
2494*3d8817e4Smiod #define TARGET_UNDERSCORE 0
2495*3d8817e4Smiod #endif
2496*3d8817e4Smiod
2497*3d8817e4Smiod #ifndef EXTRA_S_FLAGS
2498*3d8817e4Smiod #ifdef COFF_WITH_PE
2499*3d8817e4Smiod #define EXTRA_S_FLAGS (SEC_CODE | SEC_LINK_ONCE | SEC_LINK_DUPLICATES)
2500*3d8817e4Smiod #else
2501*3d8817e4Smiod #define EXTRA_S_FLAGS SEC_CODE
2502*3d8817e4Smiod #endif
2503*3d8817e4Smiod #endif
2504*3d8817e4Smiod
2505*3d8817e4Smiod /* Forward declaration for use initialising alternative_target field. */
2506*3d8817e4Smiod extern const bfd_target TARGET_BIG_SYM ;
2507*3d8817e4Smiod
2508*3d8817e4Smiod /* Target vectors. */
2509*3d8817e4Smiod CREATE_LITTLE_COFF_TARGET_VEC (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME, D_PAGED, EXTRA_S_FLAGS, TARGET_UNDERSCORE, & TARGET_BIG_SYM, COFF_SWAP_TABLE)
2510*3d8817e4Smiod CREATE_BIG_COFF_TARGET_VEC (TARGET_BIG_SYM, TARGET_BIG_NAME, D_PAGED, EXTRA_S_FLAGS, TARGET_UNDERSCORE, & TARGET_LITTLE_SYM, COFF_SWAP_TABLE)
2511