{"id":1572,"date":"2012-02-04T09:59:26","date_gmt":"2012-02-04T08:59:26","guid":{"rendered":"http:\/\/www.blaess.fr\/christophe\/?p=1572"},"modified":"2012-02-04T09:59:26","modified_gmt":"2012-02-04T08:59:26","slug":"development-of-a-dynamic-library-23","status":"publish","type":"post","link":"https:\/\/www.blaess.fr\/christophe\/2012\/02\/04\/development-of-a-dynamic-library-23\/","title":{"rendered":"Development of a dynamic library (2\/3)"},"content":{"rendered":"<p style=\"text-align: justify;\">(<a title=\"Mise au point de biblioth\u00e8que dynamique (2\/3)\" href=\"http:\/\/www.blaess.fr\/christophe\/2012\/02\/04\/mise-au-point-de-bibliotheque-dynamique-23\/\">Version originale en fran\u00e7ais<\/a>)<\/p>\n<p style=\"text-align: justify;\">In <a title=\"Development of a dynamic library (1\/3)\" href=\"http:\/\/www.blaess.fr\/christophe\/2012\/01\/28\/development-of-a-dynamic-library-13\/\" target=\"_blank\">the previous article<\/a> we saw how to build a dynamic library and properly manage its major and minor version numbers for easy maintenance, both for the developer (of the library but also of the applications that use it) and for the administrator of the system where it is installed. We will now consider how to debug our library and applications that call it.<\/p>\n<p>\n<!--more-->\n<\/p>\n<h1>Calls tracking<\/h1>\n<p style=\"text-align: justify;\">The first tool to know is <code>ltrace<\/code>. It sends to the error output of the process a log of all function calls to dynamic libraries. We put ourselves back in the same situation as for the previous article with the following directories:<\/p>\n<ul>\n<li style=\"text-align: justify;\"><code>factorial\/src<\/code> contains the source code of the library<\/li>\n<li style=\"text-align: justify;\"><code>factorial\/include<\/code> where the header files of the library are<\/li>\n<li style=\"text-align: justify;\"><code>factorial\/lib<\/code> containing the compiled files of the library<\/li>\n<li style=\"text-align: justify;\"><code>factorial\/test<\/code> where we find source codes and executable files of the applications using the library<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Here is an overview of the content of our directory:<\/p>\n<pre>[~] <strong>cd factorial<\/strong>\n[factorial]$ <strong>ls<\/strong>\ninclude  lib  src  test\n[factorial]$ <strong>ls include\/<\/strong>\n<a title=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/en\/fact.h\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/en\/fact.h\" target=\"_blank\">fact.h<\/a>\n[factorial]$ <strong>ls -l lib\/<\/strong>\ntotal 8\nlrwxrwxrwx 1 cpb cpb   12 2012-02-04 05:04 libfact.so -&gt; libfact.so.2\nlrwxrwxrwx 1 cpb cpb   14 2012-02-04 05:04 libfact.so.2 -&gt; libfact.so.2.0\n-rwxrwxr-x 1 cpb cpb 6661 2012-02-04 05:04 libfact.so.2.0\n[factorial]$ <strong>ls src\/<\/strong>\n<a title=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/en\/fact.c\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/en\/fact.c\" target=\"_blank\">fact.c<\/a>  fact.o\n[factorial]$ <strong>ls test\/<\/strong>\nfactorial  <a title=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/en\/factorial.c\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/en\/factorial.c\" target=\"_blank\">factorial.c<\/a>\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">Details to create executable files and symbolic links were in <a title=\"Development of a dynamic library (1\/3)\" href=\"http:\/\/www.blaess.fr\/christophe\/2012\/01\/28\/development-of-a-dynamic-library-13\/\" target=\"_blank\">the previous article<\/a>. Here is an example of the test program.<\/p>\n<pre>[factorial]$ <strong>export LD_LIBRARY_PATH=lib\/<\/strong>\n[factorial]$ <strong>.\/test\/factorial 7<\/strong>\n7! = 5040\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">Let&rsquo;s use <code>ltrace<\/code> to see library function calls.<\/p>\n<pre>[factorial]$ <strong>ltrace .\/test\/factorial 4 5 6<\/strong>\n__libc_start_main(0x80485b4, 4, 0xbf896624, 0x80486b0, 0x8048720\n__isoc99_sscanf(0xbf89745f, 0x8048796, 0xbf896578, 0x80486d1, 0x8048500) = 1\nfactorial(4, 0xbf896570, 0xbf896578, 0x80486d1, 0x8048500) = 0\nfprintf(0xb7896500, \"%ld! = %lldn\", 4, ...4! = 24\n)     = 8\n__isoc99_sscanf(0xbf897461, 0x8048796, 0xbf896578, 24, 0) = 1\nfactorial(5, 0xbf896570, 0xbf896578, 24, 0)    = 0\nfprintf(0xb7896500, \"%ld! = %lldn\", 5, ...5! = 120\n)     = 9\n__isoc99_sscanf(0xbf897463, 0x8048796, 0xbf896578, 120, 0) = 1\nfactorial(6, 0xbf896570, 0xbf896578, 120, 0)   = 0\nfprintf(0xb7896500, \"%ld! = %lldn\", 6, ...6! = 720\n)     = 9\n+++ exited (status 0) +++\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">First of all there is a mix between the standard output display and the error output content, making the reports difficult to read. We will send error output to a file:<\/p>\n<pre>[factorial]$ <strong>ltrace .\/test\/factorial 4 5 6 2&gt;traces.txt<\/strong>\n4! = 24\n5! = 120\n6! = 720\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">If our process uses its error output, we can ask <code>ltrace<\/code> to put its messages directly into a file, using the <code>-o<\/code> option.<\/p>\n<pre>[factorial]$ <strong>ltrace -o traces.txt .\/test\/factorial 4 5 6 <\/strong>\n4! = 24\n5! = 120\n6! = 720\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">Let&rsquo;s see the content of our trace file.<\/p>\n<pre>[factorial]$ <strong>cat traces.txt <\/strong>\n__libc_start_main(0x80485b4, 4, 0xbf9384f4, 0x80486b0, 0x8048720 &lt;unfinished ...&gt;\n_isoc99_sscanf(0xbf93a45f, 0x8048796, 0xbf938448, 0x80486d1, 0x8048500)                 = 1\nfactorial(4, 0xbf938440, 0xbf938448, 0x80486d1, 0x8048500)                            = 0\nfprintf(0xb771d500, \"%ld! = %lldn\", 4, ...)                                            = 8\n__isoc99_sscanf(0xbf93a461, 0x8048796, 0xbf938448, 24, 0)                               = 1\nfactorial(5, 0xbf938440, 0xbf938448, 24, 0)                                           = 0\nfprintf(0xb771d500, \"%ld! = %lldn\", 5, ...)                                            = 9\n__isoc99_sscanf(0xbf93a463, 0x8048796, 0xbf938448, 120, 0)                              = 1\nfactorial(6, 0xbf938440, 0xbf938448, 120, 0)                                          = 0\nfprintf(0xb771d500, \"%ld! = %lldn\", 6, ...)                                            = 9\n+++ exited (status 0) +++\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">Indeed we see the call to our <code>factorial()<\/code> function, but there is something strange: <code>ltrace<\/code> prints five parameters for our function, but there are in fact only two parameters (see <a title=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/en\/fact.h\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/en\/fact.h\" target=\"_blank\"><code>fact.h<\/code><\/a>).<br \/>\nIn fact, <code>ltrace<\/code> relies on a configuration file named <code>\/etc\/ltrace.conf<\/code> that contains the number and type of arguments of the functions of the system dynamic libraries. If it does not find the function in this file, it displays five arguments by default.<\/p>\n<pre><strong>\/etc\/ltrace.conf<\/strong>\n; ltrace.conf\n;\n; ~\/.ltrace.conf will also be read, if it exists. The -F option may be\n; used to suppress the automatic inclusion of both this file and\n; ~\/.ltrace.conf, and load a different config file or config files\n; instead.\n[...]\n; arpa\/inet.h\nint inet_aton(string,addr);\nstring inet_ntoa(addr);                 ; It isn't an ADDR but an hexa number...\naddr inet_addr(string);\n[...]\n; stdio.h\nint fclose(file);\nint feof(file);\nint ferror(file);\nint fflush(file);\nchar fgetc(file);\naddr fgets(+string, int, file);\nint fileno(file);\nfile fopen(string,string);\nfile fopen64(string,string);\nint fprintf(file,format);\nint fputc(char,file);\nint fputs(string,file);\nulong fread(addr,ulong,ulong,file);\nulong fread_unlocked(addr,ulong,ulong,file);\nulong fwrite(string,ulong,ulong,file);\nulong fwrite_unlocked(string,ulong,ulong,file);\nint pclose(addr);\nvoid perror(string);\naddr popen(string, string);\nint printf(format);\nint puts(string);\nint remove(string);\nint snprintf(+string2,ulong,format);\nint sprintf(+string,format);\n[...]\nint   SYS_waitpid(int,addr,int);\nulong SYS_readv(int,addr,int);\nulong SYS_writev(int,addr,int);\nint   SYS_mprotect(addr,int,int);\nint   SYS_access(string,octal);<\/pre>\n<p style=\"text-align: justify;\">Of course our function does not appear in this file. We could change it (if the library was installed in a location accessible to all users), but I propose instead to create an additional file <code>.ltrace.conf<\/code> that we put in our home directory (where <code>ltrace<\/code> look for additional configuration files).<\/p>\n<pre>[factorial]$ <strong>cat ~\/<a title=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/en\/ltrace.conf\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/en\/ltrace.conf\" target=\"_blank\">.ltrace.conf<\/a> <\/strong>\nint factorial(long,addr);\n[factorial]$ <strong>ltrace -o traces.txt .\/test\/factorial 4 5 6<\/strong>\n4! = 24\n5! = 120\n6! = 720\n[factorial]$ <strong>cat traces.txt <\/strong>\n__libc_start_main(0x80485b4, 4, 0xbf8b3764, 0x80486b0, 0x8048720\n__isoc99_sscanf(0xbf8b545c, 0x8048796, 0xbf8b36b8, 0x80486d1, 0x8048500)           = 1\nfactorial(4, 0xbf8b36b0)                                                         = 0\nfprintf(0xb7704500, \"%ld! = %lldn\", 4, ...)                                       = 8\n__isoc99_sscanf(0xbf8b545e, 0x8048796, 0xbf8b36b8, 24, 0)                          = 1\nfactorial(5, 0xbf8b36b0)                                                         = 0\nfprintf(0xb7704500, \"%ld! = %lldn\", 5, ...)                                       = 9\n__isoc99_sscanf(0xbf8b5460, 0x8048796, 0xbf8b36b8, 120, 0)                         = 1\nfactorial(6, 0xbf8b36b0)                                                         = 0\nfprintf(0xb7704500, \"%ld! = %lldn\", 6, ...)                                       = 9\n+++ exited (status 0) +++\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">We may also use the <code>-F<\/code> option to specify which <code>ltrace.conf<\/code> file to use.<\/p>\n<p style=\"text-align: justify;\">This time the result is perfect, we see our function calls, with the value to compute, the address of the result to complete and the return status (<code>0<\/code> means \u00ab\u00a0all right\u00a0\u00bb).<\/p>\n<p style=\"text-align: justify;\">Using <code>ltrace<\/code>, and its cousin command <code>strace<\/code> for system calls, is very usefull when developping applications and library. Non-intrusive (no special compiler option) and no requirement for source code make it usable even on programs deliveres in binary form only. I remember having used it successfully a few years ago on an application that needed a configuration file, but the documentation referred to an invalid directory. So I started <code>ltrace<\/code> on the application without providing the configuration file. Of course the application failed to start, but I could find in the logs (filtered with <code>grep<\/code>) the calls to the <code>fopen()<\/code> library function, and see the sucessive attempts before failure (something like <code>~\/.APPLICATION\/<\/code>, <code>\/usr\/lib\/APPLICATION<\/code>, <code>\/etc\/APPLICATION<\/code> \u2026)<\/p>\n<h1 style=\"text-align: justify;\">Debugging with Gdb<\/h1>\n<p style=\"text-align: justify;\">In most cases during application development, we consider library calls as invocations of elementary functions on whose contents we do not question. However, dynamic libraries may also require development and step-by-step analysis.<\/p>\n<p style=\"text-align: justify;\">So, let&rsquo;s try using <code>gdb<\/code> with the executable file we produced in the previons article.<\/p>\n<pre>[factorial]$ <strong>gdb .\/test\/factorial <\/strong>\nGNU gdb (Ubuntu\/Linaro 7.3-0ubuntu2) 7.3-2011.08\nCopyright (C) 2011 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later &lt;http:\/\/gnu.org\/licenses\/gpl.html&gt;\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\nThis GDB was configured as \"i686-linux-gnu\".\nFor bug reporting instructions, please see:\n&lt;http:\/\/bugs.launchpad.net\/gdb-linaro\/&gt;...\nReading symbols from \/home\/cpb\/factorial\/test\/factorial...(no debugging symbols found)...done.\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">The debugger has found our executable and loaded it into memory. However, he can&rsquo;t find any symbol table needed for debugging. Let&rsquo;s just try to put a breakpoint at the start of <code>main<\/code> function.<\/p>\n<pre>(gdb) <strong>break main<\/strong>\nBreakpoint 1 at 0x80485b9\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">It works. Run the program with a value argument.<\/p>\n<pre>(gdb) <strong>run 5<\/strong>\nStarting program: \/home\/cpb\/factorial\/test\/factorial 5\nBreakpoint 1, 0x080485b9 in main ()\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">We stopped in the beginning of <code>main()<\/code>. Try to move one step forward.<\/p>\n<pre>(gdb) next\nSingle stepping until exit from function main,\nwhich has no line number information.\n5! = 120\n0xb7e62113 in __libc_start_main () from \/lib\/i386-linux-gnu\/libc.so.6\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">Indeed, the debugger has no notion of line of code, it goes in one run until the end of <code>main()<\/code>. We can only allow the process to complete and exit the debugger.<\/p>\n<pre>(gdb) <strong>cont<\/strong>\nContinuing.\n[Inferior 1 (process 15847) exited normally]\nUndefined command: \"exit\".  Try \"help\".\n(gdb) <strong>quit<\/strong>\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">Now, we compile our code with the <code>-g<\/code> option, in order to insert in the executable file a table of associations between memory addresses and lines of code. Then repeat the experience.<\/p>\n<pre>[factorial]$ <strong>gcc -I include\/ -L lib\/ -o test\/factorial test\/factorial.c -l fact -g<\/strong>\n[factorial]$ <strong>gdb .\/test\/factorial <\/strong>\nGNU gdb (Ubuntu\/Linaro 7.3-0ubuntu2) 7.3-2011.08\nCopyright (C) 2011 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later &lt;http:\/\/gnu.org\/licenses\/gpl.html&gt;\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\nThis GDB was configured as \"i686-linux-gnu\".\nFor bug reporting instructions, please see:\n&lt;http:\/\/bugs.launchpad.net\/gdb-linaro\/&gt;\nReading symbols from \/home\/cpb\/factorial\/test\/factorial...done.\n(gdb) <strong>break main<\/strong>\nBreakpoint 1 at 0x80485bf: file test\/factorial.c, line 11.\n(gdb) <strong>run 5<\/strong>\nStarting program: \/home\/cpb\/factorial\/test\/factorial 5\n\nBreakpoint 1, main (argc=2, argv=0xbffff274) at test\/factorial.c:11\n11\t\tif (argc &lt; 2) {\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">This time, we note that <code>gdb<\/code> displays correctly the line 11. Continue to move forward instruction-by-instruction with the <code>step<\/code> command.<\/p>\n<pre>(gdb) <strong>step<\/strong>\n15\t\tfor (i = 1; i &lt; argc; i ++)\n(gdb) <strong>step<\/strong>\n16\t\t\tif (sscanf(argv[i], \"%ld\", &amp; n) == 1) {\n(gdb) <strong>step<\/strong>\n17\t\t\t\tif (factorial(n, &amp; f) == 0)\n(gdb) <strong>step<\/strong>\n18                                  fprintf(stdout, \"%ld! = %lldn\", n, f);\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">Unfortunately <code>gdb<\/code> does not have the sources of the library, so we can not enter the <code>factorial()<\/code> function, no more than we could in <code>sscanf()<\/code> or <code>fprintf()<\/code>.<\/p>\n<pre>(gdb) <strong>step<\/strong>\n5! = 120\n15\t\tfor (i = 1; i &lt; argc; i ++)\n(gdb) <strong>step<\/strong>\n22\t\treturn EXIT_SUCCESS;\n(gdb) <strong>step<\/strong>\n23\t}\n(gdb) <strong>step<\/strong>\n0xb7e62113 in __libc_start_main () from \/lib\/i386-linux-gnu\/libc.so.6\n(gdb) <strong>step<\/strong>\nSingle stepping until exit from function __libc_start_main,\nwhich has no line number information.\n[Inferior 1 (process 27455) exited normally]\n(gdb) <strong>quit<\/strong>\n[factorial]$<\/pre>\n<h2>Debugging the library<\/h2>\n<p style=\"text-align: justify;\">We have to compile the library with the <code>-g<\/code> option.<\/p>\n<pre>[factorial]$ <strong>gcc -I include\/ -o src\/fact.o -c src\/fact.c -g<\/strong>\n[factorial]$ <strong>gcc -shared -I include\/ -Wl,-soname,libfact.so.2 -o lib\/libfact.so.2.0 src\/fact.o <\/strong>\n[factorial]$ <strong>gcc -I include\/ -L lib\/ -o test\/factorial test\/factorial.c -l fact -g<\/strong><\/pre>\n<p style=\"text-align: justify;\">And start debugging\u2026<\/p>\n<pre>[factorial]$ <strong>gdb .\/test\/factorial <\/strong>\nGNU gdb (Ubuntu\/Linaro 7.3-0ubuntu2) 7.3-2011.08\nCopyright (C) 2011 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later &lt;http:\/\/gnu.org\/licenses\/gpl.html&gt;\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\nThis GDB was configured as \"i686-linux-gnu\".\nFor bug reporting instructions, please see:\n&lt;http:\/\/bugs.launchpad.net\/gdb-linaro\/&gt;...\nReading symbols from \/home\/cpb\/factorial\/test\/factorial...done.\n(gdb) <strong>break main<\/strong>\nBreakpoint 1 at 0x80485bf: file test\/factorial.c, line 11.\n(gdb) <strong>run 5<\/strong>\nStarting program: \/home\/cpb\/factorial\/test\/factorial 5\n(gdb) <strong>break main<\/strong>\nBreakpoint 1, main (argc=2, argv=0xbffff274) at test\/factorial.c:11\n11\t\tif (argc &lt; 2) {\n(gdb) <strong>step<\/strong>\n15\t\tfor (i = 1; i &lt; argc; i ++)\n(gdb) <strong>step<\/strong>\n16\t\t\tif (sscanf(argv[i], \"%ld\", &amp; n) == 1) {\n(gdb) <strong>step<\/strong>\n17\t\t\t\tif (factorial(n, &amp; f) == 0)\n(gdb) <strong>step<\/strong>\nfactorial (n=5, result=0xbffff1c0) at src\/fact.c:5\n5\t\t* result = 1;\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">Now we really are into our <code>factorial()<\/code> function,\u00a0 let&rsquo;s continue step-by-step a few instructions more\u2026<\/p>\n<pre>(gdb) <strong>step<\/strong>\n6\t\tif (n &lt; 0)\n(gdb) <strong>step<\/strong>\n9\t\t\t(*result) = (*result) * n;\n(gdb) <strong>step<\/strong>\n10\t\t\tn = n - 1;\n(gdb) <strong>step<\/strong>\n11\t\t} while (n &gt; 1);\n(gdb) <strong>step<\/strong>\n9\t\t\t(*result) = (*result) * n;\n(gdb) <strong>step<\/strong>\n10\t\t\tn = n - 1;\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">We can also look at the state of the variables. The <code>gdb<\/code> printing of the results is a bit surprising at first because it prefixes the evaluated terms by a <code>$<\/code> character followed by a serial number. This allows to easily write graphical front-ends (like <code>ddd<\/code>, <code>xxgdb<\/code>, Eclipse, etc..) that retrieve the returned values.<\/p>\n<pre>(gdb) <strong>print *result<\/strong>\n$1 = 20\n(gdb) <strong>print n<\/strong>\n$2 = 4\n(gdb) <strong>cont<\/strong>\nContinuing.\n5! = 120\n[Inferior 1 (process 30206) exited normally]\n(gdb) <strong>quit<\/strong>\n[factorial]$<\/pre>\n<h2>Source files locatoin<\/h2>\n<p style=\"text-align: justify;\">The source files location is stored into the executable file when compiling with the <code>-g<\/code> option. However they can be moved or library can be compiled on another machine that those used for debugging. We must therefore have a way to tell <code>gdb<\/code> where to find the source files of the library. Do a test by moving the sources from the library into a totally different directory.<\/p>\n<pre>[factorial]$ <strong>mkdir -p ~\/tmp\/sources<\/strong>\n[factorial]$ <strong>mv src\/* ~\/tmp\/sources\/<\/strong>\n[factorial]$ <strong>gdb .\/test\/factorial <\/strong>\nGNU gdb (Ubuntu\/Linaro 7.3-0ubuntu2) 7.3-2011.08\nCopyright (C) 2011 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later &lt;http:\/\/gnu.org\/licenses\/gpl.html&gt;\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\nThis GDB was configured as \"i686-linux-gnu\".\nFor bug reporting instructions, please see:\n&lt;http:\/\/bugs.launchpad.net\/gdb-linaro\/&gt;...\nReading symbols from \/home\/cpb\/factorial\/test\/factorial...done.\n(gdb) <strong>break factorial<\/strong>\nBreakpoint 1 at 0x80484f0\n(gdb) <strong>run 5<\/strong>\nStarting program: \/home\/cpb\/factorial\/test\/factorial 5\n\nBreakpoint 1, factorial (n=5, result=0xbffff1c0) at src\/fact.c:5\n5\tsrc\/fact.c: No such file or directory.\n\tin src\/fact.c\n(gdb) <strong>quit<\/strong>\nA debugging session is active.\n\n\tInferior 1 [process 31536] will be killed.\n\nQuit anyway? (y or n) <strong>y<\/strong>\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">Of course the debugging failed. We will now try the <code>directory<\/code> command at the <code>gdb<\/code> prompt.<\/p>\n<pre>[factorial]$ <strong>gdb .\/test\/factorial <\/strong>\nGNU gdb (Ubuntu\/Linaro 7.3-0ubuntu2) 7.3-2011.08\nCopyright (C) 2011 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later &lt;http:\/\/gnu.org\/licenses\/gpl.html&gt;\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\nThis GDB was configured as \"i686-linux-gnu\".\nFor bug reporting instructions, please see:\n&lt;http:\/\/bugs.launchpad.net\/gdb-linaro\/&gt;...\nReading symbols from \/home\/cpb\/factorial\/test\/factorial...done.\n(gdb)<strong> directory ~\/tmp\/sources\/<\/strong>\nSource directories searched: \/home\/cpb\/tmp\/sources:$cdir:$cwd\n(gdb) <strong>break factorial<\/strong>\nBreakpoint 1 at 0x80484f0\n(gdb) <strong>run 5<\/strong>\nStarting program: \/home\/cpb\/factorial\/test\/factorial 5\n\nBreakpoint 1, factorial (n=5, result=0xbffff1c0) at src\/fact.c:5\n5\t\t* result = 1;\n(gdb) <strong>step<\/strong>\n6\t\tif (n &lt; 0)\n(gdb) <strong>step<\/strong>\n9\t\t\t(*result) = (*result) * n;\n(gdb) <strong>cont<\/strong>\nContinuing.\n5! = 120\n[Inferior 1 (process 31845) exited normally]\n(gdb) <strong>quit<\/strong>\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">It works perfectly.<\/p>\n<h1>Conclusion<\/h1>\n<p style=\"text-align: justify;\">We have seen two important steps in the development of a library: function calls tracking and step-by-step debugging. We will examine the coverage tests in the <a title=\"Development of a dynamic library (3\/3)\" href=\"http:\/\/www.blaess.fr\/christophe\/2012\/02\/12\/development-of-a-dynamic-library-33\/\">next article<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>(Version originale en fran&ccedil;ais) In the previous article we saw how to build a dynamic library and properly manage its major and minor version numbers for easy maintenance, both for the developer (of the library but also of the applications that use it) and for the administrator of the system where it is installed. We [&hellip;]<\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[],"class_list":["post-1572","post","type-post","status-publish","format-standard","hentry","category-linux-2"],"_links":{"self":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/1572","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/comments?post=1572"}],"version-history":[{"count":0,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/1572\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/media?parent=1572"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/categories?post=1572"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/tags?post=1572"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}