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