mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-18 23:07:07 -05:00
fix(relinker): keep the Windows TLS rewrite from moving truncated branches
A short TLS access followed by a near branch with an operand-size prefix decided the branch was relative from its flow kind and opcode alone, then re-encoded it to the fall-through address or wrote its rel32 over the prefix and opcode. Such a branch now counts as one that cannot move. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016TFMtUC4L4wMS4eeEqaNSR
This commit is contained in:
1 parent
206aaa56cb
commit
aed1ffbae8
2 files changed
+6
-2
No files matched your search
@@ -158,8 +158,8 @@ PeDirectory WindowsTlsBuilder::Build(const std::vector<std::uint8_t>& source, co
|
||||
throw Domain::RelinkerException("Short guest TLS instruction ends its segment", header.Offset + offset);
|
||||
const auto next = decoder.DecodeInstruction(bytes + length, header.FileSize - offset - length);
|
||||
const bool relativeBranch =
|
||||
(next.FlowKind == Codegen::ControlFlowKind::ConditionalBranch && (next.IsTwoByteOpcode ? next.Opcode >= 0x80 && next.Opcode <= 0x8f : next.Opcode >= 0x70 && next.Opcode <= 0x7f)) ||
|
||||
(next.FlowKind == Codegen::ControlFlowKind::UnconditionalJump && !next.HasRipRelativeDisp && !next.IsTwoByteOpcode && (next.Opcode == 0xe9 || next.Opcode == 0xeb));
|
||||
(next.FlowKind == Codegen::ControlFlowKind::ConditionalBranch && !next.TruncatesBranchTarget && (next.IsTwoByteOpcode ? next.Opcode >= 0x80 && next.Opcode <= 0x8f : next.Opcode >= 0x70 && next.Opcode <= 0x7f)) ||
|
||||
(next.FlowKind == Codegen::ControlFlowKind::UnconditionalJump && !next.TruncatesBranchTarget && !next.HasRipRelativeDisp && !next.IsTwoByteOpcode && (next.Opcode == 0xe9 || next.Opcode == 0xeb));
|
||||
if (!relativeBranch && (next.FlowKind != Codegen::ControlFlowKind::Sequential || next.HasBranchTarget || next.SegmentPrefix != 0))
|
||||
throw Domain::RelinkerException("Short guest TLS instruction is followed by an instruction that cannot move", header.Offset + offset + length);
|
||||
std::vector<std::uint8_t> movedBytes(bytes + length, bytes + length + next.Length);
|
||||
|
||||
@@ -747,6 +747,10 @@ def main():
|
||||
"short-before-tls": bytes.fromhex("64 48 8b 03 64 48 8b 03 c3"),
|
||||
"short-alu-before-return": bytes.fromhex("64 48 33 03 c3"),
|
||||
"short-before-loop": bytes.fromhex("64 48 33 03 e2 00"),
|
||||
"short-before-word-jcc8": bytes.fromhex("64 48 33 03 66 75 00 c3"),
|
||||
"short-before-word-jmp8": bytes.fromhex("64 48 33 03 66 eb 00 c3"),
|
||||
"short-before-word-jmp16": bytes.fromhex("64 48 33 03 66 e9 00 00 c3"),
|
||||
"short-before-word-jcc16": bytes.fromhex("64 48 33 03 66 0f 85 00 00 c3"),
|
||||
}.items():
|
||||
convert(name, make_image("register", "unwind", body=instruction),
|
||||
"Short guest TLS instruction is followed by an instruction that cannot move", error_offset=0x1244)
|
||||
|
||||
Reference in new issue
Block a user