1. Scope of application
This document describes the implementation of the function implementation principle in the kernel module in the shell command line.
In VxWorks, the system comes with the function of directly executing the driver and in-app function in the shell command line, which improves the development and debugging means of the driver Development engineer and application development engineer. To enable such engineers to adapt quickly to Sylixos, a similar functional module has been developed, and the first version supports the execution of functions within the kernel module at the shell command line.
2. Sylixos kernel module Dynamic loading principle 2.1 elf files in Sylixos
There are three main elf files in Sylixos:
-obj file: Once a source file has been compiled, the compiler will stitch the instruction blocks of all functions in the source file into the text section, stitching the blocks into data sections, as well as creating additional sections (such as symbol tables, relocation tables) as needed. These sections are stitched together to form an obj file.
-Kernel module file: The kernel module file is a large file formed by multiple obj file combinations, which are stitched together into a larger text section, data section, symbol table, and relocation table for the text sections, data sections, symbol tables, and relocation tables generated by multiple obj files.
-Location-independent elf file: both the Sylixos application and the dynamic library use the location-independent elf file format, which supports both code snippet sharing and write-time copying.
2.2 Elf file format for kernel modules
The kernel module includes the ELF header, the Program Header table (or not), and the section Header table.
2.2.1 Elf Head
The ELF header describes the basic properties of the entire file, such as the Elf file version, the target machine model, the program entry address, and so on, as shown below.
Typedef struct elf32_hdr { unsigned char e_ident[EI_NIDENT]; /* indicates that the file is an executable object file */ Elf32_Half e_type; /* marking the type of object file */ Elf32_Half e_machine; /* points out the architecture required for this object */ Elf32_Word e_version; /* determining the file version of object */ elf32_ addr e_entry; /* is the virtual address of the system's first transport control */ Elf32_Off e_phoff; /* maintains the offset of the program Header table in the file */ Elf32_Off e_shoff; /* Maintains the offset of the section Header table in the file */ elf32_word e_flags; /* holds the processor flag for the relevant file */ Elf32_Half e_ehsize; /* The elf head size is preserved */ elf32_half e_ phentsize; /* Size of a program header */ elf32_half e_phnum; Number of /* Program Header table */ elf32_half e_ shentsize; /* Size of a section header */ Elf32_Half e_shnum; /* number of segment headers in the Header table of a section */ elf32_half e_shstrndx; /* section Header table index of the related entry of the section name list * /} elf32_ehdr;
2.2.2 Elf file header check
When the kernel module is loaded using the Insmod command or the Modulereg command in Sylixos, the file header of the Elf file is read first, and the validity of the elf file header is verified.
In Sylixos, the e_ident value of the elf file header should be fixed to 0x7f, ' E ', ' L ', ' F ' four bytes, and E_machine will differentiate whether the elf file is a schema-adapted file based on different architectures such as arm, PowerPC, and x86.
2.2.3 Getting the kernel module version
The Sylixos elf file contains the "__sylixos_version" symbol, which is a string with the contents of the Elf kernel module version. Sylixos compares this version to the kernel version to determine if the Elf file is compatible with the Sylixos version.
2.3 Elf File loading
Sylixos will perform different kinds of load operations on Elf files based on the E_type values in the elf file header. Et_rel is a relocatable file, kernel modules belong to relocatable files, et_exec and Et_dyn are executables, applications, dynamic libraries belong to executable files.
According to E_shentsize and S_shnum, the size of the entire Elf section Header table can be calculated, and the offset address of the ELF section Header table can be obtained according to E_shoff, thus reading the entire section Header table into memory.
Depending on the information for each segment header in each Segment Header table, you can get the type, size, and storage address of each segment, thus reading the contents of each segment into memory.
2.3.1 Section Head
Each segment header in a section Header table has a structure that resembles the following.
typedef struct { elf32_word sh_name; /* segment name, value is the index of the segment header character */ elf32_word sh_type; /* Segment Type */ Elf32_Word sh_flags; /* Segment Properties */ elf32_addr sh_addr; /* position in memory */ Elf32_Off sh_offset; /* Segment byte offset (from file start count) */ Elf32_Word sh_size; Byte size of /* segment */ Elf32_Word sh_link; Index connection for Header table of /* segment */ Elf32_Word sh_info; /* Save additional information */ elf32_word sh _addralign; /* segment address alignment constraints */ Elf32_Word sh_entsize; Byte size for each entry in the /* segment */} Elf32_Shdr;
2.3.2 Loading individual segments
First, the memory is requested for the symbol table, the relocation segment, the string table, and then the segments are read into memory.
The sh_type of the symbol table is Sht_symtab, the sh_type of the relocation section is Sht_rela (relocation item with Addend) and Sht_rel (relocation item without addend), and the sh_type of the string table is Sht_strtab.
Second, request memory for the data segment, code snippet, and read the data segment and code snippet into memory.
2.3.3 Relocation Operation
When the target file is processed, the linker iterates through all the relocation entries, and when it encounters an external reference, the linker finds the exact address of the external reference function and writes it back to the address unit occupied by the instruction operand. An operation like this is called a relocation operation. For each code snippet or data segment that needs to be relocated, there is a corresponding relocation table.
Sylixos loading the kernel module, the relocation section will be relocated, this article does not do a specific analysis of relocation.
2.4 Exporting symbol tables
2.4.1 Symbol table
typedef struct elf32_sym { elf32_word st_name; /* symbol name */ Elf32_Addr st_value; /* corresponding values for symbols */ Elf32_Word st_size;  Size of bytes occupied by the; /* symbol */ unsigned char st_info; /* symbol types and binding information */ unsigned char st_other; /* Currently for 0 */ Elf32_Half st_shndx; /* the segment where the symbol is located */} Elf32_Sym;
Symbol type
Stt_notype represents an unknown type symbol;
Stt_object indicates that the symbol is a data object, such as a variable, an array, etc.
Stt_func indicates that the symbol is a function or other executable code;
Stt_section indicates that the symbol represents a segment and that the symbol must be stb_local;
Stt_file indicates that the symbol represents a file name, which is typically the source file name for the target.
Symbol scope
Stb_local is a local symbol and is not visible to the outside of the target file;
Stb_global represents a global symbol, externally visible;
Stb_weak represents a weak reference.
The symbol is in the same segment
Shn_undef indicates that the symbol is undefined and that the symbol is referenced in this target file, but is defined in other target files;
Shn_common indicates that the symbol is a "common block" type of symbol, in general, the uninitialized global symbol definition is this type.
2.4.2 Current export symbol table operations
When the kernel module is loaded with the Insmod command or the Modulereg command in Sylixos, only the global symbol is exported. A symbol buffer is defined in the module control block Lw_ld_exec_module, which is used to store symbol nodes within the module. When a symbol needs to be exported, the memory node is opened from the symbol buffer of the module, storing the symbol's string, the entry address of the symbol, and other information.
And all memory nodes used by the symbol are sorted by hash table to facilitate quick lookups and positioning.
3. Shell command line execution Module inner function Implementation 3.1 Building module internal function mapping table
Since the current system only exports the global symbol, resulting in the need to execute the module internal non-global symbol can not get its entry address, so you need to build the function map of the module intrinsics.
The process of building the internal function mapping table of the module is similar to the INSMOD process, which requires a re-parsing of the elf file, but there are two different points:
1th, there is no need to reposition the function. Since the kernel module is loaded at this point, after getting the relative offset address of the function, we can calculate the actual address of the function in memory by simply obtaining the first address that the kernel module loads in memory.
2nd, when exporting a symbol, you should modify the filter condition so that the inner function can also be added to the kernel's symbol buffer.
3.2 Use of function modules
3.2.1 Parsing module elf file
The related functions are made into Symbolshell.ko, using the function before loading the Symbolshell.ko file, and loading the test Test_module.ko as shown.
650) this.width=650; "Src=" http://img.blog.csdn.net/20171122155859508?watermark/2/text/ ahr0cdovl2jsb2cuy3nkbi5uzxqvemh5d3h5eq==/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/dissolve/70/gravity/ Southeast "alt=" here to write a picture describing "title=" "/>
Symbolshell.ko registers the call command, which provides several features as shown.
650) this.width=650; "Src=" http://img.blog.csdn.net/20171122155924974?watermark/2/text/ ahr0cdovl2jsb2cuy3nkbi5uzxqvemh5d3h5eq==/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/dissolve/70/gravity/ Southeast "alt=" here to write a picture describing "title=" "/>
3.2.2 Functions and their relative offsets in the print module
The module manages calls to functions within a module with the concept of a session, and when it comes to invoking a function within a module, it first needs to enter the module's session.
Take Test_module.ko as an example, using the call–m Test_module.ko command to enter the Test_module.ko session as shown. You can then use the Call–l command to view the symbols within the Test_module.ko.
650) this.width=650; "Src=" http://img.blog.csdn.net/20171122160013272?watermark/2/text/ ahr0cdovl2jsb2cuy3nkbi5uzxqvemh5d3h5eq==/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/dissolve/70/gravity/ Southeast "alt=" here to write a picture describing "title=" "/>
3.2.3 Executing in-module functions
Using call Test_func, you can invoke the Test_func function in Test_module.ko, as shown, and eventually use the Call–e command to exit the session of the current module.
650) this.width=650; "Src=" http://img.blog.csdn.net/20171122160102182?watermark/2/text/ ahr0cdovl2jsb2cuy3nkbi5uzxqvemh5d3h5eq==/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/dissolve/70/gravity/ Southeast "alt=" here to write a picture describing "title=" "/>
Sylixos execution of In-module functions under shell command line