Subversion Repositories Kolibri OS

Rev

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

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