Posted: Tue Nov 21, 2006 2:40 pm
But x86 has no such addressing mode (unless you are in long mode)Solar wrote:I would say you need both. PIC allows you to access data relative to the instruction pointer, which is fine for your binary image,João Jerónimo wrote:I think that's the classical way to load programs in archs without MMU...Solar wrote:It makes certain things trickier - you need support for PIC (position-independent code); a binary format that has proper relocation tables,
If the architecture doesn't support executing PIC eficiently, then parhaps the best choice is relocation tables...
You need relocation tables even without shared libraries because, on x86, the assemblers are unable to generate position-independent code unless the programmer explicitly writes the program that way...but you need relocation tables once you want to access e.g. libraries - which will be at a different offset from your binary at each startup.
So you risk having the address space extremelly fragmented... (unless you conseder the holes in the library's space as heap, which is a solution, too)I wouldn't move a library around once it has been loaded.In my (purely theoric) opinion, address space sharing makes it much simpler to implement shared libraries than with address space separation...
???You will always have some programmers caching a library's address locally, either due to laziness or claims of efficiency. When the library moves, and programs access the old location because they don't go through the proper system services to get the current library address... booom.
I thought that the loader automatically relocated library calls...
I doubt it's a good idea to relink an application against it's libraries just because you now have a new library version!Why did I say you need offset tables? Easy: Library versions. If your apps were jumping at library functions directly, you would have to relink all applications using a certain library once you update that library. Functions change length, new functions get inserted between the old ones...
*Newly executed* programs will use the new lib, not the old ones...
Didn't understand...AmigaOS solved it quite smartly: When you request a library from the system via OpenLibrary(), the system would give you the "base pointer" to that library - either the position where it was already loaded previously, or the address it was just loaded to due to your request.
I was talking only about shared (but not dynamic linked libraries)...
PS: Have you ever considered to omit shared (loadtime linking) library support at all and using IPC to call library functions? That's exactly what I'm thinking about to implement in the future!
Some time ago, when I started doing low level programming in DOS, one of the first programs I worked on was a Brainfuck interpreter... And I immediatly thought about a BrainfuckOS, capable of multitasking Brainfuck apps by counting interpreted instructions! One of the things I though was using the brainfuck "terminal" (read with "," and written to with ".") as a command space to allow apps to access kernel services (the IO manager and th IPC subsystem)... When an app wanted to provide some shared function(ality) (being it a previlleged service or an ordinary utilitary function), it would registry that command (which in fact would behave like an IPC (or would I say RPC?) port) sending the correct commands to the kernel command space... To call a shared function from some other program, that program would issue a command calling that function...
None of this stupid ideas have passed beyond pure "JJ's brainfuck" so far!
In fact, that's a lie! I'm still thinking about using IPC to call functions, but now I've thrown away that idea of interpreting BF code... also, I'm convinced that a new mechanism, called "IPC scripts" I've invented will attenuate the overhead of calling the (kernelmode) IPC subsystem too much times during program execution and waiting for the other process to handle the request and return back the result...
I've not yet spent much time thinking about this applied to library calls... but for calling system functions (such as "servers" in a microkernel design) I think it will work...
PS2: Another solution for having dynamic link functions in any OS (not just without MMU), that relies on IPC too (but this time not for making the proper function calls) would be to implement a library server that would enumerate all the library functions available using the IPC namespace (assuming that the kernel has one) and the application that needs the function would ask that server to provide the function through *some* way that the underlying platform allows to use (shared memory, IPC messaging to copy the code through address spaces, a far pointer), already correctly relocated to the address the requesting app asks (this isn't needed if the address space is shared, as happens without MMUs)...
PS3: None of this solutions is suitable if you already implemented a shared library mechanism (they are just design proposals), but I hope it provides some ideas the work arround the problem...
JJ