Merge pull request #4338 from ArjenS-LA/fix/diagnostic-input-preservation
fix(relinker): preserve inputs when writing Windows diagnostics
This commit is contained in:
commit
57f5ec232c
|
|
@ -128,6 +128,8 @@ int Run(const int argc, char* argv[]) {
|
|||
checkOutputInputs(desktopEntry->IconPath, "Icon");
|
||||
checkOutputInputs(desktopEntry->EntryPath, "Desktop entry");
|
||||
}
|
||||
if (args.windowsDiagnostics)
|
||||
checkOutputInputs(std::filesystem::absolute("windows-diagnostics-imports.txt"), "Windows import diagnostics");
|
||||
|
||||
if (args.writeRegistry) {
|
||||
const std::filesystem::path outFsPath = Io::NativePath(absPath);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,72 @@ from test_guest_intel_trampolines import PLAIN_SITE, guest_fixture, main_fixture
|
|||
from test_linux_desktop_entry_output import png
|
||||
|
||||
|
||||
def check_diagnostic_inputs(relinker, work):
|
||||
filename = "windows-diagnostics-imports.txt"
|
||||
for bundled in (False, True):
|
||||
for alias in ("direct", "hardlink", "symlink"):
|
||||
for registry in (False, True):
|
||||
case = work / f"diagnostics-{bundled}-{alias}-{registry}"
|
||||
modules = case / "sce_module"
|
||||
modules.mkdir(parents=True)
|
||||
diagnostics = (modules if bundled and alias == "direct" else case) / filename
|
||||
source = diagnostics if not bundled and alias == "direct" else case / "input.elf"
|
||||
original = bytes(main_fixture())
|
||||
source.write_bytes(original)
|
||||
module = diagnostics if bundled and alias == "direct" else modules / "sample.prx"
|
||||
module_original = bytes(guest_fixture(PLAIN_SITE))
|
||||
module.write_bytes(module_original)
|
||||
protected = module if bundled else source
|
||||
if alias == "hardlink":
|
||||
os.link(protected, diagnostics)
|
||||
elif alias == "symlink":
|
||||
try:
|
||||
diagnostics.symlink_to(protected)
|
||||
except OSError as error:
|
||||
if os.name != "nt" or error.winerror != 1314:
|
||||
raise
|
||||
print("Diagnostic symbolic-link case skipped: Windows symlink privilege unavailable")
|
||||
continue
|
||||
output = case / "output.exe"
|
||||
previous_output = b"previous executable"
|
||||
output.write_bytes(previous_output)
|
||||
registry_path = case / "output.registry.json"
|
||||
previous_registry = b"previous registry"
|
||||
registry_path.write_bytes(previous_registry)
|
||||
options = [] if bundled else ["--skip-sce-module"]
|
||||
if registry:
|
||||
options.append("--registry")
|
||||
result = subprocess.run([str(relinker), "--windows", "--windows-diagnostics", *options,
|
||||
str(source), str(output)], cwd=diagnostics.parent,
|
||||
capture_output=True, text=True, timeout=20)
|
||||
owner = "an input module" if bundled else "the input executable"
|
||||
assert result.returncode == 2 and f"Windows import diagnostics output would overwrite {owner}" in result.stderr, (result.stdout, result.stderr)
|
||||
assert str(diagnostics) in result.stderr, result.stderr
|
||||
assert source.read_bytes() == original and module.read_bytes() == module_original
|
||||
assert diagnostics.read_bytes() == (module_original if bundled else original)
|
||||
assert output.read_bytes() == previous_output and registry_path.read_bytes() == previous_registry
|
||||
assert not (case / "app0").exists()
|
||||
|
||||
for enabled in (False, True):
|
||||
for existing in (False, True):
|
||||
case = work / f"diagnostics-valid-{enabled}-{existing}"
|
||||
case.mkdir()
|
||||
diagnostics = case / filename
|
||||
source = case / "input.elf" if enabled else diagnostics
|
||||
original = bytes(main_fixture())
|
||||
source.write_bytes(original)
|
||||
if enabled and existing:
|
||||
diagnostics.write_bytes(b"previous diagnostics")
|
||||
output = case / "output.exe"
|
||||
options = ["--windows-diagnostics"] if enabled else []
|
||||
result = subprocess.run([str(relinker), "--windows", "--skip-sce-module", *options,
|
||||
str(source), str(output)], cwd=case,
|
||||
capture_output=True, text=True, timeout=20)
|
||||
assert result.returncode == 0 and output.read_bytes().startswith(b"MZ"), (result.stdout, result.stderr)
|
||||
assert source.read_bytes() == original
|
||||
assert diagnostics.read_bytes() == (b"" if enabled else original)
|
||||
|
||||
|
||||
def check_registry_inputs(relinker, work, windows):
|
||||
options = ["--windows"] if windows else []
|
||||
for module_registry in (False, True):
|
||||
|
|
@ -112,6 +178,7 @@ def main():
|
|||
relinker = Path(sys.argv[1]).resolve()
|
||||
with tempfile.TemporaryDirectory(prefix="anyps5-input-preservation-") as directory:
|
||||
work = Path(directory)
|
||||
check_diagnostic_inputs(relinker, work)
|
||||
check_desktop_inputs(relinker, work)
|
||||
for windows in (False, True):
|
||||
options = ["--windows"] if windows else []
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ relinker --macos source/input.elf eboot
|
|||
|
||||
Add `--to-intel` for Intel hosts, or `--to-rosetta` for Rosetta; a title that runs under Rosetta on Apple silicon is relinked with `--macos --to-rosetta`. `--to-intel` rewrites AMD-specific instructions found in the executable and bundled modules; it cannot translate AMD-specific instructions generated by a title at runtime, so such titles require an AMD host. The output format defaults to Linux ELF regardless of the filename; `.exe` alone does not select Windows.
|
||||
|
||||
The executable, registry, icon and desktop entry output files must not refer to the input executable or a bundled module being converted, including through a hard link or symbolic link. These collisions fail before any output is written. An existing output file can be replaced if it is separate from those inputs.
|
||||
The executable, registry, Windows import diagnostics, icon and desktop entry output files must not refer to the input executable or a bundled module being converted, including through a hard link or symbolic link. These collisions fail before any output is written. An existing output file can be replaced if it is separate from those inputs.
|
||||
|
||||
## Options
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue