Does anyone have a working dynamic linker, or some good documentation on implementing one.

I have reached a point where I would like to add drivers to my OS, which are loaded at runtime (rather than statically linked).

If I understand correctly, to achieve this I need a dynamic linker - which is where I'm stuck :)

I did notice that old DOS drivers didn't need to be dynamically linked, so if there is a good solid workaround for dynamic linking I'd be interested in that too.

The only considerations are that the drivers are loaded from disk (I have a working FAT12 FS) and may be stored anywhere in memory.
Posted on 2004-03-08 01:11:57 by Sentient

Does anyone have a working dynamic linker, or some good documentation on implementing one.

I have reached a point where I would like to add drivers to my OS, which are loaded at runtime (rather than statically linked).

The easily solution is to require fixed entry points at known offsets from the beginning of the file.


If I understand correctly, to achieve this I need a dynamic linker - which is where I'm stuck :)

Well, strictly speaking this is not necessary if you carefully define the interface to your drivers. Dynamic linking is useful when you need to link arbitrary code at run-time (i.e., code that doesn't have a fixed set of entry points).


I did notice that old DOS drivers didn't need to be dynamically linked, so if there is a good solid workaround for dynamic linking I'd be interested in that too.

They had fixed entry points (or used the INT instruction).


The only considerations are that the drivers are loaded from disk (I have a working FAT12 FS) and may be stored anywhere in memory.


If you need true dynamic linking, all you do is build part of the linker into the OS and have it automatically resolve the linkages when it loads the dynamically linked code. Obviously, you have to be able to read some sort of symbol table information from the file being loaded for linking and correlate this with the program (OS) linking to such code. But as it is *your* OS, you get to define how the linkage works.
Cheers,
Randy Hyde
Posted on 2004-03-08 14:29:30 by rhyde
Being in a flat protected mode (4GB Selectors), each driver will have a different offset in memory which is dynamically allocated.

I understand your idea about fixed offset within the file, but when I use absolute addressing its going to cause serious problems. Without prior knowledge, I would assume that DOS drivers avoided this by being loaded on segment boundaries (ie 16byte aligned), hence the offset would always start at 0. I dont have this option (or should I say, I want to avoid segmentation).

Am I missing a point, or did I fail to mention something which changes your answer?
Posted on 2004-03-08 18:14:39 by Sentient
Dynamic linkage is a good thing - this means you can reference your kernel-mode API by name instead of by syscall "magic numbers". And some basic dynamic linking isn't very hard to implement (until you start adding reference counting and such, but that can be added 'later' ;)). If you use a format like PE or ELF for kernel+drivers (and you really should), you already have import and export tables.

There's a bunch of ways to do a driver model. You could either have no exports and a single "DriverEntry" entrypoint, which would fill a structure with various other information, depending on your OS needs (DriverInit, DriverDestroy, DriverIoControl, DriverProcessAttach, DriverProcessDetach comes to mind), or you could export all the necessary routines via an export table.

Btw, if your drivers share the same memory space (having each driver being a separate process w/separate CR3 is probably a bit overkill :p),
do remember to "rebase" the core OS drivers to avoid relocations... if using the PE format for your drivers, this is easy - the MS rebase tool can do it :)
Posted on 2004-03-09 01:59:24 by f0dder

Being in a flat protected mode (4GB Selectors), each driver will have a different offset in memory which is dynamically allocated.

I understand your idea about fixed offset within the file, but when I use absolute addressing its going to cause serious problems. Without prior knowledge, I would assume that DOS drivers avoided this by being loaded on segment boundaries (ie 16byte aligned), hence the offset would always start at 0. I dont have this option (or should I say, I want to avoid segmentation).

Am I missing a point, or did I fail to mention something which changes your answer?


By "fixed entry points" I meant offset from the beginning of the file, not an absolute address in memory. When you load the file into memory, you can compute the entry points of the various routines by adding the offset and the load address together.

That's the easy way, and works okay for device drivers.

For generic dynamic loading, you need to supply a symbol table with the object files that specifies the offsets of the various symbols into the object file and use a simple lookup at load time to correlate addresses. Again, the details depend upon the file format you use (or create).
Cheers,
Randy Hyde
Posted on 2004-03-09 12:59:35 by rhyde
It probably makes more sense to call them "relative entry points". Relative to your driver load address, where the load address is where you load the first byte of the driver file.

You can also skip the symbol table lookup, and just hold a table of entry point addresses at or near the beginning of the driver file. The table in the file will contain file offsets and an entry point count. The driver loader would just load the driver and update the table to hold true addresses.

How will you handle data?

In a flat model, nonstack labels are absolute. There is no implicit relative address mode for data to mirror the EIP-relative address mode for jumps and calls. All relative data addresses must use "based addressing", where you use up a register to hold a "base" address.

If you do not use based addresses for driver data, the driver file will need to hold a relocation table for data addresses.
Posted on 2004-03-10 23:24:23 by tenkey
It all depends on what you want to do, I guess. If you want to support other tools than just whatever assembler you're using, "fixed entrypoints" is not the best idea - most linkers don't give you the fine-grained control necessary to do this. There's sense in using ELF or PE. But of course it's your OS, so you choose what to do.

Whatever fileformat you choose, I would still recommend a symbol-based approach rather than fixed offsets, though. Even if you don't care for other tools than your own, named importing/exporting is a lot more flexible & extensible.
Posted on 2004-03-11 03:27:55 by f0dder