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