From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Mark P. Mitchell" To: binutils@sourceware.cygnus.com Subject: elf32-mips.c patch Date: Mon, 09 Aug 1999 23:29:00 -0000 Message-id: <199908100629.AAA770945@n02.acl.lanl.gov> X-SW-Source: 1999-08/msg00075.html This patch is the result of an audit of the changes in the rel.dyn generation from the pre-N32 code to the present, as well as conversation with Ian. Checked in after verification on IRIX6. -- Mark Tue Aug 10 00:21:08 1999 Mark P. Mitchell * elf32-mips.c (mips_elf_create_dynamic_relocation): Change prototype. Handle local symbols. Add commentary. (mips_elf_calculate_relocation): Adjust accordingly. (_bfd_mips_elf_check_relocs): Handle local symbols in R_MIPS_32 relocations. Index: elf32-mips.c =================================================================== RCS file: /cvs/binutils/binutils/bfd/elf32-mips.c,v retrieving revision 1.46 diff -c -p -r1.46 elf32-mips.c *** elf32-mips.c 1999/08/09 22:45:38 1.46 --- elf32-mips.c 1999/08/10 06:23:15 *************** static bfd_vma mips_elf_create_local_got *** 192,200 **** PARAMS ((bfd *, struct mips_got_info *, asection *, bfd_vma)); static bfd_vma mips_elf_got16_entry PARAMS ((bfd *, struct bfd_link_info *, bfd_vma)); ! static unsigned int mips_elf_create_dynamic_relocation PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *, ! long, bfd_vma, asection *)); static void mips_elf_allocate_dynamic_relocations PARAMS ((bfd *, unsigned int)); static boolean mips_elf_stub_section_p --- 192,201 ---- PARAMS ((bfd *, struct mips_got_info *, asection *, bfd_vma)); static bfd_vma mips_elf_got16_entry PARAMS ((bfd *, struct bfd_link_info *, bfd_vma)); ! static boolean mips_elf_create_dynamic_relocation PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *, ! struct mips_elf_link_hash_entry *, asection *, ! bfd_vma, bfd_vma *, asection *)); static void mips_elf_allocate_dynamic_relocations PARAMS ((bfd *, unsigned int)); static boolean mips_elf_stub_section_p *************** mips_elf_got16_entry (abfd, info, value) *** 5541,5547 **** want, it is really the %high value. The complete value is calculated with a `addiu' of a LO16 relocation, just as with a HI16/LO16 pair. */ ! value = mips_elf_high (value); g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot); /* Look to see if we already have an appropriate entry. */ --- 5542,5548 ---- want, it is really the %high value. The complete value is calculated with a `addiu' of a LO16 relocation, just as with a HI16/LO16 pair. */ ! value = mips_elf_high (value) << 16; g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot); /* Look to see if we already have an appropriate entry. */ *************** mips_elf_next_lo16_relocation (relocatio *** 5594,5612 **** return NULL; } ! /* Create a rel.dyn relocation for the dynamic linker to resolve. The ! relocatin is against the symbol with the dynamic symbol table index ! DYNINDX. REL is the original relocation, which is now being made ! dynamic. */ ! ! static unsigned int ! mips_elf_create_dynamic_relocation (output_bfd, info, rel, dynindx, ! addend, input_section) bfd *output_bfd; struct bfd_link_info *info; const Elf_Internal_Rela *rel; ! long dynindx; ! bfd_vma addend; asection *input_section; { Elf_Internal_Rel outrel; --- 5595,5615 ---- return NULL; } ! /* Create a rel.dyn relocation for the dynamic linker to resolve. REL ! is the original relocation, which is now being transformed into a ! dyanmic relocation. The ADDENDP is adjusted if necessary; the ! caller should store the result in place of the original addend. */ ! ! static boolean ! mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec, ! symbol, addendp, input_section) bfd *output_bfd; struct bfd_link_info *info; const Elf_Internal_Rela *rel; ! struct mips_elf_link_hash_entry *h; ! asection *sec; ! bfd_vma symbol; ! bfd_vma *addendp; asection *input_section; { Elf_Internal_Rel outrel; *************** mips_elf_create_dynamic_relocation (outp *** 5624,5659 **** skip = false; ! /* The symbol for the relocation is the same as it was for the ! original relocation. */ ! outrel.r_info = ELF32_R_INFO (dynindx, R_MIPS_REL32); ! ! /* The offset for the dynamic relocation is the same as for the ! original relocation, adjusted by the offset at which the original ! section is output. */ if (elf_section_data (input_section)->stab_info == NULL) outrel.r_offset = rel->r_offset; else { ! bfd_vma off; ! ! off = (_bfd_stab_section_offset ! (output_bfd, &elf_hash_table (info)->stab_info, ! input_section, ! &elf_section_data (input_section)->stab_info, ! rel->r_offset)); ! if (off == (bfd_vma) -1) skip = true; - outrel.r_offset = off; } - outrel.r_offset += (input_section->output_section->vma - + input_section->output_offset); /* If we've decided to skip this relocation, just output an emtpy ! record. */ if (skip) memset (&outrel, 0, sizeof (outrel)); if (ABI_64_P (output_bfd)) { (*get_elf_backend_data (output_bfd)->s->swap_reloc_out) --- 5627,5720 ---- skip = false; ! /* We begin by assuming that the offset for the dynamic relocation ! is the same as for the original relocation. We'll adjust this ! later to reflect the correct output offsets. */ if (elf_section_data (input_section)->stab_info == NULL) outrel.r_offset = rel->r_offset; else { ! /* Except that in a stab section things are more complex. ! Because we compress stab information, the offset given in the ! relocation may not be the one we want; we must let the stabs ! machinery tell us the offset. */ ! outrel.r_offset ! = (_bfd_stab_section_offset ! (output_bfd, &elf_hash_table (info)->stab_info, ! input_section, ! &elf_section_data (input_section)->stab_info, ! rel->r_offset)); ! /* If we didn't need the relocation at all, this value will be ! -1. */ ! if (outrel.r_offset == (bfd_vma) -1) skip = true; } /* If we've decided to skip this relocation, just output an emtpy ! record. Note that R_MIPS_NONE == 0, so that this call to memset ! is a way of setting R_TYPE to R_MIPS_NONE. */ if (skip) memset (&outrel, 0, sizeof (outrel)); + else + { + long indx; + bfd_vma section_offset; + + /* We must now calculate the dynamic symbol table index to use + in the relocation. */ + if (h != NULL + && (! info->symbolic || (h->root.elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0)) + { + indx = h->root.dynindx; + BFD_ASSERT (indx != -1); + } + else + { + if (sec != NULL && bfd_is_abs_section (sec)) + indx = 0; + else if (sec == NULL || sec->owner == NULL) + { + bfd_set_error (bfd_error_bad_value); + return false; + } + else + { + indx = elf_section_data (sec->output_section)->dynindx; + if (indx == 0) + abort (); + } + /* Figure out how far the target of the relocation is from + the beginning of its section. */ + section_offset = symbol - sec->output_section->vma; + /* The relocation we're building is section-relative. + Therefore, the original addend must be adjusted by the + section offset. */ + *addendp += symbol - sec->output_section->vma; + /* Now, the relocation is just against the section. */ + symbol = sec->output_section->vma; + } + + /* If the relocation was previously an absolute relocation, we + must adjust it by the value we give it in the dynamic symbol + table. */ + if (r_type != R_MIPS_REL32) + *addendp += symbol; + + /* The relocation is always an REL32 relocation because we don't + know where the shared library will wind up at load-time. */ + outrel.r_info = ELF32_R_INFO (indx, R_MIPS_REL32); + + /* Adjust the output offset of the relocation to reference the + correct location in the output file. */ + outrel.r_offset += (input_section->output_section->vma + + input_section->output_offset); + } + + /* Put the relocation back out. We have to use the special + relocation outputter in the 64-bit case since the 64-bit + relocation format is non-standard. */ if (ABI_64_P (output_bfd)) { (*get_elf_backend_data (output_bfd)->s->swap_reloc_out) *************** mips_elf_create_dynamic_relocation (outp *** 5666,5671 **** --- 5727,5741 ---- (((Elf32_External_Rel *) sreloc->contents) + sreloc->reloc_count)); + + /* Record the index of the first relocation referencing H. This + information is later emitted in the .msym section. */ + if (h != NULL + && (h->min_dyn_reloc_index == 0 + || sreloc->reloc_count < h->min_dyn_reloc_index)) + h->min_dyn_reloc_index = sreloc->reloc_count; + + /* We've now added another relocation. */ ++sreloc->reloc_count; /* Make sure the output section is writable. The dynamic linker *************** mips_elf_create_dynamic_relocation (outp *** 5692,5698 **** else mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD); mips_elf_set_cr_dist2to (cptrel, 0); ! cptrel.konst = addend; cr = (scpt->contents + sizeof (Elf32_External_compact_rel)); --- 5762,5768 ---- else mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD); mips_elf_set_cr_dist2to (cptrel, 0); ! cptrel.konst = *addendp; cr = (scpt->contents + sizeof (Elf32_External_compact_rel)); *************** mips_elf_create_dynamic_relocation (outp *** 5703,5709 **** } } ! return sreloc->reloc_count - 1; } /* Calculate the value produced by the RELOCATION (which comes from --- 5773,5779 ---- } } ! return true; } /* Calculate the value produced by the RELOCATION (which comes from *************** mips_elf_calculate_relocation (abfd, *** 6024,6050 **** case R_MIPS_32: case R_MIPS_REL32: case R_MIPS_64: ! /* If we're creating a shared library, or this relocation is ! against a symbol in a shared library, then we can't know ! where the symbol will end up. So, we create a relocation ! record in the output, and leave the job up to the dynamic ! linker. */ ! if (info->shared || !sec->output_section) ! { ! unsigned int reloc_index; ! ! BFD_ASSERT (h != NULL); ! reloc_index ! = mips_elf_create_dynamic_relocation (abfd, ! info, ! relocation, ! h->root.dynindx, ! addend, ! input_section); ! if (h->min_dyn_reloc_index == 0 ! || reloc_index < h->min_dyn_reloc_index) ! h->min_dyn_reloc_index = reloc_index; ! value = symbol + addend; } else { --- 6094,6121 ---- case R_MIPS_32: case R_MIPS_REL32: case R_MIPS_64: ! if ((info->shared ! || (elf_hash_table (info)->dynamic_sections_created ! && h != NULL ! && ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) ! == 0))) ! && (input_section->flags & SEC_ALLOC) != 0) ! { ! /* If we're creating a shared library, or this relocation is ! against a symbol in a shared library, then we can't know ! where the symbol will end up. So, we create a relocation ! record in the output, and leave the job up to the dynamic ! linker. */ ! value = addend; ! if (!mips_elf_create_dynamic_relocation (abfd, ! info, ! relocation, ! h, ! sec, ! symbol, ! &value, ! input_section)) ! return false; } else { *************** _bfd_mips_elf_check_relocs (abfd, info, *** 7488,7494 **** this symbol, a symbol must have a dynamic symbol table index greater that DT_GOTSYM if there are dynamic relocations against it. */ ! if (!mips_elf_record_global_got_symbol (h, info, g)) return false; } --- 7559,7566 ---- this symbol, a symbol must have a dynamic symbol table index greater that DT_GOTSYM if there are dynamic relocations against it. */ ! if (h != NULL ! && !mips_elf_record_global_got_symbol (h, info, g)) return false; }