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
Thread Post new topic Reply to topic
nocona



Joined: 04 Aug 2007
Posts: 35
nocona 11 Aug 2007, 06:06
Here's an example code for elf64 executable which use the glibc dynamic linking facilities. Current fasm's "format elf/elf64 directive" is not powerful enough to allow us to do this, so i have to manually created all the necessary program headers and its associated contents. I tested this in my core 2 duo machine + kernel 2.6.22 (+kamikaze5 patchset) and glibc-2.5 - gentoo amd64 distro + default profile (not sure if this run in hardened/selinux because i set PT_LOAD flags to rwx).

The program use "/lib/ld-linux-x86-64.so.2" (lib usually a symlink to /lib64 in multilib linux) as our dynamic linker, import symbols from libc.so.6 (printf) and libpthread.so.0 (pthread_create). It does not use the plt and got stuff and instead use DT_RELA entry to fix symbol reference before program startup. afaik, plt only useful for lazy binding (DT_JMPREL need not be processed early at program startup). no need for symbol hash table also, which, from my understanding, only useful for big symbol tables to make symbol lookup faster and only if another object file reference our symbol. Our entrypoint is "jumped" to from the interpreter code and the stack contents is the same as usual (argc, argv, envp, auxv) but i'm not sure if there is a modification in their contents.

What this program does is create 100 threads using pthread_create and then exit. The thread routine just print their thread pointer (tcb?). One use of this thread pointer is for static tls using negative offset; but to use it we still need to add tls initialization block in our program (PT_TLS and other info).

Code:
use64

BASE=0x400000
OFFSETOF equ -BASE+
ELF64_PHEADER_ENTRY_SIZE = 56
org BASE

Elf64_EHdr:
db 0x7F, "ELF", 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0  ;
dw 2                                                       ;ET_EXEC
dw 62                                                       ;AMD64/EM64T
dd 1                                                    ;
dq _start                                          ;entrypoint
dq OFFSETOF Elf64_PHdr                                   
dq 0
dd 0
dw Elf64_EHdr.SIZE
dw ELF64_PHEADER_ENTRY_SIZE
dw Elf64_PHdr.SIZE/ELF64_PHEADER_ENTRY_SIZE
dw 0, 0, 0
.SIZE=$-Elf64_EHdr


Elf64_PHdr:
;PT_PHDR                                         ;not needed
;dd 6
;dd 4
;dq OFFSETOF Elf64_PHdr
;dq Elf64_PHdr, 0
;dq Elf64_PHdr.SIZE
;dq Elf64_PHdr.SIZE
;dq 8

;PT_INTERP
dd 3                                                  ;mandatory - full path to our interpreter
dd 4                                                       ;ro
dq OFFSETOF _interpreter_name_                           
dq _interpreter_name_, 0
dq _interpreter_name_.SIZE, _interpreter_name_.SIZE
dq 1                                                     ;1-byte alignment

;PT_DYNAMIC
dd 2                                                    ;mandatory - needed by interpreter
dd 4                                                      ;ro
dq OFFSETOF _dynamic_
dq _dynamic_, 0
dq _dynamic_.SIZE, _dynamic_.SIZE
dq 8                                                    ;8-bytes alignment

;PT_LOAD
dd 1                                                      ;mandatory - which area of file to load
dd 7                                                 ;wrx
dq OFFSETOF Elf64_EHdr                                  ;just load all contents of file
dq BASE, 0
dq FILE.SIZE, FILE.SIZE                                        
dq 0x100000                                         ;1-MiB alignment
.SIZE=$-Elf64_PHdr

_start:
   
    ;push   r12
 xor     r12, r12
    
_create_thread:
     cmp     r12d, 100
   je      _exit
       inc     r12

     xor     rsi, rsi
    push    rax
 mov     rdi, rsp        
    mov     edx, _thread_routine_
       mov     rcx, r12
    call    [_pthread_create_]
  test    rax, rax
    mov     rsi, rax
    pop     rax
 jnz     _exit_error
 jmp     _create_thread

_exit_error:
      mov     edi, error_msg
      call    [_printf_]
_exit:
    mov     eax, 60                                 ;sys_exit
   syscall

;void thread_routine(void *);
_thread_routine_:
       mov     rsi, rdi
    mov     rdx, [fs:0]
     mov     edi, thread_msg
     xor     eax, eax
    call    [_printf_]
  ret

thread_msg db "Thread %d with thread pointer = %p", 10, 0
error_msg db "pthread_create fails with error %d", 10, 0

align 8
_printf_                 dq ?
_pthread_create_        dq ?

align 8
_dynamic_ :
dq 1, _strtab_.libc           ;DT_NEEDED
dq 1, _strtab_.libpthread ;DT_NEEDED
dq 5, _strtab_                    ;DT_STRTAB
dq 6, _symtab_                    ;DT_SYMTAB
dq 10, _strtab_.SIZE              ;DT_STRSZ
dq 11, 24                  ;DT_SYMENT
dq 7, _rela_                      ;DT_RELA
dq 8, _rela_.SIZE           ;DT_RELASZ
dq 9, 24                  ;DT_RELAENT
dq 0, 0                          ;terminator
.SIZE=$-_dynamic_

_strtab_:
.null=$-_strtab_
   db 0
.libc=$-_strtab_
    db "libc.so.6", 0
.libpthread=$-_strtab_
       db "libpthread.so.0", 0
.printf=$-_strtab_
     db "printf", 0
.pthread_create=$-_strtab_
      db "pthread_create", 0
.SIZE=$-_strtab_

align 4
_symtab_:
.null=($-_symtab_)/24
       rb 24
.printf=($-_symtab_)/24
    dd _strtab_.printf      ;strtab_index
       db 1 shl 4 + 2          ;info=GLOBAL,STT_FUNCTION
   db 0                    ;other
      dw 0                    ;shndx=SHN_UNDEF
    dq 0, 0                 ;value=unknown,size=unknown
.pthread_create=($-_symtab_)/24
      dd _strtab_.pthread_create
  db 1 shl 4 + 2          ;GLOBAL,STT_FUNCTION
        db 0
        dw 0
        dq 0, 0

.SIZE=$-_symtab_

align 8
_rela_:
.printf:
       dq _printf_                             ;reloc addess
       dq _symtab_.printf shl 32 + 1           ;symtab_index shl 32 + type
 dq 0                                    ;addend
.pthread_create: 
    dq _pthread_create_
 dq _symtab_.pthread_create shl 32 + 1
       dq 0

.SIZE=$-_rela_

_interpreter_name_ db "/lib/ld-linux-x86-64.so.2", 0
.SIZE=$-_interpreter_name_

FILE.SIZE=$-BASE

    


Last edited by nocona on 18 Aug 2007, 04:17; edited 1 time in total
Post 11 Aug 2007, 06:06
View user's profile Send private message Reply with quote
MichaelH



Joined: 03 May 2005
Posts: 402
MichaelH 13 Aug 2007, 00:03
Thankyou, much appreciated!
Post 13 Aug 2007, 00:03
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
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
Post 13 Aug 2007, 00:50
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
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.
Post 13 Aug 2007, 15:59
View user's profile Send private message Reply with quote
nocona



Joined: 04 Aug 2007
Posts: 35
nocona 18 Aug 2007, 04:10
Quote:

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.

according to the spec... but this is the proof that it's not always the case Smile.
Post 18 Aug 2007, 04:10
View user's profile Send private message Reply with quote
nocona



Joined: 04 Aug 2007
Posts: 35
nocona 18 Aug 2007, 04:27
Quote:

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.

done Smile
Post 18 Aug 2007, 04:27
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 18 Aug 2007, 14:14
Quote:

according to the spec... but this is the proof that it's not always the case

This is the proof that some OSes don't care about it Smile

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
Post 18 Aug 2007, 14:14
View user's profile Send private message Reply with quote
snify



Joined: 02 Dec 2004
Posts: 39
snify 09 Sep 2007, 15:39
can you please add more examples for linux "from scratch", maybe elf32 with gtk (THAT WILL BE AWESOME!)
Post 09 Sep 2007, 15:39
View user's profile Send private message Visit poster's website Reply with quote
nocona



Joined: 04 Aug 2007
Posts: 35
nocona 22 Sep 2007, 03:43
Quote:

can you please add more examples for linux "from scratch", maybe elf32 with gtk (THAT WILL BE AWESOME!)

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
    
Post 22 Sep 2007, 03:43
View user's profile Send private message Reply with quote
nocona



Joined: 04 Aug 2007
Posts: 35
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
    
Post 22 Sep 2007, 03:47
View user's profile Send private message Reply with quote
snify



Joined: 02 Dec 2004
Posts: 39
snify 23 Sep 2007, 20:22
nocona:
the 32bit elf example gives me:
"Floating Point Exception"
any ideas Confused
Post 23 Sep 2007, 20:22
View user's profile Send private message Visit poster's website Reply with quote
nocona



Joined: 04 Aug 2007
Posts: 35
nocona 29 Sep 2007, 03:06
what version of glibc u're using? I try it with glibc-2.5.
Post 29 Sep 2007, 03:06
View user's profile Send private message Reply with quote
snify



Joined: 02 Dec 2004
Posts: 39
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?
Post 30 Sep 2007, 09:37
View user's profile Send private message Visit poster's website Reply with quote
ronware



Joined: 08 Jan 2004
Posts: 179
Location: Israel
ronware 30 Sep 2007, 16:06
nocona wrote:

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..


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 Sad
Post 30 Sep 2007, 16:06
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger Reply with quote
nocona



Joined: 04 Aug 2007
Posts: 35
nocona 03 Oct 2007, 04:02
Quote:

I'm using glibc-2.3.5. My friend also have 2.3.5. Could it work somehow on this version?

sorry. I don't know what cause the bug. It also happens in 2.4.

glad u like it ronware Smile.
Post 03 Oct 2007, 04:02
View user's profile Send private message Reply with quote
snify



Joined: 02 Dec 2004
Posts: 39
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.
Post 04 Oct 2007, 09:47
View user's profile Send private message Visit poster's website Reply with quote
nocona



Joined: 04 Aug 2007
Posts: 35
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).
Post 06 Oct 2007, 04:01
View user's profile Send private message Reply with quote
snify



Joined: 02 Dec 2004
Posts: 39
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!

Sad
Post 06 Oct 2007, 09:22
View user's profile Send private message Visit poster's website Reply with quote
nocona



Joined: 04 Aug 2007
Posts: 35
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 
    
Post 13 Oct 2007, 03:01
View user's profile Send private message Reply with quote
nocona



Joined: 04 Aug 2007
Posts: 35
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
    
Post 13 Oct 2007, 03:05
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.