📄 procs.pas
字号:
begin
if FinaSize <> 0 then
raise EDecompilerError.Create('There alredy is some fina code??');
I := FindLastSimpleCallTo(TPEFileClass(PEFileClass).Units.SystemUnit.FindProcByName('@ClassDestroy').Address,
Address, Size) - Address;
if I <> -Integer(Address) then
begin
AfterFinaSize := Size - I - 5;
FinaSize := 5;
FHasClassDestroy := True;
end;
end;
end;
// Call the next event handler
if Sender <> nil then
Sender.CallNext(ProcSizeChange);
end;
{ TInitProcEnh }
constructor TInitProcEnh.CreateEnh(Proc: TProc);
begin
inherited CreateEnh(Proc);
Proc.OnInitSizeChange.Add(ProcInitSizeChange);
Proc.OnSizeChange.Add(ProcInitSizeChange);
ProcInitSizeChange(nil);
end;
destructor TInitProcEnh.Destroy;
begin
Proc.OnSizeChange.Remove(ProcInitSizeChange);
Proc.OnInitSizeChange.Remove(ProcInitSizeChange);
inherited Destroy;
end;
procedure TInitProcEnh.ProcInitSizeChange(Sender: TmlneMethodList);
var
AfterInitAddress: PChar;
Table: PChar;
J, K: Integer;
PEFileClass: TPEFileClass;
begin
if Proc.ImportInfo.Imported then Exit;
PEFileClass := TPEFileClass(Proc.PEFileClass);
AfterInitAddress := Proc.Address + Proc.BeforeInitSize + Proc.InitSize;
// Check for init res string imort
if (not FHasInitResStringImport) and
(PEFileClass.StringInfos.Count <> 0) and
(PEFileClass.VarInfos.Count <> 0) and
(AfterInitAddress + 10 <= Proc.Address + Proc.ProcSize) and
(AfterInitAddress[0] = #$B8) and
(AfterInitAddress[5] = #$E8) and
(TPEFileClass(PEFileClass).FindSystemProc(InitResStringImportsProcName) <> nil) and
(PDWord(AfterInitAddress + 6)^ + AfterInitAddress + 10 = TPEFileClass(PEFileClass).FindSystemProc(InitResStringImportsProcName).Address) then
begin
Table := PPChar(AfterInitAddress + 1)^;
// Create the vars.
for J := 0 to PDWord(Table)^ -1 do
begin
// The assigend var.
K := PEFileClass.VarInfos.IndexOfAddress(PPChar(Table + J * 8 + 4)^);
if K = -1 then
raise EDecompilerError.Create('Res string import var isn''t a var');
PEFileClass.VarInfos[K].AUnit := Proc.AUnit;
PEFileClass.VarInfos[K].AddDecomp(PEFileClass.StringInfos.FindString(PPChar(PPChar(Table + J * 8 +8)^)^),
PPChar(Table + J * 8 + 4)^ - PEFileClass.VarInfos[K].Address, dtResString);
end;
// Create a Decomps the fill the block
with TDecompItem.Create(PEFileClass.miscs) do
begin
Address := Table;
RefAddress := Address;
Size := PDWord(Table)^ * 8 + 4;
Comments.Add('InitResStringImports Table filler');
end;
// Add the call the InitImports to the auto generated Code.
{$IFOPT D+}
SendDebug(Format('Found an init res string imports %p', [Pointer(Table)]));
{$ENDIF}
FHasInitResStringImport := True;
Proc.InitSize := Proc.InitSize + 10;
// Exit the proc because we are already called by changed the initsize.
Exit;
end;
// Check for init import
if (PEFileClass.FindSystemProc(InitImportsProcName) <> nil) and
(not HasInitImport) and
(PEFileClass.StringInfos.Count <> 0) and
(PEFileClass.VarInfos.Count <> 0) and
(AfterInitAddress + 10 <= Proc.Address + Proc.ProcSize) and
(AfterInitAddress[0] = #$B8) and
(AfterInitAddress[5] = #$E8) and
(PDWord(AfterInitAddress + 6)^ + AfterInitAddress + 10 =
PEFileClass.FindSystemProc(InitImportsProcName).Address) then
begin
Table := PPChar(AfterInitAddress + 1)^;
// Apply the fixup
asm
mov eax, Table
call system.@InitImports
end;
// Create the vars.
for J := 0 to PDWord(Table)^ -1 do
begin
K := PEFileClass.VarInfos.IndexOfAddress(PPChar(Table + J * 12 + 4)^);
if K = -1 then
raise EDecompilerError.Create('Address not in a var');
PEFileClass.VarInfos[K].AUnit := Proc.AUnit;
if PPChar(Table + J * 12 + 8)^ >= PEFileClass.Data then
begin
K := PEFileClass.VarInfos.IndexOfAddress(PPChar(Table + J*12 + 8)^);
if K = -1 then
raise EDecompilerError.Create('Address not in a var *');
with PEFileClass.VarInfos[K] do
begin
Size := 4;
Name := Format('!VarCorrector%p', [Pointer(Address)]);
AUnit := Proc.AUnit;
RefVar := True;
end;
end;
end;
// Create a Decomps the fill the block
with TDecompItem.Create(PEFileClass.miscs) do
begin
Address := Table;
RefAddress := Address;
Size := PDWord(Table)^ * 12 + 4;
Comments.Add('InitStringImports Table filler');
end;
// Add the call the InitImports to the auto generated Code.
{$IFOPT D+}
SendDebug(Format('Found an init imports %p', [Pointer(Table)]));
{$ENDIF}
FHasInitImport := True;
Proc.InitSize := Proc.InitSize + 10;
Exit;
end;
// Call the next event handler.
if Sender <> nil then
Sender.CallNext(ProcInitSizeChange);
end;
{ TInitProc }
constructor TInitProc.CreateInit(Procs: TProcs; Address: PChar);
var
ASize: Integer;
begin
inherited Create(Procs, Address);
PossProcTypes := [ptInitialization];
if (Address[0] = #$FF) and (Address[1] = #$25) then
begin
// This is an imported init proc.
ProcSize := 0;
Size := 8;
Exit;
end;
ProcSize := GetProcSize(Address);
Size := Align4(ProcSize);
FinaSize := 1;
// If Size > 8 a jnb must also be skipped.
if Size > 8 then
begin
// The init code starts at sub dword Ptr [], $01; jnz ...
while PWord(Address + FBeforeInitSize)^ <> $2D83 do
begin
Inc(FBeforeInitSize);
if BeforeInitSize > Size then
raise EDecompilerError.Create('Wrong Init section');
end;
with TDisAsm.Create do
try
GetInstruction(Address + BeforeInitSize + 7, ASize);
finally
Free;
end;
InitSize := 7 + ASize;
end
else
InitSize := 7;
end;
constructor TInitProc.CreateFInit(Procs: TProcs; Address: PChar);
var
ASize: Integer;
begin
inherited Create(Procs, Address);
PossProcTypes := [ptFinalization];
if (Address[0] = #$FF) and (Address[1] = #$25) then
begin
// This is an imported FInit proc.
ProcSize := 0;
Size := 8;
Exit;
end;
ProcSize := GetProcSize(Address);
Size := Align4(ProcSize);
if Size > $30 then
begin
with TDisAsm.Create do
try
GetInstruction(Address + $17, ASize);
finally
Free;
end;
InitSize := $17 + ASize;
end
else
InitSize := $17;
FinaSize := $17;
end;
{ TProcs }
constructor TProcs.CreateDecomp(PEFileClass: TPEFile);
begin
inherited CreateDecomp(PEFileClass);
FOnLoadPublishedMethods := TmlneMethodList.Create;
end;
destructor TProcs.Destroy;
begin
FOnLoadPublishedMethods.Free;
inherited Destroy;
end;
procedure TProcs.LoadPublishedMethods;
var
MethodTable: PMethodTable;
MethodEntry: PMethodEntry;
I, J: Integer;
Proc: TProc;
begin
with TPEFileClass(PEFileClass) do
// Loop all the classes.
for I := 0 to Classes.Count -1 do
begin
// Get the method table.
MethodTable := GetMethodTable(Classes[I].AClass);
if MethodTable <> nil then
for J := 0 to MethodTable^.Count -1 do
begin
MethodEntry := GetMethodEntry(MethodTable, J);
Proc := Procs.FindProc(MethodEntry^.Address);
if Proc = nil then
Proc := Procs.Add(MethodEntry^.Address);
with Proc do
begin
Comments.Add('Published method');
PossProcTypes := PossProcTypes * ptMethods;
Name := MethodEntry^.Name;
APublished := True;
AClass := Classes[I];
end;
end;
end;
// Call the event handler
FPublishedMethodsLoaded := True;
FOnLoadPublishedMethods.CallFirst;
end;
procedure TProcs.LoadExportedProcs;
var
I, J: Integer;
Proc: TProc;
AClassInfo: TClassInfo;
InUnit: TUnit;
NMInfo: TNameManglingInfo;
resourcestring
SClassInExportNotFoundError = 'Class named %s mentioned in export not found';
begin
with TPEFileClass(PEFileClass) do
case ProjectType of
ptDLL:
// If this is a library assume all exported items are procs.
for I := 0 to PEExports.Count -1 do
begin
Proc := FindProc(PEExports[I].Address);
if Proc = nil then
Proc := Add(PEExports[I].Address);
with Proc do
begin
Comments.Add('Exported proc ' + PEExports[I].Name);
PossProcTypes := [ptProcedure];
IntfImpl := iiInterface;
AppendBefore := atMayNot;
end;
end;
ptPackage:
begin
for I := 0 to PEExports.Count -1 do
begin
NMInfo := GetNameManglingInfo(PEExports[I].Name);
if NMInfo.NMType = eitClass then
begin
AClassInfo := TPEFileClass(PEFileClass).Classes.FindClass(TClass(PEExports[I].Address));
if AClassInfo <> nil then
begin
// raise EDecompilerError.CreateFmt(SClassInExportNotFoundError, [NMInfo.ClassName]);
AClassInfo.AUnit := Units.FindInUnitUsingFInit(PChar(AClassInfo.AClass));
with TUnit(AClassInfo.AUnit) do
begin
Name := NMInfo.UnitName;
Comments.Add('Unit name set because of export item ' + PEExports[I].Name);
end;
end;
end
else if NMInfo.NMType = eitMethod then
begin
// Find the class.
with TPEFileClass(PEFileClass).Units do
AClassInfo := Items[FindByName(NMInfo.UnitName)].FindClassByName(NMInfo.ClassName);
if AClassInfo = nil then
raise EDecompilerError.CreateFmt(SClassInExportNotFoundError, [NMInfo.ClassName]);
end
else
AClassInfo := nil;
if (NMInfo.NMType in [eitProc, eitMethod]) and
(NMInfo.ItemName <> 'initialization') then
begin
InUnit := Units.FindInUnitUsingFInit(PEExports[I].Address);
InUnit.Name := NMInfo.UnitName;
InUnit.Comments.Add('Unit name set because of export item ' + PEExports[I].Name);
if (NMInfo.ItemName <> 'Finalization') then
begin
// Create the proc.
Proc := FindProc(PEExports[I].Address);
if Proc = nil then
Proc := Add(PEExports[I].Address);
with Proc do
begin
AUnit := InUnit;
Comments.Add('Exported proc ' + PEExports[I].Name);
if NMInfo.NMType = eitProc then
begin
PossProcTypes := [ptProcedure];
// move the proc the the interface part unless it is in the package unit
if TUnit(AUnit).UnitType <> utProgram then
IntfImpl := iiInterface;
end
else
begin
AClass := AClassInfo;
// there is no name it this is a constructor.
if NMInfo.ItemName = '' then
PossProcTypes := PossProcTypes * [ptConstructor, ptDestructor]
else
PossProcTypes := PossProcTypes * ptMethods;
end;
AppendBefore := atMayNot;
if Address <= Units.SystemUnit.FInit.Address then
begin
// Make it a proc of size 0 if it is in the system unit.
AppendAfter := atMayNot;
if NMInfo.ItemName <> '' then
Name := NMInfo.ItemName;
end
else
// there is no name it this is a constructor.
if NMInfo.ItemName <> '' then
begin
// If a proc with this name already exists add the address to the name.
J := FindProcByName(NMInfo.ItemName);
if (J = -1) or (Proc.Index = J) then
Name := NMInfo.ItemName
else
Name := Format('%s%p', [NMInfo.ItemName, Pointer(PEExports[I].Address)]);
end;
// Add the name including the methods as a comment.
Comments.Add(NMInfo.ItemProp);
// There are some strange procs in coride40.bpl which are in full capital
// Just thread them as proc markers (I don't known what else to do with them).
if NMInfo.ItemProp[1] = 'Q' then
AppendAfter := atMayNot;
end;
end;
end;
end;
end;
end;
end;
function TProcs.AnalyzeProc(Proc: TProc): Boolean;
var
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -