352 lines
12 KiB
C
352 lines
12 KiB
C
/**
|
|
* 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_
|