I am currently taking a course which requires me to write assembly code, to be precise x86-64 AT&T syntax assembly code. Below is a c file which contains the function definition of a function "bubble" whose assembly code I have to write.
#include<stdio.h>
#include<stdlib.h>
void bubble(int* arr, int len);
int main(){
int n;
scanf("%d", &n);
int* arr = malloc(sizeof(int)*n);
for (int i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
bubble(arr, n);
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
free(arr);
}
And below is the assembly code for the function bubble,
.global bubble
.text
bubble:
movq $-1, %rcx
.L1:
incq %rcx
movl 4(%rdi,%rcx,4), %eax
cmpl (%rdi,%rcx,4), %eax
jge .T1
movl (%rdi,%rcx,4), %eax
movl 4(%rdi,%rcx,4), %ebx
movl %eax, 4(%rdi,%rcx,4)
movl %ebx, (%rdi,%rcx,4)
.T1:
movq %rsi, %rax
subq %rcx, %rax
cmpq $0x2, %rax
jne .L1
.T2:
decq %rsi
cmpq $0x1, %rsi
jne bubble
ret
I simply compile with the command,
gcc bubble.c func.s
Now on just compiling as above and running, there are no errors and the program runs as expected (note - I am compiling and running on Ubuntu).
However, on compiling using
gcc bubble.c func.s -g -fsanitize=address
and running, I get the following error,
=================================================================
==654==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000001 (pc 0x55d713a2944e bp 0x7ffed345b730 sp 0x7ffed345b6a0 T0)
==654==The signal is caused by a WRITE memory access.
==654==Hint: address points to the zero page.
#0 0x55d713a2944e in main /mnt/c/Users/rudy/Desktop/CSO/test/bubble.c:6
#1 0x7fe6ec4b0d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#2 0x7fe6ec4b0e3f in __libc_start_main_impl ../csu/libc-start.c:392
#3 0x55d713a29124 in _start (/mnt/c/Users/rudy/Desktop/CSO/test/a.out+0x1124)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /mnt/c/Users/rudy/Desktop/CSO/test/bubble.c:6 in main
==654==ABORTING
On putting it into gcc, it runs fine and exits with
[Inferior 1 (process 685) exited normally]
and on using valgrind with command,
valgrind --leak-check=full ./a.out
it runs fine and exits with
==694==
==694== HEAP SUMMARY:
==694== in use at exit: 0 bytes in 0 blocks
==694== total heap usage: 3 allocs, 3 frees, 2,068 bytes allocated
==694==
==694== All heap blocks were freed -- no leaks are possible
==694==
==694== For lists of detected and suppressed errors, rerun with: -s
==694== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
So then why does address sanitizer give that segfault? Apologies if there are any issues with my question or formatting, this is my first question.
Your bubble function clobbers the %rbx register (modifies it without restoring its previous value before returning). This violates the Linux/SysV x86-64 calling conventions, which specify that %rbx is to be preserved by fuction calls. See What registers are preserved through a linux x86-64 function call, x86 Assembly - Why is [e]bx preserved in calling conventions?.
The simplest fix is just to use a different register that is designated as call-clobbered, such as %rdx. If you really want to use %rbx, then push %rbx at the top of your function, and pop %rbx just before returning.
As to why it crashes only when using AddressSanitizer: it appears that without ASAN, the compiled main code doesn't actually store any important value in %rbx across the function call; indeed it doesn't use %rbx at all. (Not too surprising for unoptimized compilation.) And I guess that the caller of main doesn't store a value there either. So no harm happens to result in that case. But when ASAN is switched on, %rbx is used by the instrumentation code that it adds. So we can't actually credit ASAN's rigorous checking for finding your bug; it's simply that enabling it changes the generated code in a way that happens to trigger it.
(Side bug: your bubble function will crash if passed an array of length 0 or 1.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With