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 MSCOFF;
  9.  
  10. IMPORT BIN, PE32, KOS, WR := WRITER, UTILS, ERRORS, LISTS, CHL := CHUNKLISTS;
  11.  
  12.  
  13. CONST
  14.  
  15.     SIZE_OF_DWORD = 4;
  16.  
  17.     (* SectionHeader.Characteristics *)
  18.  
  19.     SHC_flat  = 040500020H;
  20.     SHC_data  = 0C0500040H;
  21.     SHC_bss   = 0C03000C0H;
  22.  
  23.  
  24. TYPE
  25.  
  26.     FH = PE32.IMAGE_FILE_HEADER;
  27.  
  28.     SH = PE32.IMAGE_SECTION_HEADER;
  29.  
  30.  
  31. PROCEDURE WriteReloc (VirtualAddress, SymbolTableIndex, Type: INTEGER);
  32. BEGIN
  33.     WR.Write32LE(VirtualAddress);
  34.     WR.Write32LE(SymbolTableIndex);
  35.     WR.Write16LE(Type)
  36. END WriteReloc;
  37.  
  38.  
  39. PROCEDURE Reloc (program: BIN.PROGRAM);
  40. VAR
  41.     reloc:  BIN.RELOC;
  42.     offset: INTEGER;
  43.  
  44. BEGIN
  45.     reloc := program.rel_list.first(BIN.RELOC);
  46.     WHILE reloc # NIL DO
  47.  
  48.         offset := reloc.offset;
  49.         CASE reloc.opcode OF
  50.         |BIN.RIMP,
  51.          BIN.IMPTAB: WriteReloc(offset, 4, 6)
  52.         |BIN.RBSS:   WriteReloc(offset, 5, 6)
  53.         |BIN.RDATA:  WriteReloc(offset, 2, 6)
  54.         |BIN.RCODE:  WriteReloc(offset, 1, 6)
  55.         END;
  56.  
  57.         reloc := reloc.next(BIN.RELOC)
  58.     END;
  59. END Reloc;
  60.  
  61.  
  62. PROCEDURE RelocCount (program: BIN.PROGRAM): INTEGER;
  63. VAR
  64.     reloc:   BIN.RELOC;
  65.     iproc:   BIN.IMPRT;
  66.     res, L:  INTEGER;
  67.     offset:  INTEGER;
  68.     code:    CHL.BYTELIST;
  69.  
  70. BEGIN
  71.     res := 0;
  72.     code := program.code;
  73.     reloc := program.rel_list.first(BIN.RELOC);
  74.     WHILE reloc # NIL DO
  75.  
  76.         INC(res);
  77.         offset := reloc.offset;
  78.  
  79.         IF reloc.opcode = BIN.RIMP THEN
  80.             L := BIN.get32le(code, offset);
  81.             iproc := BIN.GetIProc(program, L);
  82.             BIN.put32le(code, offset, iproc.label)
  83.         END;
  84.  
  85.         IF reloc.opcode = BIN.RCODE THEN
  86.             L := BIN.get32le(code, offset);
  87.             BIN.put32le(code, offset, BIN.GetLabel(program, L))
  88.         END;
  89.  
  90.         reloc := reloc.next(BIN.RELOC)
  91.     END
  92.  
  93.     RETURN res
  94. END RelocCount;
  95.  
  96.  
  97. PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; ver: INTEGER);
  98. VAR
  99.     exp:   BIN.EXPRT;
  100.     n, i:  INTEGER;
  101.  
  102.     szversion: PE32.NAME;
  103.  
  104.     ImportTable: CHL.INTLIST;
  105.     ILen, LibCount, isize:  INTEGER;
  106.  
  107.     ExpCount: INTEGER;
  108.  
  109.     icount, ecount, dcount, ccount: INTEGER;
  110.  
  111.     FileHeader: FH;
  112.  
  113.     flat, data, edata, idata, bss: SH;
  114.  
  115.  
  116.     PROCEDURE ICount (ImportTable: CHL.INTLIST; ILen: INTEGER): INTEGER;
  117.     VAR
  118.         i, res: INTEGER;
  119.  
  120.     BEGIN
  121.         res := 0;
  122.  
  123.         FOR i := 0 TO ILen - 1 DO
  124.             IF CHL.GetInt(ImportTable, i) # 0 THEN
  125.                 INC(res)
  126.             END
  127.         END
  128.  
  129.         RETURN res
  130.     END ICount;
  131.  
  132.  
  133.     PROCEDURE SetNumberOfRelocations (VAR section: SH; NumberOfRelocations: INTEGER);
  134.     BEGIN
  135.         IF NumberOfRelocations >= 65536 THEN
  136.             ERRORS.Error(202)
  137.         END;
  138.         section.NumberOfRelocations := WCHR(NumberOfRelocations)
  139.     END SetNumberOfRelocations;
  140.  
  141.  
  142. BEGIN
  143.  
  144.     szversion := "version";
  145.  
  146.     ASSERT(LENGTH(szversion) = 7);
  147.  
  148.     KOS.Import(program, 0, ImportTable, ILen, LibCount, isize);
  149.     ExpCount := LISTS.count(program.exp_list);
  150.  
  151.     icount := CHL.Length(program._import);
  152.     dcount := CHL.Length(program.data);
  153.     ccount := CHL.Length(program.code);
  154.     ecount := CHL.Length(program.export);
  155.  
  156.     FileHeader.Machine               :=  014CX;
  157.     FileHeader.NumberOfSections      :=  5X;
  158.     FileHeader.TimeDateStamp         :=  UTILS.UnixTime();
  159.     (* FileHeader.PointerToSymbolTable  :=  0; *)
  160.     FileHeader.NumberOfSymbols       :=  6;
  161.     FileHeader.SizeOfOptionalHeader  :=  0X;
  162.     FileHeader.Characteristics       :=  0184X;
  163.  
  164.     flat.Name := ".flat";
  165.     flat.VirtualSize := 0;
  166.     flat.VirtualAddress := 0;
  167.     flat.SizeOfRawData := ccount;
  168.     flat.PointerToRawData := ORD(FileHeader.NumberOfSections) * PE32.SIZE_OF_IMAGE_SECTION_HEADER + PE32.SIZE_OF_IMAGE_FILE_HEADER;
  169.     (* flat.PointerToRelocations := 0; *)
  170.     flat.PointerToLinenumbers := 0;
  171.     SetNumberOfRelocations(flat, RelocCount(program));
  172.     flat.NumberOfLinenumbers := 0X;
  173.     flat.Characteristics := SHC_flat;
  174.  
  175.     data.Name := ".data";
  176.     data.VirtualSize := 0;
  177.     data.VirtualAddress := 0;
  178.     data.SizeOfRawData := dcount;
  179.     data.PointerToRawData := flat.PointerToRawData + flat.SizeOfRawData;
  180.     data.PointerToRelocations := 0;
  181.     data.PointerToLinenumbers := 0;
  182.     data.NumberOfRelocations := 0X;
  183.     data.NumberOfLinenumbers := 0X;
  184.     data.Characteristics := SHC_data;
  185.  
  186.     edata.Name := ".edata";
  187.     edata.VirtualSize := 0;
  188.     edata.VirtualAddress := 0;
  189.     edata.SizeOfRawData := ((ExpCount + 1) * 2 + 1) * SIZE_OF_DWORD + LENGTH(szversion) + 1 + ecount;
  190.     edata.PointerToRawData := data.PointerToRawData + data.SizeOfRawData;
  191.     (* edata.PointerToRelocations := 0; *)
  192.     edata.PointerToLinenumbers := 0;
  193.     SetNumberOfRelocations(edata, ExpCount * 2 + 1);
  194.     edata.NumberOfLinenumbers := 0X;
  195.     edata.Characteristics := SHC_data;
  196.  
  197.     idata.Name := ".idata";
  198.     idata.VirtualSize := 0;
  199.     idata.VirtualAddress := 0;
  200.     idata.SizeOfRawData := isize;
  201.     idata.PointerToRawData := edata.PointerToRawData + edata.SizeOfRawData;
  202.     (* idata.PointerToRelocations := 0; *)
  203.     idata.PointerToLinenumbers := 0;
  204.     SetNumberOfRelocations(idata, ICount(ImportTable, ILen));
  205.     idata.NumberOfLinenumbers := 0X;
  206.     idata.Characteristics := SHC_data;
  207.  
  208.     bss.Name := ".bss";
  209.     bss.VirtualSize := 0;
  210.     bss.VirtualAddress := 0;
  211.     bss.SizeOfRawData := program.bss;
  212.     bss.PointerToRawData := 0;
  213.     bss.PointerToRelocations := 0;
  214.     bss.PointerToLinenumbers := 0;
  215.     bss.NumberOfRelocations := 0X;
  216.     bss.NumberOfLinenumbers := 0X;
  217.     bss.Characteristics := SHC_bss;
  218.  
  219.     flat.PointerToRelocations := idata.PointerToRawData + idata.SizeOfRawData;
  220.     edata.PointerToRelocations := flat.PointerToRelocations + ORD(flat.NumberOfRelocations) * 10;
  221.     idata.PointerToRelocations := edata.PointerToRelocations + ORD(edata.NumberOfRelocations) * 10;
  222.  
  223.     FileHeader.PointerToSymbolTable := idata.PointerToRelocations + ORD(idata.NumberOfRelocations) * 10;
  224.  
  225.     WR.Create(FileName);
  226.  
  227.     PE32.WriteFileHeader(FileHeader);
  228.  
  229.     PE32.WriteSectionHeader(flat);
  230.     PE32.WriteSectionHeader(data);
  231.     PE32.WriteSectionHeader(edata);
  232.     PE32.WriteSectionHeader(idata);
  233.     PE32.WriteSectionHeader(bss);
  234.  
  235.     CHL.WriteToFile(program.code);
  236.     CHL.WriteToFile(program.data);
  237.  
  238.     exp := program.exp_list.first(BIN.EXPRT);
  239.     WHILE exp # NIL DO
  240.         WR.Write32LE(exp.nameoffs + edata.SizeOfRawData - ecount);
  241.         WR.Write32LE(exp.label);
  242.         exp := exp.next(BIN.EXPRT)
  243.     END;
  244.  
  245.     WR.Write32LE(((ExpCount + 1) * 2 + 1) * SIZE_OF_DWORD);
  246.     WR.Write32LE(ver);
  247.  
  248.     WR.Write32LE(0);
  249.  
  250.     PE32.WriteName(szversion);
  251.     CHL.WriteToFile(program.export);
  252.  
  253.     FOR i := 0 TO ILen - 1 DO
  254.         WR.Write32LE(CHL.GetInt(ImportTable, i))
  255.     END;
  256.  
  257.     CHL.WriteToFile(program._import);
  258.  
  259.     Reloc(program);
  260.  
  261.     n := 0;
  262.     exp := program.exp_list.first(BIN.EXPRT);
  263.     WHILE exp # NIL DO
  264.         WriteReloc(n, 3, 6);
  265.         INC(n, 4);
  266.  
  267.         WriteReloc(n, 1, 6);
  268.         INC(n, 4);
  269.  
  270.         exp := exp.next(BIN.EXPRT)
  271.     END;
  272.  
  273.     WriteReloc(n, 3, 6);
  274.  
  275.     FOR i := 0 TO LibCount * 2 - 1 DO
  276.         WriteReloc(i * SIZE_OF_DWORD, 4, 6)
  277.     END;
  278.  
  279.     FOR i := LibCount * 2 TO ILen - 1 DO
  280.         IF CHL.GetInt(ImportTable, i) # 0 THEN
  281.             WriteReloc(i * SIZE_OF_DWORD, 4, 6)
  282.         END
  283.     END;
  284.  
  285.     PE32.WriteName("EXPORTS");
  286.     WriteReloc(0, 3, 2);
  287.  
  288.     PE32.WriteName(".flat");
  289.     WriteReloc(0, 1, 3);
  290.  
  291.     PE32.WriteName(".data");
  292.     WriteReloc(0, 2, 3);
  293.  
  294.     PE32.WriteName(".edata");
  295.     WriteReloc(0, 3, 3);
  296.  
  297.     PE32.WriteName(".idata");
  298.     WriteReloc(0, 4, 3);
  299.  
  300.     PE32.WriteName(".bss");
  301.     WriteReloc(0, 5, 3);
  302.  
  303.     WR.Write32LE(4);
  304.  
  305.     WR.Close
  306. END write;
  307.  
  308.  
  309. END MSCOFF.