Subversion Repositories Kolibri OS

Rev

Rev 7696 | Rev 8097 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7983 leency 1
(*
7597 akron1 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
 
7693 akron1 10
IMPORT BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS;
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
 
7693 akron1 71
 
72
    Elf32_Dyn = POINTER TO RECORD (LISTS.ITEM)
73
 
74
        d_tag, d_val: INTEGER
75
 
76
    END;
77
 
78
 
79
    Elf32_Sym = POINTER TO RECORD (LISTS.ITEM)
80
 
81
        name, value, size: INTEGER;
82
        info, other: CHAR;
83
        shndx: WCHAR
84
 
85
    END;
86
 
87
 
7597 akron1 88
    FILE = WR.FILE;
89
 
90
 
7693 akron1 91
VAR
92
 
93
    dynamic: LISTS.LIST;
94
    strtab:  CHL.BYTELIST;
95
    symtab:  LISTS.LIST;
96
 
97
    hashtab, bucket, chain: CHL.INTLIST;
98
 
99
 
7597 akron1 100
PROCEDURE align (n, _align: INTEGER): INTEGER;
6613 leency 101
BEGIN
7597 akron1 102
    IF n MOD _align # 0 THEN
103
        n := n + _align - (n MOD _align)
104
    END
6613 leency 105
 
7597 akron1 106
    RETURN n
107
END align;
6613 leency 108
 
7597 akron1 109
 
110
PROCEDURE Write16 (file: FILE; w: WCHAR);
111
BEGIN
112
    WR.Write16LE(file, ORD(w))
113
END Write16;
114
 
115
 
116
PROCEDURE WritePH (file: FILE; ph: Elf32_Phdr);
117
BEGIN
118
    WR.Write32LE(file, ph.p_type);
119
    WR.Write32LE(file, ph.p_offset);
120
    WR.Write32LE(file, ph.p_vaddr);
121
    WR.Write32LE(file, ph.p_paddr);
122
    WR.Write32LE(file, ph.p_filesz);
123
    WR.Write32LE(file, ph.p_memsz);
124
    WR.Write32LE(file, ph.p_flags);
125
    WR.Write32LE(file, ph.p_align)
126
END WritePH;
127
 
128
 
129
PROCEDURE WritePH64 (file: FILE; ph: Elf32_Phdr);
130
BEGIN
131
    WR.Write32LE(file, ph.p_type);
132
    WR.Write32LE(file, ph.p_flags);
133
    WR.Write64LE(file, ph.p_offset);
134
    WR.Write64LE(file, ph.p_vaddr);
135
    WR.Write64LE(file, ph.p_paddr);
136
    WR.Write64LE(file, ph.p_filesz);
137
    WR.Write64LE(file, ph.p_memsz);
138
    WR.Write64LE(file, ph.p_align)
139
END WritePH64;
140
 
141
 
142
PROCEDURE fixup (program: BIN.PROGRAM; text, data, bss: INTEGER; amd64: BOOLEAN);
143
VAR
144
    reloc: BIN.RELOC;
7983 leency 145
    code:  CHL.BYTELIST;
146
    L, delta, delta0: INTEGER;
7597 akron1 147
 
148
BEGIN
7983 leency 149
    code := program.code;
150
    delta0 := 3 - 7 * ORD(amd64);
7597 akron1 151
    reloc := program.rel_list.first(BIN.RELOC);
7983 leency 152
 
7597 akron1 153
    WHILE reloc # NIL DO
154
 
7983 leency 155
        L := BIN.get32le(code, reloc.offset);
156
        delta := delta0 - reloc.offset - text;
7597 akron1 157
 
158
        CASE reloc.opcode OF
7983 leency 159
        |BIN.PICDATA: BIN.put32le(code, reloc.offset, L + data + delta)
160
        |BIN.PICCODE: BIN.put32le(code, reloc.offset, BIN.GetLabel(program, L) + text + delta)
161
        |BIN.PICBSS:  BIN.put32le(code, reloc.offset, L + bss + delta)
7597 akron1 162
        END;
163
 
164
        reloc := reloc.next(BIN.RELOC)
7983 leency 165
    END
7597 akron1 166
END fixup;
167
 
168
 
7693 akron1 169
PROCEDURE NewDyn (tag, val: INTEGER);
170
VAR
171
    dyn: Elf32_Dyn;
172
 
173
BEGIN
174
    NEW(dyn);
175
    dyn.d_tag := tag;
176
    dyn.d_val := val;
177
    LISTS.push(dynamic, dyn)
178
END NewDyn;
179
 
180
 
181
PROCEDURE NewSym (name, value, size: INTEGER; info, other: CHAR; shndx: WCHAR);
182
VAR
183
    sym: Elf32_Sym;
184
 
185
BEGIN
186
    NEW(sym);
187
    sym.name := name;
188
    sym.value := value;
189
    sym.size := size;
190
    sym.info := info;
191
    sym.other := other;
192
    sym.shndx := shndx;
193
 
194
    LISTS.push(symtab, sym)
195
END NewSym;
196
 
197
 
198
PROCEDURE HashStr (name: ARRAY OF CHAR): INTEGER;
199
VAR
200
    i, h: INTEGER;
201
    g: SET;
202
 
203
BEGIN
204
    h := 0;
205
    i := 0;
206
    WHILE name[i] # 0X DO
207
        h := h * 16 + ORD(name[i]);
208
        g := BITS(h) * {28..31};
209
        h := ORD(BITS(h) / BITS(LSR(ORD(g), 24)) - g);
210
        INC(i)
211
    END
212
 
213
    RETURN h
214
END HashStr;
215
 
216
 
217
PROCEDURE MakeHash (bucket, chain: CHL.INTLIST; symCount: INTEGER);
218
VAR
219
    symi, hi, k: INTEGER;
220
 
221
BEGIN
222
    FOR symi := 0 TO symCount - 1 DO
223
        CHL.SetInt(chain, symi, 0);
224
        hi := CHL.GetInt(hashtab, symi) MOD symCount;
225
        IF CHL.GetInt(bucket, hi) # 0 THEN
226
            k := symi;
227
            WHILE CHL.GetInt(chain, k) # 0 DO
228
                k := CHL.GetInt(chain, k)
229
            END;
230
            CHL.SetInt(chain, k, CHL.GetInt(bucket, hi))
231
        END;
232
        CHL.SetInt(bucket, hi, symi)
233
    END
234
END MakeHash;
235
 
236
 
237
PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; fini: INTEGER; so, amd64: BOOLEAN);
7597 akron1 238
CONST
239
    interp  =  0;
240
    dyn     =  1;
241
    header  =  2;
242
    text    =  3;
243
    data    =  4;
244
    bss     =  5;
245
 
7693 akron1 246
    linuxInterpreter64 = "/lib64/ld-linux-x86-64.so.2";
247
    linuxInterpreter32 = "/lib/ld-linux.so.2";
248
 
249
    exeBaseAddress32 = 8048000H;
250
    exeBaseAddress64 = 400000H;
251
    dllBaseAddress = 0;
252
 
253
    DT_NULL = 0;
254
    DT_NEEDED = 1;
255
    DT_HASH = 4;
256
    DT_STRTAB = 5;
257
    DT_SYMTAB = 6;
258
    DT_RELA = 7;
259
    DT_RELASZ = 8;
260
    DT_RELAENT = 9;
261
    DT_STRSZ = 10;
262
    DT_SYMENT = 11;
263
    DT_INIT = 12;
264
    DT_FINI = 13;
265
    DT_SONAME = 14;
266
    DT_REL = 17;
267
    DT_RELSZ = 18;
268
    DT_RELENT = 19;
269
 
7597 akron1 270
VAR
271
    ehdr: Elf32_Ehdr;
272
    phdr: ARRAY 16 OF Elf32_Phdr;
273
 
7693 akron1 274
    i, BaseAdr, offset, pad, VA, symCount: INTEGER;
7597 akron1 275
 
276
    SizeOf: RECORD header, code, data, bss: INTEGER END;
277
 
7693 akron1 278
    Offset: RECORD symtab, reltab, hash, strtab, dyn: INTEGER END;
279
 
7597 akron1 280
    File: FILE;
281
 
7693 akron1 282
    Interpreter: ARRAY 40 OF CHAR; lenInterpreter: INTEGER;
7597 akron1 283
 
7693 akron1 284
    item: LISTS.ITEM;
285
 
286
    Name: ARRAY 2048 OF CHAR;
287
 
7597 akron1 288
BEGIN
7693 akron1 289
    dynamic := LISTS.create(NIL);
290
    symtab  := LISTS.create(NIL);
291
    strtab  := CHL.CreateByteList();
292
 
7597 akron1 293
    IF amd64 THEN
7693 akron1 294
        BaseAdr := exeBaseAddress64;
295
        Interpreter := linuxInterpreter64
7597 akron1 296
    ELSE
7693 akron1 297
        BaseAdr := exeBaseAddress32;
298
        Interpreter := linuxInterpreter32
7597 akron1 299
    END;
300
 
7693 akron1 301
    IF so THEN
302
        BaseAdr := dllBaseAddress
7597 akron1 303
    END;
304
 
7693 akron1 305
    lenInterpreter := LENGTH(Interpreter) + 1;
306
 
7597 akron1 307
    SizeOf.code := CHL.Length(program.code);
308
    SizeOf.data := CHL.Length(program.data);
309
    SizeOf.bss  := program.bss;
310
 
311
    ehdr.e_ident[0] := 7FH;
312
    ehdr.e_ident[1] := ORD("E");
313
    ehdr.e_ident[2] := ORD("L");
314
    ehdr.e_ident[3] := ORD("F");
315
    IF amd64 THEN
316
        ehdr.e_ident[4] := ELFCLASS64
317
    ELSE
318
        ehdr.e_ident[4] := ELFCLASS32
319
    END;
320
    ehdr.e_ident[5] := ELFDATA2LSB;
321
    ehdr.e_ident[6] := 1;
322
    ehdr.e_ident[7] := 3;
323
    FOR i := 8 TO EI_NIDENT - 1 DO
324
        ehdr.e_ident[i] := 0
325
    END;
326
 
7693 akron1 327
    IF so THEN
328
        ehdr.e_type := WCHR(ET_DYN)
329
    ELSE
330
        ehdr.e_type := WCHR(ET_EXEC)
331
    END;
332
 
7597 akron1 333
    ehdr.e_version := 1;
334
    ehdr.e_shoff := 0;
335
    ehdr.e_flags := 0;
336
    ehdr.e_shnum := WCHR(0);
337
    ehdr.e_shstrndx := WCHR(0);
338
    ehdr.e_phnum := WCHR(6);
339
 
340
    IF amd64 THEN
341
        ehdr.e_machine := WCHR(EM_8664);
342
        ehdr.e_phoff := 40H;
343
        ehdr.e_ehsize := WCHR(40H);
344
        ehdr.e_phentsize := WCHR(38H);
345
        ehdr.e_shentsize := WCHR(40H)
346
    ELSE
347
        ehdr.e_machine := WCHR(EM_386);
348
        ehdr.e_phoff := 34H;
349
        ehdr.e_ehsize := WCHR(34H);
350
        ehdr.e_phentsize := WCHR(20H);
351
        ehdr.e_shentsize := WCHR(28H)
352
    END;
353
 
354
    SizeOf.header := ORD(ehdr.e_ehsize) + ORD(ehdr.e_phentsize) * ORD(ehdr.e_phnum);
355
 
356
    phdr[interp].p_type := 3;
357
    phdr[interp].p_offset := SizeOf.header;
7693 akron1 358
    phdr[interp].p_vaddr := BaseAdr + phdr[interp].p_offset;
359
    phdr[interp].p_paddr := phdr[interp].p_vaddr;
360
    phdr[interp].p_filesz := lenInterpreter;
361
    phdr[interp].p_memsz := lenInterpreter;
7597 akron1 362
    phdr[interp].p_flags := PF_R;
363
    phdr[interp].p_align := 1;
364
 
365
    phdr[dyn].p_type := 2;
366
    phdr[dyn].p_offset := phdr[interp].p_offset + phdr[interp].p_filesz;
7693 akron1 367
    phdr[dyn].p_vaddr := BaseAdr + phdr[dyn].p_offset;
368
    phdr[dyn].p_paddr := phdr[dyn].p_vaddr;
369
 
370
    hashtab := CHL.CreateIntList();
371
 
372
    CHL.PushInt(hashtab, HashStr(""));
373
    NewSym(CHL.PushStr(strtab, ""), 0, 0, 0X, 0X, 0X);
374
    CHL.PushInt(hashtab, HashStr("dlopen"));
375
    NewSym(CHL.PushStr(strtab, "dlopen"), 0, 0, 12X, 0X, 0X);
376
    CHL.PushInt(hashtab, HashStr("dlsym"));
377
    NewSym(CHL.PushStr(strtab, "dlsym"), 0, 0, 12X, 0X, 0X);
378
 
379
    IF so THEN
380
        item := program.exp_list.first;
381
        WHILE item # NIL DO
382
            ASSERT(CHL.GetStr(program.export, item(BIN.EXPRT).nameoffs, Name));
383
            CHL.PushInt(hashtab, HashStr(Name));
384
            NewSym(CHL.PushStr(strtab, Name), item(BIN.EXPRT).label, 0, 12X, 0X, 0X);
385
            item := item.next
386
        END;
387
        ASSERT(CHL.GetStr(program.data, program.modname, Name))
388
    END;
389
 
390
    symCount := LISTS.count(symtab);
391
 
392
    bucket  := CHL.CreateIntList();
393
    chain   := CHL.CreateIntList();
394
 
395
    FOR i := 1 TO symCount DO
396
        CHL.PushInt(bucket, 0);
397
        CHL.PushInt(chain, 0)
398
    END;
399
 
400
    MakeHash(bucket, chain, symCount);
401
 
402
    NewDyn(DT_NEEDED, CHL.PushStr(strtab, "libdl.so.2"));
403
    NewDyn(DT_STRTAB, 0);
404
    NewDyn(DT_STRSZ, CHL.Length(strtab));
405
    NewDyn(DT_SYMTAB, 0);
406
 
7597 akron1 407
    IF amd64 THEN
7693 akron1 408
        NewDyn(DT_SYMENT, 24);
409
        NewDyn(DT_RELA, 0);
410
        NewDyn(DT_RELASZ, 48);
411
        NewDyn(DT_RELAENT, 24)
7597 akron1 412
    ELSE
7693 akron1 413
        NewDyn(DT_SYMENT, 16);
414
        NewDyn(DT_REL, 0);
415
        NewDyn(DT_RELSZ, 16);
416
        NewDyn(DT_RELENT, 8)
7597 akron1 417
    END;
7693 akron1 418
 
419
    NewDyn(DT_HASH, 0);
420
 
421
    IF so THEN
422
        NewDyn(DT_SONAME, CHL.PushStr(strtab, Name));
423
        NewDyn(DT_INIT, 0);
424
        NewDyn(DT_FINI, 0)
425
    END;
426
 
427
    NewDyn(DT_NULL, 0);
428
 
429
    Offset.symtab := LISTS.count(dynamic) * (8 + 8 * ORD(amd64));
430
    Offset.reltab := Offset.symtab + symCount * (16 + 8 * ORD(amd64));
431
    Offset.hash   := Offset.reltab + (8 + 16 * ORD(amd64)) * 2;
432
    Offset.strtab := Offset.hash + (symCount * 2 + 2) * 4;
433
 
434
    Offset.dyn := phdr[dyn].p_offset;
435
 
436
    item := LISTS.getidx(dynamic, 1); item(Elf32_Dyn).d_val := Offset.strtab + Offset.dyn + BaseAdr;
437
    item := LISTS.getidx(dynamic, 3); item(Elf32_Dyn).d_val := Offset.symtab + Offset.dyn + BaseAdr;
438
    item := LISTS.getidx(dynamic, 5); item(Elf32_Dyn).d_val := Offset.reltab + Offset.dyn + BaseAdr;
439
    item := LISTS.getidx(dynamic, 8); item(Elf32_Dyn).d_val := Offset.hash   + Offset.dyn + BaseAdr;
440
 
441
    phdr[dyn].p_filesz := Offset.strtab + CHL.Length(strtab) + 8 + 8 * ORD(amd64);
442
    phdr[dyn].p_memsz  := phdr[dyn].p_filesz;
443
 
7597 akron1 444
    phdr[dyn].p_flags := PF_R;
445
    phdr[dyn].p_align := 1;
446
 
447
    offset := 0;
448
 
449
    phdr[header].p_type := 1;
450
    phdr[header].p_offset := offset;
7693 akron1 451
    phdr[header].p_vaddr := BaseAdr;
452
    phdr[header].p_paddr := BaseAdr;
453
    phdr[header].p_filesz := 244 + 156 * ORD(amd64) + lenInterpreter + phdr[dyn].p_filesz;
454
    phdr[header].p_memsz  := phdr[header].p_filesz;
7597 akron1 455
    phdr[header].p_flags := PF_R + PF_W;
456
    phdr[header].p_align := 1000H;
7693 akron1 457
 
7597 akron1 458
    offset := offset + phdr[header].p_filesz;
7693 akron1 459
    VA := BaseAdr + offset + 1000H;
7597 akron1 460
 
461
    phdr[text].p_type := 1;
462
    phdr[text].p_offset := offset;
463
    phdr[text].p_vaddr := VA;
464
    phdr[text].p_paddr := VA;
465
    phdr[text].p_filesz := SizeOf.code;
466
    phdr[text].p_memsz := SizeOf.code;
467
    phdr[text].p_flags := PF_X + PF_R;
468
    phdr[text].p_align := 1000H;
469
 
470
    ehdr.e_entry := phdr[text].p_vaddr;
7693 akron1 471
 
7597 akron1 472
    offset := offset + phdr[text].p_filesz;
7693 akron1 473
    VA := BaseAdr + offset + 2000H;
7597 akron1 474
    pad := (16 - VA MOD 16) MOD 16;
475
 
476
    phdr[data].p_type := 1;
477
    phdr[data].p_offset := offset;
478
    phdr[data].p_vaddr := VA;
479
    phdr[data].p_paddr := VA;
480
    phdr[data].p_filesz := SizeOf.data + pad;
481
    phdr[data].p_memsz := SizeOf.data + pad;
482
    phdr[data].p_flags := PF_R + PF_W;
483
    phdr[data].p_align := 1000H;
7693 akron1 484
 
7597 akron1 485
    offset := offset + phdr[data].p_filesz;
7693 akron1 486
    VA := BaseAdr + offset + 3000H;
7597 akron1 487
 
488
    phdr[bss].p_type := 1;
489
    phdr[bss].p_offset := offset;
490
    phdr[bss].p_vaddr := VA;
491
    phdr[bss].p_paddr := VA;
492
    phdr[bss].p_filesz := 0;
493
    phdr[bss].p_memsz := SizeOf.bss + 16;
494
    phdr[bss].p_flags := PF_R + PF_W;
495
    phdr[bss].p_align := 1000H;
496
 
7693 akron1 497
    fixup(program, ehdr.e_entry, phdr[data].p_vaddr + pad, align(phdr[bss].p_vaddr, 16), amd64);
7597 akron1 498
 
7693 akron1 499
    item := symtab.first;
500
    WHILE item # NIL DO
501
        IF item(Elf32_Sym).value # 0 THEN
502
            INC(item(Elf32_Sym).value, ehdr.e_entry)
503
        END;
504
        item := item.next
505
    END;
506
 
507
    IF so THEN
508
        item := LISTS.getidx(dynamic, 10); item(Elf32_Dyn).d_val := ehdr.e_entry;
509
        item := LISTS.getidx(dynamic, 11); item(Elf32_Dyn).d_val := BIN.GetLabel(program, fini) + ehdr.e_entry
510
    END;
511
 
7597 akron1 512
    File := WR.Create(FileName);
513
 
514
    FOR i := 0 TO EI_NIDENT - 1 DO
515
        WR.WriteByte(File, ehdr.e_ident[i])
516
    END;
517
 
518
    Write16(File, ehdr.e_type);
519
    Write16(File, ehdr.e_machine);
520
 
521
    WR.Write32LE(File, ehdr.e_version);
522
    IF amd64 THEN
523
        WR.Write64LE(File, ehdr.e_entry);
524
        WR.Write64LE(File, ehdr.e_phoff);
525
        WR.Write64LE(File, ehdr.e_shoff)
526
    ELSE
527
        WR.Write32LE(File, ehdr.e_entry);
528
        WR.Write32LE(File, ehdr.e_phoff);
529
        WR.Write32LE(File, ehdr.e_shoff)
530
    END;
531
    WR.Write32LE(File, ehdr.e_flags);
532
 
533
    Write16(File, ehdr.e_ehsize);
534
    Write16(File, ehdr.e_phentsize);
535
    Write16(File, ehdr.e_phnum);
536
    Write16(File, ehdr.e_shentsize);
537
    Write16(File, ehdr.e_shnum);
538
    Write16(File, ehdr.e_shstrndx);
539
 
540
    IF amd64 THEN
541
        WritePH64(File, phdr[interp]);
542
        WritePH64(File, phdr[dyn]);
543
        WritePH64(File, phdr[header]);
544
        WritePH64(File, phdr[text]);
545
        WritePH64(File, phdr[data]);
546
        WritePH64(File, phdr[bss])
547
    ELSE
548
        WritePH(File, phdr[interp]);
549
        WritePH(File, phdr[dyn]);
550
        WritePH(File, phdr[header]);
551
        WritePH(File, phdr[text]);
552
        WritePH(File, phdr[data]);
553
        WritePH(File, phdr[bss])
554
    END;
555
 
7693 akron1 556
    FOR i := 0 TO lenInterpreter - 1 DO
557
        WR.WriteByte(File, ORD(Interpreter[i]))
7597 akron1 558
    END;
559
 
560
    i := 0;
561
    IF amd64 THEN
7693 akron1 562
        item := dynamic.first;
563
        WHILE item # NIL DO
564
            WR.Write64LE(File, item(Elf32_Dyn).d_tag);
565
            WR.Write64LE(File, item(Elf32_Dyn).d_val);
566
            item := item.next
567
        END;
568
 
569
        item := symtab.first;
570
        WHILE item # NIL DO
571
            WR.Write32LE(File, item(Elf32_Sym).name);
572
            WR.WriteByte(File, ORD(item(Elf32_Sym).info));
573
            WR.WriteByte(File, ORD(item(Elf32_Sym).other));
574
            Write16(File, item(Elf32_Sym).shndx);
575
            WR.Write64LE(File, item(Elf32_Sym).value);
576
            WR.Write64LE(File, item(Elf32_Sym).size);
577
            item := item.next
578
        END;
579
 
580
        WR.Write64LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 16);
581
        WR.Write32LE(File, 1);
582
        WR.Write32LE(File, 1);
583
        WR.Write64LE(File, 0);
584
        WR.Write64LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 8);
585
        WR.Write32LE(File, 1);
586
        WR.Write32LE(File, 2);
587
        WR.Write64LE(File, 0);
588
 
589
        WR.Write32LE(File, symCount);
590
        WR.Write32LE(File, symCount);
591
 
592
        FOR i := 0 TO symCount - 1 DO
593
            WR.Write32LE(File, CHL.GetInt(bucket, i))
594
        END;
595
 
596
        FOR i := 0 TO symCount - 1 DO
597
            WR.Write32LE(File, CHL.GetInt(chain, i))
598
        END;
599
 
600
        CHL.WriteToFile(File, strtab);
601
        WR.Write64LE(File, 0);
602
        WR.Write64LE(File, 0)
603
 
7597 akron1 604
    ELSE
7693 akron1 605
        item := dynamic.first;
606
        WHILE item # NIL DO
607
            WR.Write32LE(File, item(Elf32_Dyn).d_tag);
608
            WR.Write32LE(File, item(Elf32_Dyn).d_val);
609
            item := item.next
610
        END;
611
 
612
        item := symtab.first;
613
        WHILE item # NIL DO
614
            WR.Write32LE(File, item(Elf32_Sym).name);
615
            WR.Write32LE(File, item(Elf32_Sym).value);
616
            WR.Write32LE(File, item(Elf32_Sym).size);
617
            WR.WriteByte(File, ORD(item(Elf32_Sym).info));
618
            WR.WriteByte(File, ORD(item(Elf32_Sym).other));
619
            Write16(File, item(Elf32_Sym).shndx);
620
            item := item.next
621
        END;
622
 
623
        WR.Write32LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 8);
624
        WR.Write32LE(File, 00000101H);
625
        WR.Write32LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 4);
626
        WR.Write32LE(File, 00000201H);
627
 
628
        WR.Write32LE(File, symCount);
629
        WR.Write32LE(File, symCount);
630
 
631
        FOR i := 0 TO symCount - 1 DO
632
            WR.Write32LE(File, CHL.GetInt(bucket, i))
633
        END;
634
 
635
        FOR i := 0 TO symCount - 1 DO
636
            WR.Write32LE(File, CHL.GetInt(chain, i))
637
        END;
638
 
639
        CHL.WriteToFile(File, strtab);
640
        WR.Write32LE(File, 0);
641
        WR.Write32LE(File, 0)
642
 
7597 akron1 643
    END;
644
 
645
    CHL.WriteToFile(File, program.code);
646
    WHILE pad > 0 DO
647
        WR.WriteByte(File, 0);
648
        DEC(pad)
649
    END;
650
    CHL.WriteToFile(File, program.data);
651
    WR.Close(File)
652
END write;
653
 
654
 
7983 leency 655
END ELF.