What steps will reproduce the problem?
1. Build chromium for Android with packed relocations.
2. Capture a .prof file.
3. Process with pprof.
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.
$ diff -c ./gperftools-2.2.1/src/pprof ./pprof
*** ./gperftools-2.2.1/src/pprof 2014-04-13 02:35:40.000000000 +0100
--- ./pprof 2014-10-13 16:48:37.039256051 +0100
***************
*** 4352,4357 ****
--- 4352,4358 ----
my $zero_offset = HexExtend("0");
my $buildvar = "";
+ my $priorlib = "";
foreach my $l (split("\n", $map)) {
if ($l =~ m/^\s*build=(.*)$/) {
$buildvar = $1;
***************
*** 4408,4414 ****
--- 4409,4424 ----
}
}
+ # 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)
Original issue reported on code.google.com by sim...@google.com on 15 Oct 2014 at 1:30
Original issue reported on code.google.com by
sim...@google.com
on 15 Oct 2014 at 1:30