flat assembler
Message board for the users of flat assembler.
Index
> Linux > elf executable with dynamic linker... from scratch Goto page 1, 2 Next |
Author |
|
MichaelH 13 Aug 2007, 00:03
Thankyou, much appreciated!
|
|||
13 Aug 2007, 00:03 |
|
vid 13 Aug 2007, 00:50
very nice, could you please rename this to "ELF with dynamic linking from scratch", or something with "from scratch"? That is how we use to call this kind of stuff here.
Then, i will link this thread from list of interesting threads. thank you |
|||
13 Aug 2007, 00:50 |
|
LocoDelAssembly 13 Aug 2007, 15:59
The hash table is supposed to be mandatory for both executable and shared objects according to the ELF spec (Note that I read the ELF 32 bit spec). However, you can always make a hash table of just one bucket so you don't have to bother about hashing properly.
|
|||
13 Aug 2007, 15:59 |
|
nocona 18 Aug 2007, 04:10
Quote:
according to the spec... but this is the proof that it's not always the case . |
|||
18 Aug 2007, 04:10 |
|
nocona 18 Aug 2007, 04:27
Quote:
done |
|||
18 Aug 2007, 04:27 |
|
LocoDelAssembly 18 Aug 2007, 14:14
Quote:
This is the proof that some OSes don't care about it And yes, it is somewhat stupid having a hash table on an executable. Who will reference our symbols after all? Even more, which symbols are we exporting?? Still, the spec says that DT_HASH is a mandatory dynamic tag on both executable and shared objects... BTW, last time I forgot to comment about your code, it is very nice!! Thanks for sharing |
|||
18 Aug 2007, 14:14 |
|
snify 09 Sep 2007, 15:39
can you please add more examples for linux "from scratch", maybe elf32 with gtk (THAT WILL BE AWESOME!)
|
|||
09 Sep 2007, 15:39 |
|
nocona 22 Sep 2007, 03:43
Quote:
Sure. 2 examples of gtk+-2.0. Very basic gtk+ program. 32-bit and 64-bit examples are shown below. But this time I wrapped some repeated coding into macros.. Code: use32 BASE=BASE32 ENTRYPOINT=start ELF_TYPE=ET_EXEC ELF_PHEADER_ENTRY_SIZE=ELF_PHEADER_ENTRY_SIZE32 SYMENT_SIZE=SYMENT_SIZE32 RELOCENT_SIZE=RELOCENT_SIZE32 CLASS=ELF_CLASS32 MACHINE=EM_386 program_header_entry fix program_header_entry32 symbol fix symbol32 reloc fix reloc32 addr fix addr32 offs fix offs32 interpreter fix interpreter32 ;ELF32 BASE32=0x8048000 ELF_PHEADER_ENTRY_SIZE32 = 32 SYMENT_SIZE32=16 RELOCENT_SIZE32=8 ;ELF64 BASE64=0x400000 ELF_PHEADER_ENTRY_SIZE64 = 56 SYMENT_SIZE64=24 RELOCENT_SIZE64=24 ;ELF constants ELF_CLASS32=1 ELF_CLASS64=2 ET_EXEC=2 ET_DYN=3 EM_386=3 EM_X86_64=62 DT_NEEDED=1 DT_STRTAB=5 DT_SYMTAB=6 DT_STRSZ=10 DT_SYMENT=11 DT_REL=17 DT_RELSZ=18 DT_RELENT=19 DT_RELA=7 DT_RELASZ=8 DT_RELAENT=9 PT_INTERP=3 PT_DYNAMIC=2 PT_LOAD=1 R_386_32=1 R_X86_64_64=1 STB_GLOBAL=1 STT_FUNCTION=2 read=4 write=2 execute=1 xo=1 wo=2 wx=3 ro=4 rx=5 ;rw=6 rwx=7 ;end ELF constants define interpreter64 "/lib/ld-linux-x86-64.so.2" define interpreter32 "/lib/ld-linux.so.2" macro program_header {label program_header} macro program_header_entry32 type, location, access, align, size, memsize { dd type dd OFFSETOF location, location, 0 if type <> PT_LOAD dd location#.SIZE, location#.MEMSIZE else dd size, memsize end if dd access, align } macro end_program_header { .SIZE=$-program_header .MEMSIZE=.SIZE } macro program_header_entry64 type, location, access, align, size, memsize { dd type, access dq OFFSETOF location, location, 0 if type <> PT_LOAD dq location#.SIZE, location#.MEMSIZE else dq size, memsize end if dq align } macro symbol_table {label symbol_table} macro end_symbol_table { .SIZE=$-symbol_table .MEMSIZE=.SIZE } macro symbol32 name, str, bind, type { name = ($-symbol_table)/SYMENT_SIZE if str eq times 16 db 0 else dd str, 0, 0 db bind shl 4 + 2, 0 dw 0 end if } macro symbol64 name, str, bind, type { name = ($-symbol_table)/SYMENT_SIZE if str eq times 24 db 0 else dd str db bind shl 4 + 2, 0 dw 0 dq 0, 0 end if } macro reloc_table {label reloc_table} macro end_reloc_table { .SIZE=$-reloc_table .MEMSIZE=.SIZE restore reloc_table } macro reloc32 label, symbol, type {dd label, symbol shl 8 + type} macro reloc64 label, symbol, type {dq label, symbol shl 32 + type, 0} macro string_table {label string_table} macro string name, str { name=$-string_table if str eq db 0 else db str, 0 end if } macro end_string_table { .SIZE=$-string_table .MEMSIZE=.SIZE } macro addr32 [value] {dd value} struc addr32 [value] {. dd value} macro offs32 [value] {dd value} struc offs32 [value] {. dd value} macro addr64 [value] {dq value} struc addr64 [value] {. dq value} macro offs64 [value] {dq value} struc offs64 [value] {. dq value} OFFSETOF equ -BASE+ org BASE Elf_EHdr: db 0x7F, "ELF", CLASS, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; dw ELF_TYPE dw MACHINE dd 1 addr ENTRYPOINT ;entrypoint offs OFFSETOF program_header offs 0 dd 0 dw Elf_EHdr.SIZE dw ELF_PHEADER_ENTRY_SIZE dw program_header.SIZE/ELF_PHEADER_ENTRY_SIZE dw 0, 0, 0 .SIZE=$-Elf_EHdr program_header program_header_entry PT_INTERP, _interpreter_name_, ro, 1 program_header_entry PT_DYNAMIC, _dynamic_, ro, 4 program_header_entry PT_LOAD, Elf_EHdr, rwx, 0x1000, FILE.SIZE, FILE.SIZE end_program_header align 4 _dynamic_ : addr DT_NEEDED, strtab@libc addr DT_NEEDED, strtab@gtkx11 addr DT_NEEDED, strtab@gobject addr DT_STRTAB, string_table addr DT_SYMTAB, symbol_table addr DT_STRSZ, string_table.SIZE addr DT_SYMENT, SYMENT_SIZE addr DT_REL, reloc_table addr DT_RELSZ, reloc_table.SIZE addr DT_RELENT, RELOCENT_SIZE addr 0, 0 ;terminator .SIZE=$-_dynamic_ .MEMSIZE=.SIZE string_table string strtab@null string strtab@libc, "libc.so.6" string strtab@printf, "printf" string strtab@gtk_init_check, "gtk_init_check" string strtab@gtk_window_new, "gtk_window_new" string strtab@gtk_widget_show, "gtk_widget_show" string strtab@gtk_main, "gtk_main" string strtab@gtkx11, "libgtk-x11-2.0.so.0" string strtab@exit, "exit" string strtab@gtk_main_quit, "gtk_main_quit" string strtab@g_signal_connect_data, "g_signal_connect_data" string strtab@gobject, "libgobject-2.0.so.0" string strtab@gtk_window_set_title, "gtk_window_set_title" end_string_table align 8 symbol_table symbol symtab@null symbol symtab@printf, strtab@printf, STB_GLOBAL, STT_FUNCTION symbol symtab@gtk_init_check, strtab@gtk_init_check, STB_GLOBAL, STT_FUNCTION symbol symtab@gtk_window_new, strtab@gtk_window_new, STB_GLOBAL, STT_FUNCTION symbol symtab@gtk_widget_show, strtab@gtk_widget_show, STB_GLOBAL, STT_FUNCTION symbol symtab@gtk_main, strtab@gtk_main, STB_GLOBAL, STT_FUNCTION symbol symtab@exit, strtab@exit, STB_GLOBAL, STT_FUNCTION symbol symtab@gtk_main_quit, strtab@gtk_main_quit, STB_GLOBAL, STT_FUNCTION symbol symtab@g_signal_connect_data, strtab@g_signal_connect_data, STB_GLOBAL, STT_FUNCTION symbol symtab@gtk_window_set_title, strtab@gtk_window_set_title, STB_GLOBAL, STT_FUNCTION end_symbol_table align 8 reloc_table reloc _printf_, symtab@printf, R_386_32 reloc _gtk_init_check_, symtab@gtk_init_check, R_386_32 reloc _gtk_window_new_, symtab@gtk_window_new, R_386_32 reloc _gtk_widget_show_, symtab@gtk_widget_show, R_386_32 reloc _gtk_main_, symtab@gtk_main, R_386_32 reloc _exit_, symtab@exit, R_386_32 reloc _gtk_main_quit_, symtab@gtk_main_quit, R_386_32 reloc _g_signal_connect_data_, symtab@g_signal_connect_data, R_386_32 reloc _gtk_window_set_title_, symtab@gtk_window_set_title, R_386_32 end_reloc_table _interpreter_name_ db interpreter, 0 .SIZE=$-_interpreter_name_ .MEMSIZE=.SIZE start: lea eax, [esp] lea ecx, [esp+4] push ecx lea ecx, [esp] push ecx eax call [_gtk_init_check_] add esp, 8+4 test eax, eax jz _error_init_gtk push 0 call [_gtk_window_new_] pop ecx mov ebx, eax xor eax, eax push eax eax eax destroy_handler signame_destroy ebx call [_g_signal_connect_data_] add esp, 24 push app_title ebx call [_gtk_window_set_title_] add esp, 8 push ebx call [_gtk_widget_show_] pop ecx call [_gtk_main_] jmp _exit _error_init_gtk: xor eax, eax push msg_error_gtk_init_fail call [_printf_] pop eax _exit: xor eax, eax push eax call [_exit_] destroy_handler: call [_gtk_main_quit_] ret msg_error_gtk_init_fail db "GTK+ Initialization fails!", 10, 0 app_title db "GTK+ from scratch", 0 signame_destroy db "destroy", 0 align 4 _printf_ addr ? _gtk_init_check_ addr ? _gtk_window_new_ addr ? _gtk_widget_show_ addr ? _gtk_main_ addr ? _gtk_main_quit_ addr ? _g_signal_connect_data_ addr ? _gtk_window_set_title_ addr ? _exit_ addr ? FILE.SIZE=$-BASE 64-bit : Code: use64 BASE=BASE64 ENTRYPOINT=start ELF_TYPE=ET_EXEC ELF_PHEADER_ENTRY_SIZE=ELF_PHEADER_ENTRY_SIZE64 SYMENT_SIZE=SYMENT_SIZE64 RELOCENT_SIZE=RELOCENT_SIZE64 CLASS=ELF_CLASS64 MACHINE=EM_X86_64 program_header_entry fix program_header_entry64 symbol fix symbol64 reloc fix reloc64 addr fix addr64 offs fix offs64 interpreter fix interpreter64 ;ELF32 BASE32=0x8048000 ELF_PHEADER_ENTRY_SIZE32 = 32 SYMENT_SIZE32=16 RELOCENT_SIZE32=8 ;ELF64 BASE64=0x400000 ELF_PHEADER_ENTRY_SIZE64 = 56 SYMENT_SIZE64=24 RELOCENT_SIZE64=24 ;ELF constants ELF_CLASS32=1 ELF_CLASS64=2 ET_EXEC=2 ET_DYN=3 EM_386=3 EM_X86_64=62 DT_NEEDED=1 DT_STRTAB=5 DT_SYMTAB=6 DT_STRSZ=10 DT_SYMENT=11 DT_REL=17 DT_RELSZ=18 DT_RELENT=19 DT_RELA=7 DT_RELASZ=8 DT_RELAENT=9 PT_INTERP=3 PT_DYNAMIC=2 PT_LOAD=1 R_386_32=1 R_X86_64_64=1 STB_GLOBAL=1 STT_FUNCTION=2 read=4 write=2 execute=1 xo=1 wo=2 wx=3 ro=4 rx=5 ;rw=6 rwx=7 ;end ELF constants define interpreter64 "/lib/ld-linux-x86-64.so.2" define interpreter32 "/lib/ld-linux.so.2" macro program_header {label program_header} macro program_header_entry32 type, location, access, align, size, memsize { dd type dd OFFSETOF location, location, 0 if type <> PT_LOAD dd location#.SIZE, location#.MEMSIZE else dd size, memsize end if dd access, align } macro end_program_header { .SIZE=$-program_header .MEMSIZE=.SIZE } macro program_header_entry64 type, location, access, align, size, memsize { dd type, access dq OFFSETOF location, location, 0 if type <> PT_LOAD dq location#.SIZE, location#.MEMSIZE else dq size, memsize end if dq align } macro symbol_table {label symbol_table} macro end_symbol_table { .SIZE=$-symbol_table .MEMSIZE=.SIZE } macro symbol32 name, str, bind, type { name = ($-symbol_table)/SYMENT_SIZE if str eq times 16 db 0 else dd str, 0, 0 db bind shl 4 + 2, 0 dw 0 end if } macro symbol64 name, str, bind, type { name = ($-symbol_table)/SYMENT_SIZE if str eq times 24 db 0 else dd str db bind shl 4 + 2, 0 dw 0 dq 0, 0 end if } macro reloc_table {label reloc_table} macro end_reloc_table { .SIZE=$-reloc_table .MEMSIZE=.SIZE restore reloc_table } macro reloc32 label, symbol, type {dd label, symbol shl 8 + type} macro reloc64 label, symbol, type {dq label, symbol shl 32 + type, 0} macro string_table {label string_table} macro string name, str { name=$-string_table if str eq db 0 else db str, 0 end if } macro end_string_table { .SIZE=$-string_table .MEMSIZE=.SIZE } macro addr32 [value] {dd value} struc addr32 [value] {. dd value} macro offs32 [value] {dd value} struc offs32 [value] {. dd value} macro addr64 [value] {dq value} struc addr64 [value] {. dq value} macro offs64 [value] {dq value} struc offs64 [value] {. dq value} OFFSETOF equ -BASE+ org BASE Elf_EHdr: db 0x7F, "ELF", CLASS, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; dw ELF_TYPE dw MACHINE dd 1 addr ENTRYPOINT ;entrypoint offs OFFSETOF program_header offs 0 dd 0 dw Elf_EHdr.SIZE dw ELF_PHEADER_ENTRY_SIZE dw program_header.SIZE/ELF_PHEADER_ENTRY_SIZE dw 0, 0, 0 .SIZE=$-Elf_EHdr program_header program_header_entry PT_INTERP, _interpreter_name_, ro, 1 program_header_entry PT_DYNAMIC, _dynamic_, ro, 4 program_header_entry PT_LOAD, Elf_EHdr, rwx, 0x1000, FILE.SIZE, FILE.SIZE end_program_header align 4 _dynamic_ : addr DT_NEEDED, strtab@libc addr DT_NEEDED, strtab@gtkx11 addr DT_NEEDED, strtab@gobject addr DT_STRTAB, string_table addr DT_SYMTAB, symbol_table addr DT_STRSZ, string_table.SIZE addr DT_SYMENT, SYMENT_SIZE addr DT_RELA, reloc_table addr DT_RELASZ, reloc_table.SIZE addr DT_RELAENT, RELOCENT_SIZE addr 0, 0 ;terminator .SIZE=$-_dynamic_ .MEMSIZE=.SIZE string_table string strtab@null string strtab@libc, "libc.so.6" string strtab@printf, "printf" string strtab@gtk_init_check, "gtk_init_check" string strtab@gtk_window_new, "gtk_window_new" string strtab@gtk_widget_show, "gtk_widget_show" string strtab@gtk_main, "gtk_main" string strtab@gtkx11, "libgtk-x11-2.0.so.0" string strtab@exit, "exit" string strtab@gtk_main_quit, "gtk_main_quit" string strtab@g_signal_connect_data, "g_signal_connect_data" string strtab@gobject, "libgobject-2.0.so.0" string strtab@gtk_window_set_title, "gtk_window_set_title" end_string_table align 8 symbol_table symbol symtab@null symbol symtab@printf, strtab@printf, STB_GLOBAL, STT_FUNCTION symbol symtab@gtk_init_check, strtab@gtk_init_check, STB_GLOBAL, STT_FUNCTION symbol symtab@gtk_window_new, strtab@gtk_window_new, STB_GLOBAL, STT_FUNCTION symbol symtab@gtk_widget_show, strtab@gtk_widget_show, STB_GLOBAL, STT_FUNCTION symbol symtab@gtk_main, strtab@gtk_main, STB_GLOBAL, STT_FUNCTION symbol symtab@exit, strtab@exit, STB_GLOBAL, STT_FUNCTION symbol symtab@gtk_main_quit, strtab@gtk_main_quit, STB_GLOBAL, STT_FUNCTION symbol symtab@g_signal_connect_data, strtab@g_signal_connect_data, STB_GLOBAL, STT_FUNCTION symbol symtab@gtk_window_set_title, strtab@gtk_window_set_title, STB_GLOBAL, STT_FUNCTION end_symbol_table align 8 reloc_table reloc _printf_, symtab@printf, R_X86_64_64 reloc _gtk_init_check_, symtab@gtk_init_check, R_X86_64_64 reloc _gtk_window_new_, symtab@gtk_window_new, R_X86_64_64 reloc _gtk_widget_show_, symtab@gtk_widget_show, R_X86_64_64 reloc _gtk_main_, symtab@gtk_main, R_X86_64_64 reloc _exit_, symtab@exit, R_X86_64_64 reloc _gtk_main_quit_, symtab@gtk_main_quit, R_X86_64_64 reloc _g_signal_connect_data_, symtab@g_signal_connect_data, R_X86_64_64 reloc _gtk_window_set_title_, symtab@gtk_window_set_title, R_X86_64_64 end_reloc_table _interpreter_name_ db interpreter, 0 .SIZE=$-_interpreter_name_ .MEMSIZE=.SIZE start: lea rdi, [rsp] lea rsi, [rsp+8] push rsi lea rsi, [rsp] call [_gtk_init_check_] pop rcx test rax, rax jz _error_init_gtk xor rdi, rdi call [_gtk_window_new_] mov r12, rax mov rdi, r12 mov esi, signame_destroy mov rdx, destroy_handler xor rcx, rcx xor r8, r8 xor r9, r9 call [_g_signal_connect_data_] mov rdi, r12 mov esi, app_title call [_gtk_window_set_title_] mov rdi, r12 call [_gtk_widget_show_] call [_gtk_main_] jmp _exit _error_init_gtk: xor eax, eax mov edi, msg_error_gtk_init_fail call [_printf_] _exit: xor eax, eax call [_exit_] destroy_handler: call [_gtk_main_quit_] ret msg_error_gtk_init_fail db "GTK+ Initialization fails!", 10, 0 app_title db "GTK+ from scratch", 0 signame_destroy db "destroy", 0 align 8 _printf_ addr ? _gtk_init_check_ addr ? _gtk_window_new_ addr ? _gtk_widget_show_ addr ? _gtk_main_ addr ? _gtk_main_quit_ addr ? _g_signal_connect_data_ addr ? _gtk_window_set_title_ addr ? _exit_ addr ? FILE.SIZE=$-BASE |
|||
22 Sep 2007, 03:43 |
|
nocona 22 Sep 2007, 03:47
Also below are codes for dso (64-bit) from scratch. A very simple dso that export 1 symbol - print_hello. I don't know if we can use it as input to gnu ld to link with other HLL objects since it has no section header. But certainly it can be used as dso, I tested it with the executable below. Put hello.so and test_hello in the same dir and execute with LD_LIBRARY_PATH+="." ./test_hello
#fasm hello.asm hello.so Code: use64 BASE=0 ENTRYPOINT=0 ELF_TYPE=ET_DYN ELF_PHEADER_ENTRY_SIZE=ELF_PHEADER_ENTRY_SIZE64 SYMENT_SIZE=SYMENT_SIZE64 RELOCENT_SIZE=RELOCENT_SIZE64 CLASS=ELF_CLASS64 MACHINE=EM_X86_64 program_header_entry fix program_header_entry64 symbol fix symbol64 reloc fix reloc64 addr fix addr64 offs fix offs64 interpreter fix interpreter64 ;ELF32 BASE32=0x8048000 ELF_PHEADER_ENTRY_SIZE32 = 32 SYMENT_SIZE32=16 RELOCENT_SIZE32=8 ;ELF64 BASE64=0x400000 ELF_PHEADER_ENTRY_SIZE64 = 56 SYMENT_SIZE64=24 RELOCENT_SIZE64=24 ;ELF constants ELF_CLASS32=1 ELF_CLASS64=2 ET_EXEC=2 ET_DYN=3 EM_386=3 EM_X86_64=62 DT_NEEDED=1 DT_STRTAB=5 DT_HASH=4 DT_SYMTAB=6 DT_STRSZ=10 DT_SYMENT=11 DT_REL=17 DT_RELSZ=18 DT_RELENT=19 DT_RELA=7 DT_RELASZ=8 DT_RELAENT=9 DT_SONAME=14 PT_INTERP=3 PT_DYNAMIC=2 PT_LOAD=1 R_386_32=1 R_X86_64_64=1 STB_GLOBAL=1 STT_FUNCTION=2 read=4 write=2 execute=1 xo=1 wo=2 wx=3 ro=4 rx=5 ;rw=6 rwx=7 ;end ELF constants define interpreter64 "/lib/ld-linux-x86-64.so.2" define interpreter32 "/lib/ld-linux.so.2" macro program_header {label program_header} macro program_header_entry32 type, location, access, align, size, memsize { dd type dd OFFSETOF location, location, 0 if type <> PT_LOAD dd location#.SIZE, location#.MEMSIZE else dd size, memsize end if dd access, align } macro end_program_header { .SIZE=$-program_header .MEMSIZE=.SIZE } macro program_header_entry64 type, location, access, align, size, memsize { dd type, access dq OFFSETOF location, location, 0 if type <> PT_LOAD dq location#.SIZE, location#.MEMSIZE else dq size, memsize end if dq align } macro symbol_table {label symbol_table} macro end_symbol_table { .SIZE=$-symbol_table .MEMSIZE=.SIZE } macro symbol32 name, str, bind, type { name = ($-symbol_table)/SYMENT_SIZE if str eq times 16 db 0 else dd str, 0, 0 db bind shl 4 + 2, 0 dw 0 end if } macro symbol64 name, str, bind, type, value, size, index { name = ($-symbol_table)/SYMENT_SIZE if str eq times 24 db 0 else dd str db bind shl 4 + 2, 0 dw index+0 dq value+0, size+0 end if } macro reloc_table {label reloc_table} macro end_reloc_table { .SIZE=$-reloc_table .MEMSIZE=.SIZE restore reloc_table } macro reloc32 label, symbol, type {dd label, symbol shl 8 + type} macro reloc64 label, symbol, type {dq label, symbol shl 32 + type, 0} macro string_table {label string_table} macro string name, str { name=$-string_table if str eq db 0 else db str, 0 end if } macro end_string_table { .SIZE=$-string_table .MEMSIZE=.SIZE } macro addr32 [value] {dd value} struc addr32 [value] {. dd value} macro offs32 [value] {dd value} struc offs32 [value] {. dd value} macro addr64 [value] {dq value} struc addr64 [value] {. dq value} macro offs64 [value] {dq value} struc offs64 [value] {. dq value} OFFSETOF equ -BASE+ org BASE Elf_EHdr: db 0x7F, "ELF", CLASS, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; dw ELF_TYPE dw MACHINE dd 1 addr ENTRYPOINT ;entrypoint offs OFFSETOF program_header offs 0 dd 0 dw Elf_EHdr.SIZE dw ELF_PHEADER_ENTRY_SIZE dw program_header.SIZE/ELF_PHEADER_ENTRY_SIZE dw 0, 0, 0 .SIZE=$-Elf_EHdr program_header program_header_entry PT_INTERP, _interpreter_name_, ro, 1 program_header_entry PT_DYNAMIC, _dynamic_, ro, 4 program_header_entry PT_LOAD, Elf_EHdr, rwx, 0x1000, FILE.SIZE, FILE.SIZE end_program_header align 4 _dynamic_ : addr DT_NEEDED, strtab@libc addr DT_SONAME, strtab@soname addr DT_STRTAB, string_table addr DT_HASH, hash_table addr DT_SYMTAB, symbol_table addr DT_STRSZ, string_table.SIZE addr DT_SYMENT, SYMENT_SIZE addr DT_RELA, reloc_table addr DT_RELASZ, reloc_table.SIZE addr DT_RELAENT, RELOCENT_SIZE addr 0, 0 ;terminator .SIZE=$-_dynamic_ .MEMSIZE=.SIZE string_table string strtab@null string strtab@soname, "hello.so" string strtab@libc, "libc.so.6" string strtab@printf, "printf" string strtab@print_hello, "print_hello" end_string_table align 8 symbol_table symbol symtab@null symbol symtab@printf, strtab@printf, STB_GLOBAL, STT_FUNCTION symbol symtab@print_hello, strtab@print_hello, STB_GLOBAL, STT_FUNCTION, print_hello, print_hello.SIZE end_symbol_table align 8 reloc_table reloc _printf_, symtab@printf, R_X86_64_64 end_reloc_table align 4 hash_table: dd 4 dd 3 .bucket: dd 0 dd 0 dd 1 dd 2 .chain: dd 0 dd 0 dd 0 _interpreter_name_ db interpreter, 0 .SIZE=$-_interpreter_name_ .MEMSIZE=.SIZE print_hello: xor eax, eax call @f db "Hello from hello.so::print_hello", 10, 0 @@: pop rdi call [_printf_] ret print_hello.SIZE=$-print_hello align 8 _printf_ addr ? FILE.SIZE=$-BASE #fasm test_hello.asm test_hello && chmod u+x test_hello Code: use64 BASE=BASE64 ENTRYPOINT=start ELF_TYPE=ET_EXEC ELF_PHEADER_ENTRY_SIZE=ELF_PHEADER_ENTRY_SIZE64 SYMENT_SIZE=SYMENT_SIZE64 RELOCENT_SIZE=RELOCENT_SIZE64 CLASS=ELF_CLASS64 MACHINE=EM_X86_64 program_header_entry fix program_header_entry64 symbol fix symbol64 reloc fix reloc64 addr fix addr64 offs fix offs64 interpreter fix interpreter64 ;ELF32 BASE32=0x8048000 ELF_PHEADER_ENTRY_SIZE32 = 32 SYMENT_SIZE32=16 RELOCENT_SIZE32=8 ;ELF64 BASE64=0x400000 ELF_PHEADER_ENTRY_SIZE64 = 56 SYMENT_SIZE64=24 RELOCENT_SIZE64=24 ;ELF constants ELF_CLASS32=1 ELF_CLASS64=2 ET_EXEC=2 ET_DYN=3 EM_386=3 EM_X86_64=62 DT_NEEDED=1 DT_STRTAB=5 DT_SYMTAB=6 DT_STRSZ=10 DT_SYMENT=11 DT_REL=17 DT_RELSZ=18 DT_RELENT=19 DT_RELA=7 DT_RELASZ=8 DT_RELAENT=9 DT_SONAME=14 PT_INTERP=3 PT_DYNAMIC=2 PT_LOAD=1 R_386_32=1 R_X86_64_64=1 STB_GLOBAL=1 STT_FUNCTION=2 read=4 write=2 execute=1 xo=1 wo=2 wx=3 ro=4 rx=5 ;rw=6 rwx=7 ;end ELF constants define interpreter64 "/lib/ld-linux-x86-64.so.2" define interpreter32 "/lib/ld-linux.so.2" macro program_header {label program_header} macro program_header_entry32 type, location, access, align, size, memsize { dd type dd OFFSETOF location, location, 0 if type <> PT_LOAD dd location#.SIZE, location#.MEMSIZE else dd size, memsize end if dd access, align } macro end_program_header { .SIZE=$-program_header .MEMSIZE=.SIZE } macro program_header_entry64 type, location, access, align, size, memsize { dd type, access dq OFFSETOF location, location, 0 if type <> PT_LOAD dq location#.SIZE, location#.MEMSIZE else dq size, memsize end if dq align } macro symbol_table {label symbol_table} macro end_symbol_table { .SIZE=$-symbol_table .MEMSIZE=.SIZE } macro symbol32 name, str, bind, type { name = ($-symbol_table)/SYMENT_SIZE if str eq times 16 db 0 else dd str, 0, 0 db bind shl 4 + 2, 0 dw 0 end if } macro symbol64 name, str, bind, type, value, size, index { name = ($-symbol_table)/SYMENT_SIZE if str eq times 24 db 0 else dd str db bind shl 4 + 2, 0 dw index+0 dq value+0, size+0 end if } macro reloc_table {label reloc_table} macro end_reloc_table { .SIZE=$-reloc_table .MEMSIZE=.SIZE restore reloc_table } macro reloc32 label, symbol, type {dd label, symbol shl 8 + type} macro reloc64 label, symbol, type {dq label, symbol shl 32 + type, 0} macro string_table {label string_table} macro string name, str { name=$-string_table if str eq db 0 else db str, 0 end if } macro end_string_table { .SIZE=$-string_table .MEMSIZE=.SIZE } macro addr32 [value] {dd value} struc addr32 [value] {. dd value} macro offs32 [value] {dd value} struc offs32 [value] {. dd value} macro addr64 [value] {dq value} struc addr64 [value] {. dq value} macro offs64 [value] {dq value} struc offs64 [value] {. dq value} OFFSETOF equ -BASE+ org BASE Elf_EHdr: db 0x7F, "ELF", CLASS, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; dw ELF_TYPE dw MACHINE dd 1 addr ENTRYPOINT ;entrypoint offs OFFSETOF program_header offs 0 dd 0 dw Elf_EHdr.SIZE dw ELF_PHEADER_ENTRY_SIZE dw program_header.SIZE/ELF_PHEADER_ENTRY_SIZE dw 0, 0, 0 .SIZE=$-Elf_EHdr program_header program_header_entry PT_INTERP, _interpreter_name_, ro, 1 program_header_entry PT_DYNAMIC, _dynamic_, ro, 4 program_header_entry PT_LOAD, Elf_EHdr, rwx, 0x1000, FILE.SIZE, FILE.SIZE end_program_header align 4 _dynamic_ : addr DT_NEEDED, strtab@libc addr DT_NEEDED, strtab@libhello addr DT_STRTAB, string_table addr DT_SYMTAB, symbol_table addr DT_STRSZ, string_table.SIZE addr DT_SYMENT, SYMENT_SIZE addr DT_RELA, reloc_table addr DT_RELASZ, reloc_table.SIZE addr DT_RELAENT, RELOCENT_SIZE addr 0, 0 ;terminator .SIZE=$-_dynamic_ .MEMSIZE=.SIZE string_table string strtab@null string strtab@libc, "libc.so.6" string strtab@printf, "printf" string strtab@print_hello, "print_hello" string strtab@libhello, "hello.so" string strtab@exit, "exit" end_string_table align 8 symbol_table symbol symtab@null symbol symtab@printf, strtab@printf, STB_GLOBAL, STT_FUNCTION symbol symtab@print_hello, strtab@print_hello, STB_GLOBAL, STT_FUNCTION symbol symtab@exit, strtab@exit, STB_GLOBAL, STT_FUNCTION end_symbol_table align 8 reloc_table reloc _printf_, symtab@printf, R_X86_64_64 reloc _print_hello_, symtab@print_hello, R_X86_64_64 reloc _exit_, symtab@exit, R_X86_64_64 end_reloc_table _interpreter_name_ db interpreter, 0 .SIZE=$-_interpreter_name_ .MEMSIZE=.SIZE start: call [_print_hello_] xor rdi, rdi call [_exit_] align 8 _printf_ addr ? _print_hello_ addr ? _exit_ addr ? FILE.SIZE=$-BASE |
|||
22 Sep 2007, 03:47 |
|
snify 23 Sep 2007, 20:22
nocona:
the 32bit elf example gives me: "Floating Point Exception" any ideas |
|||
23 Sep 2007, 20:22 |
|
nocona 29 Sep 2007, 03:06
what version of glibc u're using? I try it with glibc-2.5.
|
|||
29 Sep 2007, 03:06 |
|
snify 30 Sep 2007, 09:37
nocona wrote: what version of glibc u're using? I try it with glibc-2.5. I'm using glibc-2.3.5. My friend also have 2.3.5. Could it work somehow on this version? |
|||
30 Sep 2007, 09:37 |
|
ronware 30 Sep 2007, 16:06
nocona wrote:
Very cool nocona - thanks! I will try to use your technique for my Reva forth compiler (http://ronware.org/reva/). It's very frustrating to have to use gcc to compile an ASM only program |
|||
30 Sep 2007, 16:06 |
|
nocona 03 Oct 2007, 04:02
Quote:
sorry. I don't know what cause the bug. It also happens in 2.4. glad u like it ronware . |
|||
03 Oct 2007, 04:02 |
|
snify 04 Oct 2007, 09:47
nocona can u please figure it out, cause I really need this. and if it is for glibc-2.5 only, it becomes useless.
|
|||
04 Oct 2007, 09:47 |
|
nocona 06 Oct 2007, 04:01
sorry for long waiting.. i have time today to compile glibc-2.4 and invoking the program with LD_DEBUG=all using the ld.so from 2.4 i see it fails on symbol lookup from our program.. so DT_HASH comes into my mind. i added it, plus the relevant hash table with nulls and the 64-bit example run without problem... it should also solve the problem with 32-bit i think.. what you need to do :
add/modify dynamic table (note the addition of DT_HASH entry, with DT_HASH=4, add it early in source) Code: _dynamic_ : addr DT_NEEDED, strtab@libc addr DT_NEEDED, strtab@gtkx11 addr DT_NEEDED, strtab@gobject addr DT_STRTAB, string_table addr DT_SYMTAB, symbol_table addr DT_STRSZ, string_table.SIZE addr DT_SYMENT, SYMENT_SIZE addr DT_HASH, hash_table addr DT_RELA, reloc_table addr DT_RELASZ, reloc_table.SIZE addr DT_RELAENT, RELOCENT_SIZE addr 0, 0 ;terminator .SIZE=$-_dynamic_ .MEMSIZE=.SIZE then add the hash table immediately after above : Code: hash_table: dd 11, 10 rd 11 rd 10 it just a fake hash table, we usually don't export symbols from executable. first dword is total symbols in symbol table + 1 (=10+1), 2nd dword is total symbol table, then follows an array of dwords in count of first dword and 2nd dword. please test it and inform me if it still fails (i try the 64-bit version and it runs ok on glibc-2.4). |
|||
06 Oct 2007, 04:01 |
|
snify 06 Oct 2007, 09:22
Quote: Inconsistency detected by ld.so: dynamic-link.h: 163: elf_get_dynamic_info: Assertion `info[9]->d_un.d_val == sizeof (Elf32_Rela)' failed! |
|||
06 Oct 2007, 09:22 |
|
nocona 13 Oct 2007, 03:01
no. no. no.. i provide solution for 64-bit version. use the 32-bit example to add the DT_HASH info and table. 32-bit doesn't use RELA relocation info! and actually the hast_table can be reduced to :
Code: hash_table: dd 1, 1 .bucket: rd 1 .chain: rd 1 |
|||
13 Oct 2007, 03:01 |
|
nocona 13 Oct 2007, 03:05
another example : a simple qt4 (=qt-4.3.0) program. This example was taken from the first page of qt4 tutorial. The original code was:
Code: #include <QApplication> #include <QPushButton> int main (int argc, char *argv[]) { QApplication app (argc, argv); QPushButton hello ("Hello world!"); hello.resize (120, 30); hello.show (); return app.exec (); } Reference : -Itanium C++ ABI for name mangling. -Qt4 Documentation -Qt4 source code - to see the actual method/constructor prototype. -g++ -fdump-class-hierarchy switch on the above code - mainly to get the size of relevant classes... easier than to read the related headers.. note : i didn't include calls to object's destructor... Code: use64 BASE=BASE64 ENTRYPOINT=start ELF_TYPE=ET_EXEC ELF_PHEADER_ENTRY_SIZE=ELF_PHEADER_ENTRY_SIZE64 SYMENT_SIZE=SYMENT_SIZE64 RELOCENT_SIZE=RELOCENT_SIZE64 CLASS=ELF_CLASS64 MACHINE=EM_X86_64 program_header_entry fix program_header_entry64 symbol fix symbol64 reloc fix reloc64 addr fix addr64 offs fix offs64 interpreter fix interpreter64 ;ELF32 BASE32=0x8048000 ELF_PHEADER_ENTRY_SIZE32 = 32 SYMENT_SIZE32=16 RELOCENT_SIZE32=8 ;ELF64 BASE64=0x400000 ELF_PHEADER_ENTRY_SIZE64 = 56 SYMENT_SIZE64=24 RELOCENT_SIZE64=24 ;ELF constants ELF_CLASS32=1 ELF_CLASS64=2 ET_EXEC=2 ET_DYN=3 EM_386=3 EM_X86_64=62 DT_NEEDED=1 DT_STRTAB=5 DT_HASH=4 DT_SYMTAB=6 DT_STRSZ=10 DT_SYMENT=11 DT_REL=17 DT_RELSZ=18 DT_RELENT=19 DT_RELA=7 DT_RELASZ=8 DT_RELAENT=9 DT_SONAME=14 PT_INTERP=3 PT_DYNAMIC=2 PT_LOAD=1 R_386_32=1 R_X86_64_64=1 STB_GLOBAL=1 STT_FUNCTION=2 read=4 write=2 execute=1 xo=1 wo=2 wx=3 ro=4 rx=5 ;rw=6 rwx=7 ;end ELF constants define interpreter64 "/lib/ld-linux-x86-64.so.2" define interpreter32 "/lib/ld-linux.so.2" macro program_header {label program_header} macro program_header_entry32 type, location, access, align, size, memsize { dd type dd OFFSETOF location, location, 0 if type <> PT_LOAD dd location#.SIZE, location#.MEMSIZE else dd size, memsize end if dd access, align } macro end_program_header { .SIZE=$-program_header .MEMSIZE=.SIZE } macro program_header_entry64 type, location, access, align, size, memsize { dd type, access dq OFFSETOF location, location, 0 if type <> PT_LOAD dq location#.SIZE, location#.MEMSIZE else dq size, memsize end if dq align } macro symbol_table {label symbol_table} macro end_symbol_table { .SIZE=$-symbol_table .MEMSIZE=.SIZE } macro symbol32 name, str, bind, type { name = ($-symbol_table)/SYMENT_SIZE if str eq times 16 db 0 else dd str, 0, 0 db bind shl 4 + 2, 0 dw 0 end if } macro symbol64 name, str, bind, type, value, size, index { name = ($-symbol_table)/SYMENT_SIZE if str eq times 24 db 0 else dd str db bind shl 4 + 2, 0 dw index+0 dq value+0, size+0 end if } macro reloc_table {label reloc_table} macro end_reloc_table { .SIZE=$-reloc_table .MEMSIZE=.SIZE restore reloc_table } macro reloc32 label, symbol, type {dd label, symbol shl 8 + type} macro reloc64 label, symbol, type {dq label, symbol shl 32 + type, 0} macro string_table {label string_table} macro string name, str { name=$-string_table if str eq db 0 else db str, 0 end if } macro end_string_table { .SIZE=$-string_table .MEMSIZE=.SIZE } macro addr32 [value] {dd value} struc addr32 [value] {. dd value} macro offs32 [value] {dd value} struc offs32 [value] {. dd value} macro addr64 [value] {dq value} struc addr64 [value] {. dq value} macro offs64 [value] {dq value} struc offs64 [value] {. dq value} OFFSETOF equ -BASE+ org BASE ;--------------------------------------------------------------------------- QT_VERSION_STR equ "4.3.0" QT_VERSION = 0x40300 Elf_EHdr: db 0x7F, "ELF", CLASS, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; dw ELF_TYPE dw MACHINE dd 1 addr ENTRYPOINT ;entrypoint offs OFFSETOF program_header offs 0 dd 0 dw Elf_EHdr.SIZE dw ELF_PHEADER_ENTRY_SIZE dw program_header.SIZE/ELF_PHEADER_ENTRY_SIZE dw 0, 0, 0 .SIZE=$-Elf_EHdr program_header program_header_entry PT_INTERP, _interpreter_name_, ro, 1 program_header_entry PT_DYNAMIC, _dynamic_, ro, 4 program_header_entry PT_LOAD, Elf_EHdr, rwx, 0x1000, FILE.SIZE, PROGRAM.SIZE end_program_header align 4 _dynamic_ : addr DT_NEEDED, strtab@libqtgui addr DT_STRTAB, string_table addr DT_HASH, hash_table addr DT_SYMTAB, symbol_table addr DT_STRSZ, string_table.SIZE addr DT_SYMENT, SYMENT_SIZE addr DT_RELA, reloc_table addr DT_RELASZ, reloc_table.SIZE addr DT_RELAENT, RELOCENT_SIZE addr 0, 0 ;terminator .SIZE=$-_dynamic_ .MEMSIZE=.SIZE string_table string strtab@null string strtab@libqtgui, "libQtGui.so" string strtab@_ZN12QApplicationC1ERiPPci, "_ZN12QApplicationC1ERiPPci" string strtab@_ZN7QString9fromAsciiEPKci, "_ZN7QString9fromAsciiEPKci" string strtab@_ZN11QPushButtonC1ERK7QStringP7QWidget, "_ZN11QPushButtonC1ERK7QStringP7QWidget" string strtab@_ZN7QWidget6resizeERK5QSize, "_ZN7QWidget6resizeERK5QSize" string strtab@_ZN7QWidget10setVisibleEb, "_ZN7QWidget10setVisibleEb" string strtab@_ZN12QApplication4execEv, "_ZN12QApplication4execEv" string strtab@exit, "exit" ;string strtab@, "" string strtab@_ZN7QStringC1EPK5QChari, "_ZN7QStringC1EPK5QChari" end_string_table align 8 symbol_table symbol symtab@null symbol symtab@_ZN12QApplicationC1ERiPPci, strtab@_ZN12QApplicationC1ERiPPci, STB_GLOBAL, STT_FUNCTION symbol symtab@_ZN7QString9fromAsciiEPKci, strtab@_ZN7QString9fromAsciiEPKci, STB_GLOBAL, STT_FUNCTION symbol symtab@_ZN11QPushButtonC1ERK7QStringP7QWidget, strtab@_ZN11QPushButtonC1ERK7QStringP7QWidget, STB_GLOBAL, STT_FUNCTION symbol symtab@_ZN7QWidget6resizeERK5QSize, strtab@_ZN7QWidget6resizeERK5QSize, STB_GLOBAL, STT_FUNCTION symbol symtab@_ZN7QWidget10setVisibleEb, strtab@_ZN7QWidget10setVisibleEb, STB_GLOBAL, STT_FUNCTION symbol symtab@_ZN12QApplication4execEv, strtab@_ZN12QApplication4execEv, STB_GLOBAL, STT_FUNCTION symbol symtab@exit, strtab@exit, STB_GLOBAL, STT_FUNCTION symbol symtab@_ZN7QStringC1EPK5QChari, strtab@_ZN7QStringC1EPK5QChari, STB_GLOBAL, STT_FUNCTION end_symbol_table align 8 reloc_table reloc _ZN12QApplicationC1ERiPPci, symtab@_ZN12QApplicationC1ERiPPci, R_X86_64_64 reloc _ZN7QString9fromAsciiEPKci, symtab@_ZN7QString9fromAsciiEPKci, R_X86_64_64 reloc _ZN11QPushButtonC1ERK7QStringP7QWidget, symtab@_ZN11QPushButtonC1ERK7QStringP7QWidget, R_X86_64_64 reloc _ZN7QWidget6resizeERK5QSize, symtab@_ZN7QWidget6resizeERK5QSize, R_X86_64_64 reloc _ZN7QWidget10setVisibleEb, symtab@_ZN7QWidget10setVisibleEb, R_X86_64_64 reloc _ZN12QApplication4execEv, symtab@_ZN12QApplication4execEv, R_X86_64_64 reloc exit, symtab@exit, R_X86_64_64 reloc _ZN7QStringC1EPK5QChari, symtab@_ZN7QStringC1EPK5QChari, R_X86_64_64 end_reloc_table align 4 hash_table: dd 1 dd 1 .bucket: rd 1 .chain: rd 1 _interpreter_name_ db interpreter, 0 .SIZE=$-_interpreter_name_ .MEMSIZE=.SIZE start: virtual at rbp-start.local_size .app_obj rb 16 .btn_obj_hello rb 40 .str_obj_hello rb 8 .size dd ?, ? ;width, height .local_size = $-.app_obj end virtual virtual at rbp+8 .argc dq ? .pargv dq ? end virtual enter start.local_size, 0 ;QApplication(int &argc, char **argv, int = QT_VERSION) mov ecx, QT_VERSION lea rdi, [start.app_obj] lea rsi, [start.argc] lea rdx, [start.pargv] call [_ZN12QApplicationC1ERiPPci] ;QString(const QChar *unicode, int size) lea rdi, [start.str_obj_hello] mov r13, rdi lea esi, [msg_hello] xor rdx, rdx mov dl, msg_hello.SIZE call [_ZN7QStringC1EPK5QChari] ;QPushButton(const QString &text, QWidget *parent=0); lea r12, [start.btn_obj_hello] mov rdi, r12 lea rsi, [start.str_obj_hello] xor edx, edx call [_ZN11QPushButtonC1ERK7QStringP7QWidget] ;void QWidget::resize(const QSize &s) mov rdi, r12 mov [start.size], 300 mov [start.size+4], 200 lea rsi, [start.size] call [_ZN7QWidget6resizeERK5QSize] ;void QWidget::setVisible(bool visible) mov rdi, r12 xor rsi, rsi inc rsi call [_ZN7QWidget10setVisibleEb] ;int QApplication::exec() call [_ZN12QApplication4execEv] leave xor rdi, rax call [exit] msg_hello du "Hello World" .SIZE=($-msg_hello)/2 FILE.SIZE=$-BASE align 8 _ZN12QApplicationC1ERiPPci dq ? _ZN7QString9fromAsciiEPKci dq ? _ZN11QPushButtonC1ERK7QStringP7QWidget dq ? _ZN7QWidget6resizeERK5QSize dq ? _ZN7QWidget10setVisibleEb dq ? _ZN12QApplication4execEv dq ? _ZN7QStringC1EPK5QChari dq ? exit dq ? PROGRAM.SIZE=$-BASE |
|||
13 Oct 2007, 03:05 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.