In an attempt to write an OS, I need to get the address of the current function's end (right before epilogue) for task switching.
Concretely my problem is to get an EIP to assign to my newly created task (process) inside the copied stack. I have already managed to save/restore registers for a process, but I need to find what value the child process will have in it's EIP.
I used GCC's extensions to C standard : Labels as Values and Local Labels
From the documentation : You can get the address of a label defined in the current function (or a containing function) with the unary operator ‘&&’. The value has type void *.
and : GCC allows you to declare local labels in any nested block scope. A local label is just like an ordinary label, but you can only reference it (with a goto statement, or by taking its address) within the block in which it is declared.
pid_t fork(void)
{
__label__ fork_end;
...
task->regs.eip = (uintptr_t)&&fork_end;
...
return task->pid;
fork_end:;
}
GCC does compile it, with just warnings about non-standard code.
However when disassembled, gdb shows :
task->regs.eip = (uintptr_t)&&fork_end;
0x00105008 <+87>: mov $0x105008,%edx
0x0010500d <+92>: mov -0xc(%ebp),%eax
0x00105010 <+95>: mov %edx,0x40(%eax)
...
fork_end:;
}
0x00105096 <+229>: leave
0x00105097 <+230>: ret
I expect task->regs.eip = (uintptr_t)&&fork_endl
to save0x00105096
rather than 0x00105008
.CFLAGS
are -O0 -std=gnu99 -fgnu89-inline -DDEBUG -ggdb3 -ffreestanding -fbuiltin
(warnings related options not shown here).
Commenting __label__ fork_end;
changes nothing.
It appears that the compiler is optimizing out the label entirely as no code path ever leads to it. I have confirmed that moving the label to before the return
statement and ensuring that there is actual code in-between the assignment and the label results in what I believe is your desired behaviour. Here is the code I put together to test:
void *fork(void) {
__label__ fork_end;
void *test = &&fork_end;
test++;
fork_end:
return test;
}
Based on this, I would expect that you can indeed get what you want by re-working your code path slightly to ensure that the label point is reachable by any code path.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With