Subversion Repositories Kolibri OS

Rev

Rev 7983 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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