Saturday, October 31, 2009

Debugging A Running Process with GDB Debugger

So far, we've debugged executables, with and without core files. However, we can debug processes too. Think about that -- we can debug a process that has already been started outside the debugger. There are two ways of doing this: Using command line arguments and using the attach command.
Download and read beer-process.c and its Makefile. Compile it, and run it as a background job in one console (or xterm). It'll simply print out the number of bottles of beer on the wall:
$ ./beer-process &
[1] 17399
p@satan$ 100000 bottles of beer on the wall.
99999 bottles of beer on the wall.
99998 bottles of beer on the wall.
99997 bottles of beer on the wall.

With Command Line Arguments
With the beer process running one console, start GDB in another console with an argument list of the executable and the process ID. The process ID should've been printed when you started the background process:
$ gdb beer-process 17399
Attaching to program: code/running_process/beer-process, process 17399
0x410c64fb in nanosleep () from /lib/tls/libc.so.6
(gdb)
Chances are overwhelmingly good that the process is in GoToSleep(). Print out a backtrace and take a look at the stack:
(gdb) bt
#0 0x410c64fb in nanosleep () from /lib/tls/libc.so.6
#1 0x410c6358 in sleep () from /lib/tls/libc.so.6
#2 0x0804841f in GoToSleep () at beer-process.c:32
#3 0x080483e0 in main () at beer-process.c:14
Aside: Note that GoToSleep() calls the C library function sleep(), and sleep(), in turn, calls the system call nanosleep(). As you know, all library functions (glibc on Linux) do their job by calling system calls. I'm a little surprised to see the library and system functions listed in the call stack since I'm not using a debugging version of glibc. Weird.
At this point, the backtrace should be very familiar to you. But there's an important distinction. We didn't run this program from within GDB. We ran it from the command line, and then had GDB attach to an already running process.
Look at the output of the beer process: you should notice that the process has stopped! Whenever GDB attaches to a running process, the process is paused so you can get a handle on what the call stack looks like. Let's do some interesting things.
In my output above, i=9997. Yours is probably different, but nevertheless, you should be able to follow along with me. Let's verify the value of i by selecting the stack frame for main() and looking at its value:
(gdb) frame 3
#3 0x080483eb in main () at beer-process.c:15
15 GoToSleep();
(gdb) print i
$1 = 99997
No surprises here. As you'd expect, we can use next and step (which takes us out of nanosleep() and sleep() respectively, putting us into GoToSleep()):
(gdb) next
Single stepping until exit from function nanosleep,
which has no line number information.
0x410c6358 in sleep () from /lib/tls/libc.so.6
(gdb) step
Single stepping until exit from function sleep,
which has no line number information.
GoToSleep () at beer-process.c:34
34 }
(gdb) bt
#0 GoToSleep () at beer-process.c:34
#1 0x080483eb in main () at beer-process.c:15
Looking at the code, the next things to happen are that i will be decremented and then PrintMessage() will print 99996 bottles of beer on the wall. However, suppose we wanted more beer? Let's change to the stack frame for main() (where i lives) and change the number of beers on the wall.
(gdb) frame 3
#3 0x080483eb in main () at beer-process.c:15
15 GoToSleep();
(gdb) set var i = 99999999
Now quit GDB. When GDB detaches from the process, the process will continue along its merry way. We could also use the detach command to detach from the process without quiting GDB; I'll explain detach in the next session.
(gdb) quit
The program is running. Quit anyway (and detach it)? (y or n) y
Detaching from program: code/running_process/beer-process,
process 17399
but with the new value for i:
$ ./beer-process &
[1] 17399
p@satan$ 100000 bottles of beer on the wall.
99999 bottles of beer on the wall.
99998 bottles of beer on the wall.
99997 bottles of beer on the wall.
99999998 bottles of beer on the wall.
99999997 bottles of beer on the wall.
99999996 bottles of beer on the wall.
99999995 bottles of beer on the wall.
99999994 bottles of beer on the wall.
I hope you're impressed by this! We attached GDB to a process that was already running. The process halted and we were able to do everything that we would've been able to do had we started the process from within GDB. Now that's power!
One non-debugging use I've had for this in the past is with scientific programming. I had PDE solvers and Monte Carlo applications that would run for a very long time. Whenever I wanted to take a look at how my simulation was doing or what some of the intermediary answers looked like, I'd attach to the process using GDB and inspect my variables. This was a much better option than simply printing everything of interest out, which could've possibly have taken hundreds of megs of disk space!

With The Attach Command
We can also debug an already running process using GDB's attach command to attach to a running process. Again, once attached, we can use the detach command to detach from the process.
If you quit the running background process from the previous section, restart beer-process in the background. Start GDB with no command line arguments. But use the attach command to attach to the running process.
$ gdb
(gdb) attach 17399
Attaching to process 17399
Reading symbols from code/running_process/beer-process...done.
0x410c64fb in nanosleep () from /lib/tls/libc.so.6
(gdb)
As before, the process should halt. This is when you do whatever it is you want to do with the process: debug, snoop, spy, modify, etc. When you're done futzing around, quit GDB:
The program is running. Quit anyway (and detach it)? (y or n) y
Detaching from program: code/running_process/beer-process,
process 17399
As before, once you detach from the process, it'll continue running.

Processes Without Debugging Symbols
As with debugging executables and corefiles, it's only convenient to debug processes that were started from executables with debugging information compiled into them. To see this in action, strip the executable and run it in the background again:
$ strip beer-process
$ ./beer-process &
[1] 32262
p@satan$ 100000 bottles of beer on the wall.
99999 bottles of beer on the wall.
99998 bottles of beer on the wall.
Debug the process and look at the call stack:
$ gdb
(gdb) attach 32262
Attaching to process 32262
Reading symbols from code/running_process/beer-process...(no debugging symbols found)...done.
(gdb) bt
#0 0x410c64fb in nanosleep () from /lib/tls/libc.so.6
#1 0x410c6358 in sleep () from /lib/tls/libc.so.6
#2 0x0804841f in ?? ()
#3 0x00000003 in ?? ()
#4 0x0001869d in ?? ()
#5 0xbffff7b8 in ?? ()
#6 0x080483eb in ?? ()
#7 0x0001869d in ?? ()
#8 0x0001869d in ?? ()
#9 0xbffff844 in ?? ()
#10 0x4102e7f8 in __libc_start_main () from /lib/tls/libc.so.6
#11 0x41150fcc in ?? () from /lib/tls/libc.so.6

Thursday, October 22, 2009

How to export/Import Tablespaces in Oracle

Oracle tablespace Export =>

01. Make sure you set the ORACLE_SID or TWO_TASK variable appropriately
02. Login with system/sys user as sysdba
03. Execute below command to find the tablespace you want to export
Select tablespace_name, file_name from dba_data_files;
04. Execute the below command to export the tablespace
exp system/admin tablespaces=ARSYSTEM file=ARSYSTEM.dmp

Oracle Tablespace Import =>
01. Make sure you set the ORACLE_SID or TWO_TASK variable appropriately
02. Login with system/sys user as sysdba
03. Create a dummy tablespace and user before importing the new tablespace with commands
1 In an SQL*Plus window, create the tablespace. For example:
create tablespace arsystem
datafile 'c:\qa\data\QATST\data\arsys.dbf' size 500M reuse;

2 Create a user. For example:
create user aradmin identified by AR#Admin#
default tablespace arsystem
temporary tablespace temp
quota unlimited on arsystem;

3 Create a role for the user you created. For example:
create role ARole_arsys not identified;

4 Set the privileges for the role. For example:
grant alter session, create cluster, create database link, create
sequence, create session, create synonym, create table, create
view, create procedure, create trigger, query rewrite to
ARole_arsys;

5 Grant the role to the user. For example:
grant ARole_arsys to aradmin;

04. Execute the below command to import the tablespace

imp system/admin tablespaces=ARSYSTEM file=ARSYSTEM.dmp FROMUSER=ARADMIN TOUSER=ARADMIN

Granting X-Window acces to your PC using Cygwin or ReflectionX or HummingBird Exceed:

  1. Edit file: /etc/X11/xdm/Xaccess

Change from:
# * #any host can get a login window

To:
* #any host can get a login window

  1. Edit file: /etc/X11/xdm/xdm-config

Change last line from:
DisplayManager.requestPort: 0

To:
!DisplayManager.requestPort: 0


  1. Edit file: /etc/X11/gdm/gdm.conf

Change last line from:
[xdmcp]
Enable=false

To:
[xdmcp]
Enable=true


  1. Restart X-Windows

[root]# init 3
[root]# init 5

For RHEL 5


Remote Graphical Desktops and XDMCP


If you have installed the X Window System and would like to log in to your Red Hat Enterprise Linux system using a graphical login manager, enable the X Display Manager Control Protocol (XDMCP). This protocol allows users to remotely log in to a desktop environment from any X Window System compatible client (such as a network-connected workstation or X terminal). To enable remote login using XDMCP, edit the following line in the /etc/gdm/custom.conf file on the Red Hat Enterprise Linux system with a text editor such as vi or nano:


Add the line Enable=true , save the file, and exit the text editor. Switch to runlevel 5 to start the X server:

/sbin/init 5