MSCOFF.ob07 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2018-2020, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE MSCOFF;
  7. IMPORT BIN, PE32, KOS, WR := WRITER, UTILS, ERRORS, LISTS, CHL := CHUNKLISTS;
  8. CONST
  9. SIZE_OF_DWORD = 4;
  10. (* SectionHeader.Characteristics *)
  11. SHC_flat = 040500020H;
  12. SHC_data = 0C0500040H;
  13. SHC_bss = 0C03000C0H;
  14. TYPE
  15. FH = PE32.IMAGE_FILE_HEADER;
  16. SH = PE32.IMAGE_SECTION_HEADER;
  17. PROCEDURE WriteReloc (VirtualAddress, SymbolTableIndex, Type: INTEGER);
  18. BEGIN
  19. WR.Write32LE(VirtualAddress);
  20. WR.Write32LE(SymbolTableIndex);
  21. WR.Write16LE(Type)
  22. END WriteReloc;
  23. PROCEDURE Reloc (program: BIN.PROGRAM);
  24. VAR
  25. reloc: BIN.RELOC;
  26. offset: INTEGER;
  27. BEGIN
  28. reloc := program.rel_list.first(BIN.RELOC);
  29. WHILE reloc # NIL DO
  30. offset := reloc.offset;
  31. CASE reloc.opcode OF
  32. |BIN.RIMP,
  33. BIN.IMPTAB: WriteReloc(offset, 4, 6)
  34. |BIN.RBSS: WriteReloc(offset, 5, 6)
  35. |BIN.RDATA: WriteReloc(offset, 2, 6)
  36. |BIN.RCODE: WriteReloc(offset, 1, 6)
  37. END;
  38. reloc := reloc.next(BIN.RELOC)
  39. END;
  40. END Reloc;
  41. PROCEDURE RelocCount (program: BIN.PROGRAM): INTEGER;
  42. VAR
  43. reloc: BIN.RELOC;
  44. iproc: BIN.IMPRT;
  45. res, L: INTEGER;
  46. offset: INTEGER;
  47. code: CHL.BYTELIST;
  48. BEGIN
  49. res := 0;
  50. code := program.code;
  51. reloc := program.rel_list.first(BIN.RELOC);
  52. WHILE reloc # NIL DO
  53. INC(res);
  54. offset := reloc.offset;
  55. IF reloc.opcode = BIN.RIMP THEN
  56. L := BIN.get32le(code, offset);
  57. iproc := BIN.GetIProc(program, L);
  58. BIN.put32le(code, offset, iproc.label)
  59. END;
  60. IF reloc.opcode = BIN.RCODE THEN
  61. L := BIN.get32le(code, offset);
  62. BIN.put32le(code, offset, BIN.GetLabel(program, L))
  63. END;
  64. reloc := reloc.next(BIN.RELOC)
  65. END
  66. RETURN res
  67. END RelocCount;
  68. PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; ver: INTEGER);
  69. VAR
  70. exp: BIN.EXPRT;
  71. n, i: INTEGER;
  72. szversion: PE32.NAME;
  73. ImportTable: CHL.INTLIST;
  74. ILen, LibCount, isize: INTEGER;
  75. ExpCount: INTEGER;
  76. icount, ecount, dcount, ccount: INTEGER;
  77. FileHeader: FH;
  78. flat, data, edata, idata, bss: SH;
  79. PROCEDURE ICount (ImportTable: CHL.INTLIST; ILen: INTEGER): INTEGER;
  80. VAR
  81. i, res: INTEGER;
  82. BEGIN
  83. res := 0;
  84. FOR i := 0 TO ILen - 1 DO
  85. IF CHL.GetInt(ImportTable, i) # 0 THEN
  86. INC(res)
  87. END
  88. END
  89. RETURN res
  90. END ICount;
  91. PROCEDURE SetNumberOfRelocations (VAR section: SH; NumberOfRelocations: INTEGER);
  92. BEGIN
  93. IF NumberOfRelocations >= 65536 THEN
  94. ERRORS.Error(202)
  95. END;
  96. section.NumberOfRelocations := WCHR(NumberOfRelocations)
  97. END SetNumberOfRelocations;
  98. BEGIN
  99. szversion := "version";
  100. ASSERT(LENGTH(szversion) = 7);
  101. KOS.Import(program, 0, ImportTable, ILen, LibCount, isize);
  102. ExpCount := LISTS.count(program.exp_list);
  103. icount := CHL.Length(program._import);
  104. dcount := CHL.Length(program.data);
  105. ccount := CHL.Length(program.code);
  106. ecount := CHL.Length(program.export);
  107. FileHeader.Machine := 014CX;
  108. FileHeader.NumberOfSections := 5X;
  109. FileHeader.TimeDateStamp := UTILS.UnixTime();
  110. (* FileHeader.PointerToSymbolTable := 0; *)
  111. FileHeader.NumberOfSymbols := 6;
  112. FileHeader.SizeOfOptionalHeader := 0X;
  113. FileHeader.Characteristics := 0184X;
  114. flat.Name := ".flat";
  115. flat.VirtualSize := 0;
  116. flat.VirtualAddress := 0;
  117. flat.SizeOfRawData := ccount;
  118. flat.PointerToRawData := ORD(FileHeader.NumberOfSections) * PE32.SIZE_OF_IMAGE_SECTION_HEADER + PE32.SIZE_OF_IMAGE_FILE_HEADER;
  119. (* flat.PointerToRelocations := 0; *)
  120. flat.PointerToLinenumbers := 0;
  121. SetNumberOfRelocations(flat, RelocCount(program));
  122. flat.NumberOfLinenumbers := 0X;
  123. flat.Characteristics := SHC_flat;
  124. data.Name := ".data";
  125. data.VirtualSize := 0;
  126. data.VirtualAddress := 0;
  127. data.SizeOfRawData := dcount;
  128. data.PointerToRawData := flat.PointerToRawData + flat.SizeOfRawData;
  129. data.PointerToRelocations := 0;
  130. data.PointerToLinenumbers := 0;
  131. data.NumberOfRelocations := 0X;
  132. data.NumberOfLinenumbers := 0X;
  133. data.Characteristics := SHC_data;
  134. edata.Name := ".edata";
  135. edata.VirtualSize := 0;
  136. edata.VirtualAddress := 0;
  137. edata.SizeOfRawData := ((ExpCount + 1) * 2 + 1) * SIZE_OF_DWORD + LENGTH(szversion) + 1 + ecount;
  138. edata.PointerToRawData := data.PointerToRawData + data.SizeOfRawData;
  139. (* edata.PointerToRelocations := 0; *)
  140. edata.PointerToLinenumbers := 0;
  141. SetNumberOfRelocations(edata, ExpCount * 2 + 1);
  142. edata.NumberOfLinenumbers := 0X;
  143. edata.Characteristics := SHC_data;
  144. idata.Name := ".idata";
  145. idata.VirtualSize := 0;
  146. idata.VirtualAddress := 0;
  147. idata.SizeOfRawData := isize;
  148. idata.PointerToRawData := edata.PointerToRawData + edata.SizeOfRawData;
  149. (* idata.PointerToRelocations := 0; *)
  150. idata.PointerToLinenumbers := 0;
  151. SetNumberOfRelocations(idata, ICount(ImportTable, ILen));
  152. idata.NumberOfLinenumbers := 0X;
  153. idata.Characteristics := SHC_data;
  154. bss.Name := ".bss";
  155. bss.VirtualSize := 0;
  156. bss.VirtualAddress := 0;
  157. bss.SizeOfRawData := program.bss;
  158. bss.PointerToRawData := 0;
  159. bss.PointerToRelocations := 0;
  160. bss.PointerToLinenumbers := 0;
  161. bss.NumberOfRelocations := 0X;
  162. bss.NumberOfLinenumbers := 0X;
  163. bss.Characteristics := SHC_bss;
  164. flat.PointerToRelocations := idata.PointerToRawData + idata.SizeOfRawData;
  165. edata.PointerToRelocations := flat.PointerToRelocations + ORD(flat.NumberOfRelocations) * 10;
  166. idata.PointerToRelocations := edata.PointerToRelocations + ORD(edata.NumberOfRelocations) * 10;
  167. FileHeader.PointerToSymbolTable := idata.PointerToRelocations + ORD(idata.NumberOfRelocations) * 10;
  168. WR.Create(FileName);
  169. PE32.WriteFileHeader(FileHeader);
  170. PE32.WriteSectionHeader(flat);
  171. PE32.WriteSectionHeader(data);
  172. PE32.WriteSectionHeader(edata);
  173. PE32.WriteSectionHeader(idata);
  174. PE32.WriteSectionHeader(bss);
  175. CHL.WriteToFile(program.code);
  176. CHL.WriteToFile(program.data);
  177. exp := program.exp_list.first(BIN.EXPRT);
  178. WHILE exp # NIL DO
  179. WR.Write32LE(exp.nameoffs + edata.SizeOfRawData - ecount);
  180. WR.Write32LE(exp.label);
  181. exp := exp.next(BIN.EXPRT)
  182. END;
  183. WR.Write32LE(((ExpCount + 1) * 2 + 1) * SIZE_OF_DWORD);
  184. WR.Write32LE(ver);
  185. WR.Write32LE(0);
  186. PE32.WriteName(szversion);
  187. CHL.WriteToFile(program.export);
  188. FOR i := 0 TO ILen - 1 DO
  189. WR.Write32LE(CHL.GetInt(ImportTable, i))
  190. END;
  191. CHL.WriteToFile(program._import);
  192. Reloc(program);
  193. n := 0;
  194. exp := program.exp_list.first(BIN.EXPRT);
  195. WHILE exp # NIL DO
  196. WriteReloc(n, 3, 6);
  197. INC(n, 4);
  198. WriteReloc(n, 1, 6);
  199. INC(n, 4);
  200. exp := exp.next(BIN.EXPRT)
  201. END;
  202. WriteReloc(n, 3, 6);
  203. FOR i := 0 TO LibCount * 2 - 1 DO
  204. WriteReloc(i * SIZE_OF_DWORD, 4, 6)
  205. END;
  206. FOR i := LibCount * 2 TO ILen - 1 DO
  207. IF CHL.GetInt(ImportTable, i) # 0 THEN
  208. WriteReloc(i * SIZE_OF_DWORD, 4, 6)
  209. END
  210. END;
  211. PE32.WriteName("EXPORTS");
  212. WriteReloc(0, 3, 2);
  213. PE32.WriteName(".flat");
  214. WriteReloc(0, 1, 3);
  215. PE32.WriteName(".data");
  216. WriteReloc(0, 2, 3);
  217. PE32.WriteName(".edata");
  218. WriteReloc(0, 3, 3);
  219. PE32.WriteName(".idata");
  220. WriteReloc(0, 4, 3);
  221. PE32.WriteName(".bss");
  222. WriteReloc(0, 5, 3);
  223. WR.Write32LE(4);
  224. WR.Close
  225. END write;
  226. END MSCOFF.