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