Ok, time to more serious things: resolving stubs. But for that we need to know first what a stub is and what structure it has.
Stubs are functions imported by an executable. We call a function "imported" when its implementation (the actual code) is not included in the executable itself, but in the OS. So the OS has to resolve these imports, that is, make those imported functions point to the right OS code (doing a jump or a syscall in our case here). As we saw before, ELF stubs are this way before being loaded:
Code: Select all
; Section .sceStub.text - Address 0x08C92974
0x08C92974: 0x03E00008 '....' - jr $ra
0x08C92978: 0x00000000 '....' - nop
0x08C9297C: 0x03E00008 '....' - jr $ra
0x08C92980: 0x00000000 '....' - nop
0x08C92984: 0x03E00008 '....' - jr $ra
0x08C92988: 0x00000000 '....' - nop
0x08C9298C: 0x03E00008 '....' - jr $ra
0x08C92990: 0x00000000 '....' - nop
0x08C92994: 0x03E00008 '....' - jr $ra
0x08C92998: 0x00000000 '....' - nop
0x08C9299C: 0x03E00008 '....' - jr $ra
0x08C929A0: 0x00000000 '....' - nop
0x08C929A4: 0x03E00008 '....' - jr $ra
0x08C929A8: 0x00000000 '....' - nop
0x08C929AC: 0x03E00008 '....' - jr $ra
0x08C929B0: 0x00000000 '....' - nop
0x08C929B4: 0x03E00008 '....' - jr $ra
0x08C929B8: 0x00000000 '....' - nop
0x08C929BC: 0x03E00008 '....' - jr $ra
0x08C929C0: 0x00000000 '....' - nop
0x08C929C4: 0x03E00008 '....' - jr $ra
0x08C929C8: 0x00000000 '....' - nop
0x08C929CC: 0x03E00008 '....' - jr $ra
0x08C929D0: 0x00000000 '....' - nop
...Code: Select all
; Section .sceStub.text - Address 0x08C92974
0x08C92974: 0x0A200020 ' . .' - j loc_08800080
0x08C92978: 0x00000000 '....' - nop
0x08C9297C: 0x0A20002B '+. .' - j loc_088000AC
0x08C92980: 0x00000000 '....' - nop
0x08C92984: 0x03E00008 '....' - jr $ra
0x08C92988: 0x00088A8C '....' - syscall 0x222A
0x08C9298C: 0x03E00008 '....' - jr $ra
0x08C92990: 0x00088B8C '....' - syscall 0x222E
0x08C92994: 0x03E00008 '....' - jr $ra
0x08C92998: 0x00088C8C '....' - syscall 0x2232
0x08C9299C: 0x03E00008 '....' - jr $ra
0x08C929A0: 0x000882CC '....' - syscall 0x220B
0x08C929A4: 0x03E00008 '....' - jr $ra
0x08C929A8: 0x000886CC '....' - syscall 0x221B
0x08C929AC: 0x03E00008 '....' - jr $ra
0x08C929B0: 0x0008874C 'L...' - syscall 0x221D
0x08C929B4: 0x03E00008 '....' - jr $ra
0x08C929B8: 0x00084D8C '.M..' - syscall 0x2136
0x08C929BC: 0x03E00008 '....' - jr $ra
0x08C929C0: 0x00084E8C '.N..' - syscall 0x213A
...For this, there's an ELF section named .lib.stubs that has stub headers like this one:
Code: Select all
typedef struct
{
u32 library_name_index;
u16 import_flags;
u16 library_version;
u16 import_stubs;
u16 stub_size;
u32* nid_pointer;
u32* jump_pointer;
} tStubEntry;* library_name_index: this is an index in string table section that holds library name as a NULL terminated character string.
* stub_size: number of stubs to resolve for this library.
* nid_pointer: address of first NID of library in NIDs array.
* jump_pointer: address of first stub to be resolved in stubs array (like seen before
What is a NID? A NID is a 32-bit universal identifier for FW functions. This way, FW recognizes what function we're talking about, just by an integer. For most functions this is first 32-bits of SHA-1 hash of function name, but some NIDs were just randomized by Sony back in 2.70 FW IIRC.
Now it's so simple: we just have to resolve all stubs indicated in each stub header. For each library (we don't even need to know the name, as NIDs are universal
Code: Select all
/* Resolves imports in ELF's program section already loaded in memory */
unsigned int resolve_imports(tStubEntry* pstub_entry, unsigned int stubs_size, tNIDResolver* nid_table)
{
int i,j;
u32* cur_nid;
u32* cur_call;
unsigned int resolving_count = 0;
/* Browse ELF stub's headers */
for(i=0; i<stubs_size; i+=sizeof(tStubEntry))
{
cur_nid = pstub_entry->nid_pointer;
cur_call = pstub_entry->jump_pointer;
/* For each stub header, browse all stubs */
for(j=0; j<pstub_entry->stub_size; j++)
{
/* Resolve stub */
resolve_call(cur_nid, cur_call);
/* Next NID */
cur_nid++;
/* Next stub (8 bytes each) */
cur_call += 2;
/* Update count */
resolving_count++;
}
/* Next stub */
pstub_entry++;
}
return resolving_count;
}
Advertising

