Showing posts with label debugging. Show all posts
Showing posts with label debugging. Show all posts

Thursday, June 23, 2011

Network and SysAdmin, Scripting, Debugging, O.S. Books


[System Administration]
UNIX and Linux System Administration Handbook (4th Edition) by Evi Nemeth, Garth Snyder, Trent R. Hein and Ben Whaley (Jul 24, 2010)
Essential System Administration, Third Edition by Æleen Frisch (Aug 15, 2002)
Linux in a Nutshell by Ellen Siever, Stephen Figgins, Robert Love and Arnold Robbins (Sep 29, 2009)
======================
[Network Administration]
Linux Network Administrator's Guide by Tony Bautts, Terry Dawson and Gregor N. Purdy (Feb 10, 2005)
LINUX Network Administrators Guide: 508 pages by Olaf Kirch and Terry Dawson (Jan 5, 2009)
Linux TCP/IP Network Administration by Scott Mann (Jul 26, 2001)  TCP/IP stack understand, configure and troubleshoot servers
Linux Firewalls (3rd Edition) by Robert L. Ziegler
Linux Networking Cookbook by Carla Schroder
========================
[Network and System Administration]
=====================
[Troubleshooting]
Linux Troubleshooting Bible by Christopher Negus and Thomas Weeks (Jul 30, 2004)
Debugging Embedded Linux (Digital Short Cut) by Christopher Hallinan (Aug 22, 2007)
Linux Troubleshooting for System Administrators and Power Users 2006
----
Wireshark Network Analysis: The Official Wireshark Certified Network Analyst Guide by Laura Chappell
Network Flow Analysis by Michael W. Lucas
=====================
[Performance Tuning]
Performance Tuning for Linux® Servers by Sandra K. Johnson, Gerrit Huizenga and Badari Pulavarty (Jun 6, 2005)

======================
[RHCE]
===================
[Scripting]
Perl Best Practices by Damian Conway
===================
[Linux Operating System]
----
[Parallel and Multi threading]
======================
[Enterprise]
Restful Web Services by Leonard Richardson
=====================

Wednesday, December 1, 2010

Linux KVM Kernel Virtual Machine

Linux KVM: Linux Kernel Virtual Machine
apt-get install -y kvm libvirt-bin ubuntu-vm-builder qemu bridge-utils
apt-get install -y ubuntu-virt-server ubuntu-virt-mgmt #KVM server utils and management GUI

Sunday, November 7, 2010

Remote Debugging with GDB

Remote debugging:
Connecting to remote target
    a) (gdb) target remote /dev/ttyb
   # serial-device
    b) (gdb) target remote host:port
    c) (gdb) target remote protocol:host:port
    d) (gdb) target remote | middleman-command   # gdb talks to a middleman command

Transfer files:
    remote put hostfile targetfile

    remote get targetfile hostfile
    remote delete targetfile

    (gdb) load filename    #   this command is used instead of 'run' in case of remote debugging
    (gdb) break
    (gdb) step
    (gdb) continue
    (gdb) detach
    (gdb) disconnect

a) Remote gdbserver on target with gdb on host (Need O.S. for this):
     target> gdbserver /dev/com1 emacs foo.txt   
    target> gdbserver host:2345 emacs foo.txt   
    target> gdbserver --attach /dev/com1 pid

    # Run a wrapper for the debugee program on the target-side
    target> gdbserver --wrapper env LD_PRELOAD=libtest.so -- :2222 ./testprog
   
    #Connect to the target gdbserver from my host gdb
    $ gdb myprogram

    (gdb) target remote myhost:9999
            0x00007f215893ba60 in ?? () from /lib64/ld-linux-x86-64.so.2
    (gdb) b main
    (gdb) continue

   # Send commands to gdbserver using the monitor command
    monitor help      # List the available monitor commands.
    monitor set debug 0 | 1      # Disable or enable general debugging messages   
    monitor set remote-debug 0|1    # Disable or enable debugging messages of the remote protocol
    monitor exit

   See Also: Remote Configuration
   More in-depth internal look at Remote Protocol

b) Remote Stub:  Used on Embedded devices without an O.S.

Blogs:
1) http://blog.flameeyes.eu/2010/02/20/remote-debugging-with-gdb-part-2-gdb
2) http://www.gentoo.org/proj/en/qa/backtraces.xml

Debugging Multiple Processes/Threads with GDB

Debugging multiple inferiors and programs
Gdb allows you to debug multiple programs at once without exiting the process you're currently running.
Gdb uses an inferior as a handle for a process. An inferior  is attachable/detachable from a process
    info inferiors    # display list of current inferiors.

     (gdb) info inferiors
       Num  Description       Executable
       2    process 2307      hello
     * 1    process 3401      goodbye
Switch to another inferior:
    inferior infno   # make inferior number infno the current inferior

Loading multiple inferiors:
1)    add-inferior [ -copies n ] [ -exec executable ] # n defaults to 1 and optional exec gives an empty inferior
2)    clone-inferior [ -copies n ] [ infno ]    # n defaults to 1 and infno defaults to current inferior number

Ending the inferiority complex:
remove-inferior infno        # Remove the empty inferior Note: Can't remove an inferior with a running assoc. process.
detach-inferior infno         # detaches from an inferior from assoc. process
kill-inferiror infno             # kills the process attached to the inferior. It can be removed or re-attached to some process.

Debugging Multi-threaded Programs:
    info threads    # displays thread info - thread number, thread-id,  stack frame summary
    thread threadno     # make threadno as active current thread and shows stack frame summary

Starting and Stopping Multi-thread Programs
2 modes of debugging:
1) All stop mode: aka 3 musketeers mode i.e. "All-for-one, One-for-all"
2) Non-stop mode:
    set target-async on|off    # Switch asynchronous mode.
    show target-async         # Show the current target-async setting.

    interrupt    # suspend execution of the running program (whole process in all-stop, current thread in non-stop modes)
    interrupt -a    # stop the whole program in non-stop mode

Wednesday, October 27, 2010

Monday, October 25, 2010

Delta Debugging

References:
Download Delta from delta.tigris.org
Why Programs Fail has won a Software Development Jolt Productivity Award!
Eclipse Plug-Ins - Software Engineering Chair (Prof. Zeller) - Saarland University
DDchange - DDchangeWiki
Delta Debugging article on Wikipedia
Delta Debugging articles by Andreas Zeller



See Also:
Episode 101: Podcast with Andreas Zeller on Debugging | Software Engineering Radio

Video by Andreas Zeller on Debugging the Debugging activities
Video YouTube - Learning from Code History
Mining Software Archives by Andreas Zeller
About Andreas Zeller - S/W Engg. Chair at Saarland University


Publications by Prof. Andreas Zeller

Adv Debugging - My Program Worked Yesterday, but Not Today (WYNOT) by Andreas Zellar

Brief Notes of my understanding of on Delta Debugging as discussed in “Worked Yesterday, NOt Today" by Andreas Zeller 
Note:  To understand the basic premise and constraints/approaches of Delta-Debugging referred to the pdf link to:
  1. Analyse the tables/graphs carefully. (80% of the understanding comes from the example tables/graphs)
  2. Connect the WYNOT talk with Andreas Zellar's podcast on Software Engineering Radio.
Problem: Yesterday's code works but Today's code doesn't. How do we find the change(s) which induces the test-case failure.
Context: Looking through the CVS history we find that N changes have been added since Yesterday.

Alternative: Normally we would need run the debugger to reproduce the failure and then try to collect information which induces it.  But this requires a programmer to interactively query the program state using a debugger.
Can the debugging be automated without needing the programmer?

Strategy: Delta Debugging using a test-case to reproduce the failure.
Data Method:
Using the Scientific Method we can first try to reduce the Input Data in a binary search mechanism to isolate the minimum data which causes the failure.
Code Method:
  1. Simple Method: When failure is caused by a single change. We can try to isolate the change which causes the failure by doing a binary search through the change history. If there are N changes between Y(esterday) and T(oday) we test 'k/2'th change where 1 <= k <= N. We go on partitioning until we find a failure-free change. The latest failing change is the culprit. Complexity of this binary search is O (log N)
  2. Complex Method: When failure is caused by a combination of changes. Unfortunately it's Not always possible to use the Simple Method in the case when combination of changes cause the failure. In such a situation we need to identify at least 2 (or more) changes which together cause the failure. 
  • Divide the change history into N changes
  • Group N changes into say 4 units i.e. N = N/4 * 4
  • Generate combinations with different units.
  • Test combinations for the failure. 
  • Prune any units which don't participate in the failure at all.
  • Recursive above steps by sub-dividing the units above (quarters into octets and so on) until we finally we end up with minimal changes that reproduce the failure.
Proposed Plans to Reduce to Reduce Computation and Avoid Inconsistent Configurations :
a) Group related changes - changes on common date/file/variable are more likely to be related. Group them into a single unit to avoid dependency across units.
b) Prune configurations when they're obvious dead-ends e.g. Where change dependency is chained all the way (Today) 10->9->8->7->6->5->4->3->2->1 (Yesterday)
c) Exclude changed code which is never executed.

See Also:
Pdf: "WYNOT - Worked Yesterday, NOt Today"
Andreas Zeller
Podcast on Software Engineering Radio
Delta Debugging

Saturday, October 23, 2010

Debugging with GDB's Cheat-Sheet of Commonly Used Options

Gdb:
Compiling a program for debugging:
    g++ -ggdb -O0 hello.cpp   # 
    g++ -g3 -O0 hello.cpp       # -g3 compiles debugging info for preprocessor macros and no optimization

Running a program under the debugger without arguments
$> gdb myProgram

Setting the program arguments:
   a)  $> gdb --args myProgram  10 20 30 40
   b)  (gdb) start 10 20 30 40  # sets temporary breakpoint at main() and calls run.
   c)  (gdb) file myProgram
        (gdb) run 10 20 30 40
   d)   (gdb)  set args 10 20 30 40
         (gdb) show args
        (gdb) run
    e) $> gdb myProgram core
    f) $> gdb -tui myProgram core  # start vim/emacs ide for debug session

Tuesday, October 19, 2010

Howto Debug a Core-Dump/Crash-Dump for a stripped binary from a production machine

Core dump Analysis:
core(5)– (Linux Programmer's Manual – File Formats)
Core Dump (Wikipedia)

Memory dump (Wikipedia)
CallStack (Wikipedia),
Enabling core dumps in embedded systems,


Dr Dobbs - Postmortem Debugging
Dr Dobbs - Post-Mortem Debugging Revisited

Stackoverflow article (with comments) on core dump analysis on Solaris,
Backtrace commands in GDB documentation
Howto generate a Backtrace for Bug Reporting by Testers (from Gentoo doc)

Stack buffer overflow (Wikipedia)

Segmentation fault (SIG_SEGV, SIG_BUS)
A FAQ: User contributed answers regarding the definition of a segmentation fault,
A "null pointer" explained,
Answer to: NULL is guaranteed to be 0, but the null pointer is not?
Resolving crashes and segmentation faults
,
What is the difference between a segmentation fault and a stack overflow?

Windows:
Crash dump analysis website


Books:
Debugging: The Nine Indispensable Rules for Finding Even the Most Elusive Software and Hardware Problems (by David J. Agans)
Software Exorcism: A Handbook for Debugging and Optimizing Legacy Code (by Bill Blunden)
Debugging by Thinking : A Multidisciplinary Approach (by Robert C. Metzger)
Memory Dump Analysis Anthology, Volume 1  (by Dmitry Vostokov)

Tuesday, September 28, 2010

mmap() is not the territory!! Part 2

Final code at end of debugging:

bool testFileCopyWithSharedMem(const string &srcFileName, const string &destFileName)
{
    bool isCopyOk = false;
    string diffCmd = "diff " + srcFileName + " " + destFileName;
    int retval = system(diffCmd.c_str());
    cout << "system(" << diffCmd << ") returned: " << retval << endl;
    if( retval == 0 )
    {
        isCopyOk = true;
    }
    return isCopyOk;
}

int doFileCopyWithSharedMem(const string &srcFileName, const string &destFileName, size_t sharedMemSize)
{
    //int retval = 0;

    //Map SourceFile
    errno = 0;
    int srcfd = open(srcFileName.c_str(), O_RDONLY);
    if (srcfd < 0) {
        const char * causeOfError = strerror(errno);
        cout << "open() returned:" << causeOfError << " at:" << __LINE__ << " in:" <<__FUNCTION__ << endl;
        cout << "open(" << srcFileName << ") returned: " << srcfd << endl;
        return -1;
    }
    struct stat sb;
    fstat(srcfd,&sb);
    long pageSize;
    //pageSize = sb.st_size;
    pageSize = sysconf(_SC_PAGESIZE);
    errno = 0;
    char *srcFilePtr = 0;
    srcFilePtr = (char *) mmap(0, pageSize, PROT_READ, MAP_SHARED, srcfd, 0);
    if (srcFilePtr == MAP_FAILED)
    {
        const char * causeOfError = strerror(errno);
        cout << "mmap() returned:" << causeOfError << " at:" << __LINE__ << " in:" <<__FUNCTION__ << endl;
        return -1;
    }

    //Map Dest File
    errno = 0;
    int destfd = open(destFileName.c_str(), O_RDWR|O_CREAT|O_TRUNC, 0600 );
    if (destfd < 0) {
        const char * causeOfError = strerror(errno);
        cout << "creat() returned:" << causeOfError << " at:" << __LINE__ << " in:" <<__FUNCTION__ << endl;
        cout << "creat(" << destFileName << ") returned: " << destfd << endl;
        return -1;
    }
    errno = 0;
    char *destFilePtr = 0;
    destFilePtr = (char *) mmap(0, pageSize, PROT_WRITE|PROT_READ, MAP_SHARED, destfd, 0);
    if (destFilePtr == MAP_FAILED) {
        const char * causeOfError = strerror(errno);
        cout << "mmap() returned:" << causeOfError << " at:" << __LINE__ << " in:" <<__FUNCTION__ << endl;
        return -1;
    }

    ftruncate(destfd, sb.st_size);
    cout<< "PID:" << getpid() <
    //cout << srcFilePtr << destFilePtr <
    system("cat /proc/self/maps");

    memcpy(destFilePtr, srcFilePtr, sb.st_size);
    //msync(destFilePtr, pageSize,MS_SYNC);

    munmap(srcFilePtr, pageSize);
    munmap(destFilePtr, pageSize);
    close(srcfd);
    close(destfd);
    return 0;
}
 
----------------------------------------------------------------------------
Time required:  
Debugging 1 AM to 5:40 AM. 
20 Minutes to note down these points in the blog. 
2 hrs to massage it into shape.

Interesting Links:
DevShed : development tutorials: http://www.devshed.com/
Gentoo Bug Reporting Guide: http://www.gentoo.org/doc/en/bugzilla-howto.xml 
C sample source on Gnu/Linux : http://www.c.happycodings.com/Gnu-Linux/index.html
Mmap() security bug with Null Pointers: http://blog.ksplice.com/2010/03/null-pointers-part-i/
Wiki on Chromium multi-process debugging with gdb: http://code.google.com/p/chromium/wiki/LinuxDebugging
BugReport: http://www.mail-archive.com/ubuntu-bugs@lists.ubuntu.com/msg2333427.html 


mmap is not the territory Part 1 : http://techtalkies.blogspot.com/2010/09/mmap-is-not-territory-or-mapfail-sigbus.html

mmap() is not the territory!! Part 1

(OR) how MAP_FAIL, SIGBUS,
beg to differ with mmap!!
Wrote a small program using mmap() to copy a fromFile.txt to toFile.txt using virtual memory

--------------------------------------------
Issue#1: mmap() returns MAP_FAIL
mmap() requires exactly the same flags as the filedescriptor/fd as when it was open()/creat()-ed
i.e. if you used O_RDONLY in open() then you can't mmap() it as PROT_WRITE.

chmod basics: http://www.linux.org/lessons/beginner/l14/lesson14b.html
creat/open man page: http://linux.about.com/od/commands/l/blcmdl2_open.htm
-------------------------------------------------
Issue#2:
Error Message: In gdb getting SIGBUS with error coming from inside memcpy!!

108        memcpy(destFilePtr, srcFilePtr, pageSize);
5: pageSize = 14
4: destFilePtr = 0xb7ffc000

3: srcFilePtr = 0xb7ffd000 "hello, world\n\n"
2: destfd = 6
1: srcfd = 5
(gdb) n

Program received signal SIGBUS, Bus error.
__memcpy_ia32 () at ../sysdeps/i386/i686/multiarch/../memcpy.S:75
75    ../sysdeps/i386/i686/multiarch/../memcpy.S: No such file or directory.
    in ../sysdeps/i386/i686/multiarch/../memcpy.S
 
Searching on this gave no direct answers on the error message but gave some pointers on causes.
Tried all the below tools but still getting the same error message:
0) used apt-get update and rebooted "just-in-case"
    https://help.ubuntu.com/8.04/serverguide/C/apt-get.html
1) used strace ./file-copy-vm to check the system calls were getting called properly.
   getting SIGBUS on write() ostensibly called from inside the memcpy
2) used ldd ./file-copy-vm to check that the libstdc++ - and libc.so were existent.
   They were present
3) Installed glibc-dbg and libstdc++-devel etc for debugging the library.
    No change.
Finally found the problem in an off-by-N error in memcpy(dest,src, pageSize)

Since SIGBUS comes when a page worth is allocated but size of mapping is less than pagesize. 
i.e. the accessed address is more than filesize but inside pagesize.

 So realized my mistake and changed:
        memcpy(destFilePtr, srcFilePtr, pageSize); //WRONG.
Corrected it to:
        memcpy(destFilePtr, srcFilePtr, sb.st_size); //Correct
------------------------------------------------------------------------------------------------------------------
Issue#3: Still getting SIGBUS from memcpy() AND
out of bounds>

Breakpoint 3, doFileCopyWithSharedMem (srcFileName=..., destFileName=..., sharedMemSize=8192) at ../src/file-copy-vm.cpp:104
104        cout<< "PID:" << getpid() <
4: destfd = 6
3: srcfd = 5
2: srcFilePtr = 0xb7ffd000 "hello, world\n\n"
1: destFilePtr = 0xb7ffc000
0xb7ffc00 out of bounds>

(gdb) n
PID:7136
106        system("cat /proc/self/maps");
4: destfd = 6
3: srcfd = 5
2: srcFilePtr = 0xb7ffd000 "hello, world\n\n"
1: destFilePtr = 0xb7ffc00
0xb7ffc00 out of bounds>

(gdb) shell cat /proc/7136/maps
[SNIP]
08048000-0804a000 r-xp 00000000 08:01 933913     /home/gurud/cdt-linux-tools-workspace/file-copy-vm/Debug/file-copy-vm
0804a000-0804b000 r--p 00001000 08:01 933913     /home/gurud/cdt-linux-tools-workspace/file-copy-vm/Debug/file-copy-vm
0804b000-0804c000 rw-p 00002000 08:01 933913     /home/gurud/cdt-linux-tools-workspace/file-copy-vm/Debug/file-copy-vm
0804c000-0806d000 rw-p 00000000 00:00 0          [heap]
b7fec000-b7fee000 rw-p 00000000 00:00 0
b7ffb000-b7ffc000 rw-p 00000000 00:00 0
b7ffc000-b7ffd000 rw-s 00000000 08:01 933725     /home/gurud/cdt-linux-tools-workspace/file-copy-vm/Debug/toFile.txt
b7ffd000-b7ffe000 r--s 00000000 08:01 933672     /home/gurud/cdt-linux-tools-workspace/file-copy-vm/Debug/fromFile.txt
b7ffe000-b8000000 rw-p 00000000 00:00 0
bffeb000-c0000000 rw-p 00000000 00:00 0          [stack]

Hmmm... here the destFilePtr seems to be pointing to the correct memory-mapped file i.e. toFile.txt
The destFilePtr
is pointing to out-of-bounds accesss.
Also the SIGBUG seems to suggest that I'm trying to write/access to an address in memory that's allocated but out of bounds of the empty dest file. Otherwise I'd have got a SIGSEGV if the memory had not been allocated.
 
I observed that toFile.txt is showing filesize as zero on the disk. Aha!!
 
Robert Love in his book "Linux System Programming" had mentioned files with slack-space/holes (in memory as well as disk respectively). Could this be the reason??!! 
http://www.devshed.com/c/a/BrainDump/Using-mmap-for-Advanced-File-IO/
Finally I cross-checked my code with a sample implementation for mmap() file copy program.
Found out that they used lseek() to expand the memory mapping instead of ftruncate() to expand file size with a hole instead of ftruncate().
http://www.c.happycodings.com/Gnu-Linux/code6.html

So we just need to increase the size of the dest-file using ftruncate.

(gdb) help call
Call a function in the program.
The argument is the function name and arguments, in the notation of the
current working language.  The result is printed and saved in the value
history, if it is not void.

(gdb) call ftruncate(destfd,sb.st_size)
$1 = 0

doFileCopyWithSharedMem() returned:0
system(diff ./fromFile.txt ./toFile.txt) returned: 0
testFileCopyWithSharedMem() returned:0

(gdb)

Hurray!! the unit testcase passes!! 
It's 6 AM!! Tiring but worth it!! Gotta go and sleep now

----------------------------------------------------------------------------

See Also : 
mmap is not the territory Part 2 : http://techtalkies.blogspot.in/2010/09/mmap-is-not-territory-part-2.html

Monday, September 20, 2010

Installing Eclipse C++ CDT with Linux Tools for debugging and profiling applications on Linux

The Eclipse incubation project Linux Tools integrates C/C++ Development tools.
It's a GUI plugin to integrate tools like Valgrind, GProf, GCov, SystemTap etc into the Eclipse C++ CDT IDE.

[Articles on Linux Tools]
Download page of Eclipse Helios gives 2 good alternatives for C++ developers on Linux:
  • Java6 JRE update :apt-get install sun-java6-jre
  • Unzip the Eclipse tarball and run the eclipse binary from inside the tarball: 
          tar -zxf eclipse-cpp-helios-linux-gtk.tar.gz && ./eclipse

[Website]
[Usage]
[Docs]
[Whitepapers]

[Interview]



[Cpp Check tool integration with Eclipse]
  • cppcheclipse integration of with Eclipse CDT from (google code):
  • About: http://code.google.com/a/eclipselabs.org/p/cppcheclipse/
  • Wiki: http://code.google.com/a/eclipselabs.org/p/cppcheclipse/wiki/Installation
  • Download: http://code.google.com/a/eclipselabs.org/p/cppcheclipse/downloads/list