Movatterモバイル変換
[0]ホーム
This is the mail archive of thebinutils@sources.redhat.commailing list for thebinutils project.
ld on irix revisited
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: binutils at sources dot redhat dot com
- Date: 21 Jun 2003 17:27:23 +0100
- Subject: ld on irix revisited
I think I've finally got ld working on irix6 with shared libraries.Patches attached below.First, here's a summary of the differences I found between glibc andirix rld. I'm sure most of this stuff isn't new, but I need to sayit anyway in order to justify the patches.glibc 2.2.5's behaviour was: If the symbol index < DT_MIPS_GOTSYM, add the final symbol value. Otherwise add the symbol's final GOT entry.glibc 2.3.2's behaviour is: If the symbol index < DT_MIPS_GOTSYM, add the base address. Otherwise add the symbol's final GOT entry.The irix rld hehaviour seems to be: If the symbol index < DT_MIPS_GOT_SYM, subtract the symbol's st_value and add its final value. Otherwise subract the symbol's initial GOT entry and add its final GOT entry.See last weekend's postings for a verbose justification of the irixbehaviour. But that's all by-the-bye. Comparing 2.3.2 with rld,there are three incompatible cases:A. Relocs against symbol STN_UNDEF---------------------------------- - glibc adds the base address - irix rld does nothing (st_value = 0, final symbol value = 0) (FWIW, glibc seems to be wrong here since the r_info description in the gABI says:If the index is STN_UNDEF, the undefined symbol index,the relocation uses 0 as the "symbol value". The 64-bit ABI has similar wording.)B. Relocs against defined external symbols------------------------------------------ - glibc adds the final symbol value - irix rld subtracts the initial contents of the GOT (the original st_value) and adds the final symbol value This one's the killer. The addend must include the symbol value when using irix rld but it must not when using glibc.C. Relocs against undefined external symbols-------------------------------------------- - glibc adds the final symbol value - irix rld subtracts the initial contents of the GOT and adds the final symbol value At the moment, ld initialises the GOT with the value it found in the external DSO, so these behaviours aren't compatible. I think we're supposed to initialise the GOT to zero in this case, see:http://sources.redhat.com/ml/binutils/2003-06/msg00525.html for justification.The attached patches are intended to fix the irix problems whilekeeping compatibility with glibc. Where the two loaders needdifferent behaviour (cases (A) and (B) above), I've used SGI_COMPATto select between them.All the patches are needed in order to get correct irix behaviour:it doesn't really make sense to apply some and not others. I've splitthem up anyway in the hope that they'll be easier to review that way.Note: the patches are against 2.14.Patch 1-------* elfxx-mips.c (_bfd_mips_elf_finish_dynamic_symbol): Alwaysinitialize a GOT entry to the symbol's st_value. Fixes the GOT initailisation for (C). glibc doesn't use the initial contents in this case, so the change is compatible with both loaders. Again, see:http://sources.redhat.com/ml/binutils/2003-06/msg00525.html for a justification.Patch 2-------* bfd/elfxx-mips.c (mips_elf_create_dynamic_relocation): In SGI-compatible objects, add the values of defined external symbolsto the addend. Fixes (B) for irix rld. This is a variation of the patch posted here:http://sources.redhat.com/ml/binutils/2003-06/msg00533.html but with the change predicated on SGI_COMPAT since it isn't compatible with glibc.Patch 3-------* bfd/elfxx-mips.c (mips_elf_create_dynamic_relocation): Treatforced-local symbols like other locals. Don't create relocationsagainst STN_UNDEF in irix objects. Disables this patch:http://sources.redhat.com/ml/binutils/2003-03/msg00148.html for SGI objects since relocations against symbol 0 do not have the desired effect ((A) above). Also treats forced-local symbols in the same way as other locals. At the moment, relocations against forced-local symbols are always turned into relocations against symbol 0. The patch prevents this for irix targets but keeps it for glibc.Patch 4-------* elfxx-mips.c (mips_elf_link_hash_entry): Remove min_dyn_reloc_index.(mips_elf_link_hash_newfunc): Don't set it.(mips_elf_create_dynamic_relocation): Likewise.(_bfd_mips_elf_copy_indirect_symbol): Likewise.(bfd_mips_elf_swap_msym_in): Reenable.(mips_elf_adjust_msym_indices): New function.(_bfd_mips_elf_finish_dynamic_symbol): Just use a 0 symbol index.(_bfd_mips_elf_finish_dynamic_sections): After sorting .rel.dyn,go through .msym and set up the ms_info fields appropriately. This is the same as the patch posted here:http://sources.redhat.com/ml/binutils/2003-06/msg00533.html except that the new version should use more canonical types. See the message for a full explanation.Patch 5-------* elfxx-mips.c (_bfd_mips_elf_finish_dynamic_symbol): Don't try tocreate .msym entries for forced-local symbols. At the moment we try this and corrupt the end of the previous section.Patch 6-------* elfxx-mips.c (mips_elf_create_dynamic_relocation): Fix handlingof relocations whose offset is -2. Fix the handling of .eh_frame if things like language-specific data are made relative. The .eh_frame code then expects to have fully-relocated lsda fields, but we never add in the symbol value.Patch 7-------* elfxx-mips.c (mips_elf_irix6_finish_dynamic_symbol): Make thesymbols protected. This is something I noticed while looking at other stuff. It copies the behaviour of the native linker and it seems fairly obvious, but I'm not aware of anything specific that breaks without it.Are these patches likely to be accepted? If so, I'll come upwith something for the testsuite.The patches were tested on a mipsel-linux-gnu cross compiler and bybootstrapping and regression testing mips-sgi-irix6.5 --with-gnu-as--with-gnu-ld. I needed some gcc patches for the irix config: I'llpost them to gcc-patches if the bfd side is accepted.Richard
*** elfxx-mips.c.cvsSat Jun 21 15:19:37 2003--- elfxx-mips.c.1Sat Jun 21 15:21:02 2003*************** _bfd_mips_elf_finish_dynamic_symbol (out*** 6749,6770 **** bfd_vma offset; bfd_vma value; ! if (sym->st_value)! value = sym->st_value;! else! {! /* For an entity defined in a shared object, this will be! NULL. (For functions in shared objects for! which we have created stubs, ST_VALUE will be non-NULL.! That's because such the functions are now no longer defined! in a shared object.) */! ! if ((info->shared && h->root.type == bfd_link_hash_undefined)! || h->root.type == bfd_link_hash_undefweak)! value = 0;! else! value = h->root.u.def.value;! } offset = mips_elf_global_got_index (dynobj, output_bfd, h); MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset); }--- 6749,6755 ---- bfd_vma offset; bfd_vma value; ! value = sym->st_value; offset = mips_elf_global_got_index (dynobj, output_bfd, h); MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset); }--- elfxx-mips.c.1Sat Jun 21 15:21:02 2003+++ elfxx-mips.c.2Sat Jun 21 16:50:00 2003@@ -3886,6 +3886,7 @@ mips_elf_create_dynamic_relocation (outp else { long indx;+ bfd_boolean defined_p; /* We must now calculate the dynamic symbol table index to use in the relocation. */@@ -3898,6 +3899,15 @@ mips_elf_create_dynamic_relocation (outp become local. */ if (indx == -1) indx = 0;+ if (SGI_COMPAT (output_bfd))+ defined_p = ((h->root.elf_link_hash_flags+ & ELF_LINK_HASH_DEF_REGULAR) != 0);+ else+ /* ??? glibc's ld.so just adds the final GOT entry to the+ relocation field. It therefore treats relocs against+ defined symbols in the same way as relocs against+ undefined symbols. */+ defined_p = FALSE; } else {@@ -3927,13 +3937,14 @@ mips_elf_create_dynamic_relocation (outp useful, after all. This should be a bit more efficient as well. */ indx = 0;+ defined_p = TRUE; } /* If the relocation was previously an absolute relocation and this symbol will not be referred to by the relocation, we must adjust it by the value we give it in the dynamic symbol table. Otherwise leave the job up to the dynamic linker. */- if (!indx && r_type != R_MIPS_REL32)+ if (defined_p && r_type != R_MIPS_REL32) *addendp += symbol; /* The relocation is always an REL32 relocation because we don't*** elfxx-mips.c.2Sat Jun 21 15:45:55 2003--- elfxx-mips.c.3Sat Jun 21 16:30:40 2003*************** mips_elf_create_dynamic_relocation (outp*** 3892,3904 **** in the relocation. */ if (h != NULL && (! info->symbolic || (h->root.elf_link_hash_flags! & ELF_LINK_HASH_DEF_REGULAR) == 0))! {! indx = h->root.dynindx; /* h->root.dynindx may be -1 if this symbol was marked to become local. */! if (indx == -1)! indx = 0; if (SGI_COMPAT (output_bfd)) defined_p = ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0);--- 3892,3903 ---- in the relocation. */ if (h != NULL && (! info->symbolic || (h->root.elf_link_hash_flags! & ELF_LINK_HASH_DEF_REGULAR) == 0) /* h->root.dynindx may be -1 if this symbol was marked to become local. */! && h->root.dynindx != -1)! {! indx = h->root.dynindx; if (SGI_COMPAT (output_bfd)) defined_p = ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0);*************** mips_elf_create_dynamic_relocation (outp*** 3936,3942 **** section-relative relocations. It's not like they're useful, after all. This should be a bit more efficient as well. */! indx = 0; defined_p = TRUE; } --- 3935,3946 ---- section-relative relocations. It's not like they're useful, after all. This should be a bit more efficient as well. */! /* ??? Although this behavior is compatible with glibc's ld.so,! the ABI says that relocations against STN_UNDEF should have! a symbol value of 0. Irix rld honors this, so relocations! against STN_UNDEF have no effect. */! if (!SGI_COMPAT (output_bfd))! indx = 0; defined_p = TRUE; }*** elfxx-mips.c.3Sat Jun 21 16:30:40 2003--- elfxx-mips.c.4Sat Jun 21 16:30:48 2003*************** struct mips_elf_link_hash_entry*** 189,198 **** a readonly section. */ bfd_boolean readonly_reloc; - /* The index of the first dynamic relocation (in the .rel.dyn- section) against this symbol. */- unsigned int min_dyn_reloc_index;- /* We must not create a stub for a symbol that has relocations related to taking the function's address, i.e. any but R_MIPS_CALL*16 ones -- see "MIPS ABI Supplement, 3rd Edition",--- 189,194 ----*************** static void bfd_elf32_swap_compact_rel_o*** 391,400 **** PARAMS ((bfd *, const Elf32_compact_rel *, Elf32_External_compact_rel *)); static void bfd_elf32_swap_crinfo_out PARAMS ((bfd *, const Elf32_crinfo *, Elf32_External_crinfo *));- #if 0 static void bfd_mips_elf_swap_msym_in PARAMS ((bfd *, const Elf32_External_Msym *, Elf32_Internal_Msym *));- #endif static void bfd_mips_elf_swap_msym_out PARAMS ((bfd *, const Elf32_Internal_Msym *, Elf32_External_Msym *)); static int sort_dynamic_relocs--- 387,394 ----*************** static bfd_boolean mips_elf_create_got_s*** 446,451 ****--- 440,447 ---- PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean)); static asection *mips_elf_create_msym_section PARAMS ((bfd *));+ static void mips_elf_adjust_msym_indices+ PARAMS ((bfd *, asection *, asection *)); static bfd_reloc_status_type mips_elf_calculate_relocation PARAMS ((bfd *, bfd *, asection *, struct bfd_link_info *, const Elf_Internal_Rela *, bfd_vma, reloc_howto_type *,*************** mips_elf_link_hash_newfunc (entry, table*** 732,738 **** ret->esym.ifd = -2; ret->possibly_dynamic_relocs = 0; ret->readonly_reloc = FALSE;- ret->min_dyn_reloc_index = 0; ret->no_fn_stub = FALSE; ret->fn_stub = NULL; ret->need_fn_stub = FALSE;--- 728,733 ----*************** bfd_elf32_swap_crinfo_out (abfd, in, ex)*** 1194,1200 **** H_PUT_32 (abfd, in->vaddr, ex->vaddr); } - #if 0 /* Swap in an MSYM entry. */ static void--- 1189,1194 ----*************** bfd_mips_elf_swap_msym_in (abfd, ex, in)*** 1206,1212 **** in->ms_hash_value = H_GET_32 (abfd, ex->ms_hash_value); in->ms_info = H_GET_32 (abfd, ex->ms_info); }! #endif /* Swap out an MSYM entry. */ static void--- 1200,1206 ---- in->ms_hash_value = H_GET_32 (abfd, ex->ms_hash_value); in->ms_info = H_GET_32 (abfd, ex->ms_info); }! /* Swap out an MSYM entry. */ static void*************** mips_elf_create_msym_section (abfd)*** 2944,2949 ****--- 2938,2981 ---- return s; }+ + /* Adjust the contents of .msym after sorting the dynamic relocations.+ RELDYN and MSYM are the two sections involved. */+ + static void+ mips_elf_adjust_msym_indices (abfd, reldyn, msym)+ bfd *abfd;+ asection *reldyn, *msym;+ {+ bfd_size_type i, entsize;+ bfd_vma lastsym;+ + entsize = MIPS_ELF_REL_SIZE (abfd);+ lastsym = (bfd_vma) -1;+ + for (i = entsize; i < reldyn->_raw_size; i += entsize)+ {+ bfd_vma sym;+ Elf_Internal_Rela reloc[3];+ + (*get_elf_backend_data (abfd)->s->swap_reloc_in)+ (abfd, reldyn->contents + i, reloc);+ sym = ELF_R_SYM (abfd, reloc[0].r_info);+ if (sym != lastsym)+ {+ /* This is the first relocation against SYM. Get its .msym+ record and adjust the ms_info field appropriately. */+ Elf32_Internal_Msym entry;+ + bfd_mips_elf_swap_msym_in+ (abfd, (Elf32_External_Msym *) msym->contents + sym, &entry);+ entry.ms_info = ELF32_MS_INFO (i / entsize, 1);+ bfd_mips_elf_swap_msym_out+ (abfd, &entry, (Elf32_External_Msym *) msym->contents + sym);+ lastsym = sym;+ }+ }+ } /* Calculate the value produced by the RELOCATION (which comes from the INPUT_BFD). The ADDEND is the addend to use for this*************** mips_elf_create_dynamic_relocation (outp*** 3999,4011 **** (output_bfd, &outrel[0], (sreloc->contents + sreloc->reloc_count * sizeof (Elf32_External_Rel))); - /* 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; --- 4031,4036 ----*************** _bfd_mips_elf_finish_dynamic_symbol (out*** 6704,6714 **** asection *smsym; struct mips_got_info *g, *gg; const char *name;- struct mips_elf_link_hash_entry *mh; dynobj = elf_hash_table (info)->dynobj; gval = sym->st_value;- mh = (struct mips_elf_link_hash_entry *) h; if (h->plt.offset != (bfd_vma) -1) {--- 6729,6737 ----*************** _bfd_mips_elf_finish_dynamic_symbol (out*** 6831,6837 **** msym.ms_hash_value = bfd_elf_hash (h->root.root.string); /* It is undocumented what the `1' indicates, but IRIX6 uses this value. */! msym.ms_info = ELF32_MS_INFO (mh->min_dyn_reloc_index, 1); bfd_mips_elf_swap_msym_out (dynobj, &msym, ((Elf32_External_Msym *) smsym->contents) + h->dynindx);--- 6854,6860 ---- msym.ms_hash_value = bfd_elf_hash (h->root.root.string); /* It is undocumented what the `1' indicates, but IRIX6 uses this value. */! msym.ms_info = ELF32_MS_INFO (0, 1); bfd_mips_elf_swap_msym_out (dynobj, &msym, ((Elf32_External_Msym *) smsym->contents) + h->dynindx);*************** _bfd_mips_elf_finish_dynamic_sections (o*** 7236,7242 **** (size_t) s->reloc_count - 1, sizeof (Elf32_External_Rel), sort_dynamic_relocs); }! } return TRUE; }--- 7259,7268 ---- (size_t) s->reloc_count - 1, sizeof (Elf32_External_Rel), sort_dynamic_relocs); }! ! if (s != 0 && smsym != 0)! mips_elf_adjust_msym_indices (output_bfd, s, smsym);! } return TRUE; }*************** _bfd_mips_elf_copy_indirect_symbol (bed,*** 7778,7787 **** dirmips->possibly_dynamic_relocs += indmips->possibly_dynamic_relocs; if (indmips->readonly_reloc) dirmips->readonly_reloc = TRUE;- if (dirmips->min_dyn_reloc_index == 0- || (indmips->min_dyn_reloc_index != 0- && indmips->min_dyn_reloc_index < dirmips->min_dyn_reloc_index))- dirmips->min_dyn_reloc_index = indmips->min_dyn_reloc_index; if (indmips->no_fn_stub) dirmips->no_fn_stub = TRUE; }--- 7804,7809 ------- elfxx-mips.c.4Sat Jun 21 16:30:48 2003+++ elfxx-mips.c.5Sat Jun 21 16:30:53 2003@@ -6847,7 +6847,7 @@ _bfd_mips_elf_finish_dynamic_symbol (out /* Create a .msym entry, if appropriate. */ smsym = bfd_get_section_by_name (dynobj, ".msym");- if (smsym)+ if (smsym && h->dynindx != -1) { Elf32_Internal_Msym msym;*** elfxx-mips.c.5Sat Jun 21 15:42:14 2003--- elfxx-mips.c.6Sat Jun 21 15:42:07 2003*************** mips_elf_create_dynamic_relocation (outp*** 3906,3914 **** } #endif ! if (outrel[0].r_offset == (bfd_vma) -1! || outrel[0].r_offset == (bfd_vma) -2) skip = TRUE; /* If we've decided to skip this relocation, just output an empty record. Note that R_MIPS_NONE == 0, so that this call to memset--- 3906,3922 ---- } #endif ! if (outrel[0].r_offset == (bfd_vma) -1)! /* The relocation field has been deleted. */ skip = TRUE;+ else if (outrel[0].r_offset == (bfd_vma) -2)+ {+ /* The relocation field has been converted into a relative value of+ some sort. Functions like _bfd_elf_write_section_eh_frame expect+ the field to be fully relocated, so add in the symbol's value. */+ skip = TRUE;+ *addendp += symbol;+ } /* If we've decided to skip this relocation, just output an empty record. Note that R_MIPS_NONE == 0, so that this call to memset*** elfxx-mips.c.6Sat Jun 21 16:31:01 2003--- elfxx-mips.c.7Sat Jun 21 16:31:10 2003*************** mips_elf_irix6_finish_dynamic_symbol (ab*** 6710,6715 ****--- 6710,6716 ---- /* All of these symbols are given type STT_SECTION by the IRIX6 linker. */ sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);+ sym->st_other = STO_PROTECTED; /* The IRIX linker puts these symbols in special sections. */ if (i == 0)
[8]ページ先頭