通过使用 rtld-debugger 接口,控制进程可以跳过过程链接表项。第一次要求控制进程(如调试器)步入 (step into) 函数时,通过过程链接表处理可将控制权传递给运行时链接程序以搜索函数定义。
通过使用以下接口,控制进程可以跳过运行时链接程序的过程链接表处理。控制进程可以基于 ELF 文件中提供的外部信息来确定何时遇到过程链接表项。
目标进程步入过程链接表项之后,便会调用 rd_plt_resolution() 接口:
此函数可返回当前过程链接表项的解析状态以及有关如何跳过此状态的信息。
rd_err_e rd_plt_resolution(rd_agent_t * rdap, paddr_t pc, lwpid_t lwpid, paddr_t plt_base, rd_plt_info_t * rpi); |
pc 表示过程链接表项的第一条指令。lwpid 提供 lwp 标识符,plt_base 提供过程链接表的基本地址。这三个变量提供的信息足以供多个体系结构用于处理过程链接表。
rpi 提供有关以下数据结构(在 rtld_db.h 中定义)中定义的过程链接表项的详细信息:
typedef enum { RD_RESOLVE_NONE, RD_RESOLVE_STEP, RD_RESOLVE_TARGET, RD_RESOLVE_TARGET_STEP } rd_skip_e; typedef struct rd_plt_info { rd_skip_e pi_skip_method; long pi_nstep; psaddr_t pi_target; psaddr_t pi_baddr; unsigned int pi_flags; } rd_plt_info_t; #define RD_FLG_PI_PLTBOUND 0x0001
rd_plt_info_t 结构的元素包括:
标识遍历过程链接表项的方法。此方法可设置为 rd_skip_e 值之一。
标识返回 RD_RESOLVE_STEP 或 RD_RESOLVE_TARGET_STEP 时跳过的指令数。
指定返回 RD_RESOLVE_TARGET_STEP 或 RD_RESOLVE_TARGET 时设置断点的地址。
添加了 RD_VERSION3 的过程链接表的目标地址。设置 pi_flags 字段的 RD_FLG_PI_PLTBOUND 标志之后,此元素可标识已解析(绑定)的目标地址。
添加了 RD_VERSION3 的标志字段。标志 RD_FLG_PI_PLTBOUND 可将过程链接项标识为已解析(绑定)到其目标地址,此地址可用于 pi_baddr 字段。
rd_plt_info_t 返回值表明了以下可能的情况:
必须由运行时链接程序解析通过此过程链接表进行的首次调用。在这种情况下,rd_plt_info_t 包含以下内容:
{RD_RESOLVE_TARGET_STEP, M, <BREAK>, 0, 0} |
控制进程会在 BREAK 处设置断点,从而使目标进程继续运行。到达断点时,即会完成过程链接表项处理。然后,控制进程可以将 M 条指令转到目标函数。请注意,由于这是通过过程链接表项进行的首次调用,因此尚未设置绑定地址 (pi_baddr)。
通过此过程链接表第 N 次进行调用时,rd_plt_info_t 会包含以下内容:
{RD_RESOLVE_STEP, M, 0, <BoundAddr>, RD_FLG_PI_PLTBOUND} |
过程链接表项已经过解析,并且控制进程可以将 M 条指令转到目标函数。过程链接表项绑定到的地址为 <BoundAddr>,并且已在标志字段中设置了 RD_FLG_PI_PLTBOUND 位。