When to use the assembly to debug a c/c++ program?
Does it help to learn some assembly to debug programs?
When to use the assembly to debug a c/c++ program?
Does it help to learn some assembly to debug programs?
Unless you suspect the compiler, I wouldn't go low-level for debugging. Best to debug at the same level of abstraction as you are expressing your intent in the algorithm.
If you write the code in C/C++ then use a good C/C++ debugger to go with it.
It may help with some of the advanced stuff, and it always helps to understand what's going on "under the hood". But unless you're doing assembly coding anyway (and if you were, you'd know assembly), debugging with assembly is probably overkill. Bugs will probably be directly in your code, and not in the translation between your code and assembly.
I presume you are asking when to use a dis-assembly when you want to debug your C/C++ written code.
There will be cases when you suspect that the compiler has not generated the code as you would have wanted it to. Typically, when the optimized version of the executable does not operate correctly but the un-optimized form works well. You would want to check the dis-assembly then to see what optimization has changed the behavior.
Another case would be when you want to understand the executable behavior but you do not have the source code to start with -- this is called reverse engineering. You have no options but to work with the dis-assembly of the executable.
A Wiki reference of dis-assembly and analysis tools for understanding the tools and start learning the one most suitable to your environment.
I can't tell you "When" but sometimes you can have weird C/C++ behavior and you really don't understand what's going on... Just look at the asm code, it will never betray you.
But here I check the ASM code of my C programs all the time... for Optimization , curiosity and learning purposes.
By all means learn x86 assembly language!
I've definitly fallen back to reading the assembly a few times. GCC makes it fairly convenient.
One good example is the subject of one of my questions. GCC changed behavior between 2.95 and 3.4.3, and going to the assembly in the suspect function explained why my program was crashing.
It's also useful on those occasions when you really need to know how certain accesses are being done. If you have memory mapped onto a bus, for example, you might want to know that you are doing a 16 bit access instead of a 32 bit access.
Another case I've been using assembly for lately is to check that my 'volatile' variables really are being treated as volatile. It turns out that almost all compilers get this wrong sometimes, so I've started checking the output of specific cases to ensure that the assembly actually references the memory location instead of some register.
The reason assembly can help to debug a program is that gcc often optimizes for you. You have to look through the assembly for any "improvements" by gcc and make sure they don't screw things up.
For example
/* global */
int x = 1;
void *myFunc() {
/* do something productive */
x = 0;
return NULL;
}
int main() {
thread_create(myFunc);
while(x) continue;
exit(1);
}
Under certain optimizations, while(x) continue;
becomes a jmp 0xDEADBEEF
(where 0xDEADBEEF
is the jmp
instruction). You can see this in the assembly, and know to change x to volatile.
Otherwise, assembly is likely to hurt you in terms of understanding anything.
It can be very helpful in cases where you can not (yet) reliably reproduce a bug, such as due to heap/stack corruption. You might get one or two core dumps, quite possibly from a customer. Even assuming your debugger is reliable, looking at assembly can tell you exactly which instruction is crashing (and thus which piece of memory is corrupted).
Furthermore, in my experience (primarily in kernel debugging) the debuggers have been relatively bad at dealing with optimized code. They get things like parameters/etc wrong, and to really tell what's going on I need to look at diassembly.
If I can reproduce a problem reliably/easily it doesn't tend to be as helpful to deal with disassembly, because I'll get more information from just stepping through the program. On the other hand, getting to the point where you can reproduce a problem is usually more than halfway to fixing it.
In some circumstances you have no choice but to revert to assembler. If your system crashes and all you have is a core dump or stack trace with few symbols then staring at the high level source code is not going to get you very far.
I think that memory dumps are much more useful at debugging than learning assembler to do so. With visual studio for example you can check which memory location change after a particular line of code. The shortcut key is ALT-6 while in debug mode. You can get variable locations by using the standard watches.
I have has some use for my assembly skills searching for bugs that was cause by a new release of the compiler we were using. But compiler bugs are very rare so my answer would be no not for debugging.
It is interesting to look at how the compiler solves a problem in assembly from your source but that is not really debugging.
I think you will need to learn assembly some time or the other. Knowing assembly is the only way out if a bug is reproducible in a release build only or while debugging a third party library where you don't have the source code. There are more reasons to learn assembly than not to.
You may also want to have a look at my recent articles on debugging in assembly better - http://www.technochakra.com/assembly-and-the-art-of-debugging/
Update -> If you would like to change the behavior of your code at runtime without recompilation, then learning assembly is a must. Have a look at http://www.technochakra.com/debugging-modifying-code-at-runtime/
It's useful for debugging optimized release builds; in particular, when a customer sends you a minidump from your application out in the field. In these cases many debuggers are quite weak at keeping track of local variables, and you have to go fish them out of the stack (or registers) by hand.