Page 2 of 2
Re:Dynamic code generation--how to fill in necessary values
Posted: Wed Dec 29, 2004 3:59 pm
by purevoid
I found a way to get the right output, but not sure if it's really the right way to do things, but anyways...
Now when I execute my ISR, I get a bochs error: running in bogus memory =(
One thing I noted was that I could write the ISR without having to fill in the function at runtime, since that's fixed: a function called `callback' from the OCaml includes.
So I tried to compile my asm with `call callback', but it doesn't link: undefined reference to callback. Is that just linking order, or something more mysterious?
Re:Dynamic code generation--how to fill in necessary values
Posted: Wed Dec 29, 2004 4:49 pm
by Candy
You need a function called "callback" for the asm call to callback to link.
This could have some probable causes:
1. You didn't define any function called callback. This is pretty obvious and probably not the cause.
2. You didn't get a link-time error but a compile-time error. You need to tell the assembler that you are actually going to make a function called callback, using "extern callback" or something similar. Probably not.
3. You don't have a function by the link-name of "callback". This can have multiple causes. Try to use a hex viewer (if you're brave) or objdump on the object in which you think it is to see what it is actually called. Common cause is an underscore before the function name, in case of some Windows development environments. Another is C++ name mangled names, after which it isn't callback either (it's _Z8callback with some characters appended).
4. You're not linking the object in which it is to the series of objects in which the call is. You need both of them in the same series.
If these all are fulfilled it should work. If not, please post some code on which it fails, preferably a small sample of the code in which the bug is isolated.
Re:Dynamic code generation--how to fill in necessary values
Posted: Wed Dec 29, 2004 4:54 pm
by Pype.Clicker
9 bytes seems too small to me. Beware when you do pointers substractions: the sizeof the base type will affect the offset you obtain.
E.g. If ptr is @0x1234 and pptr is @0x1244,
Code: Select all
extern int ptr, pptr;
printf("%i", &pptr - &ptr);
will return 4 (16/sizeof(int)) ...
I suggest you declare ISR_template and ISR_end as extern unsigned char in your C code ...
Re:Dynamic code generation--how to fill in necessary values
Posted: Wed Dec 29, 2004 6:06 pm
by purevoid
Okay, I can finally call a function with parameters from generated ISR stub =) Now I just have a general protection exception on exit from the function call...
I haven't figured out how to make my exception handler print the error code, or the values of CS & EIP yet, which could shed some light on the actual instruction causing the problems... anyways, here is my ISR stub:
Code: Select all
.global ISR_template
.global ISR_arg_1
.global ISR_arg_2
.global ISR_target
.global ISR_end
ISR_template:
cli
pusha
push %gs
push %fs
push %es
push %ds
ISR_target:
movl $0xDEADBEEF, (%eax)
ISR_arg_1:
pushl $0xAAAAAAAA
ISR_arg_2:
pushl $0xBBBBBBBB
call (%eax)
addl $8, (%esp)
pop %ds
pop %es
pop %fs
pop %gs
popa
sti
iret
ISR_end:
Which all looks correct to me. It seems the popping of the segments might be the culprit, but I dunno why.
I've tried calling a plain C function, and also my OCaml callback thing, and both trigger the GP exception, so at least I know it's not OCaml. The C function is just my original keyboard ISR without the asm("leave") or asm("iret") at the end, since the stub does the IRET...
And one other question about interrupts: will doing a near call like above always work? Or does the CPU not automatically switch segments for a near call to work once user-mode stuff is implemented?
Re:Dynamic code generation--how to fill in necessary values
Posted: Thu Dec 30, 2004 6:05 am
by Pype.Clicker
In order to access CS:EIP and other exception state, you need to capture the stack pointer in the STUB and pass it as an argument of the C function. Then you need to write a structure that will match the current stack content and access fields of this structure.
The "call near" will of course only work for calling kernel functions. There's no mechanism to call a user-level code from kernel. All you can do to emulate this is to *return* to another user-level code than the one which raised the exception ...