Millicode calls, GP register, ld -r

David Huggins-Daines dhd@linuxcare.com
11 Aug 2000 18:35:49 -0400


David Huggins-Daines <dhd@linuxcare.com> writes:

> Alan Modra <alan@linuxcare.com.au> writes:
> 
> > So...  I can turn a PLABEL reference into a GOT reference, which will
> > magically fix the $$dyncall problem.
> 
> Yes, that's the right idea.  However it only works for external
> symbols, and you still need a PLABEL32 relocation for function
> pointers to local symbols within a shared object (like dl_main for
> instance, hint hint :-)
> 
> I'll try to take a shot at it but I still don't fully comprehend the
> BFD code.

Here's an (ugly) patch that works.  Please verify that the last chunk
is okay - ld was outputting bogus PLABEL32 relocations when things
were compiled with -ffunction-sections, because it was effectively
calculating the addend as the offset within the input section.

With this patch ld.so manages to link itself again.

Index: bfd/elf32-hppa.c
===================================================================
RCS file: /home/cvs/parisc/binutils-2.10/bfd/elf32-hppa.c,v
retrieving revision 1.13.2.25
diff -u -r1.13.2.25 elf32-hppa.c
--- elf32-hppa.c	2000/08/11 18:12:40	1.13.2.25
+++ elf32-hppa.c	2000/08/12 04:28:20
@@ -1058,9 +1058,14 @@
 	    }
 	  break;
 
+	case R_PARISC_PLABEL32:
+	  /* In this case, if it's local, we don't need a .plt entry,
+             but we might need to generate a dynamic relocation. */
+	  if (h == NULL)
+	    goto local_plabel;
+
 	case R_PARISC_PLABEL14R: /* "Official" procedure labels.  */
 	case R_PARISC_PLABEL21L:
-	case R_PARISC_PLABEL32:
 	case R_PARISC_PCREL17C:
 	case R_PARISC_PCREL17F:
 	case R_PARISC_PCREL22F:
@@ -1131,6 +1136,7 @@
 	  /* Fall through.  */
 #endif
 
+	local_plabel:
 	case R_PARISC_DIR32: /* .word, PARISC.unwind relocs.  */
 
 	  /* Flag this symbol as having a non-got, non-plt reference
@@ -2738,12 +2744,16 @@
 			 + hplink->sgot->output_section->vma);
 	  break;
 
+	case R_PARISC_PLABEL32:
+	  /* As in check_relocs, we may need to output a dynamic reloc
+             here even for local symbols. */
+	  if (h == NULL)
+	    goto local_plabel;
 	case R_PARISC_PLABEL14R:
 	case R_PARISC_PLABEL21L:
-	case R_PARISC_PLABEL32:
 	  if (elf_hash_table (info)->dynamic_sections_created
 	      && h != NULL
-	      && h->elf.plt.offset != -1)
+	      && h->elf.plt.offset != (bfd_vma) -1)
 	    {
 	      /* PLABELs contain function pointers.  Relocation is to
 		 the entry for the function in the .plt.  The magic +2
@@ -2756,6 +2766,7 @@
 	    }
 	  break;
 
+	local_plabel:
 	case R_PARISC_DIR17F:
 	case R_PARISC_DIR17R:
 	case R_PARISC_DIR14R:
@@ -2832,14 +2843,18 @@
 		{
 		  int indx = 0;
 
+		  /* Add the absolute offset of the symbol. */
+		  outrel.r_addend += relocation;
+
 		  if (! bfd_is_abs_section (sym_sec))
 		    {
 		      indx = elf_section_data (sym_sec->output_section)->dynindx;
-		      outrel.r_addend -= (sym_sec->output_offset
-					  + sym_sec->output_section->vma);
+		      /* Subtract out the output section's address (but
+                         not the offset of the input section in the
+                         output section!). */
+		      outrel.r_addend -= sym_sec->output_section->vma;
 		    }
 
-		  outrel.r_addend += relocation;
 		  outrel.r_info = ELF32_R_INFO (indx, r_type);
 		}
 


-- 
dhd@linuxcare.com, http://www.linuxcare.com/
Linuxcare. Support for the revolution.