Page 1 of 1

Modules and Kernel Symbols

Posted: Thu Jun 30, 2011 12:02 am
by Nessphoro
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

Re: Modules and Kernel Symbols

Posted: Thu Jun 30, 2011 12:42 am
by Neolander
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
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.

At least that's the way I'd do it for an ELF-based kernel.

Re: Modules and Kernel Symbols

Posted: Thu Jun 30, 2011 1:32 am
by Nessphoro
Thanks, but how would one define them at runtime?

Re: Modules and Kernel Symbols

Posted: Thu Jun 30, 2011 2:20 am
by Neolander
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...

Code: Select all

.symtab ALIGN(0x1000) :
{
    knl_symtab_start = .;

    *(.symtab*)

    knl_symtab_end = .;

    *(.strtab*)
    *(.shstrtab*)
}
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...

Code: Select all

extern void knl_symtab_start;
size_t symtab_location = (size_t) &knl_symtab_start;
...would put the location of the beginning of the symbol table in the "symtab_location" variable.

Re: Modules and Kernel Symbols

Posted: Thu Jun 30, 2011 5:03 am
by bluemoon
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.

Re: Modules and Kernel Symbols

Posted: Thu Jun 30, 2011 8:16 am
by bluemoon
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:

Code: Select all

@$(OBJCOPY) --strip-debug --strip-unneeded --keep-symbols=kexport.txt $(BIN)$(KERNEL_BIN)
In kexport.txt you put in the symbols you want to export one per a line, for example:

Code: Select all

kmalloc
kprintf
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:

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 );
    }
}
The structures are defined as in ELF_format.pdf

Re: Modules and Kernel Symbols

Posted: Thu Jun 30, 2011 12:37 pm
by Owen
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
    
(Or, if using, e.g. PE, __attribute__((dllexport))/__attribute__((dllimport)))

Re: Modules and Kernel Symbols

Posted: Thu Jun 30, 2011 12:58 pm
by Nessphoro
Well thanks guys