Interesting question, and it's a bit hard to find information if your starting point is the gcc man page :-) so here goes.
Basically the -g
flag writes extra "debugging" information right into the generated object files (.o) and executable file. This extra information can then be used by a debugger (say gdb) to help make sense of what's going on for the person doing the debugging.
So for example if you have a variable name that will be kept around as extra information so that when you use a debugger you can refer to the variable that you used in your source code rather than some random memory address because symbol debug information wasn't there.
The debugging options are somewhat explained in the gcc manual here
However I think you need a debugging intro. So have a look at the GDB introduction by UWA
to get a better understanding of what's going on.
The same goes for profiling data. -p
adds extra information in the executable so that a profiler like prof
can trace the software as its running and tell you where it spends most of its time (what loops/functions etc) and how (in)efficient a program is. :-)
related things to read up on
There is a difference between symbol information in a file and debugging information. Once you start looking at linking you'll run into symbol resolution.