GNU GCC / LD - 包裹与呼叫者和被叫方的同一对象文件中定义到符号中的呼叫(GNU gc

2019-07-17 10:54发布

为了澄清,我的问题是指包裹/截取从一个功能/符号到另一个函数/符号调用当主叫用户和被叫在相同的编译单元中定义与GCC编译器和链接。

我有一个类似的情况如下:

/* foo.c */
void foo(void)
{
  /* ... some stuff */
  bar();
}

void bar(void)
{
  /* ... some other stuff */
}

我想换到这些函数的调用,而我能做到这一点(一个点)与LD的--wrap选项 (然后我实现__wrap_foo和__wrap_bar这反过来又调用__real_foo和__real_bar预期由劳工处的结果--wrap选项)。

gcc -Wl,--wrap=foo -Wl,--wrap=bar ...

我遇到的问题是,这只是生效的引用foo和该编译单元之外酒吧(和链接时解析)。 也就是说,调用foo和来自内部的foo.c等功能栏没有得到包裹。

我尝试使用objcopy把--redefine-符号 ,但只重命名符号及其引用。

我想更换调用foobar (foo.o的范围内),以__wrap_foo__wrap_bar (就像他们获得其他目标文件链接程序的解决--wrap之前我通过了* .o文件的链接器的选项) --wrap选项,而无需修改foo.c中的源代码。

这样一来,包装/拦截发生的所有调用foobar ,而不仅仅是那些发生foo.o.之外

这可能吗?

Answer 1:

你必须削弱和使用objcopy把全球化的象征。

-W symbolname
--weaken-symbol=symbolname
    Make symbol symbolname weak. This option may be given more than once.
--globalize-symbol=symbolname
    Give symbol symbolname global scoping so that it is visible outside of the file in which it is defined. This option may be given more than once.

这为我工作

bar.c:

#include <stdio.h>
int foo(){
  printf("Wrap-FU\n");
}

foo.c的:

#include <stdio.h>

void foo(){
printf("foo\n");
}

int main(){
printf("main\n");
foo();
}

编译

$ gcc -c foo.c bar.c 

削弱foo的符号,使之全球化的,它再次可供连接。

$ objcopy foo.o --globalize-symbol=foo --weaken-symbol=foo foo2.o

现在,您可以从bar.c包裹链接新的OBJ

$ gcc -o nowrap foo.o #for reference
$ gcc -o wrapme foo2.o bar.o

测试

$ ./nowrap 
main
foo

和一个包裹:

$ ./wrapme 
main
Wrap-FU


Answer 2:

#include <stdio.h>
#include <stdlib.h>

//gcc -ggdb -o test test.c -Wl,-wrap,malloc
void* __real_malloc(size_t bytes);

int main()
{
   int *p = NULL;
   int i = 0;

   p = malloc(100*sizeof(int));

   for (i=0; i < 100; i++)
       p[i] = i;

   free(p);
   return 0;
}

void* __wrap_malloc(size_t bytes)
{
      return __real_malloc(bytes);
}

然后只需编译此代码和调试。 当你调用malloc的雷尔,叫会--wrap malloc中调用和__real_malloc将调用malloc函数。

我认为这是拦截来电的方式。

主要是因为在--wrap选项由劳工处提供。



Answer 3:

您可以使用__attribute__((weak))被调用执行之前,为了让别人重新实现它没有GCC大喊大叫有关多。定义。

例如,假设你想嘲笑world在下面的hello.c代码单元的功能。 您可以以预先设置属性能够覆盖它。

#include "hello.h"
#include <stdio.h>

__attribute__((weak))
void world(void)
{
    printf("world from lib\n");
}

void hello(void)
{
    printf("hello\n");
    world();
}

然后你可以重写它在另一个单元文件。 单元测试/嘲笑非常有用的:

#include <stdio.h>
#include "hello.h"

/* overrides */
void world(void)
{
    printf("world from main.c"\n);
}

void main(void)
{
    hello();
    return 0;
}


Answer 4:

这似乎是工作的记载:

 --wrap=symbol
       Use a wrapper function for symbol. 
       Any undefined reference to symbol will be resolved to "__wrap_symbol". ...

注意上面的定义 。 当链接器处理foo.o ,所述bar() 不是未定义,所以链接器不包裹。 我不知道为什么它这样做的方式,但也有可能是需要这样的使用情况。



Answer 5:

你可以实现你想要的,如果你用什么--undefined--wrap

  -u SYMBOL, --undefined SYMBOL
                              Start with undefined reference to SYMBOL


文章来源: GNU gcc/ld - wrapping a call to symbol with caller and callee defined in the same object file