Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
616 bw 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  [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.