Starting with a version of 2.6 of the Linux kernel, the kernel introduces a mechanism for exporting symbols. Only symbols exported using Export_symbol or EXPORT_SYMBOL_GPL in the kernel can be used directly in the kernel module. However, the kernel does not export all the symbols. For example, in the kernel of 3.8.0, Do_page_fault is not exported.
And I need to use Do_page_fault in my kernel module, so what are the methods? What are the pros and cons of each of these methods?
The following is an example of do_page_fault analysis:
- Modify the kernel to add Export_symbol (Do_page_fault) or EXPORT_SYMBOL_GPL (Do_page_fault).
This method is suitable for situations where the kernel can be modified. This is the simplest way to change the kernel.
- Read with Kallsyms_lookup_name
Kallsyms_lookup_name itself is also a kernel symbol, if the symbol is exported, then you can call Kallsyms_lookup_name ("Do_page_fault") in the kernel module to get Do_page_ The symbolic address of the fault.
The limitation of this approach is that kallsyms_lookup_name itself is not necessarily exported.
- Read/boot/system.map-<kernel-version>, and then use kernel module parameters to pass in the kernel module
System.map-<kernel-version> is generated when the kernel is compiled, and it records the address of the kernel symbol at compile time. If you can guarantee that the currently used kernel corresponds to the system.map-<kernel-version>, the symbolic address read from the system.map-<kernel-version> is correct. Among them, kernel-version can be obtained by ' uname-r '.
However, this method also has limitations, when the module is running, the,system.map-<kernel-version> file does not exist, even if there is no guarantee that the current kernel is the correct counterpart.
- Read the/proc/kallsyms, and then use kernel module parameters to pass in the kernel module
/proc/kallsyms is a special file that is not a file that is stored on disk. The content is generated by the kernel only when the file is read. Because the content is dynamically generated by the kernel, it is guaranteed that the address read is correct and there is no system.map-<kernel-version> problem.
It is important to note that starting from the kernel 2.6.37, there is no way for a normal user to read the correct value from/proc/kallsyms. In some versions, the file is empty. In newer versions, the address of all symbols in the file is 0 (unless the value of/porc/sys/kernel/kptr_restrict is set to 0). But the root user is able to read the correct value from the/proc/kallsyms. Fortunately, the load module also requires root permissions, you can use the script to get the address of the symbol when loading the module. Command:
#cat/proc/kallsyms | grep "\<do_page_fault\>" | awk ' {print '} '
However, according to my actual experience, the number of symbols in/proc/kallsyms is less than that of systemp.map-<kernel-version>.