This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
This is my second shot at Mips ifunc support. It was run through the binutils test suite. I also have and abi for it attached. Jack
This is the first MIPS ifunc patch for binutils. If you want to install build and run this patch you will need the companion glibc patch. This is targeting o32, n32 and n64. Patches for MicroMips, Mips16,and possibly vxworks will follow this patch. I attempted to follow the ARM implementation, but the traditional MIPS GOT design forced me to dirverge a bit. The only change to the traditional MIPS GOT was to use the .iplt stub address for the defined ifunc function instead of the function address in executables. This should allow seamless multigot support. For defined ifunc routines in shared objects have no iplts and depend exclusively on the dynamic symbol resolution to call the resolver for the correct runtime address. I believe I have addressed all the issues of the first patch review with the exception of one of the forward declarations (fixing it was getting too messy) and the penalty of shared executables with ifunc definitions forcing everything through iplts stubs. Still not sure how to avoid that one, but the vast majority of ifunc use should be by dsos so it may not be a priority. Preemption and n32 have been tested with runtime testing, but are not yet in the test-suite. *************************************** I have a rough ABI description attached to this patch. Below is the abridged version. The attached ABI needs to be critically reviewed as well, with suggested wording hopefully. If an iplt is needed: Generate iplt stubs (.iplt) Generate igot table (.igot.plt) Generate IRELATIVE relocations for .igot.plt Iplts are needed for executables (a.outs) only. Non-shared a.outs: Always goes through the iplt with IRELATIVE relocations against the .igot.plt. Dynamic executables (both fPIC and not): All a.out references are direct with got entries containing ifunc iplt addresses. Dso references are through the iplt with IRELATIVE relocations against the igot and the dynsym entries being the iplt address and the symbol type changed STT_FUNC. The dynamic linker will update the igot table in the a.out. Dynamic shared objects: No iplt, igot or IRELATIVE relocations. The GOT and .dynsym will have the ifunc values and the dynsym type will remain STT_GNU_IFUNC. The dynamic linker will detect that the symbol is an STT_GNU_IFUNC and do the fixup based on the defining dynsym address. In all cases the contents of the igot is the ifunc address with an R_MIPS_IRELATIVE relocation against it. *************************************** bfd/ChangeLog * bfd-in2.h (BFD_RELOC_MIPS_IRELATIVE): New relocation. * bfd/elf32-mips.c (elf_mips_eh_howto table): Howto for BFD_RELOC_MIPS_IRELATIVE. (bfd_elf32_bfd_reloc_name_lookup): Case for elf_mips_irelative_howto. (mips_elf32_rtype_to_howto): Case for BFD_RELOC_MIPS_IRELATIVE. * elfxx-mips.c (struct mips_elf_link_hash_entry): Offset indexes into iplt and igot. (mips_elf_link_hash_entry): Flag to indicate sym needs an iplt. (mips_elf_link_hash_table): New shortcut pointers to iplt related sections. New size of an iplt stub. (mips_elf_allocate_ireloc): New function forward declaration. I tried to get rid of this and just got more undefines. FIXME. (mips32_exec_iplt_entry): Template for exec iplt instruction sequence. (mips64_exec_iplt_entry): Template for exec iplt instruction sequence. (mips_elf_link_hash_newfunc): Initialization of new mips_elf_link_hash_entry elements. (mips_elf_allocate_iplt): New function. (mips_elf_check_symbols): Allocate an iplt for any IFUNC symbols. (mips_elf_create_ifunc_sections): New function. Create ELF sections associated with ifunc use. (mips_elf_calculate_relocation): Point symbol value to iplt stub. (_bfd_mips_elf_section_processing): Size .igot.iplt section. (_bfd_mips_elf_add_symbol_hook): Mark output as has_gnu_symbols. (mips_elf_allocate_ireloc): New function. (_bfd_mips_elf_check_relocs): Check if we need to create iplt sections. If symbol is an IFUNC, don't convert it to an STT_FUNC. (allocate_dynrelocs): Call mips_elf_allocate_ireloc if R_MIPS_IRELATIVE. (_bfd_mips_elf_adjust_dynamic_symbol): Add STT_GNU_IFUNC to sanity check. (mips_elf_create_iplt): New function. (_bfd_mips_elf_finish_dynamic_symbol): If the symbol has been marked as, needing an iplt call the iplt creation routine. Set the iplt symbol value to the iplt entry address. * libbfd.h (bfd_reloc_code_real_names): Entry for BFD_RELOC_MIPS_IRELATIVE. * reloc.c (ENUMDOC): BFD_RELOC_MIPS_IRELATIVE entry. include/ChangeLog * elf/mips.h (START_RELOC_NUMBERS): Entry for R_MIPS_IRELATIVE. ld/testsuite/ChangeLog * ld-mips-elf/mips-ifunc.exp: Ifunc test script * ifunc-3-n32.r, ifunc-3-n32.sym, ifunc-3-n32.t, ifunc-3-n64.r, ifunc-3-n64.sym, ifunc-3-n64.t, ifunc-3-o32.r, ifunc-3-o32.sym, ifunc-3-o32.t, ifunc-4-n32.r, ifunc-4-n32.sym, ifunc-4-n32.t, ifunc-4-n64.r, ifunc-4-n64.sym, ifunc-4-n64.t, ifunc-4-o32.r, ifunc-4-o32.sym, ifunc-4-o32.t, ifunc-5-n32.g, ifunc-5-n32.r, ifunc-5-n32.sym, ifunc-5-n64.g, ifunc-5-n64.r, ifunc-5-n64.sym, ifunc-5-o32.g, ifunc-5-o32.r, ifunc-5-o32.sym, ifunc-6-n32.r, ifunc-6-n32.sym, ifunc-6-n64.r, ifunc-6-n64.sym, ifunc-6-o32.r, ifunc-6-o32.sym, ifunc-dyn-def.s, ifunc-dyn-main.s, ifunc-dyn-ref.s, ifunc-dyn.ld, ifunc-iplt-0x400000.t, ifunc-iplt-0x400000000.t, ifunc-iplt-0x4000000000000.t, ifunc-iplt.ld, ifunc-static-def.s, ifunc-static-main.s, ifunc-static-ref.s, ifunc-static.ld, libifunc-1-n32.sym, libifunc-1-n64.sym, libifunc-1-o32.sym, libifunc-2-n32.sym, libifunc-2-n64.sym, libifunc-2-o32.sym: New tests. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 644f89d..0cddfa6 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -2972,6 +2972,9 @@ to compensate for the borrow when the low bits are added. */ BFD_RELOC_MOXIE_10_PCREL, +/* MIPS support for STT_GNU_IFUNC. */ + BFD_RELOC_MIPS_IRELATIVE, + /* Fujitsu Frv Relocations. */ BFD_RELOC_FRV_LABEL16, BFD_RELOC_FRV_LABEL24, diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index eec2ef7..b05252d 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -1554,6 +1554,22 @@ static reloc_howto_type elf_mips_eh_howto = 0xffffffff, /* dst_mask */ FALSE); /* pcrel_offset */ +/* STT_GNU_IFUNC support: */ +static reloc_howto_type elf_mips_irelative_howto = + HOWTO (R_MIPS_IRELATIVE, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MIPS_IRELATIVE", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE); /* pcrel_offset */ + /* Set the GP value for OUTPUT_BFD. Returns FALSE if this is a dangerous relocation. */ @@ -2028,6 +2044,8 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code) return &elf_mips_jump_slot_howto; case BFD_RELOC_MIPS_EH: return &elf_mips_eh_howto; + case BFD_RELOC_MIPS_IRELATIVE: + return &elf_mips_irelative_howto; } } @@ -2075,6 +2093,8 @@ bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, return &elf_mips_jump_slot_howto; if (strcasecmp (elf_mips_eh_howto.name, r_name) == 0) return &elf_mips_eh_howto; + if (strcasecmp (elf_mips_irelative_howto.name, r_name) == 0) + return &elf_mips_irelative_howto; return NULL; } @@ -2101,6 +2121,8 @@ mips_elf32_rtype_to_howto (unsigned int r_type, return &elf_mips_jump_slot_howto; case R_MIPS_EH: return &elf_mips_eh_howto; + case R_MIPS_IRELATIVE: + return &elf_mips_irelative_howto; default: if (r_type >= R_MICROMIPS_min && r_type < R_MICROMIPS_max) return &elf_micromips_howto_table_rel[r_type - R_MICROMIPS_min]; diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 1c64ad3..d3730b0 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -372,6 +372,12 @@ struct mips_elf_link_hash_entry being called returns a floating point value. */ asection *call_fp_stub; + /* Offset into the IPLT table. */ + unsigned int iplt_offset; + + /* Offset into the IGOT table. */ + unsigned int igot_offset; + /* The highest GGA_* value that satisfies all references to this symbol. */ unsigned int global_got_area : 2; @@ -410,6 +416,9 @@ struct mips_elf_link_hash_entry /* Does this symbol resolve to a PLT entry? */ unsigned int use_plt_entry : 1; + + /* Does this symbol need an IPLT stub? */ + unsigned int needs_iplt: 1; }; /* MIPS ELF linker hash table. */ @@ -454,6 +463,9 @@ struct mips_elf_link_hash_table asection *srelplt2; asection *sgotplt; asection *splt; + asection *sigotplt; + asection *siplt; + asection *sreliplt; asection *sstubs; asection *sgot; @@ -482,6 +494,9 @@ struct mips_elf_link_hash_table /* The index of the next .got.plt entry to create. */ bfd_vma plt_got_index; + /* The size of an IPLT entry in bytes. */ + bfd_vma iplt_entry_size; + /* The number of functions that need a lazy-binding stub. */ bfd_vma lazy_stub_count; @@ -744,6 +759,9 @@ static bfd_boolean mips_elf_create_dynamic_relocation bfd_vma *, asection *); static bfd_vma mips_elf_adjust_gp (bfd *, struct mips_got_info *, bfd *); +static void +mips_elf_allocate_ireloc + (struct bfd_link_info *, struct mips_elf_link_hash_entry *); /* This will be used when we sort the dynamic relocation records. */ static bfd *reldyn_sorting_bfd; @@ -1160,6 +1178,32 @@ static const bfd_vma mips_vxworks_shared_plt_entry[] = 0x10000000, /* b .PLT_resolver */ 0x24180000 /* li t8, <pltindex> */ }; + +/* The format of non-pie IPLT entries. + In the case of mips1 the first nop will be issued before the + jr instuction */ +static const bfd_vma mips32_exec_iplt_entry[] = +{ + 0x3c0f0000, /* lui $15, %hi(.got.iplt entry) */ + 0x01f90000, /* l[wd] $25, %lo(.got.iplt entry)($15) */ + 0x03200008, /* jr $25 */ + 0x00000000, /* nop */ + 0x00000000 /* nop */ +}; + +/* The format of non-pie 64 bit IPLT entries. */ +static const bfd_vma mips64_exec_iplt_entry[] = +{ + 0x3c0f0000, /* lui $15, %highest(.got.iplt entry) */ + 0x65ef0000, /* daddiu $15, $15, %higher(.got.iplt entry) */ + 0x000f7c38, /* dsll $15,$15, 16 */ + 0x65ef0000, /* daddiu $15, $15, %hi(.got.iplt entry) */ + 0x000f7c38, /* dsll $15,$15, 16 */ + 0x01f90000, /* l[wd] $25, %lo(.got.iplt entry)($15) */ + 0x03200008, /* jr $25 */ + 0x00000000, /* nop */ +}; + /* microMIPS 32-bit opcode helper installer. */ @@ -1258,6 +1302,9 @@ mips_elf_link_hash_newfunc (struct bfd_hash_entry *entry, ret->has_nonpic_branches = FALSE; ret->needs_lazy_stub = FALSE; ret->use_plt_entry = FALSE; + ret->needs_iplt = FALSE; + ret->iplt_offset = -1; + ret->igot_offset = 0; } return (struct bfd_hash_entry *) ret; @@ -1935,6 +1982,40 @@ mips_elf_add_la25_stub (struct bfd_link_info *info, : mips_elf_add_la25_intro (stub, info)); } +/* Reserve space in the iplt and igot tables for another ifunc entry. + Don't do anything if this is a dso link. */ +static bfd_boolean +mips_elf_allocate_iplt (bfd *abfd, struct mips_elf_link_hash_table *mhtab, + struct bfd_link_info *info, + struct mips_elf_link_hash_entry *mh) +{ + + asection *s; + + if (mh->needs_iplt || !info->executable) + return TRUE; + + BFD_ASSERT (mhtab->siplt != NULL); + + s = mhtab->siplt; + mh->iplt_offset = s->size; + s->size += mhtab->iplt_entry_size; + + /* Create a symbol for the stub. */ + mips_elf_create_stub_symbol (info, mh, ".iplt.",s, mh->iplt_offset, + mhtab->iplt_entry_size); + + BFD_ASSERT (mhtab->sigotplt != NULL); + mh->igot_offset = mhtab->sigotplt->size; + mhtab->sigotplt->size += MIPS_ELF_GOT_SIZE (abfd); + mips_elf_allocate_ireloc (info, mh); + +/* This should be the only place needs_iplt is set */ + mh->needs_iplt = TRUE; + + return TRUE; +} + /* A mips_elf_link_hash_traverse callback that is called before sizing sections. DATA points to a mips_htab_traverse_info structure. */ @@ -1947,6 +2028,15 @@ mips_elf_check_symbols (struct mips_elf_link_hash_entry *h, void *data) if (!hti->info->relocatable) mips_elf_check_mips16_stubs (hti->info, h); + /* If the referenced symbol is ifunc, allocate an iplt stub for it. */ + if (h && !h->needs_iplt && h->root.type == STT_GNU_IFUNC) + { + struct bfd_link_info *info = hti->info; + if (!(mips_elf_allocate_iplt (info->output_bfd, + mips_elf_hash_table (info), info, h))) + return FALSE; + } + if (mips_elf_local_pic_function_p (h)) { /* PR 12845: If H is in a section that has been garbage @@ -4998,6 +5088,74 @@ mips_elf_create_compact_rel_section return TRUE; } +/* Create the .iplt, .rel(a).iplt and .igot.plt sections. */ + +static bfd_boolean +mips_elf_create_ifunc_sections (bfd *abfd, struct bfd_link_info *info) +{ + struct mips_elf_link_hash_table * volatile htab; + const struct elf_backend_data *bed; + bfd *dynobj; + asection *s; + flagword flags; + + /* Don't do anything if a dso link. */ + if (!info->executable) + return TRUE; + + htab = mips_elf_hash_table (info); + dynobj = (htab->root.dynobj) ? htab->root.dynobj : abfd; + bed = get_elf_backend_data (dynobj); + flags = bed->dynamic_sec_flags; + + if (htab->root.iplt == NULL) + { + s = bfd_make_section_anyway_with_flags (dynobj, ".iplt", + flags | SEC_READONLY | SEC_CODE); + if (s == NULL + || !bfd_set_section_alignment (dynobj, s, bed->plt_alignment)) + return FALSE; + htab->root.iplt = s; + htab->siplt = s; + if (!info->shared) + if (ABI_64_P (abfd)) + htab->iplt_entry_size = 4 * ARRAY_SIZE (mips64_exec_iplt_entry); + else + htab->iplt_entry_size = 4 * ARRAY_SIZE (mips32_exec_iplt_entry); + else + { + ; + }/* FIXME: None of the ifunc related sections should be built */ + } + + if (htab->root.igotplt == NULL ) + { + s = bfd_make_section_anyway_with_flags (dynobj, ".igot.plt", flags); + if (s == NULL + || !bfd_set_section_alignment (dynobj, s, bed->s->log_file_align)) + return FALSE; + htab->root.igotplt = s; + htab->sigotplt = s; + mips_elf_section_data (s)->elf.this_hdr.sh_flags |= SHF_ALLOC | + SHF_WRITE; + } + + if (htab->sreliplt == NULL ) + { + s = bfd_make_section_with_flags (dynobj, + ".rel.iplt", /* This is magic currently */ + flags | SEC_READONLY); + if (s == NULL + || !bfd_set_section_alignment (dynobj, s, bed->s->log_file_align)) + return FALSE; + htab->sreliplt = s; + mips_elf_section_data (s)->elf.this_hdr.sh_entsize = + MIPS_ELF_REL_SIZE (dynobj); + } + + return TRUE; +} + /* Create the .got section to hold the global offset table. */ static bfd_boolean @@ -5466,6 +5624,14 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, target_is_16_bit_code_p = !micromips_p; target_is_micromips_code_p = micromips_p; } + /* If this symbol is an ifunc, point to the iplt stub for it, */ + else if (h && h->needs_iplt) + { + BFD_ASSERT (htab->siplt != NULL); + symbol = (htab->siplt->output_section->vma + + htab->siplt->output_offset + + h->iplt_offset); + } /* Make sure MIPS16 and microMIPS are not used together. */ if ((r_type == R_MIPS16_26 && target_is_micromips_code_p) @@ -6829,6 +6995,8 @@ _bfd_mips_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *hdr) hdr->sh_size += hdr->sh_addralign - adjust; } } + else if (strcmp (name, ".igot.plt") == 0) + hdr->sh_entsize = ABI_64_P (abfd) ? 8 : 4; } return TRUE; @@ -7167,6 +7335,10 @@ _bfd_mips_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, flagword *flagsp ATTRIBUTE_UNUSED, asection **secp, bfd_vma *valp) { + + if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) + elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE; + if (SGI_COMPAT (abfd) && (abfd->flags & DYNAMIC) != 0 && strcmp (*namep, "_rld_new_interface") == 0) @@ -7680,6 +7852,29 @@ mips_elf_make_plt_record (bfd *abfd) return entry; } +/* Reserve space for R_MIPS_IRELATIVE relocations. If the link is + dynamic, the relocations should go in SRELOC, otherwise they should + go in the special .rel.iplt section. */ + +static void +mips_elf_allocate_ireloc (struct bfd_link_info *info, + struct mips_elf_link_hash_entry *hmips ATTRIBUTE_UNUSED) +{ + struct mips_elf_link_hash_table *htab; + asection *srel = NULL; + bfd *dynobj = elf_hash_table (info)->dynobj; + BFD_ASSERT (dynobj != NULL); + + htab = mips_elf_hash_table (info); + srel = (!elf_hash_table (info)->dynamic_sections_created) + ? htab->sreliplt + : mips_elf_rel_dyn_section (info, FALSE); + BFD_ASSERT (srel != NULL); + + srel->size += ((htab->is_vxworks) ? MIPS_ELF_RELA_SIZE (dynobj) + : MIPS_ELF_REL_SIZE (dynobj)); +} + /* Look through the relocs for a section during the first phase, and allocate space in the global offset table and record the need for standard MIPS and compressed procedure linkage table entries. */ @@ -7716,6 +7911,14 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, bed = get_elf_backend_data (abfd); rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel; + /* This needs to happen early. If the sections aren't needed + they will not get generated. */ + if (htab->root.dynobj == NULL) + htab->root.dynobj = abfd; + if (!htab->siplt && + !mips_elf_create_ifunc_sections (htab->root.dynobj, info)) + return FALSE; + /* Check for the mips16 stub sections. */ name = bfd_get_section_name (abfd, sec); @@ -8217,10 +8420,14 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, /* We need a stub, not a plt entry for the undefined function. But we record it as if it needs plt. See - _bfd_elf_adjust_dynamic_symbol. */ - h->needs_plt = 1; - h->type = STT_FUNC; - } + _bfd_elf_adjust_dynamic_symbol. If it is an ifunc + symbol it will go into an iplt section and not plt. */ + if (h->type != STT_GNU_IFUNC) + { + h->needs_plt = 1; + h->type = STT_FUNC; + } + } break; case R_MIPS_GOT_PAGE: @@ -8669,6 +8876,13 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) dynobj = elf_hash_table (info)->dynobj; hmips = (struct mips_elf_link_hash_entry *) h; + /* Record any ifunc symbols */ + if (h && hmips->needs_iplt) + { + mips_elf_allocate_ireloc (info, hmips); + return TRUE; + } + /* VxWorks executables are handled elsewhere; we only need to allocate relocations in shared objects. */ if (htab->is_vxworks && !info->shared) @@ -8758,6 +8972,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, /* Make sure we know what is going on here. */ BFD_ASSERT (dynobj != NULL && (h->needs_plt + || h->type == STT_GNU_IFUNC || h->u.weakdef != NULL || (h->def_dynamic && h->ref_regular @@ -9518,6 +9733,8 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, else if (! CONST_STRNEQ (name, ".init") && s != htab->sgot && s != htab->sgotplt + && s != htab->root.iplt + && s != htab->root.igotplt && s != htab->sstubs && s != htab->sdynbss) { @@ -10244,6 +10461,134 @@ mips_elf_irix6_finish_dynamic_symbol (bfd *abfd ATTRIBUTE_UNUSED, } } +/* Create the contents of a iplt entry for the ifunc symbol. */ + +static bfd_boolean +mips_elf_create_iplt (bfd *output_bfd, + bfd *dynobj, + struct mips_elf_link_hash_table *htab, + struct mips_elf_link_hash_entry *hmips, + Elf_Internal_Sym *sym, + struct bfd_link_info *info) +{ + /* We've decided to create an IPLT entry for this symbol. */ + bfd_byte *loc; + bfd_vma igot_index = 0; + bfd_vma igotplt_address = 0; + bfd_vma load; + const bfd_vma *iplt_entry; + asection *gotsect, *relsect; + + gotsect = htab->sigotplt; + igot_index = hmips->igot_offset/MIPS_ELF_GOT_SIZE (dynobj); + + relsect = (!elf_hash_table (info)->dynamic_sections_created) + ? htab->sreliplt + : mips_elf_rel_dyn_section (info, FALSE); + + /* Calculate the address of the .igot.plt entry. */ + igotplt_address = (gotsect->output_section->vma + + gotsect->output_offset + + hmips->igot_offset); + + /* Initially point the .got.iplt entry at the user ifunc routine. */ + if (!gotsect->contents) + gotsect->contents = bfd_zalloc(output_bfd,gotsect->size); + + loc = (bfd_byte *)gotsect->contents + + igot_index * MIPS_ELF_GOT_SIZE (dynobj); + + if (ABI_64_P (output_bfd)) + bfd_put_64 (output_bfd, sym->st_value, loc); + else + bfd_put_32 (output_bfd, sym->st_value, loc); + + /* Find out where the .iplt entry should go. */ + if (!htab->siplt->contents) + htab->siplt->contents = bfd_zalloc (output_bfd,htab->siplt->size); + loc = htab->siplt->contents + hmips->iplt_offset; + + /* Pick the load opcode. */ + load = MIPS_ELF_LOAD_WORD (output_bfd); + + /* Fill in the IPLT entry itself. */ + if (!info->shared) + { + if (ABI_64_P (output_bfd) && igotplt_address > 0xffffffffffffL) + { + /* 64 bit */ + bfd_vma highest = mips_elf_highest (igotplt_address); + bfd_vma higher = mips_elf_higher (igotplt_address); + bfd_vma high = mips_elf_high (igotplt_address); + bfd_vma low = igotplt_address & 0xffff; + + iplt_entry = mips64_exec_iplt_entry; + bfd_put_32 (output_bfd, iplt_entry[0] | highest, loc); + bfd_put_32 (output_bfd, iplt_entry[1] | higher, loc + 4); + bfd_put_32 (output_bfd, iplt_entry[2], loc + 8); + bfd_put_32 (output_bfd, iplt_entry[3] | high , loc + 12); + bfd_put_32 (output_bfd, iplt_entry[4], loc + 16); + bfd_put_32 (output_bfd, iplt_entry[5] | low | load, loc + 20); + bfd_put_32 (output_bfd, iplt_entry[6], loc + 24); + bfd_put_32 (output_bfd, iplt_entry[7], loc + 28); + } + else if (ABI_64_P (output_bfd) && igotplt_address > 0xffffffffL) + { + /* 48 bit */ + bfd_vma higher = mips_elf_higher (igotplt_address); + bfd_vma high = mips_elf_high (igotplt_address); + bfd_vma low = igotplt_address & 0xffff; + + iplt_entry = mips64_exec_iplt_entry; + bfd_put_32 (output_bfd, iplt_entry[0] | higher, loc); + bfd_put_32 (output_bfd, iplt_entry[1] | high, loc + 4); + bfd_put_32 (output_bfd, iplt_entry[2], loc + 8); + bfd_put_32 (output_bfd, iplt_entry[5] | low | load, loc + 12); + bfd_put_32 (output_bfd, iplt_entry[6], loc + 16); + bfd_put_32 (output_bfd, iplt_entry[7], loc + 20); + } + else + { + /* 32 bit */ + bfd_vma high = mips_elf_high (igotplt_address); + bfd_vma low = igotplt_address & 0xffff; + + iplt_entry = mips32_exec_iplt_entry; + bfd_put_32 (output_bfd, iplt_entry[0] | high, loc); + bfd_put_32 (output_bfd, iplt_entry[1] | low | load, loc + 4); + + if (LOAD_INTERLOCKS_P (output_bfd)) + { + bfd_put_32 (output_bfd, iplt_entry[2], loc + 8); + bfd_put_32 (output_bfd, iplt_entry[3], loc + 12); + } + else + { + bfd_put_32 (output_bfd, iplt_entry[3], loc + 8); + bfd_put_32 (output_bfd, iplt_entry[2], loc + 12); + } + } + } + + /* Emit an R_MIPS_IRELATIVE relocation against the igot entry. */ + if (relsect->contents == NULL) + { + /* Allocate memory for the relocation section contents. */ + relsect->contents = bfd_zalloc (dynobj, relsect->size); + if (relsect->contents == NULL) + { + bfd_set_error (bfd_error_no_memory); + return FALSE; + } + } + mips_elf_output_dynamic_relocation (output_bfd, relsect, + relsect->reloc_count++, + 0 /* sym_indx */, + R_MIPS_IRELATIVE, igotplt_address); + + return TRUE; +} + /* Finish up dynamic symbol handling. We set the contents of various dynamic sections here. */ @@ -10568,6 +10913,17 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, sym->st_other = other; } + /* IFUNC symbols get an iplt stub */ + if (hmips->needs_iplt) + { + if (!(mips_elf_create_iplt (output_bfd, dynobj, htab, hmips, sym, info))) + return FALSE; + if (!elf_hash_table (info)->dynamic_sections_created) + return TRUE; + if (h->dynindx == -1 && !h->forced_local) + return TRUE; + } + /* If we have a MIPS16 function with a stub, the dynamic symbol must refer to the stub, since only the stub uses the standard calling conventions. */ @@ -10731,6 +11087,15 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, sym->st_other -= STO_MICROMIPS; } + if (hmips->needs_iplt) + { + /* Point at the iplt stub for this ifunc symbol. */ + sym->st_value = htab->siplt->output_section->vma + + htab->siplt->output_offset + + hmips->iplt_offset; + sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_FUNC); + } + return TRUE; } diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 4f98108..7acc620 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1194,6 +1194,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_MOXIE_10_PCREL", + "BFD_RELOC_MIPS_IRELATIVE", "BFD_RELOC_FRV_LABEL16", "BFD_RELOC_FRV_LABEL24", "BFD_RELOC_FRV_LO16", diff --git a/bfd/reloc.c b/bfd/reloc.c index 8778e1d..dd564f0 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2434,6 +2434,11 @@ ENUMDOC COMMENT ENUM + BFD_RELOC_MIPS_IRELATIVE +ENUMDOC + MIPS support for STT_GNU_IFUNC. + +ENUM BFD_RELOC_FRV_LABEL16 ENUMX BFD_RELOC_FRV_LABEL24 diff --git a/include/elf/mips.h b/include/elf/mips.h index 2c5a9a6..2cfd003 100644 --- a/include/elf/mips.h +++ b/include/elf/mips.h @@ -110,6 +110,9 @@ START_RELOC_NUMBERS (elf_mips_reloc_type) RELOC_NUMBER (R_MIPS_COPY, 126) RELOC_NUMBER (R_MIPS_JUMP_SLOT, 127) + /* STT_GNU_IFUNC support */ + RELOC_NUMBER (R_MIPS_IRELATIVE, 128) + /* These relocations are specific to microMIPS. */ FAKE_RELOC (R_MICROMIPS_min, 130) RELOC_NUMBER (R_MICROMIPS_26_S1, 133) diff --git a/ld/testsuite/ld-mips-elf/ifunc-3-n32.r b/ld/testsuite/ld-mips-elf/ifunc-3-n32.r new file mode 100644 index 0000000..702d441 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-3-n32.r @@ -0,0 +1,4 @@ + +Relocation section '.rel.dyn' at offset 0x12000 contains 1 entries: + Offset Info Type Sym.Value Sym. Name +00000800 00000080 R_MIPS_IRELATIVE diff --git a/ld/testsuite/ld-mips-elf/ifunc-3-n32.sym b/ld/testsuite/ld-mips-elf/ifunc-3-n32.sym new file mode 100644 index 0000000..c586de3 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-3-n32.sym @@ -0,0 +1,6 @@ +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + 4 0: 00000000 0 FUNC GLOBAL DEFAULT UND ref1 + 2 0: 00000400 28 FUNC GLOBAL DEFAULT 1 func1 + 1 1: 00000001 0 SECTION GLOBAL DEFAULT ABS _DYNAMIC_LINKING + 3 2: 0000100c 0 OBJECT GLOBAL DEFAULT 13 __RLD_MAP diff --git a/ld/testsuite/ld-mips-elf/ifunc-3-n32.t b/ld/testsuite/ld-mips-elf/ifunc-3-n32.t new file mode 100644 index 0000000..acabe49 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-3-n32.t @@ -0,0 +1,11 @@ +tmpdir/ifunc-3-n32: file format elf32-ntradbigmips + + +Disassembly of section .iplt: + +00000400 <.iplt.func1>: + 400: 3c0f0000 lui t3,0x0 + 404: 8df90800 lw t9,2048\(t3\) + 408: 03200008 jr t9 + 40c: 00000000 nop + 410: 00000000 nop diff --git a/ld/testsuite/ld-mips-elf/ifunc-3-n64.r b/ld/testsuite/ld-mips-elf/ifunc-3-n64.r new file mode 100644 index 0000000..8b6e5ba --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-3-n64.r @@ -0,0 +1,5 @@ +Relocation section '.rel.dyn' at offset 0x12000 contains 1 entries: + Offset Info Type Sym. Value Sym. Name +000000000800 000000000080 R_MIPS_IRELATIVE + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE diff --git a/ld/testsuite/ld-mips-elf/ifunc-3-n64.sym b/ld/testsuite/ld-mips-elf/ifunc-3-n64.sym new file mode 100644 index 0000000..a85c426 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-3-n64.sym @@ -0,0 +1,6 @@ +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + 4 0: 0000000000000000 0 FUNC GLOBAL DEFAULT UND ref1 + 2 0: 0000000000000400 28 FUNC GLOBAL DEFAULT 1 func1 + 1 1: 0000000000000001 0 SECTION GLOBAL DEFAULT ABS _DYNAMIC_LINKING + 3 2: 0000000000001018 0 OBJECT GLOBAL DEFAULT 13 __RLD_MAP diff --git a/ld/testsuite/ld-mips-elf/ifunc-3-n64.t b/ld/testsuite/ld-mips-elf/ifunc-3-n64.t new file mode 100644 index 0000000..0df1db2 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-3-n64.t @@ -0,0 +1,11 @@ +tmpdir/ifunc-3-n64: file format elf64-tradbigmips + + +Disassembly of section .iplt: + +0000000000000400 <.iplt.func1>: + 400: 3c0f0000 lui t3,0x0 + 404: ddf90800 ld t9,2048\(t3\) + 408: 03200008 jr t9 + 40c: 00000000 nop + ... diff --git a/ld/testsuite/ld-mips-elf/ifunc-3-o32.r b/ld/testsuite/ld-mips-elf/ifunc-3-o32.r new file mode 100644 index 0000000..702d441 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-3-o32.r @@ -0,0 +1,4 @@ + +Relocation section '.rel.dyn' at offset 0x12000 contains 1 entries: + Offset Info Type Sym.Value Sym. Name +00000800 00000080 R_MIPS_IRELATIVE diff --git a/ld/testsuite/ld-mips-elf/ifunc-3-o32.sym b/ld/testsuite/ld-mips-elf/ifunc-3-o32.sym new file mode 100644 index 0000000..94d3db6 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-3-o32.sym @@ -0,0 +1,6 @@ +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + 4 0: 00000000 0 FUNC GLOBAL DEFAULT UND ref1 + 2 0: 00000400 40 FUNC GLOBAL DEFAULT 1 func1 + 1 1: 00000001 0 SECTION GLOBAL DEFAULT ABS _DYNAMIC_LINKING + 3 2: 0000100c 0 OBJECT GLOBAL DEFAULT 13 __RLD_MAP diff --git a/ld/testsuite/ld-mips-elf/ifunc-3-o32.t b/ld/testsuite/ld-mips-elf/ifunc-3-o32.t new file mode 100644 index 0000000..eba438f --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-3-o32.t @@ -0,0 +1,11 @@ +tmpdir/ifunc-3-o32: file format elf32-tradbigmips + + +Disassembly of section .iplt: + +00000400 <.iplt.func1>: + 400: 3c0f0000 lui t7,0x0 + 404: 8df90800 lw t9,2048\(t7\) + 408: 00000000 nop + 40c: 03200008 jr t9 + 410: 00000000 nop diff --git a/ld/testsuite/ld-mips-elf/ifunc-4-n32.r b/ld/testsuite/ld-mips-elf/ifunc-4-n32.r new file mode 100644 index 0000000..9259df6 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-4-n32.r @@ -0,0 +1,4 @@ +Relocation section '.rel.dyn' at offset 0x11000 contains 2 entries: + Offset Info Type Sym.Value Sym. Name +00080800 00000080 R_MIPS_IRELATIVE +00000000 00000000 R_MIPS_NONE diff --git a/ld/testsuite/ld-mips-elf/ifunc-4-n32.sym b/ld/testsuite/ld-mips-elf/ifunc-4-n32.sym new file mode 100644 index 0000000..cbad3aa --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-4-n32.sym @@ -0,0 +1,29 @@ +Symbol table '.symtab' contains 27 entries: + Num: Value Size Type Bind Vis Ndx Name + 0: 00000000 0 NOTYPE LOCAL DEFAULT UND + 1: 00080000 0 SECTION LOCAL DEFAULT 1 + 2: 00080400 0 SECTION LOCAL DEFAULT 2 + 3: 00080800 0 SECTION LOCAL DEFAULT 3 + 4: 00081000 0 SECTION LOCAL DEFAULT 4 + 5: 00081010 0 SECTION LOCAL DEFAULT 5 + 6: 00000000 0 SECTION LOCAL DEFAULT 6 + 7: 00000000 0 SECTION LOCAL DEFAULT 7 + 8: 00000000 0 SECTION LOCAL DEFAULT 8 + 9: 00000000 0 FILE LOCAL DEFAULT ABS ifunc_ref_main_1.c + 10: 00000000 0 FILE LOCAL DEFAULT ABS ifunc.c + 11: 00080430 36 FUNC LOCAL DEFAULT 2 f1_a + 12: 00080454 36 FUNC LOCAL DEFAULT 2 f1_b + 13: 00080478 36 FUNC LOCAL DEFAULT 2 f1_c + 14: 000804d0 0 NOTYPE LOCAL DEFAULT 2 \$L8 + 15: 000804d8 0 NOTYPE LOCAL DEFAULT 2 \$L9 + 16: 000804f8 0 NOTYPE LOCAL DEFAULT 2 \$L10 + 17: 00080520 0 NOTYPE LOCAL DEFAULT 2 \$L13 + 18: 00080518 0 NOTYPE LOCAL DEFAULT 2 \$L12 + 19: 00000000 0 FILE LOCAL DEFAULT ABS ifunc_ref.c + 20: 00000000 0 FILE LOCAL DEFAULT ABS + 21: 00080000 20 FUNC LOCAL DEFAULT 1 .iplt.func1 + 22: 0008049c 156 IFUNC GLOBAL DEFAULT 2 func1 + 23: 00000000 0 NOTYPE GLOBAL DEFAULT UND _start + 24: 00080400 48 FUNC GLOBAL DEFAULT 2 main + 25: 00080540 48 FUNC GLOBAL DEFAULT 2 ref1 + 26: 0008049c 156 FUNC GLOBAL DEFAULT 2 func1_ifunc diff --git a/ld/testsuite/ld-mips-elf/ifunc-4-n32.t b/ld/testsuite/ld-mips-elf/ifunc-4-n32.t new file mode 100644 index 0000000..5daf80f --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-4-n32.t @@ -0,0 +1,11 @@ +tmpdir/ifunc-4-n32: file format elf32-ntradbigmips + + +Disassembly of section .iplt: + +00080000 <.iplt.func1>: + 80000: 3c0f0008 lui t3,0x8 + 80004: 8df90800 lw t9,2048\(t3\) + 80008: 03200008 jr t9 + 8000c: 00000000 nop + 80010: 00000000 nop diff --git a/ld/testsuite/ld-mips-elf/ifunc-4-n64.r b/ld/testsuite/ld-mips-elf/ifunc-4-n64.r new file mode 100644 index 0000000..5c736a0 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-4-n64.r @@ -0,0 +1,8 @@ +Relocation section '.rel.dyn' at offset 0x11000 contains 2 entries: + Offset Info Type Sym. Value Sym. Name +000000080800 000000000080 R_MIPS_IRELATIVE + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE +000000000000 000000000000 R_MIPS_NONE + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE diff --git a/ld/testsuite/ld-mips-elf/ifunc-4-n64.sym b/ld/testsuite/ld-mips-elf/ifunc-4-n64.sym new file mode 100644 index 0000000..b4b950e --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-4-n64.sym @@ -0,0 +1,29 @@ +Symbol table '.symtab' contains 27 entries: + Num: Value Size Type Bind Vis Ndx Name + 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND + 1: 0000000000080000 0 SECTION LOCAL DEFAULT 1 + 2: 0000000000080400 0 SECTION LOCAL DEFAULT 2 + 3: 0000000000080800 0 SECTION LOCAL DEFAULT 3 + 4: 0000000000081000 0 SECTION LOCAL DEFAULT 4 + 5: 0000000000081020 0 SECTION LOCAL DEFAULT 5 + 6: 0000000000000000 0 SECTION LOCAL DEFAULT 6 + 7: 0000000000000000 0 SECTION LOCAL DEFAULT 7 + 8: 0000000000000000 0 SECTION LOCAL DEFAULT 8 + 9: 0000000000000000 0 FILE LOCAL DEFAULT ABS ifunc_ref_main_1.c + 10: 0000000000000000 0 FILE LOCAL DEFAULT ABS ifunc.c + 11: 0000000000080430 36 FUNC LOCAL DEFAULT 2 f1_a + 12: 0000000000080454 36 FUNC LOCAL DEFAULT 2 f1_b + 13: 0000000000080478 36 FUNC LOCAL DEFAULT 2 f1_c + 14: 00000000000804d0 0 NOTYPE LOCAL DEFAULT 2 \$L8 + 15: 00000000000804d8 0 NOTYPE LOCAL DEFAULT 2 \$L9 + 16: 00000000000804f8 0 NOTYPE LOCAL DEFAULT 2 \$L10 + 17: 0000000000080520 0 NOTYPE LOCAL DEFAULT 2 \$L13 + 18: 0000000000080518 0 NOTYPE LOCAL DEFAULT 2 \$L12 + 19: 0000000000000000 0 FILE LOCAL DEFAULT ABS ifunc_ref.c + 20: 0000000000000000 0 FILE LOCAL DEFAULT ABS + 21: 0000000000080000 32 FUNC LOCAL DEFAULT 1 .iplt.func1 + 22: 000000000008049c 156 IFUNC GLOBAL DEFAULT 2 func1 + 23: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _start + 24: 0000000000080400 48 FUNC GLOBAL DEFAULT 2 main + 25: 0000000000080540 48 FUNC GLOBAL DEFAULT 2 ref1 + 26: 000000000008049c 156 FUNC GLOBAL DEFAULT 2 func1_ifunc diff --git a/ld/testsuite/ld-mips-elf/ifunc-4-n64.t b/ld/testsuite/ld-mips-elf/ifunc-4-n64.t new file mode 100644 index 0000000..bf5a2d2 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-4-n64.t @@ -0,0 +1,11 @@ +tmpdir/ifunc-4-n64: file format elf64-tradbigmips + + +Disassembly of section .iplt: + +0000000000080000 <.iplt.func1>: + 80000: 3c0f0008 lui t3,0x8 + 80004: ddf90800 ld t9,2048\(t3\) + 80008: 03200008 jr t9 + 8000c: 00000000 nop + ... diff --git a/ld/testsuite/ld-mips-elf/ifunc-4-o32.r b/ld/testsuite/ld-mips-elf/ifunc-4-o32.r new file mode 100644 index 0000000..9259df6 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-4-o32.r @@ -0,0 +1,4 @@ +Relocation section '.rel.dyn' at offset 0x11000 contains 2 entries: + Offset Info Type Sym.Value Sym. Name +00080800 00000080 R_MIPS_IRELATIVE +00000000 00000000 R_MIPS_NONE diff --git a/ld/testsuite/ld-mips-elf/ifunc-4-o32.sym b/ld/testsuite/ld-mips-elf/ifunc-4-o32.sym new file mode 100644 index 0000000..e88cc29 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-4-o32.sym @@ -0,0 +1,24 @@ +Symbol table '.symtab' contains 22 entries: + Num: Value Size Type Bind Vis Ndx Name + 0: 00000000 0 NOTYPE LOCAL DEFAULT UND + 1: 00080000 0 SECTION LOCAL DEFAULT 1 + 2: 00080400 0 SECTION LOCAL DEFAULT 2 + 3: 00080800 0 SECTION LOCAL DEFAULT 3 + 4: 00081000 0 SECTION LOCAL DEFAULT 4 + 5: 00081010 0 SECTION LOCAL DEFAULT 5 + 6: 00000000 0 SECTION LOCAL DEFAULT 6 + 7: 00000000 0 SECTION LOCAL DEFAULT 7 + 8: 00000000 0 SECTION LOCAL DEFAULT 8 + 9: 00000000 0 FILE LOCAL DEFAULT ABS ifunc_ref_main_1.c + 10: 00000000 0 FILE LOCAL DEFAULT ABS ifunc.c + 11: 00080430 36 FUNC LOCAL DEFAULT 2 f1_a + 12: 00080454 36 FUNC LOCAL DEFAULT 2 f1_b + 13: 00080478 36 FUNC LOCAL DEFAULT 2 f1_c + 14: 00000000 0 FILE LOCAL DEFAULT ABS ifunc_ref.c + 15: 00000000 0 FILE LOCAL DEFAULT ABS + 16: 00080000 20 FUNC LOCAL DEFAULT 1 .iplt.func1 + 17: 0008049c 156 IFUNC GLOBAL DEFAULT 2 func1 + 18: 00000000 0 NOTYPE GLOBAL DEFAULT UND _start + 19: 00080400 48 FUNC GLOBAL DEFAULT 2 main + 20: 00080540 48 FUNC GLOBAL DEFAULT 2 ref1 + 21: 0008049c 156 FUNC GLOBAL DEFAULT 2 func1_ifunc diff --git a/ld/testsuite/ld-mips-elf/ifunc-4-o32.t b/ld/testsuite/ld-mips-elf/ifunc-4-o32.t new file mode 100644 index 0000000..bc71cb0 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-4-o32.t @@ -0,0 +1,11 @@ +tmpdir/ifunc-4-o32: file format elf32-tradbigmips + + +Disassembly of section .iplt: + +00080000 <.iplt.func1>: + 80000: 3c0f0008 lui t7,0x8 + 80004: 8df90800 lw t9,2048\(t7\) + 80008: 00000000 nop + 8000c: 03200008 jr t9 + 80010: 00000000 nop diff --git a/ld/testsuite/ld-mips-elf/ifunc-5-n32.g b/ld/testsuite/ld-mips-elf/ifunc-5-n32.g new file mode 100644 index 0000000..e69de29 diff --git a/ld/testsuite/ld-mips-elf/ifunc-5-n32.r b/ld/testsuite/ld-mips-elf/ifunc-5-n32.r new file mode 100644 index 0000000..64d10f6 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-5-n32.r @@ -0,0 +1 @@ +There are no relocations in this file. diff --git a/ld/testsuite/ld-mips-elf/ifunc-5-n32.sym b/ld/testsuite/ld-mips-elf/ifunc-5-n32.sym new file mode 100644 index 0000000..3756726 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-5-n32.sym @@ -0,0 +1,5 @@ +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + 2 0: 00000030 60 FUNC GLOBAL DEFAULT 1 ref1 + 4 0: 0000000c 28 IFUNC GLOBAL DEFAULT 1 func1 + 3 1: 0000000c 28 FUNC GLOBAL DEFAULT 1 func1_ifunc diff --git a/ld/testsuite/ld-mips-elf/ifunc-5-n64.g b/ld/testsuite/ld-mips-elf/ifunc-5-n64.g new file mode 100644 index 0000000..e69de29 diff --git a/ld/testsuite/ld-mips-elf/ifunc-5-n64.r b/ld/testsuite/ld-mips-elf/ifunc-5-n64.r new file mode 100644 index 0000000..64d10f6 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-5-n64.r @@ -0,0 +1 @@ +There are no relocations in this file. diff --git a/ld/testsuite/ld-mips-elf/ifunc-5-n64.sym b/ld/testsuite/ld-mips-elf/ifunc-5-n64.sym new file mode 100644 index 0000000..c28e09a --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-5-n64.sym @@ -0,0 +1,5 @@ +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + 2 0: 0000000000000030 60 FUNC GLOBAL DEFAULT 1 ref1 + 4 0: 000000000000000c 28 IFUNC GLOBAL DEFAULT 1 func1 + 3 1: 000000000000000c 28 FUNC GLOBAL DEFAULT 1 func1_ifunc diff --git a/ld/testsuite/ld-mips-elf/ifunc-5-o32.g b/ld/testsuite/ld-mips-elf/ifunc-5-o32.g new file mode 100644 index 0000000..e69de29 diff --git a/ld/testsuite/ld-mips-elf/ifunc-5-o32.r b/ld/testsuite/ld-mips-elf/ifunc-5-o32.r new file mode 100644 index 0000000..64d10f6 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-5-o32.r @@ -0,0 +1 @@ +There are no relocations in this file. diff --git a/ld/testsuite/ld-mips-elf/ifunc-5-o32.sym b/ld/testsuite/ld-mips-elf/ifunc-5-o32.sym new file mode 100644 index 0000000..66a60f7 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-5-o32.sym @@ -0,0 +1,6 @@ +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + 3 0: 00000040 76 FUNC GLOBAL DEFAULT 1 ref1 + 5 0: 0000000c 40 IFUNC GLOBAL DEFAULT 1 func1 + 2 0: 00000000 0 SECTION GLOBAL DEFAULT ABS _gp_disp + 4 1: 0000000c 40 FUNC GLOBAL DEFAULT 1 func1_ifunc diff --git a/ld/testsuite/ld-mips-elf/ifunc-6-n32.r b/ld/testsuite/ld-mips-elf/ifunc-6-n32.r new file mode 100644 index 0000000..e19667e --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-6-n32.r @@ -0,0 +1,3 @@ +Relocation section '.rel.dyn' at offset 0x12000 contains 1 entries: + Offset Info Type Sym.Value Sym. Name +00000800 00000080 R_MIPS_IRELATIVE diff --git a/ld/testsuite/ld-mips-elf/ifunc-6-n32.sym b/ld/testsuite/ld-mips-elf/ifunc-6-n32.sym new file mode 100644 index 0000000..6b930fc --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-6-n32.sym @@ -0,0 +1,6 @@ +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + 4 0: 00000070 60 FUNC GLOBAL DEFAULT 1 ref1 + 2 0: 00000400 28 FUNC GLOBAL DEFAULT 1 func1 + 1 1: 00000001 0 SECTION GLOBAL DEFAULT ABS _DYNAMIC_LINKING + 3 2: 00001000 0 OBJECT GLOBAL DEFAULT 11 __RLD_MAP diff --git a/ld/testsuite/ld-mips-elf/ifunc-6-n64.r b/ld/testsuite/ld-mips-elf/ifunc-6-n64.r new file mode 100644 index 0000000..8b6e5ba --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-6-n64.r @@ -0,0 +1,5 @@ +Relocation section '.rel.dyn' at offset 0x12000 contains 1 entries: + Offset Info Type Sym. Value Sym. Name +000000000800 000000000080 R_MIPS_IRELATIVE + Type2: R_MIPS_NONE + Type3: R_MIPS_NONE diff --git a/ld/testsuite/ld-mips-elf/ifunc-6-n64.sym b/ld/testsuite/ld-mips-elf/ifunc-6-n64.sym new file mode 100644 index 0000000..11e8f97 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-6-n64.sym @@ -0,0 +1,6 @@ +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + 4 0: 0000000000000070 60 FUNC GLOBAL DEFAULT 1 ref1 + 2 0: 0000000000000400 28 FUNC GLOBAL DEFAULT 1 func1 + 1 1: 0000000000000001 0 SECTION GLOBAL DEFAULT ABS _DYNAMIC_LINKING + 3 2: 0000000000001000 0 OBJECT GLOBAL DEFAULT 11 __RLD_MAP diff --git a/ld/testsuite/ld-mips-elf/ifunc-6-o32.r b/ld/testsuite/ld-mips-elf/ifunc-6-o32.r new file mode 100644 index 0000000..e19667e --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-6-o32.r @@ -0,0 +1,3 @@ +Relocation section '.rel.dyn' at offset 0x12000 contains 1 entries: + Offset Info Type Sym.Value Sym. Name +00000800 00000080 R_MIPS_IRELATIVE diff --git a/ld/testsuite/ld-mips-elf/ifunc-6-o32.sym b/ld/testsuite/ld-mips-elf/ifunc-6-o32.sym new file mode 100644 index 0000000..8cb795d --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-6-o32.sym @@ -0,0 +1,6 @@ +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + 4 0: 00000080 76 FUNC GLOBAL DEFAULT 1 ref1 + 2 0: 00000400 40 FUNC GLOBAL DEFAULT 1 func1 + 1 1: 00000001 0 SECTION GLOBAL DEFAULT ABS _DYNAMIC_LINKING + 3 2: 00001000 0 OBJECT GLOBAL DEFAULT 11 __RLD_MAP diff --git a/ld/testsuite/ld-mips-elf/ifunc-dyn-def.s b/ld/testsuite/ld-mips-elf/ifunc-dyn-def.s new file mode 100644 index 0000000..9b5d2a8 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-dyn-def.s @@ -0,0 +1,67 @@ + .file 1 "ifunc.c" + .section .mdebug.abi32 + .previous + .nan legacy + .gnu_attribute 4, 1 + .abicalls + .text + .align 2 + .set nomips16 + .set nomicromips + .ent f1_a + .type f1_a, @function +f1_a: + nop + + .set macro + .set reorder + .end f1_a + .size f1_a, .-f1_a + .align 2 + .set nomips16 + .set nomicromips + .ent f1_b + .type f1_b, @function +f1_b: + nop + + .set macro + .set reorder + .end f1_b + .size f1_b, .-f1_b + .align 2 + .set nomips16 + .set nomicromips + .ent f1_c + .type f1_c, @function +f1_c: + .frame $fp,8,$31 # vars= 0, regs= 1/0, args= 0, gp= 0 + nop + + .set macro + .set reorder + .end f1_c + .size f1_c, .-f1_c + .align 2 + .globl func1_ifunc + .set nomips16 + .set nomicromips + .ent func1_ifunc + .type func1_ifunc, @function +func1_ifunc: + lw $2,%got(f1_a)($28) + addiu $2,$2,%lo(f1_a) + lw $2,%got(f1_b)($28) + addiu $2,$2,%lo(f1_b) + lw $2,%got(f1_c)($28) + addiu $2,$2,%lo(f1_c) + nop + + .set macro + .set reorder + .end func1_ifunc + .size func1_ifunc, .-func1_ifunc + .globl func1 + .type func1, @gnu_indirect_function + func1 = func1_ifunc + .ident "GCC: (GNU) 4.9.0 20130917 (experimental)" diff --git a/ld/testsuite/ld-mips-elf/ifunc-dyn-main.s b/ld/testsuite/ld-mips-elf/ifunc-dyn-main.s new file mode 100644 index 0000000..8c12176 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-dyn-main.s @@ -0,0 +1,39 @@ + .file 1 "ifunc_ref_main_2.c" + .section .mdebug.abi32 + .previous + .nan legacy + .gnu_attribute 4, 1 + .abicalls + .option pic0 + .text + .align 2 + .globl main + .set nomips16 + .set nomicromips + .ent main + .type main, @function +main: + .frame $fp,32,$31 # vars= 0, regs= 2/0, args= 16, gp= 8 + .mask 0xc0000000,-4 + .fmask 0x00000000,0 + .set noreorder + .set nomacro + addiu $sp,$sp,-32 + sw $31,28($sp) + sw $fp,24($sp) + move $fp,$sp + jal ref1 + nop + + move $sp,$fp + lw $31,28($sp) + lw $fp,24($sp) + addiu $sp,$sp,32 + j $31 + nop + + .set macro + .set reorder + .end main + .size main, .-main + .ident "GCC: (GNU) 4.9.0 20130930 (experimental)" diff --git a/ld/testsuite/ld-mips-elf/ifunc-dyn-ref.s b/ld/testsuite/ld-mips-elf/ifunc-dyn-ref.s new file mode 100644 index 0000000..d562096 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-dyn-ref.s @@ -0,0 +1,43 @@ + .file 1 "ifunc_ref.c" + .section .mdebug.abi32 + .previous + .nan legacy + .gnu_attribute 4, 1 + .abicalls + .text + .align 2 + .globl ref1 + .set nomips16 + .set nomicromips + .ent ref1 + .type ref1, @function +ref1: + .frame $fp,32,$31 # vars= 0, regs= 2/0, args= 16, gp= 8 + .mask 0xc0000000,-4 + .fmask 0x00000000,0 + .set noreorder + .cpload $25 + .set nomacro + addiu $sp,$sp,-32 + sw $31,28($sp) + sw $fp,24($sp) + move $fp,$sp + .cprestore 16 + lw $2,%call16(func1)($28) + move $25,$2 + jalr $25 + nop + + lw $28,16($fp) + move $sp,$fp + lw $31,28($sp) + lw $fp,24($sp) + addiu $sp,$sp,32 + j $31 + nop + + .set macro + .set reorder + .end ref1 + .size ref1, .-ref1 + .ident "GCC: (GNU) 4.9.0 20130930 (experimental)" diff --git a/ld/testsuite/ld-mips-elf/ifunc-dyn.ld b/ld/testsuite/ld-mips-elf/ifunc-dyn.ld new file mode 100644 index 0000000..ea79ec8 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-dyn.ld @@ -0,0 +1,25 @@ +ENTRY(_start) +SECTIONS +{ + . = ALIGN (0x400); + .text : { *(.text) } + + . = ALIGN (0x400); + .iplt : { *(.iplt) } + + . = ALIGN (0x400); + .igot.plt : { *(.igot.plt) } + + . = ALIGN (0x400); + .got : { *(.got) } + + . = ALIGN (0x400); + .data : { *(.data) } + + . = ALIGN (0x1000); + .rel.dyn : + { + *(.rel.*) + } + +} diff --git a/ld/testsuite/ld-mips-elf/ifunc-iplt-0x400000.t b/ld/testsuite/ld-mips-elf/ifunc-iplt-0x400000.t new file mode 100644 index 0000000..57f60b8 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-iplt-0x400000.t @@ -0,0 +1,11 @@ +tmpdir/ifunc-iplt-0x400000: file format elf64-tradbigmips + + +Disassembly of section .iplt: + +0000000000400148 <.iplt.func1>: + 400148: 3c0f0041 lui t3,0x41 + 40014c: ddf902e0 ld t9,736\(t3\) + 400150: 03200008 jr t9 + 400154: 00000000 nop + ... diff --git a/ld/testsuite/ld-mips-elf/ifunc-iplt-0x400000000.t b/ld/testsuite/ld-mips-elf/ifunc-iplt-0x400000000.t new file mode 100644 index 0000000..a0e9aaf --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-iplt-0x400000000.t @@ -0,0 +1,13 @@ +tmpdir/ifunc-iplt-0x400000000: file format elf64-tradbigmips + + +Disassembly of section .iplt: + +0000000400000148 <.iplt.func1>: + 400000148: 3c0f0004 lui t3,0x4 + 40000014c: 65ef0001 daddiu t3,t3,1 + 400000150: 000f7c38 dsll t3,t3,0x10 + 400000154: ddf902e0 ld t9,736\(t3\) + 400000158: 03200008 jr t9 + 40000015c: 00000000 nop + ... diff --git a/ld/testsuite/ld-mips-elf/ifunc-iplt-0x4000000000000.t b/ld/testsuite/ld-mips-elf/ifunc-iplt-0x4000000000000.t new file mode 100644 index 0000000..e559746 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-iplt-0x4000000000000.t @@ -0,0 +1,14 @@ +tmpdir/ifunc-iplt-0x4000000000000: file format elf64-tradbigmips + + +Disassembly of section .iplt: + +0004000000000148 <.iplt.func1>: + 4000000000148: 3c0f0004 lui t3,0x4 + 400000000014c: 65ef0000 daddiu t3,t3,0 + 4000000000150: 000f7c38 dsll t3,t3,0x10 + 4000000000154: 65ef0001 daddiu t3,t3,1 + 4000000000158: 000f7c38 dsll t3,t3,0x10 + 400000000015c: ddf902e0 ld t9,736\(t3\) + 4000000000160: 03200008 jr t9 + 4000000000164: 00000000 nop diff --git a/ld/testsuite/ld-mips-elf/ifunc-iplt.ld b/ld/testsuite/ld-mips-elf/ifunc-iplt.ld new file mode 100644 index 0000000..c013c77 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-iplt.ld @@ -0,0 +1,26 @@ +ENTRY(_start) +SECTIONS +{ + . = ALIGN (0x400); + .iplt : { *(.iplt) } + + . = ALIGN (0x400); + .text : { *(.text) } + + . = ALIGN (0x400); + .igot.plt : { *(.igot.plt) } + + . = ALIGN (0x400); + .got : { *(.got) } + + . = ALIGN (0x400); + .data : { *(.data) } + + . = ALIGN (0x1000); + .rel.dyn : + { + *(.rel.*) + } +/* /DISCARD/ : { *(*) } */ + +} diff --git a/ld/testsuite/ld-mips-elf/ifunc-static-def.s b/ld/testsuite/ld-mips-elf/ifunc-static-def.s new file mode 100644 index 0000000..cf84696 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-static-def.s @@ -0,0 +1,155 @@ + .file 1 "ifunc.c" + .section .mdebug.abi32 + .previous + .nan legacy + .gnu_attribute 4, 1 + .abicalls + .option pic0 + .text + .align 2 + .set nomips16 + .set nomicromips + .ent f1_a + .type f1_a, @function +f1_a: + .frame $fp,8,$31 # vars= 0, regs= 1/0, args= 0, gp= 0 + .mask 0x40000000,-4 + .fmask 0x00000000,0 + .set noreorder + .set nomacro + addiu $sp,$sp,-8 + sw $fp,4($sp) + move $fp,$sp + li $2,1 # 0x1 + move $sp,$fp + lw $fp,4($sp) + addiu $sp,$sp,8 + j $31 + nop + + .set macro + .set reorder + .end f1_a + .size f1_a, .-f1_a + .align 2 + .set nomips16 + .set nomicromips + .ent f1_b + .type f1_b, @function +f1_b: + .frame $fp,8,$31 # vars= 0, regs= 1/0, args= 0, gp= 0 + .mask 0x40000000,-4 + .fmask 0x00000000,0 + .set noreorder + .set nomacro + addiu $sp,$sp,-8 + sw $fp,4($sp) + move $fp,$sp + li $2,2 # 0x2 + move $sp,$fp + lw $fp,4($sp) + addiu $sp,$sp,8 + j $31 + nop + + .set macro + .set reorder + .end f1_b + .size f1_b, .-f1_b + .align 2 + .set nomips16 + .set nomicromips + .ent f1_c + .type f1_c, @function +f1_c: + .frame $fp,8,$31 # vars= 0, regs= 1/0, args= 0, gp= 0 + .mask 0x40000000,-4 + .fmask 0x00000000,0 + .set noreorder + .set nomacro + addiu $sp,$sp,-8 + sw $fp,4($sp) + move $fp,$sp + li $2,3 # 0x3 + move $sp,$fp + lw $fp,4($sp) + addiu $sp,$sp,8 + j $31 + nop + + .set macro + .set reorder + .end f1_c + .size f1_c, .-f1_c + .align 2 + .globl func1_ifunc + .set nomips16 + .set nomicromips + .ent func1_ifunc + .type func1_ifunc, @function +func1_ifunc: + .frame $fp,432,$31 # vars= 400, regs= 2/0, args= 16, gp= 8 + .mask 0xc0000000,-4 + .fmask 0x00000000,0 + .set noreorder + .set nomacro + addiu $sp,$sp,-432 + sw $31,428($sp) + sw $fp,424($sp) + move $fp,$sp + addiu $2,$fp,28 + move $4,$2 + nop + + beq $2,$0,$L8 + nop + + li $2,48 # 0x30 + sw $2,24($fp) + j $L9 + nop + +$L8: + li $2,3 # 0x3 + sw $2,24($fp) +$L9: + lw $2,24($fp) + andi $2,$2,0xf0 + beq $2,$0,$L10 + nop + + lui $2,%hi(f1_a) + addiu $2,$2,%lo(f1_a) + j $L13 + nop + +$L10: + lw $2,24($fp) + andi $2,$2,0xf + beq $2,$0,$L12 + nop + + lui $2,%hi(f1_b) + addiu $2,$2,%lo(f1_b) + j $L13 + nop + +$L12: + lui $2,%hi(f1_c) + addiu $2,$2,%lo(f1_c) +$L13: + move $sp,$fp + lw $31,428($sp) + lw $fp,424($sp) + addiu $sp,$sp,432 + j $31 + nop + + .set macro + .set reorder + .end func1_ifunc + .size func1_ifunc, .-func1_ifunc + .globl func1 + .type func1, @gnu_indirect_function + func1 = func1_ifunc + .ident "GCC: (GNU) 4.9.0 20130930 (experimental)" diff --git a/ld/testsuite/ld-mips-elf/ifunc-static-main.s b/ld/testsuite/ld-mips-elf/ifunc-static-main.s new file mode 100644 index 0000000..2093a42 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-static-main.s @@ -0,0 +1,39 @@ + .file 1 "ifunc_ref_main_1.c" + .section .mdebug.abi32 + .previous + .nan legacy + .gnu_attribute 4, 1 + .abicalls + .option pic0 + .text + .align 2 + .globl main + .set nomips16 + .set nomicromips + .ent main + .type main, @function +main: + .frame $fp,32,$31 # vars= 0, regs= 2/0, args= 16, gp= 8 + .mask 0xc0000000,-4 + .fmask 0x00000000,0 + .set noreorder + .set nomacro + addiu $sp,$sp,-32 + sw $31,28($sp) + sw $fp,24($sp) + move $fp,$sp + jal func1 + nop + + move $sp,$fp + lw $31,28($sp) + lw $fp,24($sp) + addiu $sp,$sp,32 + j $31 + nop + + .set macro + .set reorder + .end main + .size main, .-main + .ident "GCC: (GNU) 4.9.0 20130930 (experimental)" diff --git a/ld/testsuite/ld-mips-elf/ifunc-static-ref.s b/ld/testsuite/ld-mips-elf/ifunc-static-ref.s new file mode 100644 index 0000000..e17db14 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-static-ref.s @@ -0,0 +1,39 @@ + .file 1 "ifunc_ref.c" + .section .mdebug.abi32 + .previous + .nan legacy + .gnu_attribute 4, 1 + .abicalls + .option pic0 + .text + .align 2 + .globl ref1 + .set nomips16 + .set nomicromips + .ent ref1 + .type ref1, @function +ref1: + .frame $fp,32,$31 # vars= 0, regs= 2/0, args= 16, gp= 8 + .mask 0xc0000000,-4 + .fmask 0x00000000,0 + .set noreorder + .set nomacro + addiu $sp,$sp,-32 + sw $31,28($sp) + sw $fp,24($sp) + move $fp,$sp + jal func1 + nop + + move $sp,$fp + lw $31,28($sp) + lw $fp,24($sp) + addiu $sp,$sp,32 + j $31 + nop + + .set macro + .set reorder + .end ref1 + .size ref1, .-ref1 + .ident "GCC: (GNU) 4.9.0 20130930 (experimental)" diff --git a/ld/testsuite/ld-mips-elf/ifunc-static.ld b/ld/testsuite/ld-mips-elf/ifunc-static.ld new file mode 100644 index 0000000..0579e69 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/ifunc-static.ld @@ -0,0 +1,27 @@ +ENTRY(_start) +SECTIONS +{ + . = 0x80000; + . = ALIGN (0x400); + .iplt : { *(.iplt) } + + . = ALIGN (0x400); + .text : { *(.text) } + + . = ALIGN (0x400); + .igot.plt : { *(.igot.plt) } + + . = ALIGN (0x400); + .got : { *(.got) } + + . = ALIGN (0x400); + .data : { *(.data) } + + . = ALIGN (0x1000); + .rel.dyn : + { + *(.rel.*) + } +/* /DISCARD/ : { *(*) } */ + +} diff --git a/ld/testsuite/ld-mips-elf/libifunc-1-n32.sym b/ld/testsuite/ld-mips-elf/libifunc-1-n32.sym new file mode 100644 index 0000000..88d7e5d --- /dev/null +++ b/ld/testsuite/ld-mips-elf/libifunc-1-n32.sym @@ -0,0 +1,4 @@ +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + 3 0: 0000000c 28 FUNC GLOBAL DEFAULT 1 func1_ifunc + 2 0: 0000000c 28 IFUNC GLOBAL DEFAULT 1 func1 diff --git a/ld/testsuite/ld-mips-elf/libifunc-1-n64.sym b/ld/testsuite/ld-mips-elf/libifunc-1-n64.sym new file mode 100644 index 0000000..7236950 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/libifunc-1-n64.sym @@ -0,0 +1,4 @@ +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + 3 0: 000000000000000c 28 FUNC GLOBAL DEFAULT 1 func1_ifunc + 2 0: 000000000000000c 28 IFUNC GLOBAL DEFAULT 1 func1 diff --git a/ld/testsuite/ld-mips-elf/libifunc-1-o32.sym b/ld/testsuite/ld-mips-elf/libifunc-1-o32.sym new file mode 100644 index 0000000..b5fff26 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/libifunc-1-o32.sym @@ -0,0 +1,4 @@ +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + 3 0: 0000000c 40 FUNC GLOBAL DEFAULT 1 func1_ifunc + 2 0: 0000000c 40 IFUNC GLOBAL DEFAULT 1 func1 diff --git a/ld/testsuite/ld-mips-elf/libifunc-2-n32.sym b/ld/testsuite/ld-mips-elf/libifunc-2-n32.sym new file mode 100644 index 0000000..2c1e84e --- /dev/null +++ b/ld/testsuite/ld-mips-elf/libifunc-2-n32.sym @@ -0,0 +1,4 @@ +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + 2 0: 00000000 60 FUNC GLOBAL DEFAULT 1 ref1 + 3 0: 00000040 0 FUNC GLOBAL DEFAULT UND func1 diff --git a/ld/testsuite/ld-mips-elf/libifunc-2-n64.sym b/ld/testsuite/ld-mips-elf/libifunc-2-n64.sym new file mode 100644 index 0000000..3bd53fd --- /dev/null +++ b/ld/testsuite/ld-mips-elf/libifunc-2-n64.sym @@ -0,0 +1,4 @@ +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + 2 0: 0000000000000000 60 FUNC GLOBAL DEFAULT 1 ref1 + 3 0: 0000000000000040 0 FUNC GLOBAL DEFAULT UND func1 diff --git a/ld/testsuite/ld-mips-elf/libifunc-2-o32.sym b/ld/testsuite/ld-mips-elf/libifunc-2-o32.sym new file mode 100644 index 0000000..b831edd --- /dev/null +++ b/ld/testsuite/ld-mips-elf/libifunc-2-o32.sym @@ -0,0 +1,5 @@ +Symbol table for image: + Num Buc: Value Size Type Bind Vis Ndx Name + 3 0: 00000000 76 FUNC GLOBAL DEFAULT 1 ref1 + 4 0: 00000050 0 FUNC GLOBAL DEFAULT UND func1 + 2 0: 00000000 0 SECTION GLOBAL DEFAULT ABS _gp_disp diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp index a66a289..9c7dfa4 100644 --- a/ld/testsuite/ld-mips-elf/mips-elf.exp +++ b/ld/testsuite/ld-mips-elf/mips-elf.exp @@ -837,3 +837,4 @@ run_dump_test "attr-gnu-8-12" run_dump_test "attr-gnu-8-20" run_dump_test "attr-gnu-8-21" run_dump_test "attr-gnu-8-22" + diff --git a/ld/testsuite/ld-mips-elf/mips-ifunc.exp b/ld/testsuite/ld-mips-elf/mips-ifunc.exp new file mode 100644 index 0000000..c346f0b --- /dev/null +++ b/ld/testsuite/ld-mips-elf/mips-ifunc.exp @@ -0,0 +1,151 @@ +# Expect script for MIPS IFUNC linker tests +# Copyright 2013 +# Free Software Foundation, Inc. +# +# This file is part of the GNU Binutils. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. +# + +if {![istarget mips*-*-*] || ![is_elf_format]} { + return +} + +# General setup +############################################# +set has_newabi [expr [istarget *-*-irix6*] \ + || [istarget mips*-*-linux*] \ + || [istarget mips*-sde-elf*]] +set linux_gnu [expr [istarget mips*-*-linux*]] +set embedded_elf [expr [istarget mips*-*-elf]] + +# Set defaults. +set abi_asflags(o32) "" +set abi_asflags(n32) "-march=from-abi -n32 -EB" +set abi_asflags(n64) "-march=from-abi -64 -EB" +set abi_ldflags(o32) "" +set abi_ldflags(n32) -melf32bmipn32 +set abi_ldflags(n64) -melf64bmip + +# Override as needed. +if { [istarget *-*-irix6*] } { + set abi_asflags(o32) "-32 -EB" + set abi_ldflags(o32) -melf32bsmip +} elseif { [istarget mips64*-linux*] } { + set abi_asflags(o32) "-32 -EB" + set abi_ldflags(o32) -melf32btsmip +} elseif { [istarget mips64*-*freebsd*] } { + set abi_asflags(o32) "-32 -EB" + set abi_ldflags(o32) -melf32btsmip_fbsd +} +if { [istarget mips*-*-linux*] || [istarget mips*-sde-elf*] } { + set abi_ldflags(n32) -melf32btsmipn32 + set abi_ldflags(n64) -melf64btsmip +} elseif { [istarget mips64*-*freebsd*] } { + set abi_ldflags(n32) -melf32btsmipn32_fbsd + set abi_ldflags(n64) -melf64btsmip_fbsd +} +############################################# + + +# STT_GNU_IFUNC testing: +# +# 1. Dso with ifunc defined code +# 2. Dso that references external ifunc'ed routines +# 3. Dynamic executable with ifunc defined code +# 4. Static executable with ifunc defined and referenced code +# 5. Dso with with ifunc defined and referenced code +# 6. Dynamic executable with ifunc defined and referenced code +# STT_GNU_IFUNC tests. +set abis [concat o32 [expr {$has_newabi ? "n32 n64" : ""}]] +foreach { abi } $abis { + run_ld_link_tests [list \ + [list \ + "IFUNC 1 (Simple dso with def) ${abi}" \ + "$abi_ldflags($abi) -shared -T ifunc-dyn.ld" "" \ + "$abi_asflags($abi)" \ + [list ifunc-dyn-def.s] \ + [list "readelf -Ds libifunc-1-${abi}.sym"] \ + "libifunc-1-${abi}.so" \ + ] \ + [list \ + "IFUNC 2 (Simple dso with ref) ${abi}" \ + "$abi_ldflags($abi) -shared -T ifunc-dyn.ld" "" \ + "$abi_asflags($abi)" \ + [list ifunc-dyn-ref.s] \ + [list "readelf -Ds libifunc-2-${abi}.sym"] \ + "libifunc-2-${abi}.so" \ + ] \ + [list \ + "IFUNC 3 (Simple dynamic executable with def) ${abi}" \ + "$abi_ldflags($abi) -Bdynamic -L./tmpdir -lifunc-2-${abi} -T ifunc-dyn.ld" "" \ + "$abi_asflags($abi)" \ + [list ifunc-dyn-main.s ifunc-dyn-def.s] \ + [list "readelf -Ds ifunc-3-${abi}.sym" \ + "readelf -r ifunc-3-${abi}.r" \ + "objdump -dj.iplt ifunc-3-${abi}.t"] \ + "ifunc-3-${abi}" \ + ] \ + [list \ + "IFUNC 4 (Simple static executable with def and ref) ${abi}" \ + "$abi_ldflags($abi) -Bstatic -T ifunc-static.ld" "" \ + "$abi_asflags($abi) -non_shared" \ + [list ifunc-static-main.s ifunc-static-def.s ifunc-static-ref.s] \ + [list "readelf -s ifunc-4-${abi}.sym" \ + "readelf -r ifunc-4-${abi}.r" \ + "objdump -dj.iplt ifunc-4-${abi}.t"] \ + "ifunc-4-${abi}" \ + ] \ + [list \ + "IFUNC 5 (Dynamic shared object with def and ref) ${abi}" \ + "$abi_ldflags($abi) -shared -T ifunc-dyn.ld" "" \ + "$abi_asflags($abi) -KPIC" \ + [list ifunc-dyn-def.s ifunc-dyn-ref.s] \ + [list "readelf -Ds ifunc-5-${abi}.sym" \ + "readelf -r ifunc-5-${abi}.r"] \ + "ifunc-5-${abi}" \ + ] \ + [list \ + "IFUNC 6 (Dynamic executable with def and ref) ${abi}" \ + "$abi_ldflags($abi) -Bdynamic -L./tmpdir -lifunc-2-${abi} -T ifunc-dyn.ld" "" \ + "$abi_asflags($abi)" \ + [list ifunc-dyn-main.s ifunc-dyn-def.s ifunc-dyn-ref.s] \ + [list "readelf -Ds ifunc-6-${abi}.sym" \ + "readelf -r ifunc-6-${abi}.r"] \ + "ifunc-6-${abi}" \ + ] \ + ] +} + +# IPLT sequences change based on how big the address of the +# .igot.plt section is based on Mips loading immediate values. +# +set addrs { "0x400000" "0x400000000" "0x4000000000000" } +foreach { addr } $addrs { + run_ld_link_tests [list \ + [list \ + "IFUNC IPLT (Simple static executable with def and ref) ${addr}" \ + "$abi_ldflags(n64) -Bstatic -Ttext-segment ${addr}" "" \ + "$abi_asflags(n64) -non_shared" \ + [list ifunc-static-main.s ifunc-static-def.s ifunc-static-ref.s] \ + [list "objdump -dj.iplt ifunc-iplt-${addr}.t"] \ + "ifunc-iplt-${addr}" \ + ] \ + ] +} + + +
Attachment:
ifunc_abi.txt
Description: ifunc_abi.txt
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |