I discovered that the "mysterious" exclusion of the InitHeap function accounted for in my previous patch is just the result of linking NOHEAP.OBJ. I've cleaned up the check for this and updated the comment.
Fixed incorrect section RWX flags that resulted from games that had no .sdata section and had .(s)bss sections that came before the end of the program data (Final Fantasy Tactics).
The instruction at offset -0x20 being used to determine the start of the .sbss section suffered the same issue as using the initial location of the gp register to determine .sdata in that it would line up with that value most of the time, but not always. This instruction was actually a reference to the symbol _rabackup, which would be the first address in .sbss if the developers linked the appropriate lib/object first. However this is not always the case of course (Soul Reaver), so a more reliable location to read this value is the very first pair of instructions in MAIN.OBJ/NOHEAP.OBJ, which is part of a memset() from .sbss to _rambase.
Handle cases where .(s)bss sections span across romEnd:
If .sbss starts beforeromEnd, and .bss starts after, .sbss will be extended to the start of .bss, rather than stopping at romEnd. Previously this resulted in an uninitialized "RAM" block between the segments. (ex: Brigandine)
If .bss starts beforeromEnd and it's specified length puts its end afterromEnd, then .bss will be extended to its specified length, rather than stopping at romEnd. Previously, .bss would just be cut short. (ex: Metal Gear Solid)
I believe that this strange disconnect between the header information and seemingly the actual data layout for games is entirely due to small data optimization (gp) by the linker. However I will admit that I can't reconcile that with the fact that linker would be responsible for creating the header to begin with, and I'm not sure why PSYLINK.EXE would handle this situation like this.
As a closing note, I've made a lot of changes to the PSX loader on my own personal branch that I feel are too extensive and perhaps opinionated to make for a good PR, but for possible future bugs/features, my repo may have something already that could help. The MIPS-specific constant propagation analyzer in particular required altering the plugin's SLEIGH metadata to enable it, but it's a huge step up from the basic analyzer.
InitHeap
function accounted for in my previous patch is just the result of linking NOHEAP.OBJ. I've cleaned up the check for this and updated the comment.gp
register to determine .sdata in that it would line up with that value most of the time, but not always. This instruction was actually a reference to the symbol_rabackup
, which would be the first address in .sbss if the developers linked the appropriate lib/object first. However this is not always the case of course (Soul Reaver), so a more reliable location to read this value is the very first pair of instructions in MAIN.OBJ/NOHEAP.OBJ, which is part of amemset()
from .sbss to_rambase
.romEnd
:romEnd
, and .bss starts after, .sbss will be extended to the start of .bss, rather than stopping atromEnd
. Previously this resulted in an uninitialized "RAM" block between the segments. (ex: Brigandine)romEnd
and it's specified length puts its end afterromEnd
, then .bss will be extended to its specified length, rather than stopping atromEnd
. Previously, .bss would just be cut short. (ex: Metal Gear Solid)I believe that this strange disconnect between the header information and seemingly the actual data layout for games is entirely due to small data optimization (gp) by the linker. However I will admit that I can't reconcile that with the fact that linker would be responsible for creating the header to begin with, and I'm not sure why PSYLINK.EXE would handle this situation like this.
As a closing note, I've made a lot of changes to the PSX loader on my own personal branch that I feel are too extensive and perhaps opinionated to make for a good PR, but for possible future bugs/features, my repo may have something already that could help. The MIPS-specific constant propagation analyzer in particular required altering the plugin's SLEIGH metadata to enable it, but it's a huge step up from the basic analyzer.