| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- 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; kernel: BOOLEAN);
- 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, glob32_size: INTEGER;
- code: CHL.BYTELIST;
- BEGIN
- base := 0;
- icount := CHL.Length(program._import);
- dcount := CHL.Length(program.data);
- ccount := CHL.Length(program.code);
- text := base;
- IF ~kernel THEN
- INC(text, HEADER_SIZE)
- END;
- 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);
- IF ~kernel THEN
- 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)
- END;
- 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.Padding(FileAlignment);
- IF kernel THEN
- glob32_size := program.bss DIV 4 + ORD(program.bss MOD 4 # 0);
- FOR i := 1 TO glob32_size DO
- WR.Write32LE(0)
- END
- END;
- WR.Close
- END write;
- END KOS.
|