Can DynamoRio wrap static functions?

317 views
Skip to first unread message

Stephen Cameron

unread,
Mar 21, 2012, 1:55:47 PM3/21/12
to dynamor...@googlegroups.com

Hi,

I'm new here.

I'm working on an approach to doing some unit testing of linux kernel modules.  Linux kernel modules typically only expose a few functions with all module internal functions declared static.  My idea was to use objcopy with the --globalize-symbols and possibly the --weaken option to expose those symbols for unti testing.  So far so good.  But internal calls to internal module functions I cannot override by this method, it seems.  i'm wondering if DynamoRio can do it.

Here's a simplified example of what I'm trying to do:

 If I start with something like this, a module
with global symbol "foo" is a function that calls
local symbol "bar," that calls local symbol "baz"

[scameron@localhost ~]$ cat foo.c
#include <stdio.h>
static void baz(void)
{
    printf("baz\n");
}

static void bar(void)
{
    printf("bar\n");
    baz();
}

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

[scameron@localhost ~]$ gcc -g -c foo.c
[scameron@localhost ~]$ objdump -x foo.o | egrep 'foo|bar|baz'
foo.o:     file format elf32-i386
foo.o
00000000 l    df *ABS*    00000000 foo.c
00000000 l     F .text    00000014 baz
00000014 l     F .text    00000019 bar
0000002d g     F .text    00000019 foo

It has one global, "foo" and two locals "bar" and "baz."

Suppose I want to write some unit tests that exercise bar and baz,
I can do:

[scameron@localhost ~]$ cat barbaz
bar
baz
[scameron@localhost ~]$ objcopy --globalize-symbols=barbaz foo.o foo2.o
[scameron@localhost ~]$ objdump -x foo2.o | egrep 'foo|bar|baz'
foo2.o:     file format elf32-i386
foo2.o
00000000 l    df *ABS*    00000000 foo.c
00000000 g     F .text    00000014 baz
00000014 g     F .text    00000019 bar
0000002d g     F .text    00000019 foo
[scameron@localhost ~]$

And now bar and baz are global symbols and accessible from
outside the module.  So far so good.

But what if I want to interpose my own function on top
of "baz", and have "bar" call my interposed "baz"?

Is there a way to do that?

--wrap option doesn't seem to do it...

[scameron@localhost ~]$ cat ibaz.c
#include <stdio.h>
extern void foo();
extern void bar();

void __wrap_baz()
{
    printf("wrapped baz\n");
}
int main(int argc, char *argv[])
{
    foo();
    baz();
}

[scameron@localhost ~]$ gcc -o ibaz ibaz.c foo2.o -Xlinker --wrap -Xlinker baz
[scameron@localhost ~]$ ./ibaz
foo
bar
baz
wrapped baz
[scameron@localhost ~]$

The baz called from main() got wrapped, but
bar still calls the local baz not the wrapped baz.

I also tried --weaken, still no luck

[scameron@localhost ~]$ objcopy --weaken-symbol=baz foo2.o foo3.o
[scameron@localhost ~]$ objdump -x foo3.o | grep baz
00000000  w    F .text  00000014 baz
[scameron@localhost ~]$ gcc -o ibaz ibaz.c foo3.o -Xlinker --wrap -Xlinker baz
[scameron@localhost ~]$ ./ibaz
foo
bar
baz
wrapped baz
[scameron@localhost ~]$

Is there a way to do this with DynamoRIO?

Thanks,

-- steve

Qin Zhao

unread,
Mar 21, 2012, 3:26:52 PM3/21/12
to dynamor...@googlegroups.com
-Xlinker is the compiler/linker option to replace the functions.
DynamoRIO's function wrapping is different.
You have to write a DR client and uses dr_wrap extension to wrap the function,  and yes you can wrap static function.

Qin



--
You received this message because you are subscribed to the Google Groups "DynamoRIO Users" group.
To view this discussion on the web visit https://groups.google.com/d/msg/dynamorio-users/-/hAFFh58RlL0J.
To post to this group, send email to dynamor...@googlegroups.com.
To unsubscribe from this group, send email to dynamorio-use...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/dynamorio-users?hl=en.



--
Interested in Yoga? Be careful of The Yoga Cult or The Scary Yoga Obsession.
More information from  Lorie Anderson and Rick Ross.

Stephen Cameron

unread,
Mar 21, 2012, 4:16:45 PM3/21/12
to dynamor...@googlegroups.com
> -Xlinker is the compiler/linker option to replace the functions.
> DynamoRIO's function wrapping is different.

Yeah, I figured it was different, I was just trying to explain clearly what I wanted to do and what I had tried so far. 

> You have to write a DR client and uses dr_wrap extension to wrap the function,  and yes you can wrap static function.

Good to find out that DynamoRIO can do it.  That will be very useful.  Now just have to dig into it to figure out how.

Thanks,

-- steve

Reid Kleckner

unread,
Mar 21, 2012, 4:49:33 PM3/21/12
to dynamor...@googlegroups.com
Are you doing this testing in kernel space or user space?  I'm guessing this is user space, since it's testing.  Peter Feiner did some work to run DR in kernel space, but it was never contributed back and he has since moved on to new projects.

For your purposes, you should be able to get what you need by using the drsyms and drwrap.  drsyms lets you look up symbol addrs, and drwrap will let you wrap functions.

Reid

Stephen Cameron

unread,
Mar 21, 2012, 5:15:40 PM3/21/12
to dynamor...@googlegroups.com
 
On Wednesday, March 21, 2012 3:49:33 PM UTC-5, Reid Kleckner wrote:
On Wed, Mar 21, 2012 at 4:16 PM, Stephen Cameron wrote:
> -Xlinker is the compiler/linker option to replace the functions.
> DynamoRIO's function wrapping is different.

Yeah, I figured it was different, I was just trying to explain clearly what I wanted to do and what I had tried so far. 

> You have to write a DR client and uses dr_wrap extension to wrap the function,  and yes you can wrap static function.

Good to find out that DynamoRIO can do it.  That will be very useful.  Now just have to dig into it to figure out how.

Are you doing this testing in kernel space or user space?  I'm guessing this is user space, since it's testing.  Peter Feiner did some work to run DR in kernel space, but it was never contributed back and he has since moved on to new projects.

Yeah, user space.
 

For your purposes, you should be able to get what you need by using the drsyms and drwrap.  drsyms lets you look up symbol addrs, and drwrap will let you wrap functions.

Are those commands? 

[scameron@localhost DynamoRIO-Linux-3.1.0-4]$ find . -name 'drwrap'
[scameron@localhost DynamoRIO-Linux-3.1.0-4]$ find . -name 'drsyms'
[scameron@localhost DynamoRIO-Linux-3.1.0-4]$

The infrastructure is daunting.  cmake... yuck. :)
 
-- steve

Qin Zhao

unread,
Mar 21, 2012, 9:40:55 PM3/21/12
to dynamor...@googlegroups.com
drwrap and drsym are two extension of DynamoRIO to make user writing DynamoRIO client easier.
Please have a look at the examples of DynamoRIO client in sample folder.
We will give a tutorial on CGO 2012 on Mar 31, at San Jose, CA. http://dynamorio.org/tutorial.html 
You are encouraged to attend if possible.

Qin

--
You received this message because you are subscribed to the Google Groups "DynamoRIO Users" group.
To view this discussion on the web visit https://groups.google.com/d/msg/dynamorio-users/-/8L8KbrHWYD8J.

To post to this group, send email to dynamor...@googlegroups.com.
To unsubscribe from this group, send email to dynamorio-use...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/dynamorio-users?hl=en.

Stephen Cameron

unread,
Mar 22, 2012, 10:38:52 AM3/22/12
to dynamor...@googlegroups.com


On Wednesday, March 21, 2012 8:40:55 PM UTC-5, qin wrote:
drwrap and drsym are two extension of DynamoRIO to make user writing DynamoRIO client easier.
Please have a look at the examples of DynamoRIO client in sample folder.
We will give a tutorial on CGO 2012 on Mar 31, at San Jose, CA. http://dynamorio.org/tutorial.html 
You are encouraged to attend if possible.

I had noticed that, and I would love to go, but I'm in Houston, and it seems
unlikely my employer would spring for that.

BTW, I had previously emailed Ian Lance Taylor (author of gold, an
alternate linker to ld) asking whether it was possible to wrap static
functions.  He wrote back:

> > Is there a way to override functions with static scope
> > within an object module?  (I'm on x86_64 and i386 linux)
>
> No, there isn't.  In particular, the compiler may inline calls to static
> functions, and it may also rewrite the functions to use a different
> calling convention (GCC does both of these optimizations).  So there is
> no reliable way to override a static function after the code has been
> compiled.

The inlining I think I can get around just by compiling with -fno-inline.

Does DynamoRIO deal with the rewriting of calling conventions?
 
-- steve

Reid Kleckner

unread,
Mar 22, 2012, 11:21:34 AM3/22/12
to dynamor...@googlegroups.com
On Thu, Mar 22, 2012 at 10:38 AM, Stephen Cameron <stephen...@gmail.com> wrote:
> > Is there a way to override functions with static scope 
> > within an object module?  (I'm on x86_64 and i386 linux)
>
> No, there isn't.  In particular, the compiler may inline calls to static
> functions, and it may also rewrite the functions to use a different
> calling convention (GCC does both of these optimizations).  So there is
> no reliable way to override a static function after the code has been
> compiled.

The inlining I think I can get around just by compiling with -fno-inline.

Does DynamoRIO deal with the rewriting of calling conventions?

No, but if you can disable inlining you can just build at O0 and that shouldn't happen.

It might be easier to do something horrible like pass -Dstatic= to the compiler.  For plain C, that shouldn't cause too many functional changes, so long as there are no name conflicts in the .o files you want to link into the test binary.

Reid 

Qin Zhao

unread,
Mar 22, 2012, 11:24:01 AM3/22/12
to dynamor...@googlegroups.com
The linker can wrap a exported function by simply change the linking information, e.g. the PLT or GOT table, which was designed to be modifiable for easy of linking. However, you can not do so for static internal functions. 

When running programs in DynamoRIO, all the code will actually be copied into a software code cache and executed there. During the copy, you can modify the code anyway you want, which enables you to wrap any functions, of course, at your own risk.

Best Regards
Qin


On Thu, Mar 22, 2012 at 10:38 AM, Stephen Cameron <stephen...@gmail.com> wrote:

--
You received this message because you are subscribed to the Google Groups "DynamoRIO Users" group.
To view this discussion on the web visit https://groups.google.com/d/msg/dynamorio-users/-/imE6QhuzvYkJ.

To post to this group, send email to dynamor...@googlegroups.com.
To unsubscribe from this group, send email to dynamorio-use...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/dynamorio-users?hl=en.

Stephen Cameron

unread,
Mar 22, 2012, 3:17:01 PM3/22/12
to dynamor...@googlegroups.com

Now that is not a bad idea.  It had sort of occurred to me to do that by adding a '#define static' line into the source, but I was a little uncertain as there are two meanings that static has.  But, looking over the code I'm interested in, I think it only uses it for scoping, and I forgot you could do that via gcc options too.  That would mean I could do everything I wanted to do with just the linker, which would be a lot easier.

Thanks!

-- steve

Reid 

Reid Kleckner

unread,
Mar 22, 2012, 3:47:09 PM3/22/12
to dynamor...@googlegroups.com
On Thu, Mar 22, 2012 at 3:17 PM, Stephen Cameron <stephen...@gmail.com> wrote:
Now that is not a bad idea.  It had sort of occurred to me to do that by adding a '#define static' line into the source, but I was a little uncertain as there are two meanings that static has.  But, looking over the code I'm interested in, I think it only uses it for scoping, and I forgot you could do that via gcc options too.  That would mean I could do everything I wanted to do with just the linker, which would be a lot easier.

It occurs to me it will break code like this:

void func(int args) {
    static int my_local_thats_really_global;
    ...
}

That variable will become locally scoped.

If static always comes first, you could try to regex replace ^static to get only the static decls at global scope.

Reid
Reply all
Reply to author
Forward
0 new messages