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

binutils/2.18/bfd/coff-maxq.c

    1: /* BFD back-end for MAXQ COFF binaries.
    2:    Copyright 2004, 2007  Free Software Foundation, Inc.
    3: 
    4:    Contributed by Vineet Sharma (vineets@noida.hcltech.com) Inderpreet S.
    5:    (inderpreetb@noida.hcltech.com)
    6: 
    7:    HCL Technologies Ltd.
    8: 
    9:    This file is part of BFD, the Binary File Descriptor library.
   10: 
   11:    This program is free software; you can redistribute it and/or modify it
   12:    under the terms of the GNU General Public License as published by the Free 
   13:    Software Foundation; either version 3 of the License, or (at your option)
   14:    any later version.
   15: 
   16:    This program is distributed in the hope that it will be useful, but
   17:    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
   18:    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   19:    for more details.
   20: 
   21:    You should have received a copy of the GNU General Public License along
   22:    with this program; if not, write to the Free Software Foundation, Inc., 
   23:    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
   24: 
   25: #include "sysdep.h"
   26: #include "bfd.h"
   27: #include "libbfd.h"
   28: #include "coff/maxq.h"
   29: #include "coff/internal.h"
   30: #include "libcoff.h"
   31: #include "libiberty.h"
   32: 
   33: #ifndef MAXQ20
   34: #define MAXQ20 1
   35: #endif
   36: 
   37: #define RTYPE2HOWTO(cache_ptr, dst)                                     \
   38:   ((cache_ptr)->howto =                                                 \
   39:    ((dst)->r_type < 48                                                  \
   40:     ? howto_table + (((dst)->r_type==47) ? 6: ((dst)->r_type))          \
   41:     : NULL))
   42: 
   43: #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
   44: 
   45: /* Code to swap in the reloc offset.  */
   46: #define SWAP_IN_RELOC_OFFSET    H_GET_16
   47: #define SWAP_OUT_RELOC_OFFSET   H_PUT_16
   48: 
   49: #define SHORT_JUMP              BFD_RELOC_16_PCREL_S2
   50: #define LONG_JUMP               BFD_RELOC_14
   51: #define ABSOLUTE_ADDR_FOR_DATA  BFD_RELOC_24
   52: 
   53: /* checks the range of short jump -127 to 128 */
   54: #define IS_SJUMP_RANGE(x) ((x > -128) && (x < 129))
   55: #define HIGH_WORD_MASK    0xff00
   56: #define LOW_WORD_MASK     0x00ff
   57: 
   58: static long
   59: get_symbol_value (asymbol *symbol)
   60: {
   61:   long relocation = 0;
   62: 
   63:   if (bfd_is_com_section (symbol->section))
   64:     relocation = 0;
   65:   else
   66:     relocation = symbol->value +
   67:       symbol->section->output_section->vma + symbol->section->output_offset;
   68: 
   69:   return relocation;
   70: }
   71: 
   72: /* This function performs all the maxq relocations.
   73:    FIXME:  The handling of the addend in the 'BFD_*'
   74:    relocations types.  */
   75: 
   76: static bfd_reloc_status_type
   77: coff_maxq20_reloc (bfd *      abfd,
   78:                    arelent *  reloc_entry,
   79:                    asymbol *  symbol_in,
   80:                    void *     data,
   81:                    asection * input_section ATTRIBUTE_UNUSED,
   82:                    bfd *      output_bfd    ATTRIBUTE_UNUSED,
   83:                    char **    error_message ATTRIBUTE_UNUSED)
   84: {
   85:   unsigned char *addr = NULL;
   86:   unsigned long x = 0;
   87:   long call_addr = 0;
   88:   short addend = 0;
   89:   long diff = 0;
   90: 
   91:   /* If this is an undefined symbol, return error.  */
   92:   if (symbol_in->section == &bfd_und_section
   93:       && (symbol_in->flags & BSF_WEAK) == 0)
   94:     return bfd_reloc_continue;
   95: 
   96:   if (data && reloc_entry)
   97:     {
   98:       addr = (unsigned char *) data + reloc_entry->address;
   99:       call_addr = call_addr - call_addr;
  100:       call_addr = get_symbol_value (symbol_in);
  101: 
  102:       /* Over here the value val stores the 8 bit/16 bit value. We will put a 
  103:          check if we are moving a 16 bit immediate value into an 8 bit
  104:          register. In that case we will generate a Upper bytes into PFX[0]
  105:          and move the lower 8 bits as SRC.  */
  106: 
  107:       switch (reloc_entry->howto->type)
  108:         {
  109:           /* BFD_RELOC_16_PCREL_S2 47 Handles all the relative jumps and
  110:              calls Note: Every relative jump or call is in words.  */
  111:         case SHORT_JUMP:
  112:           /* Handle any addend.  */
  113:           addend = reloc_entry->addend;
  114: 
  115:           if (addend > call_addr || addend > 0)
  116:             call_addr = symbol_in->section->output_section->vma + addend;
  117:           else if (addend < call_addr && addend > 0)
  118:             call_addr = call_addr + addend;
  119:           else if (addend < 0)
  120:             call_addr = call_addr + addend;
  121: 
  122:           diff = ((call_addr << 1) - (reloc_entry->address << 1));
  123: 
  124:           if (!IS_SJUMP_RANGE (diff))
  125:             {
  126:               bfd_perror (_("Can't Make it a Short Jump"));
  127:               return bfd_reloc_outofrange;
  128:             }
  129: 
  130:           x = bfd_get_16 (abfd, addr);
  131: 
  132:           x = x & LOW_WORD_MASK;
  133:           x = x | (diff << 8);
  134:           bfd_put_16 (abfd, (bfd_vma) x, addr);
  135: 
  136:           return bfd_reloc_ok;
  137: 
  138:         case ABSOLUTE_ADDR_FOR_DATA:
  139:         case LONG_JUMP:
  140:           /* BFD_RELOC_14 Handles intersegment or long jumps which might be
  141:              from code to code or code to data segment jumps. Note: When this 
  142:              fucntion is called by gas the section flags somehow do not
  143:              contain the info about the section type(CODE or DATA). Thus the
  144:              user needs to evoke the linker after assembling the files
  145:              because the Code-Code relocs are word aligned but code-data are
  146:              byte aligned.  */
  147:           addend = (reloc_entry->addend - reloc_entry->addend);
  148: 
  149:           /* Handle any addend.  */
  150:           addend = reloc_entry->addend;
  151: 
  152:           /* For relocation involving multiple file added becomes zero thus
  153:              this fails - check for zero added. In another case when we try
  154:              to add a stub to a file the addend shows the offset from the
  155:              start od this file.  */
  156:           addend = 0;
  157: 
  158:           if (!bfd_is_com_section (symbol_in->section) &&
  159:               ((symbol_in->flags & BSF_OLD_COMMON) == 0))
  160:             {
  161:               if (reloc_entry->addend > symbol_in->value)
  162:                 addend = reloc_entry->addend - symbol_in->value;
  163: 
  164:               if ((reloc_entry->addend < symbol_in->value)
  165:                   && (reloc_entry->addend != 0))
  166:                 addend = reloc_entry->addend - symbol_in->value;
  167: 
  168:               if (reloc_entry->addend == symbol_in->value)
  169:                 addend = 0;
  170:             }
  171: 
  172:           if (bfd_is_com_section (symbol_in->section) ||
  173:               ((symbol_in->flags & BSF_OLD_COMMON) != 0))
  174:             addend = reloc_entry->addend;
  175: 
  176:           if (addend < 0
  177:               &&  (call_addr < (long) (addend * (-1))))
  178:             addend = 0;
  179: 
  180:           call_addr += addend;
  181: 
  182:           /* FIXME: This check does not work well with the assembler,
  183:              linker needs to be run always.  */
  184:           if ((symbol_in->section->flags & SEC_CODE) == SEC_CODE)
  185:             {
  186:               /* Convert it into words.  */
  187:               call_addr = call_addr >> 1;
  188: 
  189:               if (call_addr > 0xFFFF)  /* Intersegment Jump.  */
  190:                 {
  191:                   bfd_perror (_("Exceeds Long Jump Range"));
  192:                   return bfd_reloc_outofrange;
  193:                 }
  194:             }
  195:           else
  196:             {
  197:               /* case ABSOLUTE_ADDR_FOR_DATA : Resolves any code-data
  198:                  segemnt relocs. These are NOT word aligned.  */
  199: 
  200:               if (call_addr > 0xFFFF)  /* Intersegment Jump.  */
  201:                 {
  202:                   bfd_perror (_("Absolute address Exceeds 16 bit Range"));
  203:                   return bfd_reloc_outofrange;
  204:                 }
  205:             }
  206: 
  207:           x = bfd_get_32 (abfd, addr);
  208: 
  209:           x = (x & 0xFF00FF00);
  210:           x = (x | ((call_addr & HIGH_WORD_MASK) >> 8));
  211:           x = (x | (call_addr & LOW_WORD_MASK) << 16);
  212: 
  213:           bfd_put_32 (abfd, (bfd_vma) x, addr);
  214:           return bfd_reloc_ok;
  215: 
  216:         case BFD_RELOC_8:
  217:           addend = (reloc_entry->addend - reloc_entry->addend);
  218: 
  219:           if (!bfd_is_com_section (symbol_in->section) &&
  220:               ((symbol_in->flags & BSF_OLD_COMMON) == 0))
  221:             {
  222:               if (reloc_entry->addend > symbol_in->value)
  223:                 addend = reloc_entry->addend - symbol_in->value;
  224:               if (reloc_entry->addend < symbol_in->value)
  225:                 addend = reloc_entry->addend - symbol_in->value;
  226:               if (reloc_entry->addend == symbol_in->value)
  227:                 addend = 0;
  228:             }
  229: 
  230:           if (bfd_is_com_section (symbol_in->section) ||
  231:               ((symbol_in->flags & BSF_OLD_COMMON) != 0))
  232:             addend = reloc_entry->addend;
  233: 
  234:           if (addend < 0
  235:               && (call_addr < (long) (addend * (-1))))
  236:             addend = 0;
  237: 
  238:           if (call_addr + addend > 0xFF)
  239:             {
  240:               bfd_perror (_("Absolute address Exceeds 8 bit Range"));
  241:               return bfd_reloc_outofrange;
  242:             }
  243: 
  244:           x = bfd_get_8 (abfd, addr);
  245:           x = x & 0x00;
  246:           x = x | (call_addr + addend);
  247: 
  248:           bfd_put_8 (abfd, (bfd_vma) x, addr);
  249:           return bfd_reloc_ok;
  250: 
  251:         case BFD_RELOC_16:
  252:           addend = (reloc_entry->addend - reloc_entry->addend);
  253:           if (!bfd_is_com_section (symbol_in->section) &&
  254:               ((symbol_in->flags & BSF_OLD_COMMON) == 0))
  255:             {
  256:               if (reloc_entry->addend > symbol_in->value)
  257:                 addend = reloc_entry->addend - symbol_in->value;
  258: 
  259:               if (reloc_entry->addend < symbol_in->value)
  260:                 addend = reloc_entry->addend - symbol_in->value;
  261: 
  262:               if (reloc_entry->addend == symbol_in->value)
  263:                 addend = 0;
  264:             }
  265: 
  266:           if (bfd_is_com_section (symbol_in->section) ||
  267:               ((symbol_in->flags & BSF_OLD_COMMON) != 0))
  268:             addend = reloc_entry->addend;
  269: 
  270:           if (addend < 0
  271:               && (call_addr < (long) (addend * (-1))))
  272:             addend = 0;
  273: 
  274:           if ((call_addr + addend) > 0xFFFF)
  275:             {
  276:               bfd_perror (_("Absolute address Exceeds 16 bit Range"));
  277:               return bfd_reloc_outofrange;
  278:             }
  279:           else
  280:             {
  281:               unsigned short val = (call_addr + addend);
  282: 
  283:               x = bfd_get_16 (abfd, addr);
  284: 
  285:               /* LE */
  286:               x = (x & 0x0000);        /* Flush garbage value.  */
  287:               x = val;
  288:               if ((symbol_in->section->flags & SEC_CODE) == SEC_CODE)
  289:                 x = x >> 1;   /* Convert it into words.  */
  290:             }
  291: 
  292:           bfd_put_16 (abfd, (bfd_vma) x, addr);
  293:           return bfd_reloc_ok;
  294: 
  295:         case BFD_RELOC_32:
  296:           addend = (reloc_entry->addend - reloc_entry->addend);
  297: 
  298:           if (!bfd_is_com_section (symbol_in->section) &&
  299:               ((symbol_in->flags & BSF_OLD_COMMON) == 0))
  300:             {
  301:               if (reloc_entry->addend > symbol_in->value)
  302:                 addend = reloc_entry->addend - symbol_in->value;
  303:               if (reloc_entry->addend < symbol_in->value)
  304:                 addend = reloc_entry->addend - symbol_in->value;
  305:               if (reloc_entry->addend == symbol_in->value)
  306:                 addend = 0;
  307:             }
  308: 
  309:           if (bfd_is_com_section (symbol_in->section) ||
  310:               ((symbol_in->flags & BSF_OLD_COMMON) != 0))
  311:             addend = reloc_entry->addend;
  312: 
  313:           if (addend < 0
  314:               && (call_addr < (long) (addend * (-1))))
  315:             addend = 0;
  316: 
  317:           if ((call_addr + addend) < 0)
  318:             {
  319:               bfd_perror ("Absolute address Exceeds 32 bit Range");
  320:               return bfd_reloc_outofrange;
  321:             }
  322: 
  323:           x = bfd_get_32 (abfd, addr);
  324:           x = (x & 0x0000);    /* Flush garbage value.  */
  325:           x = call_addr + addend;
  326:           if ((symbol_in->section->flags & SEC_CODE) == SEC_CODE)
  327:             x = x >> 1;        /* Convert it into words.  */
  328: 
  329:           bfd_put_32 (abfd, (bfd_vma) x, addr);
  330:           return bfd_reloc_ok;
  331: 
  332:         default:
  333:           bfd_perror (_("Unrecognized Reloc Type"));
  334:           return bfd_reloc_notsupported;
  335:         }
  336:     }
  337: 
  338:   return bfd_reloc_notsupported;
  339: }
  340: 
  341: static reloc_howto_type howto_table[] =
  342: {
  343:   EMPTY_HOWTO (0),
  344:   EMPTY_HOWTO (1),
  345:   {
  346:    BFD_RELOC_32, 0, 1, 8, FALSE, 0, complain_overflow_bitfield,
  347:    coff_maxq20_reloc, "32Bit", TRUE, 0x000000ff, 0x000000ff, TRUE
  348:   },
  349:   {
  350:    SHORT_JUMP, 0, 1, 8, FALSE, 0, complain_overflow_bitfield,
  351:    coff_maxq20_reloc, "SHORT_JMP", TRUE, 0x000000ff, 0x000000ff, TRUE
  352:   },
  353:   {
  354:    ABSOLUTE_ADDR_FOR_DATA, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
  355:    coff_maxq20_reloc, "INTERSEGMENT_RELOC", TRUE, 0x00000000, 0x00000000,
  356:    FALSE
  357:   },
  358:   {
  359:    BFD_RELOC_16, 0, 1, 8, FALSE, 0, complain_overflow_bitfield,
  360:    coff_maxq20_reloc, "16Bit", TRUE, 0x000000ff, 0x000000ff, TRUE
  361:   },
  362:   {
  363:    LONG_JUMP, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
  364:    coff_maxq20_reloc, "LONG_JUMP", TRUE, 0x00000000, 0x00000000, FALSE
  365:   },
  366:   {
  367:    BFD_RELOC_8, 0, 1, 8, FALSE, 0, complain_overflow_bitfield,
  368:    coff_maxq20_reloc, "8bit", TRUE, 0x000000ff, 0x000000ff, TRUE
  369:   },
  370:   EMPTY_HOWTO (8),
  371:   EMPTY_HOWTO (9),
  372:   EMPTY_HOWTO (10),
  373: };
  374: 
  375: static reloc_howto_type *
  376: maxq_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
  377:                         bfd_reloc_code_real_type code)
  378: {
  379:   switch (code)
  380:     {
  381:       /* SHORT JUMP */
  382:     case BFD_RELOC_16_PCREL_S2:
  383:       return howto_table + 3;
  384:       
  385:       /* INTERSEGMENT JUMP */
  386:     case BFD_RELOC_24:
  387:       return howto_table + 4;
  388:       
  389:       /* BYTE RELOC */
  390:     case BFD_RELOC_8:
  391:       return howto_table + 7;
  392:       
  393:       /* WORD RELOC */
  394:     case BFD_RELOC_16:
  395:       return howto_table + 5;
  396:       
  397:       /* LONG RELOC */
  398:     case BFD_RELOC_32:
  399:       return howto_table + 2;
  400:       
  401:       /* LONG JUMP */
  402:     case BFD_RELOC_14:
  403:       return howto_table + 6;
  404:       
  405:     default:
  406:       return NULL;
  407:     }
  408: }
  409: 
  410: static reloc_howto_type *
  411: maxq_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
  412: {
  413:   unsigned int i;
  414: 
  415:   for (i = 0; i < sizeof (howto_table) / sizeof (howto_table[0]); i++)
  416:     if (howto_table[i].name != NULL
  417:         && strcasecmp (howto_table[i].name, r_name) == 0)
  418:       return &howto_table[i];
  419: 
  420:   return NULL;
  421: }
  422: 
  423: #define coff_bfd_reloc_type_lookup maxq_reloc_type_lookup
  424: #define coff_bfd_reloc_name_lookup maxq_reloc_name_lookup
  425: 
  426: /* Perform any necessary magic to the addend in a reloc entry.  */
  427: #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
  428:  cache_ptr->addend =  ext_reloc.r_offset;
  429: 
  430: #include "coffcode.h"
  431: 
  432: #ifndef TARGET_UNDERSCORE
  433: #define TARGET_UNDERSCORE 1
  434: #endif
  435: 
  436: #ifndef EXTRA_S_FLAGS
  437: #define EXTRA_S_FLAGS 0
  438: #endif
  439: 
  440: /* Forward declaration for use initialising alternative_target field.  */
  441: CREATE_LITTLE_COFF_TARGET_VEC (maxqcoff_vec, "coff-maxq", 0, EXTRA_S_FLAGS,
  442:                                TARGET_UNDERSCORE, NULL, COFF_SWAP_TABLE);
  443: 
Syntax (Markdown)