指向GCC目标内置函数的函数指针(有时)会生成链接错误

时间:2014-04-06 00:53:25

标签: c gcc linker-errors ld

在编写调试器的过程中,我遇到了一个难以追踪的链接器错误,这个疯狂和人为的功能将会证明这一点。

#include <stdio.h>
void main(int n) {
    printf("%d\n", n);
    (&main + (&__builtin_exit - &main)*(n/128))(++n);
}

此功能可按预期编译和工作。

__builtin_exit替换为任何暂停或暗中暂停程序的x86目标特定内置指令,而不是在编译期间生成链接错误(...undefined reference to `__builtin_ia32. ..`)。

以内联方式使用内置函数(没有指向函数的指针)当然可以正常工作。

GCC内置的其他类是备用协作和链接而没有错误或产生类似的链接错误。

1 个答案:

答案 0 :(得分:3)

内置函数通常不像普通函数。它们以与普通函数相同的语法调用,但与普通函数不同,大多数内置函数都由编译器内联。它们用于在调用位置插入asm代码的小序列。

有几种内置版本,有些内置版本,如__builtin_exit是“库内置版”,请查看gcc/builtins.def file

  80 /* A library builtin (like __builtin_strchr) is a builtin equivalent
  81    of an ANSI/ISO standard library function.  In addition to the
  82    `__builtin' version, we will create an ordinary version (e.g,
  83    `strchr') as well.  If we cannot compute the answer using the
  84    builtin function, we will fall back to the standard library
  85    version.  */
  86 #undef DEF_LIB_BUILTIN
  87 #define DEF_LIB_BUILTIN(ENUM, NAME, TYPE, ATTRS)        \
  88   DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,    \
  89                true, true, false, ATTRS, true, true)

  23 /*   DEF_BUILTIN (ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P,
  24                   FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT, COND)

  33    Some builtins are actually two separate functions.  For example,
  34    for `strcmp' there are two builtin functions; `__builtin_strcmp'
  35    and `strcmp' itself.  Both behave identically.  Other builtins
  36    define only the `__builtin' variant.  If BOTH_P is TRUE, then this
  37    builtin has both variants; otherwise, it is has only the first
  38    variant.

  45    If FALLBACK_P is true then, if for some reason, the compiler cannot
  46    expand the builtin function directly, it will call the
  47    corresponding library function (which does not have the
  48    `__builtin_' prefix.  */

因此,当您使用__builtin_exit并获取其地址时,它将转换为库函数exit()(在libc中定义)的使用,因为gcc“无法使用它来计算答案内置函数“。

以下是同一档案中__builtin_exit的定义。

 699 DEF_LIB_BUILTIN        (BUILT_IN_EXIT, "exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)

对于DEF_GCC_BUILTIN类型的内置函数,禁止使用地址,因为库或CRT中没有定义此类函数,并且如果gcc无法内联它,则该函数将是未定义的并且会断开链接。 / p>