aboutsummaryrefslogtreecommitdiffstats
path: root/com32/include/sys/module.h
blob: 3e5a8d9bd698a9cc97a84980f99b9b5e6dcc5459 (plain)
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_