Talk:PRX

From PS3 Developer wiki
Revision as of 19:23, 5 October 2014 by AlexAltea (talk | contribs) (PPURELA Segment)
Jump to navigation Jump to search

This is all wrong atm. The actual symbol table is later in the second LOAD section.

Just jotting some things down quick before I forget.

Second LOAD section:

  • First: Big list of pointers to all functions?
  • Second: ????? Possibly something to do with symbol mapping. Seems to mostly always point somewhere in the magical Table 6.
  • Third: Here we go. Long pointer to function name, long pointer to pointer to function, and a zero.
  • Fourth: Fuck if I know. More mapping stuff? More pointing to Table 6.
  • Fifth: Appears to be... data? Some strings, some floats, some other nonsense. Lots of 0x9EC? Or is that just the PRX I'm looking at? This goes on for a good long time, there might actually be two tables here.
  • Sixth: Where the magic happens. Starts off with a bunch of pointers into itself (some kind of initialization hint?). Speaking of pointers to pointers, this is where those pointers being pointed to are. Each one is paired with a long next to it, which is almost always the same number across the PRX. Possibly a unique module ID? It shows up in the dep table (what I thought was the symbol table) too.

3 and 6 are the fun ones, and together let you map code blocks to function names. There's still a lot of mysteries to be found though.Roothorick 03:40, 23 June 2013 (MSK)

try the idc scripts from IDA pro disassembler and debugger, they might give you some additional information --Nas plugi 15:20, 23 June 2013 (MSK)

So as of now is it not possible to get function addresses using the FNID? Right now I can hook functions but only for a normal game(e.g. using .lib.stub to parse all entries and then I use library name+fnid and I get a pointer that points to the normal stub entry in the ELF, eg the one with the bctr instruction) However I would like to also hook VSH calls to prxs and sadly vsh uses some VERY strange method to load and call prxs. So what I would like to do is get the VA of the PRX function itself(the value in ctr). Of course this can too be done be automatically disassembling the stub jumper(bctr) as it's just a hardcoded jump address ORIS R12,R12,hi lwz r12, lo(r12) and then r12 is a pointer to the func entry address; but alas this too applies only for normal game ELFs. We can get the PRX image in RAM so how the hell are NIDs used??Pspdude 18:36, 25 June 2013 (MSK)

There is some basic info about vsh/sprx in wiki and has been tolk several times with different people to expand all pages related, the initial attempt was to make a tree of pages dependand of XMB. Most specifically the pages: VSH that is a bit empty, VSH_module-action with a list of modules availables from xmb_plugin.sprx and/or xmb_ingame.sprx, XMB_XML_Coding and XMB_modding about how modules are called from xmb .xml files (theoricaly you could make a call to a custom sprx if is correctly indexed from a custom XMB icon) --Sandungas 20:07, 25 June 2013 (MSK)

Sandungas: Hmm yes I see what you mean about the custom XMB icon, however I can also just load_start by placing it as proxy eg. in the place of sacd.sprx and then load_start sacd_orig.sprx(or not). I think it would be useful to be able to intercept calls to eg. cellHttps library. --Pspdude 21:47, 25 June 2013 (MSK)

Ok after digging in kakaroto's ps3ida sprx idc I know how a little more about ps3 sprx but to find this information, you must parse the whole file going back and forth; which is suboptimal at best to do that while running your game/app/vsh... How does lv2 know the TOC base and start of .opd for every prx it loads?--Pspdude 23:20, 27 June 2013 (MSK)

lv2: prolly calculation via elf header and descriptors, its all in there -- Mysis

FNID generation

here's some code in c# with the example "sys_crash_dump_get_user_log_area"

 void main()
 { 
   byte[] input = GetBytes(BitConverter.ToString(Encoding.UTF8.GetBytes("sys_crash_dump_get_user_log_area")).Replace("-","") + "6759659904250490566427499489741A");
   Console.WriteLine(BitConverter.ToInt32( SHA1CryptoServiceProvider.Create().ComputeHash(input) ,0 ).ToString("X0"));
 }
 byte[] GetBytes(string str)
 {
   byte[] bytes = new byte[str.Length / 2];
   for (int i = 0; i < str.Length; i += 2)
       bytes[i / 2] = byte.Parse(str.Substring(i, 2), System.Globalization.NumberStyles.HexNumber);
   return bytes;
 }


PPURELA Segment

I am not sure why hasn't this been mentioned yet. Its PHDR type value is: 0x700000A4 (PT_SCE_PPURELA).

struct
{
    u64 offset; // Offset in the second load segment
    u16 unk0;   // ???
    u8  index;  // Seems that: 0 -> First LOAD segment, 1 -> Second LOAD segment
    u8  type;   // ??? Not sure what happens when type != 1.
    u32 unk1;   // ???
    u64 ptr;    // Offset of the pointer (while patching add the base address where the segment was allocated).
};

My guess is that this segment is used to patch the addresses of the second LOAD segments like this (this may be wrong, but so far it has been proven to work for my emulator's dynamic loader):

for (auto& rel : ppurela_table) {
    if (rel.type == 1) {
        const u32 addr = prx->load_segments[1].addr + rel.offset;
        const u32 value = prx->load_segments[rel.index].addr + rel.ptr;
        write32(addr, value);
    }
}

Has anyone worked on this previously? / Can someone confirm this? -- AlexAltea