Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
I am using the JamesM kernel tutorial source and have added a function to parse an Elf Binary. I got the information to parse an ELF binary from the wiki. I am confused now on how to create a new process and execute the ELF Program from the parsed executable information with the JamesM kernel tutorial source. I think I have to call fork() to create a new process, but I am stuck on what to do after that.
After parsing the ELF file, it outputs the structure Exe_Format, which is listed below:
I think what you would do is first fork(), then jump in the child process to the entry point of your loaded code. What you really want is an exec() call that parses the binary for you, then jumps to it. That way, you don't need to worry about parsing the exe, then not having the code in your fork()ed virtual address space.
alethiophile wrote:I think what you would do is first fork(), then jump in the child process to the entry point of your loaded code. What you really want is an exec() call that parses the binary for you, then jumps to it. That way, you don't need to worry about parsing the exe, then not having the code in your fork()ed virtual address space.
How to I get the ELF binary code in my fork()ed virtual address space, as this is where I am really confused.
alethiophile wrote:First fork(), then call the functions to parse an ELF binary. Or so I would do.
I might have said it wrong, but I have a structure with the segment lists which include startAddress, offsetInFile, sizeInMemory, etc., the structures are in the first post. What I am trying to do now is copy the actual binary data using the information in the structures to the new process' address space and execute it, but I am confused on how to do this.
if(fork() == 0)
{
// Load the ELF binary... read from disk, fill structures, etc...
}
else
{
// Parent thread continues, or waits for the child, or quits
}
If your fork() is general-purpose enough it'll be able to fork kernel threads too, which gives you a free thread to work in.
You can then make a jump to user mode when you finish loading the ELF binary - pushing CS/EIP and SS/ESP and using an IRET is an easy way of doing that.
if(fork() == 0)
{
// Load the ELF binary... read from disk, fill structures, etc...
}
else
{
// Parent thread continues, or waits for the child, or quits
}
If your fork() is general-purpose enough it'll be able to fork kernel threads too, which gives you a free thread to work in.
You can then make a jump to user mode when you finish loading the ELF binary - pushing CS/EIP and SS/ESP and using an IRET is an easy way of doing that.
I am using the exact fork() in the tutorial. I am already in user mode when doing this, and I am just trying to execute a simple ELF Binary. I am just trying to figure out using the PID from fork() or something, how do I figure where to load the .TEXT and .DATA segments so the Binary will correctly execute.
I guess what I am really trying to ask is how do I know where to copy the .TEXT and .DATA segments into memory. That is where I am getting confused, like do the page tables have anything to do with where I map the virtual address to, or what?
If you're using the alloc_frame and free_frame functions, then it's hard to put something in one address space from another. Again, what I would do is fork first, then do whatever you've already done to get the entry point and so on.
JoeTheProgrammer wrote:I guess what I am really trying to ask is how do I know where to copy the .TEXT and .DATA segments into memory. That is where I am getting confused, like do the page tables have anything to do with where I map the virtual address to, or what?
When you parse the ELF binary, you have program headers. Each of these has a "vaddr" element, which is where they expect to be loaded into memory. So basically, you read in the file, and map different parts of the file to different virtual addresses, based on the program headers.
If you haven't already, read the ELF specification. It's got everything you need to know.
JamesM tutorial is a good starting point, but youll need to add alot more things yourself. His fork() will clone the address space for you, but you need functions to map more addresses in. It also depends on how you are switching tasks. If you are loading a binary, you map the addresses you need, load the executable code where it needs to be, set eip and esp appropriately, and then do a task switch and it should switch into the new process, which considers itself to be at the start of the program by now
yemista wrote:JamesM tutorial is a good starting point, but youll need to add alot more things yourself. His fork() will clone the address space for you, but you need functions to map more addresses in. It also depends on how you are switching tasks. If you are loading a binary, you map the addresses you need, load the executable code where it needs to be, set eip and esp appropriately, and then do a task switch and it should switch into the new process, which considers itself to be at the start of the program by now
Alright, I think I understand now, only I have one more question. How do I get the appropriate values for the eip, ebp, and esp?
Well, EIP is entryAddr, EBP can be anything (unless you want to do something after returning from the function in the elf binary), and ESP needs to point to some frames that will be used as stack.
Cheers, gzaloprgm
Visit https://gzalo.com : my web site with electronic circuits, articles, schematics, pcb, calculators, and other things related to electronics.