Why does a printf() stop a crash from occuring? - debugging

I have been looking all over the Internet for an answer to this question (see subject of post). I have been asked this exact question twice. Once at an interview for company and once by a friend and I cannot find the answer for the life of me.
I have actually experienced this error on multiple occasions when debugging without a debugger, and just using print statements to isolate the error. I cannot recall any exact situations, though I am positive I have experienced it. If anyone can provide a link or a reference or point me to something in printf() source that might cause an error to stop occurring when using print statements to debug code I would greatly appreciate the good read.
Thank you,
Matthew Hoggan
I am currently reading the link provided but for further conversation I have posted some of my weak attempts to investigate:
Okay, so i have started to play around myself to try and answer my own question but things are still not 100% clear to me. Below is the output from the g++ compiler using the -S option to output the assembly instead of the executable. The equivalent C++ code is also posted below. My goal is to try and recreate a simple scenario and then try and detect based on the instructions what might be happening at the processor levels. So lets say right after the "call printf" assembly code, which I am assuming is linked from the library files stored in /usr/lib or another lib directory, I tried to access a NULL pointer (not in code), or some other form of operation that would traditionally crash the program. I am assuming that I would have to find out what printf is doing instruction wise to get a deeper look into this?
.file "assembly_test_printf.cpp"
.section .rodata
.LC0:
.string "Hello World"
.text
.globl main
.type main, #function
main:
.LFB0:
.cfi_startproc
.cfi_personality 0x0,__gxx_personality_v0
pushl %ebp
.cfi_def_cfa_offset 8
movl %esp, %ebp
.cfi_offset 5, -8
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
movl $0, 28(%esp)
movl $.LC0, (%esp)
call printf
movl 28(%esp), %eax
leave
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
.section .note.GNU-stack,"",#progbits
Equivalent C++ code:
#include <stdio.h>
int main ( int argc, char** argv ) {
int x = 0;
printf ("Hello World");
return x;
}

There are several reasons adding a printf() can change the behavior of a bug. Some of the more common ones might be:
changing the timing of execution (particularly for threading bugs)
changing memory use patterns (the compiler might change how the stack is used)
changing how registers are used
For example, an uninitialized local variable might be allocated to a register. Before adding the printf() the uninitialized variable is used and gets come garbage value that's in the register (maybe the result of a previous call to rand(), so it really is indeterminate). Adding the printf() causes the register to be used in printf() and printf() always happens to leave that register set to 0 (or whatever). Now your buggy program is still bugy, but with different behavior. And maybe that behavior happens to be benign.

I've seen it before, for example in Java, in cases where initialization code isn't complete when another thread attempts to access an object assumed to have already been created. The System.out.println() slows down the other thread enough for the initialization to complete.

Related

Why is an empty function not just a return

If I compile an empty C function
void nothing(void)
{
}
using gcc -O2 -S (and clang) on MacOS, it generates:
_nothing:
pushq %rbp
movq %rsp, %rbp
popq %rbp
ret
Why does gcc not remove everything but the ret? It seems like an easy optimisation to make unless it really does something (seems not to, to me). This pattern (push/move at the beginning, pop at the end) is also visible in other non-empty functions where rbp is otherwise unused.
On Linux using a more recent gcc (4.4.5) I see just
nothing:
rep
ret
Why the rep ? The rep is absent in non-empty functions.
Why the rep ?
The reasons are explained in this blog post. In short, jumping directly to a single-byte ret instruction would mess up the branch prediction on some AMD processors. And rather than adding a nop before the ret, a meaningless prefix byte was added to save instruction decoding bandwidth.
The rep is absent in non-empty functions.
To quote from the blog post I linked to: "[rep ret] is preferred to the simple ret either when it is the target of any kind of branch, conditional (jne/je/...) or unconditional (jmp/call/...)".
In the case of an empty function, the ret would have been the direct target of a call. In a non-empty function, it wouldn't be.
Why does gcc not remove everything but the ret?
It's possible that some compilers won't omit frame pointer code even if you've specified -O2. At least with gcc, you can explicitly tell the compiler to omit them by using the -fomit-frame-pointer option.
As explained here: http://support.amd.com/us/Processor_TechDocs/25112.PDF, a two-byte near-return instruction (i.e. rep ret) is used because a single-byte return can me mispredicted on some on some amd64 processors in some situations such as this one.
If you fiddle around with the processor targeted by gcc you may find that you can get it to generate a single-byte ret. -mtune=nocona worked for me.
I suspect early, your last code is a bug. As johnfound says. The first code is because all C Compiler must always follow _cdecl calling convention that in function means (In Intel, sorry, I don't know the AT&T Syntax):
Function Definition
_functionA:
push rbp
mov rbp, rsp
;Some function
pop rbp
ret
In caller :
call _functionA
sub esp, 0 ; Maybe if it zero, some compiler can strip it
Why GCC is always follow _cdecl calling convention when not following that is nonsense, that is the compiler isn't smarter that the advanced assembly programmer. So, it always follow _cdecl at all cost.
That is, because even so called "optimization compilers" are too dumb to generate always good machine code.
They can't generate better code than their creators made them to generate.
As long as an empty function is nonsense, they probably simply didn't bother to optimize it or even to detect this very special case.
Although, single "rep" prefix is probably a bug. It does nothing when used without string instruction, but anyway, in some newer CPU it theoretically can cause an exception. (and IMHO should)

Why does GCC add assembly commands to my inline assembly?

I'm using Apple's llvm-gcc to compile some code with inline assembly. I wrote what I want it to do, but it adds extraneous commands that keep writing variables to memory. Why is it doing this and how can I stop it?
Example:
__asm__{
mov r11, [rax]
and r11, 0xff
cmp r11, '\0'
}
becomes (in the "assembly" assistant view):
mov 0(%rax), %r11 // correct
movq %r11, -104(%rbp) // no, GCC, obviously wrong
and $255, %r11
movq %r11, -104(%rbp)
cmp $0, %r11
Cheers.
You need to use GCC's extended asm syntax to tell it which registers you're using as input and output and which registers get clobbered. If you don't do that, it has no idea what you're doing, and the assembly it generates can easily interfere with your code.
By informing it about what your code is doing, it changes how it does register allocation and optimization and avoids breaking your code.
it's because gcc tries to optimize your code. you can prevent optimizations by adding -O0 to command-line.
Try adding volatile after __asm__ if you don't want that. That additional commands are probably part previous/next C instructions. Without volatile compiler is allowed to do this (as it probably executes faster this way - not your code, the whole routine).

How to write assembly language hello world program for 64 bit Mac OS X using printf?

I am trying to learn writing assembly language for 64 bit Mac OS. I have no problem with 32 bit Mac OS and both 32 bit and 64 bit Linux.
However, Mac OS 64 bit is different and I couldn't figure out. Therefore I am here to ask for help.
I have not problem using system call to print. However, I would like to learn how to call C functions using 64 bit assembly language of Mac OS.
Please look at the following code
.data
_hello:
.asciz "Hello, world\n"
.text
.globl _main
_main:
movq $0, %rax
movq _hello(%rip), %rdi
call _printf
I use
$ gcc -arch x86_64 hello.s
to assemble and link.
It generates binary code. However, I got a segmentation fault when running it.
I tried adding "subq $8, %rsp" before calling _printf, still the same result as before.
What did I do wrong?
By the way, is that any way to debug this code on Mac? I tried adding -ggdb or -gstab or -gDWARF, and
$gdb ./a.out, and can't see the code and set break points.
You didn't say exactly what the problem you're seeing is, but I'm guessing that you're crashing at the point of the call to printf. This is because OS X (both 32- and 64-bit) requires that the stack pointer have 16-byte alignment at the point of any external function call.
The stack pointer was 16-byte aligned when _main was called; that call pushed an eight-byte return address onto the stack, so the stack is not 16-byte aligned at the point of the call to _printf. Subtract eight from %rsp before making the call in order to properly align it.
So I went ahead and debugged this for you (no magic involved, just use gdb, break main, display/5i $pc, stepi, etc). The other problem you're having is here:
movq _hello(%rip), %rdi
This loads the first eight bytes of your string into %rdi, which isn't what you want at all (in particular, the first eight bytes of your string are exceedingly unlikely to constitute a valid pointer to a format string, which results in a crash in printf). Instead, you want to load the address of the string. A debugged version of your program is:
.cstring
_hello: .asciz "Hello, world\n"
.text
.globl _main
_main:
sub $8, %rsp // align rsp to 16B boundary
mov $0, %rax
lea _hello(%rip), %rdi // load address of format string
call _printf // call printf
add $8, %rsp // restore rsp
ret

Using Assembly On Mac

I'm using a MacBook Pro with an Intel Core 2 Duo processor at 2.53 GHz, but I was told Mac users must follow AT&T syntax (which adds to my confusion since I am running Intel) and x86 (not sure what this means exactly).
So I need to get into assembly but am finding it very hard to even begin. Searches online show assembly code that varies greatly in syntax and I can't find any resources that explain basic assembly how-tos. I keep reading about registers and a stack but don't understand how to look at this. Can anyone explain/point me in the right direction? Take, for example, this code which is the only code I found to work:
.data
_mystring: .ascii "Hello World\n\0" #C expects strings to terminate with a 0.
.text
.globl _foo
_foo:
push %ebp
mov %esp,%ebp
pushl $_mystring
call _myprint
add $4,%esp
pop %ebp
ret
Very simple but what is it saying? I am having a confusing time understanding how this code does what it does. I know Java, PHP, and C, among other languages, but this, the steps and syntax of it, isn't clear to me. Here's the main file to go with it:
#include <stdio.h>
void foo();
void myprint(char *s)
{printf("%s", s);}
main()
{foo();}
Also, there's this which just multiplies numbers:
.data
.globl _cntr
_cntr: .long 0
.globl _prod
_prod: .long 0
.globl _x
_x: .long 0
.globl _y
_y: .long 0
.globl _mask
_mask: .long 1
.globl _multiply
multiply:
push %ebp
mov %ebp,%esp
mov $0,%eax
mov _x,%ebx
mov _y,%edx
LOOP:
cmp $0,%ebx
je DONE
mov %ebx,%ecx
and $1,%ecx
cmp $1,%ecx
jne LOOPC
add %edx,%eax
LOOPC:
shr $1,%ebx
shl $1,%edx
jmp LOOP
DONE:
pop %ebp
ret
and the main.c to go with it:
#include <stdio.h>
extern int multiply();
extern int x, y;
int main()
{
x = 34;
y = 47;
printf("%d * %d = %d\n", x, y, multiply());
}
And finally three small questions:
What is the difference between .s and .h file names (I have both a main.c and main.h, which one is for what)?
And why does assembly need a main.c to go with it/how does it call it?
Can anyone recommend a good assembly IDE like Eclipse is for Java or PHP
Thanks to whomever answers (this is actually my first post on this site), I've been trying to figure this out for a few days and every resource I have read just doesn't explain the assembly logic to me. It says what .data or .text does but only someone who knows how to "think assembly" would understand what they mean?
Also, if anyone is around New York City and feels very comfortable with Assembly and C I would love some private lessons. I feel there is a lot of potential with this language and would love to learn it.
Assembly language is a category of programming languages which are closely tied to CPU architectures. Traditionally, there is a one-to-one correspondence between each assembly instruction and the resulting CPU instruction.
There are also assembly pseudo-instructions which do not correspond to CPU instruction, but instead affect the assembler or the generated code. .data and .text are pseudo-instructions.
Historically, each CPU manufacturer implemented an assembly language as defined by their assembler, a source code translation utility. There have been thousands of specific assembly languages defined.
In modern times, it has been recognized that each assembly language shares a lot of common features, particularly with respect to pseudo-instructions. The GNU compiler collection (GCC) supports essentially every CPU architecture, so it has evolved generic assembly features.
x86 refers to the Intel 8086 family (8088, 8086, 8087, 80186, 80286, 80386, 80486, 80586 aka Pentium, 80686 aka Pentium II, etc.)
AT&T syntax is a notation style used by many assembly language architectures. A major feature is that instruction operands are written in the order from, to as was common historically. Intel syntax uses to, from operands. There are other differences as well.
As for your many questions, here are some resources which will 1) overwhelm you, and 2) eventually provide all your answers:
assembly language overview
tutorials and resources
x86 instruction summary
comprehensive x86 architecture reference
Ordinarily, an introductory assembly language programming class is a full semester with plenty of hands-on work. It assumes you are familiar with the basics of computer architecture. It is reasonable to expect that understanding the above material will take 300-500 hours. Good luck!

GCC with the -fomit-frame-pointer option

I'm using GCC with the -fomit-frame-pointer and -O2 options. When I looked through the assembly code it generated,
push %ebp
movl %esp, %ebp
at the start and pop %ebp at the end is removed. But some redundant subl/addl instructions to esp is left in - subl $12, %esp at the start and addl $12, %esp at the end.
How will I be able to remove them as some inline assembly will jmp to another function before addl is excecuted.
You probably don't want to remove those -- that's usually the code that allocates and deallocates your local variables. If you remove those, your code will trample all over the return addresses and such.
The only safe way to get rid of them is not to use any local variables. Even in macros. And be really careful about inline functions, as they often have their own locals that'll get put in with yours. You may want to consider explicitly disabling function inlining for that section of code, if you can.
If you're absolutely sure that the adds and subs aren't needed (and i mean really, really sure), on my machine GCC apaprently does some stack manipulation to keep the stack aligned at 16 byte boundaries. You may be able to say "-mpreferred-stack-boundary=2", which will align to 4-byte boundaries -- which x86 processors like to do anyway, so no code is generated to realign it. Works on my box with my GCC; int main() { return 0; } turned into
main:
xorl %eax, %eax
ret
but the alignment code looked different to start with...so that may not be the problem for you.
Just so you're warned: optimization causes a lot of weird stuff like that to happen. Be careful with hand-coded assembler language and optimized <insert-almost-any-language-here> code, especially when you're doing something as unstructured as a jump from the middle of one function into another.
I solved the problem by giving a function prototype, then defining it manually like this:
void my_function();
asm (
".globl _my_function\n"
"_my_function:\n\t"
/* Assembler instructions go here */
);
Later I also wanted the function to be exported, so I added this at the end of the source file:
asm (
".section .drectve\n\t"
".ascii \" -export:my_function\"\n"
);
How will I be able to remove them as some inline assembly will jmp to another function before addl is executed.
This will corrupt your stack, that caller expects the stack pointer
to be corrected on function return. Does the other function return
by ret instruction? What exactly do you try to achieve? maybe there's another solution possible?
Please, show us the lines around the function call (in the caller) and your
entry/exit part of your function in question.

Resources