void core::relocate () {
_asm {
; save stack
mov eax, esp
; copies ourself to 1mb
cld
mov esi, 0x10000
mov edi, 0x100000
mov ecx, [_osloader_size]
rep movsd
; jumps to relocated addr
mov ebx, 0x100000 + (cont-0x10000)
push ebx
ret
cont:
; restore stack
mov esp, eax
; change return eip to reloc+return eip
pop ebx
sub ebx, 0x10000 ; turn return eip into offset
add ebx, 0x100000 ; ..and add reloc addr
; return to relocated code (Crashes when it returns here :( )
push ebx
ret
}
}
Relocating (x86 asm)
Hello everyone,
I am working on a software system using Microsoft Visual C++ 2008. My code is running at physical address 0x10000 but is capable of loading files and programs to the same location. I want the system to relocate itself to another part of memory when these types of programs are being read. Because only one program is ran at one time; I figure just relocate the code to 1mb.
I managed to get it working fine inline (ie; inside of a function, but not its own routine) Im looking for a cleaner method though and for it to be in a routine. It relocates it fine but I cannot seem to be able to return from the routine without problems (page faults, general protection errors..)
Does anyone spot where I might be going wrong? ...Perhaps I am messing up the stack somehow? (Although I dont see how..)
I can post more info if needed. Thanks for any help [smile]
The biggest problem I see currently is that you are using that assembly code in a C++ class function. The problem with that is you are not only getting prolog/epilog instructions inserted from VS, you are also getting additional code that was used to setup the class member function call. Also, you are going to be getting some stack checks as well (_RTC_CheckEsp, _RTC_CheckStackVars, and __security_check_cookie for example)
To see what I am talking about, what you can do is:
1. Add about 6 _asm nop at the top of the function.
2. Download OllyDbg
3. Open your executable (debug mode works best) in OllyDbg.
4. Hit ctrl + S to bring up the Find sequence of commands
5. Type NOP on seperate lines 6 times and hit Find, you should hit your function.
6. Breakpoint on the function entry and being tracing the code, you should see why it crashes at the end, you will be returning with a messed up stack due to epilog code not being executed.
I think you should be able to hack up a solution this way [smile]
To see what I am talking about, what you can do is:
1. Add about 6 _asm nop at the top of the function.
2. Download OllyDbg
3. Open your executable (debug mode works best) in OllyDbg.
4. Hit ctrl + S to bring up the Find sequence of commands
5. Type NOP on seperate lines 6 times and hit Find, you should hit your function.
6. Breakpoint on the function entry and being tracing the code, you should see why it crashes at the end, you will be returning with a messed up stack due to epilog code not being executed.
I think you should be able to hack up a solution this way [smile]
You are right--I didn't even think about my usage of it being a class member function.
I decided to make the routine global and modified the code using the disassembly as a guide (the prolog/epilog code, specifically.) Its working now, thank you for your help! [smile]
Here's the new routine in case anyone is interested. It returns to the next instruction to follow the relocate call + its relocation address.
*edit: there was a bug with the old code...it was returning to the old eip address rather then the relocated address. Updated post with new code.
[Edited by - Crypter on January 25, 2009 1:02:35 PM]
I decided to make the routine global and modified the code using the disassembly as a guide (the prolog/epilog code, specifically.) Its working now, thank you for your help! [smile]
Here's the new routine in case anyone is interested. It returns to the next instruction to follow the relocate call + its relocation address.
void relocate (uint32_t curAddr, uint32_t newAddr, uint32_t n) {#ifdef _MSC_VER _asm { ; save stack mov eax, esp ; copies ourself to reloc addr cld mov esi, [curAddr] mov edi, [newAddr] mov ecx, [n] rep movsd ; jumps to relocated addr mov ebx, cont sub ebx, [curAddr] ; cont-curAddr; turn cont into offset add ebx, [newAddr] ; ...and add the new base addr push ebx ret cont: ; change return eip to reloc+return eip mov eax, [esp+16] sub eax, [curAddr] ; (prev eip - prev base) turn return eip into offset add eax, [newAddr] ; ..and add reloc addr ; write the new return eip mov [esp+16], eax ; restore stack pop edi ; stack frame from epilog code pop esi pop ebx pop ebp ; return to relocated code ret }#endif}
*edit: there was a bug with the old code...it was returning to the old eip address rather then the relocated address. Updated post with new code.
[Edited by - Crypter on January 25, 2009 1:02:35 PM]
Off-topic, but how did you get Visual Studio to cooperate for writing freestanding code?
I'd like to get back into OS dev but the hassle of dual-booting into a Linux and creating a cross-compiling toolchain puts me off.
I'd like to get back into OS dev but the hassle of dual-booting into a Linux and creating a cross-compiling toolchain puts me off.
Quote:Off-topic, but how did you get Visual Studio to cooperate for writing freestanding code?
Check out my site (Clicky). It describes everything needed. I originally wrote it for Visual C++ 2005 but it also works with Visual C++ 2008. Hope it helps you out [smile]
Quote:Original post by Crypter
Check out my site (Clicky). It describes everything needed. I originally wrote it for Visual C++ 2005 but it also works with Visual C++ 2008. Hope it helps you out [smile]
What is the status of your page fault handler? Will you use a trap frame to catch and dissipate page faults? Do you really need a more evolved OS to dissipate page faults? (per VM)
Quote:Original post by Crypter
Check out my site (Clicky).
It's called "environment", not "envirement" ;)
Quote:What is the status of your page fault handler? Will you use a trap frame to catch and dissipate page faults? Do you really need a more evolved OS to dissipate page faults? (per VM)
I am still considering the method that I will use. You don't really *need* a more evolved OS but without a disk driver of any type you would be forced to use other methods for swapping pages from disk (ie; real mode bios perhaps?) or a completely different method for handling them.
My real system uses a trap frame, yes. er.. rather my *old* system did; it does not yet apply to my new system though sense its being rewritten.
Quote:It's called "environment", not "envirement" ;)
Thanks for the typo [smile] I tend to misspell things alot in the series; not to the point of losing comprehension though. I do plan on going back through it and cleaning it up; but for now I am more worried about its content then anything else. Of course, I clean up misspellings when I see them though or others point them out.
Quote:Original post by CrypterQuote:What is the status of your page fault handler? Will you use a trap frame to catch and dissipate page faults? Do you really need a more evolved OS to dissipate page faults? (per VM)
I am still considering the method that I will use. You don't really *need* a more evolved OS but without a disk driver of any type you would be forced to use other methods for swapping pages from disk (ie; real mode bios perhaps?) or a completely different method for handling them.
I see. The Intel CPU docs contain a lot of information about virtual memory management without touching on disks too much, but I suppose pages can't be swapped without a disk to swap them from.
Quote:Original post by Crypter
My real system uses a trap frame, yes. er.. rather my *old* system did; it does not yet apply to my new system though sense its being rewritten.
That would be "since" not "sense". Sense is what you do with your senses (eyes, ears, etc). [grin]
At any rate, I think trap frames are neat, sort of like kernel mode exception handlers.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement