Commit ecbf2c4b by Jim Stichnoth

Subzero: Fix x86-64 memory sandboxing.

Commit 2e4b960b (https://codereview.chromium.org/2084793002), which made address mode inference more aggressive, exposed a long-standing bug in memory sandboxing, which now manifests in 164.gzip. The problem is in sandboxed code like this: movl %eax, %eax movb 64(%rsp,%rax), %cl If %eax starts out -1, the mov address is something close to %rsp+4GB, instead of %rsp+63. To fix this, we need to use an lea instruction in more cases - specifically when the sandboxed address has an index register and the non-symbolic portion of the offset is nonzero. BUG= none R=jpp@chromium.org Review URL: https://codereview.chromium.org/2097193003 .
parent 633394ce
...@@ -408,18 +408,28 @@ Traits::X86OperandMem *TargetX8664::_sandbox_mem_reference(X86OperandMem *Mem) { ...@@ -408,18 +408,28 @@ Traits::X86OperandMem *TargetX8664::_sandbox_mem_reference(X86OperandMem *Mem) {
// NeedsLea is a flag indicating whether Mem needs to be materialized to a GPR // NeedsLea is a flag indicating whether Mem needs to be materialized to a GPR
// prior to being used. A LEA is needed if Mem.Offset is a constant // prior to being used. A LEA is needed if Mem.Offset is a constant
// relocatable, or if Mem.Offset is negative. In both these cases, the LEA is // relocatable with a nonzero offset, or if Mem.Offset is a nonzero immediate;
// needed to ensure the sandboxed memory operand will only use the lower // but only when the address mode contains a "user" register other than the
// 32-bits of T+Offset. // rsp/rbp/r15 base. In both these cases, the LEA is needed to ensure the
// sandboxed memory operand will only use the lower 32-bits of T+Offset.
bool NeedsLea = false; bool NeedsLea = false;
if (Offset != nullptr) { if (!Mem->getIsRebased()) {
if (llvm::isa<ConstantRelocatable>(Offset)) { bool IsOffsetZero = false;
NeedsLea = true; if (Offset == nullptr) {
IsOffsetZero = true;
} else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
IsOffsetZero = (CR->getOffset() == 0);
} else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Offset)) { } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Offset)) {
NeedsLea = Imm->getValue() < 0; IsOffsetZero = (Imm->getValue() == 0);
} else { } else {
llvm::report_fatal_error("Unexpected Offset type."); llvm::report_fatal_error("Unexpected Offset type.");
} }
if (!IsOffsetZero) {
if (Base != nullptr && Base != ZeroReg)
NeedsLea = true;
if (Index != nullptr && Index != ZeroReg)
NeedsLea = true;
}
} }
RegNumT RegNum, RegNum32; RegNumT RegNum, RegNum32;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment