从Delphi DLL导出全局符号

Ste*_*fan 11 delphi dll symbols export

我正在尝试在Delphi中创建一个与Gecko 2.0兼容的DLL.

以前(Gecko 2.0之前版本)DLL需要导出NSGetModule()函数.这完美无瑕.

从Firefox 4开始,我的DLL正在加载(我已通过初始化部分中的断点验证了这一点),但我的NSGetModule()函数不再被调用.这是设计行为,因为从Gecko 2.0(Firefox 4)开始,二进制组件不应该导出NSGetModule()函数:

https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_2.0#Binary_components

根据这些文档,我的DLL需要导出一个指向结构的NSModule数据符号.在Delphi术语中,我假设这是一个指向Delphi记录的全局变量.

在C++中,这是导出(全局)数据符号的方式:

define NSMODULE_DEFN(_name) extern "C" NS_EXPORT mozilla::Module const *const NSModule
Run Code Online (Sandbox Code Playgroud)

我的问题:我如何在Delphi中实现这一目标?如何导出全局变量?

感谢您的反馈.

Bar*_*lly 14

Delphi以类似于导出函数的方式从DLL导出全局变量:

library exp;
var
  global: Integer;
exports global;
end.
Run Code Online (Sandbox Code Playgroud)

Delphi可以从DLL导入全局变量,但这有点像黑客:声明一个与导入的全局同名的DLL导入过程,然后获取过程的地址并适当调整它.从Delphi的角度来看,DLL导入的程序是通过DLL导入表间接跳转的存根.通过将导出的全局地址放入导入表中,导出的变量由OS加载程序链接,几乎与导出过程的地址类似地修补的方式完全相同.

例如:

{$apptype console}

procedure global; external 'exp.dll';

function GetGlobalAddr: PInteger;
type
  PPPointer = ^PPointer;
var
  p: PByte;
begin
  p := @global;
  Assert(p^ = $FF); // $FF $25 => indirect jump m32
  Inc(p);
  Assert(p^ = $25);
  Inc(p);
  Result := PPPointer(p)^^
end;

begin
  Writeln(GetGlobalAddr^);
end.
Run Code Online (Sandbox Code Playgroud)

当然,后者的细节是实现和平台相关的等等.可能更安全的方法是使用LoadLibrarywith GetProcAddress,它将在传递其名称时返回全局变量的地址.当然,这也取决于平台.

64位更新:

在Windows上的64位,代码略有不同.操作码相同,但相同指令序列的寻址模式不同; 而不是32位绝对偏移,它是32位相对偏移.

function GetGlobalAddr: PInteger;
type
  PPPointer = ^PPointer;
var
  p: PByte;
  ofs: Integer;
begin
  p := @global;
  Assert(p^ = $FF); // $FF $25 => indirect jump m32
  Inc(p);
  Assert(p^ = $25);
  Inc(p);
  // 32-bit offset follows
  ofs := PInteger(p)^;
  // offset is relative to next instruction
  Inc(p, SizeOf(ofs) + ofs);
  Result := PPPointer(p)^^
end;
Run Code Online (Sandbox Code Playgroud)