Subversion Repositories Kolibri OS

Rev

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

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2018, 2019, Anton Krotov
  5.     All rights reserved.
  6. *)
  7.  
  8. MODULE BIN;
  9.  
  10. IMPORT LISTS, MACHINE, CHL := CHUNKLISTS, ARITH, UTILS;
  11.  
  12.  
  13. CONST
  14.  
  15.     RCODE*    = 1;
  16.     RDATA*    = 2;
  17.     RBSS*     = 3;
  18.     RIMP*     = 4;
  19.  
  20.     PICCODE*  = 5;
  21.     PICDATA*  = 6;
  22.     PICBSS*   = 7;
  23.     PICIMP*   = 8;
  24.  
  25.     IMPTAB*   = 9;
  26.  
  27.  
  28. TYPE
  29.  
  30.     RELOC* = POINTER TO RECORD (LISTS.ITEM)
  31.  
  32.         opcode*: INTEGER;
  33.         offset*: INTEGER
  34.  
  35.     END;
  36.  
  37.     IMPRT* = POINTER TO RECORD (LISTS.ITEM)
  38.  
  39.         nameoffs*: INTEGER;
  40.         label*:    INTEGER;
  41.  
  42.         OriginalFirstThunk*,
  43.         FirstThunk*: INTEGER
  44.  
  45.     END;
  46.  
  47.     EXPRT* = POINTER TO RECORD (LISTS.ITEM)
  48.  
  49.         nameoffs*: INTEGER;
  50.         label*:    INTEGER
  51.  
  52.     END;
  53.  
  54.     PROGRAM* = POINTER TO RECORD
  55.  
  56.         code*:      CHL.BYTELIST;
  57.         data*:      CHL.BYTELIST;
  58.         labels:     CHL.INTLIST;
  59.         bss*:       INTEGER;
  60.         stack*:     INTEGER;
  61.         vmajor*,
  62.         vminor*:    WCHAR;
  63.         modname*:   INTEGER;
  64.         import*:    CHL.BYTELIST;
  65.         export*:    CHL.BYTELIST;
  66.         rel_list*:  LISTS.LIST;
  67.         imp_list*:  LISTS.LIST;
  68.         exp_list*:  LISTS.LIST
  69.  
  70.     END;
  71.  
  72.  
  73. PROCEDURE create* (NumberOfLabels: INTEGER): PROGRAM;
  74. VAR
  75.     program:  PROGRAM;
  76.     i:        INTEGER;
  77.  
  78. BEGIN
  79.     NEW(program);
  80.  
  81.     program.bss := 0;
  82.  
  83.     program.labels := CHL.CreateIntList();
  84.     FOR i := 0 TO NumberOfLabels - 1 DO
  85.         CHL.PushInt(program.labels, 0)
  86.     END;
  87.  
  88.     program.rel_list := LISTS.create(NIL);
  89.     program.imp_list := LISTS.create(NIL);
  90.     program.exp_list := LISTS.create(NIL);
  91.  
  92.     program.data   := CHL.CreateByteList();
  93.     program.code   := CHL.CreateByteList();
  94.     program.import := CHL.CreateByteList();
  95.     program.export := CHL.CreateByteList()
  96.  
  97.     RETURN program
  98. END create;
  99.  
  100.  
  101. PROCEDURE SetParams* (program: PROGRAM; bss, stack: INTEGER; vmajor, vminor: WCHAR);
  102. BEGIN
  103.     program.bss    := bss;
  104.     program.stack  := stack;
  105.     program.vmajor := vmajor;
  106.     program.vminor := vminor
  107. END SetParams;
  108.  
  109.  
  110. PROCEDURE PutReloc* (program: PROGRAM; opcode: INTEGER);
  111. VAR
  112.     cmd: RELOC;
  113.  
  114. BEGIN
  115.     NEW(cmd);
  116.     cmd.opcode := opcode;
  117.     cmd.offset := CHL.Length(program.code);
  118.     LISTS.push(program.rel_list, cmd)
  119. END PutReloc;
  120.  
  121.  
  122. PROCEDURE PutData* (program: PROGRAM; b: BYTE);
  123. BEGIN
  124.     CHL.PushByte(program.data, b)
  125. END PutData;
  126.  
  127.  
  128. PROCEDURE get32le* (array: CHL.BYTELIST; idx: INTEGER): INTEGER;
  129. VAR
  130.     i: INTEGER;
  131.     x: INTEGER;
  132.  
  133. BEGIN
  134.     x := 0;
  135.  
  136.     FOR i := 3 TO 0 BY -1 DO
  137.         x := LSL(x, 8) + CHL.GetByte(array, idx + i)
  138.     END;
  139.  
  140.     IF UTILS.bit_depth = 64 THEN
  141.         x := MACHINE.Int32To64(x)
  142.     END
  143.  
  144.     RETURN x
  145. END get32le;
  146.  
  147.  
  148. PROCEDURE put32le* (array: CHL.BYTELIST; idx: INTEGER; x: INTEGER);
  149. VAR
  150.     i: INTEGER;
  151.  
  152. BEGIN
  153.     FOR i := 0 TO 3 DO
  154.         CHL.SetByte(array, idx + i, MACHINE.Byte(x, i))
  155.     END
  156. END put32le;
  157.  
  158.  
  159. PROCEDURE PutData32LE* (program: PROGRAM; x: INTEGER);
  160. VAR
  161.     i: INTEGER;
  162.  
  163. BEGIN
  164.     FOR i := 0 TO 3 DO
  165.         CHL.PushByte(program.data, MACHINE.Byte(x, i))
  166.     END
  167. END PutData32LE;
  168.  
  169.  
  170. PROCEDURE PutData64LE* (program: PROGRAM; x: INTEGER);
  171. VAR
  172.     i: INTEGER;
  173.  
  174. BEGIN
  175.     FOR i := 0 TO 7 DO
  176.         CHL.PushByte(program.data, MACHINE.Byte(x, i))
  177.     END
  178. END PutData64LE;
  179.  
  180.  
  181. PROCEDURE PutDataStr* (program: PROGRAM; s: ARRAY OF CHAR);
  182. VAR
  183.     i: INTEGER;
  184.  
  185. BEGIN
  186.     i := 0;
  187.     WHILE s[i] # 0X DO
  188.         PutData(program, ORD(s[i]));
  189.         INC(i)
  190.     END
  191. END PutDataStr;
  192.  
  193.  
  194. PROCEDURE PutCode* (program: PROGRAM; b: BYTE);
  195. BEGIN
  196.     CHL.PushByte(program.code, b)
  197. END PutCode;
  198.  
  199.  
  200. PROCEDURE PutCode32LE* (program: PROGRAM; x: INTEGER);
  201. VAR
  202.     i: INTEGER;
  203.  
  204. BEGIN
  205.     FOR i := 0 TO 3 DO
  206.         CHL.PushByte(program.code, MACHINE.Byte(x, i))
  207.     END
  208. END PutCode32LE;
  209.  
  210.  
  211. PROCEDURE SetLabel* (program: PROGRAM; label, offset: INTEGER);
  212. BEGIN
  213.     CHL.SetInt(program.labels, label, offset)
  214. END SetLabel;
  215.  
  216.  
  217. PROCEDURE Import* (program: PROGRAM; name: ARRAY OF CHAR; label: INTEGER);
  218. VAR
  219.     imp: IMPRT;
  220.     i:   INTEGER;
  221.  
  222. BEGIN
  223.     CHL.PushByte(program.import, 0);
  224.     CHL.PushByte(program.import, 0);
  225.  
  226.     IF ODD(CHL.Length(program.import)) THEN
  227.         CHL.PushByte(program.import, 0)
  228.     END;
  229.  
  230.     NEW(imp);
  231.     imp.nameoffs := CHL.Length(program.import);
  232.     imp.label := label;
  233.     LISTS.push(program.imp_list, imp);
  234.  
  235.     i := 0;
  236.     WHILE name[i] # 0X DO
  237.         CHL.PushByte(program.import, ORD(name[i]));
  238.         INC(i)
  239.     END;
  240.     CHL.PushByte(program.import, 0)
  241. END Import;
  242.  
  243.  
  244. PROCEDURE less (bytes: CHL.BYTELIST; a, b: EXPRT): BOOLEAN;
  245. VAR
  246.     i, j: INTEGER;
  247.  
  248. BEGIN
  249.     i := a.nameoffs;
  250.     j := b.nameoffs;
  251.  
  252.     WHILE (CHL.GetByte(bytes, i) # 0) & (CHL.GetByte(bytes, j) # 0) &
  253.           (CHL.GetByte(bytes, i) = CHL.GetByte(bytes, j)) DO
  254.         INC(i);
  255.         INC(j)
  256.     END
  257.  
  258.     RETURN CHL.GetByte(bytes, i) < CHL.GetByte(bytes, j)
  259. END less;
  260.  
  261.  
  262. PROCEDURE Export* (program: PROGRAM; name: ARRAY OF CHAR; label: INTEGER);
  263. VAR
  264.     exp, cur: EXPRT;
  265.     i: INTEGER;
  266.  
  267. BEGIN
  268.     NEW(exp);
  269.     exp.nameoffs := CHL.Length(program.export);
  270.     exp.label := CHL.GetInt(program.labels, label);
  271.  
  272.     i := 0;
  273.     WHILE name[i] # 0X DO
  274.         CHL.PushByte(program.export, ORD(name[i]));
  275.         INC(i)
  276.     END;
  277.     CHL.PushByte(program.export, 0);
  278.  
  279.     cur := program.exp_list.first(EXPRT);
  280.     WHILE (cur # NIL) & less(program.export, cur, exp) DO
  281.         cur := cur.next(EXPRT)
  282.     END;
  283.  
  284.     IF cur # NIL THEN
  285.         IF cur.prev # NIL THEN
  286.             LISTS.insert(program.exp_list, cur.prev, exp)
  287.         ELSE
  288.             LISTS.insertL(program.exp_list, cur, exp)
  289.         END
  290.     ELSE
  291.         LISTS.push(program.exp_list, exp)
  292.     END
  293.  
  294. END Export;
  295.  
  296.  
  297. PROCEDURE GetIProc* (program: PROGRAM; n: INTEGER): IMPRT;
  298. VAR
  299.     import: IMPRT;
  300.     res:    IMPRT;
  301.  
  302. BEGIN
  303.     import  := program.imp_list.first(IMPRT);
  304.  
  305.     res := NIL;
  306.     WHILE (import # NIL) & (n >= 0) DO
  307.         IF import.label # 0 THEN
  308.             res := import;
  309.             DEC(n)
  310.         END;
  311.         import := import.next(IMPRT)
  312.     END;
  313.  
  314.     ASSERT(n = -1)
  315.     RETURN res
  316. END GetIProc;
  317.  
  318.  
  319. PROCEDURE GetLabel* (program: PROGRAM; label: INTEGER): INTEGER;
  320.     RETURN CHL.GetInt(program.labels, label)
  321. END GetLabel;
  322.  
  323.  
  324. PROCEDURE NewLabel* (program: PROGRAM);
  325. BEGIN
  326.     CHL.PushInt(program.labels, 0)
  327. END NewLabel;
  328.  
  329.  
  330. PROCEDURE fixup* (program: PROGRAM);
  331. VAR
  332.     rel:    RELOC;
  333.     imp:    IMPRT;
  334.     nproc:  INTEGER;
  335.     L:      INTEGER;
  336.  
  337. BEGIN
  338.  
  339.     nproc := 0;
  340.     imp := program.imp_list.first(IMPRT);
  341.     WHILE imp # NIL DO
  342.         IF imp.label # 0 THEN
  343.             CHL.SetInt(program.labels, imp.label, nproc);
  344.             INC(nproc)
  345.         END;
  346.         imp := imp.next(IMPRT)
  347.     END;
  348.  
  349.     rel := program.rel_list.first(RELOC);
  350.     WHILE rel # NIL DO
  351.  
  352.         IF rel.opcode IN {RIMP, PICIMP} THEN
  353.             L := get32le(program.code, rel.offset);
  354.             put32le(program.code, rel.offset, GetLabel(program, L))
  355.         END;
  356.  
  357.         rel := rel.next(RELOC)
  358.     END
  359.  
  360. END fixup;
  361.  
  362.  
  363. PROCEDURE InitArray* (VAR array: ARRAY OF BYTE; VAR idx: INTEGER; hex: ARRAY OF CHAR);
  364. VAR
  365.     i, k: INTEGER;
  366.  
  367.  
  368.     PROCEDURE hexdgt (dgt: CHAR): INTEGER;
  369.     VAR
  370.         res: INTEGER;
  371.  
  372.     BEGIN
  373.         IF dgt < "A" THEN
  374.             res := ORD(dgt) - ORD("0")
  375.         ELSE
  376.             res := ORD(dgt) - ORD("A") + 10
  377.         END
  378.  
  379.         RETURN res
  380.     END hexdgt;
  381.  
  382.  
  383. BEGIN
  384.     k := LENGTH(hex);
  385.     ASSERT(~ODD(k));
  386.     k := k DIV 2;
  387.  
  388.     FOR i := 0 TO k - 1 DO
  389.         array[i + idx] := hexdgt(hex[2 * i]) * 16 + hexdgt(hex[2 * i + 1])
  390.     END;
  391.  
  392.     idx := idx + k
  393. END InitArray;
  394.  
  395.  
  396. END BIN.