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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [bfd/] [coff-arm.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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