"Number of optimized accesses to global vars");
namespace {
+/// Frontend-provided metadata for source location.
+struct LocationMetadata {
+ StringRef Filename;
+ int LineNo;
+ int ColumnNo;
+
+ LocationMetadata() : Filename(), LineNo(0), ColumnNo(0) {}
+
+ bool empty() const { return Filename.empty(); }
+
+ void parse(MDNode *MDN) {
+ assert(MDN->getNumOperands() == 3);
+ MDString *MDFilename = cast<MDString>(MDN->getOperand(0));
+ Filename = MDFilename->getString();
+ LineNo = cast<ConstantInt>(MDN->getOperand(1))->getLimitedValue();
+ ColumnNo = cast<ConstantInt>(MDN->getOperand(2))->getLimitedValue();
+ }
+};
+
/// Frontend-provided metadata for global variables.
class GlobalsMetadata {
public:
struct Entry {
Entry()
- : SourceLoc(nullptr), Name(nullptr), IsDynInit(false),
+ : SourceLoc(), Name(), IsDynInit(false),
IsBlacklisted(false) {}
- GlobalVariable *SourceLoc;
- GlobalVariable *Name;
+ LocationMetadata SourceLoc;
+ StringRef Name;
bool IsDynInit;
bool IsBlacklisted;
};
// We can already have an entry for GV if it was merged with another
// global.
Entry &E = Entries[GV];
- if (Value *Loc = MDN->getOperand(1)) {
- GlobalVariable *GVLoc = cast<GlobalVariable>(Loc);
- E.SourceLoc = GVLoc;
- addSourceLocationGlobal(GVLoc);
- }
+ if (Value *Loc = MDN->getOperand(1))
+ E.SourceLoc.parse(cast<MDNode>(Loc));
if (Value *Name = MDN->getOperand(2)) {
- GlobalVariable *GVName = cast<GlobalVariable>(Name);
- E.Name = GVName;
- InstrumentationGlobals.insert(GVName);
+ MDString *MDName = cast<MDString>(Name);
+ E.Name = MDName->getString();
}
ConstantInt *IsDynInit = cast<ConstantInt>(MDN->getOperand(3));
E.IsDynInit |= IsDynInit->isOne();
return (Pos != Entries.end()) ? Pos->second : Entry();
}
- /// Check if the global was generated by the instrumentation
- /// (we don't want to instrument it again in this case).
- bool isInstrumentationGlobal(GlobalVariable *G) const {
- return InstrumentationGlobals.count(G);
- }
-
private:
bool inited_;
DenseMap<GlobalVariable*, Entry> Entries;
- // Globals generated by the frontend instrumentation.
- DenseSet<GlobalVariable*> InstrumentationGlobals;
-
- void addSourceLocationGlobal(GlobalVariable *SourceLocGV) {
- // Source location global is a struct with layout:
- // {
- // filename,
- // i32 line_number,
- // i32 column_number,
- // }
- InstrumentationGlobals.insert(SourceLocGV);
- ConstantStruct *Contents =
- cast<ConstantStruct>(SourceLocGV->getInitializer());
- GlobalVariable *FilenameGV = cast<GlobalVariable>(Contents->getOperand(0));
- InstrumentationGlobals.insert(FilenameGV);
- }
};
/// This struct defines the shadow mapping using the rule:
return GV;
}
+/// \brief Create a global describing a source location.
+static GlobalVariable *createPrivateGlobalForSourceLoc(Module &M,
+ LocationMetadata MD) {
+ Constant *LocData[] = {
+ createPrivateGlobalForString(M, MD.Filename, true),
+ ConstantInt::get(Type::getInt32Ty(M.getContext()), MD.LineNo),
+ ConstantInt::get(Type::getInt32Ty(M.getContext()), MD.ColumnNo),
+ };
+ auto LocStruct = ConstantStruct::getAnon(LocData);
+ auto GV = new GlobalVariable(M, LocStruct->getType(), true,
+ GlobalValue::PrivateLinkage, LocStruct,
+ kAsanGenPrefix);
+ GV->setUnnamedAddr(true);
+ return GV;
+}
+
static bool GlobalWasGeneratedByAsan(GlobalVariable *G) {
return G->getName().find(kAsanGenPrefix) == 0;
}
// and set IsWrite/Alignment. Otherwise return NULL.
static Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite,
unsigned *Alignment) {
+ // Skip memory accesses inserted by another instrumentation.
+ if (I->getMetadata("nosanitize"))
+ return nullptr;
if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
if (!ClInstrumentReads) return nullptr;
*IsWrite = false;
DEBUG(dbgs() << "GLOBAL: " << *G << "\n");
if (GlobalsMD.get(G).IsBlacklisted) return false;
- if (GlobalsMD.isInstrumentationGlobal(G)) return false;
if (!Ty->isSized()) return false;
if (!G->hasInitializer()) return false;
if (GlobalWasGeneratedByAsan(G)) return false; // Our own global.
GlobalVariable *G = GlobalsToChange[i];
auto MD = GlobalsMD.get(G);
- // Create string holding the global name unless it was provided by
- // the metadata.
- GlobalVariable *Name =
- MD.Name ? MD.Name : createPrivateGlobalForString(M, G->getName(),
- /*AllowMerging*/ true);
+ // Create string holding the global name (use global name from metadata
+ // if it's available, otherwise just write the name of global variable).
+ GlobalVariable *Name = createPrivateGlobalForString(
+ M, MD.Name.empty() ? G->getName() : MD.Name,
+ /*AllowMerging*/ true);
PointerType *PtrTy = cast<PointerType>(G->getType());
Type *Ty = PtrTy->getElementType();
NewGlobal->takeName(G);
G->eraseFromParent();
+ Constant *SourceLoc;
+ if (!MD.SourceLoc.empty()) {
+ auto SourceLocGlobal = createPrivateGlobalForSourceLoc(M, MD.SourceLoc);
+ SourceLoc = ConstantExpr::getPointerCast(SourceLocGlobal, IntptrTy);
+ } else {
+ SourceLoc = ConstantInt::get(IntptrTy, 0);
+ }
+
Initializers[i] = ConstantStruct::get(
GlobalStructTy, ConstantExpr::getPointerCast(NewGlobal, IntptrTy),
ConstantInt::get(IntptrTy, SizeInBytes),
ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize),
ConstantExpr::getPointerCast(Name, IntptrTy),
ConstantExpr::getPointerCast(ModuleName, IntptrTy),
- ConstantInt::get(IntptrTy, MD.IsDynInit),
- MD.SourceLoc ? ConstantExpr::getPointerCast(MD.SourceLoc, IntptrTy)
- : ConstantInt::get(IntptrTy, 0),
- NULL);
+ ConstantInt::get(IntptrTy, MD.IsDynInit), SourceLoc, NULL);
if (ClInitializers && MD.IsDynInit)
HasDynamicallyInitializedGlobals = true;
Cmp, IP, false, MDBuilder(*C).createBranchWeights(1, 100000));
IRB.SetInsertPoint(Ins);
IRB.SetCurrentDebugLocation(EntryLoc);
- // We pass &F to __sanitizer_cov. We could avoid this and rely on
- // GET_CALLER_PC, but having the PC of the first instruction is just nice.
+ // __sanitizer_cov gets the PC of the instruction using GET_CALLER_PC.
IRB.CreateCall(AsanCovFunction);
StoreInst *Store = IRB.CreateStore(ConstantInt::get(Int8Ty, 1), Guard);
Store->setAtomic(Monotonic);
// as the function and inject this code into the entry block (-asan-coverage=1)
// or all blocks (-asan-coverage=2):
// if (*Guard) {
-// __sanitizer_cov(&F);
+// __sanitizer_cov();
// *Guard = 1;
// }
// The accesses to Guard are atomic. The rest of the logic is