flat assembler
Message board for the users of flat assembler.
Index
> Linux > Improved ELF executable support Goto page 1, 2 Next |
Author |
|
Tomasz Grysztar 14 Sep 2009, 20:07
With the new 1.69.05 release I introduced two small extensions to ELF executable formatter, in order to make a little bit more usable and analogous to the PE formatter fasm offers for Windows.
The first addition is that you can now specify a branding value to mark executable as targeted for specific system. To mark ELF as Linux executable, use directive like: Code: format ELF executable 3 Linux actually ignores this brand value, but it may be important for instance on BSD systems, which are able to emulate Linux syscalls as long as the executable is marked properly. The second addition is the ability to create some special segments. Three new keywords are introduced for this purpose: "interpreter", "dynamic" and "note". By creating the "interpreter" and "dynamic" segments and filling them with appropriate data, you can now make an "import section" for your ELF executable and make it dynamically linked. Here's the example program that imports the addresses for libc function into data fields, which are then used to indirectly call those function (it's quite like the importing mechanism used by default fasm's macros for PE format): Code: format ELF executable entry start include 'elf.inc' segment interpreter readable db '/lib/ld-linux.so.2',0 segment dynamic readable dd DT_NEEDED,_libc-strtab dd DT_STRTAB,strtab dd DT_STRSZ,strsz dd DT_SYMTAB,symtab dd DT_SYMENT,sizeof.Elf32_Sym dd DT_REL,rel dd DT_RELSZ,relsz dd DT_RELENT,sizeof.Elf32_Rel dd DT_HASH,hash dd DT_NULL,0 segment readable writeable symtab: Elf32_Sym ; 0 - NULL Elf32_Sym _printf-strtab,0,0,STB_GLOBAL,STT_FUNC,0,0 ; 1 - printf Elf32_Sym _exit-strtab,0,0,STB_GLOBAL,STT_FUNC,0,0 ; 2 - exit strtab: _null db 0 _libc db 'libc.so.6',0 _printf db 'printf',0 _exit db 'exit',0 strsz = $-strtab rel: Elf32_Rel printf,1,R_386_32 Elf32_Rel exit,2,R_386_32 relsz = $-rel hash: dd 1,3 ; size of bucket and size of chain dd 0 ; fake bucket, just one hash value times 3 dd % ; chain for all symbol table entries segment readable executable start: push msg call [printf] call [exit] segment readable writeable printf dd 0 exit dd 0 msg db 'Hello world!',0xA,0 Second example does the same, but this time it creates the "jump gates" for the imported functions - the similar mechanism that is used by some linkers: Code: format ELF executable entry start include 'elf.inc' segment interpreter readable db '/lib/ld-linux.so.2',0 segment dynamic readable dd DT_NEEDED,_libc-strtab dd DT_STRTAB,strtab dd DT_STRSZ,strsz dd DT_SYMTAB,symtab dd DT_SYMENT,sizeof.Elf32_Sym dd DT_REL,rel dd DT_RELSZ,relsz dd DT_RELENT,sizeof.Elf32_Rel dd DT_HASH,hash dd DT_NULL,0 segment readable writeable symtab: Elf32_Sym ; 0 - NULL Elf32_Sym _printf-strtab,0,0,STB_GLOBAL,STT_FUNC,0,0 ; 1 - printf Elf32_Sym _exit-strtab,0,0,STB_GLOBAL,STT_FUNC,0,0 ; 2 - exit strtab: _null db 0 _libc db 'libc.so.6',0 _printf db 'printf',0 _exit db 'exit',0 strsz = $-strtab rel: Elf32_Rel _imp_printf,1,R_386_PC32 Elf32_Rel _imp_exit,2,R_386_PC32 relsz = $-rel hash: dd 1,3 ; size of bucket and size of chain dd 0 ; fake bucket, just one hash value times 3 dd % ; chain for all symbol table entries segment readable writeable executable start: push msg call printf call exit printf: jmp near _imp_printf label _imp_printf at $-4 exit: jmp near _imp_exit label _imp_exit at $-4 segment readable writeable msg db 'Hello world!',0xA,0 Of course this all can be made automatically, just some nice and easy to use macros have to be designed, and we can start to make some standard headers for Linux programming in fasm. PS. You need ELF.INC to assemble the above samples, you can find the complete set of sources in the attachment. PPS. My credits and thanks go to nocona, who made some dynamically linked ELF executables from scratch, and whose research became an inspiration to go into this direction.
Last edited by Tomasz Grysztar on 14 Sep 2009, 20:48; edited 1 time in total |
|||||||||||
14 Sep 2009, 20:07 |
|
Fanael 14 Sep 2009, 20:46
"nocode"? Not "nocona"?
|
|||
14 Sep 2009, 20:46 |
|
Tomasz Grysztar 14 Sep 2009, 20:49
Sorry, a typo.
|
|||
14 Sep 2009, 20:49 |
|
Tomasz Grysztar 15 Sep 2009, 17:38
32-bit example simplified with macros:
Code: format ELF executable entry start include 'import32.inc' include 'proc32.inc' interpreter '/lib/ld-linux.so.2' needed 'libc.so.6' import printf,exit segment readable executable start: cinvoke printf,msg cinvoke exit segment readable writeable msg db 'Hello world!',0xA,0 Note that proc32.inc has simply been copied from the Win32 includes (this cannot be done with proc64.inc, because calling convention in 64-bit Linux is way different from the one from Win64). The complete set of sources in attachment.
|
|||||||||||
15 Sep 2009, 17:38 |
|
nocona 27 Sep 2009, 16:35
thanx .
|
|||
27 Sep 2009, 16:35 |
|
kohlrak 08 Oct 2009, 03:44
Perhaps some of the code i posted in the macros section could be used for proc64. I've pretty much left linux development at this point, but i'm sure some one could clean them up a little and make them a little more stable and usable.
Anyway, thanks thomasz, lack of linux support has been one of the detering factors of me promoting people to attempt asm on linux, now that everything's getting cleaner, soon i may be able to convince people to give it a shot. |
|||
08 Oct 2009, 03:44 |
|
gunblade 15 Oct 2009, 20:18
Just wanted to add my thanks for adding these features..
I didnt like having to use ld for linking the ELF objects into an executable, especially when developing on machines without a gcc/binutils toolchain (the HD's too small ). |
|||
15 Oct 2009, 20:18 |
|
Rahsennor 09 Nov 2009, 02:12
I'd almost given up on fasm Linux coding. Thank you!
Uh-huh, I should visit the forum more often... |
|||
09 Nov 2009, 02:12 |
|
madmatt 01 Feb 2010, 20:57
A bit late, but hopefully someone can help me out here. How would I define multiple import libraries?
Example: interpreter "/lib64/ld-linux-x86-64.so.2", "/lib64/libgtk-x11-2.0.so.0" Using this gives me an error. |
|||
01 Feb 2010, 20:57 |
|
LocoDelAssembly 01 Feb 2010, 21:57
madmatt, interpreter is to set the dynamic linker. You have to use "needed" for that.
|
|||
01 Feb 2010, 21:57 |
|
madmatt 02 Feb 2010, 00:59
LocoDelAssembly wrote: madmatt, interpreter is to set the dynamic linker. You have to use "needed" for that. All right, thanks. Until I get a decent linux programming book, I'll be shooting in the dark for a while. _________________ Gimme a sledge hammer! I'LL FIX IT! |
|||
02 Feb 2010, 00:59 |
|
d.j.peters 07 Aug 2010, 06:12
hello,
first sorry about my bad english i use FASM as an backend for an neuron simulator and i create executable binarys for linux and windows (currently under win32) my tests works great so far on lin x86 and win 32 but now i need dynamic libs on linux too the 'hand coded' libc.so.6 example works great for my needs but i need help from you to expand the example for using two *.so libs. the sencond lib is named "libother.so" and the exported function is "other" the first lib are "libc.so.6" the second is "libother.so" so i will call "printf", "other", and "exit" how must i cahnge the working example to use dynamical 2 libs ? thank you so mutch DJ see for "<--" Code: format ELF executable entry start include 'elf.inc' segment interpreter readable db '/lib/ld-linux.so.2',0 segment dynamic readable ; how to expand this block for two dynamic libs ? ; the second lib are ' libother.so' ??? dd DT_NEEDED,_libc-strtab dd DT_STRTAB,strtab dd DT_STRSZ, strsz dd DT_SYMTAB,symtab dd DT_SYMENT,sizeof.Elf32_Sym dd DT_REL, rel dd DT_RELSZ, relsz dd DT_RELENT,sizeof.Elf32_Rel dd DT_HASH, hash dd DT_NULL, 0 segment readable writeable symtab: Elf32_Sym ; 0 - NULL Elf32_Sym _printf-strtab,0,0,STB_GLOBAL,STT_FUNC,0,0 ; 1 - printf Elf32_Sym _exit-strtab ,0,0,STB_GLOBAL,STT_FUNC,0,0 ; 2 - exit ; is this the right place ? Elf32_Sym _other-strtab ,0,0,STB_GLOBAL,STT_FUNC,0,0 ; 3 - other <-- strtab: _null db 0 _libc db 'libc.so.6',0 _printf db 'printf',0 _exit db 'exit',0 _libother db 'libother.so',0 ; <-- _other db 'other',0 ; <-- strsz = $-strtab rel: Elf32_Rel printf,1,R_386_32 Elf32_Rel exit ,2,R_386_32 Elf32_Rel other ,3,R_386_32 ; <-- relsz = $-rel hash: dd 1,3 ; must i change 3 to 4 ? <--- dd 0 ; fake bucket, just one hash value times 3 dd % ; mus i change this from 3 to 4 ? <-- segment readable executable start: push msg call [printf] add esp,4 ; <-- call [other] ; <-- here i call a function named 'other' from lib 'libother.so' call [exit] segment readable writeable printf dd 0 exit dd 0 other dd 0 ; <-- msg db 'Hello world!',0xA,0 _________________ (sorry about my bad English) |
|||
07 Aug 2010, 06:12 |
|
LocoDelAssembly 07 Aug 2010, 16:43
d.j.peters, using the simplified macros from here(it is in this thread some posts above), doesn't this work?
Code: format ELF executable entry start include 'import32.inc' include 'proc32.inc' interpreter '/lib/ld-linux.so.2' needed 'libc.so.6', 'libother.so' import printf, exit, other segment readable executable start: cinvoke printf, msg cinvoke other cinvoke exit segment readable writeable msg db 'Hello world!',0xA,0 |
|||
07 Aug 2010, 16:43 |
|
LocoDelAssembly 07 Aug 2010, 16:58
Code: dd 1,3 ; must i change 3 to 4 ? <--- BTW, Tomasz I have the same question, this is also done this way in your simplified macros but isn't 3 accounting for nchain? In that case it should be always equal to the number of symbols ^^ |
|||
07 Aug 2010, 16:58 |
|
Tomasz Grysztar 07 Aug 2010, 21:27
LocoDelAssembly wrote: BTW, Tomasz I have the same question, this is also done this way in your simplified macros but isn't 3 accounting for nchain? In that case it should be always equal to the number of symbols ^^ I will correct it before including those examples in the official package (as I plan to do so). |
|||
07 Aug 2010, 21:27 |
|
d.j.peters 08 Aug 2010, 09:35
Hello Tomasz,
first thanks for your really fast responce. Macros are not a part of my neuron "simple" code generator and will never be. The neuronal network pushes only values or pointers on the stack and call's [addresses] imported from *.so libs (and *.dll's). The windows part works so far i saw an hard coded example (without macros) with more than one *.dll. please give only one hard coded linux sample with two shared libs. With this i can expand it for any number of libs and functions. Or exist a way i can see the result of the FASM preprocessor after the macro expansion ? for you it is a work of 5 minutes or may be lesser but for me i must learn how the macros works first and i need hours or days to get a hard coded result from it. thank you really mutch for your help. DJ _________________ (sorry about my bad English) |
|||
08 Aug 2010, 09:35 |
|
LocoDelAssembly 08 Aug 2010, 18:05
In the TOOLS directory you should find PREPSRC.ASM in LIBC subdirectory. Compile, link and use it (see readme file for usage instructions).
In case you have a problem, here is a fragment of the output: Code: ;interpreter '/lib/ld-linux.so.2' segment interpreter readable db '/lib/ld-linux.so.2',0 ;needed 'libc.so.6','libother.so' ; str?0 ;match needed,{define needed@dynamic needed,str?0:'libc.so.6'} ;match,{define needed@dynamic str?0:'libc.so.6'} ;define needed@dynamic str?0:'libc.so.6' ; str?1 ;match needed,str?0:'libc.so.6'{define needed@dynamic needed,str?1:'libother.so'} ;define needed@dynamic str?0:'libc.so.6',str?1:'libother.so' ;match,str?0:'libc.so.6',str?1:'libother.so'{define needed@dynamic str?1:'libother.so'} ;import printf,exit,other ; strtab?2 strsz?3 symtab?4 rel?5 relsz?6 hash?7 segment dynamic readable ;match needed,str?0:'libc.so.6',str?1:'libother.so' ;{irp item,needed \{ match str:library,item \\{ dd DT_NEEDED,str-strtab?2 \\} \}} ;irp item,str?0:'libc.so.6',str?1:'libother.so'{match str:library,item \{ dd DT_NEEDED,str-strtab?2 \}} ;match str:library,str?0:'libc.so.6'{dd DT_NEEDED,str-strtab?2} dd DT_NEEDED,str?0-strtab?2 ;match str:library,str?1:'libother.so'{dd DT_NEEDED,str-strtab?2} dd DT_NEEDED,str?1-strtab?2 dd DT_STRTAB,strtab?2 dd DT_STRSZ,strsz?3 dd DT_SYMTAB,symtab?4 dd DT_SYMENT,sizeof.Elf32_Sym dd DT_REL,rel?5 dd DT_RELSZ,relsz?6 dd DT_RELENT,sizeof.Elf32_Rel dd DT_HASH,hash?7 dd DT_NULL,0 segment readable writeable symtab?4:;Elf32_Sym dd+0 dd+0 dd+0 db(+0)shl 4+(+0) db+0 dw+0 ; fstr?8 ;Elf32_Sym fstr?8-strtab?2,0,0,STB_GLOBAL,STT_FUNC,0,0 dd fstr?8-strtab?2+0 dd 0+0 dd 0+0 db(STB_GLOBAL+0)shl 4+(STT_FUNC+0) db 0+0 dw 0+0 ; fstr?9 ;Elf32_Sym fstr?9-strtab?2,0,0,STB_GLOBAL,STT_FUNC,0,0 dd fstr?9-strtab?2+0 dd 0+0 dd 0+0 db(STB_GLOBAL+0)shl 4+(STT_FUNC+0) db 0+0 dw 0+0 ; fstr?A ;Elf32_Sym fstr?A-strtab?2,0,0,STB_GLOBAL,STT_FUNC,0,0 dd fstr?A-strtab?2+0 dd 0+0 dd 0+0 db(STB_GLOBAL+0)shl 4+(STT_FUNC+0) db 0+0 dw 0+0 rel?5: ; counter?B counter?B=1 ;Elf32_Rel printf,counter?B,R_386_32 dd printf+0 dd(counter?B+0)shl 8+(R_386_32+0) counter?B=counter?B+1 ;Elf32_Rel exit,counter?B,R_386_32 dd exit+0 dd(counter?B+0)shl 8+(R_386_32+0) counter?B=counter?B+1 ;Elf32_Rel other,counter?B,R_386_32 dd other+0 dd(counter?B+0)shl 8+(R_386_32+0) counter?B=counter?B+1 relsz?6=$-rel?5 hash?7: dd 1,3 dd 0 repeat counter?B if %=counter?B dd 0 else dd % end if end repeat strtab?2 db 0 fstr?8 db 'printf',0 fstr?9 db 'exit',0 fstr?A db 'other',0 ;match needed,str?0:'libc.so.6',str?1:'libother.so' ;{irp item,needed \{ match str:library,item \\{ str db library,0 \\} \}} ;irp item,str?0:'libc.so.6',str?1:'libother.so'{match str:library,item \{ str db library,0 \}} ;match str:library,str?0:'libc.so.6'{str db library,0} str?0 db 'libc.so.6',0 ;match str:library,str?1:'libother.so'{str db library,0} str?1 db 'libother.so',0 strsz?3=$-strtab?2 printf dd 0 exit dd 0 other dd 0 segment readable executable start: ;cinvoke printf,msg size@ccall=0 if~msg eq pushd msg size@ccall=size@ccall+4 end if call[printf] |
|||
08 Aug 2010, 18:05 |
|
d.j.peters 09 Aug 2010, 09:57
Hello LocoDelAssembly,
i will do an deeper lock to "PREPSRC.ASM" thank you for the tip. i tryed your example and it works so far but the problem are the same if my neuronal network will add more functions e.g. other2 other3 i don't understand the rule behind the numbering you use 8,9,A for the functions now if i use B for function "other2" and C for function "other3" i can see below B is in use too what is it for a numbering is it hex and i can use any number like C0001 C0002 thank you ? For an auto gnerated *.asm file the example Tomasz Grysztar posted would be the right thing for my needs. It use only 'names' and labels so it is easy for the neuronal network to create a list with diffrent names and labels. But i don't know how to use a second *.so lib with this short example. Do you know how i must change it for a second *.so lib entry ? is a secend DT_NEEDED item the key ? dd DT_NEEDED,_other-strtab ... ... DJ Code: format ELF executable entry start include 'elf.inc' segment interpreter readable db '/lib/ld-linux.so.2',0 segment dynamic readable dd DT_NEEDED,_libc-strtab dd DT_STRTAB,strtab dd DT_STRSZ,strsz dd DT_SYMTAB,symtab dd DT_SYMENT,sizeof.Elf32_Sym dd DT_REL,rel dd DT_RELSZ,relsz dd DT_RELENT,sizeof.Elf32_Rel dd DT_HASH,hash dd DT_NULL,0 segment readable writeable symtab: Elf32_Sym ; 0 - NULL Elf32_Sym _printf-strtab,0,0,STB_GLOBAL,STT_FUNC,0,0 ; 1 - printf Elf32_Sym _exit-strtab,0,0,STB_GLOBAL,STT_FUNC,0,0 ; 2 - exit strtab: _null db 0 _libc db 'libc.so.6',0 _printf db 'printf',0 _exit db 'exit',0 strsz = $-strtab rel: Elf32_Rel printf,1,R_386_32 Elf32_Rel exit,2,R_386_32 relsz = $-rel hash: dd 1,3 ; size of bucket and size of chain dd 0 ; fake bucket, just one hash value times 3 dd % ; chain for all symbol table entries segment readable executable start: push msg call [printf] call [exit] segment readable writeable printf dd 0 exit dd 0 msg db 'Hello world!',0xA,0 _________________ (sorry about my bad English) Last edited by d.j.peters on 06 Jan 2012, 12:35; edited 1 time in total |
|||
09 Aug 2010, 09:57 |
|
d.j.peters 09 Aug 2010, 10:42
Hello LocoDelAssembly, i'm again
after i tried "prepsrc" now i know what are the source of the numbers are. looks like i must use macros to support linux. first time that Windows PE files are simpler to generate without macros as ELF files. DJ _________________ (sorry about my bad English) |
|||
09 Aug 2010, 10:42 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.