tags:

views:

86

answers:

4

I'm implementing a program which loads pure code from a file and calls the first instruction. No matter what I do, I get a Segmentation fault when my call instruction is executed. What do I do wrong?

char code[65536];
...
__asm__("movl code, %eax");
__asm__("call *%eax");
+1  A: 

is the "pure code" compatible to your program? What OS? "normally" the "pure code" is relocated annd will be "moved" to the corresponding address in memory by the "linkage-loader" that does the apropriate adjustments.

Peter Miehle
A: 

OS is Linux Ubuntu.

I know that it's normally done that way. The code is compatible, it's from my own compiler which generates a file with just program code and the first instruction in the file is the first instruction of the main method.

(I'm a student and I have to do it manually so I learn something! ;-) =

loonytune
This is not an answer. It should be an edit of your question.
Fred Larson
+1  A: 

For generated code to execute - it must be in an executable section.

On x86-64, try this instead

char* code = mmap(0, 1024 * 1024, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_32BIT | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

on a 32-bit system, the map_32bit is not relevant (it is used on x86-64 to make sure code can go into the first 2GB, and use relative addressing)

auscoder
hi! this seems to do something. I'm still getting a segfault somewhere, but not from the call instruction. however could you explain to me what exactly this is doing?
loonytune
It creates a 1Mb region in the process's address space that is readable writable and executable and not shared. NB you can use the same call to directly map your file into the address space. http://linux.die.net/man/2/mmap
JeremyP
does this interfere in any way with the generated code? does it have to be generated differently? I'm asking because a code containing only a return: RET 0 (C3) works fine! But this code: ENTER 0, 0 (C8 00 00 00) LEAVE (C9) RET 0 (C3) doesn't and I can't see how an ENTER or LEAVE can trigger a Segmentation fault.
loonytune
You could also use mmap to map a file containing your executable code into your program. Then you would run a new program by `my_compiler program.source --output=program` and then `my_run program`. My run would consist almost entirely of `int (*x)(void); x = mmap(...); if (x) { return x(); }`
nategoose
A: 

Check your stack values with a debugger when returning from the imported code and double check it contains a valid return address. How does your imported code get called? Do you push any values before calling the imported code and does the imported code adjust the stack at the end?

seamast
I can't check the values when returning from my imported code since I get a segfault earlier when I use certain instructions (like LEAVE, ENTER) No, I don't push any values! I call it like I described in my initial question but allocate and map the memory like "auscoder" suggested. I already described which code works and which doesn't in a previous comment. (RET (C3) works fine but ENTER 0, 0 (C8 00 00 00) LEAVE (C9) RET (C3) doesn't). But do you think the problem could be?
loonytune