Delphi AssemblerRTTI-gurus:我可以获取函数中隐含的Result变量的内存地址和类型信息吗?

Delphi AssemblerRTTI-gurus:我可以获取函数中隐含的Result变量的内存地址和类型信息吗?,第1张

概述考虑这种典型的方法跟踪代码(简化说明): type IMethodTracer = interface end; TMethodTracer = class(TInterfacedObject, IMethodTracer) private FName: String; FResultAddr: Pointer; FResultType: PTypeInf 考虑这种典型的方法跟踪代码(简化说明):

type  IMethodTracer = interface  end;  TMethodTracer = class(TInterfacedobject,IMethodTracer)  private    Fname: String;    FResultAddr: Pointer;    FResultType: PTypeInfo;  public    constructor Create(      const Aname: String;      const AResultAddr: Pointer = nil;      const AResultType: PTypeInfo = nil);    destructor Destroy; overrIDe;  end;constructor TMethodTracer.Create(  const Aname: String;  const AResultAddr: Pointer;  const AResultType: PTypeInfo);begin  inherited Create();  Fname := Aname;  FResultAddr := AResultAddr;  FResultType := AResultType;  Writeln('Entering ' + Fname);end;destructor TMethodTracer.Destroy;var  lSuffix: String;  lResVal: TValue;begin  lSuffix := '';  if FResultAddr <> nil then    begin      //there's probably a more straight-forward to doing this,without involving TValue:      TValue.Make(FResultAddr,FResultType,lResVal);      lSuffix := ' - Result = ' + lResVal.Asstring;    end;  Writeln('Leaving ' + Fname + lSuffix);  inherited Destroy;end;function TraceMethod(  const Aname: String;  const AResultAddr: Pointer;  const AResultType: PTypeInfo): IMethodTracer;begin  Result := TMethodTracer.Create(Aname,AResultAddr,AResultType);end;//////function F1: String;begin  TraceMethod('F1',@Result,TypeInfo(String));  Writeln('Doing some stuff...');  Result := 'Booyah!';end;F1();

这是按预期工作的.输出是:

Entering F1
Doing some stuff…
Leaving F1 – Result = Booyah!

我现在正在寻找一种方法来最小化调用TraceMethod()所需的参数数量,理想情况下允许我完全跳过与Result相关的参数.我自己没有使用汇编程序或堆栈布局的经验但是如果我没有弄错,从我见过的其他人所做的“魔法”判断,至少隐含的魔法Result-variable的内存地址应该可以以某种方式获得,不应该它?也许有人可以从那里得到它的类型信息吗?

当然,如果有可能甚至可以确定“周围”函数本身的名称,这将消除完全将参数传递给TraceMethod的需要……

我正在使用Delphi XE2,因此可以使用所有最近引入的语言/框架功能.

在任何人提到它之前:我的实际代码已经使用CodeSite.EnterMethod / ExitMethod而不是Writeln调用.我也知道这个简化的例子不能处理复杂的类型,也不会执行任何错误处理.

解决方法 你最好的选择是真正传递@Result.如果不这样做,则无法保证Result甚至有地址.返回简单类型(如Integer和Boolean)的函数将结果放入EAX寄存器.如果没有理由让结果有地址,那么编译器就不会为它分配任何内存.使用@Result表达式强制编译器为其指定地址.

但是,仅仅知道地址不会得到返回类型.可能有一种方法可以通过RTTI发现它.这将涉及三个步骤:

>从方法名称中提取类名.然后你可以get the RTTI for that type.这将要求方法名称包含类的明确名称(包括单位名称).
>使用该类型的list of methods,找到该方法的RTTI.由于名称不一定唯一地标识方法,因此这将变得复杂.重载都将显示相同的名称. (Rruz在Invoke方法的上下文中显示了how to deal with RTTI of overloaded methods.)此外,从调试信息中获得的方法名称不一定与RTTI名称匹配.

您可以改为遍历所有类的方法,而不是尝试匹配名称,搜索其CodeAddress属性与调用方地址匹配的方法.然而,确定如何获得调用者的起始地址(而不是返回地址)比我预期的更难找到.
>获取the method’s return type并使用Handle属性最终获得所需的PTypeInfo值.

总结

以上是内存溢出为你收集整理的Delphi Assembler / RTTI-gurus:我可以获取函数中隐含的Result变量的内存地址和类型信息吗?全部内容,希望文章能够帮你解决Delphi Assembler / RTTI-gurus:我可以获取函数中隐含的Result变量的内存地址和类型信息吗?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1243129.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存