1,13 → 1,13 |
(* |
BSD 2-Clause License |
|
Copyright (c) 2019, Anton Krotov |
Copyright (c) 2019-2020, Anton Krotov |
All rights reserved. |
*) |
|
MODULE ELF; |
|
IMPORT BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS; |
IMPORT BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS, PE32, UTILS; |
|
|
CONST |
85,9 → 85,6 |
END; |
|
|
FILE = WR.FILE; |
|
|
VAR |
|
dynamic: LISTS.LIST; |
97,75 → 94,38 |
hashtab, bucket, chain: CHL.INTLIST; |
|
|
PROCEDURE align (n, _align: INTEGER): INTEGER; |
PROCEDURE Write16 (w: WCHAR); |
BEGIN |
IF n MOD _align # 0 THEN |
n := n + _align - (n MOD _align) |
END |
|
RETURN n |
END align; |
|
|
PROCEDURE Write16 (file: FILE; w: WCHAR); |
BEGIN |
WR.Write16LE(file, ORD(w)) |
WR.Write16LE(ORD(w)) |
END Write16; |
|
|
PROCEDURE WritePH (file: FILE; ph: Elf32_Phdr); |
PROCEDURE WritePH (ph: Elf32_Phdr); |
BEGIN |
WR.Write32LE(file, ph.p_type); |
WR.Write32LE(file, ph.p_offset); |
WR.Write32LE(file, ph.p_vaddr); |
WR.Write32LE(file, ph.p_paddr); |
WR.Write32LE(file, ph.p_filesz); |
WR.Write32LE(file, ph.p_memsz); |
WR.Write32LE(file, ph.p_flags); |
WR.Write32LE(file, ph.p_align) |
WR.Write32LE(ph.p_type); |
WR.Write32LE(ph.p_offset); |
WR.Write32LE(ph.p_vaddr); |
WR.Write32LE(ph.p_paddr); |
WR.Write32LE(ph.p_filesz); |
WR.Write32LE(ph.p_memsz); |
WR.Write32LE(ph.p_flags); |
WR.Write32LE(ph.p_align) |
END WritePH; |
|
|
PROCEDURE WritePH64 (file: FILE; ph: Elf32_Phdr); |
PROCEDURE WritePH64 (ph: Elf32_Phdr); |
BEGIN |
WR.Write32LE(file, ph.p_type); |
WR.Write32LE(file, ph.p_flags); |
WR.Write64LE(file, ph.p_offset); |
WR.Write64LE(file, ph.p_vaddr); |
WR.Write64LE(file, ph.p_paddr); |
WR.Write64LE(file, ph.p_filesz); |
WR.Write64LE(file, ph.p_memsz); |
WR.Write64LE(file, ph.p_align) |
WR.Write32LE(ph.p_type); |
WR.Write32LE(ph.p_flags); |
WR.Write64LE(ph.p_offset); |
WR.Write64LE(ph.p_vaddr); |
WR.Write64LE(ph.p_paddr); |
WR.Write64LE(ph.p_filesz); |
WR.Write64LE(ph.p_memsz); |
WR.Write64LE(ph.p_align) |
END WritePH64; |
|
|
PROCEDURE fixup (program: BIN.PROGRAM; text, data, bss: INTEGER; amd64: BOOLEAN); |
VAR |
reloc: BIN.RELOC; |
code: CHL.BYTELIST; |
L, delta, delta0: INTEGER; |
|
BEGIN |
code := program.code; |
delta0 := 3 - 7 * ORD(amd64); |
reloc := program.rel_list.first(BIN.RELOC); |
|
WHILE reloc # NIL DO |
|
L := BIN.get32le(code, reloc.offset); |
delta := delta0 - reloc.offset - text; |
|
CASE reloc.opcode OF |
|BIN.PICDATA: BIN.put32le(code, reloc.offset, L + data + delta) |
|BIN.PICCODE: BIN.put32le(code, reloc.offset, BIN.GetLabel(program, L) + text + delta) |
|BIN.PICBSS: BIN.put32le(code, reloc.offset, L + bss + delta) |
END; |
|
reloc := reloc.next(BIN.RELOC) |
END |
END fixup; |
|
|
PROCEDURE NewDyn (tag, val: INTEGER); |
VAR |
dyn: Elf32_Dyn; |
271,14 → 231,12 |
ehdr: Elf32_Ehdr; |
phdr: ARRAY 16 OF Elf32_Phdr; |
|
i, BaseAdr, offset, pad, VA, symCount: INTEGER; |
i, BaseAdr, DynAdr, offset, pad, VA, symCount: INTEGER; |
|
SizeOf: RECORD header, code, data, bss: INTEGER END; |
|
Offset: RECORD symtab, reltab, hash, strtab, dyn: INTEGER END; |
Offset: RECORD symtab, reltab, hash, strtab: INTEGER END; |
|
File: FILE; |
|
Interpreter: ARRAY 40 OF CHAR; lenInterpreter: INTEGER; |
|
item: LISTS.ITEM; |
285,6 → 243,8 |
|
Name: ARRAY 2048 OF CHAR; |
|
Address: PE32.VIRTUAL_ADDR; |
|
BEGIN |
dynamic := LISTS.create(NIL); |
symtab := LISTS.create(NIL); |
431,12 → 391,12 |
Offset.hash := Offset.reltab + (8 + 16 * ORD(amd64)) * 2; |
Offset.strtab := Offset.hash + (symCount * 2 + 2) * 4; |
|
Offset.dyn := phdr[dyn].p_offset; |
DynAdr := phdr[dyn].p_offset + BaseAdr; |
|
item := LISTS.getidx(dynamic, 1); item(Elf32_Dyn).d_val := Offset.strtab + Offset.dyn + BaseAdr; |
item := LISTS.getidx(dynamic, 3); item(Elf32_Dyn).d_val := Offset.symtab + Offset.dyn + BaseAdr; |
item := LISTS.getidx(dynamic, 5); item(Elf32_Dyn).d_val := Offset.reltab + Offset.dyn + BaseAdr; |
item := LISTS.getidx(dynamic, 8); item(Elf32_Dyn).d_val := Offset.hash + Offset.dyn + BaseAdr; |
item := LISTS.getidx(dynamic, 1); item(Elf32_Dyn).d_val := Offset.strtab + DynAdr; |
item := LISTS.getidx(dynamic, 3); item(Elf32_Dyn).d_val := Offset.symtab + DynAdr; |
item := LISTS.getidx(dynamic, 5); item(Elf32_Dyn).d_val := Offset.reltab + DynAdr; |
item := LISTS.getidx(dynamic, 8); item(Elf32_Dyn).d_val := Offset.hash + DynAdr; |
|
phdr[dyn].p_filesz := Offset.strtab + CHL.Length(strtab) + 8 + 8 * ORD(amd64); |
phdr[dyn].p_memsz := phdr[dyn].p_filesz; |
450,12 → 410,12 |
phdr[header].p_offset := offset; |
phdr[header].p_vaddr := BaseAdr; |
phdr[header].p_paddr := BaseAdr; |
phdr[header].p_filesz := 244 + 156 * ORD(amd64) + lenInterpreter + phdr[dyn].p_filesz; |
phdr[header].p_filesz := SizeOf.header + lenInterpreter + phdr[dyn].p_filesz; |
phdr[header].p_memsz := phdr[header].p_filesz; |
phdr[header].p_flags := PF_R + PF_W; |
phdr[header].p_align := 1000H; |
|
offset := offset + phdr[header].p_filesz; |
INC(offset, phdr[header].p_filesz); |
VA := BaseAdr + offset + 1000H; |
|
phdr[text].p_type := 1; |
469,7 → 429,7 |
|
ehdr.e_entry := phdr[text].p_vaddr; |
|
offset := offset + phdr[text].p_filesz; |
INC(offset, phdr[text].p_filesz); |
VA := BaseAdr + offset + 2000H; |
pad := (16 - VA MOD 16) MOD 16; |
|
482,7 → 442,7 |
phdr[data].p_flags := PF_R + PF_W; |
phdr[data].p_align := 1000H; |
|
offset := offset + phdr[data].p_filesz; |
INC(offset, phdr[data].p_filesz); |
VA := BaseAdr + offset + 3000H; |
|
phdr[bss].p_type := 1; |
494,8 → 454,13 |
phdr[bss].p_flags := PF_R + PF_W; |
phdr[bss].p_align := 1000H; |
|
fixup(program, ehdr.e_entry, phdr[data].p_vaddr + pad, align(phdr[bss].p_vaddr, 16), amd64); |
Address.Code := ehdr.e_entry; |
Address.Data := phdr[data].p_vaddr + pad; |
Address.Bss := WR.align(phdr[bss].p_vaddr, 16); |
Address.Import := 0; |
|
PE32.fixup(program, Address, amd64); |
|
item := symtab.first; |
WHILE item # NIL DO |
IF item(Elf32_Sym).value # 0 THEN |
509,146 → 474,137 |
item := LISTS.getidx(dynamic, 11); item(Elf32_Dyn).d_val := BIN.GetLabel(program, fini) + ehdr.e_entry |
END; |
|
File := WR.Create(FileName); |
WR.Create(FileName); |
|
FOR i := 0 TO EI_NIDENT - 1 DO |
WR.WriteByte(File, ehdr.e_ident[i]) |
WR.WriteByte(ehdr.e_ident[i]) |
END; |
|
Write16(File, ehdr.e_type); |
Write16(File, ehdr.e_machine); |
Write16(ehdr.e_type); |
Write16(ehdr.e_machine); |
|
WR.Write32LE(File, ehdr.e_version); |
WR.Write32LE(ehdr.e_version); |
IF amd64 THEN |
WR.Write64LE(File, ehdr.e_entry); |
WR.Write64LE(File, ehdr.e_phoff); |
WR.Write64LE(File, ehdr.e_shoff) |
WR.Write64LE(ehdr.e_entry); |
WR.Write64LE(ehdr.e_phoff); |
WR.Write64LE(ehdr.e_shoff) |
ELSE |
WR.Write32LE(File, ehdr.e_entry); |
WR.Write32LE(File, ehdr.e_phoff); |
WR.Write32LE(File, ehdr.e_shoff) |
WR.Write32LE(ehdr.e_entry); |
WR.Write32LE(ehdr.e_phoff); |
WR.Write32LE(ehdr.e_shoff) |
END; |
WR.Write32LE(File, ehdr.e_flags); |
WR.Write32LE(ehdr.e_flags); |
|
Write16(File, ehdr.e_ehsize); |
Write16(File, ehdr.e_phentsize); |
Write16(File, ehdr.e_phnum); |
Write16(File, ehdr.e_shentsize); |
Write16(File, ehdr.e_shnum); |
Write16(File, ehdr.e_shstrndx); |
Write16(ehdr.e_ehsize); |
Write16(ehdr.e_phentsize); |
Write16(ehdr.e_phnum); |
Write16(ehdr.e_shentsize); |
Write16(ehdr.e_shnum); |
Write16(ehdr.e_shstrndx); |
|
IF amd64 THEN |
WritePH64(File, phdr[interp]); |
WritePH64(File, phdr[dyn]); |
WritePH64(File, phdr[header]); |
WritePH64(File, phdr[text]); |
WritePH64(File, phdr[data]); |
WritePH64(File, phdr[bss]) |
WritePH64(phdr[interp]); |
WritePH64(phdr[dyn]); |
WritePH64(phdr[header]); |
WritePH64(phdr[text]); |
WritePH64(phdr[data]); |
WritePH64(phdr[bss]) |
ELSE |
WritePH(File, phdr[interp]); |
WritePH(File, phdr[dyn]); |
WritePH(File, phdr[header]); |
WritePH(File, phdr[text]); |
WritePH(File, phdr[data]); |
WritePH(File, phdr[bss]) |
WritePH(phdr[interp]); |
WritePH(phdr[dyn]); |
WritePH(phdr[header]); |
WritePH(phdr[text]); |
WritePH(phdr[data]); |
WritePH(phdr[bss]) |
END; |
|
FOR i := 0 TO lenInterpreter - 1 DO |
WR.WriteByte(File, ORD(Interpreter[i])) |
WR.WriteByte(ORD(Interpreter[i])) |
END; |
|
i := 0; |
IF amd64 THEN |
item := dynamic.first; |
WHILE item # NIL DO |
WR.Write64LE(File, item(Elf32_Dyn).d_tag); |
WR.Write64LE(File, item(Elf32_Dyn).d_val); |
WR.Write64LE(item(Elf32_Dyn).d_tag); |
WR.Write64LE(item(Elf32_Dyn).d_val); |
item := item.next |
END; |
|
item := symtab.first; |
WHILE item # NIL DO |
WR.Write32LE(File, item(Elf32_Sym).name); |
WR.WriteByte(File, ORD(item(Elf32_Sym).info)); |
WR.WriteByte(File, ORD(item(Elf32_Sym).other)); |
Write16(File, item(Elf32_Sym).shndx); |
WR.Write64LE(File, item(Elf32_Sym).value); |
WR.Write64LE(File, item(Elf32_Sym).size); |
WR.Write32LE(item(Elf32_Sym).name); |
WR.WriteByte(ORD(item(Elf32_Sym).info)); |
WR.WriteByte(ORD(item(Elf32_Sym).other)); |
Write16(item(Elf32_Sym).shndx); |
WR.Write64LE(item(Elf32_Sym).value); |
WR.Write64LE(item(Elf32_Sym).size); |
item := item.next |
END; |
|
WR.Write64LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 16); |
WR.Write32LE(File, 1); |
WR.Write32LE(File, 1); |
WR.Write64LE(File, 0); |
WR.Write64LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 8); |
WR.Write32LE(File, 1); |
WR.Write32LE(File, 2); |
WR.Write64LE(File, 0); |
WR.Write64LE(phdr[dyn].p_filesz + DynAdr - 16); |
WR.Write32LE(1); |
WR.Write32LE(1); |
WR.Write64LE(0); |
WR.Write64LE(phdr[dyn].p_filesz + DynAdr - 8); |
WR.Write32LE(1); |
WR.Write32LE(2); |
WR.Write64LE(0) |
|
WR.Write32LE(File, symCount); |
WR.Write32LE(File, symCount); |
|
FOR i := 0 TO symCount - 1 DO |
WR.Write32LE(File, CHL.GetInt(bucket, i)) |
END; |
|
FOR i := 0 TO symCount - 1 DO |
WR.Write32LE(File, CHL.GetInt(chain, i)) |
END; |
|
CHL.WriteToFile(File, strtab); |
WR.Write64LE(File, 0); |
WR.Write64LE(File, 0) |
|
ELSE |
item := dynamic.first; |
WHILE item # NIL DO |
WR.Write32LE(File, item(Elf32_Dyn).d_tag); |
WR.Write32LE(File, item(Elf32_Dyn).d_val); |
WR.Write32LE(item(Elf32_Dyn).d_tag); |
WR.Write32LE(item(Elf32_Dyn).d_val); |
item := item.next |
END; |
|
item := symtab.first; |
WHILE item # NIL DO |
WR.Write32LE(File, item(Elf32_Sym).name); |
WR.Write32LE(File, item(Elf32_Sym).value); |
WR.Write32LE(File, item(Elf32_Sym).size); |
WR.WriteByte(File, ORD(item(Elf32_Sym).info)); |
WR.WriteByte(File, ORD(item(Elf32_Sym).other)); |
Write16(File, item(Elf32_Sym).shndx); |
WR.Write32LE(item(Elf32_Sym).name); |
WR.Write32LE(item(Elf32_Sym).value); |
WR.Write32LE(item(Elf32_Sym).size); |
WR.WriteByte(ORD(item(Elf32_Sym).info)); |
WR.WriteByte(ORD(item(Elf32_Sym).other)); |
Write16(item(Elf32_Sym).shndx); |
item := item.next |
END; |
|
WR.Write32LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 8); |
WR.Write32LE(File, 00000101H); |
WR.Write32LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 4); |
WR.Write32LE(File, 00000201H); |
WR.Write32LE(phdr[dyn].p_filesz + DynAdr - 8); |
WR.Write32LE(00000101H); |
WR.Write32LE(phdr[dyn].p_filesz + DynAdr - 4); |
WR.Write32LE(00000201H) |
|
WR.Write32LE(File, symCount); |
WR.Write32LE(File, symCount); |
END; |
|
WR.Write32LE(symCount); |
WR.Write32LE(symCount); |
|
FOR i := 0 TO symCount - 1 DO |
WR.Write32LE(File, CHL.GetInt(bucket, i)) |
WR.Write32LE(CHL.GetInt(bucket, i)) |
END; |
|
FOR i := 0 TO symCount - 1 DO |
WR.Write32LE(File, CHL.GetInt(chain, i)) |
WR.Write32LE(CHL.GetInt(chain, i)) |
END; |
|
CHL.WriteToFile(File, strtab); |
WR.Write32LE(File, 0); |
WR.Write32LE(File, 0) |
CHL.WriteToFile(strtab); |
|
IF amd64 THEN |
WR.Write64LE(0); |
WR.Write64LE(0) |
ELSE |
WR.Write32LE(0); |
WR.Write32LE(0) |
END; |
|
CHL.WriteToFile(File, program.code); |
CHL.WriteToFile(program.code); |
WHILE pad > 0 DO |
WR.WriteByte(File, 0); |
WR.WriteByte(0); |
DEC(pad) |
END; |
CHL.WriteToFile(File, program.data); |
WR.Close(File) |
CHL.WriteToFile(program.data); |
WR.Close; |
UTILS.chmod(FileName) |
END write; |
|
|