Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reimplement/fix PRX patches #9746

Merged
merged 2 commits into from Feb 12, 2021
Merged

Reimplement/fix PRX patches #9746

merged 2 commits into from Feb 12, 2021

Conversation

elad335
Copy link
Contributor

@elad335 elad335 commented Feb 8, 2021

What is a PRX file? PRX stands for "PPU Relocatable Executable". What "relocatable" means in this context you ask? it means that the data/code segments of the PRX file can be mapped at any given address as long as the address is free from another memory mapping. Because every single PS3 application has different memory layout (it can even change within different boots of the same application!) we need PRX patches to be able to exist at any address based on relative offsets from segments instead of hardcoded addresses. This is fixed by this pull request.

Enhancements

  • Make PRX patches relocatable as they should.
  • Due to the changed control for PRX patches depending of knowing the segments addresses, I made them display in kernel explorer.
  • Added patch validation checks for PRX segments bounds. (TODO: do it for PPU/OVL patches as well)

Bugfixes

  • Fix LE32, LE64 and BE64 patches on PPU LLVM.

What this allows?
This allows to patch SPRX files as for firmware's.

I ported rujkosto's Metal Gear Solid 4's hack build in cellSpurs to a patch file of the firmware instead.
Here is the entry (need to be manually added until pushed to main patches)

PRX-rbYkgZMgx8Prd7WUAA39oYAdWcNo-0:
  "cellSpurs urgent commands hack - Metal Gear Solid 4":
    Games:
      All:
        All: [ All ]
    Author: elad335
    Notes: [ "Workaround for freezes in Metal Gear Solid 4.\nThis patch applies to a firmware file for all games!\nUsage outside of Metal Gear Solid 4 is for debug purposes only.\nYou must have firmware version of exactly 4.87 in order to use it.\n\nKnown to affect:\nMetal Gear Solid 4" ]
    Patch Version: 1.0
    Patch:
      - [ be32, 0x182B8, 0x38000002 ]

@elad335
Copy link
Contributor Author

elad335 commented Feb 8, 2021

Just a note: the MGS4 patch only applies for firmware version 4.87 and may need to be updated with newer firmware versions.

hash[4 + i * 2] = pal[prx->sha1[i] >> 4];
hash[5 + i * 2] = pal[prx->sha1[i] & 15];
}
const std::string hash = fmt::format("PRX-%s", fmt::base57(prx->sha1));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Killing two birds in one stone: old PRX patches are invalidated, and the hashes naming system is updated to use the newer LLVM's base 57 format as opposed to the old base 16.

@elad335 elad335 changed the title Reimplement/fix PRX patches [WIP] Reimplement/fix PRX patches Feb 8, 2021
@elad335 elad335 changed the title [WIP] Reimplement/fix PRX patches Reimplement/fix PRX patches Feb 8, 2021
@MSuih
Copy link
Member

MSuih commented Feb 9, 2021

I don't really like the idea of having a patch that you need to toggle off and on on game-by-game basis, to me it seems like something that'd cause a lot of confusion for end users and equal amounts of annoyance to those who try to help them. We should find a way to limit this to only apply to MGS4 by default, maybe in another PR if it's out of scope for this one.

@elad335
Copy link
Contributor Author

elad335 commented Feb 9, 2021

Where do you see the patch in pr.. lmao.

@MSuih
Copy link
Member

MSuih commented Feb 9, 2021

The patch itself isn't part of this pr, but since we're introducing patching system that allows firmware modifications we should consider the possible problems in such system and ways to avoid them. The very first implementation to this system already seems like a support nightmare, and I suspect that we'll see more patches like this in future.

This all is just my own opinion though, I'm just raising my concerns and not demanding changes. That's up to the people who have merge rights.

@elad335
Copy link
Contributor Author

elad335 commented Feb 9, 2021

It supports gameids.. I don't understand your concern.

@MSuih
Copy link
Member

MSuih commented Feb 9, 2021

Oh right, you can have the patches in patch_<gameid>.yml files. I guess that counts as a good enough of a solution if we get people to download it as such file.

@elad335
Copy link
Contributor Author

elad335 commented Feb 9, 2021

No, not right, patches support gameids even with main online patches database. I don't understand why we need specific files for each gameid.

@elad335
Copy link
Contributor Author

elad335 commented Feb 9, 2021

I'm sorry if I talked agressively but you seemed to not understand how patches work at all.

@MSuih
Copy link
Member

MSuih commented Feb 9, 2021

Seems like I've misunderstood how patches are applied then. Sorry for the confusion, and feel free to ignore my comments.

@elad335 elad335 marked this pull request as draft February 9, 2021 08:23
@elad335
Copy link
Contributor Author

elad335 commented Feb 9, 2021

There's a problem in theory with squeezing allocation: there is more chance for OOM because the memory layout may not allow it as it requires one bigger memory "hole" as opposed a few smaller holes which are easier to find. So this should be a function from patches side to handle PRX specially. I will work on it when I have time.

@Nekotekina
Copy link
Member

Nekotekina commented Feb 9, 2021

I doubt minimal patch support needs anything more than one segment base.
Possible recommendations:

  1. Extend exec allocation range to 0x10000 as well in ppu_register_range, it's currently inconsistent.
  2. Have multiple PRX hashes for each segment separately, add segment index to the end, since you are changing naming anyways.

@elad335 elad335 marked this pull request as ready for review February 12, 2021 05:38
@elad335
Copy link
Contributor Author

elad335 commented Feb 12, 2021

  • Added patch validation checks for PRX segments bounds. (TODO: do it for PPU/OVL patches as well)
    Bugfixes
  • Fix non-BE32 patches on PPU LLVM.

@elad335
Copy link
Contributor Author

elad335 commented Feb 12, 2021

I improved further this, this is the format of PRX patches:
PRX-(hash)-(segment)

@elad335 elad335 force-pushed the patches branch 2 times, most recently from ffaaad6 to 2544487 Compare February 12, 2021 05:49
@elad335
Copy link
Contributor Author

elad335 commented Feb 12, 2021

Clear firmware PPU cache before testing the patch itself with pr.

@elad335
Copy link
Contributor Author

elad335 commented Feb 12, 2021

I updated the patch entry in pr description so update it if you wanna test.

break;
}
}

applied.push_back(resval);
// Possibly an executable instruction
applied.push_back(offset & -4);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only be32 is practically used to signify executable instruction. Okay, also be64 can contain two. But other types are more likely to add garbage to the analyser rather than improve it. Especially floats.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, other types push 0 to applied on purpose

Copy link
Contributor Author

@elad335 elad335 Feb 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Who said BE32 must not be garbage as well? Analyser should deal with anything you throw at it basically including garbage.

Copy link
Contributor Author

@elad335 elad335 Feb 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, I consider changing the patch to be16 as it only meant to change op.uimm16 of ORI instruction.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't invert question like this. Basically if it works, don't break it.
If it's be16 it already contains some valid instruction, there is no need to inform analyser.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FTR I don't agree but there's no point in addressing in this pr.

@elad335 elad335 force-pushed the patches branch 2 times, most recently from e7a7989 to ddc9c75 Compare February 12, 2021 08:37
@@ -607,14 +596,14 @@ static std::basic_string<u32> apply_modification(const patch_engine::patch_info&
}
}

// Possibly an executable instruction
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of aligning them down, seems better to not add unaligned patches to resval at all.

@@ -559,6 +546,7 @@ static std::basic_string<u32> apply_modification(const patch_engine::patch_info&
case patch_type::le32:
{
*reinterpret_cast<le_t<u32, 1>*>(ptr) = static_cast<u32>(p.value.long_value);
resval = offset;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Who uses le32 for instructions? It seems very inconvenient.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not about conveniency, it's about not introducing bugs which can be discovered by the user with some effort.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed anyways.

@Nekotekina Nekotekina merged commit 5401cb7 into RPCS3:master Feb 12, 2021
@elad335
Copy link
Contributor Author

elad335 commented Feb 12, 2021

Fixed typo in patch hash.

@Nekotekina
Copy link
Member

Where? It's merged

@elad335
Copy link
Contributor Author

elad335 commented Feb 12, 2021

Just edited pr description.

@elad335 elad335 deleted the patches branch March 16, 2021 14:50
@Megamouse Megamouse added the Patches Patches and Mods label Nov 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Patches Patches and Mods
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants