195 lines
7.5 KiB
ObjectPascal
195 lines
7.5 KiB
ObjectPascal
{**************************************************************************************************}
|
|
{ }
|
|
{ Project JEDI Code Library (JCL) }
|
|
{ }
|
|
{ The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
|
|
{ you may not use this file except in compliance with the License. You may obtain a copy of the }
|
|
{ License at http://www.mozilla.org/MPL/ }
|
|
{ }
|
|
{ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
|
|
{ ANY KIND, either express or implied. See the License for the specific language governing rights }
|
|
{ and limitations under the License. }
|
|
{ }
|
|
{ The Original Code is formConverter.pas. }
|
|
{ }
|
|
{ The Initial Developer of the Original Code is Elahn Ientile }
|
|
{ Portions created by Elahn Ientile are Copyright (C) Elahn Ientile. }
|
|
{ }
|
|
{**************************************************************************************************}
|
|
{ }
|
|
{ Converts a report send by TExceptionDialogMail where no Debug Info or Map file was present into }
|
|
{ a report equivalent to one where Debug Info or Map file was present, i.e. inc. line numbers, etc }
|
|
{ }
|
|
{ Note: to generate a Map file on compile, add "-GD" to [project name].cfg }
|
|
{ the map file used must be the one generated when that copy of the program was compiled }
|
|
{ }
|
|
{ Unit owner: Elahn Ientile }
|
|
{ Last modified: $Date: 2006-09-03 11:36:16 +0200 (dim., 03 sept. 2006) $ }
|
|
{ }
|
|
{**************************************************************************************************}
|
|
|
|
unit formConverter;
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
|
|
Dialogs, StdCtrls, JclDebug;
|
|
|
|
type
|
|
TfrmConverter = class(TForm)
|
|
btnConvert: TButton;
|
|
txtReportFile: TEdit;
|
|
txtMapFile: TEdit;
|
|
btnReportFile: TButton;
|
|
btnMapFile: TButton;
|
|
dlgOpen: TOpenDialog;
|
|
procedure btnConvertClick(Sender: TObject);
|
|
procedure btnReportFileClick(Sender: TObject);
|
|
procedure btnMapFileClick(Sender: TObject);
|
|
private
|
|
FScanner: TJclMapScanner;
|
|
public
|
|
procedure ConvertFile(AMap, AInput, AOutput: TFileName);
|
|
function FormatInfo(var Info: TJclLocationInfo;
|
|
IncludeAddressOffset: Boolean = True;
|
|
IncludeStartProcLineOffset: Boolean = True): string;
|
|
function GetVALocationInfo(const VA: DWORD; var Info: TJclLocationInfo): Boolean;
|
|
end;
|
|
|
|
var
|
|
frmConverter: TfrmConverter;
|
|
|
|
implementation
|
|
|
|
{$R *.dfm}
|
|
|
|
procedure TfrmConverter.btnConvertClick(Sender: TObject);
|
|
var
|
|
lStr, lExt: string;
|
|
begin
|
|
if not FileExists(txtReportFile.Text) then
|
|
ShowMessage('Report File does not exist.')
|
|
else if not FileExists(txtMapFile.Text) then
|
|
ShowMessage('Map File does not exist.')
|
|
else
|
|
begin
|
|
lStr := txtReportFile.Text;
|
|
lExt := ExtractFileExt(lStr);
|
|
Insert('.converted', lStr, Length(lStr) + 1 - Length(lExt));
|
|
ConvertFile(txtMapFile.Text, txtReportFile.Text, lStr);
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmConverter.ConvertFile(AMap, AInput, AOutput: TFileName);
|
|
var
|
|
ls: TStringList;
|
|
i: Integer;
|
|
lInStackList: Boolean;
|
|
s: string;
|
|
VA: DWORD;
|
|
Info: TJclLocationInfo;
|
|
begin
|
|
FScanner := TJclMapScanner.Create(AMap);
|
|
ls := TStringList.Create;
|
|
try
|
|
ls.LoadFromFile(AInput);
|
|
if ls.Count = 0 then
|
|
Exit;
|
|
lInStackList := False;
|
|
i := 0;
|
|
while i < ls.Count do
|
|
begin
|
|
if (Copy(ls[i], 1, 3) = '---') then
|
|
if lInStackList then
|
|
Break
|
|
else if Copy(ls[i+1], 1, 10) = 'Stack list' then
|
|
begin
|
|
lInStackList := True;
|
|
Inc(i, 2);
|
|
end;
|
|
if lInStackList and (Copy(ls[i], 1, 1) = '(') then
|
|
begin
|
|
s := '$' + Copy(ls[i], 2, 8);
|
|
VA := DWORD(StrToInt64(s));
|
|
if GetVALocationInfo(VA, Info) then
|
|
ls[i] := ls[i] + FormatInfo(Info);
|
|
end;
|
|
Inc(i);
|
|
end;
|
|
ls.SaveToFile(AOutput);
|
|
ShowMessage('Successfully converted. Output filename:' + #13#10#13#10 + AOutput);
|
|
finally
|
|
ls.Free;
|
|
end;
|
|
end;
|
|
|
|
function TfrmConverter.FormatInfo(var Info: TJclLocationInfo;
|
|
IncludeAddressOffset, IncludeStartProcLineOffset: Boolean): string;
|
|
var
|
|
StartProcInfo: TJclLocationInfo;
|
|
OffsetStr, StartProcOffsetStr: string;
|
|
begin
|
|
OffsetStr := '';
|
|
with Info do
|
|
begin
|
|
if LineNumber > 0 then
|
|
begin
|
|
if IncludeStartProcLineOffset and GetVALocationInfo(DWORD(Cardinal(Info.Address) -
|
|
Cardinal(Info.OffsetFromProcName)), StartProcInfo) and (StartProcInfo.LineNumber > 0) then
|
|
StartProcOffsetStr := Format(' + %d', [LineNumber - StartProcInfo.LineNumber])
|
|
else
|
|
StartProcOffsetStr := '';
|
|
if IncludeAddressOffset then
|
|
begin
|
|
if OffsetFromLineNumber >= 0 then
|
|
OffsetStr := Format(' + $%x', [OffsetFromLineNumber])
|
|
else
|
|
OffsetStr := Format(' - $%x', [-OffsetFromLineNumber])
|
|
end;
|
|
Result := Format(' %s.%s (Line %u, "%s"%s)%s', [UnitName, ProcedureName, LineNumber,
|
|
SourceName, StartProcOffsetStr, OffsetStr]);
|
|
end
|
|
else
|
|
begin
|
|
if IncludeAddressOffset then
|
|
OffsetStr := Format(' + $%x', [OffsetFromProcName]);
|
|
if UnitName <> '' then
|
|
Result := Format(' %s.%s%s', [UnitName, ProcedureName, OffsetStr])
|
|
else
|
|
Result := Format(' %s%s', [ProcedureName, OffsetStr]);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TfrmConverter.GetVALocationInfo(const VA: DWORD; var Info: TJclLocationInfo): Boolean;
|
|
begin
|
|
with FScanner do
|
|
begin
|
|
Info.UnitName := ModuleNameFromAddr(VA);
|
|
Result := (Info.UnitName <> '');
|
|
if Result then
|
|
begin
|
|
Info.Address := Pointer(VA);
|
|
Info.ProcedureName := ProcNameFromAddr(VA, Info.OffsetFromProcName);
|
|
Info.LineNumber := LineNumberFromAddr(VA, Info.OffsetFromLineNumber);
|
|
Info.SourceName := SourceNameFromAddr(VA);
|
|
Info.DebugInfo := nil;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TfrmConverter.btnReportFileClick(Sender: TObject);
|
|
begin
|
|
if dlgOpen.Execute then
|
|
txtReportFile.Text := dlgOpen.FileName;
|
|
end;
|
|
|
|
procedure TfrmConverter.btnMapFileClick(Sender: TObject);
|
|
begin
|
|
if dlgOpen.Execute then
|
|
txtMapFile.Text := dlgOpen.FileName;
|
|
end;
|
|
|
|
end.
|