【问题标题】:How can I tell the linker which one of multiple implementations of a method to use?如何告诉链接器使用方法的多个实现中的哪一个?
【发布时间】:2015-07-26 01:43:48
【问题描述】:

我使用一个工具来生成一个 111k 行长的 C++ 类实现。它生成的方法按应有的方式工作,但它们往往会在所使用的 API 中触发缓慢的路径。

有没有什么办法,在 Mac OS X 上使用 Clang,我可以在不同的源文件中手动实现一些最常用的方法,并告诉链接器(或任何其他相关程序)忽略工具生成的方法是否存在该方法的其他实现?

我可以完全控制工具的输出,但自动生成更好的代码非常困难。

【问题讨论】:

  • 您使用哪个工具来生成长达 111k 行的 C++ 类实现?
  • 这是我制作的一个工具,它是一个 LLVM IR 模块并将其转换为 C++ 代码,其中模块函数和 C++ 方法之间存在 1:1 映射。每种方法都会生成匹配函数的 IR,除了带有常数参数外,因此可以很容易地对代码进行专门化和优化,然后进行分析。它有一个非常特殊的用途。
  • 这很脏,但如果该工具生成足够模块化的代码,那么相关“更高效”标头的#include_next 就可以轻松做到这一点。
  • @CodaFi,我不确定我是否理解您的解决方案。这个想法是我手动指定一个更有效的实现,而不是更有效的声明。
  • 这个想法是,鉴于该工具和您可以生成 2 个不同的标头(或更多),您可以将函数的实现分解为不同的标头,并在您觉得特定实现更值得时使用 #include_next它在“高效”标题中,而不是“工具生成”标题中。是的,这不是链接时更改,而是 CPP 更改,但我宁愿拥有模块化而不是 DYLD。

标签: macos linker clang


【解决方案1】:

如果代码是在库中交付的,则链接器会搜索连续库中的 .o 文件,直到满足所有未解析的符号。因此,如果您的代码生成可以确保将弱代码分成不同的 .cpp 文件,那么您可以在链接路径上以较早的 .a 交付自定义编写的版本,该文件将在代码生成提供的 .a 之前使用。

或者,如果您可以在代码中添加虚假模板,则可以为代码指定显式特化。这将由编译器/链接器使用,因为它是一种特定的特化。

【讨论】:

  • 链接器会抱怨 .a 方法存在多个符号定义,除非那里有技巧。
  • 它选择库中的 .o 文件来满足每个依赖项。所以如果一个 .o 文件包含多个项目,是的,链接器会抱怨。但是,如果每个方法位于不同的 .cpp 文件中,那么它将位于单独的 .o 文件中,并且链接器只会将未满足的符号添加回。如果您可以将弱方法代码生成到单个 .o 文件中,那么这就足够了
  • 我没有意识到链接器只会从 .a 中获取它需要的符号,并且会悄悄地丢弃重复的符号。
【解决方案2】:

工具生成的方法需要标记为weak externals。在 GCC 和 clang this is achieved__attribute__((weak_import))。然后,如果您手工制作的等价物是强外部(默认情况下),它们将优先于生成的。

【讨论】:

  • 我知道您可以将weak_import 用于外部,但我不知道您是否可以对将在可执行文件中静态链接的方法执行此操作。我尝试使用this,但X::y 出现重复符号错误。
  • 如果方法是静态链接的,为什么会有所不同?
  • 我的假设是弱导入依赖于 dyld 用空指针填充 PLT/GOT 条目,而静态链接的符号(不是导入)不需要间接,因此不需要有被淘汰的机会。除此之外,我不认为weak_import 意味着该符号已合并。这些符号类在Apple's Mach-O file documentation 上进行了描述。
猜你喜欢
  • 1970-01-01
  • 2019-04-27
  • 2016-01-25
  • 1970-01-01
  • 1970-01-01
  • 2017-01-19
  • 2010-09-27
  • 2020-10-13
  • 1970-01-01
相关资源
最近更新 更多