(* BSD 2-Clause License Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) MODULE KOS; IMPORT BIN, WR := WRITER, LISTS, CHL := CHUNKLISTS; CONST HEADER_SIZE = 36; SIZE_OF_DWORD = 4; TYPE HEADER = RECORD menuet01: ARRAY 9 OF CHAR; ver, start, size, mem, sp, param, path: INTEGER END; PROCEDURE Import* (program: BIN.PROGRAM; idata: INTEGER; VAR ImportTable: CHL.INTLIST; VAR len, libcount, size: INTEGER); VAR i: INTEGER; imp: BIN.IMPRT; BEGIN libcount := 0; imp := program.imp_list.first(BIN.IMPRT); WHILE imp # NIL DO IF imp.label = 0 THEN INC(libcount) END; imp := imp.next(BIN.IMPRT) END; len := libcount * 2 + 2; size := (LISTS.count(program.imp_list) + len + 1) * SIZE_OF_DWORD; ImportTable := CHL.CreateIntList(); FOR i := 0 TO size DIV SIZE_OF_DWORD - 1 DO CHL.PushInt(ImportTable, 0) END; i := 0; imp := program.imp_list.first(BIN.IMPRT); WHILE imp # NIL DO IF imp.label = 0 THEN CHL.SetInt(ImportTable, len, 0); INC(len); CHL.SetInt(ImportTable, i, idata + len * SIZE_OF_DWORD); INC(i); CHL.SetInt(ImportTable, i, imp.nameoffs + size + idata); INC(i) ELSE CHL.SetInt(ImportTable, len, imp.nameoffs + size + idata); imp.label := len * SIZE_OF_DWORD; INC(len) END; imp := imp.next(BIN.IMPRT) END; CHL.SetInt(ImportTable, len, 0); CHL.SetInt(ImportTable, i, 0); CHL.SetInt(ImportTable, i + 1, 0); INC(len); INC(size, CHL.Length(program._import)) END Import; PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR); CONST PARAM_SIZE = 2048; FileAlignment = 16; VAR header: HEADER; base, text, data, idata, bss, offset: INTEGER; reloc: BIN.RELOC; iproc: BIN.IMPRT; L: INTEGER; delta: INTEGER; i: INTEGER; ImportTable: CHL.INTLIST; ILen, libcount, isize: INTEGER; icount, dcount, ccount: INTEGER; code: CHL.BYTELIST; BEGIN base := 0; icount := CHL.Length(program._import); dcount := CHL.Length(program.data); ccount := CHL.Length(program.code); text := base + HEADER_SIZE; data := WR.align(text + ccount, FileAlignment); idata := WR.align(data + dcount, FileAlignment); Import(program, idata, ImportTable, ILen, libcount, isize); bss := WR.align(idata + isize, FileAlignment); header.menuet01 := "MENUET01"; header.ver := 1; header.start := text; header.size := idata + isize - base; header.mem := WR.align(header.size + program.stack + program.bss + PARAM_SIZE * 2 + 4096, FileAlignment); header.sp := base + header.mem - PARAM_SIZE * 2; header.param := header.sp; header.path := header.param + PARAM_SIZE; code := program.code; reloc := program.rel_list.first(BIN.RELOC); WHILE reloc # NIL DO offset := reloc.offset; L := BIN.get32le(code, offset); delta := 3 - offset - text; CASE reloc.opcode OF |BIN.RIMP: iproc := BIN.GetIProc(program, L); delta := idata + iproc.label |BIN.RBSS: delta := L + bss |BIN.RDATA: delta := L + data |BIN.RCODE: delta := BIN.GetLabel(program, L) + text |BIN.PICDATA: INC(delta, L + data) |BIN.PICCODE: INC(delta, BIN.GetLabel(program, L) + text) |BIN.PICBSS: INC(delta, L + bss) |BIN.PICIMP: iproc := BIN.GetIProc(program, L); INC(delta, idata + iproc.label) |BIN.IMPTAB: INC(delta, idata) END; BIN.put32le(code, offset, delta); reloc := reloc.next(BIN.RELOC) END; WR.Create(FileName); FOR i := 0 TO 7 DO WR.WriteByte(ORD(header.menuet01[i])) END; WR.Write32LE(header.ver); WR.Write32LE(header.start); WR.Write32LE(header.size); WR.Write32LE(header.mem); WR.Write32LE(header.sp); WR.Write32LE(header.param); WR.Write32LE(header.path); CHL.WriteToFile(code); WR.Padding(FileAlignment); CHL.WriteToFile(program.data); WR.Padding(FileAlignment); FOR i := 0 TO ILen - 1 DO WR.Write32LE(CHL.GetInt(ImportTable, i)) END; CHL.WriteToFile(program._import); WR.Close END write; END KOS.