{"id":2842,"date":"2019-08-21T20:17:17","date_gmt":"2019-08-21T20:17:17","guid":{"rendered":"https:\/\/nenadnoveljic.com\/blog\/?p=2842"},"modified":"2019-08-21T20:21:24","modified_gmt":"2019-08-21T20:21:24","slug":"tracking-arguments-gdb","status":"publish","type":"post","link":"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/","title":{"rendered":"Tracking Arguments with gdb"},"content":{"rendered":"<h1>DTrace<\/h1>\n<p>Being able to track function arguments is essential for in-depth troubleshooting and researching software internals. DTrace makes this extremely easy, because all of the arguments are exposed through the variables <i>arg0, arg1, arg2,<\/i> etc. in the function entry probe.<\/p>\n<p>I&#8217;m going to use the following C program from <a href=\"https:\/\/beginners.re\/RE4B-EN.pdf\">[Yurichev 2013]<\/a> for demonstration purposes:<\/p>\n<pre><code>#include &lt;stdio.h&gt;\n\nvoid f1(int a1, int a2, int a3, int a4, int a5, int a6, int a7)\n{\n  printf (\"%d %d %d %d %d %d %d\\n\", a1, a2, a3, a4, a5, a6, a7);\n};\n\nint main()\n{\n  f1(1,2,3,4,5,6,7);\n};<\/code><\/pre>\n<p>I compiled it with gcc:<\/p>\n<pre><code>gcc f1.c -o f1<\/code><\/pre>\n<p>As you can see, capturing arguments is really trivial with DTrace:<\/p>\n<pre><code>sudo -u root \/usr\/sbin\/dtrace -qn 'pid$target::f1:entry{ printf(\"%d %d %d %d %d %d %d \\n\",arg0,arg1,arg2,arg3,arg4,arg5,arg6);}' -p PID\n1 2 3 4 5 6 7 <\/code><\/pre>\n<p>gdb is an alternative where DTrace isn&#8217;t available. However, the complexity increases when the debugging information is stripped, which is rather common with proprietary software. To show how to track arguments under such circumstances, I&#8217;m going to disassemble the compiled C program and observe how the arguments get passed around. Dennis Yurichev explained this reverse engineering technique in <a href=\"https:\/\/beginners.re\/RE4B-EN.pdf\">[Yurichev 2013]<\/a>.<\/p>\n<h1>Integers<\/h1>\n<p>Generally, the parameters can be passed in two ways: via CPU registers and stack. Which registers are used is precisely defined by calling conventions specific to CPU architecture and OS. The x86 calling conventions are, for instance, described in <a href=\"https:\/\/en.wikipedia.org\/wiki\/X86_calling_conventions\">[Wikipedia]<\/a>.The integers are passed via <i>rdi, rsi, rdx, rcx, r8<\/i> and <i>r9<\/i> registers on Linux and Solaris. Since only 6 parameters can be passed through these registers, the rest must be passed via stack. Disassembled <i>main<\/i> function indeed shows how these first 6 argument values are moved to the registers prior to calling the <i>f1<\/i> function:<\/p>\n<pre><code>0x0000000000400fc4 &lt;+0&gt;:     push   %rbp\n0x0000000000400fc5 &lt;+1&gt;:     mov    %rsp,%rbp\n0x0000000000400fc8 &lt;+4&gt;:     sub    $0x8,%rsp\n0x0000000000400fcc &lt;+8&gt;:     pushq  $0x7\n0x0000000000400fce &lt;+10&gt;:    <span style=\"color: red;\">mov    $0x6,%r9d<\/span>\n0x0000000000400fd4 &lt;+16&gt;:    <span style=\"color: red;\">mov    $0x5,%r8d<\/span>\n0x0000000000400fda &lt;+22&gt;:    <span style=\"color: red;\">mov    $0x4,%ecx<\/span>\n0x0000000000400fdf &lt;+27&gt;:    <span style=\"color: red;\">mov    $0x3,%edx<\/span>\n0x0000000000400fe4 &lt;+32&gt;:    <span style=\"color: red;\">mov    $0x2,%esi<\/span>\n0x0000000000400fe9 &lt;+37&gt;:    <span style=\"color: red;\">mov    $0x1,%edi<\/span>\n0x0000000000400fee &lt;+42&gt;:    callq  0x400f72 \n0x0000000000400ff3 &lt;+47&gt;:    add    $0x10,%rsp\n0x0000000000400ff7 &lt;+51&gt;:    mov    $0x0,%eax\n0x0000000000400ffc &lt;+56&gt;:    leaveq \n0x0000000000400ffd &lt;+57&gt;:    retq   <\/code><\/pre>\n<p>By the way, I&#8217;m using Franck Pachot&#8217;s one-liner for disassembling functions provided in <a href=\"https:\/\/blog.dbi-services.com\/12cr2-no-cardinality-feedback-for-small-queries\/\">[Pachot 2017]<\/a>:<\/p>\n<pre><code>gdb f1 &lt;&lt;&lt; \"disas main\"<\/code><\/pre>\n<p>Since the integer arguments fit into 32 bits they are passed via <i>edi, esi, edx, ecx, r8d<\/i> and <i>r9d<\/i> registers. All of those 32-bit registers exist for efficiently accessing the least significant 32 bits of the 64-bit registers <i>rdi, rsi, rdx, rcx, r8<\/i> and <i>r9<\/i>, respectively.<\/p>\n<p>Thus, we can display the first 6 integer arguments by printing the register values when the function <i>f1<\/i> is entered:<\/p>\n<pre><code>b f1 \nc\nThread 2 hit Breakpoint 1, 0x0000000000400f76 in f1 ()\n\nprintf \"%d, %d, %d, %d, %d, %d \\n\", $edi, $esi, $edx, $ecx, $r8d, $r9d \n1, 2, 3, 4, 5, 6 <\/code><\/pre>\n<h1>Stack<\/h1>\n<p>The 7th argument was pushed onto the stack prior to calling <i>f1<\/i>:<\/p>\n<pre><code>0x0000000000400fcc &lt;+8&gt;:     pushq  $0x7<\/code><\/pre>\n<p>Before retrieving the argument from the stack within <i>f1<\/i>, we have to know exactly how many values are on the stack in front of the argument.<\/p>\n<p>But first, let&#8217;s take a closer look at the addresses. Below is the disassembled <i>f1<\/i> function:<\/p>\n<pre><code>gdb f1 &lt;&lt;&lt; \"disas f1\"\n\n<span style=\"color: blue;\">0x0000000000400f72<\/span> &lt;+0&gt;:     push   %rbp\n0x0000000000400f73 &lt;+1&gt;:     mov    %rsp,%rbp\n<span style=\"color: brown;\">0x0000000000400f76<\/span> &lt;+4&gt;:     sub    $0x20,%rsp\n0x0000000000400f7a &lt;+8&gt;:     mov    %edi,%eax\n...<\/code><\/pre>\n<p>It&#8217;s worth noting that the function begins at the address <span style=\"color: blue;\">0x400f72<\/span>, but the breakpoint was set a couple of lines farther &#8211; at the address <span style=\"color: brown;\">0x400f76<\/span>:<\/p>\n<pre><code>info b\nNum     Type           Disp Enb Address            What\n1       breakpoint     keep y   <span style=\"color: brown;\">0x0000000000400f76<\/span> &lt;f1+4&gt;\n&lt;\/f1+4&gt;<\/code><\/pre>\n<p>The code fragment inbetween is the function prologue, which first saves the caller&#8217;s frame pointer (stored in <i>rbp<\/i>) on the stack and then creates callee&#8217;s frame by copying <i>rbp<\/i> into the stack pointer register <i>rsp<\/i>. Gustavo Duarte described this mechanism in detail in <a href=\"https:\/\/manybutfinite.com\/post\/journey-to-the-stack\/\">[Duarte 2014]<\/a>. Consequently, argument&#8217;s position on the stack relative to the stack pointer <i>rsp<\/i> will change after the prologue execution.<\/p>\n<p>The following picture illustrates the stack before and after the prologue execution:<\/p>\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"694\" height=\"396\" src=\"https:\/\/nenadnoveljic.com\/blog\/wp-content\/uploads\/2019\/08\/Stack-3.gif\" alt=\"\" class=\"wp-image-2875\"\/><\/figure>\n\n\n<p>When retrieving the argument, we have to exactly know where the program stopped. In our example gdb detected the prologue and set the breakpoint at its end. But this mechanism isn&#8217;t reliable, because gdb doesn&#8217;t always recognize the prologue. This can happen, for example, when some compiler optimizations are employed. Fortunately, we can enforce a break point at the function entry, i.e. before the prologue, by specifying <i>*<\/i> before the function name:<\/p>\n<pre><code>b *f1\nBreakpoint 1 at <span style=\"color: blue;\">0x400f72<\/span><\/code><\/pre>\n<p>Now the 7th argument can be safely retrieved from the second location on the stack:<\/p>\n<pre><code>x\/d $rsp+8\n0x7fffbffff930: 7<\/code><\/pre>\n<h1>Floating point<\/h1>\n<p>The floating point arguments are passed via <i>xmm0 &#8211; xmm7<\/i> registers.<\/p>\n<p>We can easily demonstrate this by converting the first argument to floating point:<\/p>\n<pre><code>#include &lt;stdio.h&gt;\n\nvoid f1(<span style=\"color: red;\">float<\/span> a1, int a2, int a3, int a4, int a5, int a6, int a7)\n{\n  printf (\"%f %d %d %d %d %d %d\\n\", a1, a2, a3, a4, a5, a6, a7);\n};\n\nint main()\n{\n  f1(1,2,3,4,5,6,7);\n};<\/code><\/pre>\n<p>The floating point value is stored as a constant on the location <span style=\"color: red;\">0x400d64<\/span> and loaded into the <i>xmm0<\/i> register.<\/p>\n<pre><code>\n0x0000000000400fce &lt;+0&gt;:     push   %rbp\n0x0000000000400fcf &lt;+1&gt;:     mov    %rsp,%rbp\n0x0000000000400fd2 &lt;+4&gt;:     mov    $0x7,%r9d\n0x0000000000400fd8 &lt;+10&gt;:    mov    $0x6,%r8d\n0x0000000000400fde &lt;+16&gt;:    mov    $0x5,%ecx\n0x0000000000400fe3 &lt;+21&gt;:    mov    $0x4,%edx\n0x0000000000400fe8 &lt;+26&gt;:    mov    $0x3,%esi\n0x0000000000400fed &lt;+31&gt;:    mov    $0x2,%edi\n0x0000000000400ff2 &lt;+36&gt;:    <span style=\"color: red;\">movss  -0x296(%rip),%xmm0        # 0x400d64<\/span>\n0x0000000000400ffa &lt;+44&gt;:    callq  0x400f72 \n0x0000000000400fff &lt;+49&gt;:    mov    $0x0,%eax\n0x0000000000401004 &lt;+54&gt;:    pop    %rbp\n0x0000000000401005 &lt;+55&gt;:    retq   \n   \nx\/f 0x400d64\n<span style=\"color: red;\">0x400d64:       1<\/span>\n<\/code><\/pre>\n<p>Expectedly, there aren&#8217;t any parameters passed via stack anymore as the other 6 parameters fit into the <i>r*<\/i> registers.<\/p>\n<p>The value of the first argument can be retrieved on the <i>f1<\/i> entry point as follows:<\/p>\n<pre><code>p $xmm0\n$1 = {<span style=\"color: red;\">v4_float = {1<\/span>, 0, 0, 0}, v2_double = {5.2635442471208903e-315, 0}, v16_int8 = {0, 0, -128, 63, 0 }, v8_int16 = {0, 16256, 0, 0, 0, 0, 0, 0}, v4_int32 = {1065353216, 0, 0, 0}, \n  v2_int64 = {1065353216, 0}, uint128 = 1065353216}<\/code><\/pre>\n<h1>Pointers<\/h1>\n<p>To demonstrate how to retrieve the variables passed by reference, I modified the C program to pass a pointer to a string as the first argument. Additionally, I added the 8th argument &#8211; also a pointer to a string &#8211; in order to show how to dereference pointers when passed in both ways: via register and via stack.<\/p>\n<pre><code>#include &lt;stdio.h&gt;\n#include &lt;stdint.h&gt;\n\nvoid f1(<span style=\"color: red;\">char* a1<\/span>, int a2, int a3, int a4, int a5, int a6, int a7, <span style=\"color: blue;\">char* a8<\/span>)\n{\n  printf (\"%s %d %d %d %d %d %d %s\\n\", a1, a2, a3, a4, a5, a6, a7, a8);\n};\n\nint main()\n{\n  uint64_t dummy = 1 ;\n  char *str1 = \"String 1\";\n  char *str2 = \"String 8\";\n  f1(str1,2,3,4,5,6,7,str2);\n};<\/code><\/pre>\n<p>We can see that for pointers the whole 64-bit <i>rdi<\/i> register is being used &#8211; as opposed to the least significant 32 bits referenced via <i>edi<\/i> when dealing with integers.<\/p>\n<pre><code>0x0000000000400fde &lt;+0&gt;:     push   %rbp\n0x0000000000400fdf &lt;+1&gt;:     mov    %rsp,%rbp\n0x0000000000400fe2 &lt;+4&gt;:     sub    $0x10,%rsp\n0x0000000000400fe6 &lt;+8&gt;:     <span style=\"color: red;\">movq   $0x400d65,-0x8(%rbp)<\/span>\n0x0000000000400fee &lt;+16&gt;:    <span style=\"color: blue;\">movq   $0x400d6e,-0x10(%rbp)<\/span>\n0x0000000000400ff6 &lt;+24&gt;:    <span style=\"color: red;\">mov    -0x8(%rbp),%rax<\/span>\n0x0000000000400ffa &lt;+28&gt;:    <span style=\"color: blue;\">pushq  -0x10(%rbp)<\/span>\n0x0000000000400ffd &lt;+31&gt;:    pushq  $0x7\n0x0000000000400fff &lt;+33&gt;:    mov    $0x6,%r9d\n0x0000000000401005 &lt;+39&gt;:    mov    $0x5,%r8d\n0x000000000040100b &lt;+45&gt;:    mov    $0x4,%ecx\n0x0000000000401010 &lt;+50&gt;:    mov    $0x3,%edx\n0x0000000000401015 &lt;+55&gt;:    mov    $0x2,%esi\n0x000000000040101a &lt;+60&gt;:    <span style=\"color: red;\">mov    %rax,%rdi<\/span>\n0x000000000040101d &lt;+63&gt;:    callq  0x400f82 \n0x0000000000401022 &lt;+68&gt;:    add    $0x10,%rsp\n0x0000000000401026 &lt;+72&gt;:    mov    $0x0,%eax\n0x000000000040102b &lt;+77&gt;:    leaveq \n0x000000000040102c &lt;+78&gt;:    retq   <\/code><\/pre>\n<p>Both string constants are stored at fix addresses:<\/p>\n<pre><code>(gdb) x\/s 0x400d65\n<span style=\"color: red;\">0x400d65:       \"String 1\"<\/span>\n(gdb) x\/s 0x400d6e\n<span style=\"color: blue;\">0x400d6e:       \"String 8\"<\/span><\/code><\/pre>\n<p>First, I&#8217;ll run the program and stop the execution after entering <i>f1<\/i>:<\/p>\n<pre><code>b *f1\nBreakpoint 1 at 0x400f82: file f1.c, line 5.\nr<\/code><\/pre>\n<p>The pointer to the first argument is passed via the <i>rdi<\/i> register, which we can simply dereference as follows:<\/p>\n<pre><code><span style=\"color: red;\">x\/s $rdi\n0x400d65:       \"String 1\"<\/span><\/code><\/pre>\n<p>The pointer to the string passed as the 8th argument, which is the second argument passed via stack, is stored on the third stack location. Therefore, it can be dereferenced as follows:<\/p>\n<pre><code><span style=\"color: blue;\">x\/s *(uint64_t *)($rsp+8+8)\n0x400d6e:       \"String 8\"<\/span><\/code><\/pre>\n<p>A side note: I had to include <i>stdint.h<\/i> header file and declare a <i>uint64_t<\/i> variable, just to be able to use <i>uint64_t<\/i> type when dereferencing the pointer in gdb. For the same reason, I additionally compiled the program with the <i>-g<\/i> option to include the symbol table:<\/p>\n<pre><code>gcc -g f1.c -o f1<\/code><\/pre>\n<h1>Tracing Oracle memory allocations<\/h1>\n<p>Finally, it&#8217;s time to do something useful, like, for example, trace Oracle memory allocations. These are performed within the Oracle C functions <i>kghalf, kghalo<\/i> and <i>kghalp<\/i>.<\/p>\n<p>Tanel Poder and Stefan Koehler have already written DTrace scripts for tracing their execution: <a href=\"https:\/\/github.com\/tanelpoder\/tpt-oracle\/blob\/master\/dtrace\/trace_kghal.sh\">trace_kghal.sh<\/a> and <a href=\"http:\/\/www.soocs.de\/public\/scripts\/dtrace_kghal_pga_code\">dtrace_kghal_pga_code<\/a>, respectively.<\/p>\n<p>By looking into their DTrace scripts, we can identify the following information of interest:<\/p>\n<ul>\n<li>heap name, whose pointer is stored in the location <i>arg2+76<\/i>,<\/li>\n<li>allocation reason, whose pointer is passed via <i>arg6<\/i> in <i>kghalf<\/i> and <i>kghalp<\/i>, and via <i>arg9<\/i> in <i>kghalo<\/i>.<\/li>\n<\/ul>\n<p>Knowing that, it&#8217;s fairly easy to come up with the gdb commands:<\/p>\n<pre><code>b *kghalf\ncommands 1\nsilent\nprintf \"kghalf: %s - %s \\n\", (char *)($rsi+76), (char *)($r9)\ncontinue\nend\n\nb *kghalp\ncommands 2\nsilent\nprintf \"kghalp: %s - %s \\n\", (char *)($rsi+76), (char *)($r9)\ncontinue\nend<\/code><\/pre>\n<p>Notice that kghalo recieves the allocation reason via <i>arg9<\/i> which is, therefore, passed via stack:<\/p>\n<pre><code>b *kghalo\ncommands 3\nsilent\nprintf \"kghalo: %s - %s \\n\", (char *)($rsi+76), (char *)(*(uint64_t *)($rsp+8+8+8))\ncontinue\nend<\/code><\/pre>\n<p>Optionally, you can set the following parameters for spooling the output into a file:<\/p>\n<pre><code>set pagination off\nset logging file kgh_allocations.log\nset logging on\n\nattach PID\nc\n\nset logging off<\/code><\/pre>\n<p>The sample output looks as follows:<\/p>\n<pre><code>...\nkghalo: SQLA^bf668378 - qbcqtcHTHeap \nkghalp: 13910.kgght - 13910.kgght \nkghalo: qbcqtcHTHeap - 13910.kgght \nkghalp: 13910.kgght - 13910.kgght \nkghalo: qbcqtcHTHeap - 13910.kgght \nkghalo: SQLA^bf668378 - qbcqtcHTHeap \nkghalo: sga heap - SQLA^bf668378 \nkghalf: qbcqtcHTHeap - 613.kggec \nkghalo: SQLA^bf668378 - qbcqtcHTHeap \nkghalp: 613.kggec - 613.kggec \nkghalo: qbcqtcHTHeap - 613.kggec \nkghalp: 613.kggec - 613.kggec \nkghalo: qbcqtcHTHeap - 613.kggec \nkghalo: SQLA^bf668378 - qbcqtcHTHeap \nkghalo: sga heap - SQLA^bf668378 \nkghalp: SQLA^bf668378 - qcpifqtqc : qcsidn \nkghalf: SQLA^bf668378 - qcpifqtqc : qcsidn \nkghalp: SQLA^bf668378 - frodef:qcpitnm \nkghalf: SQLA^bf668378 - frodef:qcpitnm \nkghalp: SQLA^bf668378 - idndef : qcuAllocIdn \nkghalf: SQLA^bf668378 - idndef : qcuAllocIdn \nkghalp: SQLA^bf668378 - idndef : qcuAllocIdn \nkghalf: SQLA^bf668378 - idndef : qcuAllocIdn \nkghalp: SQLA^bf668378 - chedef : qcuatc \nkghalf: SQLA^bf668378 - chedef : qcuatc \nkghalp: SQLA^bf668378 - qbpdef: qekbCreateQbp \nkghalf: SQLA^bf668378 - qbpdef: qekbCreateQbp \nkghalp: kxs-heap-c - opsdef: qcpipsh1 \nkghalp: kxs-heap-c - chedef : qcuatc \nkghalp: KGLH0^bf668378 - kgltbtab2 \nkghalo: KGLH0^bf668378 - kgltbtab \n...<\/code><\/pre>\n<h1>References<\/h1>\n<ul>\n<li><a href=\"https:\/\/beginners.re\/RE4B-EN.pdf\">[Yurichev 2013]<\/a> Dennis Yurichev. (2013). Reverse Engineering for Beginners (Understanding Assembly Language)<\/li>\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/X86_calling_conventions\">[Wikipedia]<\/a> Wikipedia. X86 calling conventions<\/li>\n<li><a href=\"https:\/\/blog.dbi-services.com\/12cr2-no-cardinality-feedback-for-small-queries\/\">[Pachot 2017]<\/a> Franck Pachot. (January 5, 2017). 12cR2: no cardinality feedback for small queries<\/li>\n<li><a href=\"https:\/\/manybutfinite.com\/post\/journey-to-the-stack\/\">[Duarte 2014]<\/a> Gustavo Duarte. (March 10, 2014). Journey to the Stack, Part I<\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>Tracking function arguments with gdb, with an example of tracing memory allocations in Oracle database <a href=\"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/\" class=\"more-link\">Continue Reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[27,5],"tags":[],"class_list":["post-2842","post","type-post","status-publish","format-standard","hentry","category-gdb","category-oracle"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Tracking Arguments with gdb - All-round Database Topics<\/title>\n<meta name=\"description\" content=\"Tracking function arguments with gdb, with an example of tracing memory allocations in Oracle database\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Tracking Arguments with gdb - All-round Database Topics\" \/>\n<meta property=\"og:description\" content=\"Tracking function arguments with gdb, with an example of tracing memory allocations in Oracle database\" \/>\n<meta property=\"og:url\" content=\"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/\" \/>\n<meta property=\"og:site_name\" content=\"All-round Database Topics\" \/>\n<meta property=\"article:published_time\" content=\"2019-08-21T20:17:17+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-08-21T20:21:24+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/nenadnoveljic.com\/blog\/wp-content\/uploads\/2019\/08\/Stack-3.gif\" \/>\n<meta name=\"author\" content=\"Nenad Noveljic\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@NenadNoveljic\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nenad Noveljic\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracking-arguments-gdb\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracking-arguments-gdb\\\/\"},\"author\":{\"name\":\"Nenad Noveljic\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\"},\"headline\":\"Tracking Arguments with gdb\",\"datePublished\":\"2019-08-21T20:17:17+00:00\",\"dateModified\":\"2019-08-21T20:21:24+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracking-arguments-gdb\\\/\"},\"wordCount\":1033,\"commentCount\":1,\"image\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracking-arguments-gdb\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/08\\\/Stack-3.gif\",\"articleSection\":[\"gdb\",\"Oracle\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracking-arguments-gdb\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracking-arguments-gdb\\\/\",\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracking-arguments-gdb\\\/\",\"name\":\"Tracking Arguments with gdb - All-round Database Topics\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracking-arguments-gdb\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracking-arguments-gdb\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/08\\\/Stack-3.gif\",\"datePublished\":\"2019-08-21T20:17:17+00:00\",\"dateModified\":\"2019-08-21T20:21:24+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\"},\"description\":\"Tracking function arguments with gdb, with an example of tracing memory allocations in Oracle database\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracking-arguments-gdb\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracking-arguments-gdb\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracking-arguments-gdb\\\/#primaryimage\",\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/08\\\/Stack-3.gif\",\"contentUrl\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/08\\\/Stack-3.gif\",\"width\":694,\"height\":396},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracking-arguments-gdb\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tracking Arguments with gdb\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/\",\"name\":\"All-round Database Topics\",\"description\":\"Nenad Noveljic\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\",\"name\":\"Nenad Noveljic\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"caption\":\"Nenad Noveljic\"},\"sameAs\":[\"nenad-noveljic-9b746a6\",\"https:\\\/\\\/x.com\\\/NenadNoveljic\"],\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/author\\\/nenad\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Tracking Arguments with gdb - All-round Database Topics","description":"Tracking function arguments with gdb, with an example of tracing memory allocations in Oracle database","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/","og_locale":"en_US","og_type":"article","og_title":"Tracking Arguments with gdb - All-round Database Topics","og_description":"Tracking function arguments with gdb, with an example of tracing memory allocations in Oracle database","og_url":"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/","og_site_name":"All-round Database Topics","article_published_time":"2019-08-21T20:17:17+00:00","article_modified_time":"2019-08-21T20:21:24+00:00","og_image":[{"url":"https:\/\/nenadnoveljic.com\/blog\/wp-content\/uploads\/2019\/08\/Stack-3.gif","type":"","width":"","height":""}],"author":"Nenad Noveljic","twitter_card":"summary_large_image","twitter_creator":"@NenadNoveljic","twitter_misc":{"Written by":"Nenad Noveljic","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/#article","isPartOf":{"@id":"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/"},"author":{"name":"Nenad Noveljic","@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa"},"headline":"Tracking Arguments with gdb","datePublished":"2019-08-21T20:17:17+00:00","dateModified":"2019-08-21T20:21:24+00:00","mainEntityOfPage":{"@id":"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/"},"wordCount":1033,"commentCount":1,"image":{"@id":"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/#primaryimage"},"thumbnailUrl":"https:\/\/nenadnoveljic.com\/blog\/wp-content\/uploads\/2019\/08\/Stack-3.gif","articleSection":["gdb","Oracle"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/","url":"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/","name":"Tracking Arguments with gdb - All-round Database Topics","isPartOf":{"@id":"https:\/\/nenadnoveljic.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/#primaryimage"},"image":{"@id":"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/#primaryimage"},"thumbnailUrl":"https:\/\/nenadnoveljic.com\/blog\/wp-content\/uploads\/2019\/08\/Stack-3.gif","datePublished":"2019-08-21T20:17:17+00:00","dateModified":"2019-08-21T20:21:24+00:00","author":{"@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa"},"description":"Tracking function arguments with gdb, with an example of tracing memory allocations in Oracle database","breadcrumb":{"@id":"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/#primaryimage","url":"https:\/\/nenadnoveljic.com\/blog\/wp-content\/uploads\/2019\/08\/Stack-3.gif","contentUrl":"https:\/\/nenadnoveljic.com\/blog\/wp-content\/uploads\/2019\/08\/Stack-3.gif","width":694,"height":396},{"@type":"BreadcrumbList","@id":"https:\/\/nenadnoveljic.com\/blog\/tracking-arguments-gdb\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/nenadnoveljic.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Tracking Arguments with gdb"}]},{"@type":"WebSite","@id":"https:\/\/nenadnoveljic.com\/blog\/#website","url":"https:\/\/nenadnoveljic.com\/blog\/","name":"All-round Database Topics","description":"Nenad Noveljic","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/nenadnoveljic.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa","name":"Nenad Noveljic","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","caption":"Nenad Noveljic"},"sameAs":["nenad-noveljic-9b746a6","https:\/\/x.com\/NenadNoveljic"],"url":"https:\/\/nenadnoveljic.com\/blog\/author\/nenad\/"}]}},"_links":{"self":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/2842","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/comments?post=2842"}],"version-history":[{"count":1,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/2842\/revisions"}],"predecessor-version":[{"id":2877,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/2842\/revisions\/2877"}],"wp:attachment":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/media?parent=2842"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/categories?post=2842"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/tags?post=2842"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}