flat assembler
Message board for the users of flat assembler.

Index > Linux > elf executable with dynamic linker... from scratch

Goto page Previous  1, 2
Author
Thread Post new topic Reply to topic
snify



Joined: 02 Dec 2004
Posts: 39
snify
dude, same problem. *please* check this cause I need it for my compiler
32bit elf gtk example (fixed):
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_HASH=4  ;; <--
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_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

;; here comes the hash table
hash_table:
dd 1, 1
.bucket:
rd 1
.chain:
rd 1

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
    


gives me:
Quote:
andLinux:/mnt/e# ./testelf
Inconsistency detected by ld.so: dynamic-link.h: 163: elf_get_dynamic_info: Assertion `info[9]->d_un.d_val == sizeof (Elf32_Rela)' failed!
Post 14 Oct 2007, 11:20
View user's profile Send private message Visit poster's website Reply with quote
nocona



Joined: 04 Aug 2007
Posts: 35
nocona
change line

Code:
addr DT_RELA, reloc_table 
addr DT_RELASZ, reloc_table.SIZE 
    


to

Code:
addr DT_REL, reloc_table 
addr DT_RELSZ, reloc_table.SIZE 
    


as i said before, x86 use DT_REL type.
Post 16 Oct 2007, 04:07
View user's profile Send private message Reply with quote
snify



Joined: 02 Dec 2004
Posts: 39
snify
now it gives Segmentation Fault. whatever, thanks Smile
Post 16 Oct 2007, 07:55
View user's profile Send private message Visit poster's website Reply with quote
nocona



Joined: 04 Aug 2007
Posts: 35
nocona
could u please provide some info on where it segfault? it's in ld.so code or the program itself? i ran it on my system with glibc-2.4 installed and it execute fine.
Post 27 Oct 2007, 03:37
View user's profile Send private message Reply with quote
Raedwulf



Joined: 13 Jul 2005
Posts: 375
Location: United Kingdom
Raedwulf
<Ooops post deleted> found your shared library sample Razz.

Edit: Maybe show an example using a proper hash table for exported symbols?


Last edited by Raedwulf on 07 Nov 2007, 14:18; edited 2 times in total
Post 06 Nov 2007, 21:24
View user's profile Send private message MSN Messenger Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid
nocona: wow, OOP called from assembly, this is pretty cool hack.

by the way, you could assign nicer local names to decorated method names, like "QWidget.setVisible" etc...
Post 07 Nov 2007, 06:48
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
Raedwulf



Joined: 13 Jul 2005
Posts: 375
Location: United Kingdom
Raedwulf
Yea that would be even cooler Smile All I can say is once Tomasz wakes up, he should take a look at this elf from scratch Smile.
Post 07 Nov 2007, 07:55
View user's profile Send private message MSN Messenger Reply with quote
nocona



Joined: 04 Aug 2007
Posts: 35
nocona
Quote:

Maybe show an example using a proper hash table for exported symbols?

i didn't really quite understand ur question. that was a proper hash table, otherwise linker couldn't find any symbols from the shared library. maybe you means a macro that create hash table automatically?

thanks vid..i actually don't have any needs to use these libraries and that time I want to know how it is possible to call C++ libraries (e.g qt) from asm source.. it is strictly for my learning purpose so i just leave the name that way Smile.

btw.. i tested the 32-bit example in my PCBSD installation and it run without modification (no need for brandelf -f linux!). it seems the loader knows about linux binary just by looking the interpreter name.. also if we want to use bsd dynamic linker, we need to change the interpreter name to /libexec/ld-elf.so.1.. not just that, we need to define 2 symbols ( i think) "environ" and "__progname" because libc imported it and it seems every bsd program define them.. so we need proper hash table here also.. next time i will put the example source for BSD.. but not here of course Wink
Post 08 Nov 2007, 06:13
View user's profile Send private message Reply with quote
Raedwulf



Joined: 13 Jul 2005
Posts: 375
Location: United Kingdom
Raedwulf
Yea I meant a hash table with some macro magic Wink.

Oh yea just to note:
define interpreter64 "/lib/ld-linux-x86-64.so.2"

There's sometimes no link between that and "/lib64/ld-linux-x86-64.so.2" so it may not run on some systems - as I've discovered Smile.
Better use lib64.

There's also an extra DT_RPATH which is useful for specifying library paths.

e.g.
Code:
rpath fix rpath64 ; or rpath32
define rpath64 ".:/lib64:/usr/lib64:/usr/local/lib64"
define rpath32 ".:/lib:/usr/lib:/usr/local/lib"

_dynamic_ :
addr DT_RPATH, strtab@rpath
.....
.....
addr 0, 0                               ;terminator
.SIZE=$-_dynamic_
.MEMSIZE=.SIZE

string_table
 string strtab@null
 string strtab@rpath, rpath ; HERE
....
....
end_string_table

    


Otherwise the binary can't find a linked .so in the same path as the file (or so i've discovered on my test system (University of York Slackware 12.0)).

_________________
Raedwulf
Post 08 Nov 2007, 08:43
View user's profile Send private message MSN Messenger Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2

< 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-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.