KOS.ob07 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2018-2020, 2023, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE KOS;
  7. IMPORT BIN, WR := WRITER, LISTS, CHL := CHUNKLISTS;
  8. CONST
  9. HEADER_SIZE = 36;
  10. SIZE_OF_DWORD = 4;
  11. TYPE
  12. HEADER = RECORD
  13. menuet01: ARRAY 9 OF CHAR;
  14. ver, start, size, mem, sp, param, path: INTEGER
  15. END;
  16. PROCEDURE Import* (program: BIN.PROGRAM; idata: INTEGER; VAR ImportTable: CHL.INTLIST; VAR len, libcount, size: INTEGER);
  17. VAR
  18. i: INTEGER;
  19. imp: BIN.IMPRT;
  20. BEGIN
  21. libcount := 0;
  22. imp := program.imp_list.first(BIN.IMPRT);
  23. WHILE imp # NIL DO
  24. IF imp.label = 0 THEN
  25. INC(libcount)
  26. END;
  27. imp := imp.next(BIN.IMPRT)
  28. END;
  29. len := libcount * 2 + 2;
  30. size := (LISTS.count(program.imp_list) + len + 1) * SIZE_OF_DWORD;
  31. ImportTable := CHL.CreateIntList();
  32. FOR i := 0 TO size DIV SIZE_OF_DWORD - 1 DO
  33. CHL.PushInt(ImportTable, 0)
  34. END;
  35. i := 0;
  36. imp := program.imp_list.first(BIN.IMPRT);
  37. WHILE imp # NIL DO
  38. IF imp.label = 0 THEN
  39. CHL.SetInt(ImportTable, len, 0);
  40. INC(len);
  41. CHL.SetInt(ImportTable, i, idata + len * SIZE_OF_DWORD);
  42. INC(i);
  43. CHL.SetInt(ImportTable, i, imp.nameoffs + size + idata);
  44. INC(i)
  45. ELSE
  46. CHL.SetInt(ImportTable, len, imp.nameoffs + size + idata);
  47. imp.label := len * SIZE_OF_DWORD;
  48. INC(len)
  49. END;
  50. imp := imp.next(BIN.IMPRT)
  51. END;
  52. CHL.SetInt(ImportTable, len, 0);
  53. CHL.SetInt(ImportTable, i, 0);
  54. CHL.SetInt(ImportTable, i + 1, 0);
  55. INC(len);
  56. INC(size, CHL.Length(program._import))
  57. END Import;
  58. PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; kernel: BOOLEAN);
  59. CONST
  60. PARAM_SIZE = 2048;
  61. FileAlignment = 16;
  62. VAR
  63. header: HEADER;
  64. base, text, data, idata, bss, offset: INTEGER;
  65. reloc: BIN.RELOC;
  66. iproc: BIN.IMPRT;
  67. L: INTEGER;
  68. delta: INTEGER;
  69. i: INTEGER;
  70. ImportTable: CHL.INTLIST;
  71. ILen, libcount, isize: INTEGER;
  72. icount, dcount, ccount, glob32_size: INTEGER;
  73. code: CHL.BYTELIST;
  74. BEGIN
  75. base := 0;
  76. icount := CHL.Length(program._import);
  77. dcount := CHL.Length(program.data);
  78. ccount := CHL.Length(program.code);
  79. text := base;
  80. IF ~kernel THEN
  81. INC(text, HEADER_SIZE)
  82. END;
  83. data := WR.align(text + ccount, FileAlignment);
  84. idata := WR.align(data + dcount, FileAlignment);
  85. Import(program, idata, ImportTable, ILen, libcount, isize);
  86. bss := WR.align(idata + isize, FileAlignment);
  87. header.menuet01 := "MENUET01";
  88. header.ver := 1;
  89. header.start := text;
  90. header.size := idata + isize - base;
  91. header.mem := WR.align(header.size + program.stack + program.bss + PARAM_SIZE * 2 + 4096, FileAlignment);
  92. header.sp := base + header.mem - PARAM_SIZE * 2;
  93. header.param := header.sp;
  94. header.path := header.param + PARAM_SIZE;
  95. code := program.code;
  96. reloc := program.rel_list.first(BIN.RELOC);
  97. WHILE reloc # NIL DO
  98. offset := reloc.offset;
  99. L := BIN.get32le(code, offset);
  100. delta := 3 - offset - text;
  101. CASE reloc.opcode OF
  102. |BIN.RIMP:
  103. iproc := BIN.GetIProc(program, L);
  104. delta := idata + iproc.label
  105. |BIN.RBSS:
  106. delta := L + bss
  107. |BIN.RDATA:
  108. delta := L + data
  109. |BIN.RCODE:
  110. delta := BIN.GetLabel(program, L) + text
  111. |BIN.PICDATA:
  112. INC(delta, L + data)
  113. |BIN.PICCODE:
  114. INC(delta, BIN.GetLabel(program, L) + text)
  115. |BIN.PICBSS:
  116. INC(delta, L + bss)
  117. |BIN.PICIMP:
  118. iproc := BIN.GetIProc(program, L);
  119. INC(delta, idata + iproc.label)
  120. |BIN.IMPTAB:
  121. INC(delta, idata)
  122. END;
  123. BIN.put32le(code, offset, delta);
  124. reloc := reloc.next(BIN.RELOC)
  125. END;
  126. WR.Create(FileName);
  127. IF ~kernel THEN
  128. FOR i := 0 TO 7 DO
  129. WR.WriteByte(ORD(header.menuet01[i]))
  130. END;
  131. WR.Write32LE(header.ver);
  132. WR.Write32LE(header.start);
  133. WR.Write32LE(header.size);
  134. WR.Write32LE(header.mem);
  135. WR.Write32LE(header.sp);
  136. WR.Write32LE(header.param);
  137. WR.Write32LE(header.path)
  138. END;
  139. CHL.WriteToFile(code);
  140. WR.Padding(FileAlignment);
  141. CHL.WriteToFile(program.data);
  142. WR.Padding(FileAlignment);
  143. FOR i := 0 TO ILen - 1 DO
  144. WR.Write32LE(CHL.GetInt(ImportTable, i))
  145. END;
  146. CHL.WriteToFile(program._import);
  147. WR.Padding(FileAlignment);
  148. IF kernel THEN
  149. glob32_size := program.bss DIV 4 + ORD(program.bss MOD 4 # 0);
  150. FOR i := 1 TO glob32_size DO
  151. WR.Write32LE(0)
  152. END
  153. END;
  154. WR.Close
  155. END write;
  156. END KOS.