Trying to run through GDB and keep getting a segmentation fault once the C main program enters the main function.
GDB Error:
Breakpoint 1, main () at binom_main.c:7
7 n=10;
(gdb) s
10 0;
(gdb) s
12 +){
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x00000000004005c4 in otherwise ()
(gdb)
I compiled the code as such:
as binom.s -o binom.o
gcc -S -Og binom_main.c
gcc -c binom_main.s
gcc binom_main.o binom.o -o runtimes
I'm trying to learn how to use GDB more efficiently here but segfaults like these are pretty ambiguous and limiting. Why is this segfault being caused the moment the function begins? Have I linked the two files incorrectly?
Main :
#include <stdio.h>
unsigned int result,m,n,i;
unsigned int binom(int,int);
int main(){
n=10;
i=0;
for (i=1; i<2;i++){
result = binom(n,i);
printf("i=%d | %d \n", i, result );
}
return 0;
}
Sub:
.text
.globl binom
binom:
mov $0x00, %edx #for difference calculation
cmp %edi, %esi #m=n?
je equalorzero #jump to equalorzero for returning of value 1
cmp $0x00, %esi #m=0?
je equalorzero
cmp $0x01, %esi #m=1?
mov %esi,%edx
sub %edi, %edx
cmp $0x01, %edx # n-m = 1 ?
je oneoronedifference
jmp otherwise
equalorzero:
add $1, %eax #return 1
call printf
ret
oneoronedifference:
add %edi, %eax #return n
ret
otherwise:
sub $1, %edi #binom(n-1,m)
call binom
sub $1, %esi #binom(n-1,m-1)
call binom
ret
When you use gdb to debug asm, look at the disassembly window as well as the source window. (e.g. layout asm / layout reg, and layout next until you get the combo of windows that you want.) See the bottom of the x86 tag wiki for some more tips and a link to docs.
You can use stepi (si) to step by instructions, not by C statements, while investigating a crash outside your asm, caused by it corrupting something before returning.
This looks like a bug:
sub $1, %edi #binom(n-1,m)
call binom
# at this point, %edi no longer holds n-1, and %esi no longer holds m.
# because binom clobbers them. (This is normal)
# as Jester points out, you also don't save the return value (%eax) from the first call anywhere.
sub $1, %esi #binom(n-1,m-1)
call binom
Another (minor?) bug is:
cmp $0x01, %esi #m=1?
# but then you never read the flags that cmp set
Another serious bug:
equalorzero:
add $1, %eax #return 1 # wrong: nothing before this set %eax to anything.
# mov $1, %eax # You probably want this instead
ret
Related
I have a __kernel_vsyscall error in a function that gives the correct output but the program can never get past it and gives a __kernel_vsyscall error.
C functions:
void f1(int* input, int* output, int nbElements);
Assembler function (GAS). I can't post the whole thing since it's for an assignment and I don't want someone to copy it.
f1:
push %ebp
mov %esp, %ebp
movl $0, %ecx
movl $0, %ebx
jmp for_loop1
for_loop1:
cmpl %ecx, 16(%ebp)
jb end
movl $0, %ebx
jmp for_loop2
for_loop2:
/*move input elements to output elements*/
cmpl %ecx, %ebx
jmp incr_2
incr_2:
addl $1, %ebx
cmpl %ebx, 16(%ebp)
jb incr_1
jmp for_loop2
incr_1:
addl $1, %ecx
jmp for_loop1
end:
addl $8, %esp
leave
ret
Error when the program terminated :
malloc(): invalid size (unsorted)
Aborted (core dumped)
Error when debugging with gdb with the coredump file :
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./program_name...
[New LWP 2634]
warning: Loadable section ".note.gnu.property" outside of ELF segments
Core was generated by `./program_name'.
Program terminated with signal SIGABRT, Aborted.
#0 0xf7f35ac9 in __kernel_vsyscall ()
I've tried looking at what is at address 0xf7f35ac9 and it returned -402652697, or another random value.
Local variables are at adresses around 0xff83b1fc, the values stored in the pointers are at adresses around 0x80cab30, the functions declared previously are at adresses around 0x8049fc4, and the stack has values around 0xffaddedc, so I have no idea where this is.
Thanks
I was able to fix the problem by changing
cmpl %ecx, 16(%ebp)
jb end
to
cmpl 16(%ebp), %ecx
jge end
same as with all the other comparisons. Looked around online and apparently the difference between jb/ja and jl/jg is that jb/ja is for unsigned comparison while jl/jg is for signed comparison, but I'm still not sure why this causes this error.
This is my assembly program add.s
.globl add
add:
movl 4(%esp), %eax
movl 8(%esp), %ebx
addl %ebx, %eax
ret
This is my C program. I am trying to call the assembly program from the C program.
#include <stdio.h>
int add(int a, int b);
int main() {
int res = add(5,6);
printf("%d",res);
return 0;
}
But the above code gives me a segmentation fault. What is causing this error and how do I fix it?
Assuming the cdecl calling convention, you are using the ebx register which is supposed not to be clobbered: its value has to be saved and then restored by the callee if it is going to be modified.
The caller assumes that ebx is not going to change by calling a function. Therefore if the callee modifies ebx it has to save it first and then restore it to its original value before returning from the function.
The registers eax, ecx and edx can be used without having to save them first and then restored. Therefore, I would recommend replacing ebx with edx in your code:
add:
movl 4(%esp), %eax
movl 8(%esp), %edx
addl %edx, %eax
ret
I'm trying to link assembly functions to a C code for exercise.
Here's my assembly function, written in x86 assembly:
.code32
.section .text
.globl max_function
.type max_function, #function
# i parametri saranno in ordine inverso a partire da 8(%ebp)
max_function:
pushl %ebp # save ebp
movl %esp, %ebp # new frame function
movl $0, %edi # first index is 0
movl 8(%ebp), %ecx # ecx is loaded with the number of elements
cmpl $0, %ecx # check that the number of elements is not 0
je end_function_err #if it is, exit
movl 12(%ebp),%edx # edx is loaded with the array base
movl (%edx), %eax # first element of the array
start_loop:
incl %edi #increment the index
cmpl %edi,%ecx #if it's at the end quit
je loop_exit
movl (%edx,%edi,4),%ebx #pick the value
cmpl %ebx,%eax #compare with actual maximum value
jle start_loop #less equal -> repeat loop
movl %ebx,%eax #greater -> update value
jmp start_loop #repeat loop
loop_exit:
jmp end_function #finish
end_function: #exit operations
movl %ebp, %esp
popl %ebp
ret
end_function_err:
movl $0xffffffff, %eax #return -1 and quit
jmp end_function
It basically defines a function that finds the maximum number of an array (or it should be)
And my C code:
#include <stdio.h>
#include <stdlib.h>
extern int max_function(int size, int* values);
int main(){
int values[] = { 4 , 5 , 7 , 3 , 2 , 8 , 5 , 6 } ;
printf("\nMax value is: %d\n",max_function(8,values));
}
I compile them with gcc -o max max.s max.c.
I get a SegmentationFault when executing the code.
My suspect is that I don't access the value in a right manner, but I can't see why, even because I based my code on an example code that prints argc and argv values when called from the command line.
I'm running Debian 8 64-bit
The problems were:
not preserving %ebx and %edi
not compiling for 32 bit (had to use -m32 flag for gcc)
cmpl operands were inverted
Thanks everybody, problem is solved.
I'll focus more on debugging tools to (disassembling and running step by step was very useful)!
I am trying to interface c code with asm.
But it is not working correctly and I am not able to find the problem.
program.c
#include<stdio.h>
int *asm_multi(int *ptr);
int main()
{
int i=10;
int *p=&i;
asm_multi(p);
printf("%d\n",*p);
return 0;
}
code.asm
.section .text
.global asm_multi
.type asm_multi,#function
asm_multi:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax
movl %eax,%edx
leal (%edx,%edx,1),%edx
movl %edx,%eax
movl %ebp,%esp
popl %ebp
ret
I am creating the final executable by
as code.asm -o code.o
gcc program.c code.o -o output
./output
The output it prints is :10 whereas I am expecting: 20
What is the problem in the code? Don't consider the efficiency of the program. I have just started asm programming.
I created above code after reading from a more complex example kept at this link. This works perfectly.
You should learn to use a debugger as soon as possible. It not only helps you find bugs, but also allows you to exactly see what the cpu is doing at each instruction and you can compare that to your intentions.
Also, comment your code, especially when asking for help, so we can tell you where the instructions don't match your intentions, if you were unable to do so yourself.
Let's comment your code then:
asm_multi:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax # fetch first argument, that is p into eax
movl %eax,%edx # edx = p too
leal (%edx,%edx,1),%edx # edx = eax + edx = 2 * p
movl %edx,%eax # eax = edx = 2 * p
movl %ebp,%esp
popl %ebp
ret
As you can see, there are two problems:
You are doubling the pointer not the value it points to
You are not writing it back into memory, just returning it in eax which is then ignored by the C code
A possible fix:
asm_multi:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax # fetch p
shll $1, (%eax) # double *p by shifting 1 bit to the left
# alternatively
# movl (%eax), %edx # fetch *p
# addl %edx, (%eax) # add *p to *p, doubling it
movl %ebp,%esp
popl %ebp
ret
I translated a simple c program into IA32 and then transliterated it into Y86 but I am getting an error I don't understand or know how to debug since I am just learning Y86. The error is:
Stopped in 1 steps at PC = 0x1. Exception 'HLT', CC Z=1 S=0 O=0
Changes to registers:
Changes to memory:
The program is supposed to initialize i to 0 and then proceed through a for loop until i is greater than or equal to 5 and increment i each time. Inside the for loop I set j equal to i*2 and k is equal to j+1. My Y86 code is as follows:
main:
irmovl $0, %ebx
jmp L2
halt
L3:
rrmovl %ebx, %eax
addl %eax, %eax
rrmovl %eax, %ecx
rrmovl %ecx, %eax
irmovl $1, %esi
addl %esi, %eax
rrmovl %eax, %edx
addl %esi, %ebx
L2:
irmovl $4, %edi
subl %edi, %ebx
jle L3
I can provide the C code and IA32 code I transliterated from if it would help you answer my problem I really need some help thanks.
You forgot to add the extra NL (CR) in the source file. YAS is flawed. When it assembles it wraps the assembly around if there is no NL (CR) at the end of the source (ys) file, overwriting the beginning of the created object code (yo) file.
The result... well it is bad. In your case, YAS probably inserted a HLT instruction in the first character of the object file.