I assume the reader knows how the library imports work, I am not going to go over it again :)
If a library has variable imports it sets up an extra pointer after the function and nid pointers are taken care of. This points to a table which has the structures of:
Code: Select all
struct VariableImport {
u32 *pFixups;
u32 nid;
};
Each fixup table is a list of 32bit integers terminated with a value of 0. Each entry represents one code fixup, the lower 26bits are the address of the fixup dividing by 4, the upper 6 bits correspond to the standard MIPS ELF relocation numbers which indicate what part to fixup, e.g.
Code: Select all
// MIPS Reloc Entry Types
#define R_MIPS_NONE 0
#define R_MIPS_16 1
#define R_MIPS_32 2
#define R_MIPS_REL32 3
#define R_MIPS_26 4
#define R_MIPS_HI16 5
#define R_MIPS_LO16 6
etc...
Now to do this properly I think would require modifying the toolchain itself, something I am not in the mood to do, therefore my proposed solution is thus.
For every variable you use allocate a single 32bit integer and add the entry to fixup it's value as a whole. This can then be referenced by your code through a direct pointer rather than having to fix it up in the code itself.
So if you export say 'int myvariable;' then in your linked app you would get 'int * const pmyvariable;' Not as clean as I would like but hey them are the breaks. I might see if I can do this sooner or later, it would require some modification to the SDK.
If anyone thinks of a way to implement this properly without toolchain modifications I am all ears ;)