diff --git a/elf/rtld.c b/elf/rtld.c
index 9918fda05e76..c514cc723b68 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -175,6 +175,24 @@ enum mode { normal, list, verify, trace };
    all the entries.  */
 static void process_envvars (enum mode *modep, struct audit_list *);
 
+/* Option to display relative load addresses, with display address
+ * having executable base address subtracted, making output constant
+ * in the presence of ASLR, as well as reducing output differences.
+ * `LD_TRACE_ADDR_ABSOLUTE=1` restores prior behavior.  */
+static int trace_addr_relative = 1;
+
+/* Option to negate load addresses, otherwise the default shows
+ * negative relative offsets beacuase ld.so loads libs downwards,
+ * and brk space is just after the executable in memory. The
+ * justified format has sign to show negated address offsets.
+ * `LD_TRACE_ADDR_NEGATE=1` to show signed positive offsets.  */
+static int trace_addr_negate = 0;
+
+/* Option to display left-justified addresses, making the listing
+ * easier to read because addresses are all lined up in one column.
+ * `LD_TRACE_ADDR_JUSTIFY=1` will left-justify addresses.  */
+static int trace_addr_justify = 0;
+
 #ifdef DL_ARGV_NOT_RELRO
 int _dl_argc attribute_hidden;
 char **_dl_argv = NULL;
@@ -1683,6 +1701,8 @@ of this helper program; chances are you did not intend to run this program.\n\
   GL(dl_rtld_map).l_phdr = rtld_phdr;
   GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum;
 
+  /* base address (ld.so ehdr) used for relative display addresses */
+  size_t disp_addr, base_addr = (size_t) rtld_ehdr;
 
   /* PT_GNU_RELRO is usually the last phdr.  */
   size_t cnt = rtld_ehdr->e_phnum;
@@ -1989,6 +2009,12 @@ of this helper program; chances are you did not intend to run this program.\n\
 	  for (i = 0; i < scope->r_nlist; i++)
 	    {
 	      l = scope->r_list [i];
+
+	      /* Subtract and negate base from load address if requested  */
+	      disp_addr = (size_t) l->l_map_start;
+	      if (trace_addr_relative) disp_addr -= base_addr;
+	      if (trace_addr_negate) disp_addr = -disp_addr;
+
 	      if (l->l_faked)
 		{
 		  _dl_printf ("\t%s => not found\n", l->l_libname->name);
@@ -1996,20 +2022,42 @@ of this helper program; chances are you did not intend to run this program.\n\
 		}
 	      if (_dl_name_match_p (GLRO(dl_trace_prelink), l))
 		GLRO(dl_trace_prelink_map) = l;
-	      _dl_printf ("\t%s => %s (0x%0*Zx, 0x%0*Zx)",
-			  DSO_FILENAME (l->l_libname->name),
-			  DSO_FILENAME (l->l_name),
-			  (int) sizeof l->l_map_start * 2,
-			  (size_t) l->l_map_start,
-			  (int) sizeof l->l_addr * 2,
-			  (size_t) l->l_addr);
-
-	      if (l->l_tls_modid)
-		_dl_printf (" TLS(0x%Zx, 0x%0*Zx)\n", l->l_tls_modid,
-			    (int) sizeof l->l_tls_offset * 2,
-			    (size_t) l->l_tls_offset);
+	      if (trace_addr_justify)
+	        {
+		  _dl_printf ("\t(%s0x%0*Zx, 0x%0*Zx)",
+		          trace_addr_negate ? "-" : "+",
+			      (int) sizeof l->l_map_start * 2,
+			      disp_addr,
+			      (int) sizeof l->l_addr * 2,
+			      (size_t) l->l_addr);
+
+		  if (l->l_tls_modid)
+		    _dl_printf (" TLS(0x%Zx, 0x%0*Zx)", l->l_tls_modid,
+				(int) sizeof l->l_tls_offset * 2,
+				(size_t) l->l_tls_offset);
+
+		  _dl_printf (" %s => %s\n",
+			      DSO_FILENAME (l->l_libname->name),
+			      DSO_FILENAME (l->l_name));
+
+		}
 	      else
-		_dl_printf ("\n");
+		{
+		  _dl_printf ("\t%s => %s (0x%0*Zx, 0x%0*Zx)",
+			      DSO_FILENAME (l->l_libname->name),
+			      DSO_FILENAME (l->l_name),
+			      (int) sizeof l->l_map_start * 2,
+			      disp_addr,
+			      (int) sizeof l->l_addr * 2,
+			      (size_t) l->l_addr);
+
+	          if (l->l_tls_modid)
+		    _dl_printf (" TLS(0x%Zx, 0x%0*Zx)\n", l->l_tls_modid,
+			        (int) sizeof l->l_tls_offset * 2,
+			        (size_t) l->l_tls_offset);
+	          else
+		    _dl_printf ("\n");
+	      }
 	    }
 	}
       else if (GLRO(dl_debug_mask) & DL_DEBUG_UNUSED)
@@ -2063,17 +2111,41 @@ of this helper program; chances are you did not intend to run this program.\n\
       else
 	{
 	  for (l = main_map->l_next; l; l = l->l_next)
+	  {
+	    /* Subtract and negate base from load address if requested  */
+	    disp_addr = (size_t) l->l_map_start;
+	    if (trace_addr_relative) disp_addr -= base_addr;
+	    if (trace_addr_negate) disp_addr = -disp_addr;
+
 	    if (l->l_faked)
 	      /* The library was not found.  */
 	      _dl_printf ("\t%s => not found\n", l->l_libname->name);
-	    else if (strcmp (l->l_libname->name, l->l_name) == 0)
-	      _dl_printf ("\t%s (0x%0*Zx)\n", l->l_libname->name,
-			  (int) sizeof l->l_map_start * 2,
-			  (size_t) l->l_map_start);
 	    else
-	      _dl_printf ("\t%s => %s (0x%0*Zx)\n", l->l_libname->name,
-			  l->l_name, (int) sizeof l->l_map_start * 2,
-			  (size_t) l->l_map_start);
+	      if (trace_addr_justify)
+		if (strcmp (l->l_libname->name, l->l_name) == 0)
+		  _dl_printf ("\t(%s0x%0*Zx) %s\n",
+			      trace_addr_negate ? "-" : "+",
+			      (int) sizeof l->l_map_start * 2,
+			      disp_addr,
+			      l->l_libname->name);
+		else
+		  _dl_printf ("\t(%s0x%0*Zx) %s => %s\n",
+			      trace_addr_negate ? "-" : "+",
+			      (int) sizeof l->l_map_start * 2,
+			      disp_addr,
+			      l->l_libname->name, l->l_name);
+	      else
+		if (strcmp (l->l_libname->name, l->l_name) == 0)
+		  _dl_printf ("\t%s (0x%0*Zx)\n",
+			      l->l_libname->name,
+			      (int) sizeof l->l_map_start * 2,
+			      disp_addr);
+		else
+		  _dl_printf ("\t%s => %s (0x%0*Zx)\n",
+			      l->l_libname->name,
+			      l->l_name, (int) sizeof l->l_map_start * 2,
+			      disp_addr);
+	  }
 	}
 
       if (__builtin_expect (mode, trace) != trace)
@@ -2761,6 +2833,27 @@ process_envvars (enum mode *modep, struct audit_list *audit_list)
 	    }
 	  break;
 
+	case 17:
+	  /* Addresses can be negated.  */
+	  if (!__libc_enable_secure
+	      && memcmp (envline, "TRACE_ADDR_NEGATE", 17) == 0)
+	      trace_addr_negate = envline[18] != '\0';
+	  break;
+
+	case 18:
+	  /* Addresses can be left-justified.  */
+	  if (!__libc_enable_secure
+	      && memcmp (envline, "TRACE_ADDR_JUSTIFY", 18) == 0)
+	      trace_addr_justify = envline[19] != '\0';
+	  break;
+
+	case 19:
+	  /* Absolute addresses can be displayed.  */
+	  if (!__libc_enable_secure
+	      && memcmp (envline, "TRACE_ADDR_ABSOLUTE", 19) == 0)
+	      trace_addr_relative = envline[20] == '\0';
+	  break;
+
 	case 20:
 	  /* The mode of the dynamic linker can be set.  */
 	  if (memcmp (envline, "TRACE_LOADED_OBJECTS", 20) == 0)
