Subversion Repositories Kolibri OS

Rev

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

  1. {$mode objfpc}
  2. {$apptype console}
  3.  
  4. program exe2kos;
  5.  
  6. uses
  7.   SysUtils, Classes, ExeTypes, KosTypes;
  8.  
  9. const
  10.   ARGS_SIZE = 512;
  11.   PATH_SIZE = 512;
  12.  
  13. type
  14.   EExeError = class(Exception);
  15.  
  16.   TExeImage = class;
  17.   TExeImageSection = class;
  18.  
  19.   TExeImageSection = class
  20.   private
  21.     FExeImage: TExeImage;
  22.     FHeader: IMAGE_SECTION_HEADER;
  23.     FName: String;
  24.     procedure Read(var Buffer);
  25.   public
  26.     constructor Create(AExeImage: TExeImage; APosition: DWord);
  27.     property Name: String read FName;
  28.     property VirtualSize: DWord read FHeader.PhysicalAddress;
  29.     property SectionRVA: DWord read FHeader.VirtualAddress;
  30.     property PhysicalSize: DWord read FHeader.SizeOfRawData;
  31.     property PhysicalOffset: DWord read FHeader.PointerToRawData;
  32.     property ObjectFlags: DWord read FHeader.Characteristics;
  33.   end;
  34.  
  35.   TExeImageSections = class
  36.   private
  37.     FCount: DWord;
  38.     FItems: array of TExeImageSection;
  39.     function GetItem(Index: DWord): TExeImageSection;
  40.   public
  41.     constructor Create(AExeImage: TExeImage; APosition, ACount: DWord);
  42.     destructor Destroy; override;
  43.     function ByName(AName: String): TExeImageSection;
  44.     property Count: DWord read FCount;
  45.     property Items[Index: DWord]: TExeImageSection read GetItem; default;
  46.   end;
  47.  
  48.   TExeImage = class
  49.   private
  50.     FFileName: String;
  51.     FFileStream: TStream;
  52.     FDosHeader: IMAGE_DOS_HEADER;
  53.     FNTHeader: IMAGE_NT_HEADERS;
  54.     FSections: TExeImageSections;
  55.     procedure Read(var Buffer; Position, Size: Longint);
  56.     function GetSizeOfCode(): DWord;
  57.     function GetSizeOfInitData(): DWord;
  58.     function GetSizeOfUnInitData(): DWord;
  59.     function GetEntryPoint(): DWord;
  60.     function GetImageBase(): DWord;
  61.     function GetObjectAlign(): DWord;
  62.     function GetFileAlign(): DWord;
  63.     function GetImageSize(): DWord;
  64.     function GetHeaderSize(): DWord;
  65.     function GetStackReserveSize(): DWord;
  66.     function GetStackCommitSize(): DWord;
  67.     function GetHeapReserveSize(): DWord;
  68.     function GetHeapCommitSize(): DWord;
  69.   public
  70.     constructor Create(AFileName: String);
  71.     destructor Destroy; override;
  72.     property FileName: String read FFileName;
  73.     property Sections: TExeImageSections read FSections;
  74.     property SizeOfCode: DWord read GetSizeOfCode;
  75.     property SizeOfInitializedData: DWord read GetSizeOfInitData;
  76.     property SizeOfUninitializedData: DWord read GetSizeOfUnInitData;
  77.     property EntryPoint: DWord read FNTHeader.OptionalHeader.AddressOfEntryPoint{GetEntryPoint};
  78.     property ImageBase: DWord read FNTHeader.OptionalHeader.ImageBase{GetImageBase};
  79.     property ObjectAlign: DWord read GetObjectAlign;
  80.     property FileAlign: DWord read GetFileAlign;
  81.     property ImageSize: DWord read GetImageSize;
  82.     property HeaderSize: DWord read GetHeaderSize;
  83.     property StackReserveSize: DWord read GetStackReserveSize;
  84.     property StackCommitSize: DWord read GetStackCommitSize;
  85.     property HeapReserveSize: DWord read GetHeapReserveSize;
  86.     property HeapCommitSize: DWord read GetHeapCommitSize;
  87.   end;
  88.  
  89.  
  90. constructor TExeImage.Create(AFileName: String);
  91. begin
  92.   FFileName := AFileName;
  93.   FFileStream := TFileStream.Create(FFileName, fmOpenRead);
  94.  
  95.   Read(FDosHeader, 0, SizeOf(FDosHeader));
  96.   if not FDosHeader.e_magic = IMAGE_DOS_SIGNATURE then
  97.     EExeError.Create('Unrecognized file format');
  98.  
  99.   Read(FNTHeader, FDosHeader.e_lfanew, SizeOf(FNTHeader));
  100.   if FNTHeader.Signature <> IMAGE_NT_SIGNATURE then
  101.     EExeError.Create('Not a PE (WIN32 Executable) file');
  102.  
  103.   FSections := TExeImageSections.Create(Self,
  104.     FDosHeader.e_lfanew + SizeOf(FNTHeader), FNTHeader.FileHeader.NumberOfSections);
  105. end;
  106.  
  107. destructor TExeImage.Destroy;
  108. begin
  109.   FSections.Free;
  110.   FFileStream.Free;
  111. end;
  112.  
  113. procedure TExeImage.Read(var Buffer; Position, Size: Longint);
  114. begin
  115.   FFileStream.Position := Position;
  116.   if FFileStream.Read(Buffer, Size) <> Size then
  117.     EExeError.Create('Damaged or unrecognized file');
  118. end;
  119.  
  120. function TExeImage.GetSizeOfCode(): DWord;
  121. begin
  122.   Result := FNTHeader.OptionalHeader.SizeOfCode;
  123. end;
  124.  
  125. function TExeImage.GetSizeOfInitData(): DWord;
  126. begin
  127.   Result := FNTHeader.OptionalHeader.SizeOfInitializedData;
  128. end;
  129.  
  130. function TExeImage.GetSizeOfUnInitData(): DWord;
  131. begin
  132.   Result := FNTHeader.OptionalHeader.SizeOfUninitializedData;
  133. end;
  134.  
  135. function TExeImage.GetEntryPoint(): DWord;
  136. begin
  137.   Result := FNTHeader.OptionalHeader.AddressOfEntryPoint;
  138. end;
  139.  
  140. function TExeImage.GetImageBase(): DWord;
  141. begin
  142.   Result := FNTHeader.OptionalHeader.ImageBase;
  143. end;
  144.  
  145. function TExeImage.GetObjectAlign(): DWord;
  146. begin
  147.   Result := FNTHeader.OptionalHeader.SectionAlignment;
  148. end;
  149.  
  150. function TExeImage.GetFileAlign(): DWord;
  151. begin
  152.   Result := FNTHeader.OptionalHeader.FileAlignment;
  153. end;
  154.  
  155. function TExeImage.GetImageSize(): DWord;
  156. begin
  157.   Result := FNTHeader.OptionalHeader.SizeOfImage;
  158. end;
  159.  
  160. function TExeImage.GetHeaderSize(): DWord;
  161. begin
  162.   Result := FNTHeader.OptionalHeader.SizeOfHeaders;
  163. end;
  164.  
  165. function TExeImage.GetStackReserveSize(): DWord;
  166. begin
  167.   Result := FNTHeader.OptionalHeader.SizeOfStackReserve;
  168. end;
  169.  
  170. function TExeImage.GetStackCommitSize(): DWord;
  171. begin
  172.   Result := FNTHeader.OptionalHeader.SizeOfStackCommit;
  173. end;
  174.  
  175. function TExeImage.GetHeapReserveSize(): DWord;
  176. begin
  177.   Result := FNTHeader.OptionalHeader.SizeOfHeapReserve;
  178. end;
  179.  
  180. function TExeImage.GetHeapCommitSize(): DWord;
  181. begin
  182.   Result := FNTHeader.OptionalHeader.SizeOfHeapCommit;
  183. end;
  184.  
  185.  
  186. constructor TExeImageSections.Create(AExeImage: TExeImage; APosition, ACount: DWord);
  187. var
  188.   i: Integer;
  189. begin
  190.   FCount := ACount;
  191.   SetLength(FItems, ACount);
  192.   for i := 0 to ACount - 1 do
  193.   begin
  194.     FItems[i] := TExeImageSection.Create(AExeImage, APosition);
  195.     Inc(APosition, SizeOf(IMAGE_SECTION_HEADER));
  196.   end;
  197. end;
  198.  
  199. destructor TExeImageSections.Destroy;
  200. var
  201.   i: Integer;
  202. begin
  203.   for i := 0 to Length(FItems) - 1 do FItems[i].Free;
  204.   SetLength(FItems, 0);
  205. end;
  206.  
  207. function TExeImageSections.GetItem(Index: DWord): TExeImageSection;
  208. begin
  209.   Result := FItems[Index];
  210. end;
  211.  
  212. function TExeImageSections.ByName(AName: String): TExeImageSection;
  213. var
  214.   i: Integer;
  215. begin
  216.   for i := 0 to Length(FItems) - 1 do
  217.   if FItems[i].Name = AName then
  218.   begin
  219.     Result := FItems[i];
  220.     Exit;
  221.   end;
  222.   Result := nil;
  223. end;
  224.  
  225.  
  226.  
  227. constructor TExeImageSection.Create(AExeImage: TExeImage; APosition: DWord);
  228. begin
  229.   FExeImage := AExeImage;
  230.   FExeImage.Read(FHeader, APosition, SizeOf(FHeader));
  231.   FName := FHeader.Name;
  232. end;
  233.  
  234. procedure TExeImageSection.Read(var Buffer);
  235. begin
  236.   FExeImage.Read(Buffer, PhysicalOffset, PhysicalSize);
  237. end;
  238.  
  239.  
  240. procedure WriteHead(s: String);
  241. var
  242.   i: Integer;
  243. begin
  244.   WriteLn;
  245.   WriteLn(s);
  246.   for i:=1 to Length(s) do Write('-');
  247.   WriteLn;
  248. end;
  249.  
  250. procedure Convert(InputFile, OutputFile: String);
  251. var
  252.   ExeImage: TExeImage;
  253.   KosHeader: TKosHeader;
  254.   FileStream: TStream;
  255.   ImageBase, ImageSize, Size: DWord;
  256.   Buffer: Pointer;
  257.   i: Integer;
  258. begin
  259.   ExeImage := TExeImage.Create(InputFile);
  260.   WriteHead('NT Header');
  261.   WriteLn(Format('Size of Code: %d', [ExeImage.SizeOfCode]));
  262.   WriteLn(Format('Size of Init Data: %d', [ExeImage.SizeOfInitializedData]));
  263.   WriteLn(Format('Size of UnInit Data: %d', [ExeImage.SizeOfUninitializedData]));
  264.   WriteLn(Format('Entry Point: 0x%x', [ExeImage.EntryPoint]));
  265.   WriteLn(Format('Image Base: 0x%x', [ExeImage.ImageBase]));
  266.   WriteLn(Format('Object Align: %d; File Align: %d', [ExeImage.ObjectAlign, ExeImage.FileAlign]));
  267.   WriteLn(Format('Image Size: %d; Header Size: %d', [ExeImage.ImageSize, ExeImage.HeaderSize]));
  268.   WriteLn(Format('Stack Reserve Size: %d; Stack Commit Size: %d', [ExeImage.StackReserveSize, ExeImage.StackCommitSize]));
  269.   WriteLn(Format('Heap Reserve Size: %d; Heap Comit Size: %d', [ExeImage.HeapReserveSize, ExeImage.HeapCommitSize]));
  270.  
  271.   ImageBase := ExeImage.ImageBase;
  272.   ImageSize := 0;
  273.  
  274.   { чряшё№ ёхъЎшщ }
  275.   FileStream := TFileStream.Create(OutputFile, fmCreate);
  276.   for i:=0 to ExeImage.Sections.Count-1 do
  277.   with ExeImage.Sections[i] do
  278.   begin
  279.     WriteHead(Format('Section %s (0x%x)', [Name, ObjectFlags]));
  280.     WriteLn(Format('Section RVA/Size: 0x%x / %d', [SectionRVA, VirtualSize]));
  281.     WriteLn(Format('Physical Offset/Size: 0x%x / %d', [PhysicalOffset, PhysicalSize]));
  282.  
  283.     Size := ImageBase + SectionRVA;
  284.     FileStream.Position := Size;
  285.     Inc(Size, VirtualSize);
  286.     if Size > ImageSize then ImageSize := Size;
  287.  
  288.     if PhysicalSize > 0 then
  289.     begin
  290.       GetMem(Buffer, PhysicalSize);
  291.       Read(Buffer^);
  292.       FileStream.Write(Buffer^, PhysicalSize);
  293.       FreeMem(Buffer);
  294.     end;
  295.     {if VirtualSize - PhysicalSize > 0 then
  296.     begin
  297.       GetMem(Buffer, VirtualSize - PhysicalSize);
  298.       FillByte(Buffer^, VirtualSize - PhysicalSize, 0);
  299.       FileStream.Write(Buffer^, VirtualSize - PhysicalSize);
  300.       FreeMem(Buffer);
  301.     end;}
  302.   end;
  303.  
  304.   FillByte(KosHeader, SizeOf(KosHeader), 0);
  305.   with KosHeader do
  306.   begin
  307.     sign    := KOS_SIGN;
  308.     version := 1;
  309.     start   := ImageBase + ExeImage.EntryPoint;
  310.     size    := FileStream.Size;
  311.     args    := ImageSize;
  312.     path    := args + ARGS_SIZE;
  313.     stack   := path + PATH_SIZE + ExeImage.StackReserveSize;
  314.     memory  := stack;
  315.   end;
  316.   FileStream.Position := 0;
  317.   FileStream.Write(KosHeader, SizeOf(KosHeader));
  318.   FileStream.Free();
  319. end;
  320.  
  321.  
  322. var
  323.   InputFile, OutputFile: String;
  324. begin
  325.   if ParamCount < 1 then
  326.   begin
  327.     WriteLn(Format('%s <exe input file> [kos output file]', [ExtractFileName(ParamStr(0))]));
  328.     Exit;
  329.   end;
  330.  
  331.   InputFile := ParamStr(1);
  332.   if ParamCount <2 then
  333.     OutputFile := ChangeFileExt(InputFile, '') else
  334.     OutputFile := ParamStr(2);
  335.  
  336.   if InputFile = OutputFile then
  337.     WriteLn(Format('Cannot convert the file "%s" onto itself.', [InputFile])) else
  338.  
  339.   if not FileExists(InputFile) then
  340.     WriteLn(Format('Input the file "%s", not found.', [InputFile])) else
  341.  
  342.   begin
  343.     WriteLn(Format('Converting "%s" to "%s"...', [InputFile, OutputFile]));
  344.     Convert(InputFile, OutputFile);
  345.   end;
  346. end.
  347.