linux_helper_direct_mapping_offset() fails on Xen guests
Here's a fun one.
I was doing some live debugging yesterday on a Xen guest. I got a strange failure:
```
...
File "/root/drgnlite-ol7-x86_64-2026-02-04/lib64/python3.6/site-packages/drgn/helpers/linux/slab.py", line 255, in for_each_allocated_object
yield from self._page_objects(page, slab, pointer_type)
File "/root/drgnlite-ol7-x86_64-2026-02-04/lib64/python3.6/site-packages/drgn/helpers/linux/slab.py", line 373, in _page_objects
addr = page_to_virt(page).value_() + self._red_left_pad
File "/root/drgnlite-ol7-x86_64-2026-02-04/lib64/python3.6/site-packages/drgn/helpers/linux/mm.py", line 928, in page_to_virt
return pfn_to_virt(page_to_pfn(page))
File "/root/drgnlite-ol7-x86_64-2026-02-04/lib64/python3.6/site-packages/drgn/helpers/common/prog.py", line 115, in wrapper
return f(args[0].prog_, *args, **kwds)
File "/root/drgnlite-ol7-x86_64-2026-02-04/lib64/python3.6/site-packages/drgn/helpers/linux/mm.py", line 950, in pfn_to_virt
return phys_to_virt(PFN_PHYS(prog, pfn))
File "/root/drgnlite-ol7-x86_64-2026-02-04/lib64/python3.6/site-packages/drgn/helpers/common/prog.py", line 115, in wrapper
return f(args[0].prog_, *args, **kwds)
File "/root/drgnlite-ol7-x86_64-2026-02-04/lib64/python3.6/site-packages/drgn/helpers/linux/mm.py", line 973, in phys_to_virt
prog, "void *", operator.index(addr) + _linux_helper_direct_mapping_offset(prog)
_drgn.FaultError: could not find physical memory segment: 0x802aa0c058
```
The guest only has 8.2 GiB of memory (a suspicously specific amount), so barring some strange memory holes/gaps, this was way too large for a physical address on this machine.
I read through the helper and saw it's translating the address of symbol `saved_command_line` to a physical address and using the resulting offset for the direct mapping offset. And honestly, I spent an hour or two in GDB assuming that there was something wrong with the address translation or the memory reader. But then it finally dawned on me that Xen guests manage their page tables using _machine physical addresses_. So all the physical addresses in the page tables are physical to the _host machine_. Whereas when drgn reads physical addresses in `/proc/kcore`, it's reading ["guest pseudo-physical memory"](https://wiki.xenproject.org/wiki/XenTerminology).
Yuck.
So I guess the takeaway is (1) that page table walks on Xen are broken, and (2) so are helpers depending on `_linux_helper_direct_mapping_offset()`. The first issue, I'm not sure how to solve, and whether it would be worth the cost either. The second issue though, I'm wondering if it would be worth using `page_offset_base` for x86_64? This would sidestep the address translation issue. I know that's indulging in the very complexity that this approach was trying to avoid...
关闭于 2026-02-14 4 条评论