Coverage Report

Created: 2023-08-28 06:28

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