Go4Expert

Go4Expert (http://www.go4expert.com/)
-   Linux (http://www.go4expert.com/articles/linux/)
-   -   ltrace - Linux Debugging Utility Tutorial (http://www.go4expert.com/articles/ltrace-linux-debugging-utility-tutorial-t29095/)

Trinity 16Sep2012 13:04

ltrace - Linux Debugging Utility Tutorial
 
'ltrace' is another Linux Utility similar to 'strace'. However, ltrace lists all the library calls being called in an executable or a running process. Its name itself comes from library-call tracing. This tool is very useful for debugging user-space applications to determine which library call is failing. It is also capable of receiving signals for segmentation faults, etc.

Using ltrace



One does NOT need any root privileges to run ltrace.

Using ltrace to debug an application executable
Code:

ltrace ./executable <parameters>
Using ltrace to debug a running process
Code:

ltrace -p <PID>
Here is an example usage of ltrace along with its output for a rare command 'time'
Code:

rupali@ubuntu:~/source$ ltrace time
__libc_start_main(0x8048a50, 1, 0xbfc806e4, 0x8049890, 0x8049880 <unfinished ...>
getenv("TIME")                                                                                          = NULL
getopt_long(1, 0xbfc806e4, "+af:o:pqvV", 0x0804c0a0, NULL)                                              = -1
__fprintf_chk(0x7b6980, 1, 0x8049948, 0xbfc81dce, 0Usage: time [-apvV] [-f format] [-o file] [--append] [--verbose]
      [--portability] [--format=format] [--output=file] [--version]
      [--quiet] [--help] command [arg...]
)                                                    = 177
exit(1 <unfinished ...>
+++ exited (status 1) +++

Notice the familiar library calls along with their parameters and return values in the output.

Refer ltrace man page for details to run ltrace with various other options offered. Man page can be found by typing
Code:

man ltrace
or through this link.

Debugging with ltrace



The ltrace utility is most useful for debugging user-space application programs as the bugs could be surfaced out seeing the dynamic records of the library calls. Here, let us take an scenario where we'll see what kind of errors we see and how we debug while using ltrace.

Lets take a sample program.
This program has a bug, and I suggest you not to even try to find the bug in this program on your own. Let ltrace help us to find the bug, as that is what we are here to learn. :)
Code:

1.  #include <stdio.h>
2.  #include <unistd.h>
3.
4.  int main()
5.  {
6.    FILE *fp = fopen("rfile.txt", "w+");
7.    fprintf(fp+1, "Invalid Write\n");
8.    fclose(fp);
9.    return 0;
10. }

Lets compile and run it.
Code:

rupali@ubuntu:~/source$ gcc file.c -Wall -o file
rupali@ubuntu:~/source$./file
Segmentation fault (core dumped)

Oh, that is a segmentation fault. Lets use ltrace to debug and see what is happening.
Code:

rupali@ubuntu:~/source$ltrace ./file
 __libc_start_main(0x8048454, 1, 0xbfc19db4, 0x80484c0, 0x8048530 <unfinished ...>
 fopen("rfile.txt", "w+")                          = 0x9160008
 fwrite("Invalid Write\n", 1, 14, 0x916009c <unfinished ...>
 --- SIGSEGV (Segmentation fault) ---
 +++ killed by SIGSEGV +++

The first line states the libc function call 'main()', with its parameters and it terminated unfinished. Since we saw the segmentation fault, so unfinished main() aligns with our understanding.

Next line has listed the fopen() call to open 'rfile.txt' in write plus mode and returning a valid file pointer address.
Moving on to the next library call, we have fwrite which is unfinished. Here is the bug because of which program crashed. So focusing on this call and analyzing, notice the file pointer containing the address in fwrite() call doesnt match the one in fopen() call. Hence, the crash. The program is trying to write onto a file using file pointer which is invalid following a SIGSEGV signal.
Getting back to our program, the bug is in line 7 of our program where the file pointer being passed to the fprintf() call is tampered. So, we just found the bug.

Here is the corrected code
Code:

1.  #include <stdio.h>
2.  #include <unistd.h>
3.
4.  int main()
5.  {
6.    FILE *fp = fopen("rfile.txt", "w+");
7.    fprintf(fp, "Invalid Write\n");
8.    fclose(fp);
9.    return 0;
10. }

In the example, we had taken a simple straight-forward program. Imagine, if it was a complicated huge program for some considerable data, ltrace output would had been much efficient to debug than re-checking each line of source or adding various printf's.

Conclusion



Now we know how to use ltrace for debugging applications. For more better intricate functionalities like breakpoints, stepping through, etc use GDB. However, most of the bugs can be resolved using ltrace/strace by knowing and analysing the calls and their success and failure errors.


All times are GMT +5.5. The time now is 23:59.