OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [bfd/] [coff-arm.c] - Blame information for rev 853

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.