zoukankan      html  css  js  c++  java
  • GDB---Oracle Function Call List

    http://yong321.freeshell.org/
    Oracle Function Call List

    1. Oracle function call list

    If you want to see what other functions a given function calls in software, you can disassemble the function. Inspired by Dennis Yurichev's Oracle function call list, which enumerates all functions in the modules inside $ORACLE_HOME/lib/libserver.a, I generate the function call list from $ORACLE_HOME/bin/oracle, with the script described in theAppendix. The result is

    apadrv
          1 apaqbdDescendents
          1 chnacc
          5 dbgdChkEventIntV
          5 dbgtCtrl_intEvalCtrlEvent
          1 dbgtCtrl_intEvalTraceFilters
          1 dbgtGrpB_int
          1 dbgtGrpE_int
          1 dbgtWrf_int
          1 dbkdChkEventRdbmsErr
    ...
    

    This means adbdrv calls apaqbdDescendents once, dbgdChkEventIntV 5 times, etc.

    To-do: search of my function call list result file.

    2. Event check list

    Unfortunately, the above function call list does not show the arguments passed to each function. One of the most useful functions in Oracle is dbkdChkEventRdbmsErr (probably DB kernel debug check event of RDBMS error), which requires one argument, the RDBMS event number. With a little more effort, we can find what event a given function checks by extracting the argument passed to the said function. The result is

    ELMAINT: 37393
    GELErase: 37397
    Java_oracle_xdb_spi_XDBNamingEnumeration_closeKprbNative: 31150
    ...
    apadrv: 10507
    apaqba: 10137
    atbadd: 10851
    atbadd: 12498
    atbadd: 12498
    ...
    

    This means function ELMAINT will call dbkdChkEventRdbmsErr to check for event 37393, apadrv will check for event 10507, and so forth. Many RDBMS events are recorded or documented in $ORACLE_HOME/rdbms/mesg/oraus.msg and can be retrieved by oerr, e.g.,

    $ oerr ora 10507
    10507, 00000, "Trace bind equivalence logic"
    // *Cause:
    // *Action:
    

    This event makes sense because apadrv is the function that "drive(s) the access path selection for a SQL command" according to Bug 5584629 and many others. But be aware that not all events are documented. Event 37393 is one of them; you won't get anything by running oerr ora 37393.

    The above output also shows multiple lines for one function atbadd. My program sequentially generates these lines and show the same function name repeatedly, which makes the output of a simple grep command easier to read. In the case of atbadd, it checks RDBMS events 10851, 12498 and 12498 again.

    For your convenience, you can search my function-event result file given a function name or an event number:

      Enter a function or event number:  
      Enter a function or event number:  

    The search result is equivalent to a grep command run against your own result file, e.g. a search for event 10035 ("Write parse failures to alert log file"):

    $ grep 10035 oracle_func_evt.txt
    kksSetBindType: 10035
    ...
    kksfbc: 10035
    ...
    

    This means that functions kksSetBindType and kksfbc will check for event 10035. Prefix kks is for "Shared Cursor" according to oradebug doc component or "support for managing shared cursors/ shared sql" according to Doc 175982.1note1, and function kksfbc is to "find bound cursor" according to many bug reports.

    3. Summary

    Next time you see an Oracle function in the call stack in a trace file, or in the output of pstack pid, and wonder what it does, you can either disassemble it or check your event check list file (see Appendix). But if you want to see what other functions may call this function, the latter is the only option. This of course won't really tell you exactly what the function does, but at least you have one more tool to aid the guesswork.note1

    The second part of the work, event check list, is useful in that many events are documented. If a given function happens to check for an RDBMS event, it greatly helps decipher what this function does. In addition, if you're interested in a reverse search, i.e. finding all the functions that check for a specific event, you can do so as well.

    Appendix

    The code below is run on Linux and generates Oracle function call list:

    nm $ORACLE_HOME/bin/oracle | awk '/ [Tt] / {print $3}' | grep -v '.' > oracle.Txt.nm #extract global and local text symbols
    
    for i in $(<oracle.Txt.nm); do
     echo $i
     gdb -n -q -ex "disas $i" -ex q $ORACLE_HOME/bin/oracle | perl -nle 'print $1 if /(?:call|jmp)q .+ <([^+>]+)[+d>]+$/' | sort | uniq -c | grep -w -v "$i$"
    done > oracle_func.txt
    

    The nm line extracts global and local text (i.e. code) symbols from oracle binarynote2 and saves them into a file. Then gdb runs against the oracle binary for each symbol i.e. function from the file, and disassembles the function passed in. Perl extracts from the output just the last component on each line enclosed in angle brackets if the line contains callq or jmpq. After sorting and removing duplicates, the final output is stripped of the line with that symbol itself (i.e. ignore the lines that say this function calls itself in its code, which I'm not really interested in). The code will run for many hours, depending on the CPU speed. The output is saved in oracle_func.txt. You could remove | sort | uniq -c after the perl filter line if you don't want to see a summary with call counts.

    + Optimize with named pipes.

    To find out what event a function checks, the argument to function dbkdChkEventRdbmsErr must be extracted. The argument can be found in the direct output of disas command in gdb.

    (gdb) disas apadrv
    Dump of assembler code for function apadrv:
    ...
       0x0000000002a05394 <+6580>:  mov    $0x290b,%edi
       0x0000000002a05399 <+6585>:  callq  0xcc13110 <dbkdChkEventRdbmsErr>
    

    According to the x86-64 calling convention used by Linux, the first argument to the function is placed in the 64-bit register rdi, of which edi is the lower 32-bit. In case of function apadrv, the Oracle database event it checks is 0x290b (the value moved into edi) or 10507 in decimal

    In order to find the events a given function checks, the following code can be run.

    for i in $(<oracle.Txt.nm); do
     gdb -n -q -ex "disas $i" -ex q $ORACLE_HOME/bin/oracle | grep -B1 dbkdChkEventRdbmsErr | perl -nle "print '${i}: '.hex($1) if /x([0-9a-f]+),\%edi$/"
    done > oracle_func_evt.txt
    

    If you wish, you can append | sort | uniq -c to the perl line as done previously so as to remove duplicates and optionally show the count of checking a specific event.

    + Optimize with named pipes.

    Notes

    [note1] Oracle used to publish the document ORA-600 Lookup Error Categories (Doc ID 175982.1), which you can still find on the Internet. Many function prefixes are listed in the document.
    [note2] I exclude the symbols with dot in the names to simplify the work. If you include them, you have to put them in single quotes when passing to the gdb command, e.g.,disas '__intel_new_proc_init.A'. For the 12.1.0.2 oracle binary, there're 58 of them, which all seem to be interanl Intel CPU specific functions, including those like__svml_cbrt2_mask.A related to short vector math library.

     

  • 相关阅读:
    如何修改容器内的/etc/resolv.conf
    OpenShift DNS的机制
    OpenShift 容器日志和应用日志分离问题
    python办公自动化(一)PPTX
    python装饰器 语法糖
    一步一步FLASK(一)
    linux python 安装 pymssql
    定制flask-admin的主页
    复制pycharm虚拟环境
    离线安装pycharm数据库驱动
  • 原文地址:https://www.cnblogs.com/zengkefu/p/5455861.html
Copyright © 2011-2022 走看看