Linux driver module generation and load analysis 0x00 Hello World
Let's start with an example of what this article needs to analyze, with the Hello World program as an example:
hello.c
#include <linux/init.h> #include <linux/kernel.h>int __init hello_init (void) { printk (kern_info) Hello world!\n "); return 0;} void __exit hello_exit (void) { printk (kern_info "Hello module exit done!\n");} Module_license ("GPL"); Module_author ("Macwe"); Module_description ("This was a Hello World module"); Module_init (Hello_init); Module_exit (Hello_exit);
Makefile
obj-m:=hello.okdir=/lib/modules/$ (Shell uname-r)/buildpwd=$ (shell pwd) All: $ (make)-C Kdir m=$ (PWD) modules
Compile
My compilation environment is as follows:
- Linux:debian 8.0 x86_64
- Kernel:3.16.0-4-amd64
- gcc:4.9.2 (Debian 4.9.2-10)
After you run make, the following files are generated:
? Hello ls-altotal 352drwxr-xr-x 3 root root 4096 Jul 22:10. drwx------root root 4096 Jul 22 22:19. .-rw-r--r-- 1 root root 196 Jul 21:26. hello.ko.cmd-rw-r--r-- 1 root root 12288 Jul 22:10. hello.mod . c.swp-rw-r--r-- 1 root root 36812 Jul 20:00. hello.mod.o.cmd-rw-r--r-- 1 root root 36670 Jul 22 21 : Hello.o.cmddrwxr-xr-x 2 root root 4096 Jul 21:26. tmp_versions-rw-r--r-- 1 root root 118 Jul 20:00 makefile-rw-r--r-- 1 root root 0 Jul 20:00 module.symvers//Record module export function information-rw-r--r-- 1 root root< c20/>392 Jul 21:26 hello.c-rw-r--r-- 1 root root 3176 Jul 21:27 hello.ko-rw-r--r-- 1 root root 6 20:00 hello.mod.c-rw-r--r-- 1 root root 63936 Jul 20:00 hello.mod.o-rw-r--r-- 1 root root
51024 Jul 21:26 hello.o-rw-r--r-- 1 root root ( 21:26 modules.order
Where Hello.ko is a compiled binary module file. Note that several files are hidden files, so don't ignore them.
Some release version of the default generated module file is with debugging information, we do not care about debugging information, through the Strip command to remove the first:
Strip--strip-debug--strip-unneeded Hello.ko
Load the module to see the effect:
? Hello insmod hello.ko? Hello dmesg | tail-n 1[21747.509290] Hello world!? Hello rmmod hello.ko? Hello dmesg | tail-n 2[21747.509290] Hello world![ 21812.503243] Hello module Exit done!
. *.cmd file
The file was created by the Scripts/kbuild.include script,
0x01 Hello.ko File Analysis basic information:
? Hello file Hello.kohello.ko:ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), buildid[sha1]=7a3200ea06f414895526a920 E6d91375078446b7, not stripped? Hello Modinfo hello.kofilename:/root/hello/hello.kodescription:this is a Hello world moduleauthor:mac Welicense:gpldepends:vermagic:3.16.0-4-amd64 SMP mod_unload modversions? Hello readelf-h hello.koelf header:magic:7f 4c--------Class: ELF64 Data:2 ' s complement, little endian Version:1 (c urrent) Os/abi:unix-system V ABI version:0 Type: REL (relocatable file) machine:advanced Micro Devices x86-64 Version: 0x1 Entry Point address:0x0 start of program headers:0 (bytes to file) start of section headers: 1960 (bytes into file) flags:0x0 Size of this header:64 (bytes) Siz E of Program headers:0 (bytes) Number of the program headers:0 Size of sections headers:64 (by TES) Number of section headers:19 section header string Table Index:16
The. ko file is a relocatable binary file in elf format, equivalent to the. o file for the kernel, all code and data starting from 0, we mainly look at the section in the file.
Section
? Hello READELF-SW Hello.kothere is headers, starting at offset 0x7a8:section headers: [Nr] Name Type Address Off Size ES Flg Lk Inf Al [0] NULL 0000000000000000 000000 000000 0 0 0 [1]. Note.gnu.build-id Note 0000000000000000 000040 000024 xx A 0 0 4 [ 2]. Text progbits 0000000000000000 000064 000000 xx AX 0 0 1 [3]. Init.text progbits 0000000000000000 000064 000011 AX 0 0 1 [4]. Rela.init.text rela 0000000000000000 000718 000030 I 3 8 [5]. Exit.text progbits 0000000000000000 000075 00000e Microsoft AX 0 0 1 [6]. rela.exit . Text RELA 0000000000000000 000748 000030 I 5 8 [7]. rodata.str1.1 progbits 0000000000 000000 000083 00002b (AMS) 0 0 1 [8]. Modinfo progbits 0000000000000000 0000ae 00007f xx A 0 0 1 [9] __versions Progbits 0000000000000000 000140 000080 A 0 0 []. Data Progbits 00000000000 00000 0001c0 000000-wa 0 0 1 [one]. Gnu.linkonce.this_module progbits 0000000000000000 0001c0 000258 xx wa 0 0 [[]. rela.gnu.linkonce.this_module rela 0000000000000000 000778 000030 [8]. BSS Nobits 0000000000000000 000418 000000-WA 0 0 1 [+]. Comment progbits 0000 000000000000 000418 00003a MS 0 0 1 [+]. Note. Gnu-stack progbits 0000000000000000 000452 000000 0 0 1 [+]. Shstrtab strtab 000000 0000000000 000452 0000b4 0 0 1 [+]. Symtab symtab 0000000000000000 000508 0001c8 18 18 8 [+]. Strtab strtab 0000000000000000 0006d0 000047 0 0 1Key to Flags:w (write), A (Alloc), X (execute), M (merge), S (Strings), L (Large) I (info), L (link order), G (groUP), T (TLS), E (Exclude), X (unknown) O (extra OS processing required) O (OS specific), p (processor specific)
This KO is made up of 19 sections, below to see a few more useful sections
. gnu.linkonce.this_module
This section holds a struct module struct, see HELLO.MOD.C
From HELLO.MOD.C 7 __visible struct module __this_module 8 __attribute__ (Section (". Gnu.linkonce.this_module ")) = { 9 . Name = Kbuild_modname, init = init_module, one #ifdef config_module_unload . Exit = Clean Up_module, #endif . Arch = module_arch_init, 15}; Kbuild_modname
__versions
This section records the CRC value of the kernel function used to verify the version, see HELLO.MOD.C
Other sections
Section |
explain |
. rela* |
Elf64_rela Structural Body |
. rodata.str1.1 |
A global string constant is saved |
. modinfo |
Modinfo Hello.ko See the information is here |
. Comment |
Compiler information |
. shstrtab |
Name strings for each section |
. strtab |
Symbol string |
0x02 Module Loading
The following is the pseudo-code that the module loads:
After calling Syscall:init_module
src/kernel/module.csys_init_module:->{struct Load_info info; Copy module file to kernel space, Info->hdr point to Module Head, Info->len for module size copy_module_from_user (Umod, Len, &info); return load_module:->{struct module *mod; Check signature [Config_module_sig] Module_sig_check (info); Check that the file header of the module image is legal (Magic,type,arch,shoff) Elf_header_check (info); Load each section of the module, create a struct module mod = layout_and_allocate:->{//Reposition the code and the data address. MoD = Setup_load_info (info); Check the legality of the module, for example: Vermagic,license check_modinfo (mod, info, 0); Continue to initialize mod layout_sections (mod, info); Layout_symtab (mod, info); }//Add mod to the Global Module list and mark it as module_state_unformed add_unformed_module (mod); ...//release info, now content is saved in MoD return do_init_module:->{//Call own module initialization function, both hello_init (); Do_one_initcall (Mod->init); Set the module status to Module_state_live } }}
0X03 Module Uninstallation
The uninstallation process is relatively simple
After calling Syscall:delete_module
src/kernel/module.csys_delete_module:->{ struct module *mod; Find module mod = find_module (name); Check if there is a module dependency// Check whether the state is module_state_live //state set to module_state_going //Call Mod->exit (), both Hello_exit () //Notify kernel I want to uninstall //Release Memory}
0x04 Reference
Http://stackoverflow.com/questions/17922234/meaning-of-version-info-in-mod-c-file-in-linux-kernel
Linux driver module generation and load analysis