链接C代码时如何分辨符号在哪里定义

时间:2019-03-19 16:00:31

标签: c gcc makefile gnu

我在链接中遇到了带有特定符号的未定义参考问题。

error: undefined reference to 'g_queue_pop_nth'

我正在LOP和ARM平台上工作。我们在两个平台上都使用相同的环境。我们的ARM版本正在链接,没有任何问题。但是在LOP平台上,我遇到了以上故障。我想检查从哪个库在ARM主机上定义了该符号。 GCC是否有任何标志或参数来获取有关哪个库提供了此符号的定义的信息?

2 个答案:

答案 0 :(得分:1)

我刚刚在星期五写了一个脚本来几乎做到这一点。该脚本在给定目录中找到对符号的已定义和未定义引用:

#!/bin/bash
#findsym.sh
PATTERN=${1:-"symbol"}
OBJDUMP=armdir/arm-linux-gnuabi-objdump

for f in $(find . -name "*.so" -o -name "*.[ao]"); do
    ${OBJDUMP} -tT $f 2>/dev/null | grep -q ${PATTERN}  2>/dev/null
    [[ ${PIPESTATUS[0]} -eq 0 && ${PIPESTATUS[1]} -eq 0 ]] || continue
    echo "FILE: $f"
    ${OBJDUMP} -tT $f | grep  ${PATTERN}
    echo
done

用法:

 findsym.sh g_queue_pop_nth

您将必须修改objdump路径,并且如果要浏览C ++生成的文件,则可能需要将-C添加到objdump标志中。

答案 1 :(得分:1)

在链接时,您可以请求链接器告诉您哪个输入文件 (目标文件,静态库成员或共享库)可以找到定义 的任何符号,以及在哪个文件中找到使用该符号的符号 链接器选项-trace-symbol=name

例如:

$ cat main.c
extern void foo(void);

int main(void)
{
    foo();
    return 0;
}

$ cat foo.c
#include <stdio.h>

void foo(void)
{
    fputs(__func__,stdout);
}

编译源代码:

$ gcc -Wall -c main.c foo.c

制作静态库:

$ ar rcs libfoo.a foo.o

链接程序,请求foofputs的符号跟踪:

$ gcc -o prog main.o -L. -lfoo -Wl,-trace-symbol=foo,-trace-symbol=fputs
/usr/bin/ld: main.o: reference to foo
/usr/bin/ld: ./libfoo.a(foo.o): definition of foo
/usr/bin/ld: ./libfoo.a(foo.o): reference to fputs
/usr/bin/ld: //lib/x86_64-linux-gnu/libc.so.6: definition of fputs

因此foo是在foo.o的存档成员./libfoo.a中定义的,而fputs是 在/lib/x86_64-linux-gnu/libc.so.6

中定义