Generate intermediate files ( assembling, preprocessing) in gcc

It is good to see the output files generated by GCC at its each ( preprocessing, assembling..etc) stage.. You will get an idea on  different processes involved and the result worked out by GCC to make a binary/ELF..There are different ways to generate these output files by specifying GCC options..That said, it is possible to generate only assembly output of your source by below way:

#gcc -S -c program.c

Ex:

[root@humbles-lap gcc]# ls
program.c

[root@humbles-lap gcc]# file program.c
program.c: ASCII text
[root@humbles-lap gcc]# gcc -S -c program.c
[root@humbles-lap gcc]# ls
program.c  program.s
[root@humbles-lap gcc]# file program.s
program.s: ASCII assembler program text
[root@humbles-lap gcc]# cat program.s |head -n 5
    .file    "program.c"
    .section    .rodata
    .align 8
.LC0:
    .string    "\n I am always  an example program"
[root@humbles-lap gcc]#How-ever it wont give you all the resulted files in each stage , for ex: preprocessor files. For that, I use below gcc option to generate different output files of my source..#man gcc

       -save-temps
       -save-temps=cwd
           Store the usual “temporary” intermediate files permanently; place them in the current directory and name them based on
           the source file.  Thus, compiling foo.c with -c -save-temps would produce files foo.i and foo.s, as well as foo.o.
           This creates a preprocessed foo.i output file even though the compiler now normally uses an integrated preprocessor.

           When used in combination with the -x command line option, -save-temps is sensible enough to avoid over writing an input
           source file with the same extension as an intermediate file.  The corresponding intermediate file may be obtained by
           renaming the source file before using -save-temps.

           If you invoke GCC in parallel, compiling several different source files that share a common base name in different
           subdirectories or the same source file compiled for multiple output destinations, it is likely that the different
           parallel compilers will interfere with each other, and overwrite the temporary files.  For instance:

                   gcc -save-temps -o outdir1/foo.o indir1/foo.c&
                   gcc -save-temps -o outdir2/foo.o indir2/foo.c&

           may result in foo.i and foo.o being written to simultaneously by both compilers.

#end of man gcc

As mentioned in “man’ page it will generate “.i”, “s”, “.o” files ..

Ex:

[root@humbles-lap gcc]# ls
program.c
[root@humbles-lap gcc]# gcc -o program program.c --save-temps

[root@humbles-lap gcc]# ls
program  program.c  program.i  program.o  program.s
[root@humbles-lap gcc]# file program.i
program.i: ASCII C program text
[root@humbles-lap gcc]# file program.s
program.s: ASCII assembler program text
[root@humbles-lap gcc]# file program.o
program.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
[root@humbles-lap gcc]# file program
program: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, not stripped
[root@humbles-lap gcc]#Examine those “intermediate files” and try to make sense out of it.. it is funny..I will write more about each stage in another blog..

Find integer array size in C programming

Someone asked me once “how can I get integer array size in C programming and use it in the code?”.Unfortunately there is no defined standard function to get that in C.
Rather you could use below method .Suppose you have defined an integer array ( static ) called , int intArray[10];Its size can be derived by,size_t size = sizeof(intArray)/sizeof(intArray[0]);

or
size_t size = sizeof(intArray) / sizeof(int);
Thats it..

gdb to list process/thread information (state, command, stack..etc )

Do you know,  how powerful are debuggers ? It has lots of capabilities to track debugged program.. Here in this blog, I will describe some of the commands which are very handy with “GDB”..
I was tracking down a running program in my setup with gdb ( gdb -p),  it is nothing but “qemu-kvm”.. which is a “multithreaded application”..
I will show some example gdb commands below.
info threads” will show you the threads of debugged program…
(gdb) info threads
4 Thread 0x7f7a6ee2b700 (LWP 8120)  0x000000392a8d82a7 in ioctl () from /lib64/libc.so.6
3 Thread 0x7f7a6e62a700 (LWP 8121)  0x000000392a8d82a7 in ioctl () from /lib64/libc.so.6
2 Thread 0x7f7a67875700 (LWP 8127)  0x000000392ac0b82f in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
* 1 Thread 0x7f7a6f039980 (LWP 8119)  0x000000392a8d89a3 in select () from /lib64/libc.so.6
below is shortform of “thread apply all bt” command which will show you back trace of all the threads..
(gdb) thr a a bt
Thread 4 (Thread 0x7f7a6ee2b700 (LWP 8120)):
#0  0x000000392a8d82a7 in ioctl () from /lib64/libc.so.6
#1  0x0000000000429869 in kvm_run (env=0x1a50580) at /usr/src/debug/qemu-kvm-0.13.0/qemu-kvm.c:610
#2  0x000000000042a669 in kvm_cpu_exec (env=) at /usr/src/debug/qemu-kvm-0.13.0/qemu-kvm.c:1238
#3  0x000000000042a8a5 in kvm_main_loop_cpu (_env=0x1a50580) at /usr/src/debug/qemu-kvm-0.13.0/qemu-kvm.c:1495
#4  ap_main_loop (_env=0x1a50580) at /usr/src/debug/qemu-kvm-0.13.0/qemu-kvm.c:1541
#5  0x000000392ac07b41 in start_thread () from /lib64/libpthread.so.0
#6  0x000000392a8df49d in clone () from /lib64/libc.so.6

Thread 3 (Thread 0x7f7a6e62a700 (LWP 8121)):
#0  0x000000392a8d82a7 in ioctl () from /lib64/libc.so.6
#1  0x0000000000429869 in kvm_run (env=0x1a6c080) at /usr/src/debug/qemu-kvm-0.13.0/qemu-kvm.c:610
#2  0x000000000042a669 in kvm_cpu_exec (env=) at /usr/src/debug/qemu-kvm-0.13.0/qemu-kvm.c:1238
#3  0x000000000042a8a5 in kvm_main_loop_cpu (_env=0x1a6c080) at /usr/src/debug/qemu-kvm-0.13.0/qemu-kvm.c:1495
#4  ap_main_loop (_env=0x1a6c080) at /usr/src/debug/qemu-kvm-0.13.0/qemu-kvm.c:1541
#5  0x000000392ac07b41 in start_thread () from /lib64/libpthread.so.0
#6  0x000000392a8df49d in clone () from /lib64/libc.so.6

Thread 2 (Thread 0x7f7a67875700 (LWP 8127)):
#0  0x000000392ac0b82f in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x000000000043d4bb in cond_timedwait (unused=) at posix-aio-compat.c:103
#2  aio_thread (unused=<value optimized out>) at posix-aio-compat.c:324
#3  0x000000392ac07b41 in start_thread () from /lib64/libpthread.so.0
#4  0x000000392a8df49d in clone () from /lib64/libc.so.6

Thread 1 (Thread 0x7f7a6f039980 (LWP 8119)):
#0  0x000000392a8d89a3 in select () from /lib64/libc.so.6
#1  0x00000000004196d4 in main_loop_wait (nonblocking=) at /usr/src/debug/qemu-kvm-0.13.0/vl.c:1291
#2  0x000000000042b067 in kvm_main_loop () at /usr/src/debug/qemu-kvm-0.13.0/qemu-kvm.c:1710
#3  0x000000000041a51e in main_loop (argc=, argv=, envp=)

 

“thread <thread number>” this will help you to switch between “threads”…

 

(gdb) thread 3
[Switching to thread 3 (Thread 0x7f7a6e62a700 (LWP 8121))]#0  0x000000392a8d82a7 in ioctl () from /lib64/libc.so.6
(gdb)

Suppose you want to show “stat” or any related information of a process, you can print it in “gdb” as shown below..

** 8127″ is the process id.. Here “STATE” says “t” ..

because it is being traced by the debugger..

(gdb) info proc 8127 stat
process 8127
cmdline = '/usr/bin/qemu-kvm'
cwd = '/'
exe = '/usr/bin/qemu-kvm'
Process: 8127
Exec file: qemu-kvm
State: t
Parent process: 1
Process group: 8118
Session id: 8118
TTY: 0
TTY owner process group: -1
Flags: 0x84020c0
Minor faults (no memory page): 11392
Minor faults, children: 0
Major faults (memory page faults): 1
Major faults, children: 0
utime: 344
stime: 427
utime, children: 0
stime, children: 0
jiffies remaining in current time slice: 20
'nice' value: 0
jiffies until next timeout: 4
jiffies until next SIGALRM: 0
start time (jiffies since system boot): 1005403
Virtual memory size: 892162048
Resident set size: 10937
rlim: 18446744073709551615
Start of text: 0x400000
End of text: 0x659d4c
Start of stack: 0x7fff86b785b0
(gdb) info proc 1 stat
process 1
cmdline = '/sbin/init'
cwd = '/'
exe = '/sbin/upstart'
Process: 1
Exec file: init
State: S
Parent process: 0
Process group: 1
Session id: 1
TTY: 0
TTY owner process group: -1
Flags: 0x402100
Minor faults (no memory page): 2662
Minor faults, children: 4307085
Major faults (memory page faults): 11
Major faults, children: 808
utime: 6
stime: 116
utime, children: 210588
stime, children: 24321
jiffies remaining in current time slice: 20
'nice' value: 0
jiffies until next timeout: 1
jiffies until next SIGALRM: 0
start time (jiffies since system boot): 2
Virtual memory size: 19865600
Resident set size: 381
rlim: 18446744073709551615
Start of text: 0x400000
End of text: 0x421dc6
Start of stack: 0x7fffa2558780
           I thought of printing information of "init" process :
(gdb) info proc 1 stat
process 1
cmdline = '/sbin/init'
cwd = '/'
exe = '/sbin/upstart'
Process: 1
Exec file: init
State: S
Parent process: 0
Process group: 1
Session id: 1
TTY: 0
TTY owner process group: -1
Flags: 0x402100
Minor faults (no memory page): 2662
Minor faults, children: 4307085
Major faults (memory page faults): 11
Major faults, children: 808
utime: 6
stime: 116
utime, children: 210588
stime, children: 24321
jiffies remaining in current time slice: 20
'nice' value: 0
jiffies until next timeout: 1
jiffies until next SIGALRM: 0
start time (jiffies since system boot): 2
Virtual memory size: 19865600
Resident set size: 381
rlim: 18446744073709551615
Start of text: 0x400000
End of text: 0x421dc6
Start of stack: 0x7fffa2558780
Thats it guys.. I hope this helps you when playing with debuggers.!!! Njoy!!!
[Note: modified..]