Resolving References

resolve_symbol is used to resolve undefined symbol references. It is primarily a wrapper function, as the code flow diagram in Figure 7-5 indicates.

resolve_symbol1

__find_symbol1

check_version1

use_module|

Figure 7-5: Code flow diagram for resolve_symbol.

Actual resolution of the symbol is performed in_find_symbol. The kernel first looks through all symbols permanently compiled into the kernel:

kernel/module.c static unsigned long _find_symbol(const char *name, struct module **owner, const unsigned long **crc, int gplok)

struct module *mod; const struct kernel_symbol *ks;

ks = lookup_symbol(name, _start_ksymtab, _stop if (ks) {

return ks->value;

The helper function lookup_symbol(name, start, end) searches through the symbol table found between start and end and checks if an entry with a given name can be found. symversion is an auxiliary macro. If the modversions option is enabled, it extracts the corresponding entry from the CRC table; otherwise, it returns 0.

The code to search in further sections is basically identical to the code shown above, so we don't list it explicitly here. If gplok is set to 1 because the module uses a GPL-compatible license, the GPL symbols of the kernel located between_start_ksymtab_gpl and_stop_kysmtab_gpl are scanned if no matching information is found in the generally accessible symbols. If this fails, the future GPL-exported symbols are searched. If this still fails, the unused symbols as well as the unused GPL symbols are searched. Should the symbol be present in these section, the kernel uses it to resolve the dependency but prints out a warning because the symbol is bound to disappear sooner or later, so any modules using the symbol will stop working at this point.

If the search is still unsuccessful, the exported symbols of the modules already loaded are scanned:

kernel/module.c

list_for_each_entry(mod, kmodules, list) {

ksymtab);

.start_ksymtab));

ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms); if (ks) {

*crc = symversion(mod->crcs, (ks - mod->syms)); return ks->value;

ks = lookup_symbol(name, mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms);

*crc = symversion(mod->gpl_crcs,

return ks->value;

return 0;

Each module stores its exported symbols in the mod->syms array, which has the same structure as the symbol array of the kernel.

If the module is GPL-compatible, all GPL-exported symbols of the modules are scanned; this is done in exactly the same way as the above search, but mod->gpl_syms is used as the database. If this remains unsuccessful, the kernel tries the remaining symbol sections.

The kernel sets the owner parameter of_find_symbol to the module data structure of the second module that is presently being processed. This serves to create a dependency between modules when a symbol is resolved with the help of another module.

0 is returned if the kernel cannot resolve the symbol.

Let's return to resolve_symbol. If_find_symbol is successful, the kernel first uses check_version to determine whether the checksums match (this function is discussed in Section 7.5). If the symbol used originates from another module, a dependency between the two modules is established by means of the familiar use_module function; this prevents the referenced module from being removed as long as the symbol just loaded is still in memory.

Continue reading here: Removing Modules

Was this article helpful?

0 0