Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
995 views
in Technique[技术] by (71.8m points)

linker - GNU gcc/ld - wrapping a call to symbol with caller and callee defined in the same object file

to clarify, my question refers to wrapping/intercepting calls from one function/symbol to another function/symbol when the caller and the callee are defined in the same compilation unit with the GCC compiler and linker.

I have a situation resembling the following:

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

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

I would like to wrap calls to these functions, and I can do that (to a point) with ld's --wrap option (and then I implement __wrap_foo and __wrap_bar which in turn call __real_foo and __real_bar as expected by the result of ld's --wrap option).

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

The problem I'm having is that this only takes effect for references to foo and bar from outside of this compilation unit (and resolved at link time). That is, calls to foo and bar from other functions within foo.c do not get wrapped.

calls from within the compilation unit get resolved before the linker's wrapping

I tried using objcopy --redefine-sym, but that only renames the symbols and their references.

I would like to replace calls to foo and bar (within foo.o) to __wrap_foo and __wrap_bar (just as they get resolved in other object files by the linker's --wrap option) BEFORE I pass the *.o files to the linker's --wrap options, and without having to modify foo.c's source code.

That way, the wrapping/interception takes place for all calls to foo and bar, and not just the ones taking place outside of foo.o.

Is this possible?

question from:https://stackoverflow.com/questions/13961774/gnu-gcc-ld-wrapping-a-call-to-symbol-with-caller-and-callee-defined-in-the-sam

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You have to weaken and globalize the symbol using 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.

This worked for me

bar.c:

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

foo.c:

#include <stdio.h>

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

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

Compile it

$ gcc -c foo.c bar.c 

Weaken the foo symbol and make it global, so it's available for linker again.

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

Now you can link your new obj with the wrap from bar.c

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

Test

$ ./nowrap 
main
foo

And the wrapped one:

$ ./wrapme 
main
Wrap-FU

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...