Using gcc with -g flag before running gdb - c

without -g flag:
(gdb) break main
Breakpoint 1 at 0x8048274
with -g flag:
(gdb) break main
Breakpoint 1 at 0x8048277: file example.c, line 31.
I vaguely know -g option stores the symbol table information.
What does the -g option exactly do?
Is there any way I can look at this symbol table?

-g (for gcc) stores debugging information in the output files so that debuggers can pick it up and present more useful information during the debugging process. Exactly what gets stored can depend a great deal on the environment you're running in.
One way to look at what this consists of is to use objdump with the --debugging option (or its equivalent short form -g which matches gcc).

The -g command line option asks the compiler to emit additional debugging information; on Linux, the format is DWARF 2, but other platforms may have different defaults -- stabs was more common, once upon a time.
readelf --debug-dump can be used to dump the debugging information itself if you're curious in what it adds -- you can see the entire program source in the .debug_info section, for example.

Related

Is -g the same as -g2 for gcc and clang?

GCC debug option documentation is not that comprehensive. So trying to compile a binary with different options -g, -g1, -g2, -g3 I got the following result.
When compiling with -g and -g2 binary has the same 13KB in size.
When compiling with -g1 the binary ended up in 9.3KB in size
When compiling with -g3 the binary has 73KB in size
So is -g equivalent to -g2? But the level 2 is not even explained in the documentation. Here is what the docs say (no level 2):
Level 0 produces no debug information at all. Thus, -g0 negates -g.
Level 1 produces minimal information, enough for making backtraces in
parts of the program that you don’t plan to debug. This includes
descriptions of functions and external variables, and line number
tables, but no information about local variables.
Level 3 includes extra information, such as all the macro definitions
present in the program. Some debuggers support macro expansion when
you use -g3.
Or am I missing something?
So is -g equivalent to -g2?
Yes.
But the level 2 is not even explained in the documentation. [...] Or am I missing something?
You are missing something. You have overlooked the sentence immediately preceding your quotation:
The default level is 2.
This means that -g2 means the same thing as -g. (And -ggdb2 means the same thing as -ggdb, etc.) This serves in part as a reference for each of the -g*2 options to the docs of the corresponding unnumbered -g* options, where you will find the relevant documentation. In particular, the documentation for -g2 is the documentation for -g, which appears first in the section.

Is it possible to pass GCC arguments directly from C source code?

I want to be able to pass arguments to GCC from my C source code, something like this...
// pass the "-ggdb" argument to GCC (I know this won't work!)
#define GCC_DEBUG_ARG -ggdb
int main(void) {
return 0;
}
With this code I'd like to simply run gcc myfile.c which would really run gcc myfile.c -ggdb (as the "-ggdb" argument has been picked up from the C source code).
I'm not interested in using make with the CFLAGS environment variable, I just want to know if its possible to embed GCC options within C source code
What you want to do is not possible in general.
However, recent GCC (e.g. GCC 8 in end of 2018) accepts many options and some of them could be passed by function attributes or by function specific pragmas (However, they don't accept -g but do accept -O2).
Also, you can use -g in every compilation (with GCC, it is mixable with optimization flags such as -O2; so runtime performance won't suffer. Of course the -g will increase compile time and size of produced object file). Notice that (on Linux) the DWARF debug information is visible in the generated assembler file (e.g. try to compile your foo.c with gcc -Wall -g -O -S -fverbose-asm foo.c, look into the generated foo.s, and repeat by removing the -g)
I'd like to simply run gcc myfile.c
That is a very bad habit. You should run gcc -Wall -Wextra -g myfile.c -o myprog to get all warnings (you really want them) and debug info in your executable myprog. Read How to debug small programs before continuing coding your program.
I'm not interested in using make with the CFLAGS environment variable
But you really should. Using make or some other build automation tool (e.g. ninja, omake, rake, etc, etc....) is, in practice, the conventional and usual way of using GCC.
Alternatively, on Linux, write a tiny shell script doing the compilation (this is particularly worthwhile if your program is a single source file; for anything bigger, you really should use some build automation tool). At last, if you use emacs as your source code editor, you could add a few lines of comments (like at end of my manydl.c example) specifying Emacs file variables to tune the compilation (done from emacs)
If these conventions surprise you, read about the Unix philosophy then study -for inspiration- the source code of some existing free software (e.g. on github, gitlab, or in your favorite Linux distribution).
At last, GCC itself is a free software project (but a huge one of more than five millions lines of mostly C++ source code). So you can improve it the way you desire (if you follow its GPLv3+ license), after having studying somehow its source code. That would take you several months (or years) of work (because GCC is very complex to understand).
See also this answer to a related question.
You might also (but I recommend not to, because it is very confusing) play tricks with your PATH variable and have some directory there -e.g. $HOME/bin/, ahead of /usr/bin/ which contains /usr/bin/gcc, with your shell script named gcc; but don't do that, you'll be confused. Instead write some "generic" mygcc shell script which would run /usr/bin/gcc and add appropriate flags to it (I believe it is not worth the effort).

C programming: How to use gdb with Makefile and command line arguments?

To create the .out executable, I have to enter:
$: make
$: myprogram.out name.ged
My program incorporates a command line argument, thus the "name.ged".
Whenever I run gdb after getting a segmentation fault (core dumped), I enter:
$: gdb a.out core
(gdb): bt
I then use the back trace command, and gdb returns:
#0 0x4a145155 in ?? ()
#1 0x08a16ce0 in ?? ()
I even tried using the up command t move up the stack, but still no luck. I can't tell which line in my program is giving me the seg fault. gdb works with my other programs that do not involve a Makefile and command arguments, so I'm wondering if my commands are incorrect.
Summarizing the comments (before anyone else does :).
Your executable file is missing the symbolic information that gdb needs to display the relevant source code. You need to add the -g option to the compile command and produce a new executable. Then re-run your failing test to produce a new core file. gdb with this executable and core will be able to show you the stack of function calls using backtrace.
In a makefile, the easiest way to do this is to add (to) the CFLAGS variable which is used with the implicit .o.c rule.
CFLAGS= -g -Wall -Wextra
You can also add this directly to the command-line (assuming a decent shell :). This sets the value as an environment variable during the execution of the make command (and sub-commands).
$ CFLAGS='-g -Wall -Wextra' make
I'd actually recommend you add this to your bash .profile, so you always get the most information from the compiler.
CFLAGS='-Wall -Wextra'
Then, when you need it, put this in the makefile to make a debuggable executable:
CFLAGS+= -g

GCC -g vs -g3 GDB Flag: What is the Difference?

When compiling C source code with either gcc or Clang, I always use the -g flag to generate debugging information for gdb.
gcc -g -o helloworld helloworld.c
I noticed that some people recommend -g3 instead. What is the difference between the -g and -g3 flags? Also is there a difference between -g and -ggdb?
From the docs:
-g
Produce debugging information in the operating system's native format (stabs, COFF, XCOFF, or DWARF 2). GDB can work with this
debugging information. On most systems that use stabs format, -g
enables use of extra debugging information that only GDB can use; this
extra information makes debugging work better in GDB but probably
makes other debuggers crash or refuse to read the program. If you want
to control for certain whether to generate the extra information, use
-gstabs+, -gstabs, -gxcoff+, -gxcoff, or -gvms (see below).
...
-ggdb
Produce debugging information for use by GDB. This means to use the most expressive format available (DWARF 2, stabs, or the native
format if neither of those are supported), including GDB extensions if
at all possible.
-gvmslevel
Request debugging information and also use level to specify how much information. The default level is 2. Level 0 produces no
debug information at all. Thus, -g0 negates -g.
....
Level 3 includes extra information, such as all the macro definitions
present in the program. Some debuggers support macro expansion when
you use -g3.
tl;dr: To answer your specific question, -g3 "includes extra information such as macro definitions... Some debuggers support macro expansion when you use -g3", while -g does not include this extra information.
The broader answer is that gcc supports four levels of debug information, from -g0 (debug information disabled) through -g3 (maximum debug information).
Specifying -g is equivalent to -g2. Curiously, the gcc docs say little about what information -g/-g2 includes or excludes:
Request debugging information and also use level to specify how much information. The default level is 2.
Level 0 produces no debug information at all. Thus, -g0 negates -g.
Level 1 produces minimal information, enough for making backtraces in parts of the program that you don't plan to debug. This includes descriptions of functions and external variables, and line number tables, but no information about local variables.
Level 3 includes extra information, such as all the macro definitions present in the program. Some debuggers support macro expansion when you use -g3.

How do I emulate objdump --dwarf=decodedline in .bundle files?

I've been successfully using objdump --dwarf=decodedline to find the source location of each offset in a .so file on Linux.
Unfortunately on Mac-OS X. It seems that .bundle files (used as shared libraries) are not queriable in this manner.
I'm optimistic that there's something I can do, because gdb is able to correctly debug and step through code in these bundles — does anyone know what it's doing?
Further information:
The dwarfdump utility claims that the .bundle file contains no DWARF data, but that it does contain STABS data; however objdump --stabs cannot find any stabs data either.
(If it makes the question easier to answer, I don't actually need all of the offsets; being able to query the source location of any given offset would be good enough).
The bundle file I've been testing this on was generated using:
cc -dynamic -bundle -undefined suppress -flat_namespace -g -o c_location.bundle c_location.o -L. -L/Users/User/.rvm/rubies/ruby-1.8.7-p357/lib -L. -lruby -ldl -lobjc
The original c_location.o file does contain the necessary information for objdump --dwarf=decodedline to work.
So it turns out that one way to do this is to use Apple's nm -pa *.bundle to find the symbol name and the original object file for a given offset.
Once you have that, you can first use objdump -tT to find the offset of the symbol name in the original object file; and then use objdump --dwarf=decodedline as before.
Each step requires a little bit of simplistic output parsing, but it does seem to work™. I'd be interested if there are more robust approaches.

Resources