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>