Back to index

cell-binutils  2.17cvs20070401
coff-arm.c
Go to the documentation of this file.
00001 /* BFD back-end for ARM COFF files.
00002    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
00003    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
00004    Free Software Foundation, Inc.
00005    Written by Cygnus Support.
00006 
00007    This file is part of BFD, the Binary File Descriptor library.
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013 
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00022 
00023 #include "bfd.h"
00024 #include "sysdep.h"
00025 #include "libbfd.h"
00026 #include "coff/arm.h"
00027 #include "coff/internal.h"
00028 
00029 #ifdef COFF_WITH_PE
00030 #include "coff/pe.h"
00031 #endif
00032 
00033 #include "libcoff.h"
00034 
00035 /* Macros for manipulation the bits in the flags field of the coff data
00036    structure.  */
00037 #define APCS_26_FLAG(abfd) \
00038   (coff_data (abfd)->flags & F_APCS_26)
00039 
00040 #define APCS_FLOAT_FLAG(abfd) \
00041   (coff_data (abfd)->flags & F_APCS_FLOAT)
00042 
00043 #define PIC_FLAG(abfd) \
00044   (coff_data (abfd)->flags & F_PIC)
00045 
00046 #define APCS_SET(abfd) \
00047   (coff_data (abfd)->flags & F_APCS_SET)
00048 
00049 #define SET_APCS_FLAGS(abfd, flgs) \
00050   do                                                           \
00051     {                                                          \
00052       coff_data (abfd)->flags &= ~(F_APCS_26 | F_APCS_FLOAT | F_PIC); \
00053       coff_data (abfd)->flags |= (flgs) | F_APCS_SET;                 \
00054     }                                                          \
00055   while (0)
00056 
00057 #define INTERWORK_FLAG(abfd) \
00058   (coff_data (abfd)->flags & F_INTERWORK)
00059 
00060 #define INTERWORK_SET(abfd) \
00061   (coff_data (abfd)->flags & F_INTERWORK_SET)
00062 
00063 #define SET_INTERWORK_FLAG(abfd, flg) \
00064   do                                                           \
00065     {                                                          \
00066       coff_data (abfd)->flags &= ~F_INTERWORK;                        \
00067       coff_data (abfd)->flags |= (flg) | F_INTERWORK_SET;             \
00068     }                                                          \
00069   while (0)
00070 
00071 #ifndef NUM_ELEM
00072 #define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))
00073 #endif
00074 
00075 typedef enum {bunknown, b9, b12, b23} thumb_pcrel_branchtype;
00076 /* Some typedefs for holding instructions.  */
00077 typedef unsigned long int insn32;
00078 typedef unsigned short int insn16;
00079 
00080 /* The linker script knows the section names for placement.
00081    The entry_names are used to do simple name mangling on the stubs.
00082    Given a function name, and its type, the stub can be found. The
00083    name can be changed. The only requirement is the %s be present.  */
00084 
00085 #define THUMB2ARM_GLUE_SECTION_NAME ".glue_7t"
00086 #define THUMB2ARM_GLUE_ENTRY_NAME   "__%s_from_thumb"
00087 
00088 #define ARM2THUMB_GLUE_SECTION_NAME ".glue_7"
00089 #define ARM2THUMB_GLUE_ENTRY_NAME   "__%s_from_arm"
00090 
00091 /* Used by the assembler.  */
00092 
00093 static bfd_reloc_status_type
00094 coff_arm_reloc (bfd *abfd,
00095               arelent *reloc_entry,
00096               asymbol *symbol ATTRIBUTE_UNUSED,
00097               void * data,
00098               asection *input_section ATTRIBUTE_UNUSED,
00099               bfd *output_bfd,
00100               char **error_message ATTRIBUTE_UNUSED)
00101 {
00102   symvalue diff;
00103 
00104   if (output_bfd == NULL)
00105     return bfd_reloc_continue;
00106 
00107   diff = reloc_entry->addend;
00108 
00109 #define DOIT(x)                                                \
00110   x = ((x & ~howto->dst_mask)                                  \
00111        | (((x & howto->src_mask) + diff) & howto->dst_mask))
00112 
00113     if (diff != 0)
00114       {
00115        reloc_howto_type *howto = reloc_entry->howto;
00116        unsigned char *addr = (unsigned char *) data + reloc_entry->address;
00117 
00118        switch (howto->size)
00119          {
00120          case 0:
00121            {
00122              char x = bfd_get_8 (abfd, addr);
00123              DOIT (x);
00124              bfd_put_8 (abfd, x, addr);
00125            }
00126            break;
00127 
00128          case 1:
00129            {
00130              short x = bfd_get_16 (abfd, addr);
00131              DOIT (x);
00132              bfd_put_16 (abfd, (bfd_vma) x, addr);
00133            }
00134            break;
00135 
00136          case 2:
00137            {
00138              long x = bfd_get_32 (abfd, addr);
00139              DOIT (x);
00140              bfd_put_32 (abfd, (bfd_vma) x, addr);
00141            }
00142            break;
00143 
00144          default:
00145            abort ();
00146          }
00147       }
00148 
00149   /* Now let bfd_perform_relocation finish everything up.  */
00150   return bfd_reloc_continue;
00151 }
00152 
00153 /* If USER_LABEL_PREFIX is defined as "_" (see coff_arm_is_local_label_name()
00154    in this file), then TARGET_UNDERSCORE should be defined, otherwise it
00155    should not.  */
00156 #ifndef TARGET_UNDERSCORE
00157 #define TARGET_UNDERSCORE '_'
00158 #endif
00159 
00160 #ifndef PCRELOFFSET
00161 #define PCRELOFFSET TRUE
00162 #endif
00163 
00164 /* These most certainly belong somewhere else. Just had to get rid of
00165    the manifest constants in the code.  */
00166 
00167 #ifdef ARM_WINCE
00168 
00169 #define ARM_26D      0
00170 #define ARM_32       1
00171 #define ARM_RVA32    2
00172 #define ARM_26            3
00173 #define ARM_THUMB12  4
00174 #define ARM_SECTION  14
00175 #define ARM_SECREL   15
00176 
00177 #else
00178 
00179 #define ARM_8        0
00180 #define ARM_16       1
00181 #define ARM_32       2
00182 #define ARM_26       3
00183 #define ARM_DISP8    4
00184 #define ARM_DISP16   5
00185 #define ARM_DISP32   6
00186 #define ARM_26D      7
00187 /* 8 is unused.  */
00188 #define ARM_NEG16    9
00189 #define ARM_NEG32   10
00190 #define ARM_RVA32   11
00191 #define ARM_THUMB9  12
00192 #define ARM_THUMB12 13
00193 #define ARM_THUMB23 14
00194 
00195 #endif
00196 
00197 static bfd_reloc_status_type aoutarm_fix_pcrel_26_done
00198   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
00199 static bfd_reloc_status_type aoutarm_fix_pcrel_26
00200   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
00201 static bfd_reloc_status_type coff_thumb_pcrel_12
00202   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
00203 #ifndef ARM_WINCE
00204 static bfd_reloc_status_type coff_thumb_pcrel_9
00205   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
00206 static bfd_reloc_status_type coff_thumb_pcrel_23
00207   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
00208 #endif
00209 
00210 static reloc_howto_type aoutarm_std_reloc_howto[] =
00211   {
00212 #ifdef ARM_WINCE
00213     HOWTO (ARM_26D,
00214           2,
00215           2,
00216           24,
00217           TRUE,
00218           0,
00219           complain_overflow_dont,
00220           aoutarm_fix_pcrel_26_done,
00221           "ARM_26D",
00222           TRUE,      /* partial_inplace.  */
00223           0x00ffffff,
00224           0x0,
00225           PCRELOFFSET),
00226     HOWTO (ARM_32,
00227           0,
00228           2,
00229           32,
00230           FALSE,
00231           0,
00232           complain_overflow_bitfield,
00233           coff_arm_reloc,
00234           "ARM_32",
00235           TRUE,      /* partial_inplace.  */
00236           0xffffffff,
00237           0xffffffff,
00238           PCRELOFFSET),
00239     HOWTO (ARM_RVA32,
00240           0,
00241           2,
00242           32,
00243           FALSE,
00244           0,
00245           complain_overflow_bitfield,
00246           coff_arm_reloc,
00247           "ARM_RVA32",
00248           TRUE,      /* partial_inplace.  */
00249           0xffffffff,
00250           0xffffffff,
00251           PCRELOFFSET),
00252     HOWTO (ARM_26,
00253           2,
00254           2,
00255           24,
00256           TRUE,
00257           0,
00258           complain_overflow_signed,
00259           aoutarm_fix_pcrel_26 ,
00260           "ARM_26",
00261           FALSE,
00262           0x00ffffff,
00263           0x00ffffff,
00264           PCRELOFFSET),
00265     HOWTO (ARM_THUMB12,
00266           1,
00267           1,
00268           11,
00269           TRUE,
00270           0,
00271           complain_overflow_signed,
00272           coff_thumb_pcrel_12 ,
00273           "ARM_THUMB12",
00274           FALSE,
00275           0x000007ff,
00276           0x000007ff,
00277           PCRELOFFSET),
00278     EMPTY_HOWTO (-1),
00279     EMPTY_HOWTO (-1),
00280     EMPTY_HOWTO (-1),
00281     EMPTY_HOWTO (-1),
00282     EMPTY_HOWTO (-1),
00283     EMPTY_HOWTO (-1),
00284     EMPTY_HOWTO (-1),
00285     EMPTY_HOWTO (-1),
00286     EMPTY_HOWTO (-1),
00287     HOWTO (ARM_SECTION,
00288           0,
00289           1,
00290           16,
00291           FALSE,
00292           0,
00293           complain_overflow_bitfield,
00294           coff_arm_reloc,
00295           "ARM_SECTION",
00296           TRUE,      /* partial_inplace.  */
00297           0x0000ffff,
00298           0x0000ffff,
00299           PCRELOFFSET),
00300     HOWTO (ARM_SECREL,
00301           0,
00302           2,
00303           32,
00304           FALSE,
00305           0,
00306           complain_overflow_bitfield,
00307           coff_arm_reloc,
00308           "ARM_SECREL",
00309           TRUE,      /* partial_inplace.  */
00310           0xffffffff,
00311           0xffffffff,
00312           PCRELOFFSET),
00313 #else /* not ARM_WINCE */
00314     HOWTO (ARM_8,
00315           0,
00316           0,
00317           8,
00318           FALSE,
00319           0,
00320           complain_overflow_bitfield,
00321           coff_arm_reloc,
00322           "ARM_8",
00323           TRUE,
00324           0x000000ff,
00325           0x000000ff,
00326           PCRELOFFSET),
00327     HOWTO (ARM_16,
00328           0,
00329           1,
00330           16,
00331           FALSE,
00332           0,
00333           complain_overflow_bitfield,
00334           coff_arm_reloc,
00335           "ARM_16",
00336           TRUE,
00337           0x0000ffff,
00338           0x0000ffff,
00339           PCRELOFFSET),
00340     HOWTO (ARM_32,
00341           0,
00342           2,
00343           32,
00344           FALSE,
00345           0,
00346           complain_overflow_bitfield,
00347           coff_arm_reloc,
00348           "ARM_32",
00349           TRUE,
00350           0xffffffff,
00351           0xffffffff,
00352           PCRELOFFSET),
00353     HOWTO (ARM_26,
00354           2,
00355           2,
00356           24,
00357           TRUE,
00358           0,
00359           complain_overflow_signed,
00360           aoutarm_fix_pcrel_26 ,
00361           "ARM_26",
00362           FALSE,
00363           0x00ffffff,
00364           0x00ffffff,
00365           PCRELOFFSET),
00366     HOWTO (ARM_DISP8,
00367           0,
00368           0,
00369           8,
00370           TRUE,
00371           0,
00372           complain_overflow_signed,
00373           coff_arm_reloc,
00374           "ARM_DISP8",
00375           TRUE,
00376           0x000000ff,
00377           0x000000ff,
00378           TRUE),
00379     HOWTO (ARM_DISP16,
00380           0,
00381           1,
00382           16,
00383           TRUE,
00384           0,
00385           complain_overflow_signed,
00386           coff_arm_reloc,
00387           "ARM_DISP16",
00388           TRUE,
00389           0x0000ffff,
00390           0x0000ffff,
00391           TRUE),
00392     HOWTO (ARM_DISP32,
00393           0,
00394           2,
00395           32,
00396           TRUE,
00397           0,
00398           complain_overflow_signed,
00399           coff_arm_reloc,
00400           "ARM_DISP32",
00401           TRUE,
00402           0xffffffff,
00403           0xffffffff,
00404           TRUE),
00405     HOWTO (ARM_26D,
00406           2,
00407           2,
00408           24,
00409           FALSE,
00410           0,
00411           complain_overflow_dont,
00412           aoutarm_fix_pcrel_26_done,
00413           "ARM_26D",
00414           TRUE,
00415           0x00ffffff,
00416           0x0,
00417           FALSE),
00418     /* 8 is unused */
00419     EMPTY_HOWTO (-1),
00420     HOWTO (ARM_NEG16,
00421           0,
00422           -1,
00423           16,
00424           FALSE,
00425           0,
00426           complain_overflow_bitfield,
00427           coff_arm_reloc,
00428           "ARM_NEG16",
00429           TRUE,
00430           0x0000ffff,
00431           0x0000ffff,
00432           FALSE),
00433     HOWTO (ARM_NEG32,
00434           0,
00435           -2,
00436           32,
00437           FALSE,
00438           0,
00439           complain_overflow_bitfield,
00440           coff_arm_reloc,
00441           "ARM_NEG32",
00442           TRUE,
00443           0xffffffff,
00444           0xffffffff,
00445           FALSE),
00446     HOWTO (ARM_RVA32,
00447           0,
00448           2,
00449           32,
00450           FALSE,
00451           0,
00452           complain_overflow_bitfield,
00453           coff_arm_reloc,
00454           "ARM_RVA32",
00455           TRUE,
00456           0xffffffff,
00457           0xffffffff,
00458           PCRELOFFSET),
00459     HOWTO (ARM_THUMB9,
00460           1,
00461           1,
00462           8,
00463           TRUE,
00464           0,
00465           complain_overflow_signed,
00466           coff_thumb_pcrel_9 ,
00467           "ARM_THUMB9",
00468           FALSE,
00469           0x000000ff,
00470           0x000000ff,
00471           PCRELOFFSET),
00472     HOWTO (ARM_THUMB12,
00473           1,
00474           1,
00475           11,
00476           TRUE,
00477           0,
00478           complain_overflow_signed,
00479           coff_thumb_pcrel_12 ,
00480           "ARM_THUMB12",
00481           FALSE,
00482           0x000007ff,
00483           0x000007ff,
00484           PCRELOFFSET),
00485     HOWTO (ARM_THUMB23,
00486           1,
00487           2,
00488           22,
00489           TRUE,
00490           0,
00491           complain_overflow_signed,
00492           coff_thumb_pcrel_23 ,
00493           "ARM_THUMB23",
00494           FALSE,
00495           0x07ff07ff,
00496           0x07ff07ff,
00497           PCRELOFFSET)
00498 #endif /* not ARM_WINCE */
00499   };
00500 
00501 #define NUM_RELOCS NUM_ELEM (aoutarm_std_reloc_howto)
00502 
00503 #ifdef COFF_WITH_PE
00504 /* Return TRUE if this relocation should
00505    appear in the output .reloc section.  */
00506 
00507 static bfd_boolean
00508 in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED,
00509            reloc_howto_type * howto)
00510 {
00511   return !howto->pc_relative && howto->type != ARM_RVA32;
00512 }
00513 #endif
00514 
00515 #define RTYPE2HOWTO(cache_ptr, dst)              \
00516   (cache_ptr)->howto =                           \
00517     (dst)->r_type < NUM_RELOCS                   \
00518     ? aoutarm_std_reloc_howto + (dst)->r_type    \
00519     : NULL
00520 
00521 #define coff_rtype_to_howto coff_arm_rtype_to_howto
00522 
00523 static reloc_howto_type *
00524 coff_arm_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
00525                       asection *sec,
00526                       struct internal_reloc *rel,
00527                       struct coff_link_hash_entry *h ATTRIBUTE_UNUSED,
00528                       struct internal_syment *sym ATTRIBUTE_UNUSED,
00529                       bfd_vma *addendp)
00530 {
00531   reloc_howto_type * howto;
00532 
00533   if (rel->r_type >= NUM_RELOCS)
00534     return NULL;
00535 
00536   howto = aoutarm_std_reloc_howto + rel->r_type;
00537 
00538   if (rel->r_type == ARM_RVA32)
00539     *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
00540 
00541 #if defined COFF_WITH_PE && defined ARM_WINCE
00542   if (rel->r_type == ARM_SECREL)
00543     {
00544       bfd_vma osect_vma;
00545 
00546       if (h && (h->type == bfd_link_hash_defined
00547               || h->type == bfd_link_hash_defweak))
00548        osect_vma = h->root.u.def.section->output_section->vma;
00549       else
00550        {
00551          asection *sec;
00552          int i;
00553 
00554          /* Sigh, the only way to get the section to offset against
00555             is to find it the hard way.  */
00556 
00557          for (sec = abfd->sections, i = 1; i < sym->n_scnum; i++)
00558            sec = sec->next;
00559 
00560          osect_vma = sec->output_section->vma;
00561        }
00562 
00563       *addendp -= osect_vma;
00564     }
00565 #endif
00566 
00567   return howto;
00568 }
00569 
00570 /* Used by the assembler.  */
00571 
00572 static bfd_reloc_status_type
00573 aoutarm_fix_pcrel_26_done (bfd *abfd ATTRIBUTE_UNUSED,
00574                         arelent *reloc_entry ATTRIBUTE_UNUSED,
00575                         asymbol *symbol ATTRIBUTE_UNUSED,
00576                         void * data ATTRIBUTE_UNUSED,
00577                         asection *input_section ATTRIBUTE_UNUSED,
00578                         bfd *output_bfd ATTRIBUTE_UNUSED,
00579                         char **error_message ATTRIBUTE_UNUSED)
00580 {
00581   /* This is dead simple at present.  */
00582   return bfd_reloc_ok;
00583 }
00584 
00585 /* Used by the assembler.  */
00586 
00587 static bfd_reloc_status_type
00588 aoutarm_fix_pcrel_26 (bfd *abfd,
00589                     arelent *reloc_entry,
00590                     asymbol *symbol,
00591                     void * data,
00592                     asection *input_section,
00593                     bfd *output_bfd,
00594                     char **error_message ATTRIBUTE_UNUSED)
00595 {
00596   bfd_vma relocation;
00597   bfd_size_type addr = reloc_entry->address;
00598   long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
00599   bfd_reloc_status_type flag = bfd_reloc_ok;
00600 
00601   /* If this is an undefined symbol, return error.  */
00602   if (symbol->section == &bfd_und_section
00603       && (symbol->flags & BSF_WEAK) == 0)
00604     return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
00605 
00606   /* If the sections are different, and we are doing a partial relocation,
00607      just ignore it for now.  */
00608   if (symbol->section->name != input_section->name
00609       && output_bfd != (bfd *)NULL)
00610     return bfd_reloc_continue;
00611 
00612   relocation = (target & 0x00ffffff) << 2;
00613   relocation = (relocation ^ 0x02000000) - 0x02000000; /* Sign extend.  */
00614   relocation += symbol->value;
00615   relocation += symbol->section->output_section->vma;
00616   relocation += symbol->section->output_offset;
00617   relocation += reloc_entry->addend;
00618   relocation -= input_section->output_section->vma;
00619   relocation -= input_section->output_offset;
00620   relocation -= addr;
00621 
00622   if (relocation & 3)
00623     return bfd_reloc_overflow;
00624 
00625   /* Check for overflow.  */
00626   if (relocation & 0x02000000)
00627     {
00628       if ((relocation & ~ (bfd_vma) 0x03ffffff) != ~ (bfd_vma) 0x03ffffff)
00629        flag = bfd_reloc_overflow;
00630     }
00631   else if (relocation & ~(bfd_vma) 0x03ffffff)
00632     flag = bfd_reloc_overflow;
00633 
00634   target &= ~0x00ffffff;
00635   target |= (relocation >> 2) & 0x00ffffff;
00636   bfd_put_32 (abfd, (bfd_vma) target, (bfd_byte *) data + addr);
00637 
00638   /* Now the ARM magic... Change the reloc type so that it is marked as done.
00639      Strictly this is only necessary if we are doing a partial relocation.  */
00640   reloc_entry->howto = &aoutarm_std_reloc_howto[ARM_26D];
00641 
00642   return flag;
00643 }
00644 
00645 static bfd_reloc_status_type
00646 coff_thumb_pcrel_common (bfd *abfd,
00647                       arelent *reloc_entry,
00648                       asymbol *symbol,
00649                       void * data,
00650                       asection *input_section,
00651                       bfd *output_bfd,
00652                       char **error_message ATTRIBUTE_UNUSED,
00653                       thumb_pcrel_branchtype btype)
00654 {
00655   bfd_vma relocation = 0;
00656   bfd_size_type addr = reloc_entry->address;
00657   long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
00658   bfd_reloc_status_type flag = bfd_reloc_ok;
00659   bfd_vma dstmsk;
00660   bfd_vma offmsk;
00661   bfd_vma signbit;
00662 
00663   /* NOTE: This routine is currently used by GAS, but not by the link
00664      phase.  */
00665   switch (btype)
00666     {
00667     case b9:
00668       dstmsk  = 0x000000ff;
00669       offmsk  = 0x000001fe;
00670       signbit = 0x00000100;
00671       break;
00672 
00673     case b12:
00674       dstmsk  = 0x000007ff;
00675       offmsk  = 0x00000ffe;
00676       signbit = 0x00000800;
00677       break;
00678 
00679     case b23:
00680       dstmsk  = 0x07ff07ff;
00681       offmsk  = 0x007fffff;
00682       signbit = 0x00400000;
00683       break;
00684 
00685     default:
00686       abort ();
00687     }
00688 
00689   /* If this is an undefined symbol, return error.  */
00690   if (symbol->section == &bfd_und_section
00691       && (symbol->flags & BSF_WEAK) == 0)
00692     return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
00693 
00694   /* If the sections are different, and we are doing a partial relocation,
00695      just ignore it for now.  */
00696   if (symbol->section->name != input_section->name
00697       && output_bfd != (bfd *)NULL)
00698     return bfd_reloc_continue;
00699 
00700   switch (btype)
00701     {
00702     case b9:
00703     case b12:
00704       relocation = ((target & dstmsk) << 1);
00705       break;
00706 
00707     case b23:
00708       if (bfd_big_endian (abfd))
00709        relocation = ((target & 0x7ff) << 1)  | ((target & 0x07ff0000) >> 4);
00710       else
00711        relocation = ((target & 0x7ff) << 12) | ((target & 0x07ff0000) >> 15);
00712       break;
00713 
00714     default:
00715       abort ();
00716     }
00717 
00718   relocation = (relocation ^ signbit) - signbit; /* Sign extend.  */
00719   relocation += symbol->value;
00720   relocation += symbol->section->output_section->vma;
00721   relocation += symbol->section->output_offset;
00722   relocation += reloc_entry->addend;
00723   relocation -= input_section->output_section->vma;
00724   relocation -= input_section->output_offset;
00725   relocation -= addr;
00726 
00727   if (relocation & 1)
00728     return bfd_reloc_overflow;
00729 
00730   /* Check for overflow.  */
00731   if (relocation & signbit)
00732     {
00733       if ((relocation & ~offmsk) != ~offmsk)
00734        flag = bfd_reloc_overflow;
00735     }
00736   else if (relocation & ~offmsk)
00737     flag = bfd_reloc_overflow;
00738 
00739   target &= ~dstmsk;
00740   switch (btype)
00741    {
00742    case b9:
00743    case b12:
00744      target |= (relocation >> 1);
00745      break;
00746 
00747    case b23:
00748      if (bfd_big_endian (abfd))
00749        target |= (((relocation & 0xfff) >> 1)
00750                 | ((relocation << 4)  & 0x07ff0000));
00751      else
00752        target |= (((relocation & 0xffe) << 15)
00753                 | ((relocation >> 12) & 0x7ff));
00754      break;
00755 
00756    default:
00757      abort ();
00758    }
00759 
00760   bfd_put_32 (abfd, (bfd_vma) target, (bfd_byte *) data + addr);
00761 
00762   /* Now the ARM magic... Change the reloc type so that it is marked as done.
00763      Strictly this is only necessary if we are doing a partial relocation.  */
00764   reloc_entry->howto = & aoutarm_std_reloc_howto [ARM_26D];
00765 
00766   /* TODO: We should possibly have DONE entries for the THUMB PCREL relocations.  */
00767   return flag;
00768 }
00769 
00770 #ifndef ARM_WINCE
00771 static bfd_reloc_status_type
00772 coff_thumb_pcrel_23 (bfd *abfd,
00773                    arelent *reloc_entry,
00774                    asymbol *symbol,
00775                    void * data,
00776                    asection *input_section,
00777                    bfd *output_bfd,
00778                    char **error_message)
00779 {
00780   return coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data,
00781                                   input_section, output_bfd, error_message,
00782                               b23);
00783 }
00784 
00785 static bfd_reloc_status_type
00786 coff_thumb_pcrel_9 (bfd *abfd,
00787                   arelent *reloc_entry,
00788                   asymbol *symbol,
00789                   void * data,
00790                   asection *input_section,
00791                   bfd *output_bfd,
00792                   char **error_message)
00793 {
00794   return coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data,
00795                                   input_section, output_bfd, error_message,
00796                               b9);
00797 }
00798 #endif /* not ARM_WINCE */
00799 
00800 static bfd_reloc_status_type
00801 coff_thumb_pcrel_12 (bfd *abfd,
00802                    arelent *reloc_entry,
00803                    asymbol *symbol,
00804                    void * data,
00805                    asection *input_section,
00806                    bfd *output_bfd,
00807                    char **error_message)
00808 {
00809   return coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data,
00810                                   input_section, output_bfd, error_message,
00811                               b12);
00812 }
00813 
00814 static const struct reloc_howto_struct *
00815 coff_arm_reloc_type_lookup (bfd * abfd, bfd_reloc_code_real_type code)
00816 {
00817 #define ASTD(i,j)       case i: return aoutarm_std_reloc_howto + j
00818 
00819   if (code == BFD_RELOC_CTOR)
00820     switch (bfd_get_arch_info (abfd)->bits_per_address)
00821       {
00822       case 32:
00823         code = BFD_RELOC_32;
00824         break;
00825       default:
00826        return NULL;
00827       }
00828 
00829   switch (code)
00830     {
00831 #ifdef ARM_WINCE
00832       ASTD (BFD_RELOC_32,                   ARM_32);
00833       ASTD (BFD_RELOC_RVA,                  ARM_RVA32);
00834       ASTD (BFD_RELOC_ARM_PCREL_BRANCH,     ARM_26);
00835       ASTD (BFD_RELOC_THUMB_PCREL_BRANCH12, ARM_THUMB12);
00836       ASTD (BFD_RELOC_32_SECREL,            ARM_SECREL);
00837 #else
00838       ASTD (BFD_RELOC_8,                    ARM_8);
00839       ASTD (BFD_RELOC_16,                   ARM_16);
00840       ASTD (BFD_RELOC_32,                   ARM_32);
00841       ASTD (BFD_RELOC_ARM_PCREL_BRANCH,     ARM_26);
00842       ASTD (BFD_RELOC_ARM_PCREL_BLX,        ARM_26);
00843       ASTD (BFD_RELOC_8_PCREL,              ARM_DISP8);
00844       ASTD (BFD_RELOC_16_PCREL,             ARM_DISP16);
00845       ASTD (BFD_RELOC_32_PCREL,             ARM_DISP32);
00846       ASTD (BFD_RELOC_RVA,                  ARM_RVA32);
00847       ASTD (BFD_RELOC_THUMB_PCREL_BRANCH9,  ARM_THUMB9);
00848       ASTD (BFD_RELOC_THUMB_PCREL_BRANCH12, ARM_THUMB12);
00849       ASTD (BFD_RELOC_THUMB_PCREL_BRANCH23, ARM_THUMB23);
00850       ASTD (BFD_RELOC_THUMB_PCREL_BLX,      ARM_THUMB23);
00851 #endif
00852     default: return NULL;
00853     }
00854 }
00855 
00856 static reloc_howto_type *
00857 coff_arm_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00858                          const char *r_name)
00859 {
00860   unsigned int i;
00861 
00862   for (i = 0;
00863        i < (sizeof (aoutarm_std_reloc_howto)
00864            / sizeof (aoutarm_std_reloc_howto[0]));
00865        i++)
00866     if (aoutarm_std_reloc_howto[i].name != NULL
00867        && strcasecmp (aoutarm_std_reloc_howto[i].name, r_name) == 0)
00868       return &aoutarm_std_reloc_howto[i];
00869 
00870   return NULL;
00871 }
00872 
00873 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER  2
00874 #define COFF_PAGE_SIZE                        0x1000
00875 
00876 /* Turn a howto into a reloc  nunmber.  */
00877 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
00878 #define BADMAG(x)             ARMBADMAG(x)
00879 #define ARM                   1                  /* Customize coffcode.h.  */
00880 
00881 #ifndef ARM_WINCE
00882 /* Make sure that the 'r_offset' field is copied properly
00883    so that identical binaries will compare the same.  */
00884 #define SWAP_IN_RELOC_OFFSET       H_GET_32
00885 #define SWAP_OUT_RELOC_OFFSET      H_PUT_32
00886 #endif
00887 
00888 /* Extend the coff_link_hash_table structure with a few ARM specific fields.
00889    This allows us to store global data here without actually creating any
00890    global variables, which is a no-no in the BFD world.  */
00891 struct coff_arm_link_hash_table
00892   {
00893     /* The original coff_link_hash_table structure.  MUST be first field.  */
00894     struct coff_link_hash_table    root;
00895 
00896     /* The size in bytes of the section containing the Thumb-to-ARM glue.  */
00897     bfd_size_type           thumb_glue_size;
00898 
00899     /* The size in bytes of the section containing the ARM-to-Thumb glue.  */
00900     bfd_size_type           arm_glue_size;
00901 
00902     /* An arbitrary input BFD chosen to hold the glue sections.  */
00903     bfd *                   bfd_of_glue_owner;
00904 
00905     /* Support interworking with old, non-interworking aware ARM code.  */
00906     int                     support_old_code;
00907 };
00908 
00909 /* Get the ARM coff linker hash table from a link_info structure.  */
00910 #define coff_arm_hash_table(info) \
00911   ((struct coff_arm_link_hash_table *) ((info)->hash))
00912 
00913 /* Create an ARM coff linker hash table.  */
00914 
00915 static struct bfd_link_hash_table *
00916 coff_arm_link_hash_table_create (bfd * abfd)
00917 {
00918   struct coff_arm_link_hash_table * ret;
00919   bfd_size_type amt = sizeof (struct coff_arm_link_hash_table);
00920 
00921   ret = bfd_malloc (amt);
00922   if (ret == NULL)
00923     return NULL;
00924 
00925   if (!_bfd_coff_link_hash_table_init (&ret->root,
00926                                    abfd,
00927                                    _bfd_coff_link_hash_newfunc,
00928                                    sizeof (struct coff_link_hash_entry)))
00929     {
00930       free (ret);
00931       return NULL;
00932     }
00933 
00934   ret->thumb_glue_size   = 0;
00935   ret->arm_glue_size     = 0;
00936   ret->bfd_of_glue_owner = NULL;
00937 
00938   return & ret->root.root;
00939 }
00940 
00941 static void
00942 arm_emit_base_file_entry (struct bfd_link_info *info,
00943                        bfd *output_bfd,
00944                        asection *input_section,
00945                        bfd_vma reloc_offset)
00946 {
00947   bfd_vma addr = reloc_offset
00948                 - input_section->vma
00949                 + input_section->output_offset
00950                   + input_section->output_section->vma;
00951 
00952   if (coff_data (output_bfd)->pe)
00953      addr -= pe_data (output_bfd)->pe_opthdr.ImageBase;
00954   fwrite (& addr, 1, sizeof (addr), (FILE *) info->base_file);
00955 
00956 }
00957 
00958 #ifndef ARM_WINCE
00959 /* The thumb form of a long branch is a bit finicky, because the offset
00960    encoding is split over two fields, each in it's own instruction. They
00961    can occur in any order. So given a thumb form of long branch, and an
00962    offset, insert the offset into the thumb branch and return finished
00963    instruction.
00964 
00965    It takes two thumb instructions to encode the target address. Each has
00966    11 bits to invest. The upper 11 bits are stored in one (identified by
00967    H-0.. see below), the lower 11 bits are stored in the other (identified
00968    by H-1).
00969 
00970    Combine together and shifted left by 1 (it's a half word address) and
00971    there you have it.
00972 
00973      Op: 1111 = F,
00974      H-0, upper address-0 = 000
00975      Op: 1111 = F,
00976      H-1, lower address-0 = 800
00977 
00978    They can be ordered either way, but the arm tools I've seen always put
00979    the lower one first. It probably doesn't matter. krk@cygnus.com
00980 
00981    XXX:  Actually the order does matter.  The second instruction (H-1)
00982    moves the computed address into the PC, so it must be the second one
00983    in the sequence.  The problem, however is that whilst little endian code
00984    stores the instructions in HI then LOW order, big endian code does the
00985    reverse.  nickc@cygnus.com.  */
00986 
00987 #define LOW_HI_ORDER 0xF800F000
00988 #define HI_LOW_ORDER 0xF000F800
00989 
00990 static insn32
00991 insert_thumb_branch (insn32 br_insn, int rel_off)
00992 {
00993   unsigned int low_bits;
00994   unsigned int high_bits;
00995 
00996   BFD_ASSERT ((rel_off & 1) != 1);
00997 
00998   rel_off >>= 1;                              /* Half word aligned address.  */
00999   low_bits = rel_off & 0x000007FF;            /* The bottom 11 bits.  */
01000   high_bits = (rel_off >> 11) & 0x000007FF;   /* The top 11 bits.  */
01001 
01002   if ((br_insn & LOW_HI_ORDER) == LOW_HI_ORDER)
01003     br_insn = LOW_HI_ORDER | (low_bits << 16) | high_bits;
01004   else if ((br_insn & HI_LOW_ORDER) == HI_LOW_ORDER)
01005     br_insn = HI_LOW_ORDER | (high_bits << 16) | low_bits;
01006   else
01007     /* FIXME: the BFD library should never abort except for internal errors
01008        - it should return an error status.  */
01009     abort (); /* Error - not a valid branch instruction form.  */
01010 
01011   return br_insn;
01012 }
01013 
01014 
01015 static struct coff_link_hash_entry *
01016 find_thumb_glue (struct bfd_link_info *info,
01017                const char *name,
01018                bfd *input_bfd)
01019 {
01020   char *tmp_name;
01021   struct coff_link_hash_entry *myh;
01022   bfd_size_type amt = strlen (name) + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1;
01023 
01024   tmp_name = bfd_malloc (amt);
01025 
01026   BFD_ASSERT (tmp_name);
01027 
01028   sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name);
01029 
01030   myh = coff_link_hash_lookup
01031     (coff_hash_table (info), tmp_name, FALSE, FALSE, TRUE);
01032 
01033   if (myh == NULL)
01034     /* xgettext:c-format */
01035     _bfd_error_handler (_("%B: unable to find THUMB glue '%s' for `%s'"),
01036                      input_bfd, tmp_name, name);
01037 
01038   free (tmp_name);
01039 
01040   return myh;
01041 }
01042 #endif /* not ARM_WINCE */
01043 
01044 static struct coff_link_hash_entry *
01045 find_arm_glue (struct bfd_link_info *info,
01046               const char *name,
01047               bfd *input_bfd)
01048 {
01049   char *tmp_name;
01050   struct coff_link_hash_entry * myh;
01051   bfd_size_type amt = strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1;
01052 
01053   tmp_name = bfd_malloc (amt);
01054 
01055   BFD_ASSERT (tmp_name);
01056 
01057   sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);
01058 
01059   myh = coff_link_hash_lookup
01060     (coff_hash_table (info), tmp_name, FALSE, FALSE, TRUE);
01061 
01062   if (myh == NULL)
01063     /* xgettext:c-format */
01064     _bfd_error_handler (_("%B: unable to find ARM glue '%s' for `%s'"),
01065                      input_bfd, tmp_name, name);
01066 
01067   free (tmp_name);
01068 
01069   return myh;
01070 }
01071 
01072 /*
01073   ARM->Thumb glue:
01074 
01075        .arm
01076        __func_from_arm:
01077             ldr r12, __func_addr
01078             bx  r12
01079        __func_addr:
01080             .word func    @ behave as if you saw a ARM_32 reloc
01081 */
01082 
01083 #define ARM2THUMB_GLUE_SIZE 12
01084 static const insn32 a2t1_ldr_insn       = 0xe59fc000;
01085 static const insn32 a2t2_bx_r12_insn    = 0xe12fff1c;
01086 static const insn32 a2t3_func_addr_insn = 0x00000001;
01087 
01088 /*
01089    Thumb->ARM:                            Thumb->(non-interworking aware) ARM
01090 
01091    .thumb                          .thumb
01092    .align 2                        .align 2
01093       __func_from_thumb:              __func_from_thumb:
01094           bx pc                           push {r6, lr}
01095           nop                             ldr  r6, __func_addr
01096    .arm                                          mov  lr, pc
01097       __func_change_to_arm:               bx   r6
01098           b func                   .arm
01099                                       __func_back_to_thumb:
01100                                           ldmia r13! {r6, lr}
01101                                            bx    lr
01102                                       __func_addr:
01103                                            .word func
01104 */
01105 
01106 #define THUMB2ARM_GLUE_SIZE (globals->support_old_code ? 20 : 8)
01107 #ifndef ARM_WINCE
01108 static const insn16 t2a1_bx_pc_insn = 0x4778;
01109 static const insn16 t2a2_noop_insn  = 0x46c0;
01110 static const insn32 t2a3_b_insn     = 0xea000000;
01111 
01112 static const insn16 t2a1_push_insn  = 0xb540;
01113 static const insn16 t2a2_ldr_insn   = 0x4e03;
01114 static const insn16 t2a3_mov_insn   = 0x46fe;
01115 static const insn16 t2a4_bx_insn    = 0x4730;
01116 static const insn32 t2a5_pop_insn   = 0xe8bd4040;
01117 static const insn32 t2a6_bx_insn    = 0xe12fff1e;
01118 #endif
01119 
01120 /* TODO:
01121      We should really create new local (static) symbols in destination
01122      object for each stub we create.  We should also create local
01123      (static) symbols within the stubs when switching between ARM and
01124      Thumb code.  This will ensure that the debugger and disassembler
01125      can present a better view of stubs.
01126 
01127      We can treat stubs like literal sections, and for the THUMB9 ones
01128      (short addressing range) we should be able to insert the stubs
01129      between sections. i.e. the simplest approach (since relocations
01130      are done on a section basis) is to dump the stubs at the end of
01131      processing a section. That way we can always try and minimise the
01132      offset to and from a stub. However, this does not map well onto
01133      the way that the linker/BFD does its work: mapping all input
01134      sections to output sections via the linker script before doing
01135      all the processing.
01136 
01137      Unfortunately it may be easier to just to disallow short range
01138      Thumb->ARM stubs (i.e. no conditional inter-working branches,
01139      only branch-and-link (BL) calls.  This will simplify the processing
01140      since we can then put all of the stubs into their own section.
01141 
01142   TODO:
01143      On a different subject, rather than complaining when a
01144      branch cannot fit in the number of bits available for the
01145      instruction we should generate a trampoline stub (needed to
01146      address the complete 32bit address space).  */
01147 
01148 /* The standard COFF backend linker does not cope with the special
01149    Thumb BRANCH23 relocation.  The alternative would be to split the
01150    BRANCH23 into seperate HI23 and LO23 relocations. However, it is a
01151    bit simpler simply providing our own relocation driver.  */
01152 
01153 /* The reloc processing routine for the ARM/Thumb COFF linker.  NOTE:
01154    This code is a very slightly modified copy of
01155    _bfd_coff_generic_relocate_section.  It would be a much more
01156    maintainable solution to have a MACRO that could be expanded within
01157    _bfd_coff_generic_relocate_section that would only be provided for
01158    ARM/Thumb builds.  It is only the code marked THUMBEXTENSION that
01159    is different from the original.  */
01160 
01161 static bfd_boolean
01162 coff_arm_relocate_section (bfd *output_bfd,
01163                         struct bfd_link_info *info,
01164                         bfd *input_bfd,
01165                         asection *input_section,
01166                         bfd_byte *contents,
01167                         struct internal_reloc *relocs,
01168                         struct internal_syment *syms,
01169                         asection **sections)
01170 {
01171   struct internal_reloc * rel;
01172   struct internal_reloc * relend;
01173 #ifndef ARM_WINCE
01174   bfd_vma high_address = bfd_get_section_limit (input_bfd, input_section);
01175 #endif
01176 
01177   rel = relocs;
01178   relend = rel + input_section->reloc_count;
01179 
01180   for (; rel < relend; rel++)
01181     {
01182       int                            done = 0;
01183       long                           symndx;
01184       struct coff_link_hash_entry *  h;
01185       struct internal_syment *       sym;
01186       bfd_vma                        addend;
01187       bfd_vma                        val;
01188       reloc_howto_type *             howto;
01189       bfd_reloc_status_type          rstat;
01190       bfd_vma                        h_val;
01191 
01192       symndx = rel->r_symndx;
01193 
01194       if (symndx == -1)
01195        {
01196          h = NULL;
01197          sym = NULL;
01198        }
01199       else
01200        {
01201          h = obj_coff_sym_hashes (input_bfd)[symndx];
01202          sym = syms + symndx;
01203        }
01204 
01205       /* COFF treats common symbols in one of two ways.  Either the
01206          size of the symbol is included in the section contents, or it
01207          is not.  We assume that the size is not included, and force
01208          the rtype_to_howto function to adjust the addend as needed.  */
01209 
01210       if (sym != NULL && sym->n_scnum != 0)
01211        addend = - sym->n_value;
01212       else
01213        addend = 0;
01214 
01215       howto = coff_rtype_to_howto (input_bfd, input_section, rel, h,
01216                                    sym, &addend);
01217       if (howto == NULL)
01218        return FALSE;
01219 
01220       /* The relocation_section function will skip pcrel_offset relocs
01221          when doing a relocatable link.  However, we want to convert
01222          ARM_26 to ARM_26D relocs if possible.  We return a fake howto in
01223          this case without pcrel_offset set, and adjust the addend to
01224          compensate.  'partial_inplace' is also set, since we want 'done'
01225          relocations to be reflected in section's data.  */
01226       if (rel->r_type == ARM_26
01227           && h != NULL
01228           && info->relocatable
01229           && (h->root.type == bfd_link_hash_defined
01230              || h->root.type == bfd_link_hash_defweak)
01231           && (h->root.u.def.section->output_section
01232              == input_section->output_section))
01233         {
01234           static reloc_howto_type fake_arm26_reloc =
01235            HOWTO (ARM_26,
01236               2,
01237               2,
01238               24,
01239               TRUE,
01240               0,
01241               complain_overflow_signed,
01242               aoutarm_fix_pcrel_26 ,
01243               "ARM_26",
01244               TRUE,
01245               0x00ffffff,
01246               0x00ffffff,
01247               FALSE);
01248 
01249           addend -= rel->r_vaddr - input_section->vma;
01250 #ifdef ARM_WINCE
01251           /* FIXME: I don't know why, but the hack is necessary for correct
01252                     generation of bl's instruction offset.  */
01253           addend -= 8;
01254 #endif
01255           howto = & fake_arm26_reloc;
01256         }
01257 
01258 #ifdef ARM_WINCE
01259       /* MS ARM-CE makes the reloc relative to the opcode's pc, not
01260         the next opcode's pc, so is off by one.  */
01261       if (howto->pc_relative && !info->relocatable)
01262        addend -= 8;
01263 #endif
01264 
01265       /* If we are doing a relocatable link, then we can just ignore
01266          a PC relative reloc that is pcrel_offset.  It will already
01267          have the correct value.  If this is not a relocatable link,
01268          then we should ignore the symbol value.  */
01269       if (howto->pc_relative && howto->pcrel_offset)
01270         {
01271           if (info->relocatable)
01272             continue;
01273          /* FIXME - it is not clear which targets need this next test
01274             and which do not.  It is known that it is needed for the
01275             VxWorks and EPOC-PE targets, but it is also known that it
01276             was suppressed for other ARM targets.  This ought to be
01277             sorted out one day.  */
01278 #ifdef ARM_COFF_BUGFIX
01279          /* We must not ignore the symbol value.  If the symbol is
01280             within the same section, the relocation should have already
01281             been fixed, but if it is not, we'll be handed a reloc into
01282             the beginning of the symbol's section, so we must not cancel
01283             out the symbol's value, otherwise we'll be adding it in
01284             twice.  */
01285           if (sym != NULL && sym->n_scnum != 0)
01286             addend += sym->n_value;
01287 #endif
01288         }
01289 
01290       val = 0;
01291 
01292       if (h == NULL)
01293        {
01294          asection *sec;
01295 
01296          if (symndx == -1)
01297            {
01298              sec = bfd_abs_section_ptr;
01299              val = 0;
01300            }
01301          else
01302            {
01303              sec = sections[symndx];
01304               val = (sec->output_section->vma
01305                    + sec->output_offset
01306                    + sym->n_value
01307                    - sec->vma);
01308            }
01309        }
01310       else
01311        {
01312           /* We don't output the stubs if we are generating a
01313              relocatable output file, since we may as well leave the
01314              stub generation to the final linker pass. If we fail to
01315             verify that the name is defined, we'll try to build stubs
01316             for an undefined name...  */
01317           if (! info->relocatable
01318              && (   h->root.type == bfd_link_hash_defined
01319                 || h->root.type == bfd_link_hash_defweak))
01320             {
01321              asection *   h_sec = h->root.u.def.section;
01322              const char * name  = h->root.root.string;
01323 
01324              /* h locates the symbol referenced in the reloc.  */
01325              h_val = (h->root.u.def.value
01326                      + h_sec->output_section->vma
01327                      + h_sec->output_offset);
01328 
01329               if (howto->type == ARM_26)
01330                 {
01331                   if (   h->class == C_THUMBSTATFUNC
01332                     || h->class == C_THUMBEXTFUNC)
01333                   {
01334                     /* Arm code calling a Thumb function.  */
01335                     unsigned long int                 tmp;
01336                     bfd_vma                           my_offset;
01337                     asection *                        s;
01338                     long int                          ret_offset;
01339                     struct coff_link_hash_entry *     myh;
01340                     struct coff_arm_link_hash_table * globals;
01341 
01342                     myh = find_arm_glue (info, name, input_bfd);
01343                     if (myh == NULL)
01344                      return FALSE;
01345 
01346                     globals = coff_arm_hash_table (info);
01347 
01348                     BFD_ASSERT (globals != NULL);
01349                     BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
01350 
01351                     my_offset = myh->root.u.def.value;
01352 
01353                     s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
01354                                             ARM2THUMB_GLUE_SECTION_NAME);
01355                     BFD_ASSERT (s != NULL);
01356                     BFD_ASSERT (s->contents != NULL);
01357                     BFD_ASSERT (s->output_section != NULL);
01358 
01359                     if ((my_offset & 0x01) == 0x01)
01360                      {
01361                        if (h_sec->owner != NULL
01362                            && INTERWORK_SET (h_sec->owner)
01363                            && ! INTERWORK_FLAG (h_sec->owner))
01364                          _bfd_error_handler
01365                            /* xgettext:c-format */
01366                            (_("%B(%s): warning: interworking not enabled.\n"
01367                              "  first occurrence: %B: arm call to thumb"),
01368                             h_sec->owner, input_bfd, name);
01369 
01370                        --my_offset;
01371                        myh->root.u.def.value = my_offset;
01372 
01373                        bfd_put_32 (output_bfd, (bfd_vma) a2t1_ldr_insn,
01374                                   s->contents + my_offset);
01375 
01376                        bfd_put_32 (output_bfd, (bfd_vma) a2t2_bx_r12_insn,
01377                                   s->contents + my_offset + 4);
01378 
01379                        /* It's a thumb address.  Add the low order bit.  */
01380                        bfd_put_32 (output_bfd, h_val | a2t3_func_addr_insn,
01381                                   s->contents + my_offset + 8);
01382 
01383                           if (info->base_file)
01384                             arm_emit_base_file_entry (info, output_bfd, s,
01385                                                       my_offset + 8);
01386 
01387                      }
01388 
01389                     BFD_ASSERT (my_offset <= globals->arm_glue_size);
01390 
01391                     tmp = bfd_get_32 (input_bfd, contents + rel->r_vaddr
01392                                    - input_section->vma);
01393 
01394                     tmp = tmp & 0xFF000000;
01395 
01396                     /* Somehow these are both 4 too far, so subtract 8.  */
01397                     ret_offset =
01398                      s->output_offset
01399                      + my_offset
01400                      + s->output_section->vma
01401                      - (input_section->output_offset
01402                         + input_section->output_section->vma
01403                         + rel->r_vaddr)
01404                      - 8;
01405 
01406                     tmp = tmp | ((ret_offset >> 2) & 0x00FFFFFF);
01407 
01408                     bfd_put_32 (output_bfd, (bfd_vma) tmp,
01409                               contents + rel->r_vaddr - input_section->vma);
01410                     done = 1;
01411                   }
01412                 }
01413 
01414 #ifndef ARM_WINCE
01415              /* Note: We used to check for ARM_THUMB9 and ARM_THUMB12.  */
01416               else if (howto->type == ARM_THUMB23)
01417                 {
01418                   if (   h->class == C_EXT
01419                     || h->class == C_STAT
01420                     || h->class == C_LABEL)
01421                   {
01422                     /* Thumb code calling an ARM function.  */
01423                     asection *                         s = 0;
01424                     bfd_vma                            my_offset;
01425                     unsigned long int                  tmp;
01426                     long int                           ret_offset;
01427                     struct coff_link_hash_entry *      myh;
01428                     struct coff_arm_link_hash_table *  globals;
01429 
01430                     myh = find_thumb_glue (info, name, input_bfd);
01431                     if (myh == NULL)
01432                      return FALSE;
01433 
01434                     globals = coff_arm_hash_table (info);
01435 
01436                     BFD_ASSERT (globals != NULL);
01437                     BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
01438 
01439                     my_offset = myh->root.u.def.value;
01440 
01441                     s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
01442                                              THUMB2ARM_GLUE_SECTION_NAME);
01443 
01444                     BFD_ASSERT (s != NULL);
01445                     BFD_ASSERT (s->contents != NULL);
01446                     BFD_ASSERT (s->output_section != NULL);
01447 
01448                     if ((my_offset & 0x01) == 0x01)
01449                      {
01450                        if (h_sec->owner != NULL
01451                            && INTERWORK_SET (h_sec->owner)
01452                            && ! INTERWORK_FLAG (h_sec->owner)
01453                            && ! globals->support_old_code)
01454                          _bfd_error_handler
01455                            /* xgettext:c-format */
01456                            (_("%B(%s): warning: interworking not enabled.\n"
01457                              "  first occurrence: %B: thumb call to arm\n"
01458                              "  consider relinking with --support-old-code enabled"),
01459                             h_sec->owner, input_bfd, name);
01460 
01461                        -- my_offset;
01462                        myh->root.u.def.value = my_offset;
01463 
01464                        if (globals->support_old_code)
01465                          {
01466                            bfd_put_16 (output_bfd, (bfd_vma) t2a1_push_insn,
01467                                      s->contents + my_offset);
01468 
01469                            bfd_put_16 (output_bfd, (bfd_vma) t2a2_ldr_insn,
01470                                      s->contents + my_offset + 2);
01471 
01472                            bfd_put_16 (output_bfd, (bfd_vma) t2a3_mov_insn,
01473                                      s->contents + my_offset + 4);
01474 
01475                            bfd_put_16 (output_bfd, (bfd_vma) t2a4_bx_insn,
01476                                      s->contents + my_offset + 6);
01477 
01478                            bfd_put_32 (output_bfd, (bfd_vma) t2a5_pop_insn,
01479                                      s->contents + my_offset + 8);
01480 
01481                            bfd_put_32 (output_bfd, (bfd_vma) t2a6_bx_insn,
01482                                      s->contents + my_offset + 12);
01483 
01484                            /* Store the address of the function in the last word of the stub.  */
01485                            bfd_put_32 (output_bfd, h_val,
01486                                      s->contents + my_offset + 16);
01487 
01488                               if (info->base_file)
01489                                 arm_emit_base_file_entry (info, output_bfd, s,
01490                                                    my_offset + 16);
01491                          }
01492                        else
01493                          {
01494                            bfd_put_16 (output_bfd, (bfd_vma) t2a1_bx_pc_insn,
01495                                      s->contents + my_offset);
01496 
01497                            bfd_put_16 (output_bfd, (bfd_vma) t2a2_noop_insn,
01498                                      s->contents + my_offset + 2);
01499 
01500                            ret_offset =
01501               /* Address of destination of the stub.  */
01502                             ((bfd_signed_vma) h_val)
01503                             - ((bfd_signed_vma)
01504               /* Offset from the start of the current section to the start of the stubs.  */
01505                                (s->output_offset
01506               /* Offset of the start of this stub from the start of the stubs.  */
01507                                 + my_offset
01508               /* Address of the start of the current section.  */
01509                                 + s->output_section->vma)
01510               /* The branch instruction is 4 bytes into the stub.  */
01511                                + 4
01512               /* ARM branches work from the pc of the instruction + 8.  */
01513                                + 8);
01514 
01515                            bfd_put_32 (output_bfd,
01516                                      (bfd_vma) t2a3_b_insn | ((ret_offset >> 2) & 0x00FFFFFF),
01517                                      s->contents + my_offset + 4);
01518 
01519                          }
01520                      }
01521 
01522                     BFD_ASSERT (my_offset <= globals->thumb_glue_size);
01523 
01524                     /* Now go back and fix up the original BL insn to point
01525                       to here.  */
01526                     ret_offset =
01527                      s->output_offset
01528                      + my_offset
01529                      - (input_section->output_offset
01530                         + rel->r_vaddr)
01531                      -4;
01532 
01533                     tmp = bfd_get_32 (input_bfd, contents + rel->r_vaddr
01534                                    - input_section->vma);
01535 
01536                     bfd_put_32 (output_bfd,
01537                               (bfd_vma) insert_thumb_branch (tmp,
01538                                                          ret_offset),
01539                               contents + rel->r_vaddr - input_section->vma);
01540 
01541                     done = 1;
01542                     }
01543                 }
01544 #endif
01545             }
01546 
01547           /* If the relocation type and destination symbol does not
01548              fall into one of the above categories, then we can just
01549              perform a direct link.  */
01550 
01551          if (done)
01552            rstat = bfd_reloc_ok;
01553          else
01554            if (   h->root.type == bfd_link_hash_defined
01555               || h->root.type == bfd_link_hash_defweak)
01556            {
01557              asection *sec;
01558 
01559              sec = h->root.u.def.section;
01560              val = (h->root.u.def.value
01561                    + sec->output_section->vma
01562                    + sec->output_offset);
01563              }
01564 
01565          else if (! info->relocatable)
01566            {
01567              if (! ((*info->callbacks->undefined_symbol)
01568                    (info, h->root.root.string, input_bfd, input_section,
01569                     rel->r_vaddr - input_section->vma, TRUE)))
01570               return FALSE;
01571            }
01572        }
01573 
01574       if (info->base_file)
01575        {
01576          /* Emit a reloc if the backend thinks it needs it.  */
01577          if (sym && pe_data(output_bfd)->in_reloc_p(output_bfd, howto))
01578             arm_emit_base_file_entry (info, output_bfd, input_section,
01579                                   rel->r_vaddr);
01580        }
01581 
01582       if (done)
01583        rstat = bfd_reloc_ok;
01584 #ifndef ARM_WINCE
01585       /* Only perform this fix during the final link, not a relocatable link.  */
01586       else if (! info->relocatable
01587               && howto->type == ARM_THUMB23)
01588         {
01589           /* This is pretty much a copy of what the default
01590              _bfd_final_link_relocate and _bfd_relocate_contents
01591              routines do to perform a relocation, with special
01592              processing for the split addressing of the Thumb BL
01593              instruction.  Again, it would probably be simpler adding a
01594              ThumbBRANCH23 specific macro expansion into the default
01595              code.  */
01596 
01597           bfd_vma address = rel->r_vaddr - input_section->vma;
01598 
01599          if (address > high_address)
01600            rstat = bfd_reloc_outofrange;
01601           else
01602             {
01603               bfd_vma relocation = val + addend;
01604              int size = bfd_get_reloc_size (howto);
01605              bfd_boolean overflow = FALSE;
01606              bfd_byte *location = contents + address;
01607              bfd_vma x = bfd_get_32 (input_bfd, location);
01608              bfd_vma src_mask = 0x007FFFFE;
01609              bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
01610              bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
01611              bfd_vma check;
01612              bfd_signed_vma signed_check;
01613              bfd_vma add;
01614              bfd_signed_vma signed_add;
01615 
01616              BFD_ASSERT (size == 4);
01617 
01618               /* howto->pc_relative should be TRUE for type 14 BRANCH23.  */
01619               relocation -= (input_section->output_section->vma
01620                              + input_section->output_offset);
01621 
01622               /* howto->pcrel_offset should be TRUE for type 14 BRANCH23.  */
01623               relocation -= address;
01624 
01625              /* No need to negate the relocation with BRANCH23.  */
01626              /* howto->complain_on_overflow == complain_overflow_signed for BRANCH23.  */
01627              /* howto->rightshift == 1 */
01628 
01629              /* Drop unwanted bits from the value we are relocating to.  */
01630              check = relocation >> howto->rightshift;
01631 
01632              /* If this is a signed value, the rightshift just dropped
01633                leading 1 bits (assuming twos complement).  */
01634              if ((bfd_signed_vma) relocation >= 0)
01635               signed_check = check;
01636              else
01637               signed_check = (check
01638                             | ((bfd_vma) - 1
01639                                & ~((bfd_vma) - 1 >> howto->rightshift)));
01640 
01641              /* Get the value from the object file.  */
01642              if (bfd_big_endian (input_bfd))
01643               add = (((x) & 0x07ff0000) >> 4) | (((x) & 0x7ff) << 1);
01644              else
01645               add = ((((x) & 0x7ff) << 12) | (((x) & 0x07ff0000) >> 15));
01646 
01647              /* Get the value from the object file with an appropriate sign.
01648                The expression involving howto->src_mask isolates the upper
01649                bit of src_mask.  If that bit is set in the value we are
01650                adding, it is negative, and we subtract out that number times
01651                two.  If src_mask includes the highest possible bit, then we
01652                can not get the upper bit, but that does not matter since
01653                signed_add needs no adjustment to become negative in that
01654                case.  */
01655              signed_add = add;
01656 
01657              if ((add & (((~ src_mask) >> 1) & src_mask)) != 0)
01658               signed_add -= (((~ src_mask) >> 1) & src_mask) << 1;
01659 
01660              /* howto->bitpos == 0 */
01661              /* Add the value from the object file, shifted so that it is a
01662                straight number.  */
01663              signed_check += signed_add;
01664              relocation   += signed_add;
01665 
01666              BFD_ASSERT (howto->complain_on_overflow == complain_overflow_signed);
01667 
01668              /* Assumes two's complement.  */
01669              if (   signed_check > reloc_signed_max
01670                 || signed_check < reloc_signed_min)
01671               overflow = TRUE;
01672 
01673              /* Put the relocation into the correct bits.
01674                For a BLX instruction, make sure that the relocation is rounded up
01675                to a word boundary.  This follows the semantics of the instruction
01676                which specifies that bit 1 of the target address will come from bit
01677                1 of the base address.  */
01678              if (bfd_big_endian (input_bfd))
01679                {
01680                 if ((x & 0x1800) == 0x0800 && (relocation & 0x02))
01681                   relocation += 2;
01682                 relocation = (((relocation & 0xffe) >> 1)  | ((relocation << 4) & 0x07ff0000));
01683               }
01684              else
01685                {
01686                 if ((x & 0x18000000) == 0x08000000 && (relocation & 0x02))
01687                   relocation += 2;
01688                 relocation = (((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff));
01689               }
01690 
01691              /* Add the relocation to the correct bits of X.  */
01692              x = ((x & ~howto->dst_mask) | relocation);
01693 
01694              /* Put the relocated value back in the object file.  */
01695              bfd_put_32 (input_bfd, x, location);
01696 
01697              rstat = overflow ? bfd_reloc_overflow : bfd_reloc_ok;
01698             }
01699         }
01700 #endif
01701       else
01702         if (info->relocatable && ! howto->partial_inplace)
01703             rstat = bfd_reloc_ok;
01704         else
01705          rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
01706                                        contents,
01707                                        rel->r_vaddr - input_section->vma,
01708                                        val, addend);
01709       /* Only perform this fix during the final link, not a relocatable link.  */
01710       if (! info->relocatable
01711          && (rel->r_type == ARM_32 || rel->r_type == ARM_RVA32))
01712        {
01713          /* Determine if we need to set the bottom bit of a relocated address
01714             because the address is the address of a Thumb code symbol.  */
01715          int patchit = FALSE;
01716 
01717          if (h != NULL
01718              && (   h->class == C_THUMBSTATFUNC
01719                 || h->class == C_THUMBEXTFUNC))
01720            {
01721              patchit = TRUE;
01722            }
01723          else if (sym != NULL
01724                  && sym->n_scnum > N_UNDEF)
01725            {
01726              /* No hash entry - use the symbol instead.  */
01727              if (   sym->n_sclass == C_THUMBSTATFUNC
01728                 || sym->n_sclass == C_THUMBEXTFUNC)
01729               patchit = TRUE;
01730            }
01731 
01732          if (patchit)
01733            {
01734              bfd_byte * location = contents + rel->r_vaddr - input_section->vma;
01735              bfd_vma    x        = bfd_get_32 (input_bfd, location);
01736 
01737              bfd_put_32 (input_bfd, x | 1, location);
01738            }
01739        }
01740 
01741       switch (rstat)
01742        {
01743        default:
01744          abort ();
01745        case bfd_reloc_ok:
01746          break;
01747        case bfd_reloc_outofrange:
01748          (*_bfd_error_handler)
01749            (_("%B: bad reloc address 0x%lx in section `%A'"),
01750             input_bfd, input_section, (unsigned long) rel->r_vaddr);
01751          return FALSE;
01752        case bfd_reloc_overflow:
01753          {
01754            const char *name;
01755            char buf[SYMNMLEN + 1];
01756 
01757            if (symndx == -1)
01758              name = "*ABS*";
01759            else if (h != NULL)
01760              name = NULL;
01761            else
01762              {
01763               name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
01764               if (name == NULL)
01765                 return FALSE;
01766              }
01767 
01768            if (! ((*info->callbacks->reloc_overflow)
01769                  (info, (h ? &h->root : NULL), name, howto->name,
01770                   (bfd_vma) 0, input_bfd, input_section,
01771                   rel->r_vaddr - input_section->vma)))
01772              return FALSE;
01773          }
01774        }
01775     }
01776 
01777   return TRUE;
01778 }
01779 
01780 #ifndef COFF_IMAGE_WITH_PE
01781 
01782 bfd_boolean
01783 bfd_arm_allocate_interworking_sections (struct bfd_link_info * info)
01784 {
01785   asection *                        s;
01786   bfd_byte *                        foo;
01787   struct coff_arm_link_hash_table * globals;
01788 
01789   globals = coff_arm_hash_table (info);
01790 
01791   BFD_ASSERT (globals != NULL);
01792 
01793   if (globals->arm_glue_size != 0)
01794     {
01795       BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
01796 
01797       s = bfd_get_section_by_name
01798        (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
01799 
01800       BFD_ASSERT (s != NULL);
01801 
01802       foo = bfd_alloc (globals->bfd_of_glue_owner, globals->arm_glue_size);
01803 
01804       s->size = globals->arm_glue_size;
01805       s->contents = foo;
01806     }
01807 
01808   if (globals->thumb_glue_size != 0)
01809     {
01810       BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
01811 
01812       s = bfd_get_section_by_name
01813        (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
01814 
01815       BFD_ASSERT (s != NULL);
01816 
01817       foo = bfd_alloc (globals->bfd_of_glue_owner, globals->thumb_glue_size);
01818 
01819       s->size = globals->thumb_glue_size;
01820       s->contents = foo;
01821     }
01822 
01823   return TRUE;
01824 }
01825 
01826 static void
01827 record_arm_to_thumb_glue (struct bfd_link_info *        info,
01828                        struct coff_link_hash_entry * h)
01829 {
01830   const char *                      name = h->root.root.string;
01831   register asection *               s;
01832   char *                            tmp_name;
01833   struct coff_link_hash_entry *     myh;
01834   struct bfd_link_hash_entry *      bh;
01835   struct coff_arm_link_hash_table * globals;
01836   bfd_vma val;
01837   bfd_size_type amt;
01838 
01839   globals = coff_arm_hash_table (info);
01840 
01841   BFD_ASSERT (globals != NULL);
01842   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
01843 
01844   s = bfd_get_section_by_name
01845     (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
01846 
01847   BFD_ASSERT (s != NULL);
01848 
01849   amt = strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1;
01850   tmp_name = bfd_malloc (amt);
01851 
01852   BFD_ASSERT (tmp_name);
01853 
01854   sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);
01855 
01856   myh = coff_link_hash_lookup
01857     (coff_hash_table (info), tmp_name, FALSE, FALSE, TRUE);
01858 
01859   if (myh != NULL)
01860     {
01861       free (tmp_name);
01862       /* We've already seen this guy.  */
01863       return;
01864     }
01865 
01866   /* The only trick here is using globals->arm_glue_size as the value. Even
01867      though the section isn't allocated yet, this is where we will be putting
01868      it.  */
01869   bh = NULL;
01870   val = globals->arm_glue_size + 1;
01871   bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name,
01872                             BSF_GLOBAL, s, val, NULL, TRUE, FALSE, &bh);
01873 
01874   free (tmp_name);
01875 
01876   globals->arm_glue_size += ARM2THUMB_GLUE_SIZE;
01877 
01878   return;
01879 }
01880 
01881 #ifndef ARM_WINCE
01882 static void
01883 record_thumb_to_arm_glue (struct bfd_link_info *        info,
01884                        struct coff_link_hash_entry * h)
01885 {
01886   const char *                       name = h->root.root.string;
01887   asection *                         s;
01888   char *                             tmp_name;
01889   struct coff_link_hash_entry *      myh;
01890   struct bfd_link_hash_entry *       bh;
01891   struct coff_arm_link_hash_table *  globals;
01892   bfd_vma val;
01893   bfd_size_type amt;
01894 
01895   globals = coff_arm_hash_table (info);
01896 
01897   BFD_ASSERT (globals != NULL);
01898   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
01899 
01900   s = bfd_get_section_by_name
01901     (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
01902 
01903   BFD_ASSERT (s != NULL);
01904 
01905   amt = strlen (name) + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1;
01906   tmp_name = bfd_malloc (amt);
01907 
01908   BFD_ASSERT (tmp_name);
01909 
01910   sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name);
01911 
01912   myh = coff_link_hash_lookup
01913     (coff_hash_table (info), tmp_name, FALSE, FALSE, TRUE);
01914 
01915   if (myh != NULL)
01916     {
01917       free (tmp_name);
01918       /* We've already seen this guy.  */
01919       return;
01920     }
01921 
01922   bh = NULL;
01923   val = globals->thumb_glue_size + 1;
01924   bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name,
01925                             BSF_GLOBAL, s, val, NULL, TRUE, FALSE, &bh);
01926 
01927   /* If we mark it 'thumb', the disassembler will do a better job.  */
01928   myh = (struct coff_link_hash_entry *) bh;
01929   myh->class = C_THUMBEXTFUNC;
01930 
01931   free (tmp_name);
01932 
01933   /* Allocate another symbol to mark where we switch to arm mode.  */
01934 
01935 #define CHANGE_TO_ARM "__%s_change_to_arm"
01936 #define BACK_FROM_ARM "__%s_back_from_arm"
01937 
01938   amt = strlen (name) + strlen (CHANGE_TO_ARM) + 1;
01939   tmp_name = bfd_malloc (amt);
01940 
01941   BFD_ASSERT (tmp_name);
01942 
01943   sprintf (tmp_name, globals->support_old_code ? BACK_FROM_ARM : CHANGE_TO_ARM, name);
01944 
01945   bh = NULL;
01946   val = globals->thumb_glue_size + (globals->support_old_code ? 8 : 4);
01947   bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name,
01948                             BSF_LOCAL, s, val, NULL, TRUE, FALSE, &bh);
01949 
01950   free (tmp_name);
01951 
01952   globals->thumb_glue_size += THUMB2ARM_GLUE_SIZE;
01953 
01954   return;
01955 }
01956 #endif /* not ARM_WINCE */
01957 
01958 /* Select a BFD to be used to hold the sections used by the glue code.
01959    This function is called from the linker scripts in ld/emultempl/
01960    {armcoff/pe}.em  */
01961 
01962 bfd_boolean
01963 bfd_arm_get_bfd_for_interworking (bfd *           abfd,
01964                               struct bfd_link_info * info)
01965 {
01966   struct coff_arm_link_hash_table * globals;
01967   flagword                      flags;
01968   asection *                    sec;
01969 
01970   /* If we are only performing a partial link do not bother
01971      getting a bfd to hold the glue.  */
01972   if (info->relocatable)
01973     return TRUE;
01974 
01975   globals = coff_arm_hash_table (info);
01976 
01977   BFD_ASSERT (globals != NULL);
01978 
01979   if (globals->bfd_of_glue_owner != NULL)
01980     return TRUE;
01981 
01982   sec = bfd_get_section_by_name (abfd, ARM2THUMB_GLUE_SECTION_NAME);
01983 
01984   if (sec == NULL)
01985     {
01986       flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
01987               | SEC_CODE | SEC_READONLY);
01988       sec = bfd_make_section_with_flags (abfd, ARM2THUMB_GLUE_SECTION_NAME,
01989                                     flags);
01990       if (sec == NULL
01991          || ! bfd_set_section_alignment (abfd, sec, 2))
01992        return FALSE;
01993     }
01994 
01995   sec = bfd_get_section_by_name (abfd, THUMB2ARM_GLUE_SECTION_NAME);
01996 
01997   if (sec == NULL)
01998     {
01999       flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
02000               | SEC_CODE | SEC_READONLY);
02001       sec = bfd_make_section_with_flags (abfd, THUMB2ARM_GLUE_SECTION_NAME,
02002                                     flags);
02003 
02004       if (sec == NULL
02005          || ! bfd_set_section_alignment (abfd, sec, 2))
02006        return FALSE;
02007     }
02008 
02009   /* Save the bfd for later use.  */
02010   globals->bfd_of_glue_owner = abfd;
02011 
02012   return TRUE;
02013 }
02014 
02015 bfd_boolean
02016 bfd_arm_process_before_allocation (bfd *                   abfd,
02017                                struct bfd_link_info *  info,
02018                                int                   support_old_code)
02019 {
02020   asection * sec;
02021   struct coff_arm_link_hash_table * globals;
02022 
02023   /* If we are only performing a partial link do not bother
02024      to construct any glue.  */
02025   if (info->relocatable)
02026     return TRUE;
02027 
02028   /* Here we have a bfd that is to be included on the link.  We have a hook
02029      to do reloc rummaging, before section sizes are nailed down.  */
02030   _bfd_coff_get_external_symbols (abfd);
02031 
02032   globals = coff_arm_hash_table (info);
02033 
02034   BFD_ASSERT (globals != NULL);
02035   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
02036 
02037   globals->support_old_code = support_old_code;
02038 
02039   /* Rummage around all the relocs and map the glue vectors.  */
02040   sec = abfd->sections;
02041 
02042   if (sec == NULL)
02043     return TRUE;
02044 
02045   for (; sec != NULL; sec = sec->next)
02046     {
02047       struct internal_reloc * i;
02048       struct internal_reloc * rel;
02049 
02050       if (sec->reloc_count == 0)
02051        continue;
02052 
02053       /* Load the relocs.  */
02054       /* FIXME: there may be a storage leak here.  */
02055       i = _bfd_coff_read_internal_relocs (abfd, sec, 1, 0, 0, 0);
02056 
02057       BFD_ASSERT (i != 0);
02058 
02059       for (rel = i; rel < i + sec->reloc_count; ++rel)
02060        {
02061          unsigned short                 r_type  = rel->r_type;
02062          long                           symndx;
02063          struct coff_link_hash_entry *  h;
02064 
02065          symndx = rel->r_symndx;
02066 
02067          /* If the relocation is not against a symbol it cannot concern us.  */
02068          if (symndx == -1)
02069            continue;
02070 
02071          /* If the index is outside of the range of our table, something has gone wrong.  */
02072          if (symndx >= obj_conv_table_size (abfd))
02073            {
02074              _bfd_error_handler (_("%B: illegal symbol index in reloc: %d"),
02075                               abfd, symndx);
02076              continue;
02077            }
02078 
02079          h = obj_coff_sym_hashes (abfd)[symndx];
02080 
02081          /* If the relocation is against a static symbol it must be within
02082             the current section and so cannot be a cross ARM/Thumb relocation.  */
02083          if (h == NULL)
02084            continue;
02085 
02086          switch (r_type)
02087            {
02088            case ARM_26:
02089              /* This one is a call from arm code.  We need to look up
02090                the target of the call. If it is a thumb target, we
02091                insert glue.  */
02092 
02093              if (h->class == C_THUMBEXTFUNC)
02094               record_arm_to_thumb_glue (info, h);
02095              break;
02096 
02097 #ifndef ARM_WINCE
02098            case ARM_THUMB23:
02099              /* This one is a call from thumb code.  We used to look
02100                for ARM_THUMB9 and ARM_THUMB12 as well.  We need to look
02101                up the target of the call. If it is an arm target, we
02102                insert glue.  If the symbol does not exist it will be
02103                given a class of C_EXT and so we will generate a stub
02104                for it.  This is not really a problem, since the link
02105                is doomed anyway.  */
02106 
02107              switch (h->class)
02108               {
02109               case C_EXT:
02110               case C_STAT:
02111               case C_LABEL:
02112                 record_thumb_to_arm_glue (info, h);
02113                 break;
02114               default:
02115                 ;
02116               }
02117              break;
02118 #endif
02119 
02120            default:
02121              break;
02122            }
02123        }
02124     }
02125 
02126   return TRUE;
02127 }
02128 
02129 #endif /* ! defined (COFF_IMAGE_WITH_PE) */
02130 
02131 #define coff_bfd_reloc_type_lookup               coff_arm_reloc_type_lookup
02132 #define coff_bfd_reloc_name_lookup coff_arm_reloc_name_lookup
02133 #define coff_relocate_section                    coff_arm_relocate_section
02134 #define coff_bfd_is_local_label_name             coff_arm_is_local_label_name
02135 #define coff_adjust_symndx                coff_arm_adjust_symndx
02136 #define coff_link_output_has_begun               coff_arm_link_output_has_begun
02137 #define coff_final_link_postscript        coff_arm_final_link_postscript
02138 #define coff_bfd_merge_private_bfd_data          coff_arm_merge_private_bfd_data
02139 #define coff_bfd_print_private_bfd_data          coff_arm_print_private_bfd_data
02140 #define coff_bfd_set_private_flags              _bfd_coff_arm_set_private_flags
02141 #define coff_bfd_copy_private_bfd_data          coff_arm_copy_private_bfd_data
02142 #define coff_bfd_link_hash_table_create          coff_arm_link_hash_table_create
02143 
02144 /* When doing a relocatable link, we want to convert ARM_26 relocs
02145    into ARM_26D relocs.  */
02146 
02147 static bfd_boolean
02148 coff_arm_adjust_symndx (bfd *obfd ATTRIBUTE_UNUSED,
02149                      struct bfd_link_info *info ATTRIBUTE_UNUSED,
02150                      bfd *ibfd,
02151                      asection *sec,
02152                      struct internal_reloc *irel,
02153                      bfd_boolean *adjustedp)
02154 {
02155   if (irel->r_type == ARM_26)
02156     {
02157       struct coff_link_hash_entry *h;
02158 
02159       h = obj_coff_sym_hashes (ibfd)[irel->r_symndx];
02160       if (h != NULL
02161          && (h->root.type == bfd_link_hash_defined
02162              || h->root.type == bfd_link_hash_defweak)
02163          && h->root.u.def.section->output_section == sec->output_section)
02164        irel->r_type = ARM_26D;
02165     }
02166   *adjustedp = FALSE;
02167   return TRUE;
02168 }
02169 
02170 /* Called when merging the private data areas of two BFDs.
02171    This is important as it allows us to detect if we are
02172    attempting to merge binaries compiled for different ARM
02173    targets, eg different CPUs or different APCS's.     */
02174 
02175 static bfd_boolean
02176 coff_arm_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
02177 {
02178   BFD_ASSERT (ibfd != NULL && obfd != NULL);
02179 
02180   if (ibfd == obfd)
02181     return TRUE;
02182 
02183   /* If the two formats are different we cannot merge anything.
02184      This is not an error, since it is permissable to change the
02185      input and output formats.  */
02186   if (   ibfd->xvec->flavour != bfd_target_coff_flavour
02187       || obfd->xvec->flavour != bfd_target_coff_flavour)
02188     return TRUE;
02189 
02190   /* Determine what should happen if the input ARM architecture
02191      does not match the output ARM architecture.  */
02192   if (! bfd_arm_merge_machines (ibfd, obfd))
02193     return FALSE;
02194 
02195   /* Verify that the APCS is the same for the two BFDs.  */
02196   if (APCS_SET (ibfd))
02197     {
02198       if (APCS_SET (obfd))
02199        {
02200          /* If the src and dest have different APCS flag bits set, fail.  */
02201          if (APCS_26_FLAG (obfd) != APCS_26_FLAG (ibfd))
02202            {
02203              _bfd_error_handler
02204               /* xgettext: c-format */
02205               (_("ERROR: %B is compiled for APCS-%d, whereas %B is compiled for APCS-%d"),
02206                ibfd, obfd,
02207                APCS_26_FLAG (ibfd) ? 26 : 32,
02208                APCS_26_FLAG (obfd) ? 26 : 32
02209                );
02210 
02211              bfd_set_error (bfd_error_wrong_format);
02212              return FALSE;
02213            }
02214 
02215          if (APCS_FLOAT_FLAG (obfd) != APCS_FLOAT_FLAG (ibfd))
02216            {
02217              const char *msg;
02218 
02219              if (APCS_FLOAT_FLAG (ibfd))
02220               /* xgettext: c-format */
02221               msg = _("ERROR: %B passes floats in float registers, whereas %B passes them in integer registers");
02222              else
02223               /* xgettext: c-format */
02224               msg = _("ERROR: %B passes floats in integer registers, whereas %B passes them in float registers");
02225 
02226              _bfd_error_handler (msg, ibfd, obfd);
02227 
02228              bfd_set_error (bfd_error_wrong_format);
02229              return FALSE;
02230            }
02231 
02232          if (PIC_FLAG (obfd) != PIC_FLAG (ibfd))
02233            {
02234              const char * msg;
02235 
02236              if (PIC_FLAG (ibfd))
02237               /* xgettext: c-format */
02238               msg = _("ERROR: %B is compiled as position independent code, whereas target %B is absolute position");
02239              else
02240               /* xgettext: c-format */
02241               msg = _("ERROR: %B is compiled as absolute position code, whereas target %B is position independent");
02242              _bfd_error_handler (msg, ibfd, obfd);
02243 
02244              bfd_set_error (bfd_error_wrong_format);
02245              return FALSE;
02246            }
02247        }
02248       else
02249        {
02250          SET_APCS_FLAGS (obfd, APCS_26_FLAG (ibfd) | APCS_FLOAT_FLAG (ibfd) | PIC_FLAG (ibfd));
02251 
02252          /* Set up the arch and fields as well as these are probably wrong.  */
02253          bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
02254        }
02255     }
02256 
02257   /* Check the interworking support.  */
02258   if (INTERWORK_SET (ibfd))
02259     {
02260       if (INTERWORK_SET (obfd))
02261        {
02262          /* If the src and dest differ in their interworking issue a warning.  */
02263          if (INTERWORK_FLAG (obfd) != INTERWORK_FLAG (ibfd))
02264            {
02265              const char * msg;
02266 
02267              if (INTERWORK_FLAG (ibfd))
02268               /* xgettext: c-format */
02269               msg = _("Warning: %B supports interworking, whereas %B does not");
02270              else
02271               /* xgettext: c-format */
02272               msg = _("Warning: %B does not support interworking, whereas %B does");
02273 
02274              _bfd_error_handler (msg, ibfd, obfd);
02275            }
02276        }
02277       else
02278        {
02279          SET_INTERWORK_FLAG (obfd, INTERWORK_FLAG (ibfd));
02280        }
02281     }
02282 
02283   return TRUE;
02284 }
02285 
02286 /* Display the flags field.  */
02287 
02288 static bfd_boolean
02289 coff_arm_print_private_bfd_data (bfd * abfd, void * ptr)
02290 {
02291   FILE * file = (FILE *) ptr;
02292 
02293   BFD_ASSERT (abfd != NULL && ptr != NULL);
02294 
02295   /* xgettext:c-format */
02296   fprintf (file, _("private flags = %x:"), coff_data (abfd)->flags);
02297 
02298   if (APCS_SET (abfd))
02299     {
02300       /* xgettext: APCS is ARM Procedure Call Standard, it should not be translated.  */
02301       fprintf (file, " [APCS-%d]", APCS_26_FLAG (abfd) ? 26 : 32);
02302 
02303       if (APCS_FLOAT_FLAG (abfd))
02304        fprintf (file, _(" [floats passed in float registers]"));
02305       else
02306        fprintf (file, _(" [floats passed in integer registers]"));
02307 
02308       if (PIC_FLAG (abfd))
02309        fprintf (file, _(" [position independent]"));
02310       else
02311        fprintf (file, _(" [absolute position]"));
02312     }
02313 
02314   if (! INTERWORK_SET (abfd))
02315     fprintf (file, _(" [interworking flag not initialised]"));
02316   else if (INTERWORK_FLAG (abfd))
02317     fprintf (file, _(" [interworking supported]"));
02318   else
02319     fprintf (file, _(" [interworking not supported]"));
02320 
02321   fputc ('\n', file);
02322 
02323   return TRUE;
02324 }
02325 
02326 /* Copies the given flags into the coff_tdata.flags field.
02327    Typically these flags come from the f_flags[] field of
02328    the COFF filehdr structure, which contains important,
02329    target specific information.
02330    Note: Although this function is static, it is explicitly
02331    called from both coffcode.h and peicode.h.  */
02332 
02333 static bfd_boolean
02334 _bfd_coff_arm_set_private_flags (bfd * abfd, flagword flags)
02335 {
02336   flagword flag;
02337 
02338   BFD_ASSERT (abfd != NULL);
02339 
02340   flag = (flags & F_APCS26) ? F_APCS_26 : 0;
02341 
02342   /* Make sure that the APCS field has not been initialised to the opposite
02343      value.  */
02344   if (APCS_SET (abfd)
02345       && (   (APCS_26_FLAG    (abfd) != flag)
02346          || (APCS_FLOAT_FLAG (abfd) != (flags & F_APCS_FLOAT))
02347          || (PIC_FLAG        (abfd) != (flags & F_PIC))
02348          ))
02349     return FALSE;
02350 
02351   flag |= (flags & (F_APCS_FLOAT | F_PIC));
02352 
02353   SET_APCS_FLAGS (abfd, flag);
02354 
02355   flag = (flags & F_INTERWORK);
02356 
02357   /* If the BFD has already had its interworking flag set, but it
02358      is different from the value that we have been asked to set,
02359      then assume that that merged code will not support interworking
02360      and set the flag accordingly.  */
02361   if (INTERWORK_SET (abfd) && (INTERWORK_FLAG (abfd) != flag))
02362     {
02363       if (flag)
02364        /* xgettext: c-format */
02365        _bfd_error_handler (_("Warning: Not setting interworking flag of %B since it has already been specified as non-interworking"),
02366                          abfd);
02367       else
02368        /* xgettext: c-format */
02369        _bfd_error_handler (_("Warning: Clearing the interworking flag of %B due to outside request"),
02370                          abfd);
02371       flag = 0;
02372     }
02373 
02374   SET_INTERWORK_FLAG (abfd, flag);
02375 
02376   return TRUE;
02377 }
02378 
02379 /* Copy the important parts of the target specific data
02380    from one instance of a BFD to another.  */
02381 
02382 static bfd_boolean
02383 coff_arm_copy_private_bfd_data (bfd * src, bfd * dest)
02384 {
02385   BFD_ASSERT (src != NULL && dest != NULL);
02386 
02387   if (src == dest)
02388     return TRUE;
02389 
02390   /* If the destination is not in the same format as the source, do not do
02391      the copy.  */
02392   if (src->xvec != dest->xvec)
02393     return TRUE;
02394 
02395   /* Copy the flags field.  */
02396   if (APCS_SET (src))
02397     {
02398       if (APCS_SET (dest))
02399        {
02400          /* If the src and dest have different APCS flag bits set, fail.  */
02401          if (APCS_26_FLAG (dest) != APCS_26_FLAG (src))
02402            return FALSE;
02403 
02404          if (APCS_FLOAT_FLAG (dest) != APCS_FLOAT_FLAG (src))
02405            return FALSE;
02406 
02407          if (PIC_FLAG (dest) != PIC_FLAG (src))
02408            return FALSE;
02409        }
02410       else
02411        SET_APCS_FLAGS (dest, APCS_26_FLAG (src) | APCS_FLOAT_FLAG (src)
02412                      | PIC_FLAG (src));
02413     }
02414 
02415   if (INTERWORK_SET (src))
02416     {
02417       if (INTERWORK_SET (dest))
02418        {
02419          /* If the src and dest have different interworking flags then turn
02420             off the interworking bit.  */
02421          if (INTERWORK_FLAG (dest) != INTERWORK_FLAG (src))
02422            {
02423              if (INTERWORK_FLAG (dest))
02424               {
02425                 /* xgettext:c-format */
02426                 _bfd_error_handler (("\
02427 Warning: Clearing the interworking flag of %B because non-interworking code in %B has been linked with it"),
02428                                   dest, src);
02429               }
02430 
02431              SET_INTERWORK_FLAG (dest, 0);
02432            }
02433        }
02434       else
02435        {
02436          SET_INTERWORK_FLAG (dest, INTERWORK_FLAG (src));
02437        }
02438     }
02439 
02440   return TRUE;
02441 }
02442 
02443 /* Note:  the definitions here of LOCAL_LABEL_PREFIX and USER_LABEL_PREIFX
02444    *must* match the definitions in gcc/config/arm/{coff|semi|aout}.h.  */
02445 #ifndef LOCAL_LABEL_PREFIX
02446 #define LOCAL_LABEL_PREFIX ""
02447 #endif
02448 #ifndef USER_LABEL_PREFIX
02449 #define USER_LABEL_PREFIX "_"
02450 #endif
02451 
02452 /* Like _bfd_coff_is_local_label_name, but
02453    a) test against USER_LABEL_PREFIX, to avoid stripping labels known to be
02454       non-local.
02455    b) Allow other prefixes than ".", e.g. an empty prefix would cause all
02456       labels of the form Lxxx to be stripped.  */
02457 
02458 static bfd_boolean
02459 coff_arm_is_local_label_name (bfd *        abfd ATTRIBUTE_UNUSED,
02460                            const char * name)
02461 {
02462 #ifdef USER_LABEL_PREFIX
02463   if (USER_LABEL_PREFIX[0] != 0)
02464     {
02465       size_t len = strlen (USER_LABEL_PREFIX);
02466 
02467       if (strncmp (name, USER_LABEL_PREFIX, len) == 0)
02468        return FALSE;
02469     }
02470 #endif
02471 
02472 #ifdef LOCAL_LABEL_PREFIX
02473   /* If there is a prefix for local labels then look for this.
02474      If the prefix exists, but it is empty, then ignore the test.  */
02475 
02476   if (LOCAL_LABEL_PREFIX[0] != 0)
02477     {
02478       size_t len = strlen (LOCAL_LABEL_PREFIX);
02479 
02480       if (strncmp (name, LOCAL_LABEL_PREFIX, len) != 0)
02481        return FALSE;
02482 
02483       /* Perform the checks below for the rest of the name.  */
02484       name += len;
02485     }
02486 #endif
02487 
02488   return name[0] == 'L';
02489 }
02490 
02491 /* This piece of machinery exists only to guarantee that the bfd that holds
02492    the glue section is written last.
02493 
02494    This does depend on bfd_make_section attaching a new section to the
02495    end of the section list for the bfd.  */
02496 
02497 static bfd_boolean
02498 coff_arm_link_output_has_begun (bfd * sub, struct coff_final_link_info * info)
02499 {
02500   return (sub->output_has_begun
02501          || sub == coff_arm_hash_table (info->info)->bfd_of_glue_owner);
02502 }
02503 
02504 static bfd_boolean
02505 coff_arm_final_link_postscript (bfd * abfd ATTRIBUTE_UNUSED,
02506                             struct coff_final_link_info * pfinfo)
02507 {
02508   struct coff_arm_link_hash_table * globals;
02509 
02510   globals = coff_arm_hash_table (pfinfo->info);
02511 
02512   BFD_ASSERT (globals != NULL);
02513 
02514   if (globals->bfd_of_glue_owner != NULL)
02515     {
02516       if (! _bfd_coff_link_input_bfd (pfinfo, globals->bfd_of_glue_owner))
02517        return FALSE;
02518 
02519       globals->bfd_of_glue_owner->output_has_begun = TRUE;
02520     }
02521 
02522   return bfd_arm_update_notes (abfd, ARM_NOTE_SECTION);
02523 }
02524 
02525 #include "coffcode.h"
02526 
02527 #ifndef TARGET_LITTLE_SYM
02528 #define TARGET_LITTLE_SYM armcoff_little_vec
02529 #endif
02530 #ifndef TARGET_LITTLE_NAME
02531 #define TARGET_LITTLE_NAME "coff-arm-little"
02532 #endif
02533 #ifndef TARGET_BIG_SYM
02534 #define TARGET_BIG_SYM armcoff_big_vec
02535 #endif
02536 #ifndef TARGET_BIG_NAME
02537 #define TARGET_BIG_NAME "coff-arm-big"
02538 #endif
02539 
02540 #ifndef TARGET_UNDERSCORE
02541 #define TARGET_UNDERSCORE 0
02542 #endif
02543 
02544 #ifndef EXTRA_S_FLAGS
02545 #ifdef COFF_WITH_PE
02546 #define EXTRA_S_FLAGS (SEC_CODE | SEC_LINK_ONCE | SEC_LINK_DUPLICATES)
02547 #else
02548 #define EXTRA_S_FLAGS SEC_CODE
02549 #endif
02550 #endif
02551 
02552 /* Forward declaration for use initialising alternative_target field.  */
02553 extern const bfd_target TARGET_BIG_SYM ;
02554 
02555 /* Target vectors.  */
02556 CREATE_LITTLE_COFF_TARGET_VEC (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME, D_PAGED, EXTRA_S_FLAGS, TARGET_UNDERSCORE, & TARGET_BIG_SYM, COFF_SWAP_TABLE)
02557 CREATE_BIG_COFF_TARGET_VEC (TARGET_BIG_SYM, TARGET_BIG_NAME, D_PAGED, EXTRA_S_FLAGS, TARGET_UNDERSCORE, & TARGET_LITTLE_SYM, COFF_SWAP_TABLE)