Labels

Sunday 17 December 2017

GDB tutorial. What is gdb and how to run commands in gdb?

GDB Tutorial

GDB, short for GNU Debugger, is the most popular debugger for UNIX systems to debug C and C++ programs.

A debugger is a program that runs other programs, allowing the user to exercise control over these programs, and to examine variables when problems arise.
GNU Debugger, which is also called gdb, is the most popular debugger for UNIX systems to debug C and C++ programs.
GNU Debugger helps you in getting information about the following:
  • If a core dump happened, then what statement or expression did the program crash on?
  • If an error occurs while executing a function, what line of the program contains the call to that function, and what are the parameters?
  • What are the values of program variables at a particular point during execution of the program?
  • What is the result of a particular expression in a program?

How GDB Debugs?

GDB allows you to run the program up to a certain point, then stop and print out the values of certain variables at that point, or step through the program one line at a time and print out the values of each variable after executing each line.
GDB uses a simple command line interface.

Points to Note

Even though GDB can help you in finding out memory leakage related bugs, but it is not a tool to detect memory leakages.

GDB cannot be used for programs that compile with errors and it does not help in fixing those errors.

GDB Commands:

GDB offers a big list of commands, however the following commands are the ones used most frequently:
  • b main - Puts a breakpoint at the beginning of the program
  • b - Puts a breakpoint at the current line
  • b N - Puts a breakpoint at line N
  • b +N - Puts a breakpoint N lines down from the current line
  • b fn - Puts a breakpoint at the beginning of function "fn"
  • d N - Deletes breakpoint number N
  • info break - list breakpoints
  • r - Runs the program until a breakpoint or error
  • c - Continues running the program until the next breakpoint or error
  • f - Runs until the current function is finished
  • s - Runs the next line of the program
  • s N - Runs the next N lines of the program
  • n - Like s, but it does not step into functions
  • u N - Runs until you get N lines in front of the current line
  • p var - Prints the current value of the variable "var"
  • bt - Prints a stack trace
  • u - Goes up a level in the stack
  • d - Goes down a level in the stack
  • q - Quits gdb

Getting Started: Starting and Stopping

  • gcc -g myprogram.c
    • Compiles myprogram.c with the debugging option (-g). You still get an a.out, but it contains debugging information that lets you use variables and function names inside GDB, rather than raw memory locations (not fun).
  • gdb a.out
    • Opens GDB with file a.out, but does not run the program. You’ll see a prompt (gdb) - all examples are from this prompt.
  • r
  • r arg1 arg2
  • r < file1
    • Three ways to run “a.out”, loaded previously. You can run it directly (r), pass arguments (r arg1 arg2), or feed in a file. You will usually set breakpoints before running.
  • help
  • h breakpoints
    • Lists help topics (help) or gets help on a specific topic (h breakpoints). GDB is well-documented.
  • q - Quit GDB

Stepping through Code

Stepping lets you trace the path of your program, and zero in on the code that is crashing or returning invalid input.
  • l
  • l 50
  • l myfunction
    • Lists 10 lines of source code for current line (l), a specific line (l 50), or for a function (l myfunction).
  • next
    • Runs the program until next line, then pauses. If the current line is a function, it executes the entire function, then pauses. next is good for walking through your code quickly.
  • step
    • Runs the next instruction, not line. If the current instruction is setting a variable, it is the same as next. If it’s a function, it will jump into the function, execute the first statement, then pause. step is good for diving into the details of your code.
  • finish
    • Finishes executing the current function, then pause (also called step out). Useful if you accidentally stepped into a function.

Breakpoints or Watchpoints

Breakpoints play an important role in debugging. They pause (break) a program when it reaches a certain point. You can examine and change variables and resume execution. This is helpful when some input failure occurs, or inputs are to be tested.
  • break 45
  • break myfunction
    • Sets a breakpoint at line 45, or at myfunction. The program will pause when it reaches the breakpoint.
  • watch x == 3
    • Sets a watchpoint, which pauses the program when a condition changes (when x == 3 changes). Watchpoints are great for certain inputs (myPtr != NULL) without having to break on every function call.
  • continue
    • Resumes execution after being paused by a breakpoint/watchpoint. The program will continue until it hits the next breakpoint/watchpoint.
  • delete N
    • Deletes breakpoint N (breakpoints are numbered when created).

Setting Variables

Viewing and changing variables at runtime is a critical part of debugging. Try providing invalid inputs to functions or running other test cases to find the root cause of problems. Typically, you will view/set variables when the program is paused.
  • print x
    • Prints current value of variable x. Being able to use the original variable names is why the (-g) flag is needed; programs compiled regularly have this information removed.
  • set x = 3
  • set x = y
    • Sets x to a set value (3) or to another variable (y)
  • call myfunction()
  • call myotherfunction(x)
  • call strlen(mystring)
    • Calls user-defined or system functions. This is extremely useful, but beware of calling buggy functions.
  • display x
    • Constantly displays the value of variable x, which is shown after every step or pause. Useful if you are constantly checking for a certain value.
  • undisplay x
    • Removes the constant display of a variable displayed by display command.

Backtrace and Changing Frames

A stack is a list of the current function calls - it shows you where you are in the program. A frame stores the details of a single function call, such as the arguments.
  • bt
    • Backtraces or prints the current function stack to show where you are in the current program. If main calls function a(), which calls b(), which calls c(), the backtrace is
  • c <= current location 
    b 
    a 
    main 
    
  • up
  • down
    • Move to the next frame up or down in the function stack. If you are in c, you can move to b or a to examine local variables.
  • return
    • Returns from current function.

Handling Signals

Signals are messages thrown after certain events, such as a timer or error. GDB may pause when it encounters a signal; you may wish to ignore them instead.
  • handle [signalname] [action]
  • handle SIGUSR1 nostop
  • handle SIGUSR1 noprint
  • handle SIGUSR1 ignore
    • Instruct GDB to ignore a certain signal (SIGUSR1) when it occurs. There are varying levels of ignoring.

To debug a program 'my_program' that has crashed and produced a core file named 'core', type the following at the command line:
gdb my_program core 
As this is mostly equivalent to starting gdb and typing the 'r' command, all of the commands above could now be used to debug the file.

The text user interface

GDB TUI
GDB features a text user interface for code, disassembler and registers. For instance:
  • Ctrl-x 1 will show the code pane
  • Ctrl-x a will hide the TUI panes
None of the GUI interfaces to gdb (Qt Creator stands out for being intuitive and easy to use) can offer access to all of the gdb functionality.

References:

https://en.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques



Sunday 30 July 2017

How to print numbers from 1 to 100 without using loop?

How to print numbers from 1 to 100 without using loop?

With the help of recursion we can achieve the output. Please find below code snippet.

#include <stdio.h>

/* Prints numbers from 1 to n */
void printNos(unsigned int n)
{
    (n > 0 && (printNos(n-1), printf("%d ", n)));
    return;
}

/* program to test printNos */
int main()
{
    printNos(100);
    getchar();
    return 0;
}
 From the above code snippet, one thing need to understand is "Usage of comma operator".

(n > 0 && (printNos(n-1), printf("%d ", n)));

As per the precedence & associativity the above statement gets evaluated from left to right. and the order follows as below

1. checks whether n is greater than 0 or not? i.e., n > 0
2. As the input (1st) for logical AND operator is true and checks for the second input. That's why it is acting as a "if" block.
3. When it comes to second input for && operator, its a set of statements enclosed by parenthesis ( '(' and ')' ). 
Note: Comma ( ,) has the lest precedence, so all statements will call/run inside the parenthesis and the right most value will be used as a final set value.


To understand this please see the below example.

int a = (3, 5); // a gets value as 5. not 3

why because = has high precedence and evaluates from right to left (as per associativity). Right part is parenthesis and has two values separated by comma (,) and comma evaluates from left to right. and the right most value will gets returned to from the set to the variable a.

Saturday 29 July 2017

How to find addition of two numbers without using any arithmatic operator?


To find sum of two numbers without using any arithmetic operator


Write a C program to find sum of positive integers without using any operator. Only use of printf() is allowed. No other library function can be used.
--> We can use printf() to find sum of two numbers as printf() returns the number of characters printed. The width field in printf() can be used to find the sum of two numbers. We can use ‘*’ which indicates the minimum width of output. For example, in the statement “printf(“%*d”, width, num);”, the specified ‘width’ is substituted in place of *, and ‘num’ is printed within the minimum width specified. --> If number of digits in ‘num’ is smaller than the specified ‘wodth’, the output is padded with blank spaces. If number of digits are more, the output is printed as it is (not truncated).
int add (int z, int x)
    return printf ("%*d%*d", z, 1, x, 2);
}
int main (void)
{
    printf ("\nsum=%d\n", add(4,4));
}
Output:
   1   2
sum=8
The output is: number "1" is represented in width (in 4 digit place, as <space><space><space><1>) and the number "2" is also followed the same. Totally first add() printed z+x characters on the console using printf and printf returns number of characters printed on the console. So we will get the addition result as a return value for add().

Saturday 8 July 2017

How to run a c program without using main() function in it?

How to write a C program without "main()" function?

Logically it’s seems impossible to write a C program without using a main() function. Since every program must have a main() function because:-
  • It’s an entry point of every C/C++ program
  • All Predefined and User-defined Functions are called directly or indirectly through the main
This can be achieved by using two methods and are as follows
  • Indirect Method
  • Direct Method

Indirect Method:

 In this indirect method, we will use the main function indirectly and that is with the help of macro's. Please take a look at the code snippet given below

Example1:
#include <stdio.h>
#define fun main
int fun(void)
{
    printf("This is My Main Function");
    return 0;
}
 From the above code, fun is the function which i am using instead of main and fun is a macro which equivalent is "main". While compiling the above program, fun gets replaced by main at the time of preprocessing stage. After preprocessing stage code almost looks same like we used main.

Example 2:
#include <stdio.h>
#define fun m##a##i##n
int fun(void)
{
    printf("This is My Main Function");
    return 0;
}
The example 2 is almost same as example 1. The only difference is that, example 2 uses tokens in macro, which will concatenate the m,a,i,n and forms a string called "main".

Direct Method:

In this method, we will directly use custom main function and there is no main concept at all.
Always compiler uses _start as the starting point for any program. The _start function always looks for an entry point from the user program and that entry point is fixed and named as "main". So whenever we use start files (_start) which always looks for main and that's why main is necessary.

In order to avoid the main function from our program, we shouldn't use the start files (_start). While compiling our program we should tell to the compiler that, "No need to use start files". We can intimate to the compiler that not to use start files by using compiler arguments and is given below.
gcc test.c -nostartfiles -o test_bin
Example 3:
#include <stdio.h>
int fun(void)
{
    printf("This is My Function");
    exit(0); //return statement shouldn't use, cause segmentation fault
}
 If you compile the above program (example 3) with "-nostartfiles" option, then binary will gets created. 
From the above program (example 3) we should note few important things and are listed below.
1. We shouldn't use return statement, why because as we haven't used _start, So no one will be ready to collect our return status. If we try to use return statement, which will leads to segmentation fault.
2. exit(0) statement tells the loader to unload the program from the memory. Why because loader is the one who loads our program into memory.

What if multiple functions definitions present?

If multiple functions (definitions) present in the file, then the compiler will choose one entry point for the program. And the compiler always choose first function which defined in the program.

Example 4:
#include <stdio.h>
int fun(void)
{
    printf("This is My fun Function");
    exit(0); //return statement shouldn't use, cause segmentation fault
}
int print(void)
{
      printf("This is My print Function");
    exit(0); //return statement shouldn't use, cause segmentation fault
}
 If we compile and run the above program (example 4), then we will get output as "This is My fun Function".

If we want to select our function as entry point, then we should intimate to the compiler while compiling program by using option.
From the example if i want to use print as my entry point, then i should compile by specifying entry point option.
gcc test.c -nostartfiles -e print -o test_bin
 "-e" option tells the compiler as an entry point.

Case Study:

We can use customized entry point option even when the main present. See the code below. 

Example 5:
#include <stdio.h>
int main(void)
{
    printf("This is My main Function");
    exit(0); //return statement also works
}
int print(void)
{
      printf("This is My print Function");
    exit(0); //return statement shouldn't use, cause segmentation fault
}
From the above example we can compile and run the program by using entry point option.
gcc test.c -e print -o test_bin
If we runt the test_bin binary, then the output will be "This is My print Function".

***************************** Thanks for Reading ***************************