gpt4 book ai didi

delphi - 使用汇编语言和Delphi映射文件获取函数的地址

转载 作者:行者123 更新时间:2023-12-03 15:54:16 24 4
gpt4 key购买 nike

我正在尝试在通过在 Delphi 5 中构建项目生成的“详细”映射文件中查找单元名称和函数名称。我在网上找到了一些代码,声称可以执行此操作,但我不能让它发挥作用。

代码要求:

  • 德尔福5
  • 一个 TForm
  • 一个 TButton
  • 一个 TEdit
  • 一个 TLabel

目标:函数“Log”应该返回调用过程的地址。一旦确定了地址,就可以在映射文件中查找单元和函数名称以及行号。

目的:如果可以通过从程序中的任何位置调用“Log”来获取函数的名称,那不是很好吗?

现实:我真的很想了解“Log”函数中发生了什么,以及它为什么或为什么不工作,其次是返回单元和函数名称以及调用过程的行号的替代方法.

问题:我从 TForm1.Button1Click > TForm1.Log > TForm1.LogAddress > TForm1.ShowInfo 获得的地址与我正在查找的 map 文件中的相应项目不一致,即 M=Unit1、TForm1.Button1Click 等...

网站: http://www.haydenr.com/delphi/articles/article002.htm , http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_22596248.html最后一个网站可能无法通过链接访问 - 我将 Google 搜索字符串放入“日志”功能中。

德尔福代码:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
Procedure Log;
Procedure ShowInfo(hexAddress : Integer);
Procedure LogAddress(ptr: pointer);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

Implementation

{$R *.DFM}

Procedure TForm1.Log;
// Google Search: capturing a procedure or function's name for logging purposes
// http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_22596248.html
Begin
ASM
pop EAX
push EAX
Call LogAddress
End;//ASM
End;

Procedure TForm1.ShowInfo(hexAddress: Integer);
// http://www.haydenr.com/delphi/articles/article002.htm
Var
iMapFileAddress : Integer;
sMapFileAddress : String;
ImageBase : Integer;
SubOffset : Integer;
Offset : Integer;
Begin
ImageBase := $00400000; // Project > Options... > Linker Tab > Memory sizes group box > Image Base
SubOffset := $1000;
Offset := ImageBase + SubOffset;

iMapFileAddress := hexAddress - Offset;
sMapFileAddress := IntToHex(iMapFileAddress,8);
Edit1.Text := sMapFileAddress; //This is the value I get: sMapFileAddress = 00542214
{
Here are some excerpts from: Project1.map
|Detailed map of segments
| 0001:00040498 000002D4 C=CODE S=.text G=(none) M=Unit1 ACBP=A9
| 0001:0004076C 000001A5 C=CODE S=.text G=(none) M=Project1 ACBP=A9
| :
| :
| :
| Address Publics by Name
|
| 0001:0004071C TForm1.Button1Click
| 0001:00040668 TForm1.Log
| 0001:00040700 TForm1.LogAddress
| 0001:0004067C TForm1.ShowInfo
}
End;

procedure TForm1.LogAddress(ptr: pointer);
begin
ShowInfo(Integer(ptr));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Log;
end;

end.

最佳答案

您没有正确调用LogAddress。作为 TForm1 的一个方法,它实际上是一个双参数函数。这两个参数依次为 Selfptr,这意味着寄存器 EAX 为 Self,EDX 为 ptr >。但是,您在 EAX 中传递地址参数,并且对 EDX 没有执行任何操作。这意味着您正在查找“谁知道什么”的名称,它可能不是程序中任何代码部分的地址。最重要的是,Self 值不再有效,因此对成员变量(例如 Edit1)的任何引用都将不起作用;您将遇到访问冲突或某种形式的内存损坏。

Log 方法更改为:

procedure TForm1.Log;
asm
// fetch return address from top of stack
mov edx, [esp+4]
call LogAddress
end;

请记住,您在 ptr 参数中传递的地址是 Log 调用的返回地址。实际上,这通常是用于进入 Log 方法的 CALL 指令之后的指令地址。因此,您不应期望在映射文件的函数列表中找到该确切地址。相反,您需要查找地址最接近但不超过您拥有的地址的函数。此外,如果您将该地址转换为行号,它可能是实际调用站点之后的行。

JclDebug 单元,位于 the JCL ,已经有可以为您执行此操作的函数。您可以使用 ProcByLevel 函数获取调用者的名称,并使用 LiveByLevel 函数获取行号。

关于delphi - 使用汇编语言和Delphi映射文件获取函数的地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28374635/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com