Message ID | 20210812090746.612090-1-siddhesh@sourceware.org |
---|---|
State | New |
Headers | show |
Series | [v3] mtrace: Fix output with PIE and ASLR [BZ #22716] | expand |
On 2021-08-12, Siddhesh Poyarekar <siddhesh@sourceware.org> wrote: > Record only the relative address of the caller in mtrace file. Use > LD_TRACE_PRELINKING to get the executable as well as binary vs > executable load offsets so that we may compute a base to add to the > relative address in the mtrace file. This allows us to get a valid > address to pass to addr2line in all cases. FWIW, I tested this using an executable with a memory leak that is linked to a shared library that also has a leak. Executable 1 compiled with "-pie -fPIE". Executable 2 compiled with "-no-pie -fno-PIE". Shared library compiled with "-fPIC". Tested both executables in ASLR and non-ASLR environments successfully. The only issue is that obviously trace files from older glibc will not work with this new mtrace and vice versa. But I suppose that is not a concern. John Ogness
Ping! I'll push this if there are no further objections. Thanks, Siddhesh On 8/12/21 2:37 PM, Siddhesh Poyarekar via Libc-alpha wrote: > Record only the relative address of the caller in mtrace file. Use > LD_TRACE_PRELINKING to get the executable as well as binary vs > executable load offsets so that we may compute a base to add to the > relative address in the mtrace file. This allows us to get a valid > address to pass to addr2line in all cases. > > Co-authored-by: John Ogness <john.ogness@linutronix.de> > --- > Changes from v2: > - Don't use "" > > Changes from v1: > - Set LD_TRACE_PRELINK to an empty string so that it doesn't match any > files and add a comment explaining it. > - Formatting change in mtrace-impl.c > > malloc/mtrace-impl.c | 6 +++--- > malloc/mtrace.pl | 15 +++++++-------- > 2 files changed, 10 insertions(+), 11 deletions(-) > > diff --git a/malloc/mtrace-impl.c b/malloc/mtrace-impl.c > index 9dffddfe2d..e7ace7f6fd 100644 > --- a/malloc/mtrace-impl.c > +++ b/malloc/mtrace-impl.c > @@ -67,9 +67,9 @@ tr_where (const void *caller, Dl_info *info) > offset); > } > > - fprintf (mallstream, "@ %s%s%s[%p] ", info->dli_fname ? : "", > - info->dli_fname ? ":" : "", > - buf, caller); > + fprintf (mallstream, "@ %s%s%s[0x%" PRIxPTR "] ", > + info->dli_fname ? : "", info->dli_fname ? ":" : "", buf, > + caller - info->dli_fbase); > } > else > fprintf (mallstream, "@ [%p] ", caller); > diff --git a/malloc/mtrace.pl b/malloc/mtrace.pl > index 6f49c8338d..b1073a1931 100644 > --- a/malloc/mtrace.pl > +++ b/malloc/mtrace.pl > @@ -75,11 +75,15 @@ if ($#ARGV == 0) { > } else { > $prog = "./$binary"; > } > - if (open (LOCS, "env LD_TRACE_LOADED_OBJECTS=1 $prog |")) { > + # Set the environment variable LD_TRACE_PRELINKING to an empty string so > + # that we trigger tracing but do not match with the executable or any of > + # its dependencies. > + if (open (LOCS, "env LD_TRACE_PRELINKING= $prog |")) { > while (<LOCS>) { > chop; > - if (/^.*=> (.*) .(0x[0123456789abcdef]*).$/) { > + if (/^.*=> (.*) \((0x[0123456789abcdef]*), (0x[0123456789abcdef]*).*/) { > $locs{$1} = $2; > + $rel{$1} = hex($2) - hex($3); > } > } > close (LOCS); > @@ -110,12 +114,7 @@ sub location { > my $addr = $2; > my $searchaddr; > return $cache{$addr} if (exists $cache{$addr}); > - if ($locs{$prog} ne "") { > - $searchaddr = sprintf "%#x", $addr - $locs{$prog}; > - } else { > - $searchaddr = $addr; > - $prog = $binary; > - } > + $searchaddr = sprintf "%#x", hex($addr) + $rel{$prog}; > if ($binary ne "" && open (ADDR, "addr2line -e $prog $searchaddr|")) { > my $line = <ADDR>; > chomp $line; >
I've pushed this now since the changes in v2 and v3 were trivial. Thanks, Siddhesh On 8/17/21 8:27 AM, Siddhesh Poyarekar wrote: > Ping! I'll push this if there are no further objections. > > Thanks, > Siddhesh > > On 8/12/21 2:37 PM, Siddhesh Poyarekar via Libc-alpha wrote: >> Record only the relative address of the caller in mtrace file. Use >> LD_TRACE_PRELINKING to get the executable as well as binary vs >> executable load offsets so that we may compute a base to add to the >> relative address in the mtrace file. This allows us to get a valid >> address to pass to addr2line in all cases. >> >> Co-authored-by: John Ogness <john.ogness@linutronix.de> >> --- >> Changes from v2: >> - Don't use "" >> >> Changes from v1: >> - Set LD_TRACE_PRELINK to an empty string so that it doesn't match any >> files and add a comment explaining it. >> - Formatting change in mtrace-impl.c >> >> malloc/mtrace-impl.c | 6 +++--- >> malloc/mtrace.pl | 15 +++++++-------- >> 2 files changed, 10 insertions(+), 11 deletions(-) >> >> diff --git a/malloc/mtrace-impl.c b/malloc/mtrace-impl.c >> index 9dffddfe2d..e7ace7f6fd 100644 >> --- a/malloc/mtrace-impl.c >> +++ b/malloc/mtrace-impl.c >> @@ -67,9 +67,9 @@ tr_where (const void *caller, Dl_info *info) >> offset); >> } >> - fprintf (mallstream, "@ %s%s%s[%p] ", info->dli_fname ? : "", >> - info->dli_fname ? ":" : "", >> - buf, caller); >> + fprintf (mallstream, "@ %s%s%s[0x%" PRIxPTR "] ", >> + info->dli_fname ? : "", info->dli_fname ? ":" : "", buf, >> + caller - info->dli_fbase); >> } >> else >> fprintf (mallstream, "@ [%p] ", caller); >> diff --git a/malloc/mtrace.pl b/malloc/mtrace.pl >> index 6f49c8338d..b1073a1931 100644 >> --- a/malloc/mtrace.pl >> +++ b/malloc/mtrace.pl >> @@ -75,11 +75,15 @@ if ($#ARGV == 0) { >> } else { >> $prog = "./$binary"; >> } >> - if (open (LOCS, "env LD_TRACE_LOADED_OBJECTS=1 $prog |")) { >> + # Set the environment variable LD_TRACE_PRELINKING to an empty >> string so >> + # that we trigger tracing but do not match with the executable or >> any of >> + # its dependencies. >> + if (open (LOCS, "env LD_TRACE_PRELINKING= $prog |")) { >> while (<LOCS>) { >> chop; >> - if (/^.*=> (.*) .(0x[0123456789abcdef]*).$/) { >> + if (/^.*=> (.*) \((0x[0123456789abcdef]*), >> (0x[0123456789abcdef]*).*/) { >> $locs{$1} = $2; >> + $rel{$1} = hex($2) - hex($3); >> } >> } >> close (LOCS); >> @@ -110,12 +114,7 @@ sub location { >> my $addr = $2; >> my $searchaddr; >> return $cache{$addr} if (exists $cache{$addr}); >> - if ($locs{$prog} ne "") { >> - $searchaddr = sprintf "%#x", $addr - $locs{$prog}; >> - } else { >> - $searchaddr = $addr; >> - $prog = $binary; >> - } >> + $searchaddr = sprintf "%#x", hex($addr) + $rel{$prog}; >> if ($binary ne "" && open (ADDR, "addr2line -e $prog >> $searchaddr|")) { >> my $line = <ADDR>; >> chomp $line; >> >
diff --git a/malloc/mtrace-impl.c b/malloc/mtrace-impl.c index 9dffddfe2d..e7ace7f6fd 100644 --- a/malloc/mtrace-impl.c +++ b/malloc/mtrace-impl.c @@ -67,9 +67,9 @@ tr_where (const void *caller, Dl_info *info) offset); } - fprintf (mallstream, "@ %s%s%s[%p] ", info->dli_fname ? : "", - info->dli_fname ? ":" : "", - buf, caller); + fprintf (mallstream, "@ %s%s%s[0x%" PRIxPTR "] ", + info->dli_fname ? : "", info->dli_fname ? ":" : "", buf, + caller - info->dli_fbase); } else fprintf (mallstream, "@ [%p] ", caller); diff --git a/malloc/mtrace.pl b/malloc/mtrace.pl index 6f49c8338d..b1073a1931 100644 --- a/malloc/mtrace.pl +++ b/malloc/mtrace.pl @@ -75,11 +75,15 @@ if ($#ARGV == 0) { } else { $prog = "./$binary"; } - if (open (LOCS, "env LD_TRACE_LOADED_OBJECTS=1 $prog |")) { + # Set the environment variable LD_TRACE_PRELINKING to an empty string so + # that we trigger tracing but do not match with the executable or any of + # its dependencies. + if (open (LOCS, "env LD_TRACE_PRELINKING= $prog |")) { while (<LOCS>) { chop; - if (/^.*=> (.*) .(0x[0123456789abcdef]*).$/) { + if (/^.*=> (.*) \((0x[0123456789abcdef]*), (0x[0123456789abcdef]*).*/) { $locs{$1} = $2; + $rel{$1} = hex($2) - hex($3); } } close (LOCS); @@ -110,12 +114,7 @@ sub location { my $addr = $2; my $searchaddr; return $cache{$addr} if (exists $cache{$addr}); - if ($locs{$prog} ne "") { - $searchaddr = sprintf "%#x", $addr - $locs{$prog}; - } else { - $searchaddr = $addr; - $prog = $binary; - } + $searchaddr = sprintf "%#x", hex($addr) + $rel{$prog}; if ($binary ne "" && open (ADDR, "addr2line -e $prog $searchaddr|")) { my $line = <ADDR>; chomp $line;