This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RE: pre-compiled modules


> Sorry, I meant to say: "Will this code go in the module itself or the
> stpd daemon?"

Some of each, I think.  Indeed there are no convenient exported kernel
interfaces for finding modules.  Short of probe-like techniques using the
kernel's DWARF info to access unexported things, you can't do it all purely
in the module itself.  It's easy to do lots of these things once you have the
module handle (struct module *) for the module in question.  Every module can
find the list implicitly because it can find its own THIS_MODULE and follow
the linked list.  However, it does not have any access to the lock that
governs the list structure.  So it's not safe to access the list structure,
or any module handle you aren't sure cannot be removed.

Wacky as it is, what I actually recommend is this.  For each module of
interest (containing probe targets or global variable addresses used by other
probes), open "/sys/module/MODNAME/sections/.gnu.linkonce.this_module".  From
there you can read (0x... in ascii) the address of MODNAME's module handle.
Then, *keep the file descriptor open*.  As long as you keep the fd on a
/sys/module/MODNAME/sections/foobar file open, then MODNAME is pinned and
cannot be removed.  Keep these fd's open until the probe module has loaded
and run its initializer.  (For now, we might want to keep them open until the
probe is removed, since we are not yet prepared for modules of interest to be
removed.)  

When inserting the probe module, pass in a parameter
"module_addresses=0x123,0x234,...".  The probe code will declare:

	static struct module *modules[NMODULES_WE_CARE_ABOUT];
	module_param_array(modules, ulong, NULL, 0444);

Then its initializer can do:

	if (modules[0]->module_core != 0x123... /* module 0 base */)
	  lose;
	if (modules[1]->module_core != 0x234... /* module 1 base */)
	  lose;

etc.  Later on, this will be:

	_stp_runtime_foobar(modules[0], kprobe_list_for_0, nprobes_for_0,
			    nsections_for_0, section_offs_for_0,
			    section_names_for_0);

after defining globals like:

	const char *const sections_for_0[] = { ".text", ".data" };
	unsigned long section_offs_for_0[2];

(Probably you need to generate code to fix up each kprobe individually after
the runtime finds the section addresses.)  The translator will eventually be
generating "section_offs_for_0[0] + 0x123" for the addresses gleaned from
DWARF info instead of straight constants.

The runtime function can look at module->sect_attrs to map section names to
addresses.  This is the same data structure that
/sys/module/MODNAME/sections/SECNAME gets to via sysfs magic, but it is
probably more efficient just to consult it directly (even with linear string
searches vs dcache for the SECNAME lookup).  


What makes it robust to use an fd to pin a module of interest while a probe
module looks it up is that the module initializer runs in the context of the
process that makes the init_module system call to install it.  Until that
initializer finishes, that process can't do anything else like process
signals and die, or close an fd.  So the robustness depends on the fd being
held open by the same process that makes the syscall, and on that process not
having other threads that can close its fds.  That means one really should
replace running insmod with a specialized program that we specificially
design to keep fds open.  That is much less trouble than it sounds like.
insmod doesn't do anything.  

There is a system call, which is in libc, but helpfully not declared anywhere:

	int init_module (void *buf, size_t bytes, const char *string);

You call this with the contents and length of the whole .ko file, and a
string of "foo=abc bar=def" (space separated parameters).  That's it.
Maybe stpd can do this directly.  Or perhaps a special child program just to
do the loading, since it's the only thing that needs to be root.


Thanks,
Roland


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]