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(): ...@@ -205,6 +205,8 @@ def main():
f.write(run_cmd + '\n') f.write(run_cmd + '\n')
f.write('echo Recreate a failure using ' + __file__ + f.write('echo Recreate a failure using ' + __file__ +
' --toolchain-root=' + args.toolchain_root + ' --toolchain-root=' + args.toolchain_root +
(' --filetype=' + args.filetype
if args.filetype else '') +
' --include=' + ','.join(desc) + '\n') ' --include=' + ','.join(desc) + '\n')
f.write('# CHECK: Failures=0\n') f.write('# CHECK: Failures=0\n')
else: else:
......
...@@ -593,11 +593,16 @@ size_t MoveRelocatableFixup::emit(GlobalContext *Ctx, ...@@ -593,11 +593,16 @@ size_t MoveRelocatableFixup::emit(GlobalContext *Ctx,
IValueT Inst = Asm.load<IValueT>(position()); IValueT Inst = Asm.load<IValueT>(position());
const bool IsMovw = kind() == llvm::ELF::R_ARM_MOVW_ABS_NC || const bool IsMovw = kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ||
kind() == llvm::ELF::R_ARM_MOVW_PREL_NC; kind() == llvm::ELF::R_ARM_MOVW_PREL_NC;
const IceString Symbol = symbol();
const bool NeedsPCRelSuffix =
(Asm.fixupIsPCRel(kind()) || Symbol == GlobalOffsetTable);
Str << "\t" Str << "\t"
"mov" << (IsMovw ? "w" : "t") << "\t" "mov" << (IsMovw ? "w" : "t") << "\t"
<< RegARM32::getRegName(RegNumT::fixme((Inst >> kRdShift) & 0xF)) << RegARM32::getRegName(RegNumT::fixme((Inst >> kRdShift) & 0xF))
<< ", #:" << (IsMovw ? "lower" : "upper") << "16:" << symbol(&Asm) << ", #:" << (IsMovw ? "lower" : "upper") << "16:" << Symbol
<< "\t@ .word " << llvm::format_hex_no_prefix(Inst, 8) << "\n"; << (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; return InstARM32::InstSize;
} }
...@@ -650,7 +655,7 @@ size_t BlRelocatableFixup::emit(GlobalContext *Ctx, ...@@ -650,7 +655,7 @@ size_t BlRelocatableFixup::emit(GlobalContext *Ctx,
Ostream &Str = Ctx->getStrEmit(); Ostream &Str = Ctx->getStrEmit();
IValueT Inst = Asm.load<IValueT>(position()); IValueT Inst = Asm.load<IValueT>(position());
Str << "\t" Str << "\t"
"bl\t" << symbol(&Asm) << "\t@ .word " "bl\t" << symbol() << "\t@ .word "
<< llvm::format_hex_no_prefix(Inst, 8) << "\n"; << llvm::format_hex_no_prefix(Inst, 8) << "\n";
return InstARM32::InstSize; return InstARM32::InstSize;
} }
......
...@@ -160,8 +160,10 @@ public: ...@@ -160,8 +160,10 @@ public:
} }
bool fixupIsPCRel(FixupKind Kind) const override { bool fixupIsPCRel(FixupKind Kind) const override {
(void)Kind; if (Kind == llvm::ELF::R_ARM_MOVW_PREL_NC)
// TODO(kschimpf) Decide if we need this. return true;
if (Kind == llvm::ELF::R_ARM_MOVT_PREL)
return true;
return false; return false;
} }
......
...@@ -275,7 +275,7 @@ void ELFObjectWriter::writeFunctionCode(const IceString &FuncName, ...@@ -275,7 +275,7 @@ void ELFObjectWriter::writeFunctionCode(const IceString &FuncName,
Fixup->emitOffset(Asm); Fixup->emitOffset(Asm);
} }
} }
RelSection->addRelocations(OffsetInSection, Asm->fixups()); RelSection->addRelocations(OffsetInSection, Asm->fixups(), SymTab);
} }
Section->appendData(Str, Asm->getBufferView()); Section->appendData(Str, Asm->getBufferView());
if (TimeThisFunction) if (TimeThisFunction)
......
...@@ -67,11 +67,24 @@ void ELFDataSection::padToAlignment(ELFStreamer &Str, Elf64_Xword Align) { ...@@ -67,11 +67,24 @@ void ELFDataSection::padToAlignment(ELFStreamer &Str, Elf64_Xword Align) {
// Relocation sections. // Relocation sections.
void ELFRelocationSection::addRelocations(RelocOffsetT BaseOff, void ELFRelocationSection::addRelocations(RelocOffsetT BaseOff,
const FixupRefList &FixupRefs) { const FixupRefList &FixupRefs,
ELFSymbolTableSection *SymTab) {
for (const AssemblerFixup *FR : FixupRefs) { for (const AssemblerFixup *FR : FixupRefs) {
Fixups.push_back(*FR); Fixups.push_back(*FR);
AssemblerFixup &F = Fixups.back(); AssemblerFixup &F = Fixups.back();
F.set_position(BaseOff + F.position()); 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: ...@@ -232,7 +232,8 @@ public:
/// Track additional relocations which start out relative to offset 0, but /// Track additional relocations which start out relative to offset 0, but
/// should be adjusted to be relative to BaseOff. /// 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. /// Track a single additional relocation.
void addRelocation(const AssemblerFixup &Fixup) { Fixups.push_back(Fixup); } void addRelocation(const AssemblerFixup &Fixup) { Fixups.push_back(Fixup); }
...@@ -353,9 +354,10 @@ void ELFRelocationSection::writeData(ELFStreamer &Str, ...@@ -353,9 +354,10 @@ void ELFRelocationSection::writeData(ELFStreamer &Str,
const ELFSym *Symbol; const ELFSym *Symbol;
if (Fixup.isNullSymbol()) { if (Fixup.isNullSymbol()) {
Symbol = SymTab->getNullSymbol(); Symbol = SymTab->getNullSymbol();
} else if (Fixup.valueIsSymbol()) {
Symbol = Fixup.getSymbolValue();
} else { } else {
constexpr Assembler *Asm = nullptr; const IceString Name = Fixup.symbol();
const IceString Name = Fixup.symbol(Asm);
Symbol = SymTab->findSymbol(Name); Symbol = SymTab->findSymbol(Name);
if (!Symbol) if (!Symbol)
llvm::report_fatal_error(Name + ": Missing symbol mentioned in reloc"); llvm::report_fatal_error(Name + ": Missing symbol mentioned in reloc");
......
...@@ -24,30 +24,26 @@ const Constant *AssemblerFixup::NullSymbol = nullptr; ...@@ -24,30 +24,26 @@ const Constant *AssemblerFixup::NullSymbol = nullptr;
RelocOffsetT AssemblerFixup::offset() const { RelocOffsetT AssemblerFixup::offset() const {
if (isNullSymbol()) if (isNullSymbol())
return addend_; return addend_;
if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(value_)) if (!ValueIsSymbol) {
return CR->getOffset() + addend_; if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(ConstValue))
return CR->getOffset() + addend_;
}
return addend_; return addend_;
} }
IceString AssemblerFixup::symbol(const Assembler *Asm) const { IceString AssemblerFixup::symbol() const {
std::string Buffer;
llvm::raw_string_ostream Str(Buffer);
const Constant *C = value_;
assert(!isNullSymbol()); assert(!isNullSymbol());
assert(!ValueIsSymbol);
const Constant *C = ConstValue;
if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(C)) { if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(C)) {
Str << CR->getName(); return 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);
} }
// 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(); return Str.str();
} }
...@@ -61,8 +57,16 @@ size_t AssemblerFixup::emit(GlobalContext *Ctx, const Assembler &Asm) const { ...@@ -61,8 +57,16 @@ size_t AssemblerFixup::emit(GlobalContext *Ctx, const Assembler &Asm) const {
if (isNullSymbol()) { if (isNullSymbol()) {
Str << "__Sz_AbsoluteZero"; Str << "__Sz_AbsoluteZero";
} else { } else {
Symbol = symbol(&Asm); Symbol = symbol();
Str << 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); assert(Asm.load<RelocOffsetT>(position()) == 0);
......
...@@ -23,6 +23,8 @@ namespace Ice { ...@@ -23,6 +23,8 @@ namespace Ice {
/// This holds the specific target+container format's relocation number. /// This holds the specific target+container format's relocation number.
using FixupKind = uint32_t; using FixupKind = uint32_t;
struct ELFSym;
/// Assembler fixups are positions in generated code/data that hold relocation /// Assembler fixups are positions in generated code/data that hold relocation
/// information that needs to be processed before finalizing the code/data. /// information that needs to be processed before finalizing the code/data.
class AssemblerFixup { class AssemblerFixup {
...@@ -32,27 +34,33 @@ public: ...@@ -32,27 +34,33 @@ public:
AssemblerFixup() = default; AssemblerFixup() = default;
AssemblerFixup(const AssemblerFixup &) = default; AssemblerFixup(const AssemblerFixup &) = default;
virtual ~AssemblerFixup() = default; virtual ~AssemblerFixup() = default;
intptr_t position() const { intptr_t position() const { return position_; }
assert(position_was_set_); void set_position(intptr_t Position) { position_ = Position; }
return position_;
}
void set_position(intptr_t Position) {
position_ = Position;
position_was_set_ = true;
}
FixupKind kind() const { return kind_; } FixupKind kind() const { return kind_; }
void set_kind(FixupKind Kind) { kind_ = Kind; } void set_kind(FixupKind Kind) { kind_ = Kind; }
RelocOffsetT offset() const; RelocOffsetT offset() const;
IceString symbol(const Assembler *Asm) const; IceString symbol() const;
static const Constant *NullSymbol; static const Constant *NullSymbol;
bool isNullSymbol() const { return value_ == NullSymbol; } bool isNullSymbol() const { return ConstValue == NullSymbol; }
static constexpr AssemblerFixup *NoFixup = nullptr; 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; } void set_addend(RelocOffsetT Addend) { addend_ = Addend; }
RelocOffsetT get_addend() const { return addend_; } RelocOffsetT get_addend() const { return addend_; }
...@@ -65,13 +73,19 @@ public: ...@@ -65,13 +73,19 @@ public:
virtual void emitOffset(Assembler *Asm) const; virtual void emitOffset(Assembler *Asm) const;
private: private:
bool position_was_set_ = false;
intptr_t position_ = 0; intptr_t position_ = 0;
FixupKind kind_ = 0; FixupKind kind_ = 0;
const Constant *value_ = nullptr;
// An offset addend to the fixup offset (as returned by offset()), in case the // An offset addend to the fixup offset (as returned by offset()), in case the
// assembler needs to adjust it. // assembler needs to adjust it.
RelocOffsetT addend_ = 0; 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 /// Extends a fixup to be textual. That is, it emits text instead of a sequence
......
...@@ -270,8 +270,8 @@ class RelocOffset final { ...@@ -270,8 +270,8 @@ class RelocOffset final {
RelocOffset &operator=(const RelocOffset &) = delete; RelocOffset &operator=(const RelocOffset &) = delete;
public: public:
static RelocOffset *create(GlobalContext *Ctx) { template <typename T> static RelocOffset *create(T *AllocOwner) {
return new (Ctx->allocate<RelocOffset>()) RelocOffset(); return new (AllocOwner->template allocate<RelocOffset>()) RelocOffset();
} }
static RelocOffset *create(GlobalContext *Ctx, RelocOffsetT Value) { static RelocOffset *create(GlobalContext *Ctx, RelocOffsetT Value) {
...@@ -342,10 +342,12 @@ class ConstantRelocatable : public Constant { ...@@ -342,10 +342,12 @@ class ConstantRelocatable : public Constant {
ConstantRelocatable &operator=(const ConstantRelocatable &) = delete; ConstantRelocatable &operator=(const ConstantRelocatable &) = delete;
public: public:
static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty, template <typename T>
static ConstantRelocatable *create(T *AllocOwner, Type Ty,
const RelocatableTuple &Tuple) { const RelocatableTuple &Tuple) {
return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable( return new (AllocOwner->template allocate<ConstantRelocatable>())
Ty, Tuple.Offset, Tuple.OffsetExpr, Tuple.Name, Tuple.EmitString); ConstantRelocatable(Ty, Tuple.Offset, Tuple.OffsetExpr, Tuple.Name,
Tuple.EmitString);
} }
RelocOffsetT getOffset() const { RelocOffsetT getOffset() const {
......
...@@ -623,13 +623,14 @@ Inst *TargetX8664::emitCallToTarget(Operand *CallTarget, Variable *ReturnReg) { ...@@ -623,13 +623,14 @@ Inst *TargetX8664::emitCallToTarget(Operand *CallTarget, Variable *ReturnReg) {
// //
// push .after_call // push .after_call
InstX86Label *ReturnAddress = InstX86Label::create(Func, this); InstX86Label *ReturnAddress = InstX86Label::create(Func, this);
auto *ReturnRelocOffset = RelocOffset::create(Ctx); auto *ReturnRelocOffset = RelocOffset::create(Func->getAssembler());
ReturnAddress->setRelocOffset(ReturnRelocOffset); ReturnAddress->setRelocOffset(ReturnRelocOffset);
constexpr RelocOffsetT NoFixedOffset = 0; constexpr RelocOffsetT NoFixedOffset = 0;
const IceString EmitString = ReturnAddress->getName(Func); const IceString EmitString = ReturnAddress->getName(Func);
auto *ReturnReloc = llvm::cast<ConstantRelocatable>( auto *ReturnReloc = ConstantRelocatable::create(
Ctx->getConstantSym(NoFixedOffset, {ReturnRelocOffset}, Func->getAssembler(), IceType_i32,
Func->getFunctionName(), EmitString)); RelocatableTuple(NoFixedOffset, {ReturnRelocOffset},
Func->getFunctionName(), EmitString));
/* AutoBundle scoping */ { /* AutoBundle scoping */ {
std::unique_ptr<AutoBundle> Bundler; std::unique_ptr<AutoBundle> Bundler;
if (CallTargetR == nullptr) { 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