Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2018, Anton Krotov
  5.     All rights reserved.
  6. *)
  7.  
  8. MODULE KOS;
  9.  
  10. IMPORT BIN, WR := WRITER, LISTS, CHL := CHUNKLISTS;
  11.  
  12.  
  13. CONST
  14.  
  15.     HEADER_SIZE = 36;
  16.  
  17.     SIZE_OF_DWORD = 4;
  18.  
  19.  
  20. TYPE
  21.  
  22.     FILE = WR.FILE;
  23.  
  24.     HEADER = RECORD
  25.  
  26.         menuet01: ARRAY 9 OF CHAR;
  27.         ver, start, size, mem, sp, param, path: INTEGER
  28.  
  29.     END;
  30.  
  31.  
  32. PROCEDURE align (n, _align: INTEGER): INTEGER;
  33. BEGIN
  34.     IF n MOD _align # 0 THEN
  35.         n := n + _align - (n MOD _align)
  36.     END
  37.  
  38.     RETURN n
  39. END align;
  40.  
  41.  
  42. PROCEDURE Import* (program: BIN.PROGRAM; idata: INTEGER; VAR ImportTable: CHL.INTLIST; VAR len, libcount, size: INTEGER);
  43. VAR
  44.     i:      INTEGER;
  45.     import: BIN.IMPRT;
  46.  
  47. BEGIN
  48.     libcount  := 0;
  49.     import := program.imp_list.first(BIN.IMPRT);
  50.     WHILE import # NIL DO
  51.         IF import.label = 0 THEN
  52.             INC(libcount)
  53.         END;
  54.         import := import.next(BIN.IMPRT)
  55.     END;
  56.  
  57.     len  := libcount * 2 + 2;
  58.     size := (LISTS.count(program.imp_list) + len + 1) * SIZE_OF_DWORD;
  59.  
  60.     ImportTable := CHL.CreateIntList();
  61.     FOR i := 0 TO size DIV SIZE_OF_DWORD - 1 DO
  62.         CHL.PushInt(ImportTable, 0)
  63.     END;
  64.  
  65.     i := 0;
  66.     import := program.imp_list.first(BIN.IMPRT);
  67.     WHILE import # NIL DO
  68.  
  69.         IF import.label = 0 THEN
  70.             CHL.SetInt(ImportTable, len, 0);
  71.             INC(len);
  72.             CHL.SetInt(ImportTable, i, idata + len * SIZE_OF_DWORD);
  73.             INC(i);
  74.             CHL.SetInt(ImportTable, i, import.nameoffs + size + idata);
  75.             INC(i)
  76.         ELSE
  77.             CHL.SetInt(ImportTable, len, import.nameoffs + size + idata);
  78.             import.label := len * SIZE_OF_DWORD;
  79.             INC(len)
  80.         END;
  81.  
  82.         import := import.next(BIN.IMPRT)
  83.     END;
  84.     CHL.SetInt(ImportTable, len, 0);
  85.     CHL.SetInt(ImportTable, i, 0);
  86.     CHL.SetInt(ImportTable, i + 1, 0);
  87.     INC(len);
  88.     size := size + CHL.Length(program.import)
  89. END Import;
  90.  
  91.  
  92. PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR);
  93.  
  94. CONST
  95.  
  96.     PARAM_SIZE    = 2048;
  97.     FileAlignment = 16;
  98.  
  99.  
  100. VAR
  101.     header: HEADER;
  102.  
  103.     base, text, data, idata, bss: INTEGER;
  104.  
  105.     reloc:   BIN.RELOC;
  106.     iproc:   BIN.IMPRT;
  107.     L:       INTEGER;
  108.     delta:   INTEGER;
  109.  
  110.     i: INTEGER;
  111.  
  112.     File: FILE;
  113.  
  114.     ImportTable: CHL.INTLIST;
  115.     ILen, libcount, isize: INTEGER;
  116.  
  117.     icount, dcount, ccount: INTEGER;
  118.  
  119.  
  120. BEGIN
  121.     base := 0;
  122.  
  123.     icount := CHL.Length(program.import);
  124.     dcount := CHL.Length(program.data);
  125.     ccount := CHL.Length(program.code);
  126.  
  127.     text  := base + HEADER_SIZE;
  128.     data  := align(text + ccount, FileAlignment);
  129.     idata := align(data + dcount, FileAlignment);
  130.  
  131.     Import(program, idata, ImportTable, ILen, libcount, isize);
  132.  
  133.     bss := align(idata + isize, FileAlignment);
  134.  
  135.     header.menuet01 := "MENUET01";
  136.     header.ver      :=  1;
  137.     header.start    :=  text;
  138.     header.size     :=  idata + isize - base;
  139.     header.mem      :=  align(header.size + program.stack + program.bss + PARAM_SIZE * 2 + 4096, FileAlignment);
  140.     header.sp       :=  base + header.mem - PARAM_SIZE * 2;
  141.     header.param    :=  header.sp;
  142.     header.path     :=  header.param + PARAM_SIZE;
  143.  
  144.  
  145.     reloc := program.rel_list.first(BIN.RELOC);
  146.     WHILE reloc # NIL DO
  147.  
  148.         L := BIN.get32le(program.code, reloc.offset);
  149.         delta := 3 - reloc.offset - text;
  150.  
  151.         CASE reloc.opcode OF
  152.  
  153.         |BIN.RIMP:
  154.               iproc := BIN.GetIProc(program, L);
  155.               BIN.put32le(program.code, reloc.offset, idata + iproc.label)
  156.  
  157.         |BIN.RBSS:
  158.               BIN.put32le(program.code, reloc.offset, L + bss)
  159.  
  160.         |BIN.RDATA:
  161.               BIN.put32le(program.code, reloc.offset, L + data)
  162.  
  163.         |BIN.RCODE:
  164.               BIN.put32le(program.code, reloc.offset, BIN.GetLabel(program, L) + text)
  165.  
  166.         |BIN.PICDATA:
  167.               BIN.put32le(program.code, reloc.offset, L + data + delta)
  168.  
  169.         |BIN.PICCODE:
  170.               BIN.put32le(program.code, reloc.offset, BIN.GetLabel(program, L) + text + delta)
  171.  
  172.         |BIN.PICBSS:
  173.               BIN.put32le(program.code, reloc.offset, L + bss + delta)
  174.  
  175.         |BIN.PICIMP:
  176.               iproc := BIN.GetIProc(program, L);
  177.               BIN.put32le(program.code, reloc.offset, idata + iproc.label + delta)
  178.  
  179.         |BIN.IMPTAB:
  180.               BIN.put32le(program.code, reloc.offset, idata + delta)
  181.  
  182.         END;
  183.  
  184.         reloc := reloc.next(BIN.RELOC)
  185.     END;
  186.  
  187.     File := WR.Create(FileName);
  188.  
  189.     FOR i := 0 TO 7 DO
  190.         WR.WriteByte(File, ORD(header.menuet01[i]))
  191.     END;
  192.  
  193.     WR.Write32LE(File, header.ver);
  194.     WR.Write32LE(File, header.start);
  195.     WR.Write32LE(File, header.size);
  196.     WR.Write32LE(File, header.mem);
  197.     WR.Write32LE(File, header.sp);
  198.     WR.Write32LE(File, header.param);
  199.     WR.Write32LE(File, header.path);
  200.    
  201.     CHL.WriteToFile(File, program.code);
  202.     WR.Padding(File, FileAlignment);
  203.  
  204.     CHL.WriteToFile(File, program.data);
  205.     WR.Padding(File, FileAlignment);
  206.  
  207.     FOR i := 0 TO ILen - 1 DO
  208.         WR.Write32LE(File, CHL.GetInt(ImportTable, i))
  209.     END;      
  210.    
  211.     CHL.WriteToFile(File, program.import);
  212.  
  213.     WR.Close(File)
  214.  
  215. END write;
  216.  
  217.  
  218. END KOS.