我可以将未解析的引用链接到中止吗?

时间:2010-01-05 15:15:22

标签: c++ gcc linker

我正在尝试为一个相当大的项目中的一小部分编写一些小测试。不幸的是,如果不将整个项目链接在一起,试图链接这个野兽是相当不可能的,这是我不想做的(这是一个非常复杂的系统,用于查找所有依赖项和内容,而且我不会干涉它)。

现在,我确信在我的测试过程中不会调用引用函数的函数,恰好恰好是与我测试的东西共享文件的函数的一部分。

有没有办法简单地将这些未解决的引用链接到,比方说,中止,或者什么?或者是否有一个工具可以创建适当的存根对象文件,其中所有调用都会导致中止,给定我拥有的一组目标文件?

我使用gcc(g ++)进行编译/链接,版本3.4.4。平台是unix(solaris / sparc,如果这很重要)。

4 个答案:

答案 0 :(得分:15)

您可以告诉链接器忽略未解析的符号。我找不到将它们链接到abort或类似的东西的选项。

我认为,忽略目标文件中未解析符号的策略是最自然的:

gcc -Wl,--unresolved-symbols=ignore-in-object-files  obj.o another.o etc.o

其他选项包括(引用man ld):

   --unresolved-symbols=method
       Determine how to handle unresolved symbols.  There are four possi-
       ble values for method:

       ignore-all
           Do not report any unresolved symbols.

       report-all
           Report all unresolved symbols.  This is the default.

       ignore-in-object-files
           Report  unresolved  symbols  that  are  contained  in   shared
           libraries,  but  ignore  them if they come from regular object
           files.

       ignore-in-shared-libs
           Report unresolved symbols that come from regular object files,
           but  ignore them if they come from shared libraries.  This can
           be useful when creating a dynamic binary and it is known  that
           all  the  shared  libraries  that it should be referencing are
           included on the linker's command line.

       The behaviour for shared libraries on their own can also  be  con-
       trolled by the --[no-]allow-shlib-undefined option.

       Normally  the  linker  will  generate  an  error  message for each
       reported unresolved symbol but the  option  --warn-unresolved-sym-
       bols can change this to a warning.

在我的Linux系统上尝试调用未解析的函数导致“分段错误”。

答案 1 :(得分:1)

我能想到的一种方法是先为你的库编译.o文件。

然后使用像nm这样的工具(常见于* nix系统)来获取所有符号,nm,所有“外部”(也就是在此.o中找不到的符号)属于 U 类型(对于非nm的GNU版本可能会有所不同,请参阅您的文档。

如果您的库是一个源文件,那么它很简单,几乎所有 U 类型的符号都将是在另一个库中找到的函数,或者在链接时将无法解析。如果您的库将成为多个源文件,则稍微复杂一些,因为您将拥有源间文件依赖性。

所以现在你有一种方法可以创建一个未解析的外部列表的潜在列表,然后你可以创建一个“test_stub.c”,每个符号都有一个存根符号,你可以用这样的东西填充:

void some_func() { abort(); }

其中some_func是一个未解决的外部问题。编译并将其与您的库链接,所有调用都应导致中止。

答案 2 :(得分:1)

尝试编译以下程序

#include <iostream>

extern int bar();

int foo()
{
  return bar() + 3;
}

int main()
{
  std::cout << "Hello, world!" << std::endl;
  // std::cout << foo() << std::endl;

  return 0;
}

结果

$ g++ -o main main.cc
/tmp/ccyvuYPK.o: In function `foo()':
main.cc:(.text+0x5): undefined reference to `bar()'
collect2: ld returned 1 exit status

但我们可以告诉链接器忽略未解析的符号并运行它就好了:

$ g++ -Wl,--unresolved-symbols=ignore-all -o main main.cc
$ ./main
Hello, world!

假设您的测试工具调用了一些未解析的函数 (通过取消注释对foo的调用来模拟它),它将编译并链接正常,但是当你得到段错误时你执行程序。请务必ulimit -c unlimited,以便获得core

答案 3 :(得分:0)

尝试GCC alias属性:

/* cannot directly alias to yet undefined symbols,
 * so need an intermediate function.
 */
static void do_abort() { abort(); }

void func0() __attribute__ ((weak, alias ("do_abort")));
void func1() __attribute__ ((weak, alias ("do_abort")));
...