You are on page 1of 33

Dyzan ’08

To facilitate easy
understanding of
coding in GCC
(GNU Compiler
Collection)
Anirban Kundu
Gourab Dolui
Kushal Sarkar
Introduction

What exactly is GCC?


The tautological answer is that GCC is an acronym for the GNU Compiler
Collection. As remarked earlier, GCC is a collection of compiler front ends to
a common back-end compilation engine. The list of compilers includes C, C+
+, Objective C, Fortran (now 95, formerly 77),and Java. It is free software
distributed by the Free Software Foundation (FSF) under the GNU GPL and
GNU LGPL.
Today there is indeed a fully functional UNIX-like operating system,
named Linux, abroad in the world and is being used with great success by
countless companies, governments, and individuals. And this system, with all
its utilities and applications, is based on the GNU Compiler Collection.

Page  2
Dyzan ’08
Compiling a single source file

Compiling a single source file, myprog.c, using gcc is easy—just invoke gcc,
passing the name of the source file as the argument.
$ gcc myprog.c
$ ls –l
-rwxr-xr-x 1 wvh users 13644 Aug 5 16:17 a.out
-rw-r--r-- 1 wvh users 220 Aug5 16:17 myprog.

To define the name of the output file that gcc produces, use the -o option, as
illustrated in the following example:
$ gcc myprog.c -o output_filename

Page  3
Dyzan ’08
Compiling a single source file

$ ls -l
-rw-r--r-- 1 wvh users 220 Oct 5 16:17 myprog.c
-rwxr-xr-x 1 wvh users 13644 Oct 5 16:28 output_filename
If you are compiling multiple source files using gcc, you can simply specify
them all on the gcc command line, as in the following example, which leaves
the compiled and linked executable in the
file named showdate:
$ gcc showdate.c helper.c –o output_filename
To execute a file write
$./a.out
If we change the name of the output file then in oder to execute we write
$./output_filename
Page  4
Dyzan ’08
GCC Command-Line Option

Each command-line option begins with either a hyphen or a pair of hyphens. For
example, the following command line will compile the ANSI standard C program
named muxit.c and produce an unlinked object file named muxit.o.
$gcc -ansi -c muxit.c -o muxit.o

Despite its sensitivity to the grouping of multiple single-letter options, you are
generally free to mix the order of options and compiler arguments on the gcc
command line. That is, invoking gcc as
$gcc -pg -fno-strength-reduce -g myprog.c -o myprog
has the same result as
$gcc myprog.c -o myprog -g -fno-strength-reduce -pg

Page  5
Dyzan ’08
Some Important Command-Line Option
 -c
Do not invoke the linker. This option will allow compiling and assembling of
source files into object files, but the linker will not be run to create an executable.
The object files produced will be stored in a file of the same name as the source file
with a .o suffix.
Example :
$ gcc -c showdate.c
$ ls –l
-rw-r--r-- 1 wvh users 208 Oct 5 12:44 showdate.c
-rw-r--r-- 1 wvh users 1008 Oct 5 13:50 showdate.o
 -v
Displays the current version number of the compiler and displays all of the
commands used to run each phase of the compile and link process.

Page  6
Dyzan ’08
Some Important Command-Line Option

When used alone, this optionwill display the current version number of the compiler .When used in
combination with the --help option, a complete list of the command line options is displayed.
 --help
Print (on the standard output) a description of the command line options understood by gcc.

 @file
Read command-line options from file. The options read are inserted in place of the original
@file option. If file does not exist, or cannot be read, then the option will be treated literally, and
not removed. Options in file are separated by whitespace.

Page  7
Dyzan ’08
Some Important Command-Line Option
 -s
Stop after the stage of compilation proper; do not assemble. The output is in
the form of an assembler code file for each non-assembler input file specified. By
default, the assembler file name for a source file is made by replacing the suffix
‘.c’, ‘.i’, etc., with ‘.s’. Input files that don’t require compilation are ignored.
 -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 will probably make other debuggers crash or
refuse to read the program

Page  8
Dyzan ’08
Options for Getting Warning Messages in
GCC
 -Wformat option causes gcc to check all calls to printf(), scanf(), and other
functions that rely on format strings, making sure that the arguments supplied
have types appropriate to the format string and that the requested conversions, as
specified in the format string, are sensible.
 -Werror option to convert the warning to a hard error that terminates
compilation.
 -Wunused option, which catches all unused objects.
Each of the warning options discussed in this section results in similar output that
identifies the translation unit and line number in which a problem is detected, and
a brief message describing the problem.
Example of –Wformat
Consider the program that uses printf() to print some text to the screen.

Page  9
Dyzan ’08
Options for Getting Warning Messages in
GCC
Source Code for the Sample printme.c Application
#include <stdio.h>
#include <limits.h>
int main (void)
{
unsigned long ul = LONG_MAX;
short int si = SHRT_MIN;
printf ("%d\n", ul);
printf ("%s\n", si);
return 0;
}
There are a couple of problems here. The first printf() statement prints the value of the
unsigned long variable ul using an int format string (%d). The second printf() statement
prints the short int variable si using the %s format string (that is, as a string).
Despite these problems, gcc compiles the program without complaint. It even sort of
runs.
Page  10
Dyzan ’08
Options for Getting Warning Messages in
GCC
$ gcc printme.c -o printme
$ ./printme
2147483647
Segmentation fault

On my test system, the program even crashed because the %s formatting


option tried to use the short int si as a pointer to the beginning of a
character string, which it is not. Add the -Wformat option and lets
see what happens:
$ gcc printme.c -o printme -Wformat
printme.c: In function 'main':
printme.c:9: warning: int format, long int arg (arg 2)
printme.c:10: warning: format argument is not a pointer (arg 2)
$ ./printme
2147483647
Segmentation fault
Page  11
Dyzan ’08
Options for Getting Warning Messages in
GCC
Example of -Wunused
Source Code for the Sample unused.c Application
int main (void)
{ int i = 10;
return 0; }

As you can see, the program defines the int variable i, but never does anything with it. Here
is GCC’s output when compiling unused.c with no options:
$ gcc unused.c
Here is GCC’s complaint when we use -Wunused:
$ gcc -Wunused unused.c
unused.c: In function 'main':
unused.c:3: warning: unused variable 'i'

Page  12
Dyzan ’08
Debugging Your Program

Debugging is a phenomenon which is associated with every program


which we write. There are many ways to go about debugging, from printing out
messages to the screen, using a debugger, or just thinking about what the
program is doing and making an intelligent guess as to what the problem is.
Before a bug can be fixed, the source of the bug must be located.
For example, with segmentation faults, it is useful to know on which
line of code the seg’ fault is occuring. Once the line of code in question has been
found, it is useful to know about the values in that method, who called the
method, and why (specifically) the error is occuring. Using a debugger makes
finding all of this information very simple.
Loading a program
So you now have an executable file (in this case main)
and you want to debug it. First you must launch the debugger. The debugger is
called gdb and you can tell it which file to debug at the shell prompt.
Page  13
Dyzan ’08
Debugging Your Program
Source Code for the Sample main.c Application
#include <stdio.h>
void print_scrambled(char *message)
{
int i = 3;
do {
printf("%c", (*message)+i);
} while (*++message);
printf("\n");
}
int main()
{
char * bad_message = NULL;
char * good_message = "Hello, world.";
print_scrambled(good_message);
print_scrambled(bad_message);
}
Page  14
Dyzan ’08
Debugging Your Program

Complie this main.c


$ gcc -g main.c -o main
Because of a bug in the program, running it will result in a segmentation fault:
$ ./main
Segmentation fault

This is one of the areas where gdb comes in handy. By running the program
under gdb, we can find out the exact line that the program is crashing on.

Page  15
Dyzan ’08
Debugging Your Program

So to debug main we want to type gdb main.


Here is what it looks like when I run it:
$ gdb main
GNU gdb 4.18
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to
change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was
configured as "sparc-sun-solaris2.7"...
(gdb)

gdb is now waitng for the user to type a command. We need to run the
program so that the debugger can help us see what happens when the program
crashes. Type run at the (gdb) prompt. Here is what happens when I run this
command:
Page  16
Dyzan ’08
Debugging Your Program

(gdb) run
Starting program: /home/newren/examples/main
Program received signal SIGSEGV, Segmentation fault.
0x0804835b in print_scrambled (message=0x0) at main.c:8
1 printf("%c", (*message)+i);

The program crashed so lets see what kind of information we can gather.
Inspecting crashes
So already we can see the that the program was at line 8 of main.cc, that
this points to 0, and we can see the line of code that was executed. But we also
want to know who called this method and we would like to be able to examine
values in the calling methods. So at the gdb prompt, we type backtrace which
gives me the following output:

Page  17
Dyzan ’08
Debugging Your Program
(gdb) backtrace
#0 0x0804835b in print_scrambled (message=0x0) at main.c:8
#1 0x080483c3 in main () at main.c:20

Reading backtraces is fairly straightforward. The data associated with each function
call in the list is known as a frame. The outermost frame is the initial function
that your program started in, and is printed at the bottom of the list. Each frame is
given a number (0, 1, 2, etc.). Following the frame number is an associated
memory address, which is almost entirely useless and which you can ignore.
Then each frame contains the name of the function that was called, its
arguments, the name of the file where the function appears, and line number.
So, the stack trace for our program says that at line 20 of gdb-example.c in
function main, the print_scrambled function was called--and that the program got
to line eight of gdb-example.c inside the print_scrambled function.

Page  18
Dyzan ’08
Debugging Your Program

If you find the problem then to exit from gdb type.


(gdb) quit
The program is running. Exit anyway? (y or n) y 107
newren@Miney:debugging/gdb$
Getting more information
list show next ten lines of source
list - show previous ten lines
list lines display source surrounding lines, specified
as:
[file:]num line number [in named file]
[fille:]function beginning of function [in named file]
+off off lines after last printed
-off off lines previous to last printed
*address line containing address

Page  19
Dyzan ’08
Debugging Your Program

Example :
(gdb) run
Starting program: /home/newren/examples/main
Program received signal SIGSEGV, Segmentation fault.
0x0804835b in print_scrambled (message=0x0) at mainc:8
8 printf("%c", (*message)+i);

(gdb) list
3 void
4 print_scrambled(char *message)
5 {
6 int i = 3;
7 do {
8 printf("%c", (*message)+i);
9 } while (*++message);
10 printf("\n");
11 }
12

Page  20
Dyzan ’08
Debugging Your Program

up n select frame n frames up


down n select frame n frames down
info args arguments of selected frame
info locals local variables of selected frame
Example :
(gdb) run
Starting program: /home/newren/examples/main
Program received signal SIGSEGV, Segmentation fault.
0x0804835b in print_scrambled (message=0x0) at main.c:8
8 printf("%c", (*message)+i);
(gdb) info locals
i=3

Page  21
Dyzan ’08
Debugging Your Program
(gdb) info args
message = 0x0
(gdb) up
#1 0x080483c3 in main () at gdb-example.c:20
20 print_scrambled(bad_message);

(gdb) list
15 {
16 char * bad_message = NULL;
17 char * good_message = "Hello, world.";
18
19 print_scrambled(good_message);
20 print_scrambled(bad_message);
21 }

(gdb) info locals


bad_message = 0x0
good_message = 0x80484a1 "Hello, world.“

(gdb) info args


No arguments.

Page  22
Dyzan ’08
Debugging Your Program
print [/f ] [expr] / p [/f ] [expr] : show value of expr [or last value $]
according to format f:
x hexadecimal
d signed decimal
u unsigned decimal
o octalt binary
c character
f foating point
continue [count] : continue running; if count specified,
step [count] : execute until another line reached; repeat count times if specified
next [count] : execute next line, including any function calls
return [expr] : pop selected stack frame without executing [setting return value]
jump line : resume execution at specified line number
jump *address : or address

Page  23
Dyzan ’08
Debugging Your Program
Example :
(gdb) run
Starting program: /home/newren/examples/gdb-example
Breakpoint 1, main () at gdb-example.c:16
16 char * bad_message = NULL;
(gdb) print bad_message
$1 = 0x8048410 "U\211%G%@VS"
(gdb) next
17 char * good_message = "Hello, world.";
(gdb) print bad_message
$2 = 0x0
(gdb) next
19 print_scrambled(good_message);

Page  24
Dyzan ’08
Debugging Your Program
(gdb) next
20 print_scrambled(bad_message);
(gdb) step
print_scrambled (message=0x0) at gdb-example.c:6
6 int i = 3;
(gdb) step
8 printf("%c", (*message)+i);
(gdb) step
Program received signal SIGSEGV, Segmentation fault.
0x0804835b in print_scrambled (message=0x0) at gdb-example.c:8
8 printf("%c", (*message)+i);
(gdb) print (*message)+i
Cannot access memory at address 0x0

Page  25
Dyzan ’08
Debugging Your Program

To do anything really useful with gdb, you need to set breakpoints which
temporarily pause your program's execution so you can do useful debugging
work like inspecting variables and watching the program's execution in an
atomic line-by-line fashion. This right here is the magic of a symbolic
debugger.
Breakpoints come in three flavors:
‫ ٭‬A breakpoint stops your program whenever a particular point in the program
is reached.
‫ ٭‬A watchpoint stops your program whenever the value of a variable or
expression changes..
‫ ٭‬A catchpoint stops your program whenever a particular event occurs.

Page  26
Dyzan ’08
Debugging Your Program

We'll first concentrate on learning how to set breakpoints, and then we'll debug the
program.

Setting Basic Breakpoints


There are four major ways to set a breakpoint, in roughly the order that we use
them.:
– By function name.
– By line number.
– By filename and line number.
– By address.

Page  27
Dyzan ’08
Debugging Your Program

 By Function Name
The "break main" command sets a breakpoint at the top of main(), which
happens to be line 8 of main.c.
(gdb) break main
Breakpoint 1 at 0x8048464: file main.c, line 8.
 By Line Number
(gdb) break 9
Breakpoint 2 at 0x804846b: file main.c, line 9
 By Filename And Line Number
(gdb) break main.c:10
Breakpoint 3 at 0x80483fd: file main.c, line 10.

Page  28
Dyzan ’08
Debugging Your Program

Removing Breakpoints
Just as you can set breakpoints, you can also remove them. There are numerous
ways to remove a breakpoint:
 If you want to remove the breakpoint by its location, use clear.
 If you want to remove the breakpoint by its identifier, use delete.
(gdb) clear fgets.c:10
Deleted breakpoint 3
(gdb) clear 9
Deleted breakpoint 2
(gdb) clear main
Deleted breakpoint 1
The delete command deletes breakpoints by identifier, as opposed
to clear which removes breakpoints based on their location. In
fact, delete n deletes the breakpoint with identifier n.
Page  29
Dyzan ’08
Debugging Your Program

 Listing Breakpoints
But how do you remember the identifiers for your breakpoints, or even where your
breakpoints were set to begin with? There's a command, info breakpoints which lists all
your breakpoints, their identifiers, and lots more information.
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x08048464 in main at main.c:6
breakpoint already hit 1 time
2 breakpoint keep y 0x0804846b in main at main.c:9
breakpoint already hit 1 time
3 breakpoint keep y 0x08048477 in main at main.c:12

Page  30
Dyzan ’08
Debugging Your Program
Setting watchpoints
• watch EXPR
Set a watchpoint for an expression. GDB will break when EXPR is
written into by the program and its value changes.
Eg : watch (*message)+i

• rwatch EXPR
Set a watchpoint that will break when the value of EXPR is read by
the program.

• awatch EXPR
Set a watchpoint that will break when EXPR is either read from or
written into by the program.

• info watchpoints
This command prints a list of watchpoints, breakpoints, and
catchpoints; it is the same as `info break'

Page  31
Dyzan ’08
Some Important Tips about GCC

» Header Files alloc.h, conio.h are not available in GCC. So functions as


clrscr(), getch() cannot be used while writing a code.
» The memory allocation function are available in stdlib.h
» Use main() ,and not void main() as a main function in GCC should
always return a value.

Page  32
Dyzan ’08
Thank you

Dyzan ’08

You might also like