aboutsummaryrefslogtreecommitdiffstats
path: root/com32/include/sys/module.h
blob: c3c077addae9ac1e5a39da81c356513252dd4c6a (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
/**
 * 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 <linux/list.h>


/*
 * The maximum length of the module file name (including path), stored
 * in the struct module descriptor.
 */
#define MODULE_NAME_SIZE		64

/*
 * Initialization and finalization function signatures
 */


/**
 * module_init_t - pointer to a initialization routine
 *
 * The initialization routine is called after all module constructors were invoked.
 * It takes no parameters and returns 0 if the module was initialized successfully,
 * or a non-zero value if errors have occurred.
 */
typedef int (*module_init_t)(void);

/**
 * module_exit_t - pointer to a finalization routine
 *
 * The finalization routine is called before the module destructors are to be invoked.
 * It simply executes some cleanup code, without error reporting.
 */
typedef void (*module_exit_t)(void);

typedef int (*module_main_t)(int, char**);


/**
 * 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 elf_module {
	char				name[MODULE_NAME_SIZE]; 		// The module name

	int					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_init_t		*init_func;	// The initialization entry point
	module_exit_t		*exit_func;	// The module finalization code
	module_main_t		*main_func; // The main function (for executable modules)


	void				*module_addr; // The module location in the memory
	Elf32_Addr			base_addr;	// The base address of the module
	Elf32_Word			module_size; // The module size in memory

	Elf32_Word			*hash_table;	// The symbol hash table
	Elf32_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
	Elf32_Dyn			*dyn_table;		// Dynamic loading information table

	Elf32_Word			strtable_size;	// The size of the string table
	Elf32_Word			syment_size;	// The size of a symbol entry
	Elf32_Word			symtable_size;	// The size of the symbol table


	// Transient - Data available while the module is loading
	FILE				*_file;	// The file object of the open file
	Elf32_Off			_cr_offset; // The current offset in the open file
};

/**
 * 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
};



#ifdef DYNAMIC_MODULE

/*
 * This portion is included by dynamic (ELF) module source files.
 */

#define MODULE_INIT(fn)	static module_init_t __module_init \
	__used __attribute__((section(".ctors_modinit")))  = fn

#define MODULE_EXIT(fn) static module_exit_t __module_exit \
	__used __attribute__((section(".dtors_modexit")))  = fn

#define MODULE_MAIN(fn) static module_main_t __module_main \
	__used __attribute__((section(".ctors_modmain")))  = fn

#else

/*
 * This portion is included by the core COM32 module.
 */

/*
 * Accepted values for various ELF header parameters found in an ELF dynamic
 * object.
 */
#define MODULE_ELF_CLASS		ELFCLASS32		// 32-bit modules
#define MODULE_ELF_CLASS_SIZE	32				// Size of a word value
#define MODULE_ELF_DATA			ELFDATA2LSB		// Word endianess
#define MODULE_ELF_VERSION		EV_CURRENT		// Object version
#define MODULE_ELF_TYPE			ET_DYN			// Executable type (shared object - .so)
#define MODULE_ELF_MACHINE		EM_386			// Target architecture

/**
 * 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 -
 */
#define for_each_module(m)	list_for_each_entry(m, &modules_head, list)

/**
 * 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_load_shallow - loads a shallow 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 module metadata. The metadata currently
 * contains a symbol table that describes code & data allocated by other means.
 * Its current use is to describe the root COM32 module to the rest of the
 * module subsystem.
 */
extern int module_load_shallow(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 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_unloadable -
 */
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 Elf32_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 Elf32_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(Elf32_Addr addr, struct elf_module *module) {
	return (void*)(module->base_addr + addr);
}

#endif // DYNAMIC_MODULE

#endif // MODULE_H_