SDK initialization
SDK initialization
Hi again everybody!
I've managed to run non-signed ELFs from the MoHH exploit by kgsws.
But I ran into a problem: the ELF execute properly (at least very simple ones) if it doesn't include the SDK initialization (when I manually code module_start(), create a new thread running main(), specify PSP_NO_MAIN_THREAD() macro, and of course I include necessary linking flags on the Makefile), but it does absolutely nothing if the SDK initialization is present (the screen keeps blank). Any ideas?
I already sought some people's help, but they really had no clue xD If you need the code I'm using or any reference I'll post it, just ask me.
Thanks a lot!
I've managed to run non-signed ELFs from the MoHH exploit by kgsws.
But I ran into a problem: the ELF execute properly (at least very simple ones) if it doesn't include the SDK initialization (when I manually code module_start(), create a new thread running main(), specify PSP_NO_MAIN_THREAD() macro, and of course I include necessary linking flags on the Makefile), but it does absolutely nothing if the SDK initialization is present (the screen keeps blank). Any ideas?
I already sought some people's help, but they really had no clue xD If you need the code I'm using or any reference I'll post it, just ask me.
Thanks a lot!
The Incredible Bill Gates wrote:The obvious mathematical breakthrough would be development of an easy way to factor large prime numbers.
What code are you using? You need to place all sections to the right addresses, resolve stubs, THEN jump to the start of text section (0x0890000).
Can you post your code?
Can you post your code?
Code: Select all
%:include<stdio.h>
int _(int __,int ___,int ____,int _____)
<%for(;____<___;_____=_____*__,____++);
return _____;%>main()<%printf
("%d\n",_(2,5,0,1));%>
Yes, I do that, otherwise I wouldn't be able to run a thing, wouldn't I? :P
Here's the code; only the main function for brevity. If you need details about some function or data structure, just ask me I'll post it.
A few comments about the code:
Not ALL the sections. Only those marked as "must be allocated". And I think those are all in program section to make the loading faster (at least that's what the ELF standard paper I read said), so loading program section in the right address will suffice. Correct me if I'm wrong, but that way it works (partially as I said).You need to place all sections to the right addresses
Done. I get the stubs resolved from MoHH in a table and then load the program section from the ELF, locate the .lib.stub section and resolve the stubs. Of course, I can only resolve imports included in MoHH because they don't use fixed addresses or fixed syscalls numbers. If someone knows how can I get around this without accessing kernel mode, I'm all ears :Dresolve stubs
The entry point is specified by the ELF header, it's not a fixed address (although in PSP it's always the same, but just for safety I use the one specified in the ELF header). Btw, it's not 0x08900000 (you forgot a zero there :D), but 0x8900048 if I remember well (_start or module_start())THEN jump to the start of text section (0x0890000)
Here's the code; only the main function for brevity. If you need details about some function or data structure, just ask me I'll post it.
Code: Select all
tNIDResolver nid_table[NID_TABLE_SIZE];
/* eloader entry point */
void start_eloader(char *eboot_path)
{
unsigned int num_nids, stubs_size, stubs_resolved;
tStubEntry* pstub_entry;
SceUID elf_file;
unsigned int elf_size;
Elf32_Ehdr elf_header;
#ifdef DEBUG
dbglog = sceIoOpen(DEBUG_PATH, PSP_O_CREAT | PSP_O_WRONLY, 0777);
#endif
/* Extract resolved imports from game */
if(num_nids = build_nid_table((tStubEntry *) MOHH_LIBSTUB_ADDRESS, nid_table))
{
/* Open ELF */
elf_file = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777);
/* Read ELF header */
sceIoRead(elf_file, &elf_header, sizeof(Elf32_Ehdr));
/* Load ELF program section into memory */
elf_size = elf_load_program(elf_file, &elf_header);
/* Locate ELF's .lib.stubs section */
stubs_size = elf_find_imports(elf_file, &elf_header, &pstub_entry);
/* Resolve ELF's stubs with game's stubs */
stubs_resolved = resolve_imports(pstub_entry, stubs_size, nid_table);
/* No need for ELF file anymore */
sceIoClose(elf_file);
/* Commit changes to RAM */
sceKernelDcacheWritebackInvalidateAll();
/* Go for ELF! */
execute_elf((u32 *)elf_header.e_entry);
}
#ifdef DEBUG
sceIoClose(dbglog);
#endif
}
- I'm just considering static ELFs, not PRXs (by now). Just to simplify. If statics work, then relocation should be easy and would work without much problem (I hope xD)
- I'm using fixed-size data structures because malloc() didn't work with the exploit's SDK. I didn't try to make it work neither. I'll check that later, it's just optimization.
- Code is not optimized, just the first thought I got about it.
- The aim is of course getting an EBOOT.PBP instead of an ELF. But I think that if I get the ELFs to work, extracting them from PBPs will be fairly easy.
The Incredible Bill Gates wrote:The obvious mathematical breakthrough would be development of an easy way to factor large prime numbers.
Take a look at pspsdk/src/startup/crt0.c. That's the crt0 (initialization code) for ELF. try to use it in your application and check if it works. if it doesn't, try commenting out some things until it works. Then you'll know what prevent the ELF from loading.
EDIT: You said malloc doesn't work. Maybe it's a libc problem, in fact crt0 does some lib calls. have you tried the following in the Makefile of the elf?
also try PSP_NO_CREATE_MAIN_THREAD().
EDIT: You said malloc doesn't work. Maybe it's a libc problem, in fact crt0 does some lib calls. have you tried the following in the Makefile of the elf?
Code: Select all
USE_KERNEL_LIBC = 1
USE_KERNEL_LIBS = 1
Code: Select all
%:include<stdio.h>
int _(int __,int ___,int ____,int _____)
<%for(;____<___;_____=_____*__,____++);
return _____;%>main()<%printf
("%d\n",_(2,5,0,1));%>
you said:m0skit0 wrote:I already said that the ELF execute if I put this macro :)also try PSP_NO_CREATE_MAIN_THREAD().
Thanks for the ideas, I'll try and report any news.
i mean to use ONLY PSP_NO_MAIN_THREAD, without manually coding _start.m0skit0 wrote:when I manually code module_start(), create a new thread running main(), specify PSP_NO_MAIN_THREAD() macro, and of course I include necessary linking flags on the Makefile
Code: Select all
%:include<stdio.h>
int _(int __,int ___,int ____,int _____)
<%for(;____<___;_____=_____*__,____++);
return _____;%>main()<%printf
("%d\n",_(2,5,0,1));%>
ehhh??? but it's very strange!m0skit0 wrote:Then you got an error: "module_start" not found :P
from crt0.c:
Code: Select all
/**
* Startup thread
*
* Creates the main program thread based on variables defined by the program.
*
* @param args - Size (in bytes) of arguments passed to the program by the kernel.
* @param argp - Pointer to arguments passed by the kernel.
*/
int _start(SceSize args, void *argp)
{
void (*_main_func)(SceSize args, void *argp) = _main;
void (*_init_func)(void) = _init;
if ((&module_info != NULL) && (module_info.modattribute & 0x1000)) {
/* If we're running in kernel mode, the addresses of our _main() thread
and _init() function must also reside in kernel mode. */
_main_func = (void *) ((u32) _main_func | 0x80000000);
_init_func = (void *) ((u32) _init_func | 0x80000000);
}
/* Call _init() here, because an app may have code that needs to run in
kernel mode, but want their main() thread to run in user mode. If they
define "constructors" they can do any kernel mode initialization here
before their app is switched. */
_init_func();
if (&sce_newlib_nocreate_thread_in_start != NULL) {
/* The program does not want main() to be run in a seperate thread. */
_main_func(args, argp);
return 1;
}
int priority = DEFAULT_THREAD_PRIORITY;
unsigned int attribute = DEFAULT_THREAD_ATTRIBUTE;
unsigned int stackSize = DEFAULT_THREAD_STACK_KB_SIZE * 1024;
const char *threadName = DEFAULT_MAIN_THREAD_NAME;
if (&sce_newlib_priority != NULL) {
priority = sce_newlib_priority;
}
if (&sce_newlib_attribute != NULL) {
attribute = sce_newlib_attribute;
}
if (&sce_newlib_stack_kb_size != NULL) {
stackSize = sce_newlib_stack_kb_size * 1024;
}
if (&sce_newlib_main_thread_name != NULL) {
threadName = sce_newlib_main_thread_name;
}
/* Does the _main() thread belong to the User, VSH, or USB/WLAN APIs? */
if (attribute & (PSP_THREAD_ATTR_USER | PSP_THREAD_ATTR_USBWLAN | PSP_THREAD_ATTR_VSH)) {
/* Remove the kernel mode addressing from the pointer to _main(). */
_main_func = (void *) ((u32) _main_func & 0x7fffffff);
}
SceUID thid;
thid = sceKernelCreateThread(threadName, (void *) _main_func, priority, stackSize, attribute, 0);
sceKernelStartThread(thid, args, argp);
return 0;
}
Code: Select all
#define PSP_NO_CREATE_MAIN_THREAD ( ) int sce_newlib_nocreate_thread_in_start = 1
module_start is only an alias to _start, but it's defined ONLY when building prx (see crt0_prx.c). are you sure you aren't building with BUILD_PRX=1??? it seems strange to me...
Code: Select all
%:include<stdio.h>
int _(int __,int ___,int ____,int _____)
<%for(;____<___;_____=_____*__,____++);
return _____;%>main()<%printf
("%d\n",_(2,5,0,1));%>
Ok, my mistake, I apologize! When I have some time I'll try playing with crt0.c to see what my ELF loader doesn't like from here. I'll answer as soon as I get some answers :)
The Incredible Bill Gates wrote:The obvious mathematical breakthrough would be development of an easy way to factor large prime numbers.
Can you give me some advice about why the modifications in crt0.c doesn't affect at all? I mean, I modify that file but that seems not to affect the initialization code in my app. How can I do to test a modified crt0.c?
Sorry for the n00bishness :P
Sorry for the n00bishness :P
The Incredible Bill Gates wrote:The obvious mathematical breakthrough would be development of an easy way to factor large prime numbers.
you'll have modify it from the pspsdk source, recompile pspsdk and try.m0skit0 wrote:Can you give me some advice about why the modifications in crt0.c doesn't affect at all? I mean, I modify that file but that seems not to affect the initialization code in my app. How can I do to test a modified crt0.c?
Sorry for the n00bishness :P
you can also include crt0.c in your application, then use -mno-crt0 in your makefile to tell the compiler to not include crt0.
EDIT: There's a third way. take pspsdk source, modfiy crt0, make (only startup directory). copy crt0.o in your pspsdk and try...
Code: Select all
%:include<stdio.h>
int _(int __,int ___,int ____,int _____)
<%for(;____<___;_____=_____*__,____++);
return _____;%>main()<%printf
("%d\n",_(2,5,0,1));%>
BTW, take a look at this message: http://forums.ps2dev.org/viewtopic.php?p=26585#26585
to jump to text segment, don't use j/jr, use jal or when crt0 exits it'll return to $ra, but $ra doesn't point to the end of your loader code, and it'll crash!!! :)
to jump to text segment, don't use j/jr, use jal or when crt0 exits it'll return to $ra, but $ra doesn't point to the end of your loader code, and it'll crash!!! :)
Code: Select all
%:include<stdio.h>
int _(int __,int ___,int ____,int _____)
<%for(;____<___;_____=_____*__,____++);
return _____;%>main()<%printf
("%d\n",_(2,5,0,1));%>
Thanks for pointing out that link, very useful. I don't know I've not visited it earlier :P
The fact is that it seems that default stack allocation by SDK initialization is the problem. If I down the 256 KB reserved by default, it do work. So I'm considering freeing the MoHH reserved memory, but sincerly I've never used dynamic allocation on PSP. Which functions should I use? sceKernelAllocPartitionMemory() and the like? Any useful info about how to use such functions?
Thanks!
The fact is that it seems that default stack allocation by SDK initialization is the problem. If I down the 256 KB reserved by default, it do work. So I'm considering freeing the MoHH reserved memory, but sincerly I've never used dynamic allocation on PSP. Which functions should I use? sceKernelAllocPartitionMemory() and the like? Any useful info about how to use such functions?
Thanks!
The Incredible Bill Gates wrote:The obvious mathematical breakthrough would be development of an easy way to factor large prime numbers.
I suggest you to dump all the UIDs for allocated memory blocks, so you'll see what's allocated by MoHH. But you can't do that in usermode, so we need to find another way. I suggest you to reverse MoHH, find the exitcallback registration function, reverse the exit callback and see what it does to free memory. That way you can free MoHH memory and get memory for your homebrew.m0skit0 wrote:Thanks for pointing out that link, very useful. I don't know I've not visited it earlier :P
The fact is that it seems that default stack allocation by SDK initialization is the problem. If I down the 256 KB reserved by default, it do work. So I'm considering freeing the MoHH reserved memory, but sincerly I've never used dynamic allocation on PSP. Which functions should I use? sceKernelAllocPartitionMemory() and the like? Any useful info about how to use such functions?
Thanks!
Code: Select all
%:include<stdio.h>
int _(int __,int ___,int ____,int _____)
<%for(;____<___;_____=_____*__,____++);
return _____;%>main()<%printf
("%d\n",_(2,5,0,1));%>
BTW, can you send me a PM with the source code of your loader? i'm very interested :)
Thanks!
Thanks!
Code: Select all
%:include<stdio.h>
int _(int __,int ___,int ____,int _____)
<%for(;____<___;_____=_____*__,____++);
return _____;%>main()<%printf
("%d\n",_(2,5,0,1));%>