2019-10-06 19:55:12 +02:00
|
|
|
(*
|
2019-03-11 09:59:55 +01:00
|
|
|
BSD 2-Clause License
|
|
|
|
|
2019-10-06 19:55:12 +02:00
|
|
|
Copyright (c) 2018-2019, Anton Krotov
|
2019-03-11 09:59:55 +01:00
|
|
|
All rights reserved.
|
|
|
|
*)
|
|
|
|
|
|
|
|
MODULE MSCOFF;
|
|
|
|
|
|
|
|
IMPORT BIN, PE32, KOS, WR := WRITER, UTILS, ERRORS, LISTS, CHL := CHUNKLISTS;
|
|
|
|
|
|
|
|
|
|
|
|
CONST
|
|
|
|
|
|
|
|
SIZE_OF_DWORD = 4;
|
|
|
|
|
|
|
|
(* SectionHeader.Characteristics *)
|
|
|
|
|
|
|
|
SHC_flat = 040500020H;
|
|
|
|
SHC_data = 0C0500040H;
|
|
|
|
SHC_bss = 0C03000C0H;
|
|
|
|
|
|
|
|
|
|
|
|
TYPE
|
|
|
|
|
|
|
|
FH = PE32.IMAGE_FILE_HEADER;
|
|
|
|
|
|
|
|
SH = PE32.IMAGE_SECTION_HEADER;
|
|
|
|
|
|
|
|
|
|
|
|
PROCEDURE WriteReloc (File: WR.FILE; VirtualAddress, SymbolTableIndex, Type: INTEGER);
|
|
|
|
BEGIN
|
|
|
|
WR.Write32LE(File, VirtualAddress);
|
|
|
|
WR.Write32LE(File, SymbolTableIndex);
|
|
|
|
WR.Write16LE(File, Type)
|
|
|
|
END WriteReloc;
|
|
|
|
|
|
|
|
|
|
|
|
PROCEDURE Reloc (program: BIN.PROGRAM; File: WR.FILE);
|
|
|
|
VAR
|
|
|
|
reloc: BIN.RELOC;
|
|
|
|
|
|
|
|
BEGIN
|
|
|
|
reloc := program.rel_list.first(BIN.RELOC);
|
|
|
|
WHILE reloc # NIL DO
|
|
|
|
|
|
|
|
CASE reloc.opcode OF
|
|
|
|
|
|
|
|
|BIN.RIMP, BIN.IMPTAB:
|
|
|
|
WriteReloc(File, reloc.offset, 4, 6)
|
|
|
|
|
|
|
|
|BIN.RBSS:
|
|
|
|
WriteReloc(File, reloc.offset, 5, 6)
|
|
|
|
|
|
|
|
|BIN.RDATA:
|
|
|
|
WriteReloc(File, reloc.offset, 2, 6)
|
|
|
|
|
|
|
|
|BIN.RCODE:
|
|
|
|
WriteReloc(File, reloc.offset, 1, 6)
|
|
|
|
|
|
|
|
END;
|
|
|
|
|
|
|
|
reloc := reloc.next(BIN.RELOC)
|
|
|
|
END;
|
|
|
|
END Reloc;
|
|
|
|
|
|
|
|
|
|
|
|
PROCEDURE RelocCount (program: BIN.PROGRAM): INTEGER;
|
|
|
|
VAR
|
|
|
|
reloc: BIN.RELOC;
|
|
|
|
iproc: BIN.IMPRT;
|
|
|
|
res, L: INTEGER;
|
|
|
|
|
|
|
|
BEGIN
|
|
|
|
res := 0;
|
|
|
|
reloc := program.rel_list.first(BIN.RELOC);
|
|
|
|
WHILE reloc # NIL DO
|
|
|
|
|
|
|
|
INC(res);
|
|
|
|
|
|
|
|
IF reloc.opcode = BIN.RIMP THEN
|
|
|
|
L := BIN.get32le(program.code, reloc.offset);
|
|
|
|
iproc := BIN.GetIProc(program, L);
|
|
|
|
BIN.put32le(program.code, reloc.offset, iproc.label)
|
|
|
|
END;
|
|
|
|
|
|
|
|
IF reloc.opcode = BIN.RCODE THEN
|
|
|
|
L := BIN.get32le(program.code, reloc.offset);
|
|
|
|
BIN.put32le(program.code, reloc.offset, BIN.GetLabel(program, L))
|
|
|
|
END;
|
|
|
|
|
|
|
|
reloc := reloc.next(BIN.RELOC)
|
|
|
|
END
|
|
|
|
|
|
|
|
RETURN res
|
|
|
|
END RelocCount;
|
|
|
|
|
|
|
|
|
|
|
|
PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; ver: INTEGER);
|
|
|
|
VAR
|
|
|
|
File: WR.FILE;
|
|
|
|
exp: BIN.EXPRT;
|
|
|
|
n, i: INTEGER;
|
|
|
|
|
|
|
|
szversion: PE32.NAME;
|
|
|
|
|
|
|
|
ImportTable: CHL.INTLIST;
|
|
|
|
ILen, LibCount, isize: INTEGER;
|
|
|
|
|
|
|
|
ExpCount: INTEGER;
|
|
|
|
|
|
|
|
icount, ecount, dcount, ccount: INTEGER;
|
|
|
|
|
|
|
|
FileHeader: FH;
|
|
|
|
|
|
|
|
flat, data, edata, idata, bss: SH;
|
|
|
|
|
|
|
|
|
|
|
|
PROCEDURE ICount (ImportTable: CHL.INTLIST; ILen: INTEGER): INTEGER;
|
|
|
|
VAR
|
|
|
|
i, res: INTEGER;
|
|
|
|
|
|
|
|
BEGIN
|
|
|
|
res := 0;
|
|
|
|
|
|
|
|
FOR i := 0 TO ILen - 1 DO
|
|
|
|
IF CHL.GetInt(ImportTable, i) # 0 THEN
|
|
|
|
INC(res)
|
|
|
|
END
|
|
|
|
END
|
|
|
|
|
|
|
|
RETURN res
|
|
|
|
END ICount;
|
|
|
|
|
|
|
|
|
|
|
|
PROCEDURE SetNumberOfRelocations (VAR section: SH; NumberOfRelocations: INTEGER);
|
|
|
|
BEGIN
|
|
|
|
IF NumberOfRelocations >= 65536 THEN
|
2019-09-26 22:23:06 +02:00
|
|
|
ERRORS.Error(202)
|
2019-03-11 09:59:55 +01:00
|
|
|
END;
|
|
|
|
section.NumberOfRelocations := WCHR(NumberOfRelocations)
|
|
|
|
END SetNumberOfRelocations;
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN
|
|
|
|
|
|
|
|
szversion := "version";
|
|
|
|
|
|
|
|
ASSERT(LENGTH(szversion) = 7);
|
|
|
|
|
|
|
|
KOS.Import(program, 0, ImportTable, ILen, LibCount, isize);
|
|
|
|
ExpCount := LISTS.count(program.exp_list);
|
|
|
|
|
|
|
|
icount := CHL.Length(program.import);
|
|
|
|
dcount := CHL.Length(program.data);
|
|
|
|
ccount := CHL.Length(program.code);
|
|
|
|
ecount := CHL.Length(program.export);
|
|
|
|
|
|
|
|
FileHeader.Machine := 014CX;
|
|
|
|
FileHeader.NumberOfSections := 5X;
|
|
|
|
FileHeader.TimeDateStamp := UTILS.UnixTime();
|
|
|
|
//FileHeader.PointerToSymbolTable := 0;
|
|
|
|
FileHeader.NumberOfSymbols := 6;
|
|
|
|
FileHeader.SizeOfOptionalHeader := 0X;
|
|
|
|
FileHeader.Characteristics := 0184X;
|
|
|
|
|
|
|
|
flat.Name := ".flat";
|
|
|
|
flat.VirtualSize := 0;
|
|
|
|
flat.VirtualAddress := 0;
|
|
|
|
flat.SizeOfRawData := ccount;
|
|
|
|
flat.PointerToRawData := ORD(FileHeader.NumberOfSections) * PE32.SIZE_OF_IMAGE_SECTION_HEADER + PE32.SIZE_OF_IMAGE_FILE_HEADER;
|
|
|
|
//flat.PointerToRelocations := 0;
|
|
|
|
flat.PointerToLinenumbers := 0;
|
|
|
|
SetNumberOfRelocations(flat, RelocCount(program));
|
|
|
|
flat.NumberOfLinenumbers := 0X;
|
|
|
|
flat.Characteristics := SHC_flat;
|
|
|
|
|
|
|
|
data.Name := ".data";
|
|
|
|
data.VirtualSize := 0;
|
|
|
|
data.VirtualAddress := 0;
|
|
|
|
data.SizeOfRawData := dcount;
|
|
|
|
data.PointerToRawData := flat.PointerToRawData + flat.SizeOfRawData;
|
|
|
|
data.PointerToRelocations := 0;
|
|
|
|
data.PointerToLinenumbers := 0;
|
|
|
|
data.NumberOfRelocations := 0X;
|
|
|
|
data.NumberOfLinenumbers := 0X;
|
|
|
|
data.Characteristics := SHC_data;
|
|
|
|
|
|
|
|
edata.Name := ".edata";
|
|
|
|
edata.VirtualSize := 0;
|
|
|
|
edata.VirtualAddress := 0;
|
|
|
|
edata.SizeOfRawData := ((ExpCount + 1) * 2 + 1) * SIZE_OF_DWORD + LENGTH(szversion) + 1 + ecount;
|
|
|
|
edata.PointerToRawData := data.PointerToRawData + data.SizeOfRawData;
|
|
|
|
//edata.PointerToRelocations := 0;
|
|
|
|
edata.PointerToLinenumbers := 0;
|
|
|
|
SetNumberOfRelocations(edata, ExpCount * 2 + 1);
|
|
|
|
edata.NumberOfLinenumbers := 0X;
|
|
|
|
edata.Characteristics := SHC_data;
|
|
|
|
|
|
|
|
idata.Name := ".idata";
|
|
|
|
idata.VirtualSize := 0;
|
|
|
|
idata.VirtualAddress := 0;
|
|
|
|
idata.SizeOfRawData := isize;
|
|
|
|
idata.PointerToRawData := edata.PointerToRawData + edata.SizeOfRawData;
|
|
|
|
//idata.PointerToRelocations := 0;
|
|
|
|
idata.PointerToLinenumbers := 0;
|
|
|
|
SetNumberOfRelocations(idata, ICount(ImportTable, ILen));
|
|
|
|
idata.NumberOfLinenumbers := 0X;
|
|
|
|
idata.Characteristics := SHC_data;
|
|
|
|
|
|
|
|
bss.Name := ".bss";
|
|
|
|
bss.VirtualSize := 0;
|
|
|
|
bss.VirtualAddress := 0;
|
|
|
|
bss.SizeOfRawData := program.bss;
|
|
|
|
bss.PointerToRawData := 0;
|
|
|
|
bss.PointerToRelocations := 0;
|
|
|
|
bss.PointerToLinenumbers := 0;
|
|
|
|
bss.NumberOfRelocations := 0X;
|
|
|
|
bss.NumberOfLinenumbers := 0X;
|
|
|
|
bss.Characteristics := SHC_bss;
|
|
|
|
|
|
|
|
flat.PointerToRelocations := idata.PointerToRawData + idata.SizeOfRawData;
|
|
|
|
edata.PointerToRelocations := flat.PointerToRelocations + ORD(flat.NumberOfRelocations) * 10;
|
|
|
|
idata.PointerToRelocations := edata.PointerToRelocations + ORD(edata.NumberOfRelocations) * 10;
|
|
|
|
|
|
|
|
FileHeader.PointerToSymbolTable := idata.PointerToRelocations + ORD(idata.NumberOfRelocations) * 10;
|
|
|
|
|
|
|
|
File := WR.Create(FileName);
|
|
|
|
|
|
|
|
PE32.WriteFileHeader(File, FileHeader);
|
|
|
|
|
|
|
|
PE32.WriteSectionHeader(File, flat);
|
|
|
|
PE32.WriteSectionHeader(File, data);
|
|
|
|
PE32.WriteSectionHeader(File, edata);
|
|
|
|
PE32.WriteSectionHeader(File, idata);
|
|
|
|
PE32.WriteSectionHeader(File, bss);
|
|
|
|
|
|
|
|
CHL.WriteToFile(File, program.code);
|
|
|
|
CHL.WriteToFile(File, program.data);
|
|
|
|
|
|
|
|
exp := program.exp_list.first(BIN.EXPRT);
|
|
|
|
WHILE exp # NIL DO
|
|
|
|
WR.Write32LE(File, exp.nameoffs + edata.SizeOfRawData - ecount);
|
|
|
|
WR.Write32LE(File, exp.label);
|
|
|
|
exp := exp.next(BIN.EXPRT)
|
|
|
|
END;
|
|
|
|
|
|
|
|
WR.Write32LE(File, ((ExpCount + 1) * 2 + 1) * SIZE_OF_DWORD);
|
|
|
|
WR.Write32LE(File, ver);
|
|
|
|
|
|
|
|
WR.Write32LE(File, 0);
|
|
|
|
|
|
|
|
PE32.WriteName(File, szversion);
|
|
|
|
CHL.WriteToFile(File, program.export);
|
|
|
|
|
|
|
|
FOR i := 0 TO ILen - 1 DO
|
|
|
|
WR.Write32LE(File, CHL.GetInt(ImportTable, i))
|
|
|
|
END;
|
|
|
|
|
|
|
|
CHL.WriteToFile(File, program.import);
|
|
|
|
|
|
|
|
Reloc(program, File);
|
|
|
|
|
|
|
|
n := 0;
|
|
|
|
exp := program.exp_list.first(BIN.EXPRT);
|
|
|
|
WHILE exp # NIL DO
|
|
|
|
WriteReloc(File, n, 3, 6);
|
|
|
|
INC(n, 4);
|
|
|
|
|
|
|
|
WriteReloc(File, n, 1, 6);
|
|
|
|
INC(n, 4);
|
|
|
|
|
|
|
|
exp := exp.next(BIN.EXPRT)
|
|
|
|
END;
|
|
|
|
|
|
|
|
WriteReloc(File, n, 3, 6);
|
|
|
|
|
|
|
|
i := 0;
|
|
|
|
WHILE i < LibCount * 2 DO
|
|
|
|
WriteReloc(File, i * SIZE_OF_DWORD, 4, 6);
|
|
|
|
INC(i);
|
|
|
|
WriteReloc(File, i * SIZE_OF_DWORD, 4, 6);
|
|
|
|
INC(i)
|
|
|
|
END;
|
|
|
|
|
|
|
|
FOR i := LibCount * 2 TO ILen - 1 DO
|
|
|
|
IF CHL.GetInt(ImportTable, i) # 0 THEN
|
|
|
|
WriteReloc(File, i * SIZE_OF_DWORD, 4, 6)
|
|
|
|
END
|
|
|
|
END;
|
|
|
|
|
|
|
|
PE32.WriteName(File, "EXPORTS");
|
|
|
|
WriteReloc(File, 0, 3, 2);
|
|
|
|
|
|
|
|
PE32.WriteName(File, ".flat");
|
|
|
|
WriteReloc(File, 0, 1, 3);
|
|
|
|
|
|
|
|
PE32.WriteName(File, ".data");
|
|
|
|
WriteReloc(File, 0, 2, 3);
|
|
|
|
|
|
|
|
PE32.WriteName(File, ".edata");
|
|
|
|
WriteReloc(File, 0, 3, 3);
|
|
|
|
|
|
|
|
PE32.WriteName(File, ".idata");
|
|
|
|
WriteReloc(File, 0, 4, 3);
|
|
|
|
|
|
|
|
PE32.WriteName(File, ".bss");
|
|
|
|
WriteReloc(File, 0, 5, 3);
|
|
|
|
|
|
|
|
WR.Write32LE(File, 4);
|
|
|
|
|
|
|
|
WR.Close(File)
|
|
|
|
END write;
|
|
|
|
|
|
|
|
|
2019-10-06 19:55:12 +02:00
|
|
|
END MSCOFF.
|