KOS.ob07 5.4 KB

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