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