Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 302 Vote(s) - 3.45 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Code a simple thread with C and assembly

#1
I'm trying to code a simple user-level thread library as an exercise for my OS course. As the first step, I am trying to run a program and jump to a function leaving the first program. The code so far is this:

The initial program:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>

#define STACK_SIZE (sizeof(void *) * 512)


void proc2() //This is the function that should run as the thread.
{
int i;
for(i=0;i<30;i++)
{
printf("Here I am!\n");
sleep(0.5);
}
exit(0);
}

void* malloc_stack() //used to malloc the stack for the new thread.
{
void *ptr = malloc(STACK_SIZE + 16);
if (!ptr) return NULL;
ptr = (void *)(((unsigned long)ptr & (-1 << 4)) + 0x10); //size align
return ptr;
}

int main()
{
int *bp, *sp;
sp = malloc_stack();
bp = (int*) ((unsigned long)sp + STACK_SIZE);
proc1(&proc2,sp,bp); //the actual code that runs the thread. Written in assembly
assert(0);
}

And then I wrote a simple assembly code called proc1 that takes three arguments, pointer to a function (used as the instruction pointer), stack pointer and base pointer and replace the current registers with these values. The code I wrote is:

.globl proc1
proc1:
movq %rdx, %rbp #store the new base pointer
movq %rsi,%rsp #store the new stack pointer
jmp %rdi #jump to the new instruction pointer.

But when I run this code, what I get is a segmentation fault. Please help me to find the error here.

Well it's working correctly when I ran it under GDB using the following commands:

gcc -g test.c switch.s
gdb a.out
run

but when it rus alone as in ./a.out, it doesn't work!!!!
Please help.

Thanks in advance.
Reply

#2
Your `movq` at the top of your assembly are (well, "were" before you edited :-) ) written as

movq dst,src

but your `movq` before the `jmp` is written `movq %rax,%rsp` and `%rsp` is clearly the desired dst. That's obviously wrong, not sure about anything else.
Reply

#3
Try changing your code to include the assembly instructions directly in the C source as follow:

void proc1(void (*fun)(), int *sp, int *bp){
register int *sptr asm ("%rsi") = sp;
register int *bptr asm ("%rdx") = bp;
register void (*fptr)() asm ("%rdi") = fun;

asm (
"mov %rdx, %ebp\n"
"mov %rsi, %esp\n"
"jmp *%rdi\n"
);
}

The above code ensures that the parameters to `proc1` are in the right registers (although your code seems to be correct wrt the abi). Note the `*` in front of the `jmp` argument, which my version of gnu as warned about when I first tried your code.

With the above function, and code compiled with `-g` you should be able to debug it properly (use the `breakpoint` instruction on `proc1` and `info registers` to check the content of the cpu).

----

**The issue** is actually on the `%rsp` pointer, which must always be equal to or greater than `%rbp` (the stack grows downward). Simply passing bp instead of sp to `proc1` in main should fix the issue:

proc1(&proc2, bp, bp);



2 small remarks:

- don't forget to give `proc1` prototype in the C code for the asm version:

extern void proc1(void (*)(), int *, int *);

- the `sleep` libc function only take `unsigned long`, not `float`.

sleep(1);




Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through