1 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;; Native x86 GNU
/Linux Forth System
5 ;; Copyright
(C
) 2020 Ketmar Dark
// Invisible Vector
7 ;; This
program is free software
: you can redistribute it and
/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation
, version
3 of the License ONLY
.
11 ;; This
program is distributed in the hope that it will be useful
,
12 ;; but WITHOUT ANY WARRANTY
; without even the implied warranty of
13 ;; MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE
. See the
14 ;; GNU General Public License
for more details
.
16 ;; You should have received a copy of the GNU General Public License
17 ;; along with this
program. If not
, see
<http
://www
.gnu
.org
/licenses
/>.
18 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
19 ;; simple elf header creation
, and writing binary elf file
20 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23 : (put
-b
) ( addr value
-- addr
+1 )
27 : (put
-w
) ( addr value
-- addr
+2 )
31 : (put
-dw
) ( addr value
-- addr
+4 )
35 : (put
-strz
) ( addr count
-- addr
+count
+1 )
37 over
+ swap
do i c@
(put
-b
) loop
56 4 4 + 4 + 1 + 1 + 2 + constant ELF32_SYM_SIZE
57 4 4 + constant ELF32_REL_SIZE
59 : build
-elf
-header
( addr
-- eaddr
)
67 1 (put
-b
) ;; endianness
68 1 (put
-b
) ;; header version
74 3 (put
-w
) ;; e_machine
76 1 (put
-dw
) ;; e_version
77 dup
to elf
-entry
-point
-addr
79 $
34 (put
-dw
) ;; e_phoff
83 $
34 (put
-w
) ;; e_ehsize
84 32 (put
-w
) ;; e_phentsize
86 40 (put
-w
) ;; e_shentsize
88 0 (put
-w
) ;; e_shstrndx
90 ;; first segment
: interpreter
92 $
00000094 (put
-dw
) ;; foffset
93 $
08048094 (put
-dw
) ;; vaddr
94 $
08048094 (put
-dw
) ;; shit
95 $
00000013 (put
-dw
) ;; fsize
96 $
00000013 (put
-dw
) ;; msize
97 $
00000004 (put
-dw
) ;; flags
98 $
00000001 (put
-dw
) ;; align
100 ;; second segment
: dynamic imports
102 $
000000A7
(put
-dw
) ;; foffset
103 $
080480A7
(put
-dw
) ;; vaddr
104 $
080480A7
(put
-dw
) ;; shit
105 $
00000050 (put
-dw
) ;; fsize
106 $
00000050 (put
-dw
) ;; msize
107 $
00000004 (put
-dw
) ;; flags
108 $
00000001 (put
-dw
) ;; align
110 ;; thirds segment
: executable code
112 $
00000000 (put
-dw
) ;; foffset
113 $
08048000 (put
-dw
) ;; vaddr
114 $
08048000 (put
-dw
) ;; shit
115 dup
to elf
-code
-size
-addr
116 $
0000D3C5
(put
-dw
) ;; fsize
117 $
0000D3C5
(put
-dw
) ;; msize
118 $
00000007 (put
-dw
) ;; flags
119 $
00001000 (put
-dw
) ;; align
121 ;; first segment data
: write interpreter string
122 " /lib/ld-linux.so.2" (put
-strz
)
124 ;; second segment data
: write import table
125 ;; the only thing we need is
.so management functions
, so we
'll create
126 ;; a very simple import table for "libdl.so", with 3 imports:
127 ;; "dlopen", "dlclose", "dlsym"
128 DT_NEEDED (put-dw) 1 (put-dw) ;; elfhead_str_libdl-elfhead_strtab
129 DT_STRTAB (put-dw) $08048137 (put-dw) ;; elfhead_strtab
130 DT_STRSZ (put-dw) $0000001F (put-dw) ;; elfhead_strsz
131 DT_SYMTAB (put-dw) $080480F7 (put-dw) ;; elfhead_symtab
132 DT_SYMENT (put-dw) ELF32_SYM_SIZE (put-dw)
133 DT_REL (put-dw) $08048156 (put-dw) ;; elfhead_rel
134 DT_RELSZ (put-dw) $00000018 (put-dw) ;; elfhead_relsz (put-dw)
135 DT_RELENT (put-dw) ELF32_REL_SIZE (put-dw)
136 DT_HASH (put-dw) $0804816E (put-dw) ;; elfhead_hash (put-dw)
137 DT_NULL (put-dw) 0 (put-dw)
139 ;; here starts executable segment
140 ;; we're putting rest of import table into it
; this is prolly not right
, but it works
142 ;; import symbol table
143 ;; NULL import
, should always be here
147 $
12 (put
-b
) ;; (STB_GLOBAL
<<4)|STT_FUNC
154 $
12 (put
-b
) ;; (STB_GLOBAL
<<4)|STT_FUNC
161 $
12 (put
-b
) ;; (STB_GLOBAL
<<4)|STT_FUNC
168 $
12 (put
-b
) ;; (STB_GLOBAL
<<4)|STT_FUNC
174 " libdl.so" (put
-strz
)
176 " dlclose" (put
-strz
)
179 ;; importer will use this
to fix relocations
181 $
0804818A
(put
-dw
) ;; offset
to elfimp_dlopen
182 $
0101 (put
-dw
) ;; high bit is symbol index
, low bit is R_386_32
184 $
0804818E
(put
-dw
) ;; offset
to elfimp_dlclose
185 $
0201 (put
-dw
) ;; high bit is symbol index
, low bit is R_386_32
187 $
08048192 (put
-dw
) ;; offset
to elfimp_dlsym
188 $
0301 (put
-dw
) ;; high bit is symbol index
, low bit is R_386_32
190 ;; fake import hash table with one bucket
191 1 (put
-dw
) ;; bucket size
192 4 (put
-dw
) ;; chain size
(including NULL import
)
193 0 (put
-dw
) ;; fake bucket
, just one hash value
200 ;; loadef will add symbol offets
to the following three dwords
201 dup
real->tc
to elf
-import
-table
-rva
203 0 (put
-dw
) ;; dlclose
205 dup
real->tc elf
-import
-table
-rva
- to elf
-import
-table
-size
209 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
210 : create
-elf
-tc
-constants
( -- )
211 ;; create some assembler constants
212 " urforth_code_base_addr" elf
-base
-rva asmx86
:asm
-Make
-Constant
214 " elfhead_codesize_addr" elf
-code
-size
-addr
real->tc asmx86
:asm
-Make
-Constant
215 " elfhead_impstart" elf
-import
-table
-rva asmx86
:asm
-Make
-Constant
216 " elfhead_implen" elf
-import
-table
-size asmx86
:asm
-Make
-Constant
218 " elfimp_dlopen" elf
-import
-table
-rva
0 +cells asmx86
:asm
-Make
-Constant
219 " elfimp_dlclose" elf
-import
-table
-rva
1 +cells asmx86
:asm
-Make
-Constant
220 " elfimp_dlsym" elf
-import
-table
-rva
2 +cells asmx86
:asm
-Make
-Constant
224 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
225 : save
-elf
-binary
( addr count
-- )
226 endcr
." code size: " curr
-code
-size
. ." bytes\n"
228 curr
-code
-size elf
-code
-size
-addr
!
229 curr
-code
-size elf
-code
-size
-addr cell
+ !
231 ;; create output file
232 o
-wronly o
-creat or o
-trunc or
;; flags
233 s
-irwxu s
-irgrp or s
-ixgrp or s
-iroth or s
-ixoth or
;; mode
236 dup
0< ?abort
" cannot create output file"
238 elf
-target
-memory curr
-code
-size r@
(fwrite
)
239 curr
-code
-size
<> ?abort
" error writing file"
240 r
> (fclose
) ?abort
" error closing file"