Modules and Kernel Symbols

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
Nessphoro
Member
Member
Posts: 308
Joined: Sat Apr 30, 2011 12:50 am

Modules and Kernel Symbols

Post 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
User avatar
Neolander
Member
Member
Posts: 228
Joined: Tue Mar 23, 2010 3:01 pm
Location: Uppsala, Sweden
Contact:

Re: Modules and Kernel Symbols

Post 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.
User avatar
Nessphoro
Member
Member
Posts: 308
Joined: Sat Apr 30, 2011 12:50 am

Re: Modules and Kernel Symbols

Post by Nessphoro »

Thanks, but how would one define them at runtime?
User avatar
Neolander
Member
Member
Posts: 228
Joined: Tue Mar 23, 2010 3:01 pm
Location: Uppsala, Sweden
Contact:

Re: Modules and Kernel Symbols

Post 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.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Modules and Kernel Symbols

Post 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.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Modules and Kernel Symbols

Post 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
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Modules and Kernel Symbols

Post 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)))
User avatar
Nessphoro
Member
Member
Posts: 308
Joined: Sat Apr 30, 2011 12:50 am

Re: Modules and Kernel Symbols

Post by Nessphoro »

Well thanks guys
Post Reply