diff options
author | Aliaksey Kandratsenka <alk@tut.by> | 2014-10-18 16:35:57 -0700 |
---|---|---|
committer | Aliaksey Kandratsenka <alk@tut.by> | 2014-10-18 16:35:57 -0700 |
commit | 8c3dc52fcfe02412a529769a22cbc75388a5d368 (patch) | |
tree | b83c4963199bd98891fef1cb01046f236e40b8ab | |
parent | 44c61ce6c4c713b194330641f400bbf64fd2abec (diff) | |
download | gperftools-8c3dc52fcfe02412a529769a22cbc75388a5d368.tar.gz |
issue-654: [pprof] handle split text segments
This applies patch by user simonb.
Quoting:
Relocation packing splits a single executable load segment into two. Before:
LOAD 0x000000 0x00000000 0x00000000 0x2034d28 0x2034d28 R E 0x1000
LOAD 0x2035888 0x02036888 0x02036888 0x182d38 0x1a67d0 RW 0x1000
After:
LOAD 0x000000 0x00000000 0x00000000 0x14648 0x14648 R E 0x1000
LOAD 0x014648 0x0020c648 0x0020c648 0x1e286e0 0x1e286e0 R E 0x1000
...
LOAD 0x1e3d888 0x02036888 0x02036888 0x182d38 0x1a67d0 RW 0x1000
The .text section is in the second LOAD, and this is not at
offset/address zero. The result is that this library shows up in
/proc/self/maps as multiple executable entries, for example (note:
this trace is not from the library dissected above, but rather from an
earlier version of it):
73b0c000-73b21000 r-xp 00000000 b3:19 786460 /data/.../libchrome.2160.0.so
73b21000-73d12000 ---p 00000000 00:00 0
73d12000-75a90000 r-xp 00014000 b3:19 786460 /data/.../libchrome.2160.0.so
75a90000-75c0d000 rw-p 01d91000 b3:19 786460 /data/.../libchrome.2160.0.so
When parsing this, pprof needs to merge the two r-xp entries above
into a single entry, otherwise the addresses it prints are incorrect.
The following fix against 2.2.1 was sufficient to make pprof --text
print the correct output. Untested with other pprof options.
-rwxr-xr-x | src/pprof | 10 |
1 files changed, 10 insertions, 0 deletions
@@ -4395,6 +4395,7 @@ sub ParseLibraries { my $zero_offset = HexExtend("0"); my $buildvar = ""; + my $priorlib = ""; foreach my $l (split("\n", $map)) { if ($l =~ m/^\s*build=(.*)$/) { $buildvar = $1; @@ -4451,7 +4452,16 @@ sub ParseLibraries { } } + # If we find multiple executable segments for a single library, merge them + # into a single entry that spans the complete address range. + if ($lib eq $priorlib) { + my $prior = pop(@{$result}); + $start = @$prior[1]; + # TODO $offset may be wrong if .text is not in the final segment. + } + push(@{$result}, [$lib, $start, $finish, $offset]); + $priorlib = $lib; } # Append special entry for additional library (not relocated) |