tags:

views:

650

answers:

6

Hi,

Has anybody added a pass to gcc ? or not really a pass but adding an option to do some nasty things... :-) ...

I still have the same problem about calling a function just before returning from another...so I would like to investigate it by implementing something in gcc...

Cheers.

EDIT: Adding a pass to a compiler means revisiting the tree to perform some optimizations or some analysis. I would like to emulate the behavior of __cyg_profile_func_exit but only for some functions and be able to access the original return value.

So I'm going to try to enhance my question. I would like to emulate really basic AOSD-like behavior. AOSD or Aspect oriented programming enables to add crosscutting concerns (debugging is a cross-cutting concern).

int main(int argc, char ** argv) {
  return foo(argc);
}

int foo(int arg_num) { 
   int result = arg_num > 3 ? arg_num : 42;
   return result;
}

int dbg(int returned) {
   printf("Return %d", returned);
}

I would like to be able to say, I'd like to trigger the dbg function after function foo has been executed. The problem is how to tell the compiler to modify the control flow and execute dbg. dbg should be executed between return and foo(argc) ...

That's really like __cyg_profile_function_exit but only in some cases (and the problem in __cyg_profile_function_exit is that you cannot easily see and modify the returned value).

+1  A: 

To answer your question: gcc is a pretty popular compiler platform to do compiler research on, so yes, I'm sure someone has done it.

However, I don't think this is something done in a weekend. Hooking into gcc's code-generation is not something you'd do over the weekend. (I'm not sure what your scope is and how much time you're willing to invest.) If you really do want to hack gcc to do what you want, you most certainly want to start by discussing it on one of the gcc mailing lists.

Tips: don't assume that people have read your other questions. If you want to refer to a question, please add a link to it if you want people to find it.

JesperE
I'm pretty sure someone has done it before :-) ... I only wanted to avoid some painful moments by asking this community. Actually the documentation of gcc provides a bunch of patches representing trivial passes. But I wanted to find some more precisions. My question was really too generic. sorry..
LB
A: 

The GCC, the GNU Compiler Collection, is a large suite, and I don't think hacking up its source code is your answer for find problems in a single application.

It sounds like you are looking more-so for debugging or profiling tools, such as gdb, and its various front-ends (xgdb, ddd) and and gprof. Memory / Bounds checking tools like electric fence, glibc's memcheck, valgrind, and mudflap might help if this is a memory or pointer issues. Enabling compiler flags for warnings and newer C standards might be useful -std=c99 -Wall -pedantic.

I cannot understand what you mean by

I still have the same problem about calling a function just before returning from another.

So I am not certain what you are looking for. Can you give a trivial or pseudo-code example?

I.e.

#include <stdio.h>
void a(void) {
   b();
}
void b(void) {
   printf("Hello World\n");
}
int main(int ac, char *av[]) {
   a();
   return 0;
}
mctylr
+1  A: 

It's an interesting question. I'm going to address concepts around the question rather than answer the question directly because, well, I don't know that much about gcc internals.

You've probably already explored some higher-level manipulation of the source code to achieve what you want to accomplish; some kind of

int main(int argc, char ** argv) {
    return dbg(foo(argc));
}

inserted with with a macro on the function "foo", perhaps. If you're looking for a compiler hack, though, then you probably don't want to modify source.

There are some gcc extensions discussed here that sound a bit like what you're going for. If gcc has anything that does what you want, it'll probably be documented in the C-language extensions area of the documentation. I couldn't find anything that sounded exactly like what you've described, but perhaps since you understand best what you're looking for, you'll know better how to find it.

A gdb script would do a pretty good job of outputting debug, but it sounds like you've got bigger plans than simply doing printf's. Inserting significant logic into the code seems to be what you're after.

Which reminds me of some dynamic linker tricks I've come across recently. Library interposing could insert code around function calls without affecting the original source. The example I've encountered was on Solaris, but there is probably an analog on other platforms.

Just came across the -finstrument-functions option documented here

-finstrument-functions

Generate instrumentation calls for entry and exit to functions. Just after function entry and just before function exit, the following profiling functions will be called with the address of the current function and its call site. (On some platforms, __builtin_return_address does not work beyond the current function, so the call site information may not be available to the profiling functions otherwise.)

          void __cyg_profile_func_enter (void *this_fn,
                                         void *call_site);
          void __cyg_profile_func_exit  (void *this_fn,
                                         void *call_site);

But I guess this doesn't work because you are not able to modify the return value from the profiling functions.

veefu
the -finstrument-function enables to use __cyg_profile_function_exit, I think I'm going to add an option and an attribute to gcc to do my own version. I've used interposing before for malloc and free but the problem is that return is a keyword, so you cannot capture it.
LB
Hmm... I don't really understand. You're saying you need to execute dbg() after foo() ONLY when "return foo();" and not during other, say, "if (foo()){}" calls?
veefu
I dunno, I think interposing would work well for you. What's the difference between inserting code to modify the 'return' statement of X() and interposing another X() that calls the first X() but modifies the return it received? It's all the same to the caller, right?
veefu
+1  A: 

Do you need to use GCC? LLVM looks like it would work. It is written in C++, and it is very easy to write a pass.

Zifre
yes... I know this work... I'm trying to minimize the impact of my modification on the developers (but even recompiling gcc can be tricky)...I am going to try LLVM to see...thanks...
LB
+2  A: 

If you still are interested in adding a GCC pass, you can start reading up GCC Wiki material just about that:

Laurynas Biveinis
thanks...i knew these references though... I wanted something better-documented more like a tutorial... Looking at patches implementing passes is quite cumbersome...thanks though
LB
Hmm... To the best of my knowledge (I occasionally contribute to GCC) if any such tutorial existed, it'd be immediately linked from those pages.
Laurynas Biveinis
+2  A: 

Just for future reference: Upcoming versions of gcc (4.4.0+) will provide support for plugins specifically meant for use cases such as adding optimization passes to the compiler without having to bootstrap the whole compiler.

May 6, 2009:GCC can now be extended using a generic plugin framework on host platforms that support dynamically loadable objects. (see gcc.gnu.org)

none
nice...thanks a lot...I'm going to look at that..
LB
just for your info: the infrastructure is already in place, so if you don't mind getting the sources from their repository, then you can get started immediately
none