Hi,
I am trying to establish a shared arena for loading DLL's, i.e. a shared memory region, in which DLL's are loaded at the same address in each address space. I also need some ELF shared library loaded at fixed address, so I could call routines in .so from these DLL's (yes, a mixed case: LX format DLL's calling an ELF shared object, this shared object is a client library for some servers, and I want to call their API's from DLL's). So, I intend to load a shared oblect at fixed address to be the same in different address spaces. But the l4env build system seems to produce PIC shared objects only, and no suitable example. Is there any way to compile a non-PIC shared object with l4env build system? I also hope the 'loader' server will load the shared library at pre-compiled address. Maybe, also the PIC ones could be loaded at desired address (I know that, at least, libloader.s.so is loaded at fixed address, but maybe, this is a single hardcoded case)
Thanks in advance, valery
On Thu Sep 29, 2011 at 07:01:50 +1300, Valery V. Sedletski wrote:
I am trying to establish a shared arena for loading DLL's, i.e. a shared memory region, in which DLL's are loaded at the same address in each address space. I also need some ELF shared library loaded at fixed address, so I could call routines in .so from these DLL's (yes, a mixed case: LX format DLL's calling an ELF shared object, this shared object is a client library for some servers, and I want to call their API's from DLL's). So, I intend to load a shared oblect at fixed address to be the same in different address spaces. But the l4env build system seems to produce PIC shared objects only, and no suitable example. Is there any way to compile a non-PIC shared object with l4env build system?
No, but adding an extra rule to a Makefile should be easy.
I also hope the 'loader' server will load the shared library at pre-compiled address. Maybe, also the PIC ones could be loaded at desired address (I know that, at least, libloader.s.so is loaded at fixed address, but maybe, this is a single hardcoded case)
Yes, this address is predefined. I'm not sure if it does load such libs, just try it.
Adam
On Sun, 2 Oct 2011 23:00:11 +0200, Adam Lackorzynski wrote:
On Thu Sep 29, 2011 at 07:01:50 +1300, Valery V. Sedletski wrote:
...
No, but adding an extra rule to a Makefile should be easy.
Yes, I copied the rules for compiling *.s.o objects and linking them to *.s.so PIC shared objects to the local makefile, and changed .s.o to .ss.o and .s.so to .ss.so to make the build system happy, and deleted $(PICFLAGS) from the rules. Also, I added -Ttext ... to the linker command line. Now it builds at a predefined address.
I also hope the 'loader' server will load the shared library at pre-compiled address. Maybe, also the PIC ones could be loaded at desired address (I know that, at least, libloader.s.so is loaded at fixed address, but maybe, this is a single hardcoded case)
Yes, this address is predefined. I'm not sure if it does load such libs, just try it.
I then linked my program with a just buillt shared library using -Bdynamic linker option. But when I'm trying to start the program, it fails when loading the shared library, the error from ldso is "can't map libkal.ss.so". I searched for that string in ldso sources and it appears that the failed fragment is:
preload = (caddr_t) _dl_mmap(0, st.st_size, + 1, PROT_READ | PROT_WRITE | MAP_PRIVATE, fd, 0);
So, as I understood, it can't load the binary by mmap'ing it at random address. So, does it mean that only loading at random addresses is supported? What could I do? -- I need this library to be loaded at known address, because I need it to be the same in all programs' address spaces to have possibility to link to a single copy of this library from other programs.
Any suggestions? What could I do? Fork ld.so?
WBR, valery
On Thu, 06 Oct 2011 20:43:38 +1300 (MSD), Valery V. Sedletski wrote:
On Sun, 2 Oct 2011 23:00:11 +0200, Adam Lackorzynski wrote:
....
I now built a shared lib as PIC and linked to the binary. And made a router function, which is at the fixed address in the binary, which acts as a wrapper for shared library functions. So, now I can call the shared lib functions from a fixed address. But another problem -- libloader.s.so loads at 0x10000 and prevents my OS/2 binary to load. The area at 0x10000 is the default OS/2 binary start address and I cannot change this :( Is there a way to move libloader.s.so from the address 0x10000 or to avoid loading it at all? Now I have my shared lib dynamically linked with the binary, and it gets loaded by ldso (aka libld-l4.s.so). Maybe, there is a mode of loading shared libs when libloader.s.so is not needed (for example, I am not sure if it is needed to be loaded when I load it via dlopen() e.g.)
Maybe, I must build a custom libloader.s.so version which loads at different address? Or maybe, there is a legal way to move libloader.s.so to another address? -- I know that, for example, thread lib heap can be moved from its default position by changing a variable which is defined as a weak symbol. So, maybe it could be done likewise? Help, please..
Thanks in advance, valery
On Fri, 07 Oct 2011 01:20:19 +1300 (MSD), Valery V. Sedletski wrote:
Maybe, I must build a custom libloader.s.so version which loads at different address? Or maybe, there is a legal way to move libloader.s.so to another address? -- I know that, for example, thread lib heap can be moved from its default position by changing a variable which is defined as a weak symbol. So, maybe it could be done likewise? Help, please..
A correction: when using the dynamic loading, there is an ldso at 0x10000, not libloader. So, an idea: maybe, it is possible to compile ldso as a static lib, and link it statically to the binary? -- Then it will load at the binary link address, not 0x10000 and it will be free..
Hope it will help, valery
On Fri Oct 07, 2011 at 04:34:41 +1300, Valery V. Sedletski wrote:
On Fri, 07 Oct 2011 01:20:19 +1300 (MSD), Valery V. Sedletski wrote:
Maybe, I must build a custom libloader.s.so version which loads at different address? Or maybe, there is a legal way to move libloader.s.so to another address? -- I know that, for example, thread lib heap can be moved from its default position by changing a variable which is defined as a weak symbol. So, maybe it could be done likewise? Help, please..
A correction: when using the dynamic loading, there is an ldso at 0x10000, not libloader. So, an idea: maybe, it is possible to compile ldso as a static lib, and link it statically to the binary? -- Then it will load at the binary link address, not 0x10000 and it will be free..
There's no way to change that address at runtime. Please just change it in the code (loader/server/src/app.cc, APP_ADDR_LDSO) and try that. Changing the way the linking is done is probably much more troublesome. In L4Re this should work better as the lower region of the virtual address space is not used for that purpose.
Adam
On Thu, 6 Oct 2011 23:27:00 +0200, Adam Lackorzynski wrote:
There's no way to change that address at runtime. Please just change it in the code (loader/server/src/app.cc, APP_ADDR_LDSO) and try that. Changing the way the linking is done is probably much more troublesome. In L4Re this should work better as the lower region of the virtual address space is not used for that purpose.
Adam
Yes, so, it is hardcoded in loader binary... And it could probably break the compatibility with something. -- But I've got another idea. I could try also to avoid using ldso at all. -- Just compile in the libdl support without runtime linker support. The libdl sources contain a define #ifdef SHARED, so this gives an idea that libdl could be compiled as a static library. And even, the symbols imported from ldso, are #ifdef'ed, so maybe, it could be linked statically with the binary. Maybe, that can help..
On Fri Oct 07, 2011 at 10:31:03 +1300, Valery V. Sedletski wrote:
On Thu, 6 Oct 2011 23:27:00 +0200, Adam Lackorzynski wrote:
There's no way to change that address at runtime. Please just change it in the code (loader/server/src/app.cc, APP_ADDR_LDSO) and try that. Changing the way the linking is done is probably much more troublesome. In L4Re this should work better as the lower region of the virtual address space is not used for that purpose.
Yes, so, it is hardcoded in loader binary... And it could probably break the compatibility with something. -- But I've got another idea. I could try also to avoid using ldso at all. -- Just compile in the libdl support without runtime linker support. The libdl sources contain a define #ifdef SHARED, so this gives an idea that libdl could be compiled as a static library. And even, the symbols imported from ldso, are #ifdef'ed, so maybe, it could be linked statically with the binary. Maybe, that can help..
Ok, try it.
Adam
On Fri, 7 Oct 2011 00:36:34 +0200, Adam Lackorzynski wrote:
Ok, try it.
So, I tried to link the libdl as a static library to my program, and load my shared lib with dlopen(). It almost worked, but I got many unresolved symbols when loading the library. So, I tried to add the missing static libs when linking my shared lib. As I understood, when linking shared libs, I should link it with libs with '.p' suffix. But not all libs have their counterparts with '.p' suffix. I added these libs:
LIBS = -los2exec -los2fs -los2server -lloaderif.p -levents -llist_alloc.p -lgeneric_fprov.p \ -ldemangle.p -ll4rm.p -ldm_mem.p -ldm_generic.p -lthread.p -lsemaphore.p -ll4env.p -ll4env_err.p\ -lslab.p -llogserver_capsule.p -ll4rm.p -lthread.p -ldm_generic.p -lnames.p -ll4util_root.p -ll4util.p \ -lsigma0.p -lroot.p -ll4sys.p -nostdlib -u printf -lc_be_io.o -u mmap_anon -lc_be_simple_mem.p \ -lc_be_time -lrtc.p -ll4rm.p -ldm_mem.p -ldm_generic.p -lthread.p -lsemaphore.p -ll4env.p -ll4env_err.p \ -lslab.p -llogserver_capsule.p -ll4rm.p -lthread.p -ldm_generic.p -lnames.p -ll4util_root.p -ll4util.p \ -lsigma0.p -luc_c $(GCCLIB) -u mmap_anon \ -lc_be_simple_mem.p -ll4rm.p -ldm_mem.p -ldm_generic.p -lc_be_time -lc_be_mmap.p -lc_be_mmap_util.p \ -lc_be_l4env_start_stop.p -lgeneric_ts.p -lc_be_syslog -lc_be_file-table -luc_be_simple_sleep \ -ll4vfs_common_io -ll4vfs_basic_io -ll4vfs_connection -ll4vfs_basic_name_server -ll4vfs_name_server \ -ll4vfs_name_space_provider -ll4vfs_extendable -ll4sys.p -luc_c -ll4util_root.p -lrtc.p
-- here, os2exec, os2fs and os2server are client libs for my servers. It seems that no need for client libs to make a version with '.p' suffix (i.e. to be linked with shared libs). But I still have some missing symbols, like 'main', 'crt0_tramppage' (the last should be in C startup code, but crt0.s.o has not it). Some libs, like 'events', have no a version with '.p' suffix. (I noticed that such libs are mostly libc backends).
What is the difference of libs with '.p' suffix from the libs without it? Should I make myself such versions for my libs (I use only client ones for my servers). And could anyone tell, what libs from the above list could reference symbols like 'main', 'crt0_tramppage'?
Thanks in advance, valery
On Sat, 08 Oct 2011 23:02:40 +1300 (MSD), Valery V. Sedletski wrote:
On Fri, 7 Oct 2011 00:36:34 +0200, Adam Lackorzynski wrote:
Ok, try it.
So, I tried to link the libdl as a static library to my program, and load my shared lib with dlopen(). It almost worked, but I got many unresolved symbols when loading the library. So, I tried to add the missing static libs when linking my shared lib. As I understood, when linking shared libs, I should link it with libs with '.p' suffix. But not all libs have their counterparts with '.p' suffix. I added these libs:
What is the difference of libs with '.p' suffix from the libs without it? Should I make myself such versions for my libs (I use only client ones for my servers). And could anyone tell, what libs from the above list could reference symbols like 'main', 'crt0_tramppage'?
Yes, I found it: the symbols 'crt0_tramppage' and 'main' were referenced from libl4env.p.a. Strange, because it has '.p' suffix... But when I remove this library from linker command line, the next symbol is missing: 'l4env_request_config_u32'. Who may need it and what libs could be safely removed?
WBR, valery
Heh, 'l4env_request_config_u32' was referenced by -ll4rm.p. But I canot remove it, because I need it. -- I use l4rm functions for attaching dataspaces. So, what could be the solution? Leave -ll4env.p as is? But what to do with main() and crt0.o?
On Sun, 09 Oct 2011 01:43:32 +1300 (MSD), Valery V. Sedletski wrote:
Heh, 'l4env_request_config_u32' was referenced by -ll4rm.p. But I canot remove it, because I need it. -- I use l4rm functions for attaching dataspaces. So, what could be the solution? Leave -ll4env.p as is? But what to do with main() and crt0.o?
But l4rm must be a single instance in a single application, so I need to use an l4rm instance from my application, not in a shared lib... So, I need somehow to call my application region mapper from the shared lib... But I cannot use the ldso for linkage. So I need to make the linkage manually... I see only one solution: to pass the needed l4rm function pointers to the shared lib 'init' function. But maybe, the better solution exists? Any ideas?
On Sun Oct 09, 2011 at 03:21:14 +1300, Valery V. Sedletski wrote:
On Sun, 09 Oct 2011 01:43:32 +1300 (MSD), Valery V. Sedletski wrote:
Heh, 'l4env_request_config_u32' was referenced by -ll4rm.p. But I canot remove it, because I need it. -- I use l4rm functions for attaching dataspaces. So, what could be the solution? Leave -ll4env.p as is? But what to do with main() and crt0.o?
But l4rm must be a single instance in a single application, so I need to use an l4rm instance from my application, not in a shared lib... So, I need somehow to call my application region mapper from the shared lib... But I cannot use the ldso for linkage. So I need to make the linkage manually... I see only one solution: to pass the needed l4rm function pointers to the shared lib 'init' function. But maybe, the better solution exists? Any ideas?
Sounds hacky but I cannot provide an alternative. I think you lost me a bit wrt your current setup, so if your solution works for you I'm happy.
Adam
On Mon, 10 Oct 2011 11:19:17 +0200, Adam Lackorzynski wrote:
But l4rm must be a single instance in a single application, so I need to use an l4rm instance from my application, not in a shared lib... So, I need somehow to call my application region mapper from the shared lib... But I cannot use the ldso for linkage. So I need to make the linkage manually... I see only one solution: to pass the needed l4rm function pointers to the shared lib 'init' function. But maybe, the better solution exists? Any ideas?
Sounds hacky but I cannot provide an alternative. I think you lost me a bit wrt your current setup, so if your solution works for you I'm happy.
Yes, it almost works now -- I made the pointers to l4rm functions and some other ones, passed to the 'init' function in the shared library. So, I fixed the unresolved symbols, now application loads successfully. But it seems that some variables remained uninitialized -- when I call a function from the shared lib, which allocates memory, and calls malloc() for that, I got a message from libc (the minicmd is my OS/2 application):
minicmd | mmap(): mmap, fd: 0, flags: 34
and then from 'loader' server:
loader | os2app,#17: Not allowed to perform any I/O
Regarding the loader message, it seems that the app accessed a random region in an I/O memory because of uninitialized variables. But why mmap to fd: 0, I cannot say. fd=0 is stdin, but I know that malloc accesses the heap but why it uses a memory-mapped files I yet don't know. So, some troubles are still there, but I hope I'll work it out
(Note: os2app is the same app as minicmd.exe, I just chagned the log tag, but 'loader' server uses an old one) Still cannot say any more details, will investigate with a debugger
On Tue Oct 11, 2011 at 18:15:57 +1300, Valery V. Sedletski wrote:
On Mon, 10 Oct 2011 11:19:17 +0200, Adam Lackorzynski wrote:
But l4rm must be a single instance in a single application, so I need to use an l4rm instance from my application, not in a shared lib... So, I need somehow to call my application region mapper from the shared lib... But I cannot use the ldso for linkage. So I need to make the linkage manually... I see only one solution: to pass the needed l4rm function pointers to the shared lib 'init' function. But maybe, the better solution exists? Any ideas?
Sounds hacky but I cannot provide an alternative. I think you lost me a bit wrt your current setup, so if your solution works for you I'm happy.
Yes, it almost works now -- I made the pointers to l4rm functions and some other ones, passed to the 'init' function in the shared library. So, I fixed the unresolved symbols, now application loads successfully. But it seems that some variables remained uninitialized -- when I call a function from the shared lib, which allocates memory, and calls malloc() for that, I got a message from libc (the minicmd is my OS/2 application):
minicmd | mmap(): mmap, fd: 0, flags: 34
and then from 'loader' server:
loader | os2app,#17: Not allowed to perform any I/O
Regarding the loader message, it seems that the app accessed a random region in an I/O memory because of uninitialized variables. But why mmap to fd: 0, I cannot say. fd=0 is stdin, but I know that malloc accesses the heap but why it uses a memory-mapped files I yet don't know. So, some troubles are still there, but I hope I'll work it out
The flags indicates that anonymous memory is wanted, to the fd does not play any role.
(Note: os2app is the same app as minicmd.exe, I just chagned the log tag, but 'loader' server uses an old one) Still cannot say any more details, will investigate with a debugger
Adam
On Thu, 13 Oct 2011 00:03:54 +0200, Adam Lackorzynski wrote:
minicmd | mmap(): mmap, fd: 0, flags: 34
and then from 'loader' server:
loader | os2app,#17: Not allowed to perform any I/O
Regarding the loader message, it seems that the app accessed a random region in an I/O memory because of uninitialized variables. But why mmap to fd: 0, I cannot say. fd=0 is stdin, but I know that malloc accesses the heap but why it uses a memory-mapped files I yet don't know. So, some troubles are still there, but I hope I'll work it out
The flags indicates that anonymous memory is wanted, to the fd does not play any role.
Thanks for the note! Yes, now I made it working. It really calls mmap() when I am calling malloc(). With malloc(), the pointer to l4env_get_default_dsm() was uninitialized. I fixed that and now it works.
But another strange problem. I had the function which used the 'segments' feature. Now I moved that function from my application to the shared library -- just copied it as is. -- And got an error when trying to compile it:
/mnt/data/src/l4env/l4/pkg/os3/pkg/lib/kal/start.c: In function 'trampoline': /mnt/data/src/l4env/obj/include/x86/l4v2/l4/sys/segment.h:24:3: error: can't find a register in class 'BREG' while reloading 'asm' /mnt/data/src/l4env/obj/include/x86/l4/sys/segment.h:76:3: error: can't find a register in class 'BREG' while reloading 'asm' /mnt/data/src/l4env/obj/include/x86/l4v2/l4/sys/syscalls-l42-gcc3-pic.h:45:3: error: 'asm' operand has impossible constraints /mnt/data/src/l4env/obj/include/x86/l4v2/l4/sys/segment.h:24:3: error: 'asm' operand has impossible constraints /mnt/data/src/l4env/obj/include/x86/l4/sys/segment.h:76:3: error: 'asm' operand has impossible constraints /mnt/data/src/l4env/l4/pkg/os3/pkg/lib/kal/start.c:204:3: error: 'asm' operand has impossible constraints make[1]: *** [start.s.o] Error 1 make[1]: Leaving directory `/mnt/data/src/scratchbox/users/valerius/home/valerius/l4env/obj/pkg/os3/pkg/lib/kal/OBJ-x86_586-l4v2' make: *** [/mnt/data/src/l4env/obj/pkg/os3/pkg/lib/kal/OBJ-x86_586-l4v2] Error 2
the code fragment that causes the error is
/* L4 includes */ #include <l4/sys/segment.h> #include <l4/dm_mem/dm_mem.h> #include <l4/dm_generic/consts.h> #include <l4/events/events.h> #include <l4/generic_ts/generic_ts.h> #include <l4/env/env.h> #include <l4/env/errno.h> #include <l4/log/l4log.h> #include <l4/util/rdtsc.h> #include <l4/l4rm/l4rm.h> /* OS/2 server internal includes */ #include <l4/os3/gcc_os2def.h> #include <l4/os3/ixfmgr.h> #include <l4/os3/processmgr.h> #include <l4/os3/dl.h> /* OS/2 server RPC call includes */ #include <l4/os2srv/os2server-client.h> /* exec server RPC call includes */ #include <l4/execsrv/os2exec-client.h> /* DICE includes */ #include <dice/dice.h> /* local includes*/ #include <stacksw.h>
<...skipped...>
* GDT/LDT descriptor structure */ struct desc { short limit_lo :16; short base_lo1 :16; short base_lo2 :8; short acc_lo :8; short limit_hi :4; short acc_hi :4; short base_hi :8; };
<...skipped...> task = l4_myself(); <...skipped...>
/* Prepare TIB GDT descriptor */ desc.limit_lo = 0x30; desc.limit_hi = 0; desc.acc_lo = 0xF3; desc.acc_hi = 0; desc.base_lo1 = base & 0xffff; desc.base_lo2 = (base >> 16) & 0xff; desc.base_hi = base >> 24;
/* Allocate a GDT descriptor */ fiasco_gdt_set(&desc, sizeof(struct desc), 0, task);
/* Get a selector */ sel = (sizeof(struct desc)) * fiasco_gdt_get_entry_offset();
-- When I comment out the last two lines with fiasco_gdt_set(); and fiasco_get_entry_offset(), the error disappears. These two functions are in <l4/sys/segment.h>. But what can cause such an error? It complains about two assembly language inline functions, which are ok. -- I used it as is in my app and just moved it in unmodified state to the library -- only paths to source files are changed. Maybe, anyone encountered such an error before?
On Thu Oct 13, 2011 at 21:46:34 +1300, Valery V. Sedletski wrote:
On Thu, 13 Oct 2011 00:03:54 +0200, Adam Lackorzynski wrote:
minicmd | mmap(): mmap, fd: 0, flags: 34
and then from 'loader' server:
loader | os2app,#17: Not allowed to perform any I/O
Regarding the loader message, it seems that the app accessed a random region in an I/O memory because of uninitialized variables. But why mmap to fd: 0, I cannot say. fd=0 is stdin, but I know that malloc accesses the heap but why it uses a memory-mapped files I yet don't know. So, some troubles are still there, but I hope I'll work it out
The flags indicates that anonymous memory is wanted, to the fd does not play any role.
Thanks for the note! Yes, now I made it working. It really calls mmap() when I am calling malloc(). With malloc(), the pointer to l4env_get_default_dsm() was uninitialized. I fixed that and now it works.
Ok.
But another strange problem. I had the function which used the 'segments' feature. Now I moved that function from my application to the shared library -- just copied it as is. -- And got an error when trying to compile it:
/mnt/data/src/l4env/l4/pkg/os3/pkg/lib/kal/start.c: In function 'trampoline': /mnt/data/src/l4env/obj/include/x86/l4v2/l4/sys/segment.h:24:3: error: can't find a register in class 'BREG' while reloading 'asm'
-- When I comment out the last two lines with fiasco_gdt_set(); and fiasco_get_entry_offset(), the error disappears. These two functions are in <l4/sys/segment.h>. But what can cause such an error? It complains about two assembly language inline functions, which are ok. -- I used it as is in my app and just moved it in unmodified state to the library -- only paths to source files are changed. Maybe, anyone encountered such an error before?
The inline asm uses ebx which you cannot do in pic code. I think you need to fix the asm, like push/pop ebx to/from stack or similar.
Adam
l4-hackers@os.inf.tu-dresden.de