On 12/21/25 1:52 PM, Tatsuyuki Ishi wrote:
> Hi,
>
> I noticed that /proc/modules reports inconsistent address and size
> values for modules. In m_show():
>
> size = module_total_size(mod); // .text + .rodata +
> .data + ...
> value = mod->mem[MOD_TEXT].base; // only text base
>
> Looking at kallsyms, .data symbols can come before .text symbols, so
> [addr, addr+size) is useless as a bound and can be overlapping.
>
> I have a userspace frontend for perf [1] and the code currently
> expects non-overlapping regions. I can add a workaround to truncate
> any overlapping regions from /proc/modules. But is it possible to
> "fix" the kernel-side semantics here?
>
> [1]: https://github.com/mstange/samply/pull/736
The initial code to show the module start address in /proc/modules was
added in 2003 by "[PATCH] Module state and address in /proc/modules."
[1].
I'm not entirely sure if the intention at that time was for the address
and (already present) size read from /proc/modules to provide a range
where the module is loaded. In particular, if a module had a separate
init region and was still in the process of being loaded, the size would
also include a non-zero value of mod->init_size, which means this could
result in overlapping ranges.
Nonetheless, I assume that providing a range was indeed the intention,
as I don't see how having just the address of a module would be
particularly useful.
The patch mentions that the module address was added for use by OProfile
and ksymoops. The OProfile code reads /proc/modules in the function
_record_module_info() [2] and appears to expect that the address and
size form a valid range. The old ksymoops code [3] reads the file in the
function read_lsmod() but doesn't seem to handle the added address.
More importantly, I notice that perf has the function modules__parse()
[4], which reads the /proc/modules data and is called in several places.
For instance, the machine__create_module() callback [5] then expects
that the address and size form a valid range.
The original behavior was first broken in 2022 by commit 01dc0386efb7
("module: Add CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC"), which
introduced a third optional module region. A year later, commit
ac3b43283923 ("module: replace module_layout with module_memory")
further split the module into up to seven separate regions.
The separation of module regions was done for good reasons and should
not be reverted.
Instead, a simple and consistent approach could be for /proc/modules to
report only the size of MOD_TEXT, or to show it in an additional column.
I suspect this should be sufficient for debugging tools. However, this
requires careful checking to ensure that nothing else breaks. If more
accurate or complete information is necessary, the kernel could export
data about all module regions under something like
/sys/module/<modname>/segments/<segname>.
[1] https://lore.kernel.org/all/[email protected]/
[2]
https://sourceforge.net/p/oprofile/oprofile/ci/master/tree/libperf_events/operf_utils.cpp#l1327
[3]
https://www.kernel.org/pub/linux/utils/kernel/ksymoops/v2.4/ksymoops-2.4.11.tar.gz
[4]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/perf/util/symbol.c?h=v6.19-rc3#n668
[5]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/perf/util/machine.c?h=v6.19-rc3#n1467
--
Cheers,
Petr