Coder Social home page Coder Social logo

ghidra_psx_ldr's People

Contributors

boricj avatar discorddottest avatar itendswithtens avatar ivandsm avatar lab313ru avatar markisha64 avatar nicolasnoble avatar twevs avatar xyzz avatar zinfidel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ghidra_psx_ldr's Issues

Could not initialize class ghidra.formats.gfilesystem.factory.FileSystemFactoryMgr

Hey, installed 6.3 to ~/ghidraRun. I get the below when trying to import a file. Not sure what's really going on.

Could not initialize class ghidra.formats.gfilesystem.factory.FileSystemFactoryMgr$Singleton
java.lang.NoClassDefFoundError: Could not initialize class ghidra.formats.gfilesystem.factory.FileSystemFactoryMgr$Singleton
	at ghidra.formats.gfilesystem.factory.FileSystemFactoryMgr.getInstance(FileSystemFactoryMgr.java:46)
	at ghidra.formats.gfilesystem.FileSystemService.<init>(FileSystemService.java:144)
	at ghidra.formats.gfilesystem.FileSystemService.<init>(FileSystemService.java:159)
	at ghidra.formats.gfilesystem.FileSystemService.getInstance(FileSystemService.java:63)
	at ghidra.plugin.importer.ImporterPlugin.importFile(ImporterPlugin.java:177)
	at ghidra.plugin.importer.ImporterPlugin.doSingleImportAction(ImporterPlugin.java:346)
	at ghidra.plugin.importer.ImporterPlugin$1.actionPerformed(ImporterPlugin.java:216)
	at docking.ExecutableAction.execute(ExecutableAction.java:40)
	at docking.action.MultipleKeyAction.actionPerformed(MultipleKeyAction.java:142)
	at java.desktop/javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1810)
	at docking.KeyBindingOverrideKeyEventDispatcher.actionInProgress(KeyBindingOverrideKeyEventDispatcher.java:219)
	at docking.KeyBindingOverrideKeyEventDispatcher.dispatchKeyEvent(KeyBindingOverrideKeyEventDispatcher.java:117)
	at java.desktop/java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1133)
	at java.desktop/java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:1009)
	at java.desktop/java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:835)
	at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4892)
	at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2321)
	at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2772)
	at java.desktop/java.awt.Component.dispatchEvent(Component.java:4843)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:772)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:95)
	at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
	at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:743)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

---------------------------------------------------
Build Date: 2021-Dec-22 0027 CET
Ghidra Version: 10.1.1
Java Home: /usr/lib/jvm/java-11-openjdk
JVM Version: Oracle Corporation 11.0.13
OS: Linux 5.16.0-arch1-1 amd64
Workstation: sanic.local

Default memory mappings

By default, we should have certain memory address spaces always created. System RAM at 0x00000000, Expansion 1 at 0x1F000000, ScratchPad at 0x1F800000-3FF, MMIO at 0x1F801000-1FFF. Expansion 2 at 0x1F802000-7F(IIRC), Expansion 3 at 0x1FA00000-0x1FBFFFFF. BIOS/Boot/ROM at 0x1FC00000. And there's the odd cache control stuff at 0xFFFE0130 which I don't know the full size of so might want to have 0xFFFE0000-0xFFFEFFFF mapped for that?

See my other issue about memory address mirroring as well.

Fails to resolve global addresses in code which is not auto-analyzed.

The game I'm working on has overlays, and because of the overlays, there are certain functions in the executable which are not detected as functions by Ghidra when initially loaded, because they are only referenced by overlays which are not loaded initially.

When I use the 'D' keybind to disassemble the data, ghidra_psx_loader does not seem to handle this properly, as the references to $gp are not turned into their global references, and instead are represented as "iGp" + the offset from $gp. This is quite annoying, as this requires manually looking up what data a particular piece of code is accessing.

Here's a good example:
image

jalr instructions

First of all, thanks you very much for all of your excellent work!

I'm trying to analyze the Team Buddies game (SCES-01923). It was a really fun game, and especially a really well designed game. Two papers have been written about its internal design:

The game uses overlays, and I can understand the way it does but also load the overlays into Ghidra and reference the functions into them.

But I face some problems and I wonder if it's from the game instructions or me not doing the right thing.

In the main function, an OVERLAY.DAT file is loaded, it contains entries of 48 bytes each. Every entry have a name (e.g. SYS.BIN) and it seem to also have an offset.

The struggle comes when calling a function which is inside an overlay. When the jal instruction is used it's easy, I just have to patch the instruction with the right address and reference the overlay. But sometimes the jalr instruction is used, so the address is computed from the memory.

  FUN_8001a474("\\OVERLAY.DAT;1");
  DAT_80010204 = (code **)&DAT_80010184;
  $loadOverlayEntry(0);
  (*DAT_80010204[6])();
  (*DAT_80010204[7])();
  (*DAT_80010204[9])();
  $loadOverlayEntry(1);
  $loadOverlayEntry(3);
  (**DAT_80010204)();
  (*DAT_80010204[6])();

(the $loadOverlayEntry was renamed by me)

At the moment, to get the right addresses used by the jalr instructions, I use no$psx to debug the game and read the address from the register.

So have you ever encounter such behaviours? If so, how do you deal with them?

I've not attached any of the game file here but I can if you want.

Coprocessor 2 (GTE) instructions use incorrect registers

There are 6 store/load instructions for the GTE (LWC2, SWC2, MTC2, MFC2, CTC2, and CFC2) that come in 3 forms:

LWC2 gd, imm(base)
MTC2 rt, gd
CTC2 rt, gc

where gd is a GTE data register (0-31) and gc is a GTE control register (0-31). Using the plugin, Ghidra disassembles these instructions interpreting the first operands as either CPU registers
or constant values, however. This leads to disassembly that looks like:
javaw_c6A9IPEDDT
Notice that MTC2's second operand is listed as 0x0, where it should be the data register gd0, which happens to be the VXY0 register. For the LWC2 command, the gd operand is interpreted as CPU register 1 (at) instead of GTE data register 1 (VZ0).

The decompiled code is similarly affected:
javaw_1i4TDPIGxb
Here, iVar1 and iVar8 just happen to be associated with CPU registers 0 and 1, and so they get placed in the function call incorrectly.

Just a disclaimer, I'm a real novice with Ghidra so I'm not sure if this is a problem with the plugin, Ghidra itself, or just me!

Detect and load Parallel IO port ROMs(Action Replay, GameShark, Caetla, etc)

The Parallel I/O port on the back of the console maps to memory address 0x1F000000. Valid ROMs can be identified with offsets:
0x00000004: "Licensed by Sony Computer Entertainment, Inc."
0x00000084: "Licensed by Sony Computer Entertainment, Inc."

By default, the BIOS creates a memory region of 0x1F000000-0x1F07FFFF for the PIO port but software can easily change the size anywhere between 1 and 0x00800000 bytes. I would suggest and "uninitialized" segment be used and 0x00800000 be the size.

Entry points will be the 32-bit addresses at offset 0x00000000 and 0x00000080. If value is NULL(0x00000000) that entry point wont be used.

PsyQ signatures applier doesn't work

Upon trying to decompile King's Field (USA)'s GAME.EXE, running the PsyQ signatures applier (both manually and automatically) yields no reuslts. Here's a comparison between the result obtained with Ghidra 9.1.2 + latest git ghidra_psx_ldr vs the REDAsm identification for the PsyQ functions.

Ghidra 9.1.2 + latest git ghidra_psx_ldr:

                             LAB_80013634                                    XREF[1]:     8004a630(j)  
        80013634 e8 ff bd 27     addiu      sp,sp,-0x18
        80013638 10 00 bf af     sw         ra,0x10(sp)=>DAT_801fffe8                        = ??
        8001363c 88 29 01 0c     jal        FUN_8004a620                                     undefined FUN_8004a620(void)
        80013640 00 00 00 00     _nop
        80013644 1f 80 05 3c     lui        param_2,0x801f
        80013648 00 80 a5 34     ori        param_2,param_2,0x8000
        8001364c 1e 80 04 3c     lui        param_1,0x801e
        80013650 5c af 84 24     addiu      param_1=>DAT_801daf5c,param_1,-0x50a4            = ??
        80013654 35 2a 01 0c     jal        FUN_8004a8d4                                     undefined FUN_8004a8d4(undefined
        80013658 23 28 a4 00     _subu      param_2,param_2,param_1
        8001365c d0 30 01 0c     jal        FUN_8004c340                                     undefined FUN_8004c340(undefined
        80013660 00 00 00 00     _nop
        80013664 43 7d 01 0c     jal        FUN_8005f50c                                     undefined FUN_8005f50c(undefined
        80013668 21 20 00 00     _clear     param_1
        8001366c 26 2b 01 0c     jal        FUN_8004ac98                                     undefined FUN_8004ac98(void)
        80013670 01 00 04 34     _ori       param_1,zero,0x1
        80013674 25 80 01 0c     jal        FUN_80060094                                     undefined FUN_80060094(void)
        80013678 21 20 00 00     _clear     param_1
        8001367c 3d 80 01 0c     jal        FUN_800600f4                                     undefined FUN_800600f4(void)
        80013680 00 00 00 00     _nop
        80013684 a7 4d 00 0c     jal        FUN_8001369c                                     undefined FUN_8001369c()
        80013688 00 00 00 00     _nop
        8001368c 10 00 bf 8f     lw         ra,0x10(sp)=>DAT_801fffe8                        = ??
        80013690 00 00 00 00     nop
        80013694 08 00 e0 03     jr         ra
        80013698 18 00 bd 27     _addiu     sp,sp,0x18

REDasm 2.1.1-20190523.8848416:

loc_80013634:
TEXT:80013634      addiu $sp, $sp, -18
TEXT:80013638      sw $ra, 10($sp)
TEXT:8001363C      jal nullsub_8004A620
TEXT:80013640      nop 
TEXT:80013644      lui $a1, 801F
TEXT:80013648      ori $a1, $a1, 8000
TEXT:8001364C      lui $a0, 801E
TEXT:80013650      addiu $a0, $a0, -50A4
TEXT:80013654      jal sub_8004a8d4
TEXT:80013658      subu $a1, $a1, $a0
TEXT:8001365C      jal sub_8004c340
TEXT:80013660      nop 
TEXT:80013664      jal sub_8005f50c
TEXT:80013668      move $a0, $zero
TEXT:8001366C      jal LIBCARD.InitCARD2
TEXT:80013670      ori $a0, $zero, 1
TEXT:80013674      jal LIBAPI.ChangeClearPAD
TEXT:80013678      move $a0, $zero
TEXT:8001367C      jal LIBAPI.ExitCriticalSection
TEXT:80013680      nop 
TEXT:80013684      jal sub_8001369c
TEXT:80013688      nop 
TEXT:8001368C      lw $ra, 10($sp)
TEXT:80013690      nop 
TEXT:80013694      jr $ra
TEXT:80013698      addiu $sp, $sp, 18

Some structures from symbols not being applied

Ghidra/plugin output:

/* File: E:\DATA\MGS\MGS_REVERSING\SRC\JIMCTRL_KILL_8003853C.C */

void jimctrl_kill_8003853C(void *pJimCtrl)
{
  sub_80038004();
  dword_8009E280.m[2]._0_4_ = 0;
  sub_80024098();
  return;
}

Original code:

typedef struct
{
    int dword_8009E280;
    int dword_8009E284;
    int dword_8009E288;
    int dword_8009E28C;
} unk_8009E280;

unk_8009E280 dword_8009E280 = {0, 0, 0, 0};

void jimctrl_kill_8003853C(void *pJimCtrl)
{
    sub_80038004(pJimCtrl);
    dword_8009E280.dword_8009E28C = 0;
    sub_80024098();
}

Binary and symbol file attached for repro.

ghidra.zip

Automatic mirroring of address space

The upper 3 bits of address space indicate the virtual address segment. They all map to the same physical addresses. 0x0.. 0x8... 0xA.. all reference the same physical memory(0x00000000). 0x1F800000 ... 0x9F800000 ... 0xBF800000 all reference 0x1F800000. The only difference is how the caches are applied which don't matter for our purposes anyway. So I suggest that for all memory segments that are added, you create a physical segment that is the base representation, for example (addr & 0x1FFFFFFF). Then create byte mapped segments or whatever you wanna do to make base_addr == (base_addr | 0x80000000) == (base_addr | 0xA0000000). I don't know if ghidra needs to be informed of this in some way so that it doesn't treat them as unique memory space.

Overlay Manager Tool Missing

I built the current repository per directions, and everything seems to work except the suite of things under the Tools bar in the code browser is completely missing - of primary note, the Overlay Manager. It's definitely possible I did some step of the process wrong but any guidance/troubleshooting on this would be greatly appreciated.

Support multiple "System Configurations"

Due to the fact that there are differences between console(RAM size, BIOS, extra hardware), it would be nice if System Configurations could be defined. Basically templates that can be mixed and matched which define memory maps and the data/hw mapped to them. Support for ghidra scripting to allow for emulating hardware using read/write hooks on their memory address(es) would be fucking awesome. :)

PCSX Redux support

Is it possible in the future to implement debugger compatibility with pcsx redux gdb server, as well as fix data output in COP0, COP2Data, COPControl tabs (at the moment they are not output at all)?

Move from FunctionID feature to something else

For now FunctionID doesn't meet my requirements: xrefs, small functions (like BIOS calls - it requires modifying GHIDRA source code). So, I think it will be some custom format (similar to PAT). PAT: Yes I know, it was here already, but signs were generated by Flair utilities, and they're not full.

Detect and load PS1 BIOS ROMs

File can be identified using offsets:
0x00000000: 13 00 08 3C
0x00000108 "Sony Computer Entertainment Inc."

NOTE:Not all BIOSes are loaded to 0xBFC00000. Check offset 0x70 as a 32-bit little endian unsigned int and do load addr = ((val << 2) & 0x3FFFF000). It's almost always going to give you a result of 0x1FC00000 but 0x1FA00000 is also known(for dev hardware).

File psyq/patches.json not found error (9.2.3)

Ghidra 9.2.3 gives this error with the latest plugin:

file psyq/patches.json does not exist in module ghidra_psx_ldr
java.io.FileNotFoundException: file psyq/patches.json does not exist in module ghidra_psx_ldr
	at ghidra.framework.Application.getDataFileInModule(Application.java:361)
	at ghidra.framework.Application.getModuleDataFile(Application.java:874)
	at psx.PsxAnalyzer.applyPsyqSignaturesByVersion(PsxAnalyzer.java:108)
	at psx.PsxAnalyzer.added(PsxAnalyzer.java:89)
	at ghidra.app.plugin.core.analysis.AnalysisScheduler.runAnalyzer(AnalysisScheduler.java:186)
	at ghidra.app.plugin.core.analysis.AnalysisTask.applyTo(AnalysisTask.java:39)
	at ghidra.app.plugin.core.analysis.AutoAnalysisManager$AnalysisTaskWrapper.run(AutoAnalysisManager.java:688)
	at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:788)
	at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:667)
	at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:632)
	at ghidra.app.plugin.core.analysis.AnalysisBackgroundCommand.applyTo(AnalysisBackgroundCommand.java:58)
	at ghidra.framework.plugintool.mgr.BackgroundCommandTask.run(BackgroundCommandTask.java:102)
	at ghidra.framework.plugintool.mgr.ToolTaskManager.run(ToolTaskManager.java:315)
	at java.base/java.lang.Thread.run(Thread.java:831)

As well, the extension doesn't seem to want to stay installed.

Cannot compile

When I try to compile the loader, it says "GHIDRA_INSTALL_DIR is not defined!" despite filling it out. I'm on Windows 10.

This is my command and I'm using Powershell: cmd /C "set "GHIDRA_INSTALL_DIR=C:\Ghidra\Ghidra" && gradle buildExtension"

Build issue

I'm having trouble trying to compile on Gentoo. Using openjdk-bin-11, ghidra-9.1.2 and gradle-6.3.

$ env GHIDRA_INSTALL_DIR=/usr/share/ghidra gradle-6.3 buildExtension -g gradle-user-home

> Task :compileJava FAILED
/spare/home/lucas/ghidra_psx_ldr/src/main/java/pat/PatParser.java:12: error: cannot access DisassembleCommand
import ghidra.app.cmd.disassemble.DisassembleCommand;
                                 ^
  bad class file: /usr/share/ghidra/Ghidra/Features/Base/lib/Base.jar(ghidra/app/cmd/disassemble/DisassembleCommand.class)
    class file has wrong version 55.0, should be 52.0
    Please remove or make sure it appears in the correct subdirectory of the classpath.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler error output for details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.3/userguide/command_line_interface.html#sec:command_line_warnings

PsyQ Object Files Loader have buggy imports

Try loading GS_001.OBJ from LIBGS.LIB. Under IDA, you'll get the following:

COMM:00000040
COMM:00000040  # Segment type: Communal definitions
COMM:00000040                 .comm PSDIDX             # DATA XREF: GsInitGraph+40↓w
COMM:00000040                                          # sub_3F8+80↓w ...
COMM:00000044                 .comm GsDRAWENV:0x17     # DATA XREF: sub_274+58↓o
COMM:00000044                                          # sub_274+60↓o ...
COMM:00000048                 .comm GsDISPENV:5        # DATA XREF: sub_274+90↓o
COMM:00000048                                          # sub_274+9C↓w ...
COMM:0000004C                 .comm PSDGPU             # DATA XREF: sub_274+68↓w
COMM:0000004C                                          # sub_274+A4↓w ...
COMM:00000050                 .comm PSDBASEX:2         # DATA XREF: sub_274+78↓w
COMM:00000050                                          # sub_274+98↓o ...
COMM:00000054                 .comm PSDBASEY:2         # DATA XREF: sub_274+70↓w
COMM:00000054                                          # sub_274+B4↓w ...
COMM:00000058                 .comm POSITION:2         # DATA XREF: sub_274+7C↓w
COMM:00000058                                          # sub_274+E0↓w ...
COMM:0000005C                 .comm CLIP2:4            # DATA XREF: sub_274+8C↓w
COMM:0000005C                                          # GsInitGraph2+28↓w ...
COMM:00000060                 .comm PSDCNT:2           # DATA XREF: sub_3F8+20C↓w
COMM:00000060                                          # sub_3F8+214↓w ...
COMM:00000064                 .comm PSDOFSX:2          # DATA XREF: GsSortClear+6C↓r
COMM:00000068                 .comm PSDOFSY:2          # DATA XREF: GsSortClear+8C↓r
COMM:0000006C                 .comm GsORGOFSX:2
COMM:00000070                 .comm GsORGOFSY:2

Which are data import relocations. Even though each symbol is 4 bytes apart, their actual sizes can be much larger, like the GsDRAWENV symbol which is of type DRAWENV:

/*
 * Rectangle:
 */
typedef struct {
        short x, y;             /* offset point on VRAM */
        short w, h;             /* width and height */
} RECT;

/*
 * Environment
 */
typedef struct {
        u_long  tag;
        u_long  code[15];
} DR_ENV;                               /* Packed Drawing Environment */

typedef struct {
        RECT    clip;           /* clip area */
        short   ofs[2];         /* drawing offset */
        RECT    tw;             /* texture window */
        u_short tpage;          /* texture page */
        u_char  dtd;            /* dither flag (0:off, 1:on) */
        u_char  dfe;            /* flag to draw on display area (0:off 1:on) */
        u_char  isbg;           /* enable to auto-clear */
        u_char  r0, g0, b0;     /* initital background color */
        DR_ENV  dr_env;         /* reserved */
} DRAWENV;

But ghidra treats as if the data WAS in the relocation segment instead, which result in really wrong code:

void FUN_000001ac(undefined2 param_1,undefined2 param_2,uint param_3,byte param_4,undefined param_5)

{
  int iVar1;
  undefined4 uVar2;
  
  uVar2 = 0;
  if ((param_3 >> 4 & 3) == 3) {
    uVar2 = 3;
  }
  ResetGraph(uVar2);
  GsDRAWENV._10_2_ = 0;
  GsDRAWENV._8_2_ = 0;
  GsDRAWENV._18_2_ = 0;
  GsDRAWENV._16_2_ = 0;
  GsDRAWENV._14_2_ = 0;
  GsDRAWENV._12_2_ = 0;
  GsDRAWENV._20_2_ = 0;
  GsDRAWENV.field_0x17 = 0;
  GsDRAWENV.field_0x18 = 0;
  GsDRAWENV.field_0x16 = param_4;
  PutDrawEnv((undefined *)&GsDRAWENV);
  GsDRAWENV._0_2_ = 0;
  GsDRAWENV._2_2_ = 0;
  GsDRAWENV._8_2_ = 0;
  GsDRAWENV._10_2_ = 0;
  GsDRAWENV._12_2_ = 0;
  GsDRAWENV._14_2_ = 0;
  GsDRAWENV._4_2_ = param_1;
  GsDRAWENV._6_2_ = param_2;
  iVar1 = GetVideoMode();
  if (iVar1 == 1) {
    GsDRAWENV._10_2_ = 0x18;
    GsDRAWENV._18_2_ = GsDRAWENV._18_2_ & 0xff00 | 1;
  }
  GsDRAWENV._0_2_ = (ushort)param_3 & 4;
  GsDRAWENV._16_2_ = CONCAT11(param_5,(char)param_3) & 0xff01;
  PutDispEnv((undefined *)&GsDRAWENV);
  return;
}

In this case, the PutDrawEnv is being called on the GsDRAWENV location, but PutDispEnv is supposed to be called on the GsDISPENV location, which isn't what the import currently is doing here. It's using GsDISPENV again.

It's also visible in the disassembly window:

IDA:

.text:00000304                 la      $s0, GsDISPENV
.text:0000030C                 addiu   $v0, $s0, (PSDBASEX - 0x48)
.text:00000310                 sh      $zero, (GsDISPENV - 0x48)($s0)

ghidra:

      00000240 9c 06 10 26          addiu               s0,s0,0x69c
      00000244 08 00 02 26          addiu               v0,s0,0x8
      00000248 00 00 00 a6          sh                  zero,0x0(s0)=>GsDRAWENV                    = 

Even though the IDA output is a bit more confusing, it's properly referencing GsDISPENV instead of GsDRAWENV.

Signatures path error

Hi.

Using the last version 10.0.4 i encounter an issue when starting the analyse task.
It seems there is an issue regarding the path of the signatures

Here's the error i get:
image

I think the path needs to be updated, To see if my theory was correct i simply created a copy of psyq470.gdt and renamed it psyq47.gdt inside ghidra_10.0.4_PUBLIC_20211023_ghidra_psx_ldr.zip\ghidra_psx_ldr\data\

image
and the same for the folder 470 i renamed it 47 inside ghidra_10.0.4_PUBLIC_20211023_ghidra_psx_ldr.zip\ghidra_psx_ldr\data\psyq\

image
And indeed this fixes it (no error pop up and type recognised):
image

Hope that helps.

9.0.4 Update Doesn't Work

I tried out using the latest 9.0.4 update and Ghidra now accepts the extension and it appears properly in the extensions list. However, when I try to decompile anything it only shows the option to decompile using raw binary and not as a PSX Executable. So either I did something wrong on my end, or something needs to be updated again in the extension. But I did try reinstalling it and using a fresh 9.0.4 install but it changed nothing.

Apply EXT and STAT types

Original code:

void System_init_80015AF4(int index, int bIsDynamic, void* pMemory, unsigned int size)
{
    GV_Heap* pHeap = &gv_heaps_800AD2F0[index];
    GV_MemoryAllocation* pAllocs = &pHeap->mAllocs[0];
	unsigned char* alignedEndPtr = ((unsigned char*)pMemory) + (size & 0xfffffff0); // align
   
    pHeap->mFlags = bIsDynamic != 0;
    pHeap->mStartAddr = pMemory;
    
    pHeap->mEndAddr = alignedEndPtr;
    pHeap->mUnitsCount = 1;
	
    // First entry is free     
    pAllocs[0].mPDataStart = pMemory;
    pAllocs[0].mAllocType = GV_MemoryAllocation_States_Free_0;
 	
    // Second is used and is the entire space   
    pAllocs[1].mPDataStart = alignedEndPtr;
    pAllocs[1].mAllocType = GV_MemoryAllocation_States_Used_2;
}

Decompiled code:


/* File: E:\DATA\MGS\MGS_REVERSING\SRC\SYSTEM_INIT_80015AF4.C */

void System_init_80015AF4(int index,int bIsDynamic,void *pMemory,uint size)

{
  int iVar1;
  
  iVar1 = (int)pMemory + (size & 0xfffffff0);
  *(uint *)(&_group_gv_heaps_800AD2F0_obj + index * 0x1010) = (uint)(bIsDynamic != 0);
  *(void **)(&DAT_800ad2f4 + index * 0x404) = pMemory;
  (&DAT_800ad2f8)[index * 0x404] = iVar1;
  (&DAT_800ad2fc)[index * 0x404] = 1;
  *(void **)(&DAT_800ad300 + index * 0x404) = pMemory;
  (&DAT_800ad304)[index * 0x404] = 0;
  *(int *)(&DAT_800ad308 + index * 0x1010) = iVar1;
  (&DAT_800ad30c)[index * 0x404] = 2;
  return;
}

As you can see the type of _group_gv_heaps_800AD2F0_obj isn't correct. Likely because it was put into its own section and so some compiler added symbols also got added?

 800AD2F0  __gv_heaps_800AD2F0_obj
 800B0320  __gv_heaps_800AD2F0_objend
 800AD2F0  __gv_heaps_800AD2F0_org
 800B0320  __gv_heaps_800AD2F0_orgend
 00003030  __gv_heaps_800AD2F0_size
 800AD2F0  gv_heaps_800AD2F0

The last entry and its type is the correct one to use. _obj,_objend,_orgend and _size are generated by the tool chain.

Zip of exe + sym attached for repro:

sym.zip

Attempt to reconstruct sections

While unlike the CPE the final PSX EXE doesn't contain the section info in the header it does however have code referencing it.
If you check a binary with a linker map you can find these references. SN_ENTRY_POINT in SNMAIN.C in the PSX SDK references these section starts and ends for example.
Per the same code gp is set to .sdata section start location.

This could possibly be a accompanying java or python script with the loader as the section reference points could be different per developer.
A option to reconstruct sections from a list? should someone have the matching linker map could be useful too.

PSX Debugger doesn't work

Trying to start the PSX Debugger results in the following error:

`Cannot connect to debugger server!
java.util.concurrent.ExecutionException: java.net.ConnectException: Conexão recusada
at java.base/sun.nio.ch.PendingFuture.get(PendingFuture.java:183)
at psx.debug.DebuggerCore.(DebuggerCore.java:22)
at psx.debug.DebuggerProvider.startDebugger(DebuggerProvider.java:51)
at psx.debug.DebuggerProvider.lambda$setBtnActions$0(DebuggerProvider.java:186)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1967)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2308)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:297)
at java.desktop/java.awt.Component.processMouseEvent(Component.java:6636)
at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3342)
at java.desktop/java.awt.Component.processEvent(Component.java:6401)
at java.desktop/java.awt.Container.processEvent(Container.java:2263)
at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5012)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2321)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4844)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4919)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4548)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4489)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2307)
at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2764)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4844)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:772)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:95)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:743)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Caused by: java.net.ConnectException: Conexão recusada
at java.base/sun.nio.ch.UnixAsynchronousSocketChannelImpl.checkConnect(Native Method)
at java.base/sun.nio.ch.UnixAsynchronousSocketChannelImpl.finishConnect(UnixAsynchronousSocketChannelImpl.java:254)
at java.base/sun.nio.ch.UnixAsynchronousSocketChannelImpl.finish(UnixAsynchronousSocketChannelImpl.java:200)
at java.base/sun.nio.ch.UnixAsynchronousSocketChannelImpl.onEvent(UnixAsynchronousSocketChannelImpl.java:215)
at java.base/sun.nio.ch.EPollPort$EventHandlerTask.run(EPollPort.java:306)
at java.base/java.lang.Thread.run(Thread.java:832)


Build Date: 2020-Feb-12 1149 EST
Ghidra Version: 9.1.2
Java Home: /usr/lib/jvm/java-14-openjdk-14.0.0.36-3.rolling.fc33.x86_64
JVM Version: N/A 14
OS: Linux 5.7.0-0.rc0.git8.2.fc33.x86_64 amd64
Workstation: SolidStateSurvivor`

"Conexão recusada" means "Connection refused". Tested on latest git.

Syscalls don't have the correct signatures

I've noticed that as of the latest update ghidra_psx_ldr is identifying the syscalls, but it seems like they don't always have the correct signatures. B0:36, for example, is set to void FileClose(void), when it should be set to the Unix-style syscall int close(int fd). I've been using this document to correct syscalls signatures. Is it feasible to correct this behavior?

Thanks again for the excellent work on this extension!

java.lang.IllegalArgumentException: Split cannot be done on block start address

Attempting to load certain executables with the PS1 loader causes an IllegalArgumentException to be thrown:

Error importing file: SLUS_010.66
java.lang.IllegalArgumentException: Split cannot be done on block start address
	at ghidra.program.database.mem.MemoryMapDB.split(MemoryMapDB.java:816)
	at psx.PsxLoader.findAndAppyMain(PsxLoader.java:466)
	at psx.PsxLoader.load(PsxLoader.java:225)
	at ghidra.app.util.opinion.AbstractLibrarySupportLoader.doLoad(AbstractLibrarySupportLoader.java:346)
	at ghidra.app.util.opinion.AbstractLibrarySupportLoader.loadProgram(AbstractLibrarySupportLoader.java:83)
	at ghidra.app.util.opinion.AbstractProgramLoader.load(AbstractProgramLoader.java:112)
	at ghidra.plugin.importer.ImporterUtilities.importSingleFile(ImporterUtilities.java:401)
	at ghidra.plugin.importer.ImporterDialog.lambda$okCallback$7(ImporterDialog.java:351)
	at ghidra.util.task.TaskLauncher$1.run(TaskLauncher.java:90)
	at ghidra.util.task.Task.monitoredRun(Task.java:126)
	at ghidra.util.task.TaskRunner.lambda$startTaskThread$1(TaskRunner.java:94)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:830)

---------------------------------------------------
Build Date: 2019-Dec-18 1306 EST
Ghidra Version: 9.1.1
Java Home: C:\jdk-13.0.1
JVM Version: Oracle Corporation 13.0.1
OS: Windows 10 10.0 amd64
Workstation: SpencerComputer

This happens with Tony Hawk's Pro Skater (SLUS-00860) and Tony Hawk's Pro Skater 2 (SLUS-01066), but not the German demo version (all demo versions?) of THPS2. Both executables load fine using the raw binary loader.

Gradle Build Failure

I can't seem to build the extension. I keep getting the following error:

C:\Users\Kapsey\Documents\Disassembly\ghidra_psx_ldr-master\ghidra_psx_ldr-master>cmd /C "set "GHIDRA_INSTALL_DIR=C:\Users\Kapsey\Documents\Disassembly\ghidra_9.2.2_PUBLIC_20201229\ghidra_9.2.2_PUBLIC" && gradle buildExtension"

FAILURE: Build failed with an exception.

* Where:
Script 'C:\Users\Kapsey\Documents\Disassembly\ghidra_9.2.2_PUBLIC_20201229\ghidra_9.2.2_PUBLIC\support\buildExtension.gradle' line: 36

* What went wrong:
A problem occurred evaluating script.
> Could not find method compile() for arguments [directory 'lib'] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

It's probably an error on my end. Is there something I'm doing incorrectly?

Loader is broken after v1.2.3 release

It doesn't work on any of the psx binaries i tried that it worked on before.
v1.2.3 still works, later ones just offer Raw Binary as the loader option
Some of the bins im having the issue with(remove log, for some reason i can't upload zip :/ )
psxbins.zip.log

Error then analyze Vigilante 8

Then i try to analyz Vigilante 8(USA) got error:

Analysis Task: PSYQ Signatures - Invalid address specified for new Label symbol: Stack[-0x8]
java.lang.IllegalArgumentException: Invalid address specified for new Label symbol: Stack[-0x8]
	at ghidra.program.database.symbol.SymbolManager.checkAddressAndNameSpaceValidForSymbolType(SymbolManager.java:2585)
	at ghidra.program.database.symbol.SymbolManager.validateNamespace(SymbolManager.java:2486)
	at ghidra.program.database.symbol.SymbolManager.createCodeSymbol(SymbolManager.java:2352)
	at ghidra.program.database.symbol.SymbolManager.createLabel(SymbolManager.java:2335)
	at ghidra.program.database.symbol.SymbolManager.createLabel(SymbolManager.java:2323)
	at pat.PatParser.setInstrRefName(PatParser.java:225)
	at pat.PatParser.applySignatures(PatParser.java:105)
	at psx.PsxAnalyzer.added(PsxAnalyzer.java:85)
	at ghidra.app.plugin.core.analysis.AnalysisScheduler.runAnalyzer(AnalysisScheduler.java:185)
	at ghidra.app.plugin.core.analysis.AnalysisTask.applyTo(AnalysisTask.java:39)
	at ghidra.app.plugin.core.analysis.AutoAnalysisManager$AnalysisTaskWrapper.run(AutoAnalysisManager.java:685)
	at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:785)
	at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:664)
	at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:629)
	at ghidra.app.plugin.core.analysis.AnalysisBackgroundCommand.applyTo(AnalysisBackgroundCommand.java:62)
	at ghidra.framework.plugintool.mgr.BackgroundCommandTask.run(BackgroundCommandTask.java:101)
	at ghidra.framework.plugintool.mgr.ToolTaskManager.run(ToolTaskManager.java:315)
	at java.base/java.lang.Thread.run(Thread.java:834)

---------------------------------------------------
Build Date: 2019-Feb-28 1236 EST
Ghidra Version: 9.0
Java Home: C:\Program Files\Java\jdk-11.0.2
JVM Version: Oracle Corporation 11.0.2
OS: Windows 7 6.1 amd64
Workstation: VBKesha_Z370

SLUS_005.zip

Support "System Snapshot" file

Now, there's no file format that exists that I know of that quite describes this but emulators could definitely generate these. Basically a "System Configuration"(see other feature request) that has been made from a save state of an emulator. Basically coredump including RAM(0x0-0x001FFFFF/0x007FFFFF), ScratchPad(0x1F800000-0x3FF), BIOS(0xBFC00000-0x7FFFF(by default but can be up to 0x00400000 bytes in size), Expansion 1(0x1F000000-0x0007FFFF(by default but can be up to 0x00800000 bytes in size), Expansion 2(0x1F802000-0x7F though size may vary), Expansion 3(0x1FA00000-0x0007FFFF though ca be up to 0x00200000 bytes long). And hardware registers at 0x1F801000-1FFF.

Need 9.2.3 support.

Ghidra 9.2.3 was released lately and I need to make sure there's a compatible loader.

Exception on analysis: data/psyq/[any] does not exist in module ghidra_psx_ldr

I recently moved my project from ghidra 9.1.x to the latest version, I exported my data and re-imported it to a fresh ghidra 10.1 installation. After the installation I installed your beloved plugin downloaded from github.

I don't remember exactly my steps but Importing the old project brought the references of the old plugin, it wasn't a problem, I just removed the psyq lib from the data type manager, I saved and reopened the file.

At this step I clicked the Auto Analysis and I got this error

(These messages are also written to the application log file)

data/psyq/43 does not exist in module ghidra_psx_ldr
java.io.FileNotFoundException: data/psyq/43 does not exist in module ghidra_psx_ldr
  at ghidra.framework.Application.getDataSubDirectoryInModule(Application.java:415)
  at ghidra.framework.Application.getModuleDataSubDirectory(Application.java:854)
  at psx.PsxAnalyzer.added(PsxAnalyzer.java:86)
  at ghidra.app.plugin.core.analysis.AnalysisScheduler.runAnalyzer(AnalysisScheduler.java:186)
  at ghidra.app.plugin.core.analysis.AnalysisTask.applyTo(AnalysisTask.java:39)
  at ghidra.app.plugin.core.analysis.AutoAnalysisManager$AnalysisTaskWrapper.run(AutoAnalysisManager.java:688)
  at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:788)
  at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:667)
  at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:632)
  at ghidra.app.plugin.core.analysis.AnalysisBackgroundCommand.applyTo(AnalysisBackgroundCommand.java:58)
  at ghidra.framework.plugintool.mgr.BackgroundCommandTask.run(BackgroundCommandTask.java:102)
  at ghidra.framework.plugintool.mgr.ToolTaskManager.run(ToolTaskManager.java:319)
  at java.base/java.lang.Thread.run(Thread.java:829)

The strange thing is...the data in the plugin is there but in a different path!

The correct path is data/psyq/430 with zero! I got this error in other projects as well, seems somehow the last digit is missing, if I symlink the path 43->430 it works but is just a workaround.

I tried a couple of times to delete ghidra and start over, but still the problem is there.

I am using ghidra on fedora linux with Java 11

image

as always thank you for this amazing plugin!

Incorrect segment configuration due to dubious heap initialization

Vagrant Story passes 0x800401ac to InitHeap, but makes no use of system memory management and has its own separate heap.

Unfortunately 0x800401ac is right in the middle of the main exe, which occupies 0x80010000 - 0x80061fff, and due to the way psx_ldr sets up the segments the region from 0x800401a8 - 0x80061fff is configured as uninitialized when it actually contains code and data.

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.