(linenum→info "unix/slp.c:2238")

binutils/2.18/bfd/coff-arm.c

    1: /* BFD back-end for ARM COFF files.
    2:    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
    3:    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    4:    Free Software Foundation, Inc.
    5:    Written by Cygnus Support.
    6: 
    7:    This file is part of BFD, the Binary File Descriptor library.
    8: 
    9:    This program is free software; you can redistribute it and/or modify
   10:    it under the terms of the GNU General Public License as published by
   11:    the Free Software Foundation; either version 3 of the License, or
   12:    (at your option) any later version.
   13: 
   14:    This program is distributed in the hope that it will be useful,
   15:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   16:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17:    GNU General Public License for more details.
   18: 
   19:    You should have received a copy of the GNU General Public License
   20:    along with this program; if not, write to the Free Software
   21:    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   22:    MA 02110-1301, USA.  */
   23: 
   24: #include "sysdep.h"
   25: #include "bfd.h"
   26: #include "libbfd.h"
   27: #include "coff/arm.h"
   28: #include "coff/internal.h"
   29: 
   30: #ifdef COFF_WITH_PE
   31: #include "coff/pe.h"
   32: #endif
   33: 
   34: #include "libcoff.h"
   35: 
   36: /* Macros for manipulation the bits in the flags field of the coff data
   37:    structure.  */
   38: #define APCS_26_FLAG(abfd) \
   39:   (coff_data (abfd)->flags & F_APCS_26)
   40: 
   41: #define APCS_FLOAT_FLAG(abfd) \
   42:   (coff_data (abfd)->flags & F_APCS_FLOAT)
   43: 
   44: #define PIC_FLAG(abfd) \
   45:   (coff_data (abfd)->flags & F_PIC)
   46: 
   47: #define APCS_SET(abfd) \
   48:   (coff_data (abfd)->flags & F_APCS_SET)
   49: 
   50: #define SET_APCS_FLAGS(abfd, flgs) \
   51:   do                                                                    \
   52:     {                                                                   \
   53:       coff_data (abfd)->flags &= ~(F_APCS_26 | F_APCS_FLOAT | F_PIC);   \
   54:       coff_data (abfd)->flags |= (flgs) | F_APCS_SET;                   \
   55:     }                                                                   \
   56:   while (0)
   57: 
   58: #define INTERWORK_FLAG(abfd) \
   59:   (coff_data (abfd)->flags & F_INTERWORK)
   60: 
   61: #define INTERWORK_SET(abfd) \
   62:   (coff_data (abfd)->flags & F_INTERWORK_SET)
   63: 
   64: #define SET_INTERWORK_FLAG(abfd, flg) \
   65:   do                                                                    \
   66:     {                                                                   \
   67:       coff_data (abfd)->flags &= ~F_INTERWORK;                          \
   68:       coff_data (abfd)->flags |= (flg) | F_INTERWORK_SET;               \
   69:     }                                                                   \
   70:   while (0)
   71: 
   72: #ifndef NUM_ELEM
   73: #define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))
   74: #endif
   75: 
   76: typedef enum {bunknown, b9, b12, b23} thumb_pcrel_branchtype;
   77: /* Some typedefs for holding instructions.  */
   78: typedef unsigned long int insn32;
   79: typedef unsigned short int insn16;
   80: 
   81: /* The linker script knows the section names for placement.
   82:    The entry_names are used to do simple name mangling on the stubs.
   83:    Given a function name, and its type, the stub can be found. The
   84:    name can be changed. The only requirement is the %s be present.  */
   85: 
   86: #define THUMB2ARM_GLUE_SECTION_NAME ".glue_7t"
   87: #define THUMB2ARM_GLUE_ENTRY_NAME   "__%s_from_thumb"
   88: 
   89: #define ARM2THUMB_GLUE_SECTION_NAME ".glue_7"
   90: #define ARM2THUMB_GLUE_ENTRY_NAME   "__%s_from_arm"
   91: 
   92: /* Used by the assembler.  */
   93: 
   94: static bfd_reloc_status_type
   95: coff_arm_reloc (bfd *abfd,
   96:                 arelent *reloc_entry,
   97:                 asymbol *symbol ATTRIBUTE_UNUSED,
   98:                 void * data,
   99:                 asection *input_section ATTRIBUTE_UNUSED,
  100:                 bfd *output_bfd,
  101:                 char **error_message ATTRIBUTE_UNUSED)
  102: {
  103:   symvalue diff;
  104: 
  105:   if (output_bfd == NULL)
  106:     return bfd_reloc_continue;
  107: 
  108:   diff = reloc_entry->addend;
  109: 
  110: #define DOIT(x)                                                 \
  111:   x = ((x & ~howto->dst_mask)                                   \
  112:        | (((x & howto->src_mask) + diff) & howto->dst_mask))
  113: 
  114:     if (diff != 0)
  115:       {
  116:         reloc_howto_type *howto = reloc_entry->howto;
  117:         unsigned char *addr = (unsigned char *) data + reloc_entry->address;
  118: 
  119:         switch (howto->size)
  120:           {
  121:           case 0:
  122:             {
  123:               char x = bfd_get_8 (abfd, addr);
  124:               DOIT (x);
  125:               bfd_put_8 (abfd, x, addr);
  126:             }
  127:             break;
  128: 
  129:           case 1:
  130:             {
  131:               short x = bfd_get_16 (abfd, addr);
  132:               DOIT (x);
  133:               bfd_put_16 (abfd, (bfd_vma) x, addr);
  134:             }
  135:             break;
  136: 
  137:           case 2:
  138:             {
  139:               long x = bfd_get_32 (abfd, addr);
  140:               DOIT (x);
  141:               bfd_put_32 (abfd, (bfd_vma) x, addr);
  142:             }
  143:             break;
  144: 
  145:           default:
  146:             abort ();
  147:           }
  148:       }
  149: 
  150:   /* Now let bfd_perform_relocation finish everything up.  */
  151:   return bfd_reloc_continue;
  152: }
  153: 
  154: /* If USER_LABEL_PREFIX is defined as "_" (see coff_arm_is_local_label_name()
  155:    in this file), then TARGET_UNDERSCORE should be defined, otherwise it
  156:    should not.  */
  157: #ifndef TARGET_UNDERSCORE
  158: #define TARGET_UNDERSCORE '_'
  159: #endif
  160: 
  161: #ifndef PCRELOFFSET
  162: #define PCRELOFFSET TRUE
  163: #endif
  164: 
  165: /* These most certainly belong somewhere else. Just had to get rid of
  166:    the manifest constants in the code.  */
  167: 
  168: #ifdef ARM_WINCE
  169: 
  170: #define ARM_26D      0
  171: #define ARM_32       1
  172: #define ARM_RVA32    2
  173: #define ARM_26       3
  174: #define ARM_THUMB12  4
  175: #define ARM_SECTION  14
  176: #define ARM_SECREL   15
  177: 
  178: #else
  179: 
  180: #define ARM_8        0
  181: #define ARM_16       1
  182: #define ARM_32       2
  183: #define ARM_26       3
  184: #define ARM_DISP8    4
  185: #define ARM_DISP16   5
  186: #define ARM_DISP32   6
  187: #define ARM_26D      7
  188: /* 8 is unused.  */
  189: #define ARM_NEG16    9
  190: #define ARM_NEG32   10
  191: #define ARM_RVA32   11
  192: #define ARM_THUMB9  12
  193: #define ARM_THUMB12 13
  194: #define ARM_THUMB23 14
  195: 
  196: #endif
  197: 
  198: static bfd_reloc_status_type aoutarm_fix_pcrel_26_done
  199:   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
  200: static bfd_reloc_status_type aoutarm_fix_pcrel_26
  201:   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
  202: static bfd_reloc_status_type coff_thumb_pcrel_12
  203:   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
  204: #ifndef ARM_WINCE
  205: static bfd_reloc_status_type coff_thumb_pcrel_9
  206:   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
  207: static bfd_reloc_status_type coff_thumb_pcrel_23
  208:   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
  209: #endif
  210: 
  211: static reloc_howto_type aoutarm_std_reloc_howto[] =
  212:   {
  213: #ifdef ARM_WINCE
  214:     HOWTO (ARM_26D,
  215:            2,
  216:            2,
  217:            24,
  218:            TRUE,
  219:            0,
  220:            complain_overflow_dont,
  221:            aoutarm_fix_pcrel_26_done,
  222:            "ARM_26D",
  223:            TRUE,       /* partial_inplace.  */
  224:            0x00ffffff,
  225:            0x0,
  226:            PCRELOFFSET),
  227:     HOWTO (ARM_32,
  228:            0,
  229:            2,
  230:            32,
  231:            FALSE,
  232:            0,
  233:            complain_overflow_bitfield,
  234:            coff_arm_reloc,
  235:            "ARM_32",
  236:            TRUE,       /* partial_inplace.  */
  237:            0xffffffff,
  238:            0xffffffff,
  239:            PCRELOFFSET),
  240:     HOWTO (ARM_RVA32,
  241:            0,
  242:            2,
  243:            32,
  244:            FALSE,
  245:            0,
  246:            complain_overflow_bitfield,
  247:            coff_arm_reloc,
  248:            "ARM_RVA32",
  249:            TRUE,       /* partial_inplace.  */
  250:            0xffffffff,
  251:            0xffffffff,
  252:            PCRELOFFSET),
  253:     HOWTO (ARM_26,
  254:            2,
  255:            2,
  256:            24,
  257:            TRUE,
  258:            0,
  259:            complain_overflow_signed,
  260:            aoutarm_fix_pcrel_26 ,
  261:            "ARM_26",
  262:            FALSE,
  263:            0x00ffffff,
  264:            0x00ffffff,
  265:            PCRELOFFSET),
  266:     HOWTO (ARM_THUMB12,
  267:            1,
  268:            1,
  269:            11,
  270:            TRUE,
  271:            0,
  272:            complain_overflow_signed,
  273:            coff_thumb_pcrel_12 ,
  274:            "ARM_THUMB12",
  275:            FALSE,
  276:            0x000007ff,
  277:            0x000007ff,
  278:            PCRELOFFSET),
  279:     EMPTY_HOWTO (-1),
  280:     EMPTY_HOWTO (-1),
  281:     EMPTY_HOWTO (-1),
  282:     EMPTY_HOWTO (-1),
  283:     EMPTY_HOWTO (-1),
  284:     EMPTY_HOWTO (-1),
  285:     EMPTY_HOWTO (-1),
  286:     EMPTY_HOWTO (-1),
  287:     EMPTY_HOWTO (-1),
  288:     HOWTO (ARM_SECTION,
  289:            0,
  290:            1,
  291:            16,
  292:            FALSE,
  293:            0,
  294:            complain_overflow_bitfield,
  295:            coff_arm_reloc,
  296:            "ARM_SECTION",
  297:            TRUE,       /* partial_inplace.  */
  298:            0x0000ffff,
  299:            0x0000ffff,
  300:            PCRELOFFSET),
  301:     HOWTO (ARM_SECREL,
  302:            0,
  303:            2,
  304:            32,
  305:            FALSE,
  306:            0,
  307:            complain_overflow_bitfield,
  308:            coff_arm_reloc,
  309:            "ARM_SECREL",
  310:            TRUE,       /* partial_inplace.  */
  311:            0xffffffff,
  312:            0xffffffff,
  313:            PCRELOFFSET),
  314: #else /* not ARM_WINCE */
  315:     HOWTO (ARM_8,
  316:            0,
  317:            0,
  318:            8,
  319:            FALSE,
  320:            0,
  321:            complain_overflow_bitfield,
  322:            coff_arm_reloc,
  323:            "ARM_8",
  324:            TRUE,
  325:            0x000000ff,
  326:            0x000000ff,
  327:            PCRELOFFSET),
  328:     HOWTO (ARM_16,
  329:            0,
  330:            1,
  331:            16,
  332:            FALSE,
  333:            0,
  334:            complain_overflow_bitfield,
  335:            coff_arm_reloc,
  336:            "ARM_16",
  337:            TRUE,
  338:            0x0000ffff,
  339:            0x0000ffff,
  340:            PCRELOFFSET),
  341:     HOWTO (ARM_32,
  342:            0,
  343:            2,
  344:            32,
  345:            FALSE,
  346:            0,
  347:            complain_overflow_bitfield,
  348:            coff_arm_reloc,
  349:            "ARM_32",
  350:            TRUE,
  351:            0xffffffff,
  352:            0xffffffff,
  353:            PCRELOFFSET),
  354:     HOWTO (ARM_26,
  355:            2,
  356:            2,
  357:            24,
  358:            TRUE,
  359:            0,
  360:            complain_overflow_signed,
  361:            aoutarm_fix_pcrel_26 ,
  362:            "ARM_26",
  363:            FALSE,
  364:            0x00ffffff,
  365:            0x00ffffff,
  366:            PCRELOFFSET),
  367:     HOWTO (ARM_DISP8,
  368:            0,
  369:            0,
  370:            8,
  371:            TRUE,
  372:            0,
  373:            complain_overflow_signed,
  374:            coff_arm_reloc,
  375:            "ARM_DISP8",
  376:            TRUE,
  377:            0x000000ff,
  378:            0x000000ff,
  379:            TRUE),
  380:     HOWTO (ARM_DISP16,
  381:            0,
  382:            1,
  383:            16,
  384:            TRUE,
  385:            0,
  386:            complain_overflow_signed,
  387:            coff_arm_reloc,
  388:            "ARM_DISP16",
  389:            TRUE,
  390:            0x0000ffff,
  391:            0x0000ffff,
  392:            TRUE),
  393:     HOWTO (ARM_DISP32,
  394:            0,
  395:            2,
  396:            32,
  397:            TRUE,
  398:            0,
  399:            complain_overflow_signed,
  400:            coff_arm_reloc,
  401:            "ARM_DISP32",
  402:            TRUE,
  403:            0xffffffff,
  404:            0xffffffff,
  405:            TRUE),
  406:     HOWTO (ARM_26D,
  407:            2,
  408:            2,
  409:            24,
  410:            FALSE,
  411:            0,
  412:            complain_overflow_dont,
  413:            aoutarm_fix_pcrel_26_done,
  414:            "ARM_26D",
  415:            TRUE,
  416:            0x00ffffff,
  417:            0x0,
  418:            FALSE),
  419:     /* 8 is unused */
  420:     EMPTY_HOWTO (-1),
  421:     HOWTO (ARM_NEG16,
  422:            0,
  423:            -1,
  424:            16,
  425:            FALSE,
  426:            0,
  427:            complain_overflow_bitfield,
  428:            coff_arm_reloc,
  429:            "ARM_NEG16",
  430:            TRUE,
  431:            0x0000ffff,
  432:            0x0000ffff,
  433:            FALSE),
  434:     HOWTO (ARM_NEG32,
  435:            0,
  436:            -2,
  437:            32,
  438:            FALSE,
  439:            0,
  440:            complain_overflow_bitfield,
  441:            coff_arm_reloc,
  442:            "ARM_NEG32",
  443:            TRUE,
  444:            0xffffffff,
  445:            0xffffffff,
  446:            FALSE),
  447:     HOWTO (ARM_RVA32,
  448:            0,
  449:            2,
  450:            32,
  451:            FALSE,
  452:            0,
  453:            complain_overflow_bitfield,
  454:            coff_arm_reloc,
  455:            "ARM_RVA32",
  456:            TRUE,
  457:            0xffffffff,
  458:            0xffffffff,
  459:            PCRELOFFSET),
  460:     HOWTO (ARM_THUMB9,
  461:            1,
  462:            1,
  463:            8,
  464:            TRUE,
  465:            0,
  466:            complain_overflow_signed,
  467:            coff_thumb_pcrel_9 ,
  468:            "ARM_THUMB9",
  469:            FALSE,
  470:            0x000000ff,
  471:            0x000000ff,
  472:            PCRELOFFSET),
  473:     HOWTO (ARM_THUMB12,
  474:            1,
  475:            1,
  476:            11,
  477:            TRUE,
  478:            0,
  479:            complain_overflow_signed,
  480:            coff_thumb_pcrel_12 ,
  481:            "ARM_THUMB12",
  482:            FALSE,
  483:            0x000007ff,
  484:            0x000007ff,
  485:            PCRELOFFSET),
  486:     HOWTO (ARM_THUMB23,
  487:            1,
  488:            2,
  489:            22,
  490:            TRUE,
  491:            0,
  492:            complain_overflow_signed,
  493:            coff_thumb_pcrel_23 ,
  494:            "ARM_THUMB23",
  495:            FALSE,
  496:            0x07ff07ff,
  497:            0x07ff07ff,
  498:            PCRELOFFSET)
  499: #endif /* not ARM_WINCE */
  500:   };
  501: 
  502: #define NUM_RELOCS NUM_ELEM (aoutarm_std_reloc_howto)
  503: 
  504: #ifdef COFF_WITH_PE
  505: /* Return TRUE if this relocation should
  506:    appear in the output .reloc section.  */
  507: 
  508: static bfd_boolean
  509: in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED,
  510:             reloc_howto_type * howto)
  511: {
  512:   return !howto->pc_relative && howto->type != ARM_RVA32;
  513: }
  514: #endif
  515: 
  516: #define RTYPE2HOWTO(cache_ptr, dst)             \
  517:   (cache_ptr)->howto =                          \
  518:     (dst)->r_type < NUM_RELOCS                  \
  519:     ? aoutarm_std_reloc_howto + (dst)->r_type   \
  520:     : NULL
  521: 
  522: #define coff_rtype_to_howto coff_arm_rtype_to_howto
  523: 
  524: static reloc_howto_type *
  525: coff_arm_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
  526:                          asection *sec,
  527:                          struct internal_reloc *rel,
  528:                          struct coff_link_hash_entry *h ATTRIBUTE_UNUSED,
  529:                          struct internal_syment *sym ATTRIBUTE_UNUSED,
  530:                          bfd_vma *addendp)
  531: {
  532:   reloc_howto_type * howto;
  533: 
  534:   if (rel->r_type >= NUM_RELOCS)
  535:     return NULL;
  536: 
  537:   howto = aoutarm_std_reloc_howto + rel->r_type;
  538: 
  539:   if (rel->r_type == ARM_RVA32)
  540:     *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
  541: 
  542: #if defined COFF_WITH_PE && defined ARM_WINCE
  543:   if (rel->r_type == ARM_SECREL)
  544:     {
  545:       bfd_vma osect_vma;
  546: 
  547:       if (h && (h->type == bfd_link_hash_defined
  548:                 || h->type == bfd_link_hash_defweak))
  549:         osect_vma = h->root.u.def.section->output_section->vma;
  550:       else
  551:         {
  552:           asection *sec;
  553:           int i;
  554: 
  555:           /* Sigh, the only way to get the section to offset against
  556:              is to find it the hard way.  */
  557: 
  558:           for (sec = abfd->sections, i = 1; i < sym->n_scnum; i++)
  559:             sec = sec->next;
  560: 
  561:           osect_vma = sec->output_section->vma;
  562:         }
  563: 
  564:       *addendp -= osect_vma;
  565:     }
  566: #endif
  567: 
  568:   return howto;
  569: }
  570: 
  571: /* Used by the assembler.  */
  572: 
  573: static bfd_reloc_status_type
  574: aoutarm_fix_pcrel_26_done (bfd *abfd ATTRIBUTE_UNUSED,
  575:                            arelent *reloc_entry ATTRIBUTE_UNUSED,
  576:                            asymbol *symbol ATTRIBUTE_UNUSED,
  577:                            void * data ATTRIBUTE_UNUSED,
  578:                            asection *input_section ATTRIBUTE_UNUSED,
  579:                            bfd *output_bfd ATTRIBUTE_UNUSED,
  580:                            char **error_message ATTRIBUTE_UNUSED)
  581: {
  582:   /* This is dead simple at present.  */
  583:   return bfd_reloc_ok;
  584: }
  585: 
  586: /* Used by the assembler.  */
  587: 
  588: static bfd_reloc_status_type
  589: aoutarm_fix_pcrel_26 (bfd *abfd,
  590:                       arelent *reloc_entry,
  591:                       asymbol *symbol,
  592:                       void * data,
  593:                       asection *input_section,
  594:                       bfd *output_bfd,
  595:                       char **error_message ATTRIBUTE_UNUSED)
  596: {
  597:   bfd_vma relocation;
  598:   bfd_size_type addr = reloc_entry->address;
  599:   long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
  600:   bfd_reloc_status_type flag = bfd_reloc_ok;
  601: 
  602:   /* If this is an undefined symbol, return error.  */
  603:   if (symbol->section == &bfd_und_section
  604:       && (symbol->flags & BSF_WEAK) == 0)
  605:     return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
  606: 
  607:   /* If the sections are different, and we are doing a partial relocation,
  608:      just ignore it for now.  */
  609:   if (symbol->section->name != input_section->name
  610:       && output_bfd != (bfd *)NULL)
  611:     return bfd_reloc_continue;
  612: 
  613:   relocation = (target & 0x00ffffff) << 2;
  614:   relocation = (<