Need trace of user methods called when running Qt Creator 2.6.0 based on Qt 4.8.2 with g++ 4.4.7 or MS Visual Studio 2010

phoffric
phoffric used Ask the Experts™
on
Using Qt Creator 2.6.0 based on Qt 4.8.2 with g++ 4.4.7 or MS Visual Studio 2010.

Was given project consisting of dozens of classes each containing many methods.

I do not want to put in break points in every method to find out which methods are called - too many methods.  Is there any way to get the QT compiled code to generate a log of the methods called while running the program?

Note that updating programs or compiler is not allowed so I am stuck with what I have.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Top Expert 2016

Commented:
imo there is no log of the current stack.

to show call hierarchy into the output window of the IDE you might add

qDebug() << "begin " << __FUNCTION__ << "\n";

at begin of each function

and

qDebug() << "end " << __FUNCTION__ << "\n";

at each return.

this can easily made more comfortable by defining macros.

#define BEG_FUNC qDebug() << "begin " << __FUNCTION__ << "\n";

in a global header file. it is also possible to indent the function names properly if you want.

note the qDebug() would do nothing in release build. so you could use the macros both in debug or release.

Sara

Author

Commented:
In some previous projects, I've done those ENTER/EXIT messages before for specific functions. But I am looking for a trace of functions for the entire program as they are called without having to modify any code. I just hit the green Debug run button, and hope to get a trace.

Hopefully, there is a way to do this by setting up some compiler configuration.

Author

Commented:
Keep in mind that I would rather not do the code modification that you suggest for 1000+ methods. I would not be allowed to include that in my code base, so in the end, I would have to remove them. I am just trying to navigate my way around 22K+ LOCs.
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Author

Commented:
<<EDIT>>
I have updated the question with the correct version numbers:
Qt Creator 2.6.0 based on Qt 4.8.2 with g++ 4.4.7.
Top Expert 2016

Commented:
i recently worked in huge project with millions of lines of code. we used macros at the begin and end of functions (non-trivial functions only) in order to get a trace and to implement a try-catch for each function. this was done over decades but adding those macros for new code is no efforts. actually it is also not very difficult to write a little tool which adds those macros to existing code. of course you might need a few of  persuading what might be easier if you can show a sample project where it already worked and where the advantages can be seen.

Sara

Author

Commented:
I recall in the past that I was able to get a function trace without having to modify the code base. I just started a new job and do not want to persuade the lead to do this.

I am looking for a qt creator method to do this without having to change the code.
Duncan RoeSoftware Developer

Commented:
With the constraints you face, you have to go for gdb breakpoints: there is no other way.
Given your assignment, I would go for a specialised expect script to drive gdb, using as a start point my generalised gdb expect script "ggo". ggo feeds gdb breakpoint and other commands from its command line, but would not be appropriate for literally thousands of breakpoints. The specialised script would set the breakpoints from a list of functions that you'll have to come up with. On hitting a breakpoint, the script reports the function being entered and sends gdb a fin command. On hitting a fin termintaion, the script reports the function being returned from and issues another fin command.

HTH
Have you tried using Qt debug mode? Or is this not a option for you?
http://doc.qt.io/qtcreator/creator-debug-mode.html

Author

Commented:
>>  you have to go for gdb breakpoints: there is no other way.
Ok, you are saying that "it cannot be done". I will try to find a mechanism to do this without modifying the existing code or using breakpoints. I think I found a Linux lead yesterday, but will need to find some time next week to see if it does the job. (I cannot always get on a Linux workstation - have to borrow one when the owner has logged out for the day.)

>>Have you tried using Qt debug mode? Or is this not a option for you?
I am guessing that you are suggesting that I put in breakpoints in the hundreds of methods.

From the OP:
I do not want to put in break points in every method to find out which methods are called - too many methods.

Author

Commented:
BTW, I thought I saw that gdb allows regex in setting breakpoints, so that if all the methods began with XYZ, then I could set a breakpoint on all the methods beginning with XYZ in one command. That would have been half way acceptable. At least I could keep hitting "go" and get a list that way. Ideally, with breakpoints, I would want a "continue" in the action on hitting the breakpoint so that I wouldn't have to keep going manually.

But the legacy project that I am looking at does not have any universal pattern in naming methods.
It may be possible to use the built in debugging helpers they have 200 or more built in.
Qt Creator ships with debugging helpers for more than 200 of the most popular Qt classes, standard C++ containers, and smart pointers, covering the usual needs of a C++ application developer out-of-the-box.
http://doc.qt.io/qtcreator/creator-debugging-helpers.html

Author

Commented:
If you could be more specific in using debugging helpers as to how to solve my question, i would appreciate that.

I am not interested in examining Qt classes or standard C++ container, or smart pointers usage. The only thing I am interested in is seeing what programmer defined methods are called when I start the program and let it run for a few seconds. Right now, it is hard for me to know what are is being called and the order they are called in once the GUI is displayed.

There are 1000's of Qt SIGNALS and SLOTS connections, so a manual trace is very difficult for the 1000 methods.

Author

Commented:
>> imo there is no log of the current stack.
Not absolutely positive of what you are referring to, but if you are saying that "the OP goal can't be done", then I have found a way to accomplish this goal.

>> qDebug() << "begin " << __FUNCTION__ << "\n";  at begin of each function
Violates the terms of the OP:
      "Note that updating programs or compiler is not allowed"
   
>> you have to go for gdb breakpoints: there is no other way.
>> Have you tried using Qt debug mode?
Violates the terms of the OP:
      "I do not want to put in break points in every method to find out which methods are called - too many methods."
Here is how to solve the OP question for Linux.

When compiling the modules to get a trace of the Enter/Exit calling sequence, add the compiler option:
-finstrument-functions
Here is the documentation for this option:

Generate instrumentation calls for entry and exit to functions. Just after function entry and just before function exit, the following profiling functions are 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);

The first argument is the address of the start of the current function, which may be looked up exactly in the symbol table. I didn't figure out what the call_site address was from the output, so I just didn't print it out. For these two functions, I had to use the following to get the C code to mix in properly with the C++ code:
extern "C"
{
... // the implementation of the enter/exit functions.
}

Open in new window


This instrumentation is also done for functions expanded inline in other functions. The profiling calls indicate where, conceptually, the inline function is entered and exited. This means that addressable versions of such functions must be available. If all your uses of a function are expanded inline, this may mean an additional expansion of code size. If you use extern inline in your C code, an addressable version of such functions must be provided. (This is normally the case anyway, but if you get lucky and the optimizer always expands the functions inline, you might have gotten away without providing static copies.)

A function may be given the attribute no_instrument_function, in which case this instrumentation is not done. This can be used, for example, for the profiling functions listed above, high-priority interrupt routines, and any functions from which the profiling functions cannot safely be called (perhaps signal handlers, if the profiling routines generate output or allocate memory).
https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html

By writing your own customized functions:
__cyg_profile_func_enter
__cyg_profile_func_exit

Open in new window

you can get the calling sequence.  You can even add proper indentation to make the nesting calling sequence easier to read. This results in the addresses of the functions/methods being called - not too user-friendly.

Next step is to run nm --demangle on the executable.

This provides a nice mapping of addresses to the functions/methods. (Actually, I haven't tried virtual methods yet - but, I don't recall that inheritance was being used except for the Qt classes which I am not concerned with.)

For a toy program with only several functions, it is easy to use the mapping and sed to view a user-friendly calling sequence. But, for 1000's of functions/methods, you just have to write a program or script to create a map from the  nm output, and then programmatically change the addresses to the function/method names based on this map.
Duncan RoeSoftware Developer

Commented:
Looks good! Will you be accepting your post as the solution?

Author

Commented:
What I am doing now is just running the program under certain GUI operations, and then looking at the calling sequence after the program completes.

Alternatively, I think I can keep the program running continuously. I believe I could customize the two enter/exit functions to send the results to another program which transforms the results into a user-friendly active display as I am running the program.

Since the program is a simulation, I would probably have to set the Time Step to an artificially long period, say 20-60 seconds, to give me a chance to review the calling sequence depending upon what GUI buttons/text entries I would make.

Author

Commented:
@Duncan

I didn't really understand your post and was going to discuss it with you when I discovered the -finstrument-functions compiler option, and pursued that approach. I have limited time at work to try things since they kick me out way too soon compared to everywhere else I worked - well, rules are rules :( :( .

If your approach satisfies the OP constraints, then I'd like to talk to you about it. I am on a crushing development effort at the moment to demonstrate that the lead's Model Description Document is sufficiently well-written that I can actually write a model from it; and I promised not to look at his model/code (which is the source of this question), so this effort is on hold for a little bit until I finish that section.

But I would like to understand what you were driving at in the next couple of weeks, if that's OK with you. I won't have time at work, but on a free weekend, I could come up with a toy foo/bar example and see what you are talking about.
Duncan RoeSoftware Developer

Commented:
Fine, look forward to that,

Cheers ... Duncan.
Duncan RoeSoftware Developer

Commented:
This appears to answer the Q and EE wants the Q closed.
phoffric - you can still post to this Q after it is closed (e.g. to pursue the expect path)

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial