Subversion Repositories Kolibri OS

Rev

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.