| /** |
| * syslinux/module.h |
| * |
| * Dynamic ELF modules definitions and services. |
| */ |
| |
| #ifndef MODULE_H_ |
| #define MODULE_H_ |
| |
| #include <stdio.h> |
| #include <elf.h> |
| #include <stdint.h> |
| #include <setjmp.h> |
| #include <stdbool.h> |
| #include <linux/list.h> |
| |
| #if __SIZEOF_POINTER__ == 4 |
| #include <i386/module.h> |
| #elif __SIZEOF_POINTER__ == 8 |
| #include <x86_64/module.h> |
| #else |
| #error "unsupported architecture" |
| #endif |
| |
| /* |
| * The maximum length of the module file name (including path), stored |
| * in the struct module descriptor. |
| */ |
| #define MODULE_NAME_SIZE 256 |
| |
| /* |
| * Some common information about what kind of modules we're dealing with |
| */ |
| #define EXEC_MODULE 0 |
| #define LIB_MODULE 1 |
| |
| #define MAX_NR_DEPS 64 |
| |
| /* |
| * Initialization and finalization function signatures |
| */ |
| |
| /** |
| * module_main_t - pointer to an entry routine |
| * |
| * The entry routine is present only in executable modules, and represents |
| * the entry point for the program. |
| */ |
| typedef int (*module_main_t)(int, char**); |
| |
| /** |
| * module_ctor_t - pointer to a constructor or destructor routine |
| * |
| * A module may have multiple routines that need to be executed before |
| * or after the main routine. These are the constructors and |
| * destructors, respectively. |
| */ |
| typedef void (*module_ctor_t) (void); |
| |
| /** |
| * struct elf_module - structure encapsulating a module loaded in memory. |
| * |
| * Each SYSLINUX ELF module must have an associated struct elf_module descriptor |
| * that keeps track of memory allocations, symbol information, and various other |
| * resources needed by the module itself or by other modules that depend on it. |
| * |
| * There are two types of modules: |
| * - regular modules, which are actual memory images of a loaded & linked shared |
| * object (ELF file). Memory is reserved for the struct elf_module structure itself |
| * and for the object loadable sections read from the file. |
| * - shallow modules, which are not associated with an ELF shared object, but contain |
| * metainformation about a memory region already present and containing the |
| * actual code and data. One particular usage of shallow modules is to access |
| * symbol information from the root COM32 module loaded by the SYSLINUX core. |
| * As their name suggests, memory is reserved only for the elf_module structure |
| * itself and optionally for a usually small memory region containing metainformation |
| * (symbol information). |
| * |
| * Module descriptors are related to each other through dependency information. A module |
| * can depend on symbols from other modules, and in turn it can provide symbols used |
| * by other dependant modules. This relationship can be described as a directed |
| * acyclic graph (DAG). The graph is stored using double linked lists of |
| * predecessors and successors. There is also a global linked list containing all |
| * the modules currently loaded. |
| */ |
| struct atexit; |
| struct elf_module { |
| char name[MODULE_NAME_SIZE]; // The module name |
| |
| bool shallow; // Whether the module contains any code |
| |
| struct list_head required; // Head of the required modules list |
| struct list_head dependants; // Head of module dependants list |
| struct list_head list; // The list entry in the module list |
| |
| module_ctor_t *ctors; // module constructors |
| module_ctor_t *dtors; // module destructors |
| module_main_t main_func; // The main function (for executable modules) |
| |
| void *module_addr; // The module location in the memory |
| Elf_Addr base_addr; // The base address of the module |
| Elf_Word module_size; // The module size in memory |
| |
| Elf_Word *hash_table; // The symbol hash table |
| Elf_Word *ghash_table; // The GNU style hash table |
| char *str_table; // The string table |
| void *sym_table; // The symbol table |
| void *got; // The Global Offset Table |
| Elf_Dyn *dyn_table; // Dynamic loading information table |
| |
| Elf_Word strtable_size; // The size of the string table |
| Elf_Word syment_size; // The size of a symbol entry |
| Elf_Word symtable_size; // The size of the symbol table |
| |
| |
| union { |
| // Transient - Data available while the module is loading |
| struct { |
| FILE *_file; // The file object of the open file |
| Elf_Off _cr_offset; // The current offset in the open file |
| } l; |
| |
| // Process execution data |
| struct { |
| jmp_buf process_exit; // Exit state |
| struct atexit *atexit_list; // atexit() chain |
| } x; |
| } u; |
| |
| // ELF DT_NEEDED entries for this module |
| int nr_needed; |
| Elf_Word needed[MAX_NR_DEPS]; |
| }; |
| |
| /** |
| * struct module_dep - structure encapsulating a module dependency need |
| * |
| * This structure represents an item in a double linked list of predecessors or |
| * successors. The item contents is a pointer to the corresponding module descriptor. |
| */ |
| struct module_dep { |
| struct list_head list; // The list entry in the dependency list |
| |
| struct elf_module *module; // The target module descriptor |
| }; |
| |
| |
| /** |
| * Unload all modules that have been loaded since @name. |
| * |
| * Returns the struct elf_module * for @name or %NULL if no modules |
| * have been loaded since @name. |
| */ |
| extern struct elf_module *unload_modules_since(const char *name); |
| |
| extern FILE *findpath(char *name); |
| |
| |
| /** |
| * Names of symbols with special meaning (treated as special cases at linking) |
| */ |
| #define MODULE_ELF_INIT_PTR "__module_init_ptr" // Initialization pointer symbol name |
| #define MODULE_ELF_EXIT_PTR "__module_exit_ptr" // Finalization pointer symbol name |
| #define MODULE_ELF_MAIN_PTR "__module_main_ptr" // Entry pointer symbol name |
| |
| /** |
| * modules_head - A global linked list containing all the loaded modules. |
| */ |
| extern struct list_head modules_head; |
| |
| |
| /** |
| * for_each_module - iterator loop through the list of loaded modules. |
| */ |
| #define for_each_module(m) list_for_each_entry(m, &modules_head, list) |
| |
| /** |
| * for_each_module_safe - iterator loop through the list of loaded modules safe against removal. |
| */ |
| #define for_each_module_safe(m, n) \ |
| list_for_each_entry_safe(m, n, &modules_head, list) |
| |
| /** |
| * module_current - return the module at the head of the module list. |
| */ |
| static inline struct elf_module *module_current(void) |
| { |
| struct elf_module *head; |
| |
| head = list_entry((&modules_head)->next, typeof(*head), list); |
| return head; |
| } |
| |
| /** |
| * modules_init - initialize the module subsystem. |
| * |
| * This function must be called before any module operation is to be performed. |
| */ |
| extern int modules_init(void); |
| |
| |
| /** |
| * modules_term - releases all resources pertaining to the module subsystem. |
| * |
| * This function should be called after all module operations. |
| */ |
| extern void modules_term(void); |
| |
| |
| /** |
| * module_alloc - reserves space for a new module descriptor. |
| * @name: the file name of the module to be loaded. |
| * |
| * The function simply allocates a new module descriptor and initializes its fields |
| * in order to be used by subsequent loading operations. |
| */ |
| extern struct elf_module *module_alloc(const char *name); |
| |
| |
| /** |
| * module_load - loads a regular ELF module into memory. |
| * @module: the module descriptor returned by module_alloc. |
| * |
| * The function reads the module file, checks whether the file has a |
| * valid structure, then loads into memory the code and the data and performs |
| * any symbol relocations. A module dependency is created automatically when the |
| * relocated symbol is defined in a different module. |
| * |
| * The function returns 0 if the operation is completed successfully, and |
| * a non-zero value if an error occurs. Possible errors include invalid module |
| * structure, missing symbol definitions (unsatisfied dependencies) and memory |
| * allocation issues. |
| */ |
| extern int module_load(struct elf_module *module); |
| |
| |
| /** |
| * module_unload - unloads the module from the system. |
| * @module: the module descriptor structure. |
| * |
| * The function checks to see whether the module can be safely |
| * removed, then it executes any destructors and releases all the |
| * associated memory. This function can be applied both for standard |
| * modules and for shallow modules. |
| * |
| * A module can be safely removed from the system when no other modules reference |
| * symbols from it. |
| */ |
| extern int module_unload(struct elf_module *module); |
| |
| /** |
| * _module_unload - unloads the module without running destructors |
| * @module: the module descriptor structure. |
| * |
| * This function is the same as module_unload(), except that the |
| * module's destructors are not executed. |
| */ |
| extern int _module_unload(struct elf_module *module); |
| |
| /** |
| * get_module_type - get type of the module |
| * @module: the module descriptor structure. |
| * |
| * This function returns the type of module we're dealing with |
| * either a library module ( LIB_MODULE ), executable module ( EXEC_MODULE ), |
| * or an error ( UNKNOWN_MODULE ). The way it checks teh type is by checking to see |
| * if the module has its main_func set ( in which case it's an executable ). In case |
| * it doesn't it then checks to see if init_func is set ( in which case it's a |
| * library module. If this isn't the case either we don't know what it is so bail out |
| */ |
| extern int get_module_type(struct elf_module *module); |
| |
| /** |
| * module_unloadable - checks whether the given module can be unloaded. |
| * @module: the module descriptor structure |
| * |
| * A module can be unloaded from the system when no other modules depend on it, |
| * that is, no symbols are referenced from it. |
| */ |
| extern int module_unloadable(struct elf_module *module); |
| |
| /** |
| * module_find - searches for a module by its name. |
| * @name: the name of the module, as it was specified in module_alloc. |
| * |
| * The function returns a pointer to the module descriptor, if found, or |
| * NULL otherwise. |
| */ |
| extern struct elf_module *module_find(const char *name); |
| |
| /** |
| * module_find_symbol - searches for a symbol definition in a given module. |
| * @name: the name of the symbol to be found. |
| * @module: the module descriptor structure. |
| * |
| * The function searches the module symbol table for a symbol matching exactly |
| * the name provided. The operation uses the following search algorithms, in this |
| * order: |
| * - If a GNU hash table is present in the module, it is used to find the symbol. |
| * - If the symbol cannot be found with the first method (either the hash table |
| * is not present or the symbol is not found) and if a regular (SysV) hash table |
| * is present, a search is performed on the SysV hash table. If the symbol is not |
| * found, NULL is returned. |
| * - If the second method cannot be applied, a linear search is performed by |
| * inspecting every symbol in the symbol table. |
| * |
| * If the symbol is found, a pointer to its descriptor structure is returned, and |
| * NULL otherwise. |
| */ |
| extern Elf_Sym *module_find_symbol(const char *name, struct elf_module *module); |
| |
| /** |
| * global_find_symbol - searches for a symbol definition in the entire module namespace. |
| * @name: the name of the symbol to be found. |
| * @module: an optional (may be NULL) pointer to a module descriptor variable that |
| * will hold the module where the symbol was found. |
| * |
| * The function search for the given symbol name in all the modules currently |
| * loaded in the system, in the reverse module loading order. That is, the most |
| * recently loaded module is searched first, followed by the previous one, until |
| * the first loaded module is reached. |
| * |
| * If no module contains the symbol, NULL is returned, otherwise the return value is |
| * a pointer to the symbol descriptor structure. If the module parameter is not NULL, |
| * it is filled with the address of the module descriptor where the symbol is defined. |
| */ |
| extern Elf_Sym *global_find_symbol(const char *name, struct elf_module **module); |
| |
| /** |
| * module_get_absolute - converts an memory address relative to a module base address |
| * to its absolute value in RAM. |
| * @addr: the relative address to convert. |
| * @module: the module whose base address is used for the conversion. |
| * |
| * The function returns a pointer to the absolute memory address. |
| */ |
| static inline void *module_get_absolute(Elf_Addr addr, struct elf_module *module) { |
| return (void*)(module->base_addr + addr); |
| } |
| |
| /** |
| * syslinux_current - get the current module process |
| */ |
| extern struct elf_module *__syslinux_current; |
| static inline const struct elf_module *syslinux_current(void) |
| { |
| return __syslinux_current; |
| } |
| |
| |
| #endif // MODULE_H_ |