ae1e44ab22942d09a176cb1edd227aa7f4cc91a1
[mes.git] / elf.mes
1 ;;; -*-scheme-*-
2
3 (define (int->bv32 value)
4   (let ((bv (make-bytevector 4)))
5     (bytevector-u32-native-set! bv 0 value)
6     bv))
7
8 (define (int->bv16 value)
9   (let ((bv (make-bytevector 2)))
10     (bytevector-u16-native-set! bv 0 value)
11     bv))
12
13 (define elf32-addr int->bv32)
14 (define elf32-half int->bv16)
15 (define elf32-off int->bv32)
16 (define elf32-word int->bv32)
17
18 (define (make-elf text data)
19  (define vaddress #x08048000)
20
21  (define ei-magic `(#x7f ,@(string->list "ELF")))
22  (define ei-class '(#x01)) ;; 32 bit
23  (define ei-data '(#x01)) ;; little endian
24  (define ei-version '(#x01))
25  (define ei-osabi '(#x00))
26  (define ei-pad '(#x0 #x0 #x0 #x0 #x0 #x0 #x0 #x0))
27  (define e-ident
28    (append
29     ei-magic
30     ei-class
31     ei-data
32     ei-version
33     ei-osabi
34     ei-pad))
35
36  (define ET-EXEC 2)
37  (define EM-386 3)
38  (define EV-CURRENT 1)
39
40  (define p-filesz (elf32-word 0))
41  (define p-memsz (elf32-word 0))
42  (define PF-X 1)
43  (define PF-W 2)
44  (define PF-R 4)
45  (define p-flags (elf32-word (logior PF-X PF-W PF-R)))
46  (define p-align (elf32-word 1))
47
48  (define (program-header type offset text)
49    (append
50     (elf32-word type)
51     (elf32-off offset)
52     (elf32-addr (+ vaddress offset))
53     (elf32-addr (+ vaddress offset))
54     (elf32-word (length text))
55     (elf32-word (length text))
56     p-flags
57     p-align
58     ))
59
60  (define (section-header name type offset text)
61    (append
62     (elf32-word name)
63     (elf32-word type)
64     (elf32-word 3) ;; write/alloc must for data hmm
65     (elf32-addr (+ vaddress offset))
66     (elf32-off offset) 
67     (elf32-word (length text))
68     (elf32-word 0)
69     (elf32-word 0)
70     (elf32-word 1)
71     (elf32-word 0)))
72
73
74  (define e-type (elf32-half ET-EXEC))
75  (define e-machine (elf32-half EM-386))
76  (define e-version (elf32-word EV-CURRENT))
77  (define e-entry (elf32-addr 0))
78  ;;(define e-entry (elf32-addr (+ vaddress text-offset)))
79  ;;(define e-phoff (elf32-off 0))
80  (define e-shoff (elf32-off 0))
81  (define e-flags (elf32-word 0))
82  ;;(define e-ehsize (elf32-half 0))
83  (define e-phentsize (elf32-half (length (program-header 0 0 '()))))
84  (define e-phnum (elf32-half 1))
85  (define e-shentsize (elf32-half (length (section-header 0 0 0 '()))))
86  (define e-shnum (elf32-half 5))
87  (define e-shstrndx (elf32-half 4))
88
89  (define (elf-header size entry sections)
90    (append
91     e-ident
92     e-type
93     e-machine
94     e-version
95     (elf32-addr (+ vaddress entry)) ;; e-entry
96     (elf32-off size) ;; e-phoff
97     (elf32-off sections) ;; e-shoff
98     e-flags
99     (elf32-half size) ;; e-ehsize
100     e-phentsize
101     e-phnum
102     e-shentsize
103     e-shnum
104     e-shstrndx
105     ))
106
107  (define elf-header-size
108    (length (elf-header 0 0 0)))
109
110  (define program-header-size
111    (length (program-header 0 0 '())))
112
113  (define text-offset
114    (+ elf-header-size program-header-size))
115
116  (define (program-headers)
117    (append
118     (program-header 1 text-offset (text 0))
119     ))
120
121
122  (define note
123    (string->list
124     (string-append
125      "MES"
126      ;;"Mes -- Maxwell Equations of Software\n"
127      ;;"https://gitlab.com/janneke/mes"
128      )
129     ;; #x05 #x00 #x00 #x00 #x00 #x00 #x00 #x00 #x02 #x00 #x00 #x00
130     ;; #\i #\3 #\8 #\6 #x00 #x00 #x00 #x00
131     ))
132
133  (define tab
134    `(
135      #x00 ,@(string->list ".shstrtab")
136           #x00 ,@(string->list ".text")
137           #x00 ,@(string->list ".data")
138           #x00 ,@(string->list ".note")
139           #x00 #x00 #x00 #x00
140           ))
141
142  (define text-length
143    (length (text 0)))
144
145  (define data-offset
146    (+ text-offset text-length))
147
148  (define data-address (+ data-offset vaddress))
149
150  (define data-length
151    (length data))
152
153  (define note-length
154    (length note))
155
156  (define note-offset
157    (+ data-offset data-length))
158
159  (define tab-offset
160    (+ note-offset note-length))
161
162  (define tab-length
163    (length tab))
164
165  (define section-headers-offset
166    (+ tab-offset tab-length))
167
168
169  (define SHT-PROGBITS 1)
170  (define SHT-STRTAB 3)
171  (define SHT-NOTE 7)
172  (define (section-headers)
173    (append
174     (section-header 0 0 0 '())
175     (section-header 11 SHT-PROGBITS text-offset (text 0))
176     (section-header 17 SHT-PROGBITS data-offset data)
177     (section-header 23 SHT-NOTE note-offset note)
178     (section-header 1 SHT-STRTAB tab-offset tab)
179     ))
180
181  (define exe
182    (append
183     (elf-header elf-header-size text-offset section-headers-offset)
184     (program-headers)
185     (text data-address)
186     data
187     note
188     tab
189     (section-headers)
190     ))
191  exe)
192
193 (define (i386:puts data)
194   `(
195      #xba #x0e #x00 #x00 #x00       ;; mov    $0xe,%edx
196           #xb9 ,@(int->bv32 data)        ;; mov    $data,%ecx
197           #xbb #x01 #x00 #x00 #x00       ;; mov    $0x1,%ebx
198           #xb8 #x04 #x00 #x00 #x00       ;; mov    $0x4,%eax
199           #xcd #x80                      ;; int    $0x80
200           ))
201
202 (define (i386:exit code)
203   `(
204     #xbb ,@(int->bv32 code)        ;; mov    $code,%ebx
205          #xb8 #x01 #x00 #x00 #x00       ;; mov    $0x1,%eax
206          #xcd #x80                      ;; int    $0x80
207          ))
208
209 (define (text data)
210   (append
211    (i386:puts data)
212    (i386:exit 0)
213    ))
214
215 (define data
216   (string->list "Hello, world!\n"))
217
218 (define (write-any x) (write-char (if (char? x) x (integer->char x))))
219 (map write-any (make-elf text data))
220