[v3] mtrace: Fix output with PIE and ASLR [BZ #22716]
Checks
Context |
Check |
Description |
dj/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
dj/TryBot-32bit |
success
|
Build for i686
|
Commit Message
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(-)
Comments
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;
>>
>
@@ -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);
@@ -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;