malloc: Remove LD_TRACE_PRELINKING usage from mtrace

The fix for BZ#22716 replacde LD_TRACE_LOADED_OBJECTS with
LD_TRACE_PRELINKING so mtrace could record executable address
position.

To provide the same information, LD_TRACE_LOADED_OBJECTS is
extended where a value or '2' also prints the executable address
as well.  It avoid adding another loader environment variable
to be used solely for mtrace.  The vDSO will be printed as
a default library (with '=>' pointing the same name), which is
ok since both mtrace and ldd already handles it.

The mtrace script is changed to also parse the new format.  To
correctly support PIE and non-PIE executables, both the default
mtrace address and the one calculated as used (it fixes mtrace
for non-PIE exectuable as for BZ#22716 for PIE).

Checked on x86_64-linux-gnu.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
This commit is contained in:
Adhemerval Zanella 2022-01-21 10:20:50 -03:00
parent 6628c742b2
commit d7703d3176
4 changed files with 51 additions and 33 deletions

4
NEWS
View File

@ -193,6 +193,10 @@ Deprecated and removed features, and other changes affecting compatibility:
removal of the LD_TRACE_PRELINKING, and LD_USE_LOAD_BIAS, environment removal of the LD_TRACE_PRELINKING, and LD_USE_LOAD_BIAS, environment
variables and their functionality in the dynamic loader. variables and their functionality in the dynamic loader.
* The LD_TRACE_PRELINKING environment variable has been removed. Similar
functionality to obtain the program mapping address can be achieved by
using LD_TRACE_LOADED_OBJECTS to value of 2.
Changes to build and runtime requirements: Changes to build and runtime requirements:
* The audit module interface version LAV_CURRENT is increased to enable * The audit module interface version LAV_CURRENT is increased to enable

View File

@ -94,6 +94,9 @@ struct dl_main_state
enum rtld_mode mode; enum rtld_mode mode;
/* True if program should be also printed for rtld_mode_trace. */
bool mode_trace_program;
/* True if any of the debugging options is enabled. */ /* True if any of the debugging options is enabled. */
bool any_debug; bool any_debug;

View File

@ -2104,18 +2104,18 @@ dl_main (const ElfW(Phdr) *phdr,
_dl_printf ("\tstatically linked\n"); _dl_printf ("\tstatically linked\n");
else else
{ {
for (l = main_map->l_next; l; l = l->l_next) for (l = state.mode_trace_program ? main_map : main_map->l_next;
l; l = l->l_next) {
if (l->l_faked) if (l->l_faked)
/* The library was not found. */ /* The library was not found. */
_dl_printf ("\t%s => not found\n", l->l_libname->name); _dl_printf ("\t%s => not found\n", l->l_libname->name);
else if (strcmp (l->l_libname->name, l->l_name) == 0) else
_dl_printf ("\t%s (0x%0*Zx)\n", l->l_libname->name, _dl_printf ("\t%s => %s (0x%0*Zx)\n",
DSO_FILENAME (l->l_libname->name),
DSO_FILENAME (l->l_name),
(int) sizeof l->l_map_start * 2, (int) sizeof l->l_map_start * 2,
(size_t) l->l_map_start); (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 (__glibc_unlikely (state.mode != rtld_mode_trace)) if (__glibc_unlikely (state.mode != rtld_mode_trace))
@ -2676,7 +2676,11 @@ process_envvars (struct dl_main_state *state)
case 20: case 20:
/* The mode of the dynamic linker can be set. */ /* The mode of the dynamic linker can be set. */
if (memcmp (envline, "TRACE_LOADED_OBJECTS", 20) == 0) if (memcmp (envline, "TRACE_LOADED_OBJECTS", 20) == 0)
{
state->mode = rtld_mode_trace; state->mode = rtld_mode_trace;
state->mode_trace_program
= _dl_strtoul (&envline[21], NULL) > 1;
}
break; break;
/* We might have some extra environment variable to handle. This /* We might have some extra environment variable to handle. This

View File

@ -74,15 +74,14 @@ if ($#ARGV == 0) {
} else { } else {
$prog = "./$binary"; $prog = "./$binary";
} }
# Set the environment variable LD_TRACE_PRELINKING to an empty string so # Set the environment variable LD_TRACE_LOADED_OBJECTS to 2 so the
# that we trigger tracing but do not match with the executable or any of # executable is also printed.
# its dependencies. if (open (locs, "env LD_TRACE_LOADED_OBJECTS=2 $prog |")) {
if (open (LOCS, "env LD_TRACE_PRELINKING= $prog |")) { while (<locs>) {
while (<LOCS>) {
chop; chop;
if (/^.*=> (.*) \((0x[0123456789abcdef]*), (0x[0123456789abcdef]*).*/) { if (/^.*=> (.*) .(0x[0123456789abcdef]*).$/) {
$locs{$1} = $2; $locs{$1} = $2;
$rel{$1} = hex($2) - hex($3); $rel{$1} = hex($2);
} }
} }
close (LOCS); close (LOCS);
@ -91,6 +90,18 @@ if ($#ARGV == 0) {
die "Wrong number of arguments, run $progname --help for help."; die "Wrong number of arguments, run $progname --help for help.";
} }
sub addr2line {
my $addr = pop(@_);
my $prog = pop(@_);
if (open (ADDR, "addr2line -e $prog $addr|")) {
my $line = <ADDR>;
chomp $line;
close (ADDR);
if ($line ne '??:0') {
return $line
}
}
}
sub location { sub location {
my $str = pop(@_); my $str = pop(@_);
return $str if ($str eq ""); return $str if ($str eq "");
@ -98,11 +109,9 @@ sub location {
my $addr = $1; my $addr = $1;
my $fct = $2; my $fct = $2;
return $cache{$addr} if (exists $cache{$addr}); return $cache{$addr} if (exists $cache{$addr});
if ($binary ne "" && open (ADDR, "addr2line -e $binary $addr|")) { if ($binary ne "") {
my $line = <ADDR>; my $line = &addr2line($binary, $addr);
chomp $line; if ($line) {
close (ADDR);
if ($line ne '??:0') {
$cache{$addr} = $line; $cache{$addr} = $line;
return $cache{$addr}; return $cache{$addr};
} }
@ -114,24 +123,22 @@ sub location {
my $searchaddr; my $searchaddr;
return $cache{$addr} if (exists $cache{$addr}); return $cache{$addr} if (exists $cache{$addr});
$searchaddr = sprintf "%#x", hex($addr) + $rel{$prog}; $searchaddr = sprintf "%#x", hex($addr) + $rel{$prog};
if ($binary ne "" && open (ADDR, "addr2line -e $prog $searchaddr|")) { if ($binary ne "") {
my $line = <ADDR>; for my $address ($searchaddr, $addr) {
chomp $line; my $line = &addr2line($prog, $address);
close (ADDR); if ($line) {
if ($line ne '??:0') {
$cache{$addr} = $line; $cache{$addr} = $line;
return $cache{$addr}; return $cache{$addr};
} }
} }
}
$cache{$addr} = $str = $addr; $cache{$addr} = $str = $addr;
} elsif ($str =~ /^.*[[](0x[^]]*)]$/) { } elsif ($str =~ /^.*[[](0x[^]]*)]$/) {
my $addr = $1; my $addr = $1;
return $cache{$addr} if (exists $cache{$addr}); return $cache{$addr} if (exists $cache{$addr});
if ($binary ne "" && open (ADDR, "addr2line -e $binary $addr|")) { if ($binary ne "") {
my $line = <ADDR>; my $line = &addr2line($binary, $addr);
chomp $line; if ($line) {
close (ADDR);
if ($line ne '??:0') {
$cache{$addr} = $line; $cache{$addr} = $line;
return $cache{$addr}; return $cache{$addr};
} }