如何强制链接程序拒绝特定的库而库本身不冲突?

时间:2019-05-07 20:20:50

标签: c linker pragma

我正在尝试在链接阶段添加健全性检查。具体来说,我有一些静态链接库的程序。某些程序仅限于允许链接的库集,而其他程序则不允许。例如,假设我有两个分别来自food.cfruits.c的程序,并且我有两个库(我有源​​程序)apple.abroccoli.aapple.abroccoli.a之间没有依赖关系。

有没有一种方法可以修改我的源代码和库的源代码,以使链接器可以将apple.abroccoli.a链接到food.c中,并且可以将apple.a链接到fruits.c中,但是当我尝试将apple.abroccoli.a(或仅将broccoli.a)加载到fruits.c中时,会产生链接器错误?假设我的源代码没有#include所链接的库中的任何标头,因为它们被错误地链接了,是从已删除的代码中遗留下来的,函数原型是手动声明的,依此类推。

如果我能以某种方式标记这些库以使程序可以拒绝特定标记,那将是一个很好的选择。

我使用的特定编译器未实现#pragma poison,这实际上是我在搜索中找到的唯一有用的工具。我的直觉告诉我,用弱符号可以做些聪明的事,但我不确定是什么或如何做。

我也不相信使用#define会对我有帮助,因为我的理解是,这只会阻止我#include特定文件的访问,但是如果我误认为是那样,可以也是一个很好的解决方案。

2 个答案:

答案 0 :(得分:0)

  

某些程序仅限于允许链接的库集,而其他程序则不允许。

那没有多大意义。

  

有没有办法修改我的源代码和库的源代码,例如   链接器将允许我将apple.abroccoli.a链接到   food.c,并允许我将apple.a链接到fruits.c,但   当我尝试加载apple.abroccoli.a时产生链接器错误(或   只是broccoli.afruits.c中?

否,因为C语言对库一无所知。它的规范以允许实现提供和使用它们的方式编写,但是在C语言中没有任何方法可以引用库本身。这不是C概念。

无论如何,这没有多大意义。静态库名称没有内在的意义。它们仅在标识其内容的范围内才有意义。禁止fruits.cbroccoli.a的链接无法获得任何收益,因为它很容易解决,并且可以想象它甚至会因构建系统维护中的错误而意外地解决-broccoly.a的> ie 对象被另外或替代地放入apple.a中。

此外,大多数链接器都很聪明-构建可执行文件时,它们会忽略未引用的函数和对象,因此在链接中包括不需要的(静态)库通常是无害的。

答案 1 :(得分:0)

好吧,首先要注意的是:这闻起来很像,就像 B B >

现在一种可能的方法是强制执行“多个定义错误”。对于我的示例,有以下文件:

  • broccoli_mark.c,用于“标记”西兰花文库(见下文)。
  • broccoli_fn.c,其中包含西兰花库的功能。
  • fruits.c,这是不应链接到西兰花库的程序。 “标记为”不允许链接西兰花。

“标记” :这可以通过在这些文件中简单定义一个具有某些已知名称的全局符号来实现。例如:

int broccoli_mark; // a global variable

仅将其放入broccoli_mark.c并将其添加到fruit.c的某个位置。

正在链接...

# Compile and ar the library
$ gcc -c broccoli_mark.c
$ gcc -c broccoli_fn.c
$ ar rcs broccoli.a broccoli_mark.o broccoli_fn.o
# Compile and link program
$ gcc -c fruits.c
$ gcc fruits.o broccoli.a

... 工作 .. 只是因为与静态库的链接是如何工作的:基本上,链接器仅选择(整个)定义符号的对象文件在当前链接集中(最初是程序,然后从库中添加了目标文件)中未定义。

因此,要失败链接,我们必须确保包含broccoli_mark.o(或更具体地说,其包含的符号broccoli_mark)。方法:

  • 将多个目标文件“合并”为一个文件:

    # Merge two object files into a single broccoli.o
    $ ld -r -o broccoli.o broccoli_fn.o broccoli_mark.o
    # create the library or not ..
    $ gcc fruits.o broccoli.o
    ld: broccoli.o:(.data+0x0): multiple definition of `broccoli_mark'; fruits.o:(.data+0x0): first defined here
    collect2: error: ld returned 1 exit status
    

    是的!

    请注意,您可以对西兰花库中的所有.o文件执行此操作……但是您随后破坏了静态库的有用属性,只包含必需的内容。

    还要注意,有options可能会破坏这一点。

    (替代方法:--whole-archive option

  • 只需在必将包含的源文件中包含“标记”(例如,其中包含库的“ main”功能的文件)。

当然,所有“标记”等都可以隐藏在描述性宏名称的后面……不过,仍然感觉像是一个非常糟糕的hack!