__kernel_vsyscall in assembly function (gdb) - c

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.

Related

Calling assembly function from c leads to segmentation fault

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

C/Assembly Subprogram Segmentation fault

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

Segmentation fault when storing hexadecimal value into register

I'm doing a class in assembly that is called from a class in C. The C class sends 2 integers as parameters but that's not relevant cause I'm getting a segmentation fault error that I don't seem to quite understand why.
Here's the relevant part of the assembly class:
.global testingclass
testingclass:
pushl %ebp
movl %esp, %ebp
subl $4, %esp #reserves space for local variable
movl 8(%ebp), %ebx #first argument of the function to %ebx
movl 12(%ebp), %ecx #second argument of the function to %ecx
function:
movl $0, %eax ----------------< segmentation fault
movl 0x0000FFFF, %eax
and %bx, %ax
movw %ax, -4(%ebp)
...
I signed the line that gives me the segmentation fault error when debugging. I really don't know how can a simple move command trigger a segmentation fault, but hope you can help me.
This is the debugger console output:
...
11 movl 12(%ebp), %ecx #second argument of the function to %ecx
(gdb) n
function() at asm.s:16
16 movl 0x0000FFFF, %eax
(gdb) n
Program received signal SIGSEGV, Segmentation fault.
function() at asm.s:16
16 movl 0x0000FFFF, %eax
the seg fault occurred at this instruction:
movl 0x0000FFFF, %eax
Not at this instruction:
movl $0, %eax
The reason for the seg fault is reading from address (64k-1)
The program can only read/write addresses that are available to the user space.
Since the OS is first, after the interrupt vectors, the code tried to read an address within the OS code. The OS code is not part of the user space.

Y86 Stopped in 1 Steps Exception HLT

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.

Decoding equivalent assembly code of C code

Wanting to see the output of the compiler (in assembly) for some C code, I wrote a simple program in C and generated its assembly file using gcc.
The code is this:
#include <stdio.h>
int main()
{
int i = 0;
if ( i == 0 )
{
printf("testing\n");
}
return 0;
}
The generated assembly for it is here (only the main function):
_main:
pushl %ebpz
movl %esp, %ebp
subl $24, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -8(%ebp)
movl -8(%ebp), %eax
call __alloca
call ___main
movl $0, -4(%ebp)
cmpl $0, -4(%ebp)
jne L2
movl $LC0, (%esp)
call _printf
L2:
movl $0, %eax
leave
ret
I am at an absolute loss to correlate the C code and assembly code. All that the code has to do is store 0 in a register and compare it with a constant 0 and take suitable action. But what is going on in the assembly?
Since main is special you can often get better results by doing this type of thing in another function (preferably in it's own file with no main). For example:
void foo(int x) {
if (x == 0) {
printf("testing\n");
}
}
would probably be much more clear as assembly. Doing this would also allow you to compile with optimizations and still observe the conditional behavior. If you were to compile your original program with any optimization level above 0 it would probably do away with the comparison since the compiler could go ahead and calculate the result of that. With this code part of the comparison is hidden from the compiler (in the parameter x) so the compiler can't do this optimization.
What the extra stuff actually is
_main:
pushl %ebpz
movl %esp, %ebp
subl $24, %esp
andl $-16, %esp
This is setting up a stack frame for the current function. In x86 a stack frame is the area between the stack pointer's value (SP, ESP, or RSP for 16, 32, or 64 bit) and the base pointer's value (BP, EBP, or RBP). This is supposedly where local variables live, but not really, and explicit stack frames are optional in most cases. The use of alloca and/or variable length arrays would require their use, though.
This particular stack frame construction is different than for non-main functions because it also makes sure that the stack is 16 byte aligned. The subtraction from ESP increases the stack size by more than enough to hold local variables and the andl effectively subtracts from 0 to 15 from it, making it 16 byte aligned. This alignment seems excessive except that it would force the stack to also start out cache aligned as well as word aligned.
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -8(%ebp)
movl -8(%ebp), %eax
call __alloca
call ___main
I don't know what all this does. alloca increases the stack frame size by altering the value of the stack pointer.
movl $0, -4(%ebp)
cmpl $0, -4(%ebp)
jne L2
movl $LC0, (%esp)
call _printf
L2:
movl $0, %eax
I think you know what this does. If not, the movl just befrore the call is moving the address of your string into the top location of the stack so that it may be retrived by printf. It must be passed on the stack so that printf can use it's address to infer the addresses of printf's other arguments (if any, which there aren't in this case).
leave
This instruction removes the stack frame talked about earlier. It is essentially movl %ebp, %esp followed by popl %ebp. There is also an enter instruction which can be used to construct stack frames, but gcc didn't use it. When stack frames aren't explicitly used, EBP may be used as a general puropose register and instead of leave the compiler would just add the stack frame size to the stack pointer, which would decrease the stack size by the frame size.
ret
I don't need to explain this.
When you compile with optimizations
I'm sure you will recompile all fo this with different optimization levels, so I will point out something that may happen that you will probably find odd. I have observed gcc replacing printf and fprintf with puts and fputs, respectively, when the format string did not contain any % and there were no additional parameters passed. This is because (for many reasons) it is much cheaper to call puts and fputs and in the end you still get what you wanted printed.
Don't worry about the preamble/postamble - the part you're interested in is:
movl $0, -4(%ebp)
cmpl $0, -4(%ebp)
jne L2
movl $LC0, (%esp)
call _printf
L2:
It should be pretty self-evident as to how this correlates with the original C code.
The first part is some initialization code, which does not make any sense in the case of your simple example. This code would be removed with an optimization flag.
The last part can be mapped to C code:
movl $0, -4(%ebp) // put 0 into variable i (located at -4(%ebp))
cmpl $0, -4(%ebp) // compare variable i with value 0
jne L2 // if they are not equal, skip to after the printf call
movl $LC0, (%esp) // put the address of "testing\n" at the top of the stack
call _printf // do call printf
L2:
movl $0, %eax // return 0 (calling convention: %eax has the return code)
Well, much of it is the overhead associated with the function. main() is just a function like any other, so it has to store the return address on the stack at the start, set up the return value at the end, etc.
I would recommend using GCC to generate mixed source code and assembler which will show you the assembler generated for each sourc eline.
If you want to see the C code together with the assembly it was converted to, use a command line like this:
gcc -c -g -Wa,-a,-ad [other GCC options] foo.c > foo.lst
See http://www.delorie.com/djgpp/v2faq/faq8_20.html
On linux, just use gcc. On Windows down load Cygwin http://www.cygwin.com/
Edit - see also this question Using GCC to produce readable assembly?
and http://oprofile.sourceforge.net/doc/opannotate.html
You need some knowledge about Assembly Language to understand assembly garneted by C compiler.
This tutorial might be helpful
See here more information. You can generate the assembly code with C comments for better understanding.
gcc -g -Wa,-adhls your_c_file.c > you_asm_file.s
This should help you a little.

Resources