1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
|
/**
* 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_
|