mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-18 23:07:07 -05:00
Merge pull request #6357 from MarcZX10/codex/relinker-relative-defined-symbol-3093
fix(relinker): accept matching defined relative symbols
This commit is contained in:
3 files changed
+30
-8
No files matched your search
@@ -208,8 +208,13 @@ std::set<Domain::VirtualAddress> CodeInstructionCollector::Collect(const std::ve
|
||||
const auto index = info >> 32;
|
||||
const auto addend = Io::ReadU64(bytes, offset + 16);
|
||||
if (type == 8) {
|
||||
const auto zeroSectionSymbol = index != 0 && index < symbolCount && (bytes[symbols + index * 24 + 4] & 15) == 3 && Io::ReadU64(bytes, symbols + index * 24 + 8) == 0;
|
||||
if ((index != 0 && !zeroSectionSymbol) || !pointers.Values.emplace(slot, addend).second) throw Domain::RelinkerException("Code analysis: invalid relative relocation", slot);
|
||||
const auto hasSymbol = index != 0 && index < symbolCount;
|
||||
const auto symbol = hasSymbol ? symbols + index * 24 : 0;
|
||||
const auto zeroSectionSymbol = hasSymbol && (bytes[symbol + 4] & 15) == 3 && Io::ReadU64(bytes, symbol + 8) == 0;
|
||||
const auto matchingDefinedSymbol = hasSymbol && Io::ReadU16(bytes, symbol + 6) != 0
|
||||
&& addend <= static_cast<std::uint64_t>(std::numeric_limits<std::int64_t>::max())
|
||||
&& Io::ReadU64(bytes, symbol + 8) == addend;
|
||||
if ((index != 0 && !zeroSectionSymbol && !matchingDefinedSymbol) || !pointers.Values.emplace(slot, addend).second) throw Domain::RelinkerException("Code analysis: invalid relative relocation", slot);
|
||||
addRoot(addend);
|
||||
} else if (type == 1 || type == 6 || type == 7) {
|
||||
if (index == 0 || index >= symbolCount) throw Domain::RelinkerException("Code analysis: invalid relocation symbol", slot);
|
||||
|
||||
@@ -233,7 +233,16 @@ GuestImage GuestImageReader::Read(const std::filesystem::path& path, std::vector
|
||||
if ((next != relocationTargets.end() && next->first < target + 8) || (next != relocationTargets.begin() && std::prev(next)->second > target)) fail("Overlapping guest relocations");
|
||||
relocationTargets.emplace(target, target + 8);
|
||||
if (relocation == 8) {
|
||||
if ((info >> 32) != 0) fail("RELATIVE relocation has a symbol");
|
||||
if ((info >> 32) != 0) {
|
||||
const auto& symbol = image.Symbols[info >> 32];
|
||||
if (symbol.Section == 0 || addend > static_cast<std::uint64_t>(std::numeric_limits<std::int64_t>::max()) || symbol.Value != addend)
|
||||
fail("RELATIVE relocation has a symbol");
|
||||
mapped(addend, 0, 0);
|
||||
Io::AppendU64(output, target);
|
||||
Io::AppendU64(output, relocation);
|
||||
Io::AppendU64(output, addend);
|
||||
continue;
|
||||
}
|
||||
mapped(addend, 0, 0);
|
||||
} else if (relocation == 1 || relocation == 6 || relocation == 7) {
|
||||
const auto& symbol = image.Symbols[info >> 32];
|
||||
|
||||
@@ -18,11 +18,13 @@ NOOP = (0, 0, 0)
|
||||
IGNORED = (0xffffffffffffffff, 0xffffffff00000000, -1)
|
||||
OVERLAP = (TARGET + 1, 0xffffffff00000000, -1)
|
||||
RELATIVE = (TARGET, 8, FUNCTION)
|
||||
RELATIVE_DEFINED = (TARGET, (1 << 32) | 8, FUNCTION)
|
||||
JUMP_SLOT = (TARGET, (1 << 32) | 7, 0)
|
||||
|
||||
|
||||
def module(rela=(), plt=(), sce=False, lifecycle=False, initial=UNCHANGED):
|
||||
image = module_with_symbol(True)
|
||||
def module(rela=(), plt=(), sce=False, lifecycle=False, initial=UNCHANGED, exported=True, symbol_info=0x12):
|
||||
image = module_with_symbol(exported)
|
||||
image[0x89c] = symbol_info
|
||||
image.extend(bytes(0xE00 - len(image)))
|
||||
struct.pack_into("<QQ", image, 120 + 32, 0x800, 0x800)
|
||||
image[0x400:0x406] = bytes.fromhex("b82a000000c3")
|
||||
@@ -75,7 +77,9 @@ def change_tag(image, tag, value=None, replacement=None):
|
||||
|
||||
|
||||
def check_output(data, system, rela, plt, initial):
|
||||
expected_rela = [entry for entry in rela if entry[1] & 0xffffffff]
|
||||
expected_rela = [(entry[0], entry[1] & 0xffffffff, entry[2])
|
||||
if (entry[1] & 0xffffffff) == 8 and entry[1] >> 32 else entry
|
||||
for entry in rela if entry[1] & 0xffffffff]
|
||||
expected_plt = [entry for entry in plt if entry[1] & 0xffffffff]
|
||||
relocated = bool(expected_rela or expected_plt)
|
||||
if system == "linux":
|
||||
@@ -108,7 +112,8 @@ def check_output(data, system, rela, plt, initial):
|
||||
|
||||
|
||||
def invalid_cases(sce):
|
||||
yield "relative-symbol", module([NOOP, (TARGET, (1 << 32) | 8, FUNCTION)], sce=sce), "RELATIVE relocation has a symbol"
|
||||
yield "relative-symbol-mismatched-value", module([(TARGET, (1 << 32) | 8, FUNCTION + 8)], sce=sce), "RELATIVE relocation has a symbol"
|
||||
yield "relative-symbol-undefined", module([(TARGET, (1 << 32) | 8, 0)], sce=sce, exported=False), "RELATIVE relocation has a symbol"
|
||||
yield "invalid-symbol", module([NOOP, (TARGET, (99 << 32) | 6, 0)], sce=sce), "Unsupported relocation or symbol index"
|
||||
yield "invalid-target", module([NOOP, (0xffffffffffffffff, 8, FUNCTION)], sce=sce), "Unmapped or inaccessible guest address"
|
||||
yield "overlapping-real", module([NOOP, RELATIVE, RELATIVE], sce=sce), "Overlapping guest relocations"
|
||||
@@ -142,6 +147,8 @@ def main():
|
||||
return
|
||||
relinker = Path(sys.argv[1]).resolve()
|
||||
cases = (("baseline", [RELATIVE], [], False, UNCHANGED),
|
||||
("relative-defined-symbol", [RELATIVE_DEFINED], [], False, UNCHANGED),
|
||||
("relative-defined-object", [RELATIVE_DEFINED], [], False, UNCHANGED),
|
||||
("mixed", [NOOP, OVERLAP, RELATIVE, IGNORED, (TARGET, 0, -1)], [], False, UNCHANGED),
|
||||
("only-none", [NOOP, IGNORED, OVERLAP], [], False, UNCHANGED),
|
||||
("plt-mixed", [], [NOOP, OVERLAP, JUMP_SLOT, IGNORED], False, UNCHANGED),
|
||||
@@ -168,7 +175,8 @@ def main():
|
||||
|
||||
for sce in (False, True):
|
||||
for name, rela, plt, lifecycle, initial in cases:
|
||||
image = module(rela, plt, sce, lifecycle, initial)
|
||||
symbol_info = 0x11 if name == "relative-defined-object" else 0x12
|
||||
image = module(rela, plt, sce, lifecycle, initial, symbol_info=symbol_info)
|
||||
for system in ("linux", "windows", "macos"):
|
||||
result, artifact, output = convert(f"{sce}-{name}", system, image)
|
||||
assert result.returncode == 0, (sce, name, system, result.stdout, result.stderr)
|
||||
|
||||
Reference in new issue
Block a user