flat assembler
Message board for the users of flat assembler.
Index
> Linux > INIT and FINI on shared libraries |
Author |
|
LocoDelAssembly 29 Sep 2006, 03:38
According to http://www.iecc.com/linker/linker10.html shared libraries can have an initializer and a finalizer procedure. http://tldp.org/HOWTO/Program-Library-HOWTO/miscellaneous.html explains how to do it in C and warns that exporting "_init" and "_fini" can lead to unpredicatable results (so doing "public _init" and "public _fini" seems to be not a good idea). I guess that when you use "void __attribute__ ((constructor)) my_init(void);" you are actually setting the INIT pointer to "my_init".
Has FASM a way to set INIT and FINI pointers? If I'm right, INIT and FINI are the DLL_PROCESS_ATTACH and DLL_PROCESS_DETACH equivalents respectivelly, something very useful to have. Regards PS: BTW, has the shared libraries a mechanism like DLL_THREAD_ATTACH and DLL_THREAD_DETACH? |
|||
29 Sep 2006, 03:38 |
|
Tomasz Grysztar 29 Sep 2006, 07:50
The INIT and FINI pointers reside in the dynamic table, which is generated by linker. So the only problem might how to tell the linker to make those entries. Perhaps arafel is right, and placing the functions in the .init and .fini sections is enough. The ELF specification say this about .init section:
ELF specification wrote: This section holds executable instructions that contribute to the process initialization code. So definitely you have to put your function into that section (and perhaps this is what the "__attribute__ ((constructor))" in C does). Whether this will be enough for linker to know that it has to make INIT entry in dynamic table for that function, is left to find out. |
|||
29 Sep 2006, 07:50 |
|
LocoDelAssembly 29 Sep 2006, 14:02
OK, I'll try and post my results
Thanks to both |
|||
29 Sep 2006, 14:02 |
|
LocoDelAssembly 29 Sep 2006, 20:17
Sorry for the late. Now I tried but not complete success
shared-lib.asm: Code: format ELF struc Msg [chars] { common rb 1 .: forward db chars common store byte $ - . at . - 1 } section '.init' executable ; separate section but _init works on .text section anyway public _init _init: push ebx call @f @@: pop ebx sub ebx,rva @b ; @b-rva @b is the GOT address lea ecx, [ebx+ rva initMessage] call printStr pop ebx ret initMessage Msg "The oracle has come to give you the answer", 10 section '.fini' executable public _fini _fini: ; never executed push ebx call @f @@: pop ebx sub ebx,rva @b ; @b-rva @b is the GOT address lea ecx, [ebx+ rva finiMessage] call printStr pop ebx ret finiMessage Msg "The oracle has left the building", 10 section '.text' executable printStr: ; ECX = Pointer to message push ebx xor edx, edx mov eax, 4 mov ebx, 1 mov dl, [ecx-1] int $80 pop ebx ret public getTheMostValuableMessage getTheMostValuableMessage: push ebx call @f @@: pop ebx sub ebx,rva @b ; @b-rva @b is the GOT address lea eax,[ebx+rva message] xor edx, edx mov dl, [eax-1] pop ebx ret message Msg 'Which is the sense of the life? 42', 10 shared-lib-test.asm: Code: format ELF section '.text' executable public _start extrn getTheMostValuableMessage _start: call getTheMostValuableMessage mov ecx,eax mov eax,4 mov ebx,1 int 0x80 mov eax, 1 xor ebx, ebx int $80 shell stript: Code: #!/bin/sh fasm shared-lib.asm fasm shared-lib-test.asm ld -m elf_i386 -shared -o shared-lib.so shared-lib.o ld -m elf_i386 -rpath . -dynamic-linker /lib/ld-linux.so.2 -o shared-lib-test shared-lib-test.o shared-lib.so output: Code: oem@athlon64:~/Desktop/test$ ./makeit flat assembler version 1.67.10 (16384 kilobytes memory) 4 passes, 885 bytes. flat assembler version 1.67.10 (16384 kilobytes memory) 1 passes, 412 bytes. oem@athlon64:~/Desktop/test$ ./shared-lib-test The oracle has come to give you the answer Which is the sense of the life? 42 oem@athlon64:~/Desktop/test$ readelf -d shared-lib.so Dynamic section at offset 0x2b8 contains 13 entries: Tag Type Name/Value 0x0000000c (INIT) 0x1e0 0x0000000d (FINI) 0x27c 0x00000004 (HASH) 0x94 0x00000005 (STRTAB) 0x170 0x00000006 (SYMTAB) 0xd0 0x0000000a (STRSZ) 63 (bytes) 0x0000000b (SYMENT) 16 (bytes) 0x00000011 (REL) 0x1b0 0x00000012 (RELSZ) 48 (bytes) 0x00000013 (RELENT) 8 (bytes) 0x00000016 (TEXTREL) 0x0 0x6ffffffa (RELCOUNT) 6 0x00000000 (NULL) 0x0 oem@athlon64:~/Desktop/test$ readelf -d shared-lib-test Dynamic section at offset 0x1e8 contains 13 entries: Tag Type Name/Value 0x00000001 (NEEDED) Shared library: [shared-lib.so] 0x0000000f (RPATH) Library rpath: [.] 0x00000004 (HASH) 0x80480e8 0x00000005 (STRTAB) 0x8048160 0x00000006 (SYMTAB) 0x8048110 0x0000000a (STRSZ) 67 (bytes) 0x0000000b (SYMENT) 16 (bytes) 0x00000015 (DEBUG) 0x0 0x00000003 (PLTGOT) 0x8049278 0x00000002 (PLTRELSZ) 8 (bytes) 0x00000014 (PLTREL) REL 0x00000017 (JMPREL) 0x80481a4 0x00000000 (NULL) 0x0 INIT gets executed but FINI no |
|||
29 Sep 2006, 20:17 |
|
arafel 29 Sep 2006, 21:59
Try linking with "-fini _fini" switch. Maybe ld fails to automatically locate the _fini entry point.
|
|||
29 Sep 2006, 21:59 |
|
LocoDelAssembly 29 Sep 2006, 23:48
Tried "ld -m elf_i386 -fini _fini -shared -o shared-lib.so shared-lib.o" and since it doesn't work I tried "ld -m elf_i386 -rpath . -dynamic-linker /lib/ld-linux.so.2 -o shared-lib-test shared-lib-test.o shared-lib.so -fini _fini" too and then both at the same time but always the same effect, the message "The oracle has left the building" never appears
|
|||
29 Sep 2006, 23:48 |
|
arafel 30 Sep 2006, 01:55
hmmm. dunno then.
|
|||
30 Sep 2006, 01:55 |
|
arafel 30 Sep 2006, 02:03
Ok, I googled a bit about this issue and here is something interesting:
Quote:
If I not mistaked _exit() is basically a wrapped sys_exit(), so this might be a reason why _finit() is not called. |
|||
30 Sep 2006, 02:03 |
|
LocoDelAssembly 30 Sep 2006, 02:20
UPDATE
Works using GCC (and using main instead of _start). But note that it works when I replace the "ExitProcess" system call with a RET (something that doesn't work without gcc). So the problem here is that I'm leaving the system too fast to give shared-lib.so->fini an oportunity to execute. Seems that I need to terminate the process in other way, do anyone know how? [edit] Sorry, apparently I spend too much time writing this and you replied when I was writing Well, is confirmed then, the question now is how to do this without relying on libc (with gcc you implicity rely on it)[/edit] |
|||
30 Sep 2006, 02:20 |
|
LocoDelAssembly 08 Oct 2006, 02:27
Today I tried using "ccall exit, 0" and "ccall _exit, 0" (and linking against libc.so.6), but same problem, seems that using exit which is supposed to terminate normally and calling the exit procedures ( see http://www.borgnet.us/cgi-bin/man2web?program=exit§ion=3 ), my _fini functions isn't get excecuted
Seems that I'll always rely on gcc to get it work |
|||
08 Oct 2006, 02:27 |
|
revolution 20 Feb 2019, 10:02
For simple programs with one dependency, like the example above, it is sufficient to scan the ELF header and call the FINI function manually. But as the dependencies get more complex the interactions become tricky and the order of FINI calls needs to be done correctly. Looking at the C code that does this, there are a lot of things happening in there. So most likely it would be necessary to reproduce the FINI call order to be sure that everything is closed properly.
But if you know your libraries well and know that the FINI call order isn't important to them, then I'd guess it would be okay to just call each FINI as it is found. Another option is to simply call EXIT_GROUP and forget about all the complexity |
|||
20 Feb 2019, 10:02 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.