diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h
index a30892f080..dcc3e0883b 100644
--- a/sysdeps/riscv/dl-machine.h
+++ b/sysdeps/riscv/dl-machine.h
@@ -348,7 +348,8 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
       gotplt[1] = (ElfW(Addr)) l;
     }
 
-  if (l->l_type == lt_executable && l->l_relocated)
+#ifdef SHARED
+  if (l->l_type == lt_executable)
     {
       /* The __global_pointer$ may not be defined by the linker if the
 	 $gp register does not be used to access the global variable
@@ -362,12 +363,16 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
       _dl_lookup_symbol_x ("__global_pointer$", l, &ref,
 			   l->l_scope, NULL, 0, 0, NULL);
       if (ref)
-        asm (
-          "mv gp, %0\n"
-          :
-          : "r" (ref->st_value)
-        );
+	asm (
+	  "mv gp, %0\n"
+	  :
+	  : "r" (ref->st_value + l->l_addr)
+	  /* Don't use SYMBOL_ADDRESS here since __global_pointer$
+	     can be SHN_ABS type, but we need the address relative to
+	     PC, not the absolute address.  */
+	);
     }
+#endif
 #endif
   return lazy;
 }
