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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [gdb-5.3/] [bfd/] [coff-arm.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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