1

我在 Android 上遇到了 Free Pascal 共享库启动代码的问题。Free Pascal RTL 源具有以下片段:

type
  TAuxiliaryValue = cuInt32;

  TInternalUnion = record
    a_val: cuint32;           //* Integer value */
      {* We use to have pointer elements added here.  We cannot do that,
         though, since it does not work when using 32-bit definitions
         on 64-bit platforms and vice versa.  *}
  end;

  Elf32_auxv_t = record
    a_type: cuint32;              //* Entry type */
    a_un: TInternalUnion;
  end;
  TElf32AuxiliaryVector = Elf32_auxv_t;
  PElf32AuxiliaryVector = ^TElf32AuxiliaryVector;

var
  psysinfo: LongWord = 0;

procedure InitSyscallIntf;
var
  ep: PPChar;
  auxv: PElf32AuxiliaryVector;
begin

  psysinfo := 0;
  ep := envp;
  while ep^ <> nil do
    Inc(ep);

  Inc(ep);

  auxv := PElf32AuxiliaryVector(ep);

  repeat
    if auxv^.a_type = AT_SYSINFO then begin
      psysinfo := auxv^.a_un.a_val;
      if psysinfo <> 0 then
        sysenter_supported := 1; // descision factor in asm syscall routines
      Break;
    end;
    Inc(auxv);
  until auxv^.a_type = AT_NULL;
end;

该过程InitSyscallIntf作为 SO 启动序列的一部分被调用。这envp是一个单元级变量,在启动序列的早期初始化为 libc's 的值environ。在我看来,代码正试图扫描environ数组越过空指针(我认为它表示环境块的结尾),然后尝试读取过去的内存。

他们期望在environ数组末尾找到什么?可能他们正在对加载的 ELF 文件的内存结构做出一些假设 - 我可以看到参考吗?

4

3 回答 3

2

看起来他们是这样过去。在环境结束之后,有一组称为辅助向量的双 DWORD 数据块。向量中的第一个 DWORD 是它的类型,第二个是值。类型记录在linux/auxvec.h; 其中大约有20个。

具体来说,FPC 启动正在寻找 AT_SYSINFO (32) 类型的向量。

辅助向量超出了环境块的末尾,但辅助向量块的副本可作为/proc/me/auxv.

于 2013-06-01T03:49:48.813 回答
1

Seva 发布的链接就是它正在查看的内容,并且它正在查看是否支持 sysenter 指令。

该指令允许更快的系统调用,并且在基于 Linux 和 FreeBSD 内核的系统上,通常 Free Pascal 程序直接访问内核,而不是通过 libc。

请参阅 rtl/linux/i386/* 和 rtl/linux/x86_64 以了解 syscall 包装例程,您将在那里看到 sysenter 的测试。

于 2013-06-01T08:24:29.103 回答
0

根据Linux/i386 ELF 二进制文件的启动状态,ELF 二进制文件的段布局在环境数组之后具有程序名称。

实际上,我不确定这是否是您的程序正在访问的内容。那是环境数据,环境数组(指向这些字符串的指针)位于初始堆栈帧中。之后上面的页面没有显示任何具体内容,我认为它是main()函数的本地数据。

于 2013-06-01T03:08:21.533 回答