Re: inline system calls?
Posted: Sat May 06, 2017 2:44 am
I always inline "neutral" code that generates an exception, and then patches it in the exception handler to whatever code the setup uses.
The Place to Start for Operating System Developers
http://f.osdev.org/
As Intel points out, those two are software issues. Yes, you have to be careful and think things thru.
The key is where you put that flexibility, in the right place you get all the flexibility you need without impacting performance at all or very little.Brendan wrote: For software that hopes to be around for a while; it's good practice to design it with some flexibility, so that if things change in future you have a way to deal with those changes (that doesn't break backward compatibility).
"Ever" is a long time, hopefully someone will or C gets replaced. I mean all the make/build tools that exist clearly show that there is a problem, compilers creating dependency files (listing the headers that are included) so that Make knows what to do, etc... It's a mess, sure it can be used but it's too complex and takes too much effort..Brendan wrote: In theory it's possible to create tools that fix all the "compile before use is too painful/annoying/fragile for C" problems; but in practice nobody ever will - they either won't be willing to write their own tools at all, or they'll go all the way and abandon C itself (e.g. create their own language).
The "neutral" code is #UD or something like "int 0x80"?rdos wrote:I always inline "neutral" code that generates an exception, and then patches it in the exception handler to whatever code the setup uses.
No, it is not a simple int x code.LtG wrote:The "neutral" code is #UD or something like "int 0x80"?rdos wrote:I always inline "neutral" code that generates an exception, and then patches it in the exception handler to whatever code the setup uses.
But what's the benefit of doing it that way? Compared to putting it in the places the binary image (ELF, PE, what ever) explicitly requests? Don't you also need padding to account for possibly longer "syscall" sequences later?
Also isn't that like self-modifying code? I'm not against it, but won't it then interfere with an application that itself wants to do self-modifying of its own (usually problematic when two entities are modifying the same thing)..? I understand that you might not want to support self-modifying so for you it's a moot point, but from theory perspective why pick a solution that is more limiting with no extra benefits?
Simply put, is there anything that makes that solution better than the others?
Code: Select all
db 55h
db 67h
db 9Ah
dd gate_nr
dw 3
db 5Dh
Code: Select all
push ebp
call far 0003:gate_nr
pop ebp
Code: Select all
db 55h
db 0CDh
db 9Ah
dd gate_nr
dw 3
db 5Dh
Code: Select all
push ebp
int 9Ah
dd gate_nr
dw 3
pop ebp
Code: Select all
db 55h
db 90h
db 9Ah
dd 0
dw gate-sel
db 5Dh
Code: Select all
push ebp
nop
call gate-sel:0
pop ebp
Code: Select all
db 55h
db 90h
db 0E8h
dd OFFSET app-stub
dw 9090h
db 5Dh
Code: Select all
push ebp
nop
call app_stub
nop
nop
pop ebp
Code: Select all
push ecx
push edx
mov ecx,esp
mov edx,gate_nr
sysenter
pop edx
pop ecx
ret
OK, I changed the post. Not used to code tags nowadays.Schol-R-LEA wrote:Purely as an aside: why didn't you use code tags? I realize that formatting isn't significant in the cases of assembly code, and that the snippets are exceedingly short, but, well, if nothing else, it gives a poor impression to newbies that a long-standing member is doing this. I expect that there may be a reason for this (e.g., you were posting from a cell phone or tablet and using the tags was impractical), but it night be worth making mention of it if so.
Fair enough; many, perhaps most, newer message boards use Snarkdown instead of BBgoad, so that would be reason enough. I've had the same problem too, before, assuming that's what happened.rdos wrote:OK, I changed the post. Not used to code tags nowadays.Schol-R-LEA wrote:Purely as an aside: why didn't you use code tags? I realize that formatting isn't significant in the cases of assembly code, and that the snippets are exceedingly short, but, well, if nothing else, it gives a poor impression to newbies that a long-standing member is doing this. I expect that there may be a reason for this (e.g., you were posting from a cell phone or tablet and using the tags was impractical), but it night be worth making mention of it if so.
The addition of push and pop ebp is recent. It was done to be able to reconstruct the usermode callstack when something crashed in kernel. It was especially useful for memory debugging, which has breakpoints in kernel when usermode code overruns its allocation or double frees.LtG wrote:rdos, is there a reason you want to push and pop ebp? Also why not simply leave required number of bytes (you seem to use 8 ) in the image and record these locations and patch the code at load/install time, instead of during run time? Given that normal apps shouldn't have that many syscalls I don't expect that load/install time will give much better performance but certainly won't be worse, and as an added bonus you don't have to worry/care about multicore issues with that approach.
So I'm asking what is the benefit you see with this more complicated approach?
Thanks, makes sense.. I was thinking why do all that extra effort, but for your design it probably makes sense. For a micro-kernel there shouldn't be much/any reason to call into userland (where drivers are), so runtime syscall "fixups" aren't really that useful for me.rdos wrote:The addition of push and pop ebp is recent. It was done to be able to reconstruct the usermode callstack when something crashed in kernel. It was especially useful for memory debugging, which has breakpoints in kernel when usermode code overruns its allocation or double frees.
As for why not to use the usermode loader to fixup syscalls at load time, the reason is that these syscalls are also used in kernel, and RDOS supports several standard executable formats, even though 32-bit flat PE is the only one that is currently in use. In fact, almost all usermode callable functions (except a few related to the usermode image itself), are usable in kernel. Things like the file API and the network stack are used in kernel drivers too. That also makes the reach of functions (usermode or kernel only) easy to redefine. If something that was originally supposed to be kernel only, but then is needed in usermode too, the function prototype is redefined and the code recompiled and then works without any other modifications.