Commit 3e324002 by Jim Stichnoth

Subzero: Control memory growth from local label fixups.

The ConstantRelocatable objects for pushing local labels are allocated from the Assembler arena, and are no longer pooled, which restricts the memory growth from sandboxing x86-64 calls. Because the Assembler arena is destroyed while the fixups are still active, these fixups have to be fixed up by holding a pointer to the symbol rather than the constant. On the 10MB test pexe, the overall growth by the end is ~20MB, instead of ~130MB as before. This also partially fixes an existing bug with arm32/nonsfi/iasm, exposed by running cross tests and forcing iasm output. BUG= none R=jpp@chromium.org Review URL: https://codereview.chromium.org/1773503003 .
parent b6e9b897
......@@ -205,6 +205,8 @@ def main():
f.write(run_cmd + '\n')
f.write('echo Recreate a failure using ' + __file__ +
' --toolchain-root=' + args.toolchain_root +
(' --filetype=' + args.filetype
if args.filetype else '') +
' --include=' + ','.join(desc) + '\n')
f.write('# CHECK: Failures=0\n')
else:
......
......@@ -593,11 +593,16 @@ size_t MoveRelocatableFixup::emit(GlobalContext *Ctx,
IValueT Inst = Asm.load<IValueT>(position());
const bool IsMovw = kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ||
kind() == llvm::ELF::R_ARM_MOVW_PREL_NC;
const IceString Symbol = symbol();
const bool NeedsPCRelSuffix =
(Asm.fixupIsPCRel(kind()) || Symbol == GlobalOffsetTable);
Str << "\t"
"mov" << (IsMovw ? "w" : "t") << "\t"
<< RegARM32::getRegName(RegNumT::fixme((Inst >> kRdShift) & 0xF))
<< ", #:" << (IsMovw ? "lower" : "upper") << "16:" << symbol(&Asm)
<< "\t@ .word " << llvm::format_hex_no_prefix(Inst, 8) << "\n";
<< ", #:" << (IsMovw ? "lower" : "upper") << "16:" << Symbol
<< (NeedsPCRelSuffix ? " - ." : "") << "\t@ .word "
// TODO(jpp): This is broken, it also needs to add a magic constant.
<< llvm::format_hex_no_prefix(Inst, 8) << "\n";
return InstARM32::InstSize;
}
......@@ -650,7 +655,7 @@ size_t BlRelocatableFixup::emit(GlobalContext *Ctx,
Ostream &Str = Ctx->getStrEmit();
IValueT Inst = Asm.load<IValueT>(position());
Str << "\t"
"bl\t" << symbol(&Asm) << "\t@ .word "
"bl\t" << symbol() << "\t@ .word "
<< llvm::format_hex_no_prefix(Inst, 8) << "\n";
return InstARM32::InstSize;
}
......
......@@ -160,8 +160,10 @@ public:
}
bool fixupIsPCRel(FixupKind Kind) const override {
(void)Kind;
// TODO(kschimpf) Decide if we need this.
if (Kind == llvm::ELF::R_ARM_MOVW_PREL_NC)
return true;
if (Kind == llvm::ELF::R_ARM_MOVT_PREL)
return true;
return false;
}
......
......@@ -275,7 +275,7 @@ void ELFObjectWriter::writeFunctionCode(const IceString &FuncName,
Fixup->emitOffset(Asm);
}
}
RelSection->addRelocations(OffsetInSection, Asm->fixups());
RelSection->addRelocations(OffsetInSection, Asm->fixups(), SymTab);
}
Section->appendData(Str, Asm->getBufferView());
if (TimeThisFunction)
......
......@@ -67,11 +67,24 @@ void ELFDataSection::padToAlignment(ELFStreamer &Str, Elf64_Xword Align) {
// Relocation sections.
void ELFRelocationSection::addRelocations(RelocOffsetT BaseOff,
const FixupRefList &FixupRefs) {
const FixupRefList &FixupRefs,
ELFSymbolTableSection *SymTab) {
for (const AssemblerFixup *FR : FixupRefs) {
Fixups.push_back(*FR);
AssemblerFixup &F = Fixups.back();
F.set_position(BaseOff + F.position());
assert(!F.valueIsSymbol());
if (!F.isNullSymbol()) {
// Do an early lookup in the symbol table. If the symbol is found,
// replace the Constant in the symbol with the ELFSym, and calculate the
// final value of the addend. As such, a local label allocated from the
// Assembler arena will be converted to a symbol before the Assembler
// arena goes away.
if (const ELFSym *Sym = SymTab->findSymbol(F.symbol())) {
F.set_addend(F.offset());
F.set_value(Sym);
}
}
}
}
......
......@@ -232,7 +232,8 @@ public:
/// Track additional relocations which start out relative to offset 0, but
/// should be adjusted to be relative to BaseOff.
void addRelocations(RelocOffsetT BaseOff, const FixupRefList &FixupRefs);
void addRelocations(RelocOffsetT BaseOff, const FixupRefList &FixupRefs,
ELFSymbolTableSection *SymTab);
/// Track a single additional relocation.
void addRelocation(const AssemblerFixup &Fixup) { Fixups.push_back(Fixup); }
......@@ -353,9 +354,10 @@ void ELFRelocationSection::writeData(ELFStreamer &Str,
const ELFSym *Symbol;
if (Fixup.isNullSymbol()) {
Symbol = SymTab->getNullSymbol();
} else if (Fixup.valueIsSymbol()) {
Symbol = Fixup.getSymbolValue();
} else {
constexpr Assembler *Asm = nullptr;
const IceString Name = Fixup.symbol(Asm);
const IceString Name = Fixup.symbol();
Symbol = SymTab->findSymbol(Name);
if (!Symbol)
llvm::report_fatal_error(Name + ": Missing symbol mentioned in reloc");
......
......@@ -24,30 +24,26 @@ const Constant *AssemblerFixup::NullSymbol = nullptr;
RelocOffsetT AssemblerFixup::offset() const {
if (isNullSymbol())
return addend_;
if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(value_))
return CR->getOffset() + addend_;
if (!ValueIsSymbol) {
if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(ConstValue))
return CR->getOffset() + addend_;
}
return addend_;
}
IceString AssemblerFixup::symbol(const Assembler *Asm) const {
std::string Buffer;
llvm::raw_string_ostream Str(Buffer);
const Constant *C = value_;
IceString AssemblerFixup::symbol() const {
assert(!isNullSymbol());
assert(!ValueIsSymbol);
const Constant *C = ConstValue;
if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(C)) {
Str << CR->getName();
if (Asm && !Asm->fixupIsPCRel(kind()) &&
GlobalContext::getFlags().getUseNonsfi() &&
CR->getName() != GlobalOffsetTable) {
// TODO(jpp): remove the special GOT test.
Str << "@GOTOFF";
}
} else {
// NOTE: currently only float/doubles are put into constant pools. In the
// future we may put integers as well.
assert(llvm::isa<ConstantFloat>(C) || llvm::isa<ConstantDouble>(C));
C->emitPoolLabel(Str);
return CR->getName();
}
// NOTE: currently only float/doubles are put into constant pools. In the
// future we may put integers as well.
assert(llvm::isa<ConstantFloat>(C) || llvm::isa<ConstantDouble>(C));
std::string Buffer;
llvm::raw_string_ostream Str(Buffer);
C->emitPoolLabel(Str);
return Str.str();
}
......@@ -61,8 +57,16 @@ size_t AssemblerFixup::emit(GlobalContext *Ctx, const Assembler &Asm) const {
if (isNullSymbol()) {
Str << "__Sz_AbsoluteZero";
} else {
Symbol = symbol(&Asm);
Symbol = symbol();
Str << Symbol;
assert(!ValueIsSymbol);
if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(ConstValue)) {
if (!Asm.fixupIsPCRel(kind()) &&
GlobalContext::getFlags().getUseNonsfi() &&
CR->getName() != GlobalOffsetTable) {
Str << "@GOTOFF";
}
}
}
assert(Asm.load<RelocOffsetT>(position()) == 0);
......
......@@ -23,6 +23,8 @@ namespace Ice {
/// This holds the specific target+container format's relocation number.
using FixupKind = uint32_t;
struct ELFSym;
/// Assembler fixups are positions in generated code/data that hold relocation
/// information that needs to be processed before finalizing the code/data.
class AssemblerFixup {
......@@ -32,27 +34,33 @@ public:
AssemblerFixup() = default;
AssemblerFixup(const AssemblerFixup &) = default;
virtual ~AssemblerFixup() = default;
intptr_t position() const {
assert(position_was_set_);
return position_;
}
void set_position(intptr_t Position) {
position_ = Position;
position_was_set_ = true;
}
intptr_t position() const { return position_; }
void set_position(intptr_t Position) { position_ = Position; }
FixupKind kind() const { return kind_; }
void set_kind(FixupKind Kind) { kind_ = Kind; }
RelocOffsetT offset() const;
IceString symbol(const Assembler *Asm) const;
IceString symbol() const;
static const Constant *NullSymbol;
bool isNullSymbol() const { return value_ == NullSymbol; }
bool isNullSymbol() const { return ConstValue == NullSymbol; }
static constexpr AssemblerFixup *NoFixup = nullptr;
void set_value(const Constant *Value) { value_ = Value; }
bool valueIsSymbol() const { return ValueIsSymbol; }
void set_value(const Constant *Value) {
ValueIsSymbol = false;
ConstValue = Value;
}
void set_value(const ELFSym *Value) {
ValueIsSymbol = true;
SymbolValue = Value;
}
const ELFSym *getSymbolValue() const {
assert(ValueIsSymbol);
return SymbolValue;
}
void set_addend(RelocOffsetT Addend) { addend_ = Addend; }
RelocOffsetT get_addend() const { return addend_; }
......@@ -65,13 +73,19 @@ public:
virtual void emitOffset(Assembler *Asm) const;
private:
bool position_was_set_ = false;
intptr_t position_ = 0;
FixupKind kind_ = 0;
const Constant *value_ = nullptr;
// An offset addend to the fixup offset (as returned by offset()), in case the
// assembler needs to adjust it.
RelocOffsetT addend_ = 0;
// Tagged union that holds either a Constant or ELFSym pointer, depending on
// the ValueIsSymbol tag.
bool ValueIsSymbol = false;
union {
const Constant *ConstValue;
const ELFSym *SymbolValue;
};
};
/// Extends a fixup to be textual. That is, it emits text instead of a sequence
......
......@@ -270,8 +270,8 @@ class RelocOffset final {
RelocOffset &operator=(const RelocOffset &) = delete;
public:
static RelocOffset *create(GlobalContext *Ctx) {
return new (Ctx->allocate<RelocOffset>()) RelocOffset();
template <typename T> static RelocOffset *create(T *AllocOwner) {
return new (AllocOwner->template allocate<RelocOffset>()) RelocOffset();
}
static RelocOffset *create(GlobalContext *Ctx, RelocOffsetT Value) {
......@@ -342,10 +342,12 @@ class ConstantRelocatable : public Constant {
ConstantRelocatable &operator=(const ConstantRelocatable &) = delete;
public:
static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty,
template <typename T>
static ConstantRelocatable *create(T *AllocOwner, Type Ty,
const RelocatableTuple &Tuple) {
return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable(
Ty, Tuple.Offset, Tuple.OffsetExpr, Tuple.Name, Tuple.EmitString);
return new (AllocOwner->template allocate<ConstantRelocatable>())
ConstantRelocatable(Ty, Tuple.Offset, Tuple.OffsetExpr, Tuple.Name,
Tuple.EmitString);
}
RelocOffsetT getOffset() const {
......
......@@ -623,13 +623,14 @@ Inst *TargetX8664::emitCallToTarget(Operand *CallTarget, Variable *ReturnReg) {
//
// push .after_call
InstX86Label *ReturnAddress = InstX86Label::create(Func, this);
auto *ReturnRelocOffset = RelocOffset::create(Ctx);
auto *ReturnRelocOffset = RelocOffset::create(Func->getAssembler());
ReturnAddress->setRelocOffset(ReturnRelocOffset);
constexpr RelocOffsetT NoFixedOffset = 0;
const IceString EmitString = ReturnAddress->getName(Func);
auto *ReturnReloc = llvm::cast<ConstantRelocatable>(
Ctx->getConstantSym(NoFixedOffset, {ReturnRelocOffset},
Func->getFunctionName(), EmitString));
auto *ReturnReloc = ConstantRelocatable::create(
Func->getAssembler(), IceType_i32,
RelocatableTuple(NoFixedOffset, {ReturnRelocOffset},
Func->getFunctionName(), EmitString));
/* AutoBundle scoping */ {
std::unique_ptr<AutoBundle> Bundler;
if (CallTargetR == nullptr) {
......
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