Improve debug info generated with enabled AddressSanitizer.

When ASan replaces <alloca instruction> with
<offset into a common large alloca>, it should also patch
llvm.dbg.declare calls and replace debug info descriptors to mark
that we've replaced alloca with a value that stores an address
of the user variable, not the user variable itself.

See PR11818 for more context.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169984 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Alexey Samsonov
2012-12-12 14:31:53 +00:00
parent cd5eb17be6
commit 1afbb51796
5 changed files with 105 additions and 0 deletions

View File

@ -928,3 +928,38 @@ DbgDeclareInst *llvm::FindAllocaDbgDeclare(Value *V) {
return 0;
}
bool llvm::replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
DIBuilder &Builder) {
DbgDeclareInst *DDI = FindAllocaDbgDeclare(AI);
if (!DDI)
return false;
DIVariable DIVar(DDI->getVariable());
if (!DIVar.Verify())
return false;
// Create a copy of the original DIDescriptor for user variable, appending
// "deref" operation to a list of address elements, as new llvm.dbg.declare
// will take a value storing address of the memory for variable, not
// alloca itself.
Type *Int64Ty = Type::getInt64Ty(AI->getContext());
SmallVector<Value*, 4> NewDIVarAddress;
if (DIVar.hasComplexAddress()) {
for (unsigned i = 0, n = DIVar.getNumAddrElements(); i < n; ++i) {
NewDIVarAddress.push_back(
ConstantInt::get(Int64Ty, DIVar.getAddrElement(i)));
}
}
NewDIVarAddress.push_back(ConstantInt::get(Int64Ty, DIBuilder::OpDeref));
DIVariable NewDIVar = Builder.createComplexVariable(
DIVar.getTag(), DIVar.getContext(), DIVar.getName(),
DIVar.getFile(), DIVar.getLineNumber(), DIVar.getType(),
NewDIVarAddress, DIVar.getArgNumber());
// Insert llvm.dbg.declare in the same basic block as the original alloca,
// and remove old llvm.dbg.declare.
BasicBlock *BB = AI->getParent();
Builder.insertDeclare(NewAllocaAddress, NewDIVar, BB);
DDI->eraseFromParent();
return true;
}