PS2DEV network    

  > HOME
  > ABOUT

  > FORUMS
  > VIEW SVN
  > MAILING LIST
  > WIKI
  > QUOTES
  > DOCS

 PS2
  > TUTORIALS
  > LOADERS
  > TOOLS
  > SAMPLE CODE
  > DEMOS
  > PROJECTS

 PSP
  > TUTORIALS
  > TOOLS
  > DEMOS
  > PROJECTS

 PS3
  > LINKS
  > TUTORIALS
  > TOOLS
  > DEMOS
  > PROJECTS

   RSS


 USER ID (register)
 
 PASSWORD
 



 
  IRX Files
INTRODUCTION
-------------

The heart of the whole PS2 is its IO processor (PS1). It works by a lot
of
chained modules, that inter-communicate themselves and some of these
modules provide communication to the EE (rpc).

Well, I have figured out how the modules works, how do they load, how do
they communicate with kernel, and how do they provide functions to other
iop modules.

IRX MODULE FILE
----------------

First of all, an .irx file is a modified version of a regular elf object
file. The difference is this file has executable extensions but also has
its relocation table without its symbol table. (read below and you'll
understand that)

When the kernel loads up a module, it seeks for a specific section
called
".iopmod" (section type 0x70000080), which has all the info iop wants.
This section is a structure like this: (to better understand this, you
should manage how an elf file works)

offset type description
------------------------------------------------------------------------
0x0 addr32 pointer to a "module" structure
this "module" structure is something like:
u16 attribute (is it version?)
char * module_name

0x4 addr32 start address (the same as the elf is)
0x8 addr32 this is some kind of "heap" start.
this value is calculated by adding
0x7ff0 + sizeof(data section) +
                                         sizeof(text section)
0xc u32 text_section size
0x10 u32 data_section size
0x14 u32 bss_section size
0x18 u16 module_structure attribute
0x1a char * module_name

The module process of loading is based on the .irx organization.
When a .irx is generated the file block is arranged like this:

           | CODE BLOCK | DATA BLOCK | BSS BLOCK |

There is a reason for that organization. When the kernel loads up the
iopmod section, it sums the text_size + data_size + bss_size. It
allocates
this ammount of memory inside iop memory. After that, it moves all data
to
this allocated segment, and (the trickiest part) loads the relocation
sections. It just sums the relocations (depending of each type, of
course) by the base iop allocated memory address. This is the reason it
doesn't need the symbol table, because it has been previously "used".
Now it just executes the "start address" and everything run.


LIBRARIANS, INTER_MODULE_COMMUNICATION
---------------------------------------

IOP has a small memory size (2M). If you manage to include the standard
libs or something like that for each module, you would probably have a
few
modules running, not dozens of it. Sony has used some very good tricks
for
its inter_module_communication. You might be asking yourself, why didn't
sony used dynamic linking. The answer is quiet easy: first of all, sony
didn't want everyone watching around modules symbol tables (I
wouldn't) and the kernel implementation would get more complex and I
guess
they didn't want to spend memory to do that.

To solve that point, they implemented some "zero register exception
handler" that will call the apropriate function. To better understand
that, I'll paste some .irx file I've found out there, containing debug
information. (You should look for them too... many, many games always
have
something good).

HOW TO IMPORT FUNCTIONS
------------------------

000000000000e570 <libsd_stub>:
    e570:       41e00000        0x41e00000     < MAGIC NUMBER
    e574:       00000000        nop            < ALWAYS ZERO
    e578:       00000104        0x104          < VERSION?
    e57c:       7362696c        0x7362696c     < "libsd"
    e580:       00000064        0x64           ^

000000000000e584 <sceSdInit>:                  < function references
    e584:       03e00008        jr      $ra
    e588:       24000004        li      $zero,4

When an exception is generated, it goes backwards the memory until it
finds the '0x41e00000'. After that, it looks for the library reference
name "libsd" and the kernel already knows the function reference name.
With this information, it's easy to write a simple program to find out
import references (and export too).


HOW TO EXPORT FUNCTIONS
------------------------

This method is quite similar to the importation one. What changes is the
magic number and the functions references. The 'stub' is the same (the
magic number for export is 0x41c00000. The functions reference is an
array
of addresses finished with a NULL entry.

Only by these magic numbers, is totally easy to track down kernel
functions, describing which functions are importable and exportable
and so on. It's possible to start reconstructing the symbol table
of a symbol-less table module, only by cross referencing the
functions.

You might look further inside the kernel modules, they are all irx
modules. You can disassemble each one of modules function and see
exactly
how the kernel work.


  > Locked
  > Edit Topic
  > Add Topic
  > Add Link
  > Add File
  > Move Topic
  > Delete Topic
  > Order Topics
  > Versions

Owned by oobles
last updated by oobles on Tue Jun 19 00:00:00 GMT 2001
 
Site Content Copyright 2001-2007 © Authors. Read Legal Statement for Information
LiveKnowledge Software by Live Media