Closed rickgaiser closed 8 months ago
This doesn't clear the sbss/bss section.
You'd need to take a pointer to _end,_fbss like so:
memset(&_fbss, 0, &_end - &_fbss);
I tried the above locally, and it still doesn't work however, I'm not entirely sure why that memset does not work.
I found this in an old commit. https://github.com/ps2dev/ps2sdk/commit/e9f7d9f209730a7d9ca6063571c1a7ab33b9ada8#diff-f2617db51cb5540d4098682e08fb7fdc8b38c290c5f3e876848b7d41587d03a7R47-R63
I see, I was remembering that I was clearing that section. So I suppose, that if memset doesn’t work, you need to save arguments via ASM.
This doesn't clear the sbss/bss section. You'd need to take a pointer to _end,_fbss like so:
memset(&_fbss, 0, &_end - &_fbss);
Good catch. The memset seems to work for me with that change, becouse ps2link arguments are cleared again :(. Debugging what ps2link passes to neutrino I get the following:
_fbss @ 0x123480
_end @ 0x12e9a8
argv @ 0x123d34
So it looks like ps2link is passing the arguments inside the bss area.
I was experiencing crashing after a soft reset when using the memset method. I assumed it was related to the newlib allocation global not being reset. We at least know the root cause of neutrinos arguments going missing though.
A quick online search didn't really give a conclusive answer as to where arguments are usually placed in memory. Maybe we need to add some calculation that gives of a range from argv->argvend and clear around that area. Or it might be possible to change the segment (or create a new segment in the linker script?) for the arguments.
A pretty easy way to test locally is to run the following code, soft reset, and run the following code again.
#include <stdio.h>
#include <kernel.h>
// gets put into bss
int global_var;
int main(void)
{
printf("Global_var is %d\n",global_var);
global_var = 1;
SleepThread();
}
This should print 'Global_var is 0' twice.
The bss section is used by our ELF executables, the data should always be 0 on entering main.
I think ps2link is doing some hacky things here. There's 2 ways to start an ELF:
This is why our crt0 has the if/else for arguments. To detect if they are passed by the bios, or by ps2link.
So where does the bios place these arguments? Can't we have ps2link do that?
So where does the bios place these arguments? Can't we have ps2link do that?
crt0 calls SetupThread
. Perhaps ps2link can 'hook' into SetupThread
to return the arguments properly.
I think traditionally (on normal OS's) the arguments get saved on the stack of the main thread. Can we do that somehow?
I think traditionally (on normal OS's) the arguments get saved on the stack of the main thread. Can we do that somehow?
I don't think so. One of the first things crt0.o does is call SetupThread
. This initializes the stack and returns the arguments. This is how it should work (using sony bios).
ps2link can't put the arguments on the stack before it is created.
Looks like on ExecPS2 the kernel copies the args into a buffer in kernel memory, then on SetupThread it copies this buffer into the user supplied arg buffer. So that's how the arguments survive a wipe of user memory in that case.
I guess we'd have to copy the args somewhere safe to guarantee keeping them around. Although why would they have been stored within reach of user bss anyway? Isn't ps2link typically hidden away somewhere.
I would expect the ps2link arguments to be hidden below 1MiB, as defined here: https://github.com/ps2dev/ps2link/blob/master/ee/cmdHandler.c#L49
However that's not what what I see when debugging... I must say I'm also using an older ps2link as it's been broke for a long time.
I think a safe and compatible approach would be to copy the ps2link arguments to the area we already have reserved for arguments from the bios. This has to be done as 1 of the first steps, before clearing the bss area.
So regardless of what right/wrong place ps2link puts the arguments, we put them somewhere standard and safe, and clear bss.
Hm yeah, I was looking at ps2link in IDA for a bit and can't see how it could be affected by the BSS clearing.
I believe @fjtrujy and I have narrowed it down to _kExecArg being located in the .bss segment. I've mentioned this is greater detail on discord.
Can you guys test #555 and see if it fixes your issues?
I can test later today, thanks.
Complicating things even further, there is also ps2-packer that can mess things up. I didn't understand why my arguments where not located at the place where I thought ps2link put them. Turns out it's becouse ps2-packer also does some if/else copy actions with it's own (different) crt0.o.: https://github.com/ps2dev/ps2-packer/blob/master/stub/crt0.s
@F0bes I'm not sure what was wrong with the assemble code, but argument passing somehow stopped working (in neutrino). I think I found a nicer solution to clearing the sbss and bss sections. Can you check if the issues you had are still fixed?