root/Whitix/trunk/kernel/module.c

Revision 2050, 12.3 KB (checked in by mwhitworth, 3 years ago)

Add function to call userspace module loader (currently used in filesystem code).

Line 
1/*  This file is part of Whitix.
2 *
3 *  Whitix is free software; you can redistribute it and/or modify
4 *  it under the terms of the GNU General Public License as published by
5 *  the Free Software Foundation; either version 2 of the License, or
6 *  (at your option) any later version.
7 *
8 *  Whitix is distributed in the hope that it will be useful,
9 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 *  GNU General Public License for more details.
12 *
13 *  You should have received a copy of the GNU General Public License
14 *  along with Whitix; if not, write to the Free Software
15 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16 *
17 */
18
19#include <config.h>
20#include <console.h>
21#include <elf.h>
22#include <error.h>
23#include <malloc.h>
24#include <module.h>
25#include <i386/i386.h>
26#include <i386/virtual.h>
27#include <sections.h>
28#include <slab.h>
29#include <sys.h>
30#include <task.h>
31#include <print.h>
32#include <panic.h>
33#include <keobject.h>
34
35LIST_HEAD(moduleList);
36Spinlock moduleListLock;
37
38void ModuleRelease(struct KeObject* object);
39KE_OBJECT_TYPE(moduleType, ModuleRelease);
40
41struct KeSet moduleSet;
42
43void* ModuleSymbolFind(struct Module* module, const char* symName, int type)
44{
45        DWORD i;
46        struct ElfSymbol* symbol;
47
48        for (i=1; i<module->symTableSize/(sizeof(struct ElfSymbol)); i++)
49        {
50                symbol=&module->symTable[i];
51
52                if (symbol->symIndex == STN_UNDEF)
53                        continue;
54
55                if (ELF_ST_TYPE(symbol->symInfo) != type)
56                        continue;
57
58                if (strcmp(symName, module->strTable+symbol->symName))
59                        continue;
60
61                /* Handle data? */
62                return (void*)(symbol->symValue);
63        }
64
65        return NULL;
66}
67
68#ifdef CONFIG_ALL_SYMBOLS
69
70void ModuleSymbolPrint(DWORD address)
71{
72        struct Module* curr, *module=NULL;
73
74        ListForEachEntry(curr, &moduleList, next)
75        {
76                if (address >= curr->textAddr && address < curr->textAddr+curr->textLength)
77                {
78                        module=curr;
79                        break;
80                }
81        }
82
83        if (module)
84        {
85                DWORD size, offset;
86                const char* SymbolLookup(char*, struct ElfSymbol*, int, DWORD, DWORD*, DWORD*);
87
88                const char* name=SymbolLookup(module->strTable, module->symTable, module->symTableSize, address, &size, &offset);
89
90                if (name)
91                        KePrint("%s+%#X/%#X (module)\n", name, offset, size);
92//              else
93//                      KePrint("%#X\n", address);
94        }
95}
96
97void ModuleSymbolAdd(struct Module* module)
98{
99        int length=module->symTableSize+module->strTableSize;
100        char* dest=(void*)VirtMapPhysRange(MODULE_START, MODULE_END, PAGE_ALIGN_UP(length) >> PAGE_SHIFT, 3);
101
102        memcpy(dest, module->symTable, module->symTableSize);
103        module->symTable=(struct ElfSymbol*)dest;
104
105        dest+=module->symTableSize;
106        memcpy(dest, module->strTable, module->strTableSize);
107        module->strTable = dest;       
108}
109
110#else
111void ModuleSymbolPrint(DWORD address)
112{
113        KePrint("%#X\n", address);
114}
115
116void ModuleSymbolAdd(struct Module* module)
117{
118}
119#endif
120
121SYMBOL_EXPORT(ModuleSymbolPrint);
122
123void ModulePrintModules()
124{
125        struct Module* curr=NULL;
126       
127        ListForEachEntry(curr, &moduleList, next)
128                KePrint("MODULE: %s: %#X to %#X\n", curr->object.name, curr->textAddr, curr->textAddr+curr->textLength);
129}
130
131DWORD ModuleResolveKernel(char* name)
132{
133        /* Look through the kernel symbol table. */
134        struct KernelSymbol* currSym=(struct KernelSymbol*)symtable_start;
135
136        while (currSym != ((struct KernelSymbol*)symtable_end))
137        {
138                if (!strcmp(currSym->name, name))
139                        return currSym->addr;
140
141                currSym++;
142        }
143
144        struct Module* curr;
145
146        PreemptDisable();
147
148        /* Look through the kernel symbol table of different modules. */
149        ListForEachEntry(curr, &moduleList, next)
150        {
151                int i = 0;
152                if (!curr->keSymTab)
153                        continue;
154
155                currSym = (struct KernelSymbol*)(curr->keSymTab);
156
157                while (i < curr->keSymTabSize)
158                {                               
159                        if (!strcmp(currSym->name, name))
160                        {
161                                PreemptEnable();
162                                return currSym->addr;
163                        }
164
165                        currSym++;
166                        i += sizeof(struct KernelSymbol);
167                }
168        }
169
170        PreemptEnable();
171
172        return 0;
173}
174
175/***********************************************************************
176 *
177 * FUNCTION: ModuleSymbolPrepare
178 *
179 * DESCRIPTION: Iterate through the symbol table and relocate them to the
180 *                              base address by altering their symValue, ready for
181 *                              ModuleSymbolResolve to update the relocations.
182 *
183 * PARAMETERS: module - the module's whose symbols are to be relocated.
184 *
185 * RETURNS: 0 on success, -ENOENT on an invalid symbol.
186 *
187 ***********************************************************************/
188
189int ModuleSymbolPrepare(struct Module* module)
190{
191        DWORD i;
192        DWORD symSize=module->symTableSize/sizeof(struct ElfSymbol);
193
194        /* Iterate through all the symbols in the symbol table, skipping the first entry,
195         * which is a NULL symbol. */
196        for (i=1; i<symSize; i++)
197        {
198                struct ElfSymbol* symbol=&module->symTable[i];
199
200                /* Get the symbol's name in the string table. */
201                char* symName=module->strTable+symbol->symName;
202
203                switch (symbol->symIndex)
204                {
205                        /* The symbol is undefined, so we've got to look at the kernel
206                         * and module symbols to set its value. */
207                        case STN_UNDEF:
208                                symbol->symValue = ModuleResolveKernel(symName);
209
210                                if (symbol->symValue)
211                                        break;
212
213                                KePrint(KERN_ERROR "Could not resolve %s (%#X)\n", symName, symName);
214
215                                return -ENOENT;
216
217                        /* Absolute symbol. No relocation needed. */
218                        case STN_ABS:
219                                break;
220
221                        /* Common symbols aren't supported by the module loading code. */
222                        case STN_COMMON:
223                                KePrint("Please recompile the module with -fno-common.\n");
224                                return -ENOENT;
225
226                        /* Just add the section base to the symbol value. */
227                        default:
228                                symbol->symValue+=module->sectionHeaders[symbol->symIndex].shAddr;
229                }
230        }
231
232        return 0;
233}
234
235void ModuleSymbolResolve(struct Module* module, char* file, int sec)
236{
237        DWORD i;
238        struct ElfReloc* reloc;
239        struct ElfReloc* relTable=(struct ElfReloc*)(file+module->sectionHeaders[sec].shOffset);
240        DWORD relSize=module->sectionHeaders[sec].shSize/sizeof(struct ElfReloc);
241
242        if (!module->sectionHeaders[ module->sectionHeaders[sec].shInfo ].shAddr)
243                return;
244
245        for (i=0; i<relSize; i++)
246        {
247                reloc=&relTable[i];
248                unsigned long* relAddr=(unsigned long*)(module->sectionHeaders[ module->sectionHeaders[sec].shInfo ].shAddr+reloc->addr);
249                int symTabIdx=ELF_R_SYM(reloc->info);
250                struct ElfSymbol* symbol=&module->symTable[symTabIdx];
251
252                switch (ELF_R_TYPE(reloc->info))
253                {
254                        case R_386_NONE:
255                                break;
256
257                        case R_386_32:
258                                *relAddr+=symbol->symValue;
259                                break;
260
261                        case R_386_PC32:
262                                *relAddr+=symbol->symValue-(DWORD)relAddr;
263                                break;
264
265                        default:
266                                KePrint("ModuleSymbolResolve: type = %u, %u\n", ELF_R_TYPE(reloc->info), symbol->symIndex);
267                }
268        }
269}
270
271void* ModuleSectionFind(struct Module* module, const char* sectionNames, const char* name, int total, int* size)
272{
273        int i;
274
275        for (i=0; i<total; i++)
276        {
277                /* If it's not allocated, it won't be in the final module image. */
278                if (!(module->sectionHeaders[i].shFlags & SEC_FLAGS_ALLOC))
279                        continue;
280
281                if (!strcmp(sectionNames+module->sectionHeaders[i].shName, name))
282                {
283                        if (size)
284                                *size=module->sectionHeaders[i].shSize;
285
286                        return (void*)(module->sectionHeaders[i].shAddr);
287                }
288        }
289
290        return NULL;
291}
292
293static struct Module* ModuleFind(char* name)
294{
295        struct Module* curr = NULL;
296       
297        PreemptDisable();
298       
299        ListForEachEntry(curr, &moduleList, next)
300                if (!strcmp(name, curr->object.name))
301                        goto out;
302       
303        curr = NULL;
304       
305out:
306        PreemptEnable();
307        return curr;
308}
309
310int ModuleAdd(char* name, void* file, void* image, unsigned long length, int flags)
311{
312        struct ElfHeader* elfHeader=(struct ElfHeader*)file;
313        struct Module module, *pModule;
314        struct ElfSectionHeader* sectionHeaders;
315        DWORD loadAddr=(DWORD)image;
316        int i, ret=0;
317
318        if (!ELF_HEAD_CHECK(elfHeader) || (elfHeader->fileType != ELF_REL) || (elfHeader->shEntrySize != sizeof(struct ElfSectionHeader)))
319                return -EINVAL;
320
321        /* Iterate through section headers. */
322        sectionHeaders=(struct ElfSectionHeader*)((char*)file+elfHeader->shOffset);
323
324        ZeroMemory(&module, sizeof(struct Module));
325        module.loadAddr = loadAddr;
326        module.sectionHeaders = sectionHeaders;
327       
328        length = PAGE_ALIGN_UP(length);
329
330        if (!image)
331                return -EFAULT;
332
333        if (ModuleFind(name))
334                return -EEXIST;
335
336        ZeroMemory(image, length);
337
338        for (i=0; i<elfHeader->shEntries; i++)
339        {
340                /* Save the symbol table off for resolving later. */
341                if (sectionHeaders[i].shType == SEC_TYPE_SYMTAB)
342                {
343                        module.symTable=(struct ElfSymbol*)(file+sectionHeaders[i].shOffset);
344                        module.symTableSize=sectionHeaders[i].shSize;
345                }
346
347                if (sectionHeaders[i].shType == SEC_TYPE_STRTAB)
348                {
349                        module.strTable=(char*)file+sectionHeaders[i].shOffset;
350                        module.strTableSize=sectionHeaders[i].shSize;
351                }
352
353                /* Align up sizes. */
354                sectionHeaders[i].shSize=SIZE_ALIGN_UP(sectionHeaders[i].shSize, sectionHeaders[i].shAddrAlign);
355        }
356       
357        if (!module.symTable || !module.strTable)
358        {
359                KePrint(KERN_ERROR "MODULE: No module symbol information.\n");
360                return -EINVAL;
361        }
362
363        /* Copy over the module data into a new image. */
364        char* dest;
365        dest=(char*)module.loadAddr;
366
367        for (i=0; i<elfHeader->shEntries; i++)
368        {
369                if (!(sectionHeaders[i].shFlags & SEC_FLAGS_ALLOC))
370                        continue;
371
372                if (sectionHeaders[i].shFlags & SEC_FLAGS_EXEC)
373                {
374                        module.textAddr=(DWORD)dest;
375                        module.textLength=sectionHeaders[i].shSize;
376                }
377
378                sectionHeaders[i].shAddr=(DWORD)dest;
379
380                /* Unless it's a BSS section (or similar), copy the data over. */
381                if (sectionHeaders[i].shType != SEC_TYPE_NOBITS)
382                        memcpy(dest, (char*)(file+sectionHeaders[i].shOffset), sectionHeaders[i].shSize);
383
384                dest+=sectionHeaders[i].shSize;
385        }
386
387        if (ModuleSymbolPrepare(&module))
388                return -ENOENT;
389
390        for (i=0; i<elfHeader->shEntries; i++)
391        {
392                if (sectionHeaders[i].shType == SEC_TYPE_REL)
393                        /* Resolve entries in the module. */
394                        ModuleSymbolResolve(&module, file, i);
395                else if (sectionHeaders[i].shType == SEC_TYPE_RELA)
396                        KePrint("RELA\n");
397        }
398       
399        pModule = (struct Module*)ModuleSectionFind(&module, (char*)file+sectionHeaders[elfHeader->strTabSectionIndex].shOffset, ".gnu.linkonce.thisModule", elfHeader->shEntries, NULL);
400       
401        /* Should rarely hit this case, but it's fairly easy to recover from. */
402        if (!pModule)
403                pModule = (struct Module*)MemAlloc(sizeof(struct Module));     
404       
405        /* FIXME: Search for this_module as well. */
406
407        /* Update the in-memory module structure. The stack structure is not used
408         * any more. */
409        memcpy(pModule, &module, sizeof(struct Module));
410
411        /* Get the symbol table and string table, so we can resolve other symbols later. */
412        pModule->keSymTab=ModuleSectionFind(pModule,
413                (char*)file+sectionHeaders[elfHeader->strTabSectionIndex].shOffset,
414                        ".symtable", elfHeader->shEntries, &pModule->keSymTabSize);
415
416        /* Find the init and exit functions, using the symbol and string table addresses. */
417        int (*modInit)(void);
418
419        modInit = ModuleSymbolFind(pModule, "_ModuleInit", STT_FUNC);
420
421        /* Support for Linux .ko modules. The module startup function can be found
422         * at init_module. */
423         
424        if (!modInit)
425                modInit = ModuleSymbolFind(pModule, "init_module", STT_FUNC);
426
427        PreemptDisable();
428        if (KeObjectCreate(&pModule->object, &moduleSet, name))
429        {
430                KePrint("ModuleAdd: could not add to config.\n");
431                return -EINVAL;
432        }
433       
434        ListAddTail(&pModule->next, &moduleList);
435        PreemptEnable();
436
437        if (modInit)
438                /* Call ModuleInit */
439                ret=(*modInit)();
440
441        return ret;
442}
443
444int SysModuleAdd(char* name, void* data, unsigned long length);
445int SysModuleRemove(const char* name);
446
447struct SysCall moduleSysCalls[]={
448        SysEntry(SysModuleAdd, 12),
449        SysEntry(SysModuleRemove, 4),
450        SysEntryEnd()
451};
452
453void ModulesBootLoad()
454{
455        ArchModulesLoad();
456
457        /* Add the calls to the system table. */
458        SysRegisterRange(SYS_MODULE_BASE, moduleSysCalls);
459}
460
461int SysModuleAdd(char* name, void* data, unsigned long length)
462{
463        void* kData;
464        int ret;
465       
466        /* Check data is ok to access. */
467        kData=(void*)VirtMapPhysRange(MODULE_START, MODULE_END, PAGE_ALIGN_UP(length) >> PAGE_SHIFT, 3);
468
469        ret = ModuleAdd(name, data, kData, length, 0);
470
471        return ret;
472}
473
474int SysModuleRemove(const char* name)
475{
476        KePrint("SysModuleRemove\n");
477        return 0;
478}
479
480int ModuleRequest(const char* fmt, ...)
481{
482        VaList list;
483        char* name;
484        char* args[2];
485        int fds[] = {0, 0, 0};
486        int pid, exitStatus, ret;
487       
488        VaStart(list, fmt);
489        name = vasprintf(fmt, list);
490        VaEnd(list);
491       
492        args[0] = name;
493        args[1] = NULL;
494       
495        pid = Exec("/System/Modules/modloader", fds, args);
496       
497        if (pid < 0)
498                return -ENOENT;
499                                                 
500        ret = ThrWaitForProcessFinish(pid, &exitStatus);
501               
502        if (ret < 0)
503                return ret;
504       
505        MemFree(name);
506
507        if (exitStatus)
508                exitStatus = -ENOENT;   
509       
510        return exitStatus;
511}
512
513void ModuleRelease(struct KeObject* object)
514{
515        KePrint("ModuleRelease\n");
516}
517
518int ModuleInfoInit()
519{
520        return KeSetCreate(&moduleSet, NULL, &moduleType, "Modules");
521}
Note: See TracBrowser for help on using the browser.