When troubleshooting a performance problem or investigating oracle internal using dynamic tracing tools like systemtap,it’s often useful to have the session address at hand. In fact, having the session address we can access many useful information such as : wait_event,p1 and p2 value,sql_id,and many other fields as stored in X$KSUSE (underlying table to V$SESSION). Luca Canali have already done a great work ,he identified that when the function “kskthewt” is called at the end of a wait event the register R13 (tested with Oracle 18.104.22.168 on RHEL6.5 and with Oracle 22.214.171.124 on OEL7 respectively) is pointing to the session addr with some offset and he manged also to determine the offset of the different column of X$KSUSE using X$KQFCO and X$KQFTA as in here.
The question is : Can we determine the session address without probing any function call ?
One way to answer this question is to determine how the value stored in the register R13 was set in the function “kskthewt”. Time to disassemble !
NOTE : This post contain no disassembly code of the oracle executable just the finding !
For basic info on reverse engineering please take look at my previous post.
Test env : OEL 6 / UEK4
First i will begin by checking oracle 126.96.36.199 :
After examining the disassembled code of the function “kskthewt” and it’s parent function “kslwtectx” i was able to determine that the value stored in the register R13 is based on the global structure “ksupga_” with some offset.
Using the readelf utility to check the symbol table :
ksupga_ is defined in section 29 which correspond to the .bss (non-initialized variables) section :
Using gdb or any other dynamic tracing tools we can easily access the session address using this global symbol (At address 0xc0f1b40):
=> “ksupga_+24” point to the session address (0xa17eeb70) ! (The offset was also determined from the disassembly code)
Let’s now check oracle 188.8.131.52.6 :
Checking the symbol table using readelf utility :
The symbol is defined in another section 21 which is .tbss !
The symbol is now defined as a thread-local variable in the Thread Local Storage (TLS) (Every thread gets its own copy of the variable) .
“Instead of putting variables in sections .data and .bss for initialized and uninitialized data respectively, thread-local variables are found in .tdata and .tbss” ELF Handling For Thread-Local Storage
This appear to be the consequence of the implementation of the multithreaded Oracle model (threaded_execution) !
Consequently, the variable is accessed differently using the Segment register fs and some offset.For more info :
Basically,the variable is now accessed at a fixed offset “-0x6ea0” from the Segment register fs:0x0 which is actually the same as the thread pointer.Using GDB or any dynamic tracing tool we can determine the session address :
=> Using “info thread” we can determine the thread pointer (0x7f40aa0d2260).We have then to add the offset of the specified variable and that’s it ! We have now our session address (0xb1df5348) !
Accessing the process address is left as an exercise to the reader 🙂
That’s it 😀