unofficial mirror of libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Michael Clark via Libc-alpha <libc-alpha@sourceware.org>
To: libc-alpha@sourceware.org
Subject: [PATCH v2] ldd: revise trace output for left-aligned relative addresses
Date: Wed,  7 Oct 2020 12:56:48 +1300	[thread overview]
Message-ID: <20201006235648.1811725-1-michaeljclark@mac.com> (raw)
In-Reply-To: <20201006054255.1676065-1-michaeljclark@mac.com>

This change updates ld.so trace for left-aligned relative addresses.
The primary goal of this change is to increase `ldd` readability by:

 - modifying trace output to use relative addresses by default.
 - adding an alternative trace output mode with left-aligned addresses.

The relative addresses are composed by subtracting the ELF ehdr address
which makes the output constant under address space layout randomization.
This should be a safe change because the default format is preserved.

The intention is to make `ldd` easier to cross reference with objdump.
Also, log files including `ldd` output will contain less differences as
the vdso is the only address that changes when using relative addresses.

* Aligned output *

The new trace format is enabled with `LD_TRACE_ADDR_ALIGN=1`, otherwise
the default `ldd` trace format is selected by default for compatibility.

* Relative addresses *

`ldd` load addresses are displayed relative to the ld.so executable header
address. Relative addresses are enabled by default, given the output mimics
systems without ASLR, thus there should be minimal compatibility issues.
There is also an option to negate addresses as an aid in interpreting them,
seeing library addresses relative to the loader with negative offsets.

The changes adds three new ld.so flags accessible via environment variables:

 - `LD_TRACE_ADDR_ALIGN=1` - Show addresses left-aligned
 - `LD_TRACE_ADDR_ABSOLUTE=1` - Show absolute addresses (backwards compat)
 - `LD_TRACE_ADDR_NEGATE=1` - Show negated addresses (combination option)

Changelog

* v1 - initial version
* v2 - change address alignment variable name to LD_TRACE_ADDR_ALIGN=1

Signed-off-by: Michael Clark <michaeljclark@mac.com>

$ LD_TRACE_ADDR_ALIGN=1 \
  LD_TRACE_ADDR_NEGATE=1 \
  LD_TRACE_LOADED_OBJECTS=1 \
  build-tree/amd64-libc/elf/ld.so /usr/bin/Xwayland
	(-0xffffffc381cdd000) linux-vdso.so.1
	(-0x00000000002b7000) libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1
	(-0x00000000003d5000) libgcrypt.so.20 => /usr/lib/x86_64-linux-gnu/libgcrypt.so.20
	(-0x00000000003db000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2
	(-0x00000000003f8000) libunwind.so.8 => /usr/lib/x86_64-linux-gnu/libunwind.so.8
	(-0x0000000000409000) libwayland-client.so.0 => /usr/lib/x86_64-linux-gnu/libwayland-client.so.0
	(-0x000000000041d000) libdrm.so.2 => /usr/lib/x86_64-linux-gnu/libdrm.so.2
	(-0x00000000004c6000) libpixman-1.so.0 => /usr/lib/x86_64-linux-gnu/libpixman-1.so.0
	(-0x00000000006f4000) libXfont2.so.2 => /usr/lib/x86_64-linux-gnu/libXfont2.so.2
	(-0x00000000006fa000) libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6
	(-0x00000000007a7000) libsystemd.so.0 => /lib/x86_64-linux-gnu/libsystemd.so.0
	(-0x00000000009a9000) libxshmfence.so.1 => /usr/lib/x86_64-linux-gnu/libxshmfence.so.1
	(-0x00000000009b1000) libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6
	(-0x0000000000ae6000) libepoxy.so.0 => /usr/lib/x86_64-linux-gnu/libepoxy.so.0
	(-0x0000000000af7000) libgbm.so.1 => /usr/lib/x86_64-linux-gnu/libgbm.so.1
	(-0x0000000000b7f000) libGL.so.1 => /usr/lib/x86_64-linux-gnu/libGL.so.1
	(-0x0000000000bab000) libaudit.so.1 => /lib/x86_64-linux-gnu/libaudit.so.1
	(-0x0000000000cfa000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6
	(-0x0000000000d14000) libbsd.so.0 => /usr/lib/x86_64-linux-gnu/libbsd.so.0
	(-0x0000000000d39000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0
	(-0x0000000000f2b000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6
	(-0x0000000000fbb000) libpcre2-8.so.0 => /usr/lib/x86_64-linux-gnu/libpcre2-8.so.0
	(-0x0000000000000000) /lib64/ld-linux-x86-64.so.2 => build-tree/amd64-libc/elf/ld.so
	(-0x0000000000fde000) libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0
	(-0x0000000001007000) liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5
	(-0x0000000001013000) libffi.so.7 => /usr/lib/x86_64-linux-gnu/libffi.so.7
	(-0x0000000001031000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1
	(-0x0000000001044000) libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0
	(-0x000000000104e000) libfontenc.so.1 => /usr/lib/x86_64-linux-gnu/libfontenc.so.1
	(-0x000000000110d000) libfreetype.so.6 => /usr/lib/x86_64-linux-gnu/libfreetype.so.6
	(-0x0000000001118000) librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1
	(-0x0000000001139000) liblz4.so.1 => /usr/lib/x86_64-linux-gnu/liblz4.so.1
	(-0x0000000001151000) libwayland-server.so.0 => /usr/lib/x86_64-linux-gnu/libwayland-server.so.0
	(-0x000000000117f000) libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1
	(-0x0000000001237000) libGLdispatch.so.0 => /usr/lib/x86_64-linux-gnu/libGLdispatch.so.0
	(-0x000000000126b000) libGLX.so.0 => /usr/lib/x86_64-linux-gnu/libGLX.so.0
	(-0x0000000001273000) libcap-ng.so.0 => /lib/x86_64-linux-gnu/libcap-ng.so.0
	(-0x00000000012ad000) libpng16.so.16 => /usr/lib/x86_64-linux-gnu/libpng16.so.16
	(-0x00000000013ea000) libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6
	(-0x0000000001414000) libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1

$ LD_TRACE_ADDR_ABSOLUTE=1 \
  LD_TRACE_LOADED_OBJECTS=1 \
  build-tree/amd64-libc/elf/ld.so  /usr/bin/Xwayland
	linux-vdso.so.1 (0x00007fff12dee000)
	libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f310f6f8000)
	libgcrypt.so.20 => /usr/lib/x86_64-linux-gnu/libgcrypt.so.20 (0x00007f310f5da000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f310f5d4000)
	libunwind.so.8 => /usr/lib/x86_64-linux-gnu/libunwind.so.8 (0x00007f310f5b7000)
	libwayland-client.so.0 => /usr/lib/x86_64-linux-gnu/libwayland-client.so.0 (0x00007f310f5a6000)
	libdrm.so.2 => /usr/lib/x86_64-linux-gnu/libdrm.so.2 (0x00007f310f592000)
	libpixman-1.so.0 => /usr/lib/x86_64-linux-gnu/libpixman-1.so.0 (0x00007f310f4e9000)
	libXfont2.so.2 => /usr/lib/x86_64-linux-gnu/libXfont2.so.2 (0x00007f310f2bb000)
	libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007f310f2b5000)
	libsystemd.so.0 => /lib/x86_64-linux-gnu/libsystemd.so.0 (0x00007f310f208000)
	libxshmfence.so.1 => /usr/lib/x86_64-linux-gnu/libxshmfence.so.1 (0x00007f310f006000)
	libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f310effe000)
	libepoxy.so.0 => /usr/lib/x86_64-linux-gnu/libepoxy.so.0 (0x00007f310eec9000)
	libgbm.so.1 => /usr/lib/x86_64-linux-gnu/libgbm.so.1 (0x00007f310eeb8000)
	libGL.so.1 => /usr/lib/x86_64-linux-gnu/libGL.so.1 (0x00007f310ee30000)
	libaudit.so.1 => /lib/x86_64-linux-gnu/libaudit.so.1 (0x00007f310ee04000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f310ecb5000)
	libbsd.so.0 => /usr/lib/x86_64-linux-gnu/libbsd.so.0 (0x00007f310ec9b000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f310ec76000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f310ea84000)
	libpcre2-8.so.0 => /usr/lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007f310e9f4000)
	/lib64/ld-linux-x86-64.so.2 => build-tree/amd64-libc/elf/ld.so (0x00007f310f9af000)
	libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007f310e9d1000)
	liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f310e9a8000)
	libffi.so.7 => /usr/lib/x86_64-linux-gnu/libffi.so.7 (0x00007f310e99c000)
	libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f310e97e000)
	libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0 (0x00007f310e96b000)
	libfontenc.so.1 => /usr/lib/x86_64-linux-gnu/libfontenc.so.1 (0x00007f310e961000)
	libfreetype.so.6 => /usr/lib/x86_64-linux-gnu/libfreetype.so.6 (0x00007f310e8a2000)
	librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f310e897000)
	liblz4.so.1 => /usr/lib/x86_64-linux-gnu/liblz4.so.1 (0x00007f310e876000)
	libwayland-server.so.0 => /usr/lib/x86_64-linux-gnu/libwayland-server.so.0 (0x00007f310e85e000)
	libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007f310e830000)
	libGLdispatch.so.0 => /usr/lib/x86_64-linux-gnu/libGLdispatch.so.0 (0x00007f310e778000)
	libGLX.so.0 => /usr/lib/x86_64-linux-gnu/libGLX.so.0 (0x00007f310e744000)
	libcap-ng.so.0 => /lib/x86_64-linux-gnu/libcap-ng.so.0 (0x00007f310e73c000)
	libpng16.so.16 => /usr/lib/x86_64-linux-gnu/libpng16.so.16 (0x00007f310e702000)
	libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007f310e5c5000)
	libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f310e59b000)
---
 elf/rtld.c | 131 +++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 111 insertions(+), 20 deletions(-)

diff --git a/elf/rtld.c b/elf/rtld.c
index 9918fda05e76..236ccef5b9ec 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
+ * aligned 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-aligned addresses, making the listing
+ * easier to read because addresses are all lined up in one column.
+ * `LD_TRACE_ADDR_ALIGN=1` will left-align addresses.  */
+static int trace_addr_align = 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_align)
+	        {
+		  _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_align)
+		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)
@@ -2759,6 +2831,25 @@ process_envvars (enum mode *modep, struct audit_list *audit_list)
 	      GLRO(dl_debug_mask) |= DL_DEBUG_PRELINK;
 	      GLRO(dl_trace_prelink) = &envline[17];
 	    }
+
+    /* Addresses can be left-aligned.  */
+    if (!__libc_enable_secure
+        && memcmp (envline, "TRACE_ADDR_ALIGN", 16) == 0)
+        trace_addr_align = envline[17] != '\0';
+    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 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:
-- 
2.25.1


  parent reply	other threads:[~2020-10-06 23:57 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-06  5:42 [PATCH] Subject: [PATCH] ldd trace left-justified relative addresses Michael Clark via Libc-alpha
2020-10-06 20:37 ` Michael Clark via Libc-alpha
2020-10-06 23:56 ` Michael Clark via Libc-alpha [this message]
2020-10-07  0:12   ` [PATCH v2] ldd: revise trace output for left-aligned " Zack Weinberg
2020-10-07  0:40     ` Michael Clark via Libc-alpha
2020-10-07 21:01   ` Adhemerval Zanella via Libc-alpha
2020-10-08  5:44     ` Michael Clark via Libc-alpha
2020-10-08 12:09       ` Adhemerval Zanella via Libc-alpha
2020-10-09  4:30         ` Michael Clark via Libc-alpha

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/libc/involved.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201006235648.1811725-1-michaeljclark@mac.com \
    --to=libc-alpha@sourceware.org \
    --cc=michaeljclark@mac.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).