How to trace specific functions/files in C? - c

I have already known that the GCC's argument -finstrument-functions can hook the functions and the argument -finstrument-functions-exclude-file(functions)-list can exclude some files/functions to be traced.
But now I have a lot of files to be compiled and only some of them need to be traced. I wonder if I can include some specific functions/files to be traced, such as something like -finstrument-functions-include-file(functions)-list?
Thanks a lot!

GCC does not support this out-of-the-box (it's more a task for your build system). One common hack to achieve what you want is to write a shell wrapper which replaces GCC and adds flags where needed:
$ cat path/to/fake/gcc
#!/bin/sh
FLAGS=
if echo "$*" | grep -q 'myfile1.c'; then
FLAGS=-finstrument-functions
fi
exec /usr/bin/gcc "$#" $FLAGS
$ export PATH="path/to/fake:$PATH"

If you use cmake to build your project you may benefit from adding COMPILE_OPTIONS at a specific level. Use
add_compile_options()
for directory-wide settings
target_compile_options()
for target-specific settings and
set_source_files_properties()
for file specific settings.
In your case
set_source_files_properties(
myfile1.cc PROPERTIES COMPILE_FLAGS -finstrument-functions)

Recent GCC compilers can be extended by GCC plugins.
But now I have a lot of files to be compiled and only some of them need to be traced.
You should consider writing your own GCC plugin to do that job. See also this draft report.
You may configure your build automation tool (e.g. GNU make or ninja) to help you.
At last, some of your C code (e.g. #include-ed files) could be generated. Think of meta-programming approaches (e.g. with SWIG or ANTLR or Bison or GPP or your own C code generator), perhaps using X-macros.

Related

Identify version of C file

For a project I need to find if a c file has code that requires >=C11 or C99 compiler. Can this be done with gcc, or ctags?
Basically I need to identify the minimum version of compiler required to compile the file. I have tried different tools including ctags etc.
Use grep -- -std= Makefile
ctags: no way
If you are looking for something smarter... bad luck.

Shell command to compile C in Gprbuild

Using GtkAda, I'm trying to use the resource API to include the Glade file directly inside my code.
For this, we can generate C code from a set of resources using glib-compile-resources which can then be linked to the Ada code.
The problem is that this C code requires Gtk includes which we usually get from the pkg-config command under Linux such as
gcc -c -x c `pkg-config --cflags gio-2.0` myglade.gresource.c
I'd like to know how to provide the same kind of information in a GPRBuild project file.
FYI, I already tried to use the pkg-config command inside the compiler package for C language without any success. Of course, I managed to build by hand but that's a bit long :)
This might work for you:
project Config_Demo is
Pkg_Config := external_as_list ("PKG_CONFIG", " ");
package Compiler is
-- only this file needs the extra switches
for Switches ("myglade.gresource.c") use Pkg_Config;
end Compiler;
end Config_Demo;
and then
gprbuild -P config_demo -XPKG_CONFIG="`pkg-config -cflags gio-2.0`"
Your best bet will be to do what GtkAda does: Look at its shared.gpr.in file, it uses the token #GTK_LIBS_GPR# which will be replaced by the configure script, giving a usable shared.gpr.
Thing is, you need to issue the pkg-config call and build your gpr file from the result somehow. GPRBuild is not equipped to do this for you and process the result. If you're comfortable with GNU autotools, you can look further at how GtkAda achieves it:
GTK_LIBS_GPR is set in aclocal.m4 using a macro that converts the C-style flags to a GPR array. The value comes from GTK_LIBS which is queried here via pkg-config.
If you're not comfortable with GNU autotools, you can write your configure script using basic shell commandos, a scripting language like Python or with whatever other tool you're comfortable with.

Need to figure our what a specific symbol is replaced to after macro expansion [duplicate]

Let's say I have a source file with many preprocessor directives. Is it possible to see how it looks after the preprocessor is done with it?
cl.exe, the command line interface to Microsoft Visual C++, has three different options for outputting the preprocessed file (hence the inconsistency in the previous responses about Visual C++):
/E: preprocess to stdout (similar to GCC's -E option)
/P: preprocess to file
/EP: preprocess to stdout without #line directives
If you want to preprocess to a file without #line directives, combine the /P and /EP options.
Most compilers have an option to just run the preprocessor. e.g., gcc provides -E:
-E Stop after the preprocessing stage; do not run the compiler proper.
The output is in the form of preprocessed source code, which is sent
to the standard output.
So you can just run:
gcc -E foo.c
If you can't find such an option, you can also just find the C preprocessor on your machine. It's usually called cpp and is probably already in your path. Invoke it like this:
cpp foo.c
If there are headers you need to include from other directories , you can pass -I/path/to/include/dir to either of these, just as you would with a regular compile.
For Windows, I'll leave it to other posters to provide answers as I'm no expert there.
Right-click on the file on the Solution Explorer, goto Properties. Under Configuration Properties->C/C++->Preprocessor, "Generate Preprocessed File" is what you are looking for. Then right-click on the file in the Solution Explorer and select "Compile". The preprocessed file is created in the output directory (e.g. Release, Debug) with an extension .i (thanks to Steed for his comment).
You typically need to do some postprocessing on the output of the preprocessor, otherwise all the macros just expand to one liners, which is hard to read and debug. For C code, something like the following would suffice:
gcc -E code.c | sed '/^\#/d' | indent -st -i2 > code-x.c
For C++ code, it's actually a lot harder. For GCC/g++, I found this Perl script useful.
I don't know anything about Microsoft compiler, but on GCC you can use this:
gcc -E -P -o result.c my_file.h
If you want to see comments use this:
gcc -E -C -P -o result.c my_file.h
More options avaliable on this page.
Try cl /EP if you are using Microsoft's C++ compiler.
As bk1e and Andreas M. answered, the /P option for the compiler will cause it to preprocess a file. However, in my project using VS2005 and Platform Builder (for an embedded ARM processor), the project did not present an option in the dialog box (as described by Jim B) to enable that option.
I could run CL manually and add /P, but it failed because I did not know all of the appropriate command-line options that were invisibly being activated by Platform Builder during the full build. So I needed to know all of those options.
My solution was to go look in the build.log file, and find the line that executed
CL blah-blah-blah myfile.c
I copied this line to the clipboard. The "blah-blah-blah" part contained the build options, and was huge.
Back in the IDE, I right-clicked on myfile.c, chose "Open Build Window", and then in that window I pasted the build command-line, and added a "/P".
CL /P blah-blah-blah myfile.c
Done. The myfile.i file was produced, which contained the preprocessor output.
In Visual Studio you can compile a file (or project) with /P.
CPIP is a new C/C++ preprocessor written in Python. If you want a detailed visual representation of a preprocessed file, give it a shot.
CPIP is a C/C++ pre-processor implemented in Python. Most pre-processors regard pre-processing as a dirty job that just has to be done as soon as possible. This can make it very hard to track down subtle defects at the pre-processing stage as pre-processors throw away a lot of useful information in favor of getting the result as cheaply as possible.
Few developers really understand pre-processing, to many it is an obscure bit of black magic. CPIP aims to improve that and by recording every detail of preprocessing so CPIP can can produce some wonderfully visual information about file dependencies, macro usage and so on.
CPIP is not designed to be a replacement for cpp (or any other established pre-processor), instead CPIP regards clarity and understanding as more important than speed of processing.
On Windows OS, a simple one line answer to this question is to use the below command in DOS prompt to see the preprocessed file:
CL /P /C myprogram.c
This will generate a file called myprogram.i. Open it and look out for your expanded preprocessors.

Can the object files output by gcc vary between compilations of the same source with the same options?

Does the gcc output of the object file (C language) vary between compilations? There is no time-specific information, no change in compilation options or the source code. No change in linked libraries, environmental variables either. This is a VxWorks MIPS64 cross compiler, if that helps. I personally think it shouldn't change. But I observe that sometimes randomly, the instructions generated changes. I don't know what's the reason. Can anyone throw some light on this?
How is this built? For example, if I built the very same Linux kernel, it includes a counter that is incremented each build. GCC has options to use profiler information to guide code generation, if the profiling information changes, so will the code.
What did you analyze? The generated assembly, an objdump of object files or the executable? How did you compare the different versions? Are you sure you looked at executable code, not compiler/assembler/linker timestamps?
Did anything change in the environment? New libraries (and header files/declarations/macro definitions!)? New compiler, linker? New kernel (yes, some header files originate with the kernel source and are shipped with it)?
Any changes in environment variables (another user doing the compiling, different machine, different hookup to the net gives a different IP address that makes it's way into the build)?
I'd try tracing the build process in detail (run a build and capture the output in a file, and do so again; compare those).
Completely mystified...
I had a similar problem with g++. Pre 4.3 versions produced exactly the same object files each time. With 4.3 (and later?) some of the mangled symbol names are different for each run - even without -g or other recordings. Perhaps the use a time stamp or random number (I hope not). Obviously some of those symbols make it into the .o symbol table and you get a difference.
Stripping the object file(s) makes them equal again (wrt. binary comparison).
g++ -c file.C ; strip file.o; cmp file.o origfile.o
Why should it vary? It is the same result always. Try this:
for i in `seq 1000`; do gcc 1.c; md5sum a.out; done | sort | uniq | wc -l
The answer is always 1. Replace 1.c and a.out to suit your needs.
The above counts how many different executables are generated by gcc when compiling the same source for 1000 times.
I've found that in at least some environments, the same source may yield a different executable if the source tree for the subsequent build is located in a different directory. Example:
Checkout a pristine copy of your project to dir1. Do a full rebuild from scratch.
Then, with the same user on the same machine, checkout the same exact copy of your source code to dir2 (dir1 != dir2). Do another full rebuild from scratch.
These builds are minutes apart, with no change in the toolchain or any 3rd party libs or code. Binary comparison of source code is the same. However, the executable in dir1 has different md5sum than the executable in dir2.
If I compare the different executables in BeyondCompare's hex editor, the difference is not just some tiny section that could plausibly be a timestamp.
I do get the same executable if I build in dir1, then rebuild again in dir1. Same if I keep building the same source over and over from dir2.
My only guess is that some sort of absolute paths of the include hierarchy are embedded in the executable.
My gcc sometimes produces different code for exactly the same Input. The output object files differ in exactly one byte.
Sometimes this causes linker Errors, because one possible object file is invalid. Recompiling another version usually fixes the linker error.
The gcc Version is 4.3.4 on Suse Linux Enterprise.
The gcc Parameters are:
cc -std=c++0x -Wall -fno-builtin -march=native -g -I<path1> -I<path2> -I<path3> -o obj/file.o -c file.cpp
If someone experiences the same effect, then please let me know.

ocaml top level and native library

I have a library that calls C code. It's compile with the -custom, -cclib, -l flags, which is working ok when I compile my code against the library with ocamlc,
but when I use the "ocaml" top level to run a script like:
ocaml -I /opt/godi/lib/ocaml/pkg-lib/xxxx xxx.cma myprog.ml
it says:
Error: The external function `caml_yyyy' is not available
Do I need additional parameters to tell the top level ?
You should build your own toplevel using "ocamlmktop":
$ ocamlmktop -custom -I /opt/godi/lib/ocaml/pkg-lib/xxxx xxx.cma -o ocaml_with_xxx
Then, you can use it :
$ ./ocaml_with_xxx -I /opt/godi/lib/ocaml/pkg-lib/xxxx
Note that you still need the -I so that the toplevel can find the interface files of the library that it contains.
IIRC you cannot use libraries compiled with -custom in toplevel. You should compile dynamically-loadable stubs so that toplevel could pick up them. This is very easy to do with e.g. oasis and somewhat more involved if invoking ocaml tools manually.

Resources