I'm trying to analyze why a (quite large) program segfaults. If the program crashes it writes a core dump to /tmp which I try to analyze using gdb. However, gdb gives me the following error:
Reading symbols from /home/user/Executable...Dwarf Error:
wrong version in compilation unit header (is 4, should be 2)
[in module /home/user/Executable]
I've searched a bit and found a thread on stackoverflow where the author assumes that this was the result of compiling parts of the code (precisely a library he/she was using) with a different -g flag.
I've checked the version of the compilation unit on my executable (C++) and a library (C) I'm using in my program via
readelf --debug-dump=info Executable | grep -A 2 'Compilation Unit #'
And apparently the executable has everywhere a version of 4, while the library has a version of 2. I'm wondering if it is possible to fix this and how? I'm also quite curious how this problem actually rose in the first place (toying around with the debug level via the -g flag doesn't helped at all).
TIA
The set of inputs that produce a single object file (.o) is called a compilation unit; for more info, see wikipedia. For convenience, "compilation unit" is often abbreviated as "CU."
When compiling a CU with debug information, each CU has a debug information section that begins with a CU header; this header contains a version number. This debugging information is in a format called DWARF.
Over time the DWARF standard has evolved. For each major release, the version number has changed. This ensures that when a DWARF producer (e.g., a compiler) creates debug information, the DWARF consumer (e.g., a debugger) knows what to expect.
When gdb complains about the version of a CU, it is really complaining about the version number that is in the DWARF CU header.
To avoid this problem, as you have discovered, you have to make sure that your entire software development toolchain (compiler, linker, debugger) is able to "speak" the same DWARF version. Your solution of compiling the latest version of gdb is correct.
From the GCC 4.8 release notes:
Before GCC 4.8 the default version used was DWARF2. To make GCC 4.8 generate an older DWARF version use -g together with -gdwarf-2 or -gdwarf-3
In my case, adding
-gdwarf-2 -gstrict-dwarf
made the old debugger to work again. I agree that using a newer GDB version is the best solution in most cases, though.
I've compiled the library with g++ (instead of gcc) which resulted in the desired compilation unit. However, this still resulted in the DWARF error thrown by gdb and so I compiled the latest version of gdb on the machine and finally it works now.
Related
I have a Fortran program I would like to profile with GNU coverage. So I compiled the program with GCC 11.2 with these coverage options:
-fprofile-arcs -ftest-coverage
Also, I add flags to disallow compiler to inline the code:
-fno-inline -fno-inline-small-functions -fno-default-inline
I turned off lto and add -lcgov to linker. This setup worked well for a sample program I proved. But when I tried to use it for the program I am interested in it did not generate any *.gcno files, just nothing. Execution, however, exited well (0 exit code) producing correct results.
My question is, how can I find where the problem is. Without an error message, I don't know where to start. It is a rather bigger program ~10 MB of source code, can that be a problem? Also, it heavily depends on MKL, can the external library be the problem? Once I accidentally mixed compile time and runtime environments and it complained about the version of libgcov.so, so something is working after all. Or do you have any other suggestions for coverage profiling?
GDB documentation tells me that in order to compile for debugging, I need to ask my compiler to generate debugging symbols. This is done by specifying a '-g' flag.
Furthermore, GDB doc recommends I'd always compile with a '-g' flag. This sounds good, and I'd like to do that.
But first, I'd like to find out about downsides. Are there any penalties involved with compiling-for-debugging in production code?
I am mostly interested in:
GCC as the compiler of choice
Red hat Linux as target OS
C and C++ languages
(Although information about other environments is welcome as well)
Many thanks!
If you use -g (which on recent GCC or Clang can be used with optimization flags like -O2):
compilation time is slower (and linking will use a lot more memory)
the executable is a bigger file (see elf(5) and use readelf(1)...)
the executable carries a lot of information about your source code.
you can use GDB easily
some interesting libraries, like Ian Taylor's libbacktrace, requires DWARF information (e.g. -g)
If you don't use -g it would be harder to use the GDB debugger (but possible).
So if you transmit the binary executable to a partner that should not understand how your source code was written, you need to avoid -g
See also the strip(1) and strace(1) commands.
Notice that using the -g flag for debugging information is also valid for Ocaml, Rust
PS. Recent GCC (e.g. GCC 10 or GCC 11 in 2021) accept many debugger flags. With -g3 your executable carries more debug information (e.g. description of C++ macros and their expansion) that with -g or -g1. Of course, compilation time increases, and executable size also. In principle, your GCC plugin (perhaps Bismon in 2021, or those inside the source code of the Linux kernel) could add even more debug information. In practice, you won't do that unless you can improve your debugger. However, a GCC plugin (or some #pragmas) can remove some debug information (e.g. remove debug information for a selected set of functions).
Generally, adding debug information increases the size of the binary files (or creates extra files for the debug information). That's nowadays usually not a problem, unless you're distributing it over slow networks. And of course this debug information may help others in analyzing your code, if they want to do that. Typically, the -g flag is used together with -O0 (the default), which disables compiler optimization and generates code that is as close as possible to the source, so that debugging is easier. While you can use debug information together with optimizations enabled, this is really tricky, because variables may not exist, or the sequence of instructions may be different than in the source. This is generally only done if an error needs to be analyzed that only happens after the optimizations are enabled. Of course, the downside of -O0 is poorer performance.
So as a conclusion: Typically one uses -g -O0 during development, and for distribution or production code just -O3.
I am trying to compile my project for use of debugging with gprof; however, I am having numerous issues.
Right now, I am trying to create a separate target in my makefile that is 'gprof' which depends upon the executable. This target, beforehand, adds the flags -g -gdwarf-3 and -pg to the compilation flags and -pg to the linker flags.
The unfortunate thing is I cannot get gprof to run successfully, as my compiled binary doesn't produce the required gmon.out. There are also side issues regarding this process.
1.) I am getting an issue regarding a clang warning when trying to introduce gdwarf-3 flags. This issue is clang: warning: argument unused during compilation: '-gdwarf-3'.
2.) The makefiles (3 of them, one main, one more main executable, and one for linked library) were produced by premake. I have edited them to introduce compiler and linker flags.
3.) I don't know how to compile the linked library (vecmath) under gprof (do I even need to?). The ar command doesn't accept the necessary -pg flag needed for gprof.
I am trying to perform this on a macbook air 2011, MAC OSX 10.8. I will try to attempt this later in linux.
My three makefiles are shared here. Makefile calls a5.make and vecmath_makefile (this file title was edited). Any help is appreciated thanks!
I have an c++ application developed using gcc(4.1) and compiled with CMAKE MakeFiles . The Code is large in size and debugging it is tough. I dont know how to debug the code line by line using cmake Utility. Any idea how to do it?
Thanks in advance :) .
CMake is a system to enhance the definition of makefiles (it is a meta system that creates platform specific makefiles). It is not a debugger. You can use gdb for debugging.
To ensure your program is compiled for debugging properly, make sure the flags passed to gcc include -O0, which means no-optimizations, and -g for debugging information,
or -ggdb to produce a format that suits gdb really well (see also http://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html).
I have just installed MinGW and in the bin folder I can see 7 .exe files that compile my program:
c++.exe
g++.exe
mingw32-c++.exe
mingw32-g++.exe
gcc.exe
mingw32-gcc.exe
mingw32-gcc-4.4.1.exe
My small program (testprog.cpp) compiles correctly with each of them; the a.exe file is generated in the bin folder and it runs correctly.
What's the difference between them and which one should I use?
Also, what can I do to change the name of the output file from a.exe to testprog.exe automatically upon each successful compile?
These follow gcc naming conventions.
c++.exe is a traditional name for the system c++ compiler
g++.exe and gcc.exe are the names for the gcc compilers that compile for the "current system"
mingw32-* versions are the names for the compilers that cross-compile to the "mingw" target. In this case this is the same as the system target.
An then mingw32-gcc-4.1.exe is "gcc for mingw target version 4.1"
You should typically compile C code with a "gcc" variant, and c++ code with a "g++" variant.
Use -o filename in order to specify the output filename, the default is a.exe
It's quite possible that they are all the same; either exact copies or symbolic links to one another. Try using the --version flag on each to see what you've got. On my MingGW installation here, each of those binaries differs (checked with diff), but they all output the same version information (with the exception of the first bit, which is the filename):
gcc.exe (GCC) 3.4.5 (mingw-vista special r3)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Use the -o flag to change the output file name:
gcc -o testprog.exe testprog.cpp
In unix they'd mostly by symbolic links. The only major difference is between the 'cc' vs. '++' ones. You should notice a difference between these two if you use any part of the standard C++ library. The '++' versions link to that lib automatically. The 'cc' ones are C compilers and so don't...though you can use them as C++ compilers by just adding -lstdc++ or whatever.
While I was searching around the web for instructions in making some DLLs, I ran into a C++ compilation process that, from what I saw, used g++ to compile c++ the same way as using gcc.
I used "g++.exe"
Then in my IDE, VSCode, I also had to change the "IntelliSense mode" to "windows-gcc-x64" to get rid of the warning