-
Notifications
You must be signed in to change notification settings - Fork 619
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add GetBase support for ASLR kernel mappings #371
Conversation
Linux Perf reports kernel mappings with an offset == start. Currently GetBase() cannot handle such a case. This behavior can be seen from a perf.report data with samples in the kernel: $ sudo perf report -D perf.data | grep MMAP 0 0x108 [0x50]: PERF_RECORD_MMAP -1/0: [0xffffffffaf800000(0x1087a000) @ 0xffffffffaf800000]: x [kernel.kallsyms]_text
Codecov Report
@@ Coverage Diff @@
## master #371 +/- ##
==========================================
+ Coverage 66.88% 66.89% +0.01%
==========================================
Files 36 36
Lines 7495 7495
==========================================
+ Hits 5013 5014 +1
+ Misses 2080 2079 -1
Partials 402 402
Continue to review full report at Codecov.
|
internal/elfexec/elfexec.go
Outdated
// Some kernels look like: | ||
// VADDR=0xffffffff80200000 | ||
// stextOffset=0xffffffff80200198 | ||
// Start=0xffffffff83200000 | ||
// Limit=0xffffffff84200000 | ||
// Offset=0 (0xc000000000000000 for PowerPC64) | ||
// Offset=0 (0xc000000000000000 for PowerPC64) (==Start for Linux Perf) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this case corresponds to when KASLR is active, so I'd reflect that in the comment and PR description. Some experimentation:
$ sudo cat /proc/kallsyms | grep _stext
ffffffff866002b8 T _stext
$ sudo perf record sleep 5
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.018 MB perf.data (7 samples) ]
$ pprof -raw perf.data | tail -3
Mappings
1: 0x0/0x1/0x0 perf_4.9 <build ID redacted>
2: 0xffffffff86600000/0xffffffffc030a000/0xffffffff86600000 [kernel.kallsyms] <build ID redacted>
Then rebooted the machine and did the same (note changed addresses):
$ sudo cat /proc/kallsyms | grep _stext
[sudo] password for aalexand:
ffffffff892002b8 T _stext
$ sudo perf record sleep 5
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.018 MB perf.data (2 samples) ]
$ pprof -raw perf.data | tail -3
Mappings
1: 0x0/0x1/0x0 perf_4.9 <build ID redacted>
2: 0xffffffff89200000/0xffffffffc0338000/0xffffffff89200000 [kernel.kallsyms] <build ID redacted>
internal/elfexec/elfexec_test.go
Outdated
@@ -55,6 +55,8 @@ func TestGetBase(t *testing.T) { | |||
{"exec offset 2", fhExec, lsOffset, nil, 0x200000, 0x600000, 0, 0, false}, | |||
{"exec nomap", fhExec, nil, nil, 0, 0, 0, 0, false}, | |||
{"exec kernel", fhExec, kernelHeader, uint64p(0xffffffff81000198), 0xffffffff82000198, 0xffffffff83000198, 0, 0x1000000, false}, | |||
{"exec kernel perf offset0", fhExec, kernelHeader, uint64p(0xffffffff810002b8), 0xffffffff81000000, 0xffffffffa0000000, 0x0, 0x0, false}, | |||
{"exec kernel perf", fhExec, kernelHeader, uint64p(0xffffffff810002b8), 0xffffffff81000000, 0xffffffffa0000000, 0xffffffff81000000, 0x0, false}, | |||
{"exec PPC64 kernel", fhExec, ppc64KernelHeader, uint64p(0xc000000000000000), 0xc000000000000000, 0xd00000001a730000, 0xc000000000000000, 0x0, false}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this case passes the new check so the condition for pageOffsetPpc64 and the constant can be removed?
internal/elfexec/elfexec_test.go
Outdated
@@ -55,6 +55,8 @@ func TestGetBase(t *testing.T) { | |||
{"exec offset 2", fhExec, lsOffset, nil, 0x200000, 0x600000, 0, 0, false}, | |||
{"exec nomap", fhExec, nil, nil, 0, 0, 0, 0, false}, | |||
{"exec kernel", fhExec, kernelHeader, uint64p(0xffffffff81000198), 0xffffffff82000198, 0xffffffff83000198, 0, 0x1000000, false}, | |||
{"exec kernel perf offset0", fhExec, kernelHeader, uint64p(0xffffffff810002b8), 0xffffffff81000000, 0xffffffffa0000000, 0x0, 0x0, false}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to other comments, I'd maybe say "KASLR" instead of "perf" in this and next test case since I am not sure there is much specifics to Linux perf, I think it's more about the mechanics of kernel loading.
For the record, #299 also fixed some issues with processing KASLR'ed kernels. The MMAP in the perf.data there was
which I think the same what we are seeing here, not sure why #299 worked there but not here. |
The only way I can see #299 work is if loadSegment.Vaddr == loadSegment.Off |
* 'master' of github.com:google/pprof: (32 commits) record diff base profile label key/value constant (google#384) apply additional command overrides based on report format (google#381) profile: fix legacy format Go heap profile parsing (google#382) add -diff flag for better profile comparision (google#369) Use -u flag in pprof installation command so that it updates if needed. (google#376) Add GetBase support for ASLR kernel mappings (google#371) Add show_from profile filter. (google#372) Update README.md due to 8dff45d (google#375) Remove stale docs, move useful ones. (google#374) internal/driver: skip tests requiring tcp on js (google#373) Add "trim path" option which can be used to relocate sources. (google#366) Move update_d3flamegraph.sh script from the root directory. (google#370) Skip unsymbolizable mapping during symbolz pass. (google#368) remove -positive_percentages flag (google#365) Render icicle graph in "Flame Graph" view (google#367) Add command-line editing support for interactive pprof (google#362) Improve profile filter unit tests, fix show filtering of mappings (google#354) Fake mappings should be merged into a single one during merging (google#357) Hack the code so that both existing Go versions and current Go master format it the same (google#358) moved filter tests into their own test file which matches the implementation file, filter.go. (google#356) ...
Add GetBase support for kernel mappings as reported by Linux Perf Linux Perf reports kernel mappings with an offset == start. Currently GetBase() cannot handle such a case. This behavior can be seen from a perf.report data with samples in the kernel: $ sudo perf report -D perf.data | grep MMAP 0 0x108 [0x50]: PERF_RECORD_MMAP -1/0: [0xffffffffaf800000(0x1087a000) @ 0xffffffffaf800000]: x [kernel.kallsyms]_text
ASLR kernel mappings include offset == start.
Currently GetBase() cannot handle such a case.
This behavior can be seen from a perf.report data with samples in the kernel:
$ sudo perf report -D perf.data | grep MMAP
0 0x108 [0x50]: PERF_RECORD_MMAP -1/0: [0xffffffffaf800000(0x1087a000) @ 0xffffffffaf800000]: x [kernel.kallsyms]_text
Also added a testcase to reproduce and document.