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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [coff-arm.c] - Blame information for rev 146

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

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