Commit 3f5cb6f3 by Thomas Lively

Implemented global redzones.

parent 7984b713
......@@ -282,6 +282,7 @@ SB_LDFLAGS := $(LINKOPTLEVEL) $(LD_EXTRA)
# List the target-specific source files first, which generally take longer to
# compile, in the hope of improving parallel build time.
SRCS = \
IceASanInstrumentation.cpp \
IceAssemblerARM32.cpp \
IceInstrumentation.cpp \
IceInstARM32.cpp \
......
//===- subzero/src/IceASanInstrumentation.cpp - ASan ------------*- C++ -*-===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Implements the AddressSanitizer instrumentation class.
///
//===----------------------------------------------------------------------===//
#include "IceASanInstrumentation.h"
#include "IceBuildDefs.h"
#include "IceGlobalInits.h"
#include <sstream>
namespace Ice {
namespace {
constexpr SizeT RzSize = 32;
const std::string RzPrefix = "__$rz";
const llvm::NaClBitcodeRecord::RecordVector RzContents =
llvm::NaClBitcodeRecord::RecordVector(RzSize, 'R');
} // end of anonymous namespace
// Create redzones between all global variables, ensuring that the initializer
// types of the redzones and their associated globals match so that they are
// laid out together in memory.
void ASanInstrumentation::instrumentGlobals(VariableDeclarationList &Globals) {
if (BuildDefs::minimal() || DidInsertRedZones)
return;
VariableDeclarationList NewGlobals;
// Global holding pointers to all redzones
auto *RzArray = VariableDeclaration::create(&NewGlobals);
// Global holding the size of RzArray
auto *RzArraySizeVar = VariableDeclaration::create(&NewGlobals);
SizeT RzArraySize = 0;
RzArray->setName(Ctx, nextRzName());
RzArraySizeVar->setName(Ctx, nextRzName());
RzArray->setIsConstant(true);
RzArraySizeVar->setIsConstant(true);
NewGlobals.push_back(RzArray);
NewGlobals.push_back(RzArraySizeVar);
for (VariableDeclaration *Global : Globals) {
VariableDeclaration *RzLeft = createRz(&NewGlobals, RzArray, RzArraySize, Global);
VariableDeclaration *RzRight = createRz(&NewGlobals, RzArray, RzArraySize, Global);
NewGlobals.push_back(RzLeft);
NewGlobals.push_back(Global);
NewGlobals.push_back(RzRight);
}
// update the contents of the RzArraySize global
llvm::NaClBitcodeRecord::RecordVector SizeContents;
for (unsigned i = 0; i < sizeof(RzArraySize); i++) {
SizeContents.emplace_back(RzArraySize % (1 << CHAR_BIT));
RzArraySize >>= CHAR_BIT;
}
RzArraySizeVar->addInitializer(
VariableDeclaration::DataInitializer::create(&NewGlobals, SizeContents));
// Replace old list of globals, without messing up arena allocators
Globals.clear();
Globals.merge(&NewGlobals);
DidInsertRedZones = true;
// Log the new set of globals
if (BuildDefs::dump() && (getFlags().getVerbose() & IceV_GlobalInit)) {
OstreamLocker _(Ctx);
Ctx->getStrDump() << "========= Instrumented Globals =========\n";
for (VariableDeclaration *Global : Globals) {
Global->dump(Ctx->getStrDump());
}
}
}
std::string ASanInstrumentation::nextRzName() {
if (BuildDefs::minimal())
return "";
std::stringstream Name;
Name << RzPrefix << RzNum++;
return Name.str();
}
VariableDeclaration *
ASanInstrumentation::createRz(VariableDeclarationList *List,
VariableDeclaration *RzArray, SizeT &RzArraySize,
VariableDeclaration *Global) {
if (BuildDefs::minimal())
return nullptr;
auto *Rz = VariableDeclaration::create(List);
Rz->setName(Ctx, nextRzName());
if (Global->hasNonzeroInitializer()) {
Rz->addInitializer(
VariableDeclaration::DataInitializer::create(List, RzContents));
} else {
Rz->addInitializer(
VariableDeclaration::ZeroInitializer::create(List, RzSize));
}
Rz->setIsConstant(Global->getIsConstant());
RzArray->addInitializer(VariableDeclaration::RelocInitializer::create(
List, Rz, RelocOffsetArray(0)));
++RzArraySize;
return Rz;
}
} // end of namespace Ice
//===- subzero/src/IceASanInstrumentation.h - AddressSanitizer --*- C++ -*-===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Declares the AddressSanitizer instrumentation class.
///
/// This class is responsible for inserting redzones around global and stack
/// variables, inserting code responsible for poisoning those redzones, and
/// performing any other instrumentation necessary to implement
/// AddressSanitizer.
///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEASANINSTRUMENTATION_H
#define SUBZERO_SRC_ICEASANINSTRUMENTATION_H
#include "IceGlobalInits.h"
#include "IceInstrumentation.h"
namespace Ice {
class ASanInstrumentation : public Instrumentation {
ASanInstrumentation() = delete;
ASanInstrumentation(const ASanInstrumentation &) = delete;
ASanInstrumentation &operator=(const ASanInstrumentation &) = delete;
public:
ASanInstrumentation(GlobalContext *Ctx) : Instrumentation(Ctx) {}
void instrumentGlobals(VariableDeclarationList &Globals) override;
private:
std::string nextRzName();
VariableDeclaration *createRz(VariableDeclarationList *List,
VariableDeclaration *RzArray,
SizeT &RzArraySize,
VariableDeclaration *Global);
bool DidInsertRedZones = false;
uint32_t RzNum = 0;
};
} // end of namespace Ice
#endif // SUBZERO_SRC_ICEASANINSTRUMENTATION_H
......@@ -14,6 +14,7 @@
#include "IceCompileServer.h"
#include "IceASanInstrumentation.h"
#include "IceClFlags.h"
#include "IceELFStreamer.h"
#include "IceGlobalContext.h"
......@@ -244,7 +245,7 @@ void CLCompileServer::run() {
// TODO(tlively): Make this instantiate an instrumentation subclass
if (!BuildDefs::minimal() && getFlags().getSanitizeAddresses()) {
std::unique_ptr<Instrumentation> Instr(new Instrumentation(Ctx.get()));
std::unique_ptr<Instrumentation> Instr(new ASanInstrumentation(Ctx.get()));
Ctx->setInstrumentation(std::move(Instr));
}
......
......@@ -177,7 +177,7 @@ public:
}
// This do nothing method is invoked when a global variable is created, but it
// will not be emitted. If we ever need to track the created variabled, having
// will not be emitted. If we ever need to track the created variable, having
// this hook is handy.
void willNotBeEmitted(VariableDeclaration *) {}
......
......@@ -488,7 +488,7 @@ void GlobalContext::lowerGlobals(const std::string &SectionSuffix) {
}
if (!BuildDefs::minimal() && Instrumentor)
Instrumentor->instrumentGlobals();
Instrumentor->instrumentGlobals(Globals);
DataLowering->lowerGlobals(Globals, SectionSuffix);
if (ProfileBlockInfos.empty() && DisposeGlobalVariablesAfterLowering) {
......
......@@ -279,7 +279,7 @@ public:
: Initializer(DataInitializerKind), ContentsSize(Values.size()),
// ugh, we should actually do new char[], but this may involve
// implementation-specific details. Given that Contents is arena
// allocated, and never detele[]d, just use char --
// allocated, and never delete[]d, just use char --
// AllocOwner->allocate_array will allocate a buffer with the right
// size.
Contents(new (VDL->allocate_initializer<char>(ContentsSize)) char) {
......
......@@ -47,61 +47,61 @@ void Instrumentation::instrumentInst(LoweringContext &Context) {
assert(!Context.atEnd());
Inst *Instr = iteratorToInst(Context.getCur());
switch (Instr->getKind()) {
case Inst::Alloca:
instrumentAlloca(Context, llvm::cast<InstAlloca>(Instr));
break;
case Inst::Arithmetic:
instrumentArithmetic(Context, llvm::cast<InstArithmetic>(Instr));
break;
case Inst::Br:
instrumentBr(Context, llvm::cast<InstBr>(Instr));
break;
case Inst::Call:
instrumentCall(Context, llvm::cast<InstCall>(Instr));
break;
case Inst::Cast:
instrumentCast(Context, llvm::cast<InstCast>(Instr));
break;
case Inst::ExtractElement:
instrumentExtractElement(Context, llvm::cast<InstExtractElement>(Instr));
break;
case Inst::Fcmp:
instrumentFcmp(Context, llvm::cast<InstFcmp>(Instr));
break;
case Inst::Icmp:
instrumentIcmp(Context, llvm::cast<InstIcmp>(Instr));
break;
case Inst::InsertElement:
instrumentInsertElement(Context, llvm::cast<InstInsertElement>(Instr));
break;
case Inst::IntrinsicCall:
instrumentIntrinsicCall(Context, llvm::cast<InstIntrinsicCall>(Instr));
break;
case Inst::Load:
instrumentLoad(Context, llvm::cast<InstLoad>(Instr));
break;
case Inst::Phi:
instrumentPhi(Context, llvm::cast<InstPhi>(Instr));
break;
case Inst::Ret:
instrumentRet(Context, llvm::cast<InstRet>(Instr));
break;
case Inst::Select:
instrumentSelect(Context, llvm::cast<InstSelect>(Instr));
break;
case Inst::Store:
instrumentStore(Context, llvm::cast<InstStore>(Instr));
break;
case Inst::Switch:
instrumentSwitch(Context, llvm::cast<InstSwitch>(Instr));
break;
case Inst::Unreachable:
instrumentUnreachable(Context, llvm::cast<InstUnreachable>(Instr));
break;
default:
// Only instrument high-level ICE instructions
assert(false && "Instrumentation encountered an unexpected instruction");
break;
case Inst::Alloca:
instrumentAlloca(Context, llvm::cast<InstAlloca>(Instr));
break;
case Inst::Arithmetic:
instrumentArithmetic(Context, llvm::cast<InstArithmetic>(Instr));
break;
case Inst::Br:
instrumentBr(Context, llvm::cast<InstBr>(Instr));
break;
case Inst::Call:
instrumentCall(Context, llvm::cast<InstCall>(Instr));
break;
case Inst::Cast:
instrumentCast(Context, llvm::cast<InstCast>(Instr));
break;
case Inst::ExtractElement:
instrumentExtractElement(Context, llvm::cast<InstExtractElement>(Instr));
break;
case Inst::Fcmp:
instrumentFcmp(Context, llvm::cast<InstFcmp>(Instr));
break;
case Inst::Icmp:
instrumentIcmp(Context, llvm::cast<InstIcmp>(Instr));
break;
case Inst::InsertElement:
instrumentInsertElement(Context, llvm::cast<InstInsertElement>(Instr));
break;
case Inst::IntrinsicCall:
instrumentIntrinsicCall(Context, llvm::cast<InstIntrinsicCall>(Instr));
break;
case Inst::Load:
instrumentLoad(Context, llvm::cast<InstLoad>(Instr));
break;
case Inst::Phi:
instrumentPhi(Context, llvm::cast<InstPhi>(Instr));
break;
case Inst::Ret:
instrumentRet(Context, llvm::cast<InstRet>(Instr));
break;
case Inst::Select:
instrumentSelect(Context, llvm::cast<InstSelect>(Instr));
break;
case Inst::Store:
instrumentStore(Context, llvm::cast<InstStore>(Instr));
break;
case Inst::Switch:
instrumentSwitch(Context, llvm::cast<InstSwitch>(Instr));
break;
case Inst::Unreachable:
instrumentUnreachable(Context, llvm::cast<InstUnreachable>(Instr));
break;
default:
// Only instrument high-level ICE instructions
assert(false && "Instrumentation encountered an unexpected instruction");
break;
}
}
......
......@@ -41,102 +41,35 @@ class Instrumentation {
public:
Instrumentation(GlobalContext *Ctx) : Ctx(Ctx) {}
virtual void instrumentGlobals() {};
virtual void instrumentGlobals(VariableDeclarationList &) {}
void instrumentFunc(Cfg *Func);
private:
void instrumentInst(LoweringContext &Context);
virtual void instrumentFuncStart(LoweringContext &Context) {
(void) Context;
}
virtual void instrumentAlloca(LoweringContext &Context,
const class InstAlloca *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentArithmetic(LoweringContext &Context,
const class InstArithmetic *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentBr(LoweringContext &Context,
const class InstBr *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentCall(LoweringContext &Context,
const class InstCall *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentCast(LoweringContext &Context,
const class InstCast *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentExtractElement(LoweringContext &Context,
const class InstExtractElement *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentFcmp(LoweringContext &Context,
const class InstFcmp *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentIcmp(LoweringContext &Context,
const class InstIcmp *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentInsertElement(LoweringContext &Context,
const class InstInsertElement *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentIntrinsicCall(LoweringContext &Context,
const class InstIntrinsicCall *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentLoad(LoweringContext &Context,
const class InstLoad *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentPhi(LoweringContext &Context,
const class InstPhi *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentRet(LoweringContext &Context,
const class InstRet *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentSelect(LoweringContext &Context,
const class InstSelect *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentStore(LoweringContext &Context,
const class InstStore *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentSwitch(LoweringContext &Context,
const class InstSwitch *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentUnreachable(LoweringContext &Context,
const class InstUnreachable *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentLocalVars(Cfg *Func) {
(void) Func;
}
virtual void instrumentFuncStart(LoweringContext &) {}
virtual void instrumentAlloca(LoweringContext &, const class InstAlloca *) {}
virtual void instrumentArithmetic(LoweringContext &,
const class InstArithmetic *) {}
virtual void instrumentBr(LoweringContext &, const class InstBr *) {}
virtual void instrumentCall(LoweringContext &, const class InstCall *) {}
virtual void instrumentCast(LoweringContext &, const class InstCast *) {}
virtual void instrumentExtractElement(LoweringContext &,
const class InstExtractElement *) {}
virtual void instrumentFcmp(LoweringContext &, const class InstFcmp *) {}
virtual void instrumentIcmp(LoweringContext &, const class InstIcmp *) {}
virtual void instrumentInsertElement(LoweringContext &,
const class InstInsertElement *) {}
virtual void instrumentIntrinsicCall(LoweringContext &,
const class InstIntrinsicCall *) {}
virtual void instrumentLoad(LoweringContext &, const class InstLoad *) {}
virtual void instrumentPhi(LoweringContext &, const class InstPhi *) {}
virtual void instrumentRet(LoweringContext &, const class InstRet *) {}
virtual void instrumentSelect(LoweringContext &, const class InstSelect *) {}
virtual void instrumentStore(LoweringContext &, const class InstStore *) {}
virtual void instrumentSwitch(LoweringContext &, const class InstSwitch *) {}
virtual void instrumentUnreachable(LoweringContext &,
const class InstUnreachable *) {}
virtual void instrumentLocalVars(Cfg *) {}
protected:
GlobalContext *Ctx;
......
; Test of global redzone layout
; REQUIRES: allow_dump
; RUN: %p2i -i %s --args -threads=0 -fsanitize-address \
; RUN: | %iflc FileCheck %s
; RUN: %p2i -i %s --args -verbose=global_init,inst -threads=0 \
; RUN: -fsanitize-address | %iflc FileCheck --check-prefix=DUMP %s
; The array of redzones
; DUMP-LABEL: ========= Instrumented Globals =========
; DUMP: @__$rz0 = internal constant <{ i32, i32, i32, i32, i32, i32 }>
; DUMP: <{ i32 ptrtoint ([32 x i8]* @__$rz2 to i32), i32 ptrtoint ([32 x i8]* @__$rz3 to i32),
; DUMP: i32 ptrtoint ([32 x i8]* @__$rz4 to i32), i32 ptrtoint ([32 x i8]* @__$rz5 to i32),
; DUMP: i32 ptrtoint ([32 x i8]* @__$rz6 to i32), i32 ptrtoint ([32 x i8]* @__$rz7 to i32) }>
; DUMP-NEXT: @__$rz1 = internal constant [4 x i8] c"\06\00\00\00"
; CHECK-LABEL: .type __$rz0,%object
; CHECK-NEXT: .section .rodata
; CHECK-NEXT: __$rz0:
; CHECK-NEXT: .long __$rz2
; CHECK-NEXT: .long __$rz3
; CHECK-NEXT: .long __$rz4
; CHECK-NEXT: .long __$rz5
; CHECK-NEXT: .long __$rz6
; CHECK-NEXT: .long __$rz7
; CHECK-LABEL: .type __$rz1,%object
; CHECK-NEXT: .section .rodata
; CHECK-NEXT: __$rz1:
; CHECK-NEXT: .byte 6
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .byte 0
; A zero-initialized global
@zeroInitGlobal = internal global [32 x i8] zeroinitializer
; DUMP-NEXT: @__$rz2 = internal global [32 x i8] zeroinitializer
; DUMP-NEXT: @zeroInitGlobal = internal global [32 x i8] zeroinitializer
; DUMP-NEXT: @__$rz3 = internal global [32 x i8] zeroinitializer
; CHECK-LABEL: .type __$rz2,%object
; CHECK-NEXT: .section .bss
; CHECK-NEXT: __$rz2:
; CHECK-LABEL: .type zeroInitGlobal,%object
; CHECK-NEXT: .section .bss
; CHECK-NEXT: zeroInitGlobal:
; CHECK-LABEL: .type __$rz3,%object
; CHECK-NEXT: .section .bss
; CHECK-NEXT: __$rz3:
; A constant-initialized global
@constInitGlobal = internal constant [32 x i8] c"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"
; CHECK-LABEL: .type __$rz4,%object
; CHECK-NEXT: .section .rodata
; CHECK-NEXT: __$rz4:
; CHECK-LABEL: .type constInitGlobal,%object
; CHECK-NEXT: .section .rodata
; CHECK-NEXT: constInitGlobal:
; CHECK-LABEL: .type __$rz5,%object
; CHECK-NEXT: .section .rodata
; CHECK-NEXT: __$rz5:
; DUMP-NEXT: @__$rz4 = internal constant [32 x i8] c"RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"
; DUMP-NEXT: @constInitGlobal = internal constant [32 x i8] c"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"
; DUMP-NEXT: @__$rz5 = internal constant [32 x i8] c"RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"
; A regular global
@regInitGlobal = internal global [32 x i8] c"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"
; DUMP-NEXT: @__$rz6 = internal global [32 x i8] c"RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"
; DUMP-NEXT: @regInitGlobal = internal global [32 x i8] c"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"
; DUMP-NEXT: @__$rz7 = internal global [32 x i8] c"RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"
; CHECK-LABEL: .type __$rz6,%object
; CHECK-NEXT: .section .data
; CHECK-NEXT: __$rz6:
; CHECK-LABEL: .type regInitGlobal,%object
; CHECK-NEXT: .section .data
; CHECK-NEXT: regInitGlobal:
; CHECK-LABEL: .type __$rz7,%object
; CHECK-NEXT: .section .data
; CHECK-NEXT: __$rz7:
define internal void @func() {
ret void
}
; DUMP-LABEL: define internal void @func() {
; CHECK-LABEL: func:
\ No newline at end of file
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