[BACK]Return to elf32-arc.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils.old / dist / bfd

Annotation of src/external/gpl3/binutils.old/dist/bfd/elf32-arc.c, Revision 1.1.1.1.2.1

1.1       christos    1: /* ARC-specific support for 32-bit ELF
1.1.1.1.2.1! pgoyette    2:    Copyright (C) 1994-2015 Free Software Foundation, Inc.
        !             3:    Contributed by Cupertino Miranda (cmiranda@synopsys.com).
1.1       christos    4:
                      5:    This file is part of BFD, the Binary File Descriptor library.
                      6:
                      7:    This program is free software; you can redistribute it and/or modify
                      8:    it under the terms of the GNU General Public License as published by
                      9:    the Free Software Foundation; either version 3 of the License, or
                     10:    (at your option) any later version.
                     11:
                     12:    This program is distributed in the hope that it will be useful,
                     13:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15:    GNU General Public License for more details.
                     16:
                     17:    You should have received a copy of the GNU General Public License
                     18:    along with this program; if not, write to the Free Software
                     19:    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
                     20:    MA 02110-1301, USA.  */
                     21:
                     22: #include "sysdep.h"
                     23: #include "bfd.h"
                     24: #include "libbfd.h"
                     25: #include "elf-bfd.h"
                     26: #include "elf/arc.h"
                     27: #include "libiberty.h"
1.1.1.1.2.1! pgoyette   28: #include "opcode/arc-func.h"
        !            29:
        !            30: #define ARC_DEBUG(...)
        !            31: #define DEBUG(...) printf (__ARGV__)
        !            32: #define DEBUG_ARC_RELOC(A)
        !            33:
        !            34: struct arc_local_data
        !            35: {
        !            36:   bfd_vma        sdata_begin_symbol_vma;
        !            37:   asection *      sdata_output_section;
        !            38:   bfd_vma        got_symbol_vma;
        !            39: };
        !            40:
        !            41: struct arc_local_data global_arc_data =
        !            42: {
        !            43:   .sdata_begin_symbol_vma = 0,
        !            44:   .sdata_output_section = NULL,
        !            45:   .got_symbol_vma = 0,
        !            46: };
        !            47:
        !            48: struct dynamic_sections
        !            49: {
        !            50:   bfd_boolean    initialized;
        !            51:   asection *      sgot;
        !            52:   asection *      srelgot;
        !            53:   asection *      sgotplt;
        !            54:   asection *      sdyn;
        !            55:   asection *      splt;
        !            56:   asection *      srelplt;
        !            57: };
        !            58:
        !            59: static struct dynamic_sections
        !            60: arc_create_dynamic_sections (bfd * abfd, struct bfd_link_info *info);
        !            61:
        !            62: enum dyn_section_types
        !            63: {
        !            64:   got = 0,
        !            65:   relgot,
        !            66:   gotplt,
        !            67:   dyn,
        !            68:   plt,
        !            69:   relplt,
        !            70:   DYN_SECTION_TYPES_END
        !            71: };
        !            72:
        !            73: const char * dyn_section_names[DYN_SECTION_TYPES_END] =
        !            74: {
        !            75:   ".got",
        !            76:   ".rela.got",
        !            77:   ".got.plt",
        !            78:   ".dynamic",
        !            79:   ".plt",
        !            80:   ".rela.plt"
        !            81: };
        !            82:
        !            83: /* The default symbols representing the init and fini dyn values.
        !            84:    TODO: Check what is the relation of those strings with arclinux.em
        !            85:    and DT_INIT.  */
        !            86: #define INIT_SYM_STRING "_init"
        !            87: #define FINI_SYM_STRING "_fini"
        !            88:
        !            89: char * init_str = INIT_SYM_STRING;
        !            90: char * fini_str = FINI_SYM_STRING;
        !            91:
        !            92:
        !            93: #define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
        !            94:       case VALUE: \
        !            95:        return #TYPE; \
        !            96:        break;
        !            97:
        !            98: static ATTRIBUTE_UNUSED const char *
        !            99: reloc_type_to_name (unsigned int type)
        !           100: {
        !           101:   switch (type)
        !           102:     {
        !           103:       #include "elf/arc-reloc.def"
        !           104:
        !           105:       default:
        !           106:        return "UNKNOWN";
        !           107:        break;
        !           108:     }
        !           109: }
        !           110: #undef ARC_RELOC_HOWTO
1.1       christos  111:
                    112: /* Try to minimize the amount of space occupied by relocation tables
                    113:    on the ROM (not that the ROM won't be swamped by other ELF overhead).  */
                    114:
1.1.1.1.2.1! pgoyette  115: #define USE_REL 1
        !           116:
        !           117: static ATTRIBUTE_UNUSED bfd_boolean
        !           118: is_reloc_PC_relative (reloc_howto_type *howto)
        !           119: {
        !           120:   return (strstr (howto->name, "PC") != NULL) ? TRUE : FALSE;
        !           121: }
        !           122:
        !           123: static bfd_boolean
        !           124: is_reloc_SDA_relative (reloc_howto_type *howto)
        !           125: {
        !           126:   return (strstr (howto->name, "SDA") != NULL) ? TRUE : FALSE;
        !           127: }
        !           128:
        !           129: static bfd_boolean
        !           130: is_reloc_for_GOT (reloc_howto_type * howto)
        !           131: {
        !           132:   return (strstr (howto->name, "GOT") != NULL) ? TRUE : FALSE;
        !           133: }
        !           134:
        !           135: static bfd_boolean
        !           136: is_reloc_for_PLT (reloc_howto_type * howto)
        !           137: {
        !           138:   return (strstr (howto->name, "PLT") != NULL) ? TRUE : FALSE;
        !           139: }
        !           140:
        !           141: #define arc_bfd_get_8(A,B,C) bfd_get_8(A,B)
        !           142: #define arc_bfd_get_16(A,B,C) bfd_get_16(A,B)
        !           143: #define arc_bfd_put_8(A,B,C,D) bfd_put_8(A,B,C)
        !           144: #define arc_bfd_put_16(A,B,C,D) bfd_put_16(A,B,C)
        !           145:
        !           146: static long
        !           147: arc_bfd_get_32 (bfd * abfd, void *loc, asection * input_section)
        !           148: {
        !           149:   long insn = bfd_get_32 (abfd, loc);
        !           150:
        !           151:   if (!bfd_big_endian (abfd)
        !           152:       && input_section
        !           153:       && (input_section->flags & SEC_CODE))
        !           154:     insn = ((0x0000fffff & insn) << 16) | ((0xffff0000 & insn) >> 16);
        !           155:
        !           156:   return insn;
        !           157: }
        !           158:
        !           159: static void
        !           160: arc_bfd_put_32 (bfd * abfd, long insn, void *loc, asection * input_section)
        !           161: {
        !           162:   if (!bfd_big_endian (abfd)
        !           163:       && input_section
        !           164:       && (input_section->flags & SEC_CODE))
        !           165:     insn = ((0x0000fffff & insn) << 16) | ((0xffff0000 & insn) >> 16);
        !           166:
        !           167:   bfd_put_32 (abfd, insn, loc);
        !           168: }
1.1       christos  169:
                    170: static bfd_reloc_status_type
1.1.1.1.2.1! pgoyette  171: arc_elf_reloc (bfd *abfd ATTRIBUTE_UNUSED,
        !           172:               arelent *reloc_entry,
        !           173:               asymbol *symbol_in,
        !           174:               void *data ATTRIBUTE_UNUSED,
        !           175:               asection *input_section,
        !           176:               bfd *output_bfd,
        !           177:               char ** error_message ATTRIBUTE_UNUSED)
        !           178: {
        !           179:   if (output_bfd != NULL)
        !           180:     {
        !           181:       reloc_entry->address += input_section->output_offset;
        !           182:
        !           183:       /* In case of relocateable link and if the reloc is against a
        !           184:         section symbol, the addend needs to be adjusted according to
        !           185:         where the section symbol winds up in the output section.  */
        !           186:       if ((symbol_in->flags & BSF_SECTION_SYM) && symbol_in->section)
        !           187:        reloc_entry->addend += symbol_in->section->output_offset;
        !           188:
        !           189:       return bfd_reloc_ok;
        !           190:     }
        !           191:
        !           192:   return bfd_reloc_continue;
        !           193: }
        !           194:
        !           195:
        !           196: #define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
        !           197:   TYPE = VALUE,
        !           198: enum howto_list
        !           199: {
        !           200: #include "elf/arc-reloc.def"
        !           201:   HOWTO_LIST_LAST
1.1       christos  202: };
1.1.1.1.2.1! pgoyette  203: #undef ARC_RELOC_HOWTO
        !           204:
        !           205: #define ARC_RELOC_HOWTO(TYPE, VALUE, RSIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
        !           206:   [TYPE] = HOWTO (R_##TYPE, 0, RSIZE, BITSIZE, FALSE, 0, complain_overflow_##OVERFLOW, arc_elf_reloc, #TYPE, FALSE, 0, 0, FALSE),
        !           207:
        !           208: static struct reloc_howto_struct elf_arc_howto_table[] =
        !           209: {
        !           210: #include "elf/arc-reloc.def"
        !           211: /* Example of what is generated by the preprocessor.  Currently kept as an example.
        !           212:  HOWTO (R_ARC_NONE, // Type.
        !           213:     0, // Rightshift.
        !           214:     2, // Size (0 = byte, 1 = short, 2 = long).
        !           215:     32, // Bitsize.
        !           216:     FALSE, // PC_relative.
        !           217:     0, // Bitpos.
        !           218:     complain_overflow_bitfield, // Complain_on_overflow.
        !           219:     bfd_elf_generic_reloc, // Special_function.
        !           220:     "R_ARC_NONE", // Name.
        !           221:     TRUE, // Partial_inplace.
        !           222:     0, // Src_mask.
        !           223:     0, // Dst_mask.
        !           224:     FALSE), // PCrel_offset.
        !           225: */
        !           226: };
        !           227: #undef ARC_RELOC_HOWTO
        !           228:
        !           229: static void arc_elf_howto_init (void)
        !           230: {
        !           231: #define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
        !           232:   elf_arc_howto_table[TYPE].pc_relative = \
        !           233:     (strstr (#FORMULA, " P ") != NULL || strstr (#FORMULA, " PDATA ") != NULL);
        !           234:
        !           235:   #include "elf/arc-reloc.def"
        !           236: }
        !           237: #undef ARC_RELOC_HOWTO
        !           238:
        !           239:
        !           240: #define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
        !           241:   [TYPE] = VALUE,
        !           242: const int howto_table_lookup[] =
        !           243: {
        !           244:   #include "elf/arc-reloc.def"
        !           245: };
        !           246: #undef ARC_RELOC_HOWTO
        !           247:
        !           248: #define ARC_ELF_HOWTO(r_type) \
        !           249:   (&elf_arc_howto_table[r_type])
1.1       christos  250:
                    251: /* Map BFD reloc types to ARC ELF reloc types.  */
                    252:
                    253: struct arc_reloc_map
                    254: {
                    255:   bfd_reloc_code_real_type bfd_reloc_val;
1.1.1.1.2.1! pgoyette  256:   unsigned char   elf_reloc_val;
1.1       christos  257: };
                    258:
1.1.1.1.2.1! pgoyette  259: #define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
        !           260:   { BFD_RELOC_##TYPE, R_##TYPE },
1.1       christos  261: static const struct arc_reloc_map arc_reloc_map[] =
                    262: {
1.1.1.1.2.1! pgoyette  263:   #include "elf/arc-reloc.def"
        !           264:   {BFD_RELOC_NONE,  R_ARC_NONE},
        !           265:   {BFD_RELOC_8,  R_ARC_8},
        !           266:   {BFD_RELOC_16, R_ARC_16},
        !           267:   {BFD_RELOC_24, R_ARC_24},
        !           268:   {BFD_RELOC_32, R_ARC_32},
1.1       christos  269: };
1.1.1.1.2.1! pgoyette  270: #undef ARC_RELOC_HOWTO
1.1       christos  271:
                    272: static reloc_howto_type *
1.1.1.1.2.1! pgoyette  273: bfd_elf32_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
1.1       christos  274:                                 bfd_reloc_code_real_type code)
                    275: {
                    276:   unsigned int i;
1.1.1.1.2.1! pgoyette  277:   static int fully_initialized = FALSE;
        !           278:
        !           279:   if (fully_initialized == FALSE)
        !           280:     {
        !           281:       arc_elf_howto_init ();
        !           282:       fully_initialized = TRUE; /* TODO: CHECK THIS IF IT STOPS WORKING.  */
        !           283:     }
1.1       christos  284:
                    285:   for (i = ARRAY_SIZE (arc_reloc_map); i--;)
1.1.1.1.2.1! pgoyette  286:     {
        !           287:       if (arc_reloc_map[i].bfd_reloc_val == code)
        !           288:        return elf_arc_howto_table + arc_reloc_map[i].elf_reloc_val;
        !           289:     }
1.1       christos  290:
                    291:   return NULL;
                    292: }
                    293:
                    294: static reloc_howto_type *
1.1.1.1.2.1! pgoyette  295: bfd_elf32_bfd_reloc_name_lookup (bfd * abfd ATTRIBUTE_UNUSED, const char *r_name)
1.1       christos  296: {
                    297:   unsigned int i;
                    298:
1.1.1.1.2.1! pgoyette  299:   for (i = 0; i < ARRAY_SIZE (elf_arc_howto_table); i++)
1.1       christos  300:     if (elf_arc_howto_table[i].name != NULL
                    301:        && strcasecmp (elf_arc_howto_table[i].name, r_name) == 0)
1.1.1.1.2.1! pgoyette  302:       return elf_arc_howto_table + i;
1.1       christos  303:
                    304:   return NULL;
                    305: }
                    306:
                    307:
1.1.1.1.2.1! pgoyette  308: /* Set the howto pointer for an ARC ELF reloc.  */
1.1       christos  309: static void
1.1.1.1.2.1! pgoyette  310: arc_info_to_howto_rel (bfd * abfd ATTRIBUTE_UNUSED,
        !           311:                       arelent * cache_ptr,
        !           312:                       Elf_Internal_Rela * dst)
1.1       christos  313: {
                    314:   unsigned int r_type;
                    315:
                    316:   r_type = ELF32_R_TYPE (dst->r_info);
                    317:   BFD_ASSERT (r_type < (unsigned int) R_ARC_max);
                    318:   cache_ptr->howto = &elf_arc_howto_table[r_type];
                    319: }
                    320:
                    321: /* Set the right machine number for an ARC ELF file.  */
                    322: static bfd_boolean
1.1.1.1.2.1! pgoyette  323: arc_elf_object_p (bfd * abfd)
1.1       christos  324: {
1.1.1.1.2.1! pgoyette  325:   /* Make sure this is initialised, or you'll have the potential of passing
        !           326:      garbage---or misleading values---into the call to
        !           327:      bfd_default_set_arch_mach ().  */
        !           328:   int            mach = bfd_mach_arc_arc700;
        !           329:   unsigned long   arch = elf_elfheader (abfd)->e_flags & EF_ARC_MACH_MSK;
        !           330:   unsigned       e_machine = elf_elfheader (abfd)->e_machine;
1.1       christos  331:
1.1.1.1.2.1! pgoyette  332:   if (e_machine == EM_ARC_COMPACT || e_machine == EM_ARC_COMPACT2)
1.1       christos  333:     {
                    334:       switch (arch)
                    335:        {
1.1.1.1.2.1! pgoyette  336:          case E_ARC_MACH_ARC600:
        !           337:            mach = bfd_mach_arc_arc600;
        !           338:            break;
        !           339:          case E_ARC_MACH_ARC601:
        !           340:            mach = bfd_mach_arc_arc601;
        !           341:            break;
        !           342:          case E_ARC_MACH_ARC700:
        !           343:            mach = bfd_mach_arc_arc700;
        !           344:            break;
        !           345:          case EF_ARC_CPU_ARCV2HS:
        !           346:          case EF_ARC_CPU_ARCV2EM:
        !           347:            mach = bfd_mach_arc_arcv2;
        !           348:            break;
        !           349:          default:
        !           350:            mach = (e_machine == EM_ARC_COMPACT) ?
        !           351:              bfd_mach_arc_arc700 : bfd_mach_arc_arcv2;
        !           352:            break;
        !           353:        }
        !           354:     }
        !           355:   else
        !           356:     {
        !           357:       if (e_machine == EM_ARC)
        !           358:        {
        !           359:          (*_bfd_error_handler)
        !           360:            (_("Error: The ARC4 architecture is no longer supported.\n"));
        !           361:          return FALSE;
        !           362:        }
        !           363:       else
        !           364:        {
        !           365:          (*_bfd_error_handler)
        !           366:            (_("Warning: unset or old architecture flags. \n"
        !           367:               "               Use default machine.\n"));
1.1       christos  368:        }
                    369:     }
1.1.1.1.2.1! pgoyette  370:
1.1       christos  371:   return bfd_default_set_arch_mach (abfd, bfd_arch_arc, mach);
                    372: }
                    373:
                    374: /* The final processing done just before writing out an ARC ELF object file.
                    375:    This gets the ARC architecture right based on the machine number.  */
                    376:
                    377: static void
1.1.1.1.2.1! pgoyette  378: arc_elf_final_write_processing (bfd * abfd, bfd_boolean linker ATTRIBUTE_UNUSED)
1.1       christos  379: {
                    380:   unsigned long val;
1.1.1.1.2.1! pgoyette  381:   unsigned long emf;
1.1       christos  382:
                    383:   switch (bfd_get_mach (abfd))
                    384:     {
1.1.1.1.2.1! pgoyette  385:     case bfd_mach_arc_arc600:
        !           386:       val = E_ARC_MACH_ARC600;
        !           387:       emf = EM_ARC_COMPACT;
1.1       christos  388:       break;
1.1.1.1.2.1! pgoyette  389:     case bfd_mach_arc_arc601:
        !           390:       val = E_ARC_MACH_ARC601;
        !           391:       emf = EM_ARC_COMPACT;
1.1       christos  392:       break;
1.1.1.1.2.1! pgoyette  393:     case bfd_mach_arc_arc700:
        !           394:       val = E_ARC_MACH_ARC700;
        !           395:       emf = EM_ARC_COMPACT;
1.1       christos  396:       break;
1.1.1.1.2.1! pgoyette  397:     case bfd_mach_arc_arcv2:
        !           398:       val = EF_ARC_CPU_GENERIC;
        !           399:       emf = EM_ARC_COMPACT2;
        !           400:       /* TODO: Check validity of this.  It can also be ARCV2EM here.
        !           401:         Previous version sets the e_machine here.  */
1.1       christos  402:       break;
1.1.1.1.2.1! pgoyette  403:     default:
        !           404:       abort ();
1.1       christos  405:     }
1.1.1.1.2.1! pgoyette  406:   elf_elfheader (abfd)->e_flags &= ~EF_ARC_MACH;
1.1       christos  407:   elf_elfheader (abfd)->e_flags |= val;
1.1.1.1.2.1! pgoyette  408:   elf_elfheader (abfd)->e_machine = emf;
        !           409:
        !           410:   /* Record whatever is the current syscall ABI version.  */
        !           411:   elf_elfheader (abfd)->e_flags |= E_ARC_OSABI_CURRENT;
1.1       christos  412: }
                    413:
1.1.1.1.2.1! pgoyette  414: #define BFD_DEBUG_PIC(...)
        !           415:
        !           416: struct arc_relocation_data
        !           417: {
        !           418:   bfd_vma        reloc_offset;
        !           419:   bfd_vma        reloc_addend;
        !           420:   bfd_vma        got_offset_value;
        !           421:
        !           422:   bfd_vma        sym_value;
        !           423:   asection *     sym_section;
        !           424:
        !           425:   reloc_howto_type *howto;
        !           426:
        !           427:   asection *     input_section;
        !           428:
        !           429:   bfd_vma        sdata_begin_symbol_vma;
        !           430:   bfd_boolean    sdata_begin_symbol_vma_set;
        !           431:   bfd_vma        got_symbol_vma;
        !           432:
        !           433:   bfd_boolean    should_relocate;
        !           434: };
        !           435:
        !           436: static void
        !           437: debug_arc_reloc (struct arc_relocation_data reloc_data)
        !           438: {
        !           439:   fprintf (stderr, "Reloc type=%s, should_relocate = %s\n",
        !           440:           reloc_data.howto->name,
        !           441:           reloc_data.should_relocate ? "true" : "false");
        !           442:   fprintf (stderr, "  offset = 0x%x, addend = 0x%x\n",
        !           443:           (unsigned int) reloc_data.reloc_offset,
        !           444:           (unsigned int) reloc_data.reloc_addend);
        !           445:   fprintf (stderr, " Symbol:\n");
        !           446:   fprintf (stderr, "  value = 0x%08x\n",
        !           447:           (unsigned int) reloc_data.sym_value);
        !           448:   if (reloc_data.sym_section != NULL)
        !           449:     {
        !           450:       fprintf (stderr, "IN IF\n");
        !           451:       fprintf (stderr,
        !           452:               "  section name = %s, output_offset 0x%08x, output_section->vma = 0x%08x\n",
        !           453:               reloc_data.sym_section->name,
        !           454:               (unsigned int) reloc_data.sym_section->output_offset,
        !           455:               (unsigned int) reloc_data.sym_section->output_section->vma);
        !           456:     }
        !           457:   else
        !           458:     fprintf (stderr, " symbol section is NULL\n");
        !           459:
        !           460:   fprintf (stderr, " Input_section:\n");
        !           461:   if (reloc_data.input_section != NULL)
        !           462:     {
        !           463:       fprintf (stderr,
        !           464:               "  section name = %s, output_offset 0x%08x, output_section->vma = 0x%08x\n",
        !           465:               reloc_data.input_section->name,
        !           466:               (unsigned int) reloc_data.input_section->output_offset,
        !           467:               (unsigned int) reloc_data.input_section->output_section->vma);
        !           468:       fprintf (stderr, "  changed_address = 0x%08x\n",
        !           469:               (unsigned int) (reloc_data.input_section->output_section->vma +
        !           470:               reloc_data.input_section->output_offset +
        !           471:               reloc_data.reloc_offset));
        !           472:     }
        !           473:   else
        !           474:     fprintf (stderr, " input section is NULL\n");
        !           475: }
        !           476:
        !           477: static ATTRIBUTE_UNUSED bfd_vma
        !           478: get_middle_endian_relocation (bfd_vma reloc)
        !           479: {
        !           480:   bfd_vma ret =
        !           481:              ((reloc & 0xffff0000) >> 16) |
        !           482:              ((reloc & 0xffff) << 16);
        !           483:   return ret;
        !           484: }
        !           485:
        !           486: #define ME(RELOC) (get_middle_endian_reloction(RELOC))
        !           487:
        !           488: #define S (reloc_data.sym_value \
        !           489:           + reloc_data.sym_section->output_offset \
        !           490:           + reloc_data.sym_section->output_section->vma)
        !           491: #define A (reloc_data.reloc_addend)
        !           492: #define B (0)
        !           493: #define G (reloc_data.got_offset_value)
        !           494: #define GOT (reloc_data.got_symbol_vma + 12)
        !           495: #define L (reloc_data.sym_value \
        !           496:           + reloc_data.sym_section->output_section->vma \
        !           497:           + reloc_data.sym_section->output_offset)
        !           498: #define MES (0)
        !           499:        /* P: relative offset to PCL The offset should be to the current location
        !           500:           aligned to 32 bits.  */
        !           501: #define P ( \
        !           502:            (reloc_data.input_section->output_section->vma \
        !           503:             + reloc_data.input_section->output_offset \
        !           504:             + (reloc_data.reloc_offset - (bitsize >= 32 ? 4 : 0)) \
        !           505:            ) & ~0x3)
        !           506: #define PDATA ( \
        !           507:            (reloc_data.input_section->output_section->vma \
        !           508:             + reloc_data.input_section->output_offset \
        !           509:             + (reloc_data.reloc_offset) \
        !           510:            ) & ~0x3)
        !           511: #define SECTSTAR (reloc_data.input_section->output_offset)
        !           512: #define SECTSTART (reloc_data.input_section->output_offset)
        !           513: #define _SDA_BASE_ (reloc_data.sdata_begin_symbol_vma)
        !           514:
        !           515: #define none (0)
        !           516:
        !           517: #define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
        !           518:   case R_##TYPE: \
        !           519:     { \
        !           520:       bfd_vma bitsize ATTRIBUTE_UNUSED = BITSIZE; \
        !           521:       relocation = FORMULA  ; \
        !           522:       insn = RELOC_FUNCTION (insn, relocation); \
        !           523:     } \
        !           524:     break;
        !           525:
        !           526: static bfd_reloc_status_type
        !           527: arc_do_relocation (bfd_byte * contents, struct arc_relocation_data reloc_data)
        !           528: {
        !           529:   bfd_vma relocation = 0;
        !           530:   bfd_vma insn;
        !           531:   bfd_vma orig_insn ATTRIBUTE_UNUSED;
        !           532:
        !           533:   if (reloc_data.should_relocate == FALSE)
        !           534:     return bfd_reloc_notsupported;
        !           535:
        !           536:   switch (reloc_data.howto->size)
        !           537:     {
        !           538:       case 2:
        !           539:        insn = arc_bfd_get_32 (reloc_data.input_section->owner,
        !           540:                               contents + reloc_data.reloc_offset,
        !           541:                               reloc_data.input_section);
        !           542:        break;
        !           543:       case 1:
        !           544:       case 0:
        !           545:        insn = arc_bfd_get_16 (reloc_data.input_section->owner,
        !           546:                               contents + reloc_data.reloc_offset,
        !           547:                               reloc_data.input_section);
        !           548:        break;
        !           549:       default:
        !           550:        insn = 0;
        !           551:        BFD_ASSERT (0);
        !           552:        break;
        !           553:     }
        !           554:
        !           555:   orig_insn = insn;
        !           556:
        !           557:   switch (reloc_data.howto->type)
        !           558:     {
        !           559:       #include "elf/arc-reloc.def"
        !           560:
        !           561:       default:
        !           562:        BFD_ASSERT (0);
        !           563:        break;
        !           564:     }
        !           565:
        !           566:   /* Check for relocation overflow.  */
        !           567:   if (reloc_data.howto->complain_on_overflow != complain_overflow_dont)
        !           568:     {
        !           569:       bfd_reloc_status_type flag;
        !           570:       flag = bfd_check_overflow (reloc_data.howto->complain_on_overflow,
        !           571:                                 reloc_data.howto->bitsize,
        !           572:                                 reloc_data.howto->rightshift,
        !           573:                                 bfd_arch_bits_per_address (reloc_data.input_section->owner),
        !           574:                                 relocation);
        !           575:
        !           576: #undef DEBUG_ARC_RELOC
        !           577: #define DEBUG_ARC_RELOC(A) debug_arc_reloc (A)
        !           578:       if (flag != bfd_reloc_ok)
        !           579:        {
        !           580:          fprintf (stderr, "Relocation overflows !!!!\n");
        !           581:
        !           582:          DEBUG_ARC_RELOC (reloc_data);
        !           583:
        !           584:          fprintf (stderr,
        !           585:                  "Relocation value = signed -> %d, unsigned -> %u, hex -> (0x%08x)\n",
        !           586:                  (int) relocation,
        !           587:                  (unsigned int) relocation,
        !           588:                  (unsigned int) relocation);
        !           589:          return flag;
        !           590:        }
        !           591:     }
        !           592: #undef DEBUG_ARC_RELOC
        !           593: #define DEBUG_ARC_RELOC(A)
        !           594:
        !           595:   switch (reloc_data.howto->size)
        !           596:     {
        !           597:       case 2:
        !           598:        arc_bfd_put_32 (reloc_data.input_section->owner, insn,
        !           599:                       contents + reloc_data.reloc_offset,
        !           600:                       reloc_data.input_section);
        !           601:        break;
        !           602:       case 1:
        !           603:       case 0:
        !           604:        arc_bfd_put_16 (reloc_data.input_section->owner, insn,
        !           605:                       contents + reloc_data.reloc_offset,
        !           606:                       reloc_data.input_section);
        !           607:        break;
        !           608:       default:
        !           609:        ARC_DEBUG ("size = %d\n", reloc_data.howto->size);
        !           610:        BFD_ASSERT (0);
        !           611:        break;
        !           612:     }
        !           613:
        !           614:   return bfd_reloc_ok;
        !           615: }
        !           616: #undef S
        !           617: #undef A
        !           618: #undef B
        !           619: #undef G
        !           620: #undef GOT
        !           621: #undef L
        !           622: #undef MES
        !           623: #undef P
        !           624: #undef SECTSTAR
        !           625: #undef SECTSTART
        !           626: #undef _SDA_BASE_
        !           627: #undef none
        !           628:
        !           629: #undef ARC_RELOC_HOWTO
        !           630:
        !           631: static bfd_vma *
        !           632: arc_get_local_got_offsets (bfd * abfd)
        !           633: {
        !           634:   static bfd_vma *local_got_offsets = NULL;
        !           635:
        !           636:   if (local_got_offsets == NULL)
        !           637:     {
        !           638:       size_t      size;
        !           639:       unsigned int i;
        !           640:       Elf_Internal_Shdr *symtab_hdr = &((elf_tdata (abfd))->symtab_hdr);
        !           641:
        !           642:       size = symtab_hdr->sh_info * sizeof (bfd_vma);
        !           643:       local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
        !           644:       if (local_got_offsets == NULL)
        !           645:        return FALSE;
        !           646:       elf_local_got_offsets (abfd) = local_got_offsets;
        !           647:       for (i = 0; i < symtab_hdr->sh_info; i++)
        !           648:        local_got_offsets[i] = (bfd_vma) - 1;
        !           649:     }
        !           650:
        !           651:   return local_got_offsets;
        !           652: }
        !           653:
        !           654:
        !           655: /* Relocate an arc ELF section.
        !           656:    Function : elf_arc_relocate_section
        !           657:    Brief    : Relocate an arc section, by handling all the relocations
        !           658:             appearing in that section.
        !           659:    Args     : output_bfd    : The bfd being written to.
        !           660:              info          : Link information.
        !           661:              input_bfd     : The input bfd.
        !           662:              input_section : The section being relocated.
        !           663:              contents      : contents of the section being relocated.
        !           664:              relocs        : List of relocations in the section.
        !           665:              local_syms    : is a pointer to the swapped in local symbols.
        !           666:              local_section : is an array giving the section in the input file
        !           667:                              corresponding to the st_shndx field of each
        !           668:                              local symbol.  */
        !           669: static bfd_boolean
        !           670: elf_arc_relocate_section (bfd *                   output_bfd,
        !           671:                          struct bfd_link_info *  info,
        !           672:                          bfd *                   input_bfd,
        !           673:                          asection *              input_section,
        !           674:                          bfd_byte *              contents,
        !           675:                          Elf_Internal_Rela *     relocs,
        !           676:                          Elf_Internal_Sym *      local_syms,
        !           677:                          asection **             local_sections)
        !           678: {
        !           679:   Elf_Internal_Shdr *           symtab_hdr;
        !           680:   struct elf_link_hash_entry ** sym_hashes;
        !           681:   bfd_vma *                     local_got_offsets;
        !           682:   Elf_Internal_Rela *           rel;
        !           683:   Elf_Internal_Rela *           relend;
        !           684:
        !           685:   symtab_hdr = &((elf_tdata (input_bfd))->symtab_hdr);
        !           686:   sym_hashes = elf_sym_hashes (input_bfd);
        !           687:
        !           688:   rel = relocs;
        !           689:   relend = relocs + input_section->reloc_count;
        !           690:   for (; rel < relend; rel++)
        !           691:     {
        !           692:       enum elf_arc_reloc_type       r_type;
        !           693:       reloc_howto_type *            howto;
        !           694:       unsigned long                 r_symndx;
        !           695:       struct elf_link_hash_entry *  h;
        !           696:       Elf_Internal_Sym *            sym;
        !           697:       asection *                    sec;
        !           698:
        !           699:       struct arc_relocation_data reloc_data =
        !           700:       {
        !           701:        .reloc_offset = 0,      /* bfd_vma reloc_offset; */
        !           702:        .reloc_addend = 0,      /* bfd_vma reloc_addend; */
        !           703:        .got_offset_value = 0,  /* bfd_vma got_offset_value; */
        !           704:        .sym_value = 0,         /* bfd_vma sym_value; */
        !           705:        .sym_section = NULL,    /* asection *sym_section; */
        !           706:        .howto = NULL,          /* reloc_howto_type *howto; */
        !           707:        .input_section = NULL,  /* asection *input_section; */
        !           708:        .sdata_begin_symbol_vma = 0,    /* bfd_vma sdata_begin_symbol_vma; */
        !           709:        .sdata_begin_symbol_vma_set = FALSE,    /* bfd_vma sdata_begin_symbol_vma_set; */
        !           710:        .got_symbol_vma = 0,    /* bfd_vma got_symbol_vma; */
        !           711:        .should_relocate = FALSE        /* bfd_boolean should_relocate; */
        !           712:       };
        !           713:
        !           714:       struct elf_link_hash_entry *h2;
        !           715:
        !           716:       h2 = elf_link_hash_lookup (elf_hash_table (info), "__SDATA_BEGIN__",
        !           717:                                 FALSE, FALSE, TRUE);
        !           718:
        !           719:       if (reloc_data.sdata_begin_symbol_vma_set == FALSE
        !           720:            && h2 != NULL && h2->root.type != bfd_link_hash_undefined)
        !           721:        {
        !           722:          reloc_data.sdata_begin_symbol_vma =
        !           723:            (h2->root.u.def.value +
        !           724:             h2->root.u.def.section->output_section->vma);
        !           725:          reloc_data.sdata_begin_symbol_vma_set = TRUE;
        !           726:        }
        !           727:
        !           728:       h2 = elf_link_hash_lookup (elf_hash_table (info),
        !           729:                                 "_GLOBAL_OFFSET_TABLE_", FALSE, FALSE,
        !           730:                                 TRUE);
        !           731:       if (h2 != NULL && h2->root.type != bfd_link_hash_undefined)
        !           732:        {
        !           733:          reloc_data.got_symbol_vma =
        !           734:              (h2->root.u.def.value +
        !           735:               h2->root.u.def.section->output_section->vma);
        !           736:        }
        !           737:
        !           738:       r_type = ELF32_R_TYPE (rel->r_info);
        !           739:
        !           740:       if (r_type >= (int) R_ARC_max)
        !           741:        {
        !           742:          bfd_set_error (bfd_error_bad_value);
        !           743:          return FALSE;
        !           744:        }
        !           745:       howto = &elf_arc_howto_table[r_type];
        !           746:
        !           747:       reloc_data.input_section = input_section;
        !           748:       reloc_data.howto = howto;
        !           749:       reloc_data.reloc_offset = rel->r_offset;
        !           750:       reloc_data.reloc_addend = rel->r_addend;
        !           751:
        !           752:       r_symndx = ELF32_R_SYM (rel->r_info);
        !           753:
        !           754:       /* This is a final link.  */
        !           755:       h = NULL;
        !           756:       sym = NULL;
        !           757:       sec = NULL;
        !           758:
        !           759:       if (r_symndx < symtab_hdr->sh_info) /* A local symbol.  */
        !           760:        {
        !           761:          sym = local_syms + r_symndx;
        !           762:          sec = local_sections[r_symndx];
        !           763:
        !           764:          reloc_data.sym_value = sym->st_value;
        !           765:          reloc_data.sym_section = sec;
        !           766:
        !           767:            if (is_reloc_for_GOT (reloc_data.howto))
        !           768:              {
        !           769:                local_got_offsets = arc_get_local_got_offsets (output_bfd);
        !           770:                reloc_data.got_offset_value = local_got_offsets[r_symndx];
        !           771:              }
        !           772:
        !           773:          reloc_data.should_relocate = TRUE;
        !           774:        }
        !           775:       else /* Global symbol.  */
        !           776:        {
        !           777:          /* Get the symbol's entry in the symtab.  */
        !           778:          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
        !           779:
        !           780:          while (h->root.type == bfd_link_hash_indirect
        !           781:                 || h->root.type == bfd_link_hash_warning)
        !           782:            h = (struct elf_link_hash_entry *) h->root.u.i.link;
        !           783:
        !           784:          BFD_ASSERT ((h->dynindx == -1) >= (h->forced_local != 0));
        !           785:          /* If we have encountered a definition for this symbol.  */
        !           786:          if (h->root.type == bfd_link_hash_defined
        !           787:              || h->root.type == bfd_link_hash_defweak)
        !           788:            {
        !           789:              reloc_data.sym_value = h->root.u.def.value;
        !           790:              reloc_data.sym_section = h->root.u.def.section;
        !           791:
        !           792:              reloc_data.should_relocate = TRUE;
        !           793:
        !           794:              if (is_reloc_for_GOT (howto))
        !           795:                {
        !           796:                  struct dynamic_sections ds =
        !           797:                  arc_create_dynamic_sections (output_bfd, info);
        !           798:
        !           799:                  /* TODO: Change it to use arc_do_relocation with ARC_32
        !           800:                     reloc.  */
        !           801:                  bfd_vma relocation =
        !           802:                    reloc_data.sym_value + reloc_data.reloc_addend
        !           803:                    + reloc_data.sym_section->output_offset
        !           804:                    + reloc_data.sym_section->output_section->vma;
        !           805:
        !           806:                  bfd_put_32 (output_bfd, relocation, ds.sgot->contents + h->got.offset);
        !           807:
        !           808:                }
        !           809:            }
        !           810:          else if (h->root.type == bfd_link_hash_undefweak)
        !           811:            {
        !           812:              /* Is weak symbol and has no definition.  */
        !           813:              continue;
        !           814:            }
        !           815:          else
        !           816:            {
        !           817:              if (is_reloc_for_GOT (howto))
        !           818:                {
        !           819:                  struct dynamic_sections ds =
        !           820:                      arc_create_dynamic_sections (output_bfd, info);
        !           821:
        !           822:                  reloc_data.sym_value = h->root.u.def.value;
        !           823:                  reloc_data.sym_section = ds.sgot;
        !           824:
        !           825:                  reloc_data.should_relocate = TRUE;
        !           826:                }
        !           827:              else if (is_reloc_for_PLT (howto))
        !           828:                {
        !           829:                  struct dynamic_sections ds =
        !           830:                    arc_create_dynamic_sections (output_bfd, info);
        !           831:
        !           832:                  reloc_data.sym_value = h->plt.offset;
        !           833:                  reloc_data.sym_section = ds.splt;
        !           834:
        !           835:                  reloc_data.should_relocate = TRUE;
        !           836:                }
        !           837:              else if (!(*info->callbacks->undefined_symbol)
        !           838:                       (info, h->root.root.string, input_bfd, input_section,
        !           839:                        rel->r_offset,!bfd_link_pic (info)))
        !           840:                {
        !           841:                  return FALSE;
        !           842:                }
        !           843:            }
        !           844:
        !           845:          reloc_data.got_offset_value = h->got.offset;
        !           846:        }
        !           847:
        !           848:       if (is_reloc_SDA_relative (howto) && reloc_data.sdata_begin_symbol_vma_set == FALSE)
        !           849:        {
        !           850:          (*_bfd_error_handler)
        !           851:              ("Error: Linker symbol __SDATA_BEGIN__ not found");
        !           852:          bfd_set_error (bfd_error_bad_value);
        !           853:          return FALSE;
        !           854:        }
        !           855:
        !           856:       DEBUG_ARC_RELOC (reloc_data);
        !           857:       if (arc_do_relocation (contents, reloc_data) != bfd_reloc_ok)
        !           858:        return FALSE;
        !           859:     }
        !           860:
        !           861:   return TRUE;
        !           862: }
        !           863:
        !           864: static struct dynamic_sections
        !           865: arc_create_dynamic_sections (bfd * abfd, struct bfd_link_info *info)
        !           866: {
        !           867:   static bfd * dynobj = NULL;
        !           868:   struct dynamic_sections ds =
        !           869:   {
        !           870:        .initialized = FALSE,
        !           871:        .sgot = NULL,
        !           872:        .srelgot = NULL,
        !           873:        .sgotplt = NULL,
        !           874:        .sdyn = NULL,
        !           875:        .splt = NULL,
        !           876:        .srelplt = NULL
        !           877:   };
        !           878:
        !           879:   if (dynobj == NULL)
        !           880:     {
        !           881:       elf_hash_table (info)->dynobj = dynobj = abfd;
        !           882:       if (!_bfd_elf_create_got_section (dynobj, info))
        !           883:        return ds;
        !           884:     }
        !           885:   else
        !           886:     dynobj = (elf_hash_table (info))->dynobj;
        !           887:
        !           888:   ds.sgot = bfd_get_section_by_name (dynobj, ".got");
        !           889:
        !           890:   ds.srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
        !           891:   if (ds.srelgot == NULL)
        !           892:     {
        !           893:       ds.srelgot = bfd_make_section_with_flags (dynobj, ".rela.got",
        !           894:                                         SEC_ALLOC
        !           895:                                         | SEC_LOAD
        !           896:                                         | SEC_HAS_CONTENTS
        !           897:                                         | SEC_IN_MEMORY
        !           898:                                         | SEC_LINKER_CREATED
        !           899:                                         | SEC_READONLY);
        !           900:       if (ds.srelgot == NULL
        !           901:          || !bfd_set_section_alignment (dynobj, ds.srelgot, 2))
        !           902:        return ds;
        !           903:     }
        !           904:
        !           905:   ds.sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
        !           906:
        !           907:   ds.sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
        !           908:   ds.splt = bfd_get_section_by_name (dynobj, ".plt");
        !           909:   ds.srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
        !           910:
        !           911:   ds.initialized = TRUE;
        !           912:
        !           913:   return ds;
        !           914: }
        !           915:
        !           916: #define ADD_SYMBOL_REF_SEC_AND_RELOC(SECNAME, COND_FOR_RELOC, H) \
        !           917:   ds.s##SECNAME->size; \
        !           918:   { \
        !           919:     if (COND_FOR_RELOC) ds.srel##SECNAME->size += sizeof (Elf32_External_Rela); \
        !           920:     if (H)  \
        !           921:       if (h->dynindx == -1 && !h->forced_local) \
        !           922:        if (! bfd_elf_link_record_dynamic_symbol (info, H)) \
        !           923:          return FALSE; \
        !           924:     ds.s##SECNAME->size += 4; \
        !           925:   }
        !           926:
        !           927: static bfd_boolean
        !           928: elf_arc_check_relocs (bfd *                      abfd,
        !           929:                      struct bfd_link_info *     info,
        !           930:                      asection *                 sec,
        !           931:                      const Elf_Internal_Rela *  relocs)
        !           932: {
        !           933:   Elf_Internal_Shdr *            symtab_hdr;
        !           934:   struct elf_link_hash_entry **  sym_hashes;
        !           935:   bfd_vma *                      local_got_offsets;
        !           936:   const Elf_Internal_Rela *      rel;
        !           937:   const Elf_Internal_Rela *      rel_end;
        !           938:   bfd *                          dynobj ATTRIBUTE_UNUSED;
        !           939:
        !           940:   dynobj = (elf_hash_table (info))->dynobj;
        !           941:   symtab_hdr = &((elf_tdata (abfd))->symtab_hdr);
        !           942:   sym_hashes = elf_sym_hashes (abfd);
        !           943:   local_got_offsets = arc_get_local_got_offsets (abfd);
        !           944:
        !           945:   struct dynamic_sections ds = arc_create_dynamic_sections (abfd, info);
        !           946:
        !           947:   rel_end = relocs + sec->reloc_count;
        !           948:   for (rel = relocs; rel < rel_end; rel++)
        !           949:     {
        !           950:       enum elf_arc_reloc_type r_type;
        !           951:       reloc_howto_type *howto;
        !           952:       unsigned long   r_symndx;
        !           953:       struct elf_link_hash_entry *h;
        !           954:
        !           955:       r_type = ELF32_R_TYPE (rel->r_info);
        !           956:
        !           957:       if (r_type >= (int) R_ARC_max)
        !           958:        {
        !           959:          bfd_set_error (bfd_error_bad_value);
        !           960:          return FALSE;
        !           961:        }
        !           962:       howto = &elf_arc_howto_table[r_type];
        !           963:
        !           964:       /* Load symbol information.  */
        !           965:       r_symndx = ELF32_R_SYM (rel->r_info);
        !           966:       if (r_symndx < symtab_hdr->sh_info) /* Is a local symbol.  */
        !           967:        h = NULL;
        !           968:       else /* Global one.  */
        !           969:        h = sym_hashes[r_symndx - symtab_hdr->sh_info];
        !           970:
        !           971:       if (is_reloc_for_PLT (howto) == TRUE)
        !           972:        {
        !           973:          if (h == NULL)
        !           974:            continue;
        !           975:          else
        !           976:            h->needs_plt = 1;
        !           977:        }
        !           978:
        !           979:       if (is_reloc_for_GOT (howto) == TRUE)
        !           980:        {
        !           981:          if (h == NULL)
        !           982:            {
        !           983:              /* Local symbol.  */
        !           984:              local_got_offsets[r_symndx] =
        !           985:                ADD_SYMBOL_REF_SEC_AND_RELOC (got, bfd_link_pic (info), NULL);
        !           986:            }
        !           987:          else
        !           988:            {
        !           989:              /* Global symbol.  */
        !           990:              h = sym_hashes[r_symndx - symtab_hdr->sh_info];
        !           991:              h->got.offset =
        !           992:                ADD_SYMBOL_REF_SEC_AND_RELOC (got, TRUE, h);
        !           993:            }
        !           994:        }
        !           995:     }
        !           996:
        !           997:   return TRUE;
        !           998: }
        !           999:
        !          1000: #define ELF_DYNAMIC_INTERPRETER  "/sbin/ld-uClibc.so"
        !          1001:
        !          1002: /* Size of one plt entry in bytes.  */
        !          1003: #define PLT_ENTRY_SIZE 12
        !          1004: #define PLT_ENTRY_SIZE_V2 16
        !          1005:
        !          1006: /* Instructions appear in memory as a sequence of half-words (16 bit);
        !          1007:    individual half-words are represented on the target in target byte order.
        !          1008:    We use 'unsigned short' on the host to represent the PLT templates,
        !          1009:    and translate to target byte order as we copy to the target.  */
        !          1010: typedef unsigned short insn_hword;
        !          1011:
        !          1012:
        !          1013: /* TODO: Make this PLT entry code be in a separate object file.  */
        !          1014: /* TODO: This is a linker BTW, we should be able to link. :)  */
        !          1015:
        !          1016: /* The zeroth entry in the absolute plt entry.  */
        !          1017: static const insn_hword elf_arc_abs_plt0_entry[2 * PLT_ENTRY_SIZE / 2] =
        !          1018: {
        !          1019:   0x1600,      /* ld %r11, [0] */
        !          1020:   0x700b,
        !          1021:   0x0000,
        !          1022:   0x0000,
        !          1023:   0x1600,      /* ld %r10, [0] */
        !          1024:   0x700a,      /* */
        !          1025:   0,
        !          1026:   0,
        !          1027:   0x2020,      /* j [%r10] */
        !          1028:   0x0280,      /* ---"---- */
        !          1029:   0x0000,      /* pad */
        !          1030:   0x0000       /* pad */
        !          1031: };
        !          1032:
        !          1033: /* Contents of the subsequent entries in the absolute plt.  */
        !          1034: static const insn_hword elf_arc_abs_pltn_entry[PLT_ENTRY_SIZE / 2] =
        !          1035: {
        !          1036:   0x2730,      /* ld %r12, [%pc,func@gotpc] */
        !          1037:   0x7f8c,      /* ------ " " -------------- */
        !          1038:   0x0000,      /* ------ " " -------------- */
        !          1039:   0x0000,      /* ------ " " -------------- */
        !          1040:   0x7c20,      /* j_s.d [%r12] */
        !          1041:   0x74ef       /* mov_s %r12, %pcl */
        !          1042: };
        !          1043:
        !          1044: /* The zeroth entry in the absolute plt entry for ARCv2.  */
        !          1045: static const insn_hword elf_arcV2_abs_plt0_entry[2 * PLT_ENTRY_SIZE_V2 / 2] =
        !          1046: {
        !          1047:   0x1600, 0x700b, 0, 0,   /* ld %r11, [0] */
        !          1048:   0x1600, 0x700a, 0, 0,   /* ld %r10, [0] */
        !          1049:   0x2020, 0x0280,        /* j [%r10] */
        !          1050:   0x0000, 0x0000,        /* -> RELOCATED TO ABS ADDRESS OF GOT <- */
        !          1051:   0x0000,                /* pad */
        !          1052:   0x0000,                /* pad */
        !          1053:   0x0000,                /* pad */
        !          1054:   0x0000                 /* pad */
        !          1055: };
        !          1056:
        !          1057: /* Contents of the subsequent entries in the absolute plt for ARCv2.  */
        !          1058: static const insn_hword elf_arcV2_abs_pltn_entry[PLT_ENTRY_SIZE_V2 / 2] =
        !          1059: {
        !          1060:   0x2730,      /* ld %r12, [%pcl,func@gotpc] */
        !          1061:   0x7f8c,      /* ------ " " -------------- */
        !          1062:   0x0000,      /* ------ " " -------------- */
        !          1063:   0x0000,      /* ------ " " -------------- */
        !          1064:   0x2021,      /* j.d [%r12] */
        !          1065:   0x0300,      /* ------ " " -------------- */
        !          1066:   0x240a,      /* mov %r12, %pcl */
        !          1067:   0x1fc0       /* ------ " " -------------- */
        !          1068: };
        !          1069:
        !          1070: /* The zeroth entry in the pic plt entry.  */
        !          1071: static const insn_hword elf_arc_pic_plt0_entry[2 * PLT_ENTRY_SIZE / 2] =
        !          1072: {
        !          1073:   0x2730,      /* ld %r11, [pcl,0] : 0 to be replaced by
        !          1074:                   _DYNAMIC@GOTPC+4 */
        !          1075:   0x7f8b,
        !          1076:   0x0000,
        !          1077:   0x0000,
        !          1078:   0x2730,      /* ld %r10, [pcl,0] : 0 to be replaced by
        !          1079:                   -DYNAMIC@GOTPC+8 */
        !          1080:   0x7f8a,      /* */
        !          1081:   0,
        !          1082:   0,
        !          1083:   0x2020,      /* j [%r10] */
        !          1084:   0x0280,      /* ---"---- */
        !          1085:   0x0000,      /* pad */
        !          1086:   0x0000       /* pad */
        !          1087: };
        !          1088:
        !          1089: /* Contents of the subsequent entries in the pic plt.  */
        !          1090: static const insn_hword elf_arc_pic_pltn_entry[PLT_ENTRY_SIZE / 2] =
        !          1091: {
        !          1092:   0x2730,      /* ld %r12, [%pc,func@got] */
        !          1093:   0x7f8c,      /* ------ " " -------------- */
        !          1094:   0x0000,      /* ------ " " -------------- */
        !          1095:   0x0000,      /* ------ " " -------------- */
        !          1096:   0x7c20,      /* j_s.d [%r12] */
        !          1097:   0x74ef,      /* mov_s %r12, %pcl */
        !          1098: };
        !          1099:
        !          1100: /* The zeroth entry in the pic plt entry for ARCv2.  */
        !          1101: static const insn_hword elf_arcV2_pic_plt0_entry[2 * PLT_ENTRY_SIZE_V2 / 2] =
        !          1102: {
        !          1103:   0x2730,      /* ld %r11, [pcl,0] : 0 to be replaced by
        !          1104:                   _DYNAMIC@GOTPC+4 */
        !          1105:   0x7f8b,
        !          1106:   0x0000,
        !          1107:   0x0000,
        !          1108:   0x2730,      /* ld %r10, [pcl,0] : 0 to be replaced by
        !          1109:                   -DYNAMIC@GOTPC+8 */
        !          1110:   0x7f8a,      /* */
        !          1111:   0,
        !          1112:   0,
        !          1113:   0x2020,      /* j [%r10] */
        !          1114:   0x0280,      /* ---"---- */
        !          1115:   0x0000,      /* pad */
        !          1116:   0x0000,      /* pad */
        !          1117:   0x0000,      /* pad */
        !          1118:   0x0000,      /* pad */
        !          1119:   0x0000,      /* pad */
        !          1120:   0x0000       /* pad */
        !          1121: };
        !          1122:
        !          1123: #define elf_arcV2_pic_PLT0_ENTRY_SIZE (2 * PLT_ENTRY_SIZE_V2/2)
        !          1124:
        !          1125: /* Contents of the subsequent entries in the pic plt for ARCv2.  */
        !          1126: static const insn_hword elf_arcV2_pic_pltn_entry[PLT_ENTRY_SIZE_V2 / 2] =
        !          1127: {
        !          1128:   0x2730,      /* ld %r12, [%pc,func@got] */
        !          1129:   0x7f8c,      /* ------ " " -------------- */
        !          1130:   0x0000,      /* ------ " " -------------- */
        !          1131:   0x0000,      /* ------ " " -------------- */
        !          1132:   0x2021,      /* j.d [%r12] */
        !          1133:   0x0300,      /* ------ " " -------------- */
        !          1134:   0x240a,      /* mov %r12, %pcl */
        !          1135:   0x1fc0       /* ------ " " -------------- */
        !          1136: };
        !          1137:
        !          1138: #define elf_arcV2_pic_PLTN_ENTRY_SIZE (PLT_ENTRY_SIZE_V2/2)
        !          1139:
        !          1140: enum plt_reloc_symbol
        !          1141: {
        !          1142:   LAST_RELOC = 0,
        !          1143:
        !          1144:   SGOT = 1,
        !          1145:
        !          1146:   RELATIVE = (1 << 8),
        !          1147:   MIDDLE_ENDIAN = (1 << 9)
        !          1148: };
        !          1149:
        !          1150: #define IS_RELATIVE(S) ((S & RELATIVE) != 0)
        !          1151: #define IS_MIDDLE_ENDIAN(S) ((S & MIDDLE_ENDIAN) != 0)
        !          1152: #define SYM_ONLY(S) (S & 0xFF)
        !          1153:
        !          1154: struct plt_reloc
        !          1155: {
        !          1156:   bfd_vma        offset;
        !          1157:   bfd_vma        size;
        !          1158:   bfd_vma        mask;
        !          1159:   enum plt_reloc_symbol symbol;
        !          1160:   bfd_vma        addend;
        !          1161: };
        !          1162:
        !          1163: struct plt_version_t
        !          1164: {
        !          1165:   const insn_hword *    entry;
        !          1166:   const bfd_vma                entry_size;
        !          1167:   const insn_hword *    elem;
        !          1168:   const bfd_vma                elem_size;
        !          1169:
        !          1170:   struct plt_reloc entry_relocs[5];
        !          1171:   struct plt_reloc elem_relocs[5];
        !          1172: };
        !          1173:
        !          1174:
        !          1175: #define PLT_DATA(NAME, ...) \
        !          1176:   .entry = NAME##_plt0_entry, \
        !          1177:   .entry_size = NAME##_PLT0_ENTRY_SIZE, \
        !          1178:   .elem = NAME##_pltn_entry, \
        !          1179:   .elem_size = NAME##_PLTN_ENTRY_SIZE
        !          1180:
        !          1181: struct plt_version_t plt_versions[] =
        !          1182: {
        !          1183:   {
        !          1184:     PLT_DATA (elf_arcV2_pic),
        !          1185:     .entry_relocs =
        !          1186:     {
        !          1187:       {4, 32, 0xFFFFFFFF, SGOT | RELATIVE | MIDDLE_ENDIAN, 4},
        !          1188:       {12, 32, 0xFFFFFFFF, SGOT | RELATIVE | MIDDLE_ENDIAN, 8},
        !          1189:       {20, 32, 0xFFFFFFFF, SGOT, 0},
        !          1190:       {0, 0, 0, LAST_RELOC, 0}
        !          1191:     },
        !          1192:     .elem_relocs =
        !          1193:     {
        !          1194:       {4, 32, 0xFFFFFFFF, SGOT, 0},
        !          1195:       {0, 0, 0, LAST_RELOC, 0}
        !          1196:     }
        !          1197:   }
        !          1198: };
        !          1199: #undef PLT_DATA
        !          1200:
        !          1201: static struct plt_version_t *
        !          1202: arc_get_plt_version (void)
        !          1203: {
        !          1204:   return &(plt_versions[0]);
        !          1205: }
        !          1206:
        !          1207: static bfd_vma
        !          1208: add_symbol_to_plt (struct bfd_link_info *info)
        !          1209: {
        !          1210:   bfd *dynobj = (elf_hash_table (info))->dynobj;
        !          1211:   struct dynamic_sections ds = arc_create_dynamic_sections (dynobj, info);
        !          1212:   bfd_vma ret;
        !          1213:
        !          1214:   /* If this is the first .plt entry, make room for the special first entry.  */
        !          1215:   if (ds.splt->size == 0)
        !          1216:     ds.splt->size += 2 *
        !          1217:                     (bfd_get_mach (dynobj) == bfd_mach_arc_arcv2
        !          1218:                      ? PLT_ENTRY_SIZE_V2 : PLT_ENTRY_SIZE);
        !          1219:
        !          1220:   ret = ds.splt->size;
        !          1221:
        !          1222:   ds.splt->size += (bfd_get_mach (dynobj) == bfd_mach_arc_arcv2
        !          1223:                    ? PLT_ENTRY_SIZE_V2
        !          1224:                    : PLT_ENTRY_SIZE
        !          1225:                   );
        !          1226:   ds.sgotplt->size += 4;
        !          1227:   ds.srelplt->size += sizeof (Elf32_External_Rela);
        !          1228:
        !          1229:   return ret;
        !          1230: }
        !          1231:
        !          1232: #define PLT_DO_RELOCS_FOR_ENTRY(DS, RELOCS) \
        !          1233:   plt_do_relocs_for_symbol (DS, RELOCS, 0, 0)
        !          1234:
        !          1235: static void
        !          1236: plt_do_relocs_for_symbol (struct dynamic_sections *ds,
        !          1237:                          struct plt_reloc *reloc,
        !          1238:                          bfd_vma plt_offset,
        !          1239:                          bfd_vma symbol_got_offset)
        !          1240: {
        !          1241:   while (SYM_ONLY (reloc->symbol) != LAST_RELOC)
        !          1242:     {
        !          1243:       bfd_vma relocation = 0;
        !          1244:
        !          1245:       switch (SYM_ONLY (reloc->symbol))
        !          1246:        {
        !          1247:          case SGOT:
        !          1248:                relocation =
        !          1249:                    ds->sgotplt->output_section->vma +
        !          1250:                    ds->sgotplt->output_offset + symbol_got_offset;
        !          1251:                break;
        !          1252:        }
        !          1253:       relocation += reloc->addend;
        !          1254:
        !          1255:       relocation -= (IS_RELATIVE (reloc->symbol))
        !          1256:          ? ds->splt->output_section->vma + ds->splt->output_offset +
        !          1257:          plt_offset + reloc->offset : 0;
        !          1258:
        !          1259:       if (IS_MIDDLE_ENDIAN (reloc->symbol))
        !          1260:        {
        !          1261:          relocation =
        !          1262:              ((relocation & 0xffff0000) >> 16) |
        !          1263:              ((relocation & 0xffff) << 16);
        !          1264:        }
        !          1265:
        !          1266:       switch (reloc->size)
        !          1267:        {
        !          1268:          case 32:
        !          1269:            bfd_put_32 (ds->splt->output_section->owner,
        !          1270:                        relocation,
        !          1271:                        ds->splt->contents + plt_offset + reloc->offset);
        !          1272:            break;
        !          1273:        }
        !          1274:
        !          1275:       reloc = &(reloc[1]);     /* Jump to next relocation.  */
        !          1276:     }
        !          1277: }
        !          1278:
        !          1279: static void
        !          1280: relocate_plt_for_symbol (struct bfd_link_info *info,
        !          1281:                         struct elf_link_hash_entry *h)
        !          1282: {
        !          1283:   bfd * dynobj = elf_hash_table (info)->dynobj;
        !          1284:   struct plt_version_t *plt_data = arc_get_plt_version ();
        !          1285:   struct dynamic_sections ds = arc_create_dynamic_sections (dynobj, info);
        !          1286:
        !          1287:   bfd_vma plt_index = h->plt.offset / plt_data->elem_size;
        !          1288:   bfd_vma got_offset = (plt_index + 3) * 4;
        !          1289:
        !          1290:   memcpy (ds.splt->contents + h->plt.offset, plt_data->elem,
        !          1291:          plt_data->elem_size * sizeof (insn_hword));
        !          1292:   plt_do_relocs_for_symbol (&ds, plt_data->elem_relocs, h->plt.offset,
        !          1293:                            got_offset);
        !          1294: }
        !          1295:
        !          1296: static void
        !          1297: relocate_plt_for_entry (struct bfd_link_info *info)
        !          1298: {
        !          1299:   bfd * dynobj = (elf_hash_table (info))->dynobj;
        !          1300:   struct plt_version_t *plt_data = arc_get_plt_version ();
        !          1301:   struct dynamic_sections ds = arc_create_dynamic_sections (dynobj, info);
        !          1302:
        !          1303:   memcpy (ds.splt->contents, plt_data->entry,
        !          1304:          plt_data->entry_size * sizeof (insn_hword));
        !          1305:   PLT_DO_RELOCS_FOR_ENTRY (&ds, plt_data->entry_relocs);
        !          1306: }
        !          1307:
        !          1308:
        !          1309: /* Desc : Adjust a symbol defined by a dynamic object and referenced by a
        !          1310:    regular object.  The current definition is in some section of the
        !          1311:    dynamic object, but we're not including those sections.  We have to
        !          1312:    change the definition to something the rest of the link can
        !          1313:    understand.  */
        !          1314:
        !          1315: static bfd_boolean
        !          1316: elf_arc_adjust_dynamic_symbol (struct bfd_link_info *info,
        !          1317:                              struct elf_link_hash_entry *h)
        !          1318: {
        !          1319:   bfd *dynobj = (elf_hash_table (info))->dynobj;
        !          1320:   struct dynamic_sections ds = arc_create_dynamic_sections (dynobj, info);
        !          1321:
        !          1322:   if (h->needs_plt == 1)
        !          1323:     {
        !          1324:       if (!bfd_link_pic (info) && !h->def_dynamic && !h->ref_dynamic)
        !          1325:        {
        !          1326:          /* This case can occur if we saw a PLT32 reloc in an input
        !          1327:             file, but the symbol was never referred to by a dynamic
        !          1328:             object.  In such a case, we don't actually need to build
        !          1329:             a procedure linkage table, and we can just do a PC32
        !          1330:             reloc instead.  */
        !          1331:          BFD_ASSERT (h->needs_plt);
        !          1332:          return TRUE;
        !          1333:        }
        !          1334:
        !          1335:       /* Make sure this symbol is output as a dynamic symbol.  */
        !          1336:       if (h->dynindx == -1 && !h->forced_local
        !          1337:          && !bfd_elf_link_record_dynamic_symbol (info, h))
        !          1338:        return FALSE;
        !          1339:
        !          1340:       if (bfd_link_pic (info) || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
        !          1341:        {
        !          1342:          bfd_vma loc = add_symbol_to_plt (info);
        !          1343:
        !          1344:          if (!bfd_link_pic (info) && !h->def_regular)
        !          1345:            {
        !          1346:              h->root.u.def.section = ds.splt;
        !          1347:              h->root.u.def.value = loc;
        !          1348:            }
        !          1349:          h->plt.offset = loc;
        !          1350:        }
        !          1351:     }
        !          1352:   else
        !          1353:     {
        !          1354:       h->plt.offset = (bfd_vma) - 1;
        !          1355:       h->needs_plt = 0;
        !          1356:     }
        !          1357:
        !          1358:   return TRUE;
        !          1359: }
        !          1360:
        !          1361: #define ADD_RELA(BFD, SECTION, OFFSET, SYM_IDX, TYPE, ADDEND) \
        !          1362: {\
        !          1363:   struct dynamic_sections ds = arc_create_dynamic_sections (output_bfd, info); \
        !          1364:   bfd_byte * rloc = ds.srel##SECTION->contents + \
        !          1365:     ((ds.srel##SECTION->reloc_count++) * sizeof (Elf32_External_Rela)); \
        !          1366:   Elf_Internal_Rela rel; \
        !          1367:   bfd_put_32 (output_bfd, (bfd_vma) 0, ds.s##SECTION->contents + OFFSET); \
        !          1368:   rel.r_addend = ADDEND; \
        !          1369:   rel.r_offset = (ds.s##SECTION)->output_section->vma + (ds.s##SECTION)->output_offset + OFFSET; \
        !          1370:   rel.r_info = ELF32_R_INFO (SYM_IDX, TYPE); \
        !          1371:   bfd_elf32_swap_reloca_out (BFD, &rel, rloc); \
        !          1372: }
        !          1373:
        !          1374: /* Function :  elf_arc_finish_dynamic_symbol
        !          1375:    Brief    :  Finish up dynamic symbol handling.  We set the
        !          1376:             contents of various dynamic sections here.
        !          1377:    Args     :  output_bfd :
        !          1378:               info       :
        !          1379:               h          :
        !          1380:               sym        :
        !          1381:    Returns  : True/False as the return status.  */
        !          1382: static bfd_boolean
        !          1383: elf_arc_finish_dynamic_symbol (bfd * output_bfd,
        !          1384:                               struct bfd_link_info *info,
        !          1385:                               struct elf_link_hash_entry *h,
        !          1386:                               Elf_Internal_Sym * sym)
        !          1387: {
        !          1388:   if (h->plt.offset != (bfd_vma) - 1)
        !          1389:     relocate_plt_for_symbol (info, h);
        !          1390:
        !          1391:   if (h->got.offset != (bfd_vma) - 1)
        !          1392:     {
        !          1393:       if (bfd_link_pic (info) && (info->symbolic || h->dynindx == -1)
        !          1394:          && h->def_regular)
        !          1395:        {
        !          1396:          ADD_RELA (output_bfd, got, h->got.offset, 0, R_ARC_RELATIVE, 0);
        !          1397:        }
        !          1398:       else
        !          1399:        {
        !          1400:          ADD_RELA (output_bfd, got, h->got.offset, h->dynindx,
        !          1401:                    R_ARC_GLOB_DAT, 0);
        !          1402:        }
        !          1403:     }
        !          1404:
        !          1405:   /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
        !          1406:   if (strcmp (h->root.root.string, "_DYNAMIC") == 0
        !          1407:       || strcmp (h->root.root.string, "__DYNAMIC") == 0
        !          1408:       || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
        !          1409:     sym->st_shndx = SHN_ABS;
        !          1410:
        !          1411:   return TRUE;
        !          1412: }
        !          1413:
        !          1414: #define GET_SYMBOL_OR_SECTION(TAG, SYMBOL, SECTION) \
        !          1415:   case TAG: \
        !          1416:     if (SYMBOL != NULL) \
        !          1417:       { \
        !          1418:        h = elf_link_hash_lookup (elf_hash_table (info), SYMBOL, FALSE, FALSE, TRUE); \
        !          1419:       } \
        !          1420:     else if (SECTION != NULL) \
        !          1421:       { \
        !          1422:        s = bfd_get_section_by_name (output_bfd, SECTION); \
        !          1423:        BFD_ASSERT (s != NULL); \
        !          1424:        do_it = TRUE; \
        !          1425:       } \
        !          1426:     break;
        !          1427:
        !          1428: /* Function :  elf_arc_finish_dynamic_sections
        !          1429:    Brief    :  Finish up the dynamic sections handling.
        !          1430:    Args     :  output_bfd :
        !          1431:               info       :
        !          1432:               h          :
        !          1433:               sym        :
        !          1434:    Returns  : True/False as the return status.  */
        !          1435: static bfd_boolean
        !          1436: elf_arc_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info *info)
        !          1437: {
        !          1438:   struct dynamic_sections ds = arc_create_dynamic_sections (output_bfd, info);
        !          1439:   bfd *dynobj = (elf_hash_table (info))->dynobj;
        !          1440:
        !          1441:   if (ds.sdyn)
        !          1442:     {
        !          1443:       Elf32_External_Dyn *dyncon, *dynconend;
        !          1444:
        !          1445:       dyncon = (Elf32_External_Dyn *) ds.sdyn->contents;
        !          1446:       dynconend =
        !          1447:          (Elf32_External_Dyn *) (ds.sdyn->contents + ds.sdyn->size);
        !          1448:       for (; dyncon < dynconend; dyncon++)
        !          1449:        {
        !          1450:          Elf_Internal_Dyn internal_dyn;
        !          1451:          bfd_boolean     do_it = FALSE;
        !          1452:
        !          1453:          struct elf_link_hash_entry *h = NULL;
        !          1454:          asection       *s = NULL;
        !          1455:
        !          1456:          bfd_elf32_swap_dyn_in (dynobj, dyncon, &internal_dyn);
        !          1457:
        !          1458:          switch (internal_dyn.d_tag)
        !          1459:            {
        !          1460:              GET_SYMBOL_OR_SECTION (DT_INIT, "_init", NULL)
        !          1461:              GET_SYMBOL_OR_SECTION (DT_FINI, "_fini", NULL)
        !          1462:              GET_SYMBOL_OR_SECTION (DT_PLTGOT, NULL, ".plt")
        !          1463:              GET_SYMBOL_OR_SECTION (DT_JMPREL, NULL, ".rela.plt")
        !          1464:              GET_SYMBOL_OR_SECTION (DT_PLTRELSZ, NULL, ".rela.plt")
        !          1465:              GET_SYMBOL_OR_SECTION (DT_RELASZ, NULL, ".rela.plt")
        !          1466:              default:
        !          1467:                break;
        !          1468:            }
        !          1469:
        !          1470:          /* In case the dynamic symbols should be updated with a
        !          1471:             symbol.  */
        !          1472:          if (h != NULL
        !          1473:              && (h->root.type == bfd_link_hash_defined
        !          1474:                  || h->root.type == bfd_link_hash_defweak)
        !          1475:              )
        !          1476:            {
        !          1477:              asection       *asec_ptr;
        !          1478:
        !          1479:              internal_dyn.d_un.d_val = h->root.u.def.value;
        !          1480:              asec_ptr = h->root.u.def.section;
        !          1481:              if (asec_ptr->output_section != NULL)
        !          1482:                {
        !          1483:                  internal_dyn.d_un.d_val +=
        !          1484:                    (asec_ptr->output_section->vma +
        !          1485:                     asec_ptr->output_offset);
        !          1486:                }
        !          1487:              else
        !          1488:                {
        !          1489:                  /* The symbol is imported from another
        !          1490:                     shared library and does not apply to this
        !          1491:                     one.  */
        !          1492:                  internal_dyn.d_un.d_val = 0;
        !          1493:                }
        !          1494:              do_it = TRUE;
        !          1495:            }
        !          1496:          else if (s != NULL) /* With a section information.  */
        !          1497:            {
        !          1498:              switch (internal_dyn.d_tag)
        !          1499:                {
        !          1500:                  case DT_PLTGOT:
        !          1501:                  case DT_JMPREL:
        !          1502:                    internal_dyn.d_un.d_ptr = s->vma;
        !          1503:                    do_it = TRUE;
        !          1504:                    break;
        !          1505:
        !          1506:                  case DT_PLTRELSZ:
        !          1507:                    internal_dyn.d_un.d_val = s->size;
        !          1508:                    do_it = TRUE;
        !          1509:                    break;
        !          1510:
        !          1511:                  case DT_RELASZ:
        !          1512:                    internal_dyn.d_un.d_val -= s->size;
        !          1513:                    do_it = TRUE;
        !          1514:                    break;
        !          1515:
        !          1516:                  default:
        !          1517:                    break;
        !          1518:                }
        !          1519:            }
        !          1520:
        !          1521:          if (do_it == TRUE)
        !          1522:            bfd_elf32_swap_dyn_out (output_bfd, &internal_dyn, dyncon);
        !          1523:        }
        !          1524:
        !          1525:       if (ds.splt->size > 0)
        !          1526:        {
        !          1527:          relocate_plt_for_entry (info);
        !          1528:        }
        !          1529:
        !          1530:       elf_section_data (ds.srelplt->output_section)->this_hdr.sh_entsize = 0xc;
        !          1531:     }
        !          1532:
        !          1533:   /* Fill in the first three entries in the global offset table.  */
        !          1534:   if (ds.sgot)
        !          1535:     {
        !          1536:       if (ds.sgot->size > 0)
        !          1537:        {
        !          1538:          if (ds.sdyn == NULL)
        !          1539:            bfd_put_32 (output_bfd, (bfd_vma) 0,
        !          1540:                        ds.sgotplt->contents);
        !          1541:          else
        !          1542:            bfd_put_32 (output_bfd,
        !          1543:                        ds.sdyn->output_section->vma + ds.sdyn->output_offset,
        !          1544:                        ds.sgotplt->contents);
        !          1545:          bfd_put_32 (output_bfd, (bfd_vma) 0, ds.sgotplt->contents + 4);
        !          1546:          bfd_put_32 (output_bfd, (bfd_vma) 0, ds.sgotplt->contents + 8);
        !          1547:
        !          1548:          elf_section_data (ds.sgot->output_section)->this_hdr.sh_entsize = 4;
        !          1549:        }
        !          1550:     }
        !          1551:
        !          1552:   if (ds.srelgot
        !          1553:       /* Check that the linker script has not dumped the .srelgot section.  */
        !          1554:       && ds.srelgot->output_section
        !          1555:       && elf_section_data (ds.srelgot->output_section))
        !          1556:     {
        !          1557:       /* TODO: Make it work even if I remove this.  */
        !          1558:       elf_section_data (ds.srelgot->output_section)->this_hdr.sh_entsize = 0xc;
        !          1559:     }
        !          1560:
        !          1561:   return TRUE;
        !          1562: }
        !          1563:
        !          1564: #define ADD_DYNAMIC_SYMBOL(NAME, TAG) \
        !          1565:   h =  elf_link_hash_lookup (elf_hash_table (info), NAME, FALSE, FALSE, FALSE); \
        !          1566:   if ((h != NULL && (h->ref_regular || h->def_regular))) \
        !          1567:     if (! _bfd_elf_add_dynamic_entry (info, TAG, 0)) \
        !          1568:       return FALSE;
        !          1569:
        !          1570: /* Set the sizes of the dynamic sections.  */
        !          1571: static bfd_boolean
        !          1572: elf_arc_size_dynamic_sections (bfd * output_bfd, struct bfd_link_info *info)
        !          1573: {
        !          1574:   bfd *           dynobj;
        !          1575:   asection *      s;
        !          1576:   bfd_boolean    relocs_exist;
        !          1577:   bfd_boolean    reltext_exist;
        !          1578:   struct dynamic_sections ds = arc_create_dynamic_sections (output_bfd, info);
        !          1579:
        !          1580:   dynobj = (elf_hash_table (info))->dynobj;
        !          1581:   BFD_ASSERT (dynobj != NULL);
        !          1582:
        !          1583:   if ((elf_hash_table (info))->dynamic_sections_created)
        !          1584:     {
        !          1585:       struct elf_link_hash_entry *h;
        !          1586:
        !          1587:       /* Set the contents of the .interp section to the interpreter.  */
        !          1588:       if (!bfd_link_pic (info))
        !          1589:        {
        !          1590:          s = bfd_get_section_by_name (dynobj, ".interp");
        !          1591:          BFD_ASSERT (s != NULL);
        !          1592:          s->size = sizeof ELF_DYNAMIC_INTERPRETER;
        !          1593:          s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
        !          1594:        }
        !          1595:
        !          1596:       /* Add some entries to the .dynamic section.  We fill in some of the
        !          1597:          values later, in elf_bfd_final_link, but we must add the entries
        !          1598:          now so that we know the final size of the .dynamic section.
        !          1599:          Checking if the .init section is present.  We also create DT_INIT
        !          1600:          and DT_FINI entries if the init_str has been changed by the user.  */
        !          1601:
        !          1602:       ADD_DYNAMIC_SYMBOL ("init", DT_INIT);
        !          1603:       ADD_DYNAMIC_SYMBOL ("fini", DT_FINI);
        !          1604:     }
        !          1605:   else
        !          1606:     {
        !          1607:       /* We may have created entries in the .rela.got section.  However, if
        !          1608:          we are not creating the dynamic sections, we will not actually
        !          1609:          use these entries.  Reset the size of .rela.got, which will cause
        !          1610:          it to get stripped from the output file below.  */
        !          1611:       ds.srelgot->size = 0;
        !          1612:     }
        !          1613:
        !          1614:   for (s = dynobj->sections; s != NULL; s = s->next)
        !          1615:     {
        !          1616:        bfd_boolean     is_dynamic_section = FALSE;
        !          1617:
        !          1618:        /* Skip any non dynamic section.  */
        !          1619:        if (strstr (s->name, ".plt") != NULL
        !          1620:            || strstr (s->name, ".got") != NULL
        !          1621:          || strstr (s->name, ".rel") != NULL)
        !          1622:        is_dynamic_section = TRUE;
        !          1623:
        !          1624:       /* Allocate memory for the section contents.  */
        !          1625:       if (!is_dynamic_section)
        !          1626:        continue;
        !          1627:
        !          1628:       s->contents = (bfd_byte *) bfd_alloc (dynobj, s->size);
        !          1629:       if (s->contents == NULL && s->size != 0)
        !          1630:          return FALSE;
        !          1631:
        !          1632:       if (s->size == 0)
        !          1633:        {
        !          1634:          s->flags |= SEC_EXCLUDE;
        !          1635:          continue;
        !          1636:        }
        !          1637:
        !          1638:       if (strcmp (s->name, ".rela.plt") != 0)
        !          1639:        {
        !          1640:          const char *outname = bfd_get_section_name (output_bfd,
        !          1641:                                                      s->output_section);
        !          1642:          asection *target = bfd_get_section_by_name (output_bfd,
        !          1643:                                                      outname + 4);
        !          1644:
        !          1645:          relocs_exist = TRUE;
        !          1646:          if (target != NULL && target->size != 0
        !          1647:              && (target->flags & SEC_READONLY) != 0
        !          1648:              && (target->flags & SEC_ALLOC) != 0)
        !          1649:            reltext_exist = TRUE;
        !          1650:        }
        !          1651:     }
        !          1652:
        !          1653:   if (ds.sdyn)
        !          1654:     {
        !          1655:       if (ds.splt && ds.splt->size != 0)
        !          1656:        if (!_bfd_elf_add_dynamic_entry (info, DT_PLTGOT, 0)
        !          1657:            || !_bfd_elf_add_dynamic_entry (info, DT_PLTRELSZ, 0)
        !          1658:            || !_bfd_elf_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
        !          1659:            || !_bfd_elf_add_dynamic_entry (info, DT_JMPREL, 0)
        !          1660:           )
        !          1661:          return FALSE;
        !          1662:
        !          1663:       if (relocs_exist == TRUE)
        !          1664:        if (!_bfd_elf_add_dynamic_entry (info, DT_RELA, 0)
        !          1665:            || !_bfd_elf_add_dynamic_entry (info, DT_RELASZ, 0)
        !          1666:            || !_bfd_elf_add_dynamic_entry (info, DT_RELENT,
        !          1667:                                            sizeof (Elf32_External_Rela))
        !          1668:           )
        !          1669:          return FALSE;
        !          1670:
        !          1671:       if (reltext_exist == TRUE)
        !          1672:        if (!_bfd_elf_add_dynamic_entry (info, DT_TEXTREL, 0))
        !          1673:          return FALSE;
        !          1674:     }
        !          1675:
        !          1676:   return TRUE;
        !          1677: }
        !          1678:
        !          1679:
        !          1680: #define TARGET_LITTLE_SYM   arc_elf32_le_vec
1.1       christos 1681: #define TARGET_LITTLE_NAME  "elf32-littlearc"
1.1.1.1.2.1! pgoyette 1682: #define TARGET_BIG_SYM     arc_elf32_be_vec
        !          1683: #define TARGET_BIG_NAME     "elf32-bigarc"
        !          1684: #define ELF_ARCH           bfd_arch_arc
        !          1685: #define ELF_MACHINE_CODE    EM_ARC_COMPACT
        !          1686: #define ELF_MACHINE_ALT1    EM_ARC_COMPACT2
        !          1687: #define ELF_MAXPAGESIZE     0x2000
        !          1688:
        !          1689: #define elf_info_to_howto_rel               arc_info_to_howto_rel
        !          1690: #define elf_backend_object_p                arc_elf_object_p
        !          1691: #define elf_backend_final_write_processing   arc_elf_final_write_processing
        !          1692:
        !          1693: #define elf_backend_relocate_section        elf_arc_relocate_section
        !          1694: #define elf_backend_check_relocs            elf_arc_check_relocs
        !          1695: #define elf_backend_create_dynamic_sections  _bfd_elf_create_dynamic_sections
        !          1696:
        !          1697: #define elf_backend_adjust_dynamic_symbol    elf_arc_adjust_dynamic_symbol
        !          1698: #define elf_backend_finish_dynamic_symbol    elf_arc_finish_dynamic_symbol
        !          1699:
        !          1700: #define elf_backend_finish_dynamic_sections  elf_arc_finish_dynamic_sections
        !          1701: #define elf_backend_size_dynamic_sections    elf_arc_size_dynamic_sections
        !          1702:
        !          1703: #define elf_backend_can_gc_sections    1
        !          1704: #define elf_backend_want_got_plt       1
        !          1705: #define elf_backend_plt_readonly       1
        !          1706: #define elf_backend_want_plt_sym       0
        !          1707: #define elf_backend_got_header_size    12
        !          1708:
        !          1709: #define elf_backend_may_use_rel_p      0
        !          1710: #define elf_backend_may_use_rela_p     1
        !          1711: #define elf_backend_default_use_rela_p 1
1.1       christos 1712:
                   1713: #include "elf32-target.h"

CVSweb <webmaster@jp.NetBSD.org>