Subject: [PATCH] ldd trace left-justified relative addresses

Message ID 20201006054255.1676065-1-michaeljclark@mac.com
State Superseded
Headers
Series Subject: [PATCH] ldd trace left-justified relative addresses |

Commit Message

Michael Clark Oct. 6, 2020, 5:42 a.m. UTC
  Folks,

Sharing a patch for ld.so for relative addresses and left-justified
output. The goal of this patch is to increase `ldd` readability:

 - modify trace output to use relative addresses by default.
 - add alternative trace output mode with left-justified 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.

* Justified output *

The new trace format is enabled with `LD_TRACE_ADDR_JUSTIFY=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 patch adds three new ld.so flags accessible via environment variables:

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

It would also be trivial to add a base addend, or make addresses relative
to the program instead of the loader, or add a program header virtual
address, essentially translating away signs of ASLR. There is also the
absolute address compatibility mode for checking that ASLR is still alive.

Anyhow, feedbackup welcome...

Regards,
Michael

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

$ LD_TRACE_ADDR_NEGATE=1 \
  LD_TRACE_ADDR_JUSTIFY=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 | 133 +++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 113 insertions(+), 20 deletions(-)
  

Comments

Michael Clark Oct. 6, 2020, 8:37 p.m. UTC | #1
> On 6/10/2020, at 6:43 PM, Michael Clark <michaeljclark@mac.com> wrote:
> 
> Folks,
> 
> Sharing a patch for ld.so for relative addresses and left-justified
> output. The goal of this patch is to increase `ldd` readability:
> 
> - modify trace output to use relative addresses by default.
> - add alternative trace output mode with left-justified 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.
> 
> * Justified output *
> 
> The new trace format is enabled with `LD_TRACE_ADDR_JUSTIFY=1`, otherwise
> the default `ldd` trace format is selected by default for compatibility.

Justified is not precise for this parameter because if it were justified the right edge would be aligned. TRACE_LEFT_ALIGN is possibly more correct.

I also realise I mucked up git send-email by forgetting git just picks the first line as the subject. …and this mail will also probably get munged because I’m sending it from Apple whitespace munger on my phone.

It seems that I have to get used to making lots of mistakes on public mailing lists if I want to participate in open source.

P.S. There is no postscript. Only Ghostscript.

> * 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 patch adds three new ld.so flags accessible via environment variables:
> 
> - `LD_TRACE_ADDR_JUSTIFY=1` - Show addresses left-justified
> - `LD_TRACE_ADDR_ABSOLUTE=1` - Show absolute addresses (backwards compat)
> - `LD_TRACE_ADDR_NEGATE=1` - Show negated addresses (combination option)
> 
> It would also be trivial to add a base addend, or make addresses relative
> to the program instead of the loader, or add a program header virtual
> address, essentially translating away signs of ASLR. There is also the
> absolute address compatibility mode for checking that ASLR is still alive.
> 
> Anyhow, feedbackup welcome...
> 
> Regards,
> Michael
> 
> Signed-off-by: Michael Clark <michaeljclark@mac.com>
> 
> $ LD_TRACE_ADDR_NEGATE=1 \
>  LD_TRACE_ADDR_JUSTIFY=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 | 133 +++++++++++++++++++++++++++++++++++++++++++++--------
> 1 file changed, 113 insertions(+), 20 deletions(-)
> 
> 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)
> -- 
> 2.25.1
>
  

Patch

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)