Wednesday, March 3, 2010

qsort Example

1. This example will demonstrate how to sort a given list in ascending or descending order

2. Many a times the structures are quite big and allocating such structures could be resource intensive exercise. Therefore I allocate a list of pointers to pointers (double pointer) to the original data structure.

3. QSORT sorts only arrays or data stored in contiguous memory locations. Therefore can't be directly used to sort linked lists.

Workaround : Walk the Linked List
                       Store the pointers to these nodes in an array/allocated memory location
                       Call Qsort to sort this array based on a comparison function that you define.

###include files : stdio.h -- stdlib.h -- string .h ####

--  This function will read the contents of a linked-list/array and copy into an "array" of pointers to the data. Qsort will sort this array.

#define ARRAY_SIZE 10

typedef struct adi_data_t_ {
    unsigned int number;
} adi_data_t;

typedef struct adi_delete_list_t_ {
    adi_data_t ** first;
    unsigned int count;
} adi_delete_list_t;

/* compare function to sort in ASCENDING order */
int adi_compare_data (const void * a, const void *b)
{
   const adi_data_t ** one = (const adi_data_t **) a;
   const adi_data_t ** two = (const adi_data_t **) b;

   printf("Number one : [%d] Number two : [%d]  ret [%d]\n", (*one)->number, (*two)->number, (*one)->number - (*two)->number);
   return (*one)->number - (*two)->number ;

}

/* compare function to sort in DESCENDING order */

int adi_compare_data (const void * a, const void *b)
{
   const adi_data_t ** one = (const adi_data_t **) a;
   const adi_data_t ** two = (const adi_data_t **) b;

   printf("Number one : [%d] Number two : [%d]  ret [%d]\n", (*one)->number, (*two)->number, (*one)->number - (*two)->number);
   return (*two)->number - (*one)->number ;

}



int adi_delete_walker(adi_delete_list_t * delete, adi_data_t * data)
{
    static adi_data_t ** list = NULL;
    void *temp = NULL;

    /* allocate memory for the list */
    temp = realloc(list, (delete->count + 1) * sizeof (adi_data_t *));
    if(temp == NULL) {
        printf("###!Ady: Hell Freezes over: Realloc failed \n");
    } else {
        list = (adi_data_t **) temp;
        delete->first = list;
        memcpy(&list[delete->count], &data, sizeof(adi_data_t *));
        printf(" First [%p] List [%p] Current element:[%p] \n", delete->first, list, &list[delete->count]);
        delete->count++;
    }
}



int main (int argc, char* argv[])
{
    adi_delete_list_t delete;
    adi_data_t data_array[10];
    unsigned int i = 0;

    memset(&delete, 0, sizeof(adi_delete_list_t));

    /* Fill the array and pass it to the delete function */
    for (i=0; i < 10 ; i++) {
        data_array[i].number = rand()/1000000;
        printf(" Data Array filled with %d \n", data_array[i].number);
        adi_delete_walker(&delete, &data_array[i]);
    }

    printf("qsort parameters: first [%p] count [%d]", delete.first, delete.count);
    /* qsort the array */
    qsort(delete.first, delete.count, sizeof(adi_data_t *), adi_compare_data);

     for (i=0; i < 10 ; i++) {
        printf(" POST SORT: Data Array filled with %d \n", (*(delete.first)[i]).number);
     }

    free(delete.first);
}
                          


Friday, December 18, 2009

Miscellaneous Debugging tips

LTRACE
=========================================
from the Man page
ltrace  is  a  program  that  simply  runs the specified command until it exits.  It intercepts and records the  dynamic library calls which are called by the executed process and the  signals  which  are  received  by  that        process.  It can also intercept and print the system calls executed by the program.





STRACE
===========================================
In the simplest case strace runs the specified command until it exits.  It intercepts and  records  the  system  calls  which  are called by a process and the signals which are received by a process.  The name of each system  call, its arguments and its return value are printed on standard error or to the file  specified  with  the  -o    option.



nemesis@nemesis-laptop:~/test_code$ strace ./crashcourse
execve("./crashcourse", ["./crashcourse"], [/* 42 vars */]) = 0
brk(0)                                  = 0x80ba000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7846000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=72786, ...}) = 0
mmap2(NULL, 72786, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7834000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/tls/i686/cmov/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\260l\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1319364, ...}) = 0
mmap2(NULL, 1325416, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x626000
mmap2(0x764000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x13e) = 0x764000
mmap2(0x767000, 10600, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x767000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7833000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb78336c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0x764000, 8192, PROT_READ)     = 0
mprotect(0x8049000, 4096, PROT_READ)    = 0
mprotect(0x3d0000, 4096, PROT_READ)     = 0
munmap(0xb7834000, 72786)               = 0
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++


MTRACE
=============================================
nemesis@nemesis-laptop:~/test_code$ mtrace ./crashcourse
No memory leaks

LibC

nemesis@nemesis-laptop:/lib$ ./libc.so.6
GNU C Library (EGLIBC) stable release version 2.10.1, by Roland McGrath et al.
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.4.1.
Compiled on a Linux >>2.6.24-23-server<< system on 2009-10-07.
Available extensions:
        crypt add-on version 2.1 by Michael Glad and others
        GNU Libidn by Simon Josefsson
        Native POSIX Threads Library by Ulrich Drepper et al
        BIND-8.2.3-T5B
For bug reporting instructions, please see:
.

Core Dump : how to enable & Debug

1. find out if core will be dumped.

nemesis@nemesis-laptop:~/test_code$ ulimit -c
0

This means that core will NOT be dumped. ulimit specifies the maximum size of the core file.

2. Now set the value of ulimit to whatever you want it to be

ulimit -c [size]

3.  you can also specify the directory in which core files will be placed
root@nemesis-laptop:/home/nemesis/test_code# echo "/tmp/corefiles/core" > /proc/sys/kernel/core_pattern

4. small program to cause the segmentation fault

###########################################
#include

void func2(void)
{
    int *p = NULL;
    *p = 0xdeadcafe;
}

void func1(void)
{
    func2();
}


int main (int argc, char **argv)
{
    func1();
    int *p = NULL;
    *p = 0xdeadcafe;

}

##############################################


nemesis@nemesis-laptop:~/test_code$ gcc -g -o crashcourse crash_core.c







5. now generate the core file
nemesis@nemesis-laptop:~/test_code$ ./corefile
Segmentation fault (core dumped)

6. a bit more details from the file command [Tells you the program which generated the core dump]

nemesis@nemesis-laptop:~/test_code$ file /tmp/corefiles/core
/tmp/corefiles/core: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from './corefile'


7. gdb [executable_file] [core_file]

##################################################
nemesis@nemesis-laptop:~/test_code$ gdb crashcourse /tmp/corefiles/core
GNU gdb (GDB) 7.0-ubuntu
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
...
Reading symbols from /home/nemesis/test_code/crashcourse...done.

warning: Can't read pathname for load map: Input/output error.
Reading symbols from /lib/tls/i686/cmov/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./crashcourse'.
Program terminated with signal 11, Segmentation fault.
#0  0x080483c4 in func2 () at crash_core.c:6
6           *p = 0xdeadcafe;

##################################################

8. Get the backtrace


(gdb) bt
#0  0x080483c4 in func2 () at crash_core.c:6
#1  0x080483d4 in func1 () at crash_core.c:11
#2  0x080483e1 in main (argc=1, argv=0xbfe81b44) at crash_core.c:17





9. use the "up" and "down" commands to go through the code. (you can't run the code remember :) )

==============================================
UP
==============================================
(gdb) up
#1  0x080483d4 in func1 () at crash_core.c:11
11          func2();
(gdb) up
#2  0x080483e1 in main (argc=1, argv=0xbfe81b44) at crash_core.c:17
17          func1();
(gdb) up
Initial frame selected; you cannot go up.

===============================================
DOWN
===============================================
(gdb) down
#1  0x080483d4 in func1 () at crash_core.c:11
11          func2();
(gdb) down
#0  0x080483c4 in func2 () at crash_core.c:6
6           *p = 0xdeadcafe;


=========================================
NOTE: What if somebody handed you a core file and you don't the crashing process ? Happens a lot of times when the test team would pass you the core file and wash their hands off the issue altogether :)

Answer:
1. from the (file) following command

file [CORE-FILE]


nemesis@nemesis-laptop:~/test_code$ file /tmp/corefiles/core
/tmp/corefiles/core: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from './corefile'


2. just load the core file in gdb with "any" program name.

nemesis@nemesis-laptop:~/test_code$ gdb /bin/ps /tmp/corefiles/core
GNU gdb (GDB) 7.0-ubuntu
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
...
Reading symbols from /bin/ps...(no debugging symbols found)...done.

warning: core file may not match specified executable file.
Core was generated by `./crashcourse'.

Program terminated with signal 11, Segmentation fault.
#0  0x080483c4 in ?? ()


GDB is intelligent enough to catch your bluff but the good that comes out of it is that it tells you the correct name of the program that core-d. (GDB can't tell if your bluffing or plain ignorant :))

Sunday, December 13, 2009

GIT Guide --- update

Before your commits make sure you have these variables defined. :)
==================================================
nemesis@nemesis-laptop:~/qemu/qemu$ git config --global user.name "nemesisofstate"
nemesis@nemesis-laptop:~/qemu/qemu$ git config --global user.email "nemesisofstate@gmail.com"


for checkin
========

edit [file]
git add [file]
git commit -m "your-message-here" -s

-s
--signoff

Add Signed-off-by line by the committer at the end of the commit log message.


======================
see your patch

git format-patch origin/master

your messages
===============
git show

gitk ===> graphic tool for git

Send out your patch
================
I use gmail to send my patches ...so u need msmtp for it [http://msmtp.sourceforge.net]. Install the file and configure your ~/.msmtprc file

git-config --global sendemail.smtpserver /usr/local/bin/msmtp

sudo apt-get install git-email

git email-send

e.g
nemesis@nemesis-laptop:~/qemu/qemu$ git send-email 0001-correcting-ARM-CPSR-register-bit-position-comment.patch