Modules and Kernel Symbols
Modules and Kernel Symbols
Hello fellow gentlemen( and ladies?),
I was wondering, when I load a module (or write it per say) how would I go about using kernel functions like printf, or floppy_read.
Everything runs in Ring 0.
Thanks
I was wondering, when I load a module (or write it per say) how would I go about using kernel functions like printf, or floppy_read.
Everything runs in Ring 0.
Thanks
Re: Modules and Kernel Symbols
Maybe you should use some form of dynamic linking. Like for user-space libraries : leaving the printf, floppy_read, etc... symbols undefined at compile time, and then defining their value based on the symbol table of the kernel at run time, when you load the module.Nessphoro wrote:Hello fellow gentlemen( and ladies?),
I was wondering, when I load a module (or write it per say) how would I go about using kernel functions like printf, or floppy_read.
Everything runs in Ring 0.
Thanks
At least that's the way I'd do it for an ELF-based kernel.
Re: Modules and Kernel Symbols
Thanks, but how would one define them at runtime?
Re: Modules and Kernel Symbols
Looking for the memory addresses of the symbols inside of the kernel itself ? For this you have to parse the kernel symbol table. Make sure that you don't strip your kernel with the -s ld parameter and that you have put a part about ".symtab", ".strtab", and ".shstrtab" in your linker script so that said symbols are loaded in RAM by your bootloader.
As for how you parse the symbol table, I leave you with the ELF specification and the gift from the OSdeving gods that the elf.h man page is. But to locate it in RAM, you can use the good old trick of defining symbols in your linker script and accessing them from your code.
An example would be this...
Then, if you code in C or C++, the way to use the newly defined knl_symtab_start and knl_symtab_end symbols is to declare them as external symbols using the "extern" keyword and remember that it's the symbol location, not its value, that is of interest to you. As an example, this...
...would put the location of the beginning of the symbol table in the "symtab_location" variable.
As for how you parse the symbol table, I leave you with the ELF specification and the gift from the OSdeving gods that the elf.h man page is. But to locate it in RAM, you can use the good old trick of defining symbols in your linker script and accessing them from your code.
An example would be this...
Code: Select all
.symtab ALIGN(0x1000) :
{
knl_symtab_start = .;
*(.symtab*)
knl_symtab_end = .;
*(.strtab*)
*(.shstrtab*)
}
Code: Select all
extern void knl_symtab_start;
size_t symtab_location = (size_t) &knl_symtab_start;
Re: Modules and Kernel Symbols
There are at least 3 way to expose functions to dynamic loaded module (and also application).
One is implement a runtime linker, as other suggested. If you used ELF the relo symbols will have st_value left zero for undefined symbols, and you can patch relevant address into it.
Second method is to pass the function pointers (ie API entry point) to the module, so you can control what can be used as well as handle different interface version
Another way to do it is syscall approach. where you expose function via interrupt, much like BIOS, DOS, and "INT 80" services.
One is implement a runtime linker, as other suggested. If you used ELF the relo symbols will have st_value left zero for undefined symbols, and you can patch relevant address into it.
Second method is to pass the function pointers (ie API entry point) to the module, so you can control what can be used as well as handle different interface version
Another way to do it is syscall approach. where you expose function via interrupt, much like BIOS, DOS, and "INT 80" services.
Re: Modules and Kernel Symbols
To share a bit on the topic, sooner you will find that the kernel symbol table is full of ... symbols. You can do this to reduce the table size:
In kexport.txt you put in the symbols you want to export one per a line, for example:
To retrieve the kernel symbol and offsets, you walk on the ELF header, look for SHT_SYMTAB sections. It may be easier to understand with code, here is what I do:
The structures are defined as in ELF_format.pdf
Code: Select all
@$(OBJCOPY) --strip-debug --strip-unneeded --keep-symbols=kexport.txt $(BIN)$(KERNEL_BIN)
Code: Select all
kmalloc
kprintf
Code: Select all
if ( (s = find_section ( SHT_SYMTAB )) != NULL ) {
symtbl = (Elf32_Sym*) (image + s->sh_offset);
symtbl_num = (s->sh_size / sizeof(Elf32_Sym));
symbols = (char*) (image + s->sh_offset + s->sh_size );
kprintf ("symbols: %p\n", symbols );
}
void Elf32::list_sym ( void ) {
kprintf ( "Symbol Table: %p, Total %d symbols\n", symbols, symtbl_num );
for ( int i=0; i<symtbl_num; i++ ) {
if ( symtbl[i].st_name == 0 ) continue;
kprintf ("Sym[%d] := %X (%s) -> %X+%X\n", i, symtbl[i].st_name, symbols + symtbl[i].st_name, image_base, symtbl[i].st_value );
}
}
- Owen
- Member
- Posts: 1700
- Joined: Fri Jun 13, 2008 3:21 pm
- Location: Cambridge, United Kingdom
- Contact:
Re: Modules and Kernel Symbols
This is why you
- Build as a DSO
- Use -fvisibility=hidden and
Code: Select all
#if defined(BUILDING_THE_KERNEL_BINARY) #define KERNEL_API __attribute__((visibility("default"))) #else #define KERNEL_API __attribute__((visibility("hidden"))) #endif
Re: Modules and Kernel Symbols
Well thanks guys