| View previous topic :: View next topic |
| Author |
Message |
willow :--)
Joined: 13 Jan 2007 Posts: 126
|
Posted: Thu Mar 25, 2010 11:48 am Post subject: how is the $gp register set? |
|
|
I'm trying to change the value of the $gp register at runtime and am having a hard time doing it. I think I'm changing the value in a thread A but it gets reinitialized in a thread B.
I think I need more insight on when that register gets changed.
What I'm trying to do:
starting a thread that uses a different $gp than the code that spawned it.
My understanding:
The value of GP is attached to a module (see: modinfo in PSPLink).
Every thread that belongs to a module (how does the PSP knows which thread belongs to which module? Ram boundaries ?) uses that value for GP.
Since all threads use different code, they need to re-set the various registers they use. How are these values stored and retrieved?
My interest currently is in $gp, but I'm thinking that other registers such as $fp, $sp... are the same...
Here's how I imagine it works:
- Thread 1 starts
- Thread1 restores its registers from ???
- Thread1 does stuff
- Thread1 pauses
- Thread1 stores its current registers to ???
- Thread 2 starts
- Thread 2 restores its registers from ???
- Thread 2 does stuff...
-...
my guess for gp:
When a thread is created, the kernel(?) looks for the position of the code calling it in Ram (probably ra?) and gets the moduleid based on that. It then gets the value of GP from the module info, and that's how gp is initialized.
I'd like to know if that's correct and if any code or documentation regarding this process is available somewhere.
So my questions are:
1) Is my understanding roughly correct?
2) How does the registers save/restore sequence work? What are the sce* functions that deal with that, if any?
3) When a thread starts, how are the initial register values computed? (especially $gp) _________________ Wagic. Play that card game against an AI on your PSP |
|
| Back to top |
|
 |
willow :--)
Joined: 13 Jan 2007 Posts: 126
|
Posted: Thu Mar 25, 2010 1:51 pm Post subject: |
|
|
I think I can find partial answers to my question in this file:
http://svn.lan.st/utopia/threadman/threadman.c
I'll ask more questions after studying this
Edit:
I think that's the interesting part for me, threads are not taking GP from the thread that spawned them, but from the module they belong to.
I think this answers my questions for now
| Code: |
SceModule *mod = sceKernelFindModuleByAddress(entry);
thinfo->gpreg = mod ? mod->unk_68 : GET_GP;
|
_________________ Wagic. Play that card game against an AI on your PSP |
|
| Back to top |
|
 |
willow :--)
Joined: 13 Jan 2007 Posts: 126
|
Posted: Sun Mar 28, 2010 10:25 pm Post subject: |
|
|
Just in case somebody encounters the same kind of issue as me: I ended up bypassing the issue by doing the following:
- load some code outside of any "module" ram boundaries. That function (run) takes an address and jumps to it
- When I want to start a thread with a different GP, I set the value of GP to whatever I want, and start a thread of "run", asking it to launch the actual function.
When creating the thread, the kernel realizes I'm attempting to load a function outside of any module boundaries (run), and therefore gets the current GP value instead of that from a module _________________ Wagic. Play that card game against an AI on your PSP |
|
| Back to top |
|
 |
Coldbird

Joined: 08 Feb 2007 Posts: 155
|
Posted: Mon Mar 29, 2010 12:33 am Post subject: |
|
|
Wow... thats a pretty evil workaround isn't it?
Judging from what you said you rely on a fallback GP detection function inside the firmware? Tricky. _________________ Been gone for some time. Now I'm back. Someone mind getting me up-2-date? |
|
| Back to top |
|
 |
Davee
Joined: 22 Jun 2009 Posts: 59
|
Posted: Mon Mar 29, 2010 12:36 am Post subject: |
|
|
Below is for 5.03. It should work for other firmwares too though, I don't pay much attention to internal threadman :P
| Code: | /*
This will change a threads GP reg (theoretically).
Usage:
SceUID thid = sceKernelCreateThread(...);
change_thread_gp(thid, gp);
sceKernelStartThread();
Although it may work after the thread has started.
*/
int change_thread_gp(SceUID thid, u32 gp)
{
uidControlBlock *uidcb;
if (!gp)
{
asm volatile ("move %0, $gp\n" : "=r" (gp));
}
if (sceKernelGetUIDcontrolBlock(thid, *uidcb) != 0) //SysMemForKernel_523E300A
{
/* error */
return -1;
}
u32 *threadman_struct = (u32 *)((u32)uidcb + (uidcb->type->size * 4));
threadman_struct[212/4] = gp;
return 0;
} |
This is all theoretical. Alternatively, you could hook the LoadCoreForKernel_6C00BE57 which gets the gp to set from the module. |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Mon Mar 29, 2010 12:45 am Post subject: |
|
|
DELETED
Last edited by hlide on Mon Mar 29, 2010 12:48 am; edited 1 time in total |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Mon Mar 29, 2010 12:46 am Post subject: |
|
|
DELETED - i had a spurious message telling me a PHP bug...
Last edited by hlide on Mon Mar 29, 2010 12:47 am; edited 1 time in total |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Mon Mar 29, 2010 12:46 am Post subject: |
|
|
| willow :--) wrote: | I think I can find partial answers to my question in this file:
http://svn.lan.st/utopia/threadman/threadman.c
I'll ask more questions after studying this
Edit:
I think that's the interesting part for me, threads are not taking GP from the thread that spawned them, but from the module they belong to.
I think this answers my questions for now
| Code: |
SceModule *mod = sceKernelFindModuleByAddress(entry);
thinfo->gpreg = mod ? mod->unk_68 : GET_GP;
|
|
Do you want to use $gp as an allocatable/temporary register for *Dead*alusX64 (I couldn't resist) ?
you set $gp in thread A. There is a switch to thread B (it's normal $gp si no the same) then there is another switch to thread A : does $gp change ? if not, that's okay. I remember POPS uses $gp a lot and still it has several threads. So i'm kind suspicious it can be changed internally after switching back to thread A.
And I don't see any point for $gp being the same in thread A and B since it shouldn't be used as the usual way other OS does.
And don't forget to use options "-G0 -nogpopt" (or something like that). |
|
| Back to top |
|
 |
sauron_le_noir
Joined: 05 Jul 2008 Posts: 229
|
Posted: Mon Mar 29, 2010 1:29 am Post subject: |
|
|
-mgpopt
-mno-gpopt
Use (do not use) GP-relative accesses for symbols that are known to be in a small data section; see -G, -mlocal-sdata and -mextern-sdata. -mgpopt is the default for all configurations.
-mno-gpopt is useful for cases where the $gp register might not hold the value of _gp. For example, if the code is part of a library that might be used in a boot monitor, programs that call boot monitor routines will pass an unknown value in $gp. (In such situations, the boot monitor itself would usually be compiled with -G0.)
-mno-gpopt implies -mno-local-sdata and -mno-extern-sdata. |
|
| Back to top |
|
 |
SilverSpring
Joined: 27 Feb 2007 Posts: 115
|
Posted: Mon Mar 29, 2010 1:48 am Post subject: |
|
|
| Davee wrote: |
This is all theoretical. Alternatively, you could hook the LoadCoreForKernel_6C00BE57 which gets the gp to set from the module. |
*cough*0xA6D40F56 sceKernelGetModuleGPByAddressForKernel*cough*
That's the real name before the NID's got randomised of course. LoadCoreForKernel_6C00BE57 is the 5.xx randomised version. _________________ PSP PRX LibDocs |
|
| Back to top |
|
 |
Davee
Joined: 22 Jun 2009 Posts: 59
|
Posted: Mon Mar 29, 2010 1:50 am Post subject: |
|
|
| SilverSpring wrote: | | Davee wrote: |
This is all theoretical. Alternatively, you could hook the LoadCoreForKernel_6C00BE57 which gets the gp to set from the module. |
*cough*0xA6D40F56 sceKernelGetModuleGPByAddressForKernel*cough*
That's the real name before the NID's got randomised of course. LoadCoreForKernel_6C00BE57 is the 5.xx randomised version. |
>:D |
|
| Back to top |
|
 |
willow :--)
Joined: 13 Jan 2007 Posts: 126
|
Posted: Mon Mar 29, 2010 8:03 am Post subject: |
|
|
| Davee wrote: |
if (sceKernelGetUIDcontrolBlock(thid, *uidcb) != 0) //SysMemForKernel_523E300A
[...]
This is all theoretical. Alternatively, you could hook the LoadCoreForKernel_6C00BE57 which gets the gp to set from the module. |
I'm going to assume those are both Kernel functions, and I'm in user mode, so that wouldn't work for me
Edit: Coldbird: yes, that's exactly what I'm doing, relying on the fallback mechanism in the firmware _________________ Wagic. Play that card game against an AI on your PSP
Last edited by willow :--) on Mon Mar 29, 2010 10:20 pm; edited 1 time in total |
|
| Back to top |
|
 |
m0skit0
Joined: 02 Jun 2009 Posts: 226
|
Posted: Mon Mar 29, 2010 8:59 am Post subject: |
|
|
Effectvely, he means only user-mode access. Nice trick btw, you didn't explain it to me on our official thread xD _________________
| The Incredible Bill Gates wrote: | | The obvious mathematical breakthrough would be development of an easy way to factor large prime numbers. |
|
|
| Back to top |
|
 |
Davee
Joined: 22 Jun 2009 Posts: 59
|
Posted: Mon Mar 29, 2010 9:23 am Post subject: |
|
|
| willow :--) wrote: | | Davee wrote: |
if (sceKernelGetUIDcontrolBlock(thid, *uidcb) != 0) //SysMemForKernel_523E300A
[...]
This is all theoretical. Alternatively, you could hook the LoadCoreForKernel_6C00BE57 which gets the gp to set from the module. |
I'm going to assume those are both Kernel functions, and I'm in user mode, so that wouldn't work for me
Edit: Coolbird: yes, that's exactly what I'm doing, relying on the fallback mechanism in the firmware |
Ah well, maybe that should of been stated in the original post ;) |
|
| Back to top |
|
 |
willow :--)
Joined: 13 Jan 2007 Posts: 126
|
|
| Back to top |
|
 |
Coldbird

Joined: 08 Feb 2007 Posts: 155
|
Posted: Mon Mar 29, 2010 8:11 pm Post subject: |
|
|
It's Coldbird................ why the hell does everyone think it's Coolbird.... *shakes his head and sighs*
That aside, how did you figure out the fallback mechanism in the first place?
Did you do a asm dive yourself and found it via reversal or did Mathieulh and Co. take it off you with Project Utopia? _________________ Been gone for some time. Now I'm back. Someone mind getting me up-2-date? |
|
| Back to top |
|
 |
willow :--)
Joined: 13 Jan 2007 Posts: 126
|
Posted: Mon Mar 29, 2010 10:21 pm Post subject: |
|
|
| Coldbird wrote: | It's Coldbird................ why the hell does everyone think it's Coolbird.... *shakes his head and sighs*
|
woops, sorry about that, edited my post.
| Quote: |
That aside, how did you figure out the fallback mechanism in the first place?
Did you do a asm dive yourself and found it via reversal or did Mathieulh and Co. take it off you with Project Utopia? |
The utopia project is open source, so I just dug into it, assuming it's mostly a reverse from the OFW. (I don't have cool reverse-engineer skills yet) _________________ Wagic. Play that card game against an AI on your PSP |
|
| Back to top |
|
 |
Coldbird

Joined: 08 Feb 2007 Posts: 155
|
Posted: Mon Mar 29, 2010 11:38 pm Post subject: |
|
|
I must admit I am very interested in the Utopia Project and have been monitoring it from afar for some time now...
But thats mostly because I AM a big fan of opensource software in the first place so...
I see I see. Well I do dig a lot into asm myself, atleast I know enough to find my way around...
The only thing still a big mystery to myself is how gcc / g++ compiles more than 4 arguments in mips... :-/
Oh how I wished mips would use a argument stack like x86......... lol. _________________ Been gone for some time. Now I'm back. Someone mind getting me up-2-date? |
|
| Back to top |
|
 |
coyotebean
Joined: 05 Dec 2009 Posts: 26
|
Posted: Mon Mar 29, 2010 11:46 pm Post subject: |
|
|
| Coldbird wrote: | The only thing still a big mystery to myself is how gcc / g++ compiles more than 4 arguments in mips... :-/
Oh how I wished mips would use a argument stack like x86......... lol. |
After $a0 to $a3, then $t0 to $t3, then uses the stack. _________________ GBASP x1, GBM x2, NDSL x2, PSP 100X x3, PSP 200X x5, PSP 300X x3, PSP Go x2, Wii x1 |
|
| Back to top |
|
 |
Coldbird

Joined: 08 Feb 2007 Posts: 155
|
Posted: Mon Mar 29, 2010 11:52 pm Post subject: |
|
|
Thanks! Another mystery solved! _________________ Been gone for some time. Now I'm back. Someone mind getting me up-2-date? |
|
| Back to top |
|
 |
noob81
Joined: 07 Mar 2010 Posts: 1
|
Posted: Tue Mar 30, 2010 11:21 am Post subject: |
|
|
| Coldbird wrote: |
The only thing still a big mystery to myself is how gcc / g++ compiles more than 4 arguments in mips... :-/
|
Have been wondering the same thing myself :P Thanks for the tip, coyotebean. _________________ n00b81 |
|
| Back to top |
|
 |
|