Coverage Report

Created: 2026-07-25 10:20

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