Tweak our symbol resolution again - #336
Conversation
|
The 3.15 CI failures can be ignored. Those failures currently exist on main, and will be fixed by rebasing after #337 is merged. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #336 +/- ##
==========================================
- Coverage 77.63% 77.55% -0.09%
==========================================
Files 57 57
Lines 6601 6612 +11
Branches 628 630 +2
==========================================
+ Hits 5125 5128 +3
- Misses 1476 1484 +8
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
I've found another case where the libpython gets mmap'ed by a process and breaks pystack's ability to find `_PyRuntime`. This time, I noticed it happening when Memray is symbolizing native stacks, which can trigger elfutils to mmap the text section of libpython if one of those native stack frames resolves to an address inside libpython. When this happened, the symbol resolution callback was finding an address for the symbol, and discovering that that address was mapped, but not noticing that it fell within a different module entirely, since only a small part of libpython was mapped at that first mapping. Address this by preferring matches which fall within the module we searched in over mappings which don't, while continuing to prefer a match in an earlier module over one in a later one. Signed-off-by: Matt Wozniski <mwozniski@bloomberg.net>
f2473ff to
ca8042d
Compare
|
I think the way to solve this is to actually try to resolve the main thread in one of those images and then once we know which one contain the actual data only use that one. |
I think I follow what you're saying. You're suggesting that we could unwind the main thread, and then some of the main thread's frames have to have been in the interpreter, so we can look at the image that each frame's code falls within to see if that image contains a If I've got that idea right, it does sound more reliable than this hack, but it does have some disadvantages:
And it's also slower and more complex, on top of all of that. If I understand your proposal right, I lean towards landing this PR, but keeping that idea in our back pocket in case we find another case where this still isn't good enough. Does that sound reasonable to you, @pablogsal ? |
No, much simpler than this. There is only ONE of these images that will correspond to the executable and that image will have its bss initialized. So what i propose is to iterate over all valid candidate libpythons and for every libpython:
If these conditions are satisfied this map collection will be the actual libpython driving the process and symbols for python should be resolved there. All symbols can be calculated as well in an offset-relative way to the elf file so it should work for all cases. |
Ah, indeed. Although...
this only works from 3.13 onwards. There's no cookie and version in the It may still be true that we can simply check candidates to see if they do or don't start with too many zero bytes to have been initialized, though... At least |
I've found another case where the libpython gets mmap'ed by a process and breaks pystack's ability to find
_PyRuntime. This time, I noticed it happening when Memray is symbolizing native stacks, which can trigger elfutils to mmap the text section of libpython if one of those native stack frames resolves to an address inside libpython.When this happened, the symbol resolution callback was finding an address for the symbol, and discovering that that address was mapped, but not noticing that it fell within a different module entirely, since only a small part of libpython was mapped at that first mapping.
Address this by preferring matches which fall within the module we searched in over mappings which don't, while continuing to prefer a match in an earlier module over one in a later one.