diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4e3860d5692..f9cc5e38d80 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,12 @@
+2001-04-27  Andreas Jaeger  <aj@suse.de>
+
+	* elf64-x86-64.c (elf64_x86_64_finish_dynamic_sections): Only swap
+	out handled entries.
+	(elf64_x86_64_finish_dynamic_symbol): Set up GOT entries.
+	(elf64_x86_64_relocate_section): Fix GOTPCREL calculation.
+	(elf64_x86_64_relocate_section): Merge entries for GOTPCREL and
+	GOT32.
+
 2001-04-27  Sean McNeil <sean@mcneil.com>
 
 	* config.bfd: Add arm-vxworks target.
@@ -48,12 +57,12 @@
 	(cpu-openrisc.lo, elf32-openrisc.lo): New rules.
 	* Makefile.in: Regenerated.
 	* config.bfd: (openrisc-*-elf): New target.
-	* configure.in (bfd_elf32_openrisc_vec): New vector. 
+	* configure.in (bfd_elf32_openrisc_vec): New vector.
 	* configure: Regenerated.
 	* libbfd.h: Regenerated.
 	* bfd-in2.h: Regenerated.
 	* reloc.c: Add OpenRISC relocations.
-	* targets.c (bfd_elf32_openrisc_vec): Declare. 
+	* targets.c (bfd_elf32_openrisc_vec): Declare.
 	(bfd_target_vect): Add bfd_elf32_openrisc_vec.
 	* archures.c (enum bfd_architecture): Add bfd_arch_openrisc.
 	(bfd_openrisc_arch): Declare.
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 912f666bfba..f23e06cdb13 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1321,92 +1321,10 @@ elf64_x86_64_relocate_section (output_bfd, info, input_bfd, input_section,
 	case R_X86_64_GOT32:
 	  /* Relocation is to the entry for this symbol in the global
 	     offset table.  */
-	  BFD_ASSERT (sgot != NULL);
-
-	  if (h != NULL)
-	    {
-	      bfd_vma off = h->got.offset;
-	      BFD_ASSERT (off != (bfd_vma) -1);
-
-	      if (! elf_hash_table (info)->dynamic_sections_created
-		  || (info->shared
-		      && (info->symbolic || h->dynindx == -1)
-		      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
-		{
-		  /* This is actually a static link, or it is a -Bsymbolic
-		     link and the symbol is defined locally, or the symbol
-		     was forced to be local because of a version file.	We
-		     must initialize this entry in the global offset table.
-		     Since the offset must always be a multiple of 8, we
-		     use the least significant bit to record whether we
-		     have initialized it already.
-
-		     When doing a dynamic link, we create a .rela.got
-		     relocation entry to initialize the value.	This is
-		     done in the finish_dynamic_symbol routine.	 */
-		  if ((off & 1) != 0)
-		    off &= ~1;
-		  else
-		    {
-		      bfd_put_64 (output_bfd, relocation,
-				  sgot->contents + off);
-		      h->got.offset |= 1;
-		    }
-		}
-	      relocation = sgot->output_offset + off;
-	    }
-	  else
-	    {
-	      bfd_vma off;
-
-	      BFD_ASSERT (local_got_offsets != NULL
-			  && local_got_offsets[r_symndx] != (bfd_vma) -1);
-
-	      off = local_got_offsets[r_symndx];
-
-	      /* The offset must always be a multiple of 8.  We use
-		 the least significant bit to record whether we have
-		 already generated the necessary reloc.	 */
-	      if ((off & 1) != 0)
-		off &= ~1;
-	      else
-		{
-		  bfd_put_64 (output_bfd, relocation, sgot->contents + off);
-
-		  if (info->shared)
-		    {
-		      asection *srelgot;
-		      Elf_Internal_Rela outrel;
-
-		      /* We need to generate a R_X86_64_RELATIVE reloc
-			 for the dynamic linker.  */
-		      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
-		      BFD_ASSERT (srelgot != NULL);
-
-		      outrel.r_offset = (sgot->output_section->vma
-					 + sgot->output_offset
-					 + off);
-		      outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE);
-		      outrel.r_addend = relocation;
-		      bfd_elf64_swap_reloca_out (output_bfd, &outrel,
-						 (((Elf64_External_Rela *)
-						   srelgot->contents)
-						  + srelgot->reloc_count));
-		      ++srelgot->reloc_count;
-		    }
-
-		  local_got_offsets[r_symndx] |= 1;
-		}
-
-	      relocation = sgot->output_offset + off;
-	    }
-
-	  break;
-
 	case R_X86_64_GOTPCREL:
 	  /* Use global offset table as symbol value.  */
-
 	  BFD_ASSERT (sgot != NULL);
+
 	  if (h != NULL)
 	    {
 	      bfd_vma off = h->got.offset;
@@ -1437,7 +1355,10 @@ elf64_x86_64_relocate_section (output_bfd, info, input_bfd, input_section,
 		      h->got.offset |= 1;
 		    }
 		}
-	      relocation = sgot->output_offset + off;
+	      if (r_type == R_X86_64_GOTPCREL)
+		relocation = sgot->output_section->vma + sgot->output_offset + off;
+	      else
+		relocation = sgot->output_offset + off;
 	    }
 	  else
 	    {
@@ -1482,7 +1403,10 @@ elf64_x86_64_relocate_section (output_bfd, info, input_bfd, input_section,
 		  local_got_offsets[r_symndx] |= 1;
 		}
 
-	      relocation = sgot->output_section->vma + off;
+	      if (r_type == R_X86_64_GOTPCREL)
+		relocation = sgot->output_section->vma + sgot->output_offset + off;
+	      else
+		relocation = sgot->output_offset + off;
 	    }
 	  break;
 
@@ -1769,6 +1693,52 @@ elf64_x86_64_finish_dynamic_symbol (output_bfd, info, h, sym)
 	}
     }
 
+  if (h->got.offset != (bfd_vma) -1)
+    {
+      asection *sgot;
+      asection *srela;
+      Elf_Internal_Rela rela;
+
+      /* This symbol has an entry in the global offset table.  Set it
+         up.  */
+
+      sgot = bfd_get_section_by_name (dynobj, ".got");
+      srela = bfd_get_section_by_name (dynobj, ".rela.got");
+      BFD_ASSERT (sgot != NULL && srela != NULL);
+
+      rela.r_offset = (sgot->output_section->vma
+		       + sgot->output_offset
+		       + (h->got.offset &~ 1));
+
+      /* If this is a static link, or it is a -Bsymbolic link and the
+	 symbol is defined locally or was forced to be local because
+	 of a version file, we just want to emit a RELATIVE reloc.
+	 The entry in the global offset table will already have been
+	 initialized in the relocate_section function.  */
+      if (! elf_hash_table (info)->dynamic_sections_created
+	  || (info->shared
+	      && (info->symbolic || h->dynindx == -1)
+	      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+	{
+	  rela.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE);
+	  rela.r_addend = (h->root.u.def.value
+			   + h->root.u.def.section->output_section->vma
+			   + h->root.u.def.section->output_offset);
+	}
+      else
+	{
+	  BFD_ASSERT((h->got.offset & 1) == 0);
+	  bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
+	  rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_GLOB_DAT);
+	  rela.r_addend = 0;
+	}
+
+      bfd_elf64_swap_reloca_out (output_bfd, &rela,
+				 ((Elf64_External_Rela *) srela->contents
+				  + srela->reloc_count));
+      ++srela->reloc_count;
+    }
+
   if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
     {
       asection *s;
@@ -1840,7 +1810,7 @@ elf64_x86_64_finish_dynamic_sections (output_bfd, info)
 	  switch (dyn.d_tag)
 	    {
 	    default:
-	      break;
+	      continue;
 
 	    case DT_PLTGOT:
 	      name = ".got";
@@ -1878,7 +1848,6 @@ elf64_x86_64_finish_dynamic_sections (output_bfd, info)
 		(s->_cooked_size != 0 ? s->_cooked_size : s->_raw_size);
 	      break;
 	    }
-
 	  bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
 	}