Rev 6613 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7597 | akron1 | 1 | (* |
2 | BSD 2-Clause License |
||
6613 | leency | 3 | |
7597 | akron1 | 4 | Copyright (c) 2019, Anton Krotov |
5 | All rights reserved. |
||
6 | *) |
||
6613 | leency | 7 | |
7597 | akron1 | 8 | MODULE ELF; |
6613 | leency | 9 | |
7597 | akron1 | 10 | IMPORT BIN, WR := WRITER, CHL := CHUNKLISTS; |
6613 | leency | 11 | |
12 | |||
7597 | akron1 | 13 | CONST |
6613 | leency | 14 | |
7597 | akron1 | 15 | EI_NIDENT = 16; |
16 | ET_EXEC = 2; |
||
17 | ET_DYN = 3; |
||
6613 | leency | 18 | |
7597 | akron1 | 19 | EM_386 = 3; |
20 | EM_8664 = 3EH; |
||
6613 | leency | 21 | |
7597 | akron1 | 22 | ELFCLASS32 = 1; |
23 | ELFCLASS64 = 2; |
||
24 | |||
25 | ELFDATA2LSB = 1; |
||
26 | ELFDATA2MSB = 2; |
||
27 | |||
28 | PF_X = 1; |
||
29 | PF_W = 2; |
||
30 | PF_R = 4; |
||
31 | |||
32 | |||
33 | TYPE |
||
34 | |||
35 | Elf32_Ehdr = RECORD |
||
36 | |||
37 | e_ident: ARRAY EI_NIDENT OF BYTE; |
||
38 | |||
39 | e_type, |
||
40 | e_machine: WCHAR; |
||
41 | |||
42 | e_version, |
||
43 | e_entry, |
||
44 | e_phoff, |
||
45 | e_shoff, |
||
46 | e_flags: INTEGER; |
||
47 | |||
48 | e_ehsize, |
||
49 | e_phentsize, |
||
50 | e_phnum, |
||
51 | e_shentsize, |
||
52 | e_shnum, |
||
53 | e_shstrndx: WCHAR |
||
54 | |||
55 | END; |
||
56 | |||
57 | |||
58 | Elf32_Phdr = RECORD |
||
59 | |||
60 | p_type, |
||
61 | p_offset, |
||
62 | p_vaddr, |
||
63 | p_paddr, |
||
64 | p_filesz, |
||
65 | p_memsz, |
||
66 | p_flags, |
||
67 | p_align: INTEGER |
||
68 | |||
69 | END; |
||
70 | |||
71 | FILE = WR.FILE; |
||
72 | |||
73 | |||
74 | PROCEDURE align (n, _align: INTEGER): INTEGER; |
||
6613 | leency | 75 | BEGIN |
7597 | akron1 | 76 | IF n MOD _align # 0 THEN |
77 | n := n + _align - (n MOD _align) |
||
78 | END |
||
6613 | leency | 79 | |
7597 | akron1 | 80 | RETURN n |
81 | END align; |
||
6613 | leency | 82 | |
7597 | akron1 | 83 | |
84 | PROCEDURE Write16 (file: FILE; w: WCHAR); |
||
85 | BEGIN |
||
86 | WR.Write16LE(file, ORD(w)) |
||
87 | END Write16; |
||
88 | |||
89 | |||
90 | PROCEDURE WritePH (file: FILE; ph: Elf32_Phdr); |
||
91 | BEGIN |
||
92 | WR.Write32LE(file, ph.p_type); |
||
93 | WR.Write32LE(file, ph.p_offset); |
||
94 | WR.Write32LE(file, ph.p_vaddr); |
||
95 | WR.Write32LE(file, ph.p_paddr); |
||
96 | WR.Write32LE(file, ph.p_filesz); |
||
97 | WR.Write32LE(file, ph.p_memsz); |
||
98 | WR.Write32LE(file, ph.p_flags); |
||
99 | WR.Write32LE(file, ph.p_align) |
||
100 | END WritePH; |
||
101 | |||
102 | |||
103 | PROCEDURE WritePH64 (file: FILE; ph: Elf32_Phdr); |
||
104 | BEGIN |
||
105 | WR.Write32LE(file, ph.p_type); |
||
106 | WR.Write32LE(file, ph.p_flags); |
||
107 | WR.Write64LE(file, ph.p_offset); |
||
108 | WR.Write64LE(file, ph.p_vaddr); |
||
109 | WR.Write64LE(file, ph.p_paddr); |
||
110 | WR.Write64LE(file, ph.p_filesz); |
||
111 | WR.Write64LE(file, ph.p_memsz); |
||
112 | WR.Write64LE(file, ph.p_align) |
||
113 | END WritePH64; |
||
114 | |||
115 | |||
116 | PROCEDURE fixup (program: BIN.PROGRAM; text, data, bss: INTEGER; amd64: BOOLEAN); |
||
117 | VAR |
||
118 | reloc: BIN.RELOC; |
||
119 | L, delta: INTEGER; |
||
120 | |||
121 | BEGIN |
||
122 | reloc := program.rel_list.first(BIN.RELOC); |
||
123 | WHILE reloc # NIL DO |
||
124 | |||
125 | L := BIN.get32le(program.code, reloc.offset); |
||
126 | delta := 3 - reloc.offset - text - 7 * ORD(amd64); |
||
127 | |||
128 | CASE reloc.opcode OF |
||
129 | |BIN.PICDATA: BIN.put32le(program.code, reloc.offset, L + data + delta) |
||
130 | |BIN.PICCODE: BIN.put32le(program.code, reloc.offset, BIN.GetLabel(program, L) + text + delta) |
||
131 | |BIN.PICBSS: BIN.put32le(program.code, reloc.offset, L + bss + delta) |
||
132 | END; |
||
133 | |||
134 | reloc := reloc.next(BIN.RELOC) |
||
135 | END; |
||
136 | END fixup; |
||
137 | |||
138 | |||
139 | PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; amd64: BOOLEAN); |
||
140 | CONST |
||
141 | interp = 0; |
||
142 | dyn = 1; |
||
143 | header = 2; |
||
144 | text = 3; |
||
145 | data = 4; |
||
146 | bss = 5; |
||
147 | |||
148 | VAR |
||
149 | ehdr: Elf32_Ehdr; |
||
150 | phdr: ARRAY 16 OF Elf32_Phdr; |
||
151 | |||
152 | i, LoadAdr, offset, pad, VA: INTEGER; |
||
153 | |||
154 | SizeOf: RECORD header, code, data, bss: INTEGER END; |
||
155 | |||
156 | File: FILE; |
||
157 | |||
158 | str: ARRAY 40 OF CHAR; lstr: INTEGER; |
||
159 | Dyn: ARRAY 350 OF BYTE; |
||
160 | |||
161 | BEGIN |
||
162 | IF amd64 THEN |
||
163 | str := "/lib64/ld-linux-x86-64.so.2" |
||
164 | ELSE |
||
165 | str := "/lib/ld-linux.so.2" |
||
166 | END; |
||
167 | lstr := LENGTH(str); |
||
168 | |||
169 | IF amd64 THEN |
||
170 | LoadAdr := 400000H |
||
171 | ELSE |
||
172 | LoadAdr := 08048000H |
||
173 | END; |
||
174 | |||
175 | SizeOf.code := CHL.Length(program.code); |
||
176 | SizeOf.data := CHL.Length(program.data); |
||
177 | SizeOf.bss := program.bss; |
||
178 | |||
179 | ehdr.e_ident[0] := 7FH; |
||
180 | ehdr.e_ident[1] := ORD("E"); |
||
181 | ehdr.e_ident[2] := ORD("L"); |
||
182 | ehdr.e_ident[3] := ORD("F"); |
||
183 | IF amd64 THEN |
||
184 | ehdr.e_ident[4] := ELFCLASS64 |
||
185 | ELSE |
||
186 | ehdr.e_ident[4] := ELFCLASS32 |
||
187 | END; |
||
188 | ehdr.e_ident[5] := ELFDATA2LSB; |
||
189 | ehdr.e_ident[6] := 1; |
||
190 | ehdr.e_ident[7] := 3; |
||
191 | FOR i := 8 TO EI_NIDENT - 1 DO |
||
192 | ehdr.e_ident[i] := 0 |
||
193 | END; |
||
194 | |||
195 | ehdr.e_type := WCHR(ET_EXEC); |
||
196 | ehdr.e_version := 1; |
||
197 | ehdr.e_shoff := 0; |
||
198 | ehdr.e_flags := 0; |
||
199 | ehdr.e_shnum := WCHR(0); |
||
200 | ehdr.e_shstrndx := WCHR(0); |
||
201 | ehdr.e_phnum := WCHR(6); |
||
202 | |||
203 | IF amd64 THEN |
||
204 | ehdr.e_machine := WCHR(EM_8664); |
||
205 | ehdr.e_phoff := 40H; |
||
206 | ehdr.e_ehsize := WCHR(40H); |
||
207 | ehdr.e_phentsize := WCHR(38H); |
||
208 | ehdr.e_shentsize := WCHR(40H) |
||
209 | ELSE |
||
210 | ehdr.e_machine := WCHR(EM_386); |
||
211 | ehdr.e_phoff := 34H; |
||
212 | ehdr.e_ehsize := WCHR(34H); |
||
213 | ehdr.e_phentsize := WCHR(20H); |
||
214 | ehdr.e_shentsize := WCHR(28H) |
||
215 | END; |
||
216 | |||
217 | SizeOf.header := ORD(ehdr.e_ehsize) + ORD(ehdr.e_phentsize) * ORD(ehdr.e_phnum); |
||
218 | |||
219 | phdr[interp].p_type := 3; |
||
220 | phdr[interp].p_offset := SizeOf.header; |
||
221 | phdr[interp].p_vaddr := LoadAdr + phdr[interp].p_offset; |
||
222 | phdr[interp].p_paddr := LoadAdr + phdr[interp].p_offset; |
||
223 | phdr[interp].p_filesz := lstr + 1; |
||
224 | phdr[interp].p_memsz := lstr + 1; |
||
225 | phdr[interp].p_flags := PF_R; |
||
226 | phdr[interp].p_align := 1; |
||
227 | |||
228 | phdr[dyn].p_type := 2; |
||
229 | phdr[dyn].p_offset := phdr[interp].p_offset + phdr[interp].p_filesz; |
||
230 | phdr[dyn].p_vaddr := LoadAdr + phdr[dyn].p_offset; |
||
231 | phdr[dyn].p_paddr := LoadAdr + phdr[dyn].p_offset; |
||
232 | IF amd64 THEN |
||
233 | phdr[dyn].p_filesz := 0A0H; |
||
234 | phdr[dyn].p_memsz := 0A0H |
||
235 | ELSE |
||
236 | phdr[dyn].p_filesz := 50H; |
||
237 | phdr[dyn].p_memsz := 50H |
||
238 | END; |
||
239 | phdr[dyn].p_flags := PF_R; |
||
240 | phdr[dyn].p_align := 1; |
||
241 | |||
242 | offset := 0; |
||
243 | |||
244 | phdr[header].p_type := 1; |
||
245 | phdr[header].p_offset := offset; |
||
246 | phdr[header].p_vaddr := LoadAdr; |
||
247 | phdr[header].p_paddr := LoadAdr; |
||
248 | IF amd64 THEN |
||
249 | phdr[header].p_filesz := 305H; |
||
250 | phdr[header].p_memsz := 305H |
||
251 | ELSE |
||
252 | phdr[header].p_filesz := 1D0H; |
||
253 | phdr[header].p_memsz := 1D0H |
||
254 | END; |
||
255 | phdr[header].p_flags := PF_R + PF_W; |
||
256 | phdr[header].p_align := 1000H; |
||
257 | |||
258 | offset := offset + phdr[header].p_filesz; |
||
259 | VA := LoadAdr + offset + 1000H; |
||
260 | |||
261 | phdr[text].p_type := 1; |
||
262 | phdr[text].p_offset := offset; |
||
263 | phdr[text].p_vaddr := VA; |
||
264 | phdr[text].p_paddr := VA; |
||
265 | phdr[text].p_filesz := SizeOf.code; |
||
266 | phdr[text].p_memsz := SizeOf.code; |
||
267 | phdr[text].p_flags := PF_X + PF_R; |
||
268 | phdr[text].p_align := 1000H; |
||
269 | |||
270 | ehdr.e_entry := phdr[text].p_vaddr; |
||
271 | |||
272 | offset := offset + phdr[text].p_filesz; |
||
273 | VA := LoadAdr + offset + 2000H; |
||
274 | pad := (16 - VA MOD 16) MOD 16; |
||
275 | |||
276 | phdr[data].p_type := 1; |
||
277 | phdr[data].p_offset := offset; |
||
278 | phdr[data].p_vaddr := VA; |
||
279 | phdr[data].p_paddr := VA; |
||
280 | phdr[data].p_filesz := SizeOf.data + pad; |
||
281 | phdr[data].p_memsz := SizeOf.data + pad; |
||
282 | phdr[data].p_flags := PF_R + PF_W; |
||
283 | phdr[data].p_align := 1000H; |
||
284 | |||
285 | offset := offset + phdr[data].p_filesz; |
||
286 | VA := LoadAdr + offset + 3000H; |
||
287 | |||
288 | phdr[bss].p_type := 1; |
||
289 | phdr[bss].p_offset := offset; |
||
290 | phdr[bss].p_vaddr := VA; |
||
291 | phdr[bss].p_paddr := VA; |
||
292 | phdr[bss].p_filesz := 0; |
||
293 | phdr[bss].p_memsz := SizeOf.bss + 16; |
||
294 | phdr[bss].p_flags := PF_R + PF_W; |
||
295 | phdr[bss].p_align := 1000H; |
||
296 | |||
297 | fixup(program, phdr[text].p_vaddr, phdr[data].p_vaddr + pad, align(phdr[bss].p_vaddr, 16), amd64); |
||
298 | |||
299 | File := WR.Create(FileName); |
||
300 | |||
301 | FOR i := 0 TO EI_NIDENT - 1 DO |
||
302 | WR.WriteByte(File, ehdr.e_ident[i]) |
||
303 | END; |
||
304 | |||
305 | Write16(File, ehdr.e_type); |
||
306 | Write16(File, ehdr.e_machine); |
||
307 | |||
308 | WR.Write32LE(File, ehdr.e_version); |
||
309 | IF amd64 THEN |
||
310 | WR.Write64LE(File, ehdr.e_entry); |
||
311 | WR.Write64LE(File, ehdr.e_phoff); |
||
312 | WR.Write64LE(File, ehdr.e_shoff) |
||
313 | ELSE |
||
314 | WR.Write32LE(File, ehdr.e_entry); |
||
315 | WR.Write32LE(File, ehdr.e_phoff); |
||
316 | WR.Write32LE(File, ehdr.e_shoff) |
||
317 | END; |
||
318 | WR.Write32LE(File, ehdr.e_flags); |
||
319 | |||
320 | Write16(File, ehdr.e_ehsize); |
||
321 | Write16(File, ehdr.e_phentsize); |
||
322 | Write16(File, ehdr.e_phnum); |
||
323 | Write16(File, ehdr.e_shentsize); |
||
324 | Write16(File, ehdr.e_shnum); |
||
325 | Write16(File, ehdr.e_shstrndx); |
||
326 | |||
327 | IF amd64 THEN |
||
328 | WritePH64(File, phdr[interp]); |
||
329 | WritePH64(File, phdr[dyn]); |
||
330 | WritePH64(File, phdr[header]); |
||
331 | WritePH64(File, phdr[text]); |
||
332 | WritePH64(File, phdr[data]); |
||
333 | WritePH64(File, phdr[bss]) |
||
334 | ELSE |
||
335 | WritePH(File, phdr[interp]); |
||
336 | WritePH(File, phdr[dyn]); |
||
337 | WritePH(File, phdr[header]); |
||
338 | WritePH(File, phdr[text]); |
||
339 | WritePH(File, phdr[data]); |
||
340 | WritePH(File, phdr[bss]) |
||
341 | END; |
||
342 | |||
343 | FOR i := 0 TO lstr DO |
||
344 | WR.WriteByte(File, ORD(str[i])) |
||
345 | END; |
||
346 | |||
347 | i := 0; |
||
348 | IF amd64 THEN |
||
349 | BIN.InitArray(Dyn, i, "01000000000000000E000000000000000500000000000000DC02400000000000"); |
||
350 | BIN.InitArray(Dyn, i, "0A00000000000000190000000000000006000000000000004C02400000000000"); |
||
351 | BIN.InitArray(Dyn, i, "0B00000000000000180000000000000007000000000000009402400000000000"); |
||
352 | BIN.InitArray(Dyn, i, "0800000000000000300000000000000009000000000000001800000000000000"); |
||
353 | BIN.InitArray(Dyn, i, "0400000000000000C40240000000000000000000000000000000000000000000"); |
||
354 | BIN.InitArray(Dyn, i, "0000000000000000000000000000000000000000000000000100000012000000"); |
||
355 | BIN.InitArray(Dyn, i, "0000000000000000000000000000000008000000120000000000000000000000"); |
||
356 | BIN.InitArray(Dyn, i, "0000000000000000F50240000000000001000000010000000000000000000000"); |
||
357 | BIN.InitArray(Dyn, i, "FD02400000000000010000000200000000000000000000000100000003000000"); |
||
358 | BIN.InitArray(Dyn, i, "0000000001000000020000000000000000646C6F70656E00646C73796D006C69"); |
||
359 | BIN.InitArray(Dyn, i, "62646C2E736F2E320000000000000000000000000000000000") |
||
360 | ELSE |
||
361 | BIN.InitArray(Dyn, i, "010000000E00000005000000AF8104080A000000190000000600000057810408"); |
||
362 | BIN.InitArray(Dyn, i, "0B00000010000000110000008781040812000000100000001300000008000000"); |
||
363 | BIN.InitArray(Dyn, i, "0400000097810408000000000000000000000000000000000000000000000000"); |
||
364 | BIN.InitArray(Dyn, i, "0100000000000000000000001200000008000000000000000000000012000000"); |
||
365 | BIN.InitArray(Dyn, i, "C881040801010000CC8104080102000001000000030000000000000001000000"); |
||
366 | BIN.InitArray(Dyn, i, "020000000000000000646C6F70656E00646C73796D006C6962646C2E736F2E32"); |
||
367 | BIN.InitArray(Dyn, i, "000000000000000000") |
||
368 | END; |
||
369 | |||
370 | WR.Write(File, Dyn, i); |
||
371 | |||
372 | CHL.WriteToFile(File, program.code); |
||
373 | WHILE pad > 0 DO |
||
374 | WR.WriteByte(File, 0); |
||
375 | DEC(pad) |
||
376 | END; |
||
377 | CHL.WriteToFile(File, program.data); |
||
378 | WR.Close(File) |
||
379 | END write; |
||
380 | |||
381 | |||
6613 | leency | 382 | END ELF. |