Elf Shared Libraries
Elf Shared Libraries
I'm writing code to handle ELF shared libraries (.so files).
In kernel mode I've yet done something, because it's simpler (only the kernel can load the modules).
For usermode, how can I implement ELF shared libraries?
I've seen some implementations. They use a user mode program that loads the new program, resolves its dependencies and executes it. Maybe it's a modular way, But with this method, how can I share shared libraries in memory? I must load a shared library two times for two different programs? And what if I want to resolve dependencies at run-time instead of load-time?
I'm very confused, what must I do in your opinion? Have you any example implementation that share shared libraries and resolve at run-time? Or also that only share shared libraries if loading at runtime isn't very useful?
Help me!!!
In kernel mode I've yet done something, because it's simpler (only the kernel can load the modules).
For usermode, how can I implement ELF shared libraries?
I've seen some implementations. They use a user mode program that loads the new program, resolves its dependencies and executes it. Maybe it's a modular way, But with this method, how can I share shared libraries in memory? I must load a shared library two times for two different programs? And what if I want to resolve dependencies at run-time instead of load-time?
I'm very confused, what must I do in your opinion? Have you any example implementation that share shared libraries and resolve at run-time? Or also that only share shared libraries if loading at runtime isn't very useful?
Help me!!!
Re: Elf Shared Libraries
if you find any could you post it here?
i've been looking for good examples for ~2 months. I havnt found any yet
so far i've been able to load simple applications, read the .note section and identify the section headers (which is where i am stuck, as although there is a lot of information there, none of it seems to be correct and im Page Faulting left, right and centre :S)
i've been looking for good examples for ~2 months. I havnt found any yet
so far i've been able to load simple applications, read the .note section and identify the section headers (which is where i am stuck, as although there is a lot of information there, none of it seems to be correct and im Page Faulting left, right and centre :S)
Re: Elf Shared Libraries
No, you needn't, but you have to implement COW. If they just read or execute the code you can share the library across all processes and all will be fine. If one tries to write data to the libraries range you just create a new page, copy the data and map it to the process. All other process' data won't be touched.MarkOS wrote: I must load a shared library two times for two different programs?
Re: Elf Shared Libraries
You might want to have a look at using position independent code for your shared libraries. The way it is performed changes from architecture to architecture. However, on an Intel or AMD processor it uses a global offset table.
Normally, the compiler emits a instruction which accesses a global variable or calls a function with an absolute address. When using position independent code the compiler will emit call instructions that use relative addresses. The slight more complex part is when the compiler emits code to access a global variable (non-local non-stack variable).
To access a global variable the compiler will emit a call to a i686.. get_px.. something function. This function is generated by the linker automatically. However, you can define this function your self. Anyway, this function (odd but true) will return the address the processor pushed onto the stack for the call instruction. The next instructions add a offset, that was generated by the linker, to this value return (which is the instruction after the call instruction's address) to produce the address of the position independent code global offset table.
It then access a entry inside this table which is the address of the actual variable it wants. So essentially the table is a list of pointers to global variables.
The relative call instructions to functions and the indirection provided by the global offset table _should_ allow you to load and execute the library's code anywhere in memory. It would even allow you to map the library to completely different addresses in different process spaces which is what you are wanting to do.
This behavior is invoked for gcc/g++ using the option -fPIC. gcc test.c -fPIC -o test && objdump test -x
Normally, the compiler emits a instruction which accesses a global variable or calls a function with an absolute address. When using position independent code the compiler will emit call instructions that use relative addresses. The slight more complex part is when the compiler emits code to access a global variable (non-local non-stack variable).
To access a global variable the compiler will emit a call to a i686.. get_px.. something function. This function is generated by the linker automatically. However, you can define this function your self. Anyway, this function (odd but true) will return the address the processor pushed onto the stack for the call instruction. The next instructions add a offset, that was generated by the linker, to this value return (which is the instruction after the call instruction's address) to produce the address of the position independent code global offset table.
It then access a entry inside this table which is the address of the actual variable it wants. So essentially the table is a list of pointers to global variables.
The relative call instructions to functions and the indirection provided by the global offset table _should_ allow you to load and execute the library's code anywhere in memory. It would even allow you to map the library to completely different addresses in different process spaces which is what you are wanting to do.
This behavior is invoked for gcc/g++ using the option -fPIC. gcc test.c -fPIC -o test && objdump test -x
Re: Elf Shared Libraries
OK. I know this. But if dynamic linking is handled by an external program (and not by the kernel) like in Linux, how can it know that the shared library is yet loaded by a program?cyr1x wrote:No, you needn't, but you have to implement COW. If they just read or execute the code you can share the library across all processes and all will be fine. If one tries to write data to the libraries range you just create a new page, copy the data and map it to the process. All other process' data won't be touched.MarkOS wrote: I must load a shared library two times for two different programs?
Which is better for performance between runtime and loadtime dynamic linking? If runtime is better, how can I handle it?
Re: Elf Shared Libraries
If you load a sl you just do a RegisterLibrary(char*) or something like that and the kernel will know.MarkOS wrote:cyr1x wrote:MarkOS wrote: ..., how can it know that the shared library is yet loaded by a program?
Re: Elf Shared Libraries
OK. But with this implementation where an external program does the dynamic linking, why must I let the kernel know libraries loaded???cyr1x wrote: If you load a sl you just do a RegisterLibrary(char*) or something like that and the kernel will know.
With this implementation is the external program that should know libraries yet loaded...But how?
Or maybe do you think shared libraries must be handled directly by the kernel and not with an external program?
Re: Elf Shared Libraries
Yep.MarkOS wrote: Or maybe do you think shared libraries must be handled directly by the kernel.
Nevertheless, if an program wants to load an library itself no one stops it from doing a "open()".
Re: Elf Shared Libraries
But in Linux, the dynamic linker ld is itself an ELF file. At program startup, the system maps the ld.so to a part of the address space and runs its bootstrap code. ld.so resolves dependencies of the program, and after passes the control to the program.
Which are pro and cons of dynamic linking with an external program and of dynamic linking directly in the kernel?
This is my main question.
Which are pro and cons of dynamic linking with an external program and of dynamic linking directly in the kernel?
This is my main question.
Re: Elf Shared Libraries
HmmMarkOS wrote: Which are pro and cons of dynamic linking with an external program and of dynamic linking directly in the kernel?
For the extern linker you would have more modularity, but it adds more complexity.
For kernel you would have less complexity with _probably_ more speed.
I prefer the second, but it's really up to you on how you do it.
Re: Elf Shared Libraries
My idea is the same. Because I read that implementing into the kernel is faster than into an external program. And also because with the kernel the libraries are shared more simply. In your opinion I must share libraries directly into kernel memory (up to 3GB) or into lower memory? Into kernel memory they would be yet shared, because kernel memory is in each address space.cyr1x wrote: Hmm
For the extern linker you would have more modularity, but it adds more complexity.
For kernel you would have less complexity with _probably_ more speed.
I prefer the second, but it's really up to you on how you do it.
But...Dynamic linking with the kernel can be also done at runtime? Or only at loadtime?
Re: Elf Shared Libraries
I would load them into userspace memory just below(or above, depending on your memory layout), because you don't need context-switches to call functions. Libraries don't need to be in every address-space as only few need them. When you put them in userspace make sure that you use copy-on-write or you will be in very bad shape if one program modifies the code and another executes this.MarkOS wrote: In your opinion I must share libraries directly into kernel memory (up to 3GB) or into lower memory? Into kernel memory they would be yet shared, because kernel memory is in each address space.
Of course it can be done, but this adds complexity to the dynamic linker. Again it's up to you.MarkOS wrote: But...Dynamic linking with the kernel can be also done at runtime? Or only at loadtime?
Re: Elf Shared Libraries
Thank you for your opinions and clarifications! Now I go to develop dynamic linking. When I'll reach this goal, I'll study how runtime linking works.cyr1x wrote:I would load them into userspace memory just below(or above, depending on your memory layout), because you don't need context-switches to call functions. Libraries don't need to be in every address-space as only few need them. When you put them in userspace make sure that you use copy-on-write or you will be in very bad shape if one program modifies the code and another executes this.MarkOS wrote: In your opinion I must share libraries directly into kernel memory (up to 3GB) or into lower memory? Into kernel memory they would be yet shared, because kernel memory is in each address space.
Of course it can be done, but this adds complexity to the dynamic linker. Again it's up to you.MarkOS wrote: But...Dynamic linking with the kernel can be also done at runtime? Or only at loadtime?
Re: Elf Shared Libraries
For now I'm developing elf header handling and relocation.
I think this is what must I do to execute an elf. Correct my mistakes.
1 - Load ELF file (of course )
2 - Relocate section headers
3 - Get dependencies of the ELF file
4 - Load shared libraries needed (for each library you must do 2, 3, 4 and 5)
5 - Relocate all the ELF replacing external symbols
6 - Execute the ELF!!!
I think this is what must I do to execute an elf. Correct my mistakes.
1 - Load ELF file (of course )
2 - Relocate section headers
3 - Get dependencies of the ELF file
4 - Load shared libraries needed (for each library you must do 2, 3, 4 and 5)
5 - Relocate all the ELF replacing external symbols
6 - Execute the ELF!!!
Re: Elf Shared Libraries
I haven't gone in deep in ELF for now, but this should be correct, well except for one point, you need to load the shared libraries too .