IBM Support

== DEBUGGING CORE FILES [05] == STACK TRACE <-> SOURCE CODE

Technical Blog Post


Abstract

== DEBUGGING CORE FILES [05] == STACK TRACE <-> SOURCE CODE

Body


== DEBUGGING CORE FILES [05] == STACK TRACE <-> SOURCE CODE

We know now what is a stack trace, what help it can provide and how
to read it. When a program is compiled with -g the stack trace will
usually contain the line number in the source file. In that case it
is quite easy to find the exact location in the source.

It becomes a bit more complicated when the program was not compiled
with -g and most of the time this is the case. To add to this many
other things can make your quest even harder, to name a few only:
static functions, C++, AIX FDPR and so on...

Let's take a few examples:

  - If function 'f1()' calls 'f2()' at only one place in the source
    code, then no possible confusion. You can spot the call quite easily.

  - If function 'f1()' calls 'f2()' from different location in the source
    then things become a bit more complicated and looking at the assembly
    will be the only way to spot the accurate location of the call in
    the source.

  - If this is the last line of the source, as we mentioned before, the
    address you'll see in the stack trace will be the address of the
    instruction at the time of the trap. So here again no other choice but
    looking at the assembly.

  - Sometimes the core file might have been generated while the program
    was executing an instruction in some system library for which you
    won't have the source code. Most of the time this is because the
    arguments passed to the function were incorrect. So the idea here
    would be to locate that call in your program for which you do have
    the source code.

One doesn't need to be an expert in assembly to follow things but most
likely the first times you'll do it you'll need someone to answer the
multiple questions you'll probably have. But the more you do it the easier
it will become.

When you have to match assembly with source code one of the things you
want to do is find some 'easy things' to locate. Those would for example
be literal number assignment like 'i = 673' because you would see the
value '673' in the assembly output. Another example would be a 'printf'
because the core file would contain the 'format' string and it would
be quite easy to locate.

Now the question is where do we start?

Well, the top line of the stack trace will provide the address of
the instruction that was executing when the core file was generated.
It can also be found in the special register that holds the current
instruction address. The name of that register varies with the
platform you are running on:

  AIX      : 'iar'
  LINUX X86: 'rip'
  SOLARIS  : 'pc'

For viewing the value of the registers in the debugger you can use:

  AIX      : dbx - (dbx) registers
  LINUX X86: gdb - (gdb) info regs
  SOLARIS  : dbx - (dbx) regs

Also, something that might come handy (though we'll speak of it in more
details later) is the name of the registers used to pass arguments to
functions:

  AIX      : $r3 to $r10 (arg0 to arg7)
  LINUX X86: $rdi, $rsi, $rdx, $rcx, $r8, $r9 (arg0 to arg5)
  SOLARIS  : $o0 to $o5 (arg0 to arg5)


[{"Business Unit":{"code":"BU058","label":"IBM Infrastructure w\/TPS"},"Product":{"code":"SSEPGG","label":"Db2 for Linux, UNIX and Windows"},"Component":"","Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"","Edition":"","Line of Business":{"code":"LOB10","label":"Data and AI"}}]

UID

ibm13286071