Subversion Repositories Kolibri OS

Rev

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