ZHCADC4A September 2011 – March 2014
一般而言,由于被调用方负责设置自己的 DP,因此无需对函数指针进行特殊处理。导出函数可安全地从定义它们的模块内部或外部间接调用。(这是 DSBT 模型相对于其他一些无 MMU 方法的主要优势。)
但是,使用函数指针时会遇到潜在陷阱。如果具有内部可见性的函数获取其地址并传递给另一个静态链接单元,然后间接调用,则很可能无法正确设置 DP,并且程序会失败。
严格来说,获取内部函数的地址并将其提供给另一个模块属于编程错误,因为这种操作违反了可见性声明暗示的假设。为帮助检测此类违规行为,工具链可能会选择让编译器在获取非导出函数的地址时发出警告。操作合规的用户可禁用该警告。
获取外部函数的地址并将其传递到另一个模块始终是合规的。为了能够按预期对在不同模块中计算的函数指针进行比较,ABI 要求表示函数地址的表达式在所有模块中的求值是唯一值。其他架构的一些 ABI 采用约定:在可执行文件中,对函数地址的引用可解析为 PLT 条目,从而允许静态解析这些引用。(由于占先,必须动态解析来自共享对象的引用)。
C6000 ABI 未采用该约定,因为它会导致通过函数指针进行跨模块调用时出现问题。如果此类指针可解析为 PLT 条目,则当间接调用到达该 PLT 条目时,DP 值可能是不同静态链接单元的 DP 值,从而使 PLT 条目不能访问 GOT。实际上,PLT 条目是一个内部函数,因此不应从模块外部间接调用。
因此,C6000 ABI 的约定是:对函数地址的引用必须解析为该函数的实际地址。这意味着对于导入对象,此类引用是无法静态解析的;它们必须在加载时由动态链接器解析。