summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2019-06-17 23:39:41 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2019-06-17 23:39:41 +0000
commitfb9ce100d19be130d004d03088ccd4af295f3435 (patch)
tree83f492dda41a0acb0aeabd5211c238750c530ddc /llvm/lib
parentc3b6d777553d59a032680493b2fbb55d4d41a32a (diff)
downloadbcm5719-llvm-fb9ce100d19be130d004d03088ccd4af295f3435.tar.gz
bcm5719-llvm-fb9ce100d19be130d004d03088ccd4af295f3435.zip
hwasan: Add a tag_offset DWARF attribute to instrumented stack variables.
The goal is to improve hwasan's error reporting for stack use-after-return by recording enough information to allow the specific variable that was accessed to be identified based on the pointer's tag. Currently we record the PC and lower bits of SP for each stack frame we create (which will eventually be enough to derive the base tag used by the stack frame) but that's not enough to determine the specific tag for each variable, which is the stack frame's base tag XOR a value (the "tag offset") that is unique for each variable in a function. In IR, the tag offset is most naturally represented as part of a location expression on the llvm.dbg.declare instruction. However, the presence of the tag offset in the variable's actual location expression is likely to confuse debuggers which won't know about tag offsets, and moreover the tag offset is not required for a debugger to determine the location of the variable on the stack, so at the DWARF level it is represented as an attribute so that it will be ignored by debuggers that don't know about it. Differential Revision: https://reviews.llvm.org/D63119 llvm-svn: 363635
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/BinaryFormat/Dwarf.cpp3
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp3
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp3
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h2
-rw-r--r--llvm/lib/IR/DebugInfoMetadata.cpp6
-rw-r--r--llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp23
6 files changed, 36 insertions, 4 deletions
diff --git a/llvm/lib/BinaryFormat/Dwarf.cpp b/llvm/lib/BinaryFormat/Dwarf.cpp
index b6d4d5b0730..eb6bd33ce58 100644
--- a/llvm/lib/BinaryFormat/Dwarf.cpp
+++ b/llvm/lib/BinaryFormat/Dwarf.cpp
@@ -147,6 +147,8 @@ StringRef llvm::dwarf::OperationEncodingString(unsigned Encoding) {
return "DW_OP_LLVM_convert";
case DW_OP_LLVM_fragment:
return "DW_OP_LLVM_fragment";
+ case DW_OP_LLVM_tag_offset:
+ return "DW_OP_LLVM_tag_offset";
}
}
@@ -157,6 +159,7 @@ unsigned llvm::dwarf::getOperationEncoding(StringRef OperationEncodingString) {
#include "llvm/BinaryFormat/Dwarf.def"
.Case("DW_OP_LLVM_convert", DW_OP_LLVM_convert)
.Case("DW_OP_LLVM_fragment", DW_OP_LLVM_fragment)
+ .Case("DW_OP_LLVM_tag_offset", DW_OP_LLVM_tag_offset)
.Default(0);
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 37e963ed63b..f0ceba50f14 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -683,6 +683,9 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
NVPTXAddressSpace ? *NVPTXAddressSpace : NVPTX_ADDR_local_space);
}
addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
+ if (DwarfExpr.TagOffset)
+ addUInt(*VariableDie, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1,
+ *DwarfExpr.TagOffset);
return VariableDie;
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index c7c28320202..d483a30e499 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -438,6 +438,9 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
emitOp(dwarf::DW_OP_deref_size);
emitData1(Op->getArg(0));
break;
+ case dwarf::DW_OP_LLVM_tag_offset:
+ TagOffset = Op->getArg(0);
+ break;
default:
llvm_unreachable("unhandled opcode found in expression");
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
index 6985debe613..3a9347a3e0a 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
@@ -140,6 +140,8 @@ public:
return LocationKind == Implicit;
}
+ Optional<uint8_t> TagOffset;
+
protected:
/// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed
/// to represent a subregister.
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index fa8438ea900..76d9ce3332c 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -835,6 +835,7 @@ unsigned DIExpression::ExprOperand::getSize() const {
case dwarf::DW_OP_constu:
case dwarf::DW_OP_deref_size:
case dwarf::DW_OP_plus_uconst:
+ case dwarf::DW_OP_LLVM_tag_offset:
return 2;
default:
return 1;
@@ -876,6 +877,7 @@ bool DIExpression::isValid() const {
break;
}
case dwarf::DW_OP_LLVM_convert:
+ case dwarf::DW_OP_LLVM_tag_offset:
case dwarf::DW_OP_constu:
case dwarf::DW_OP_plus_uconst:
case dwarf::DW_OP_plus:
@@ -905,7 +907,9 @@ bool DIExpression::isImplicit() const {
unsigned N = getNumElements();
if (isValid() && N > 0) {
switch (getElement(N-1)) {
- case dwarf::DW_OP_stack_value: return true;
+ case dwarf::DW_OP_stack_value:
+ case dwarf::DW_OP_LLVM_tag_offset:
+ return true;
case dwarf::DW_OP_LLVM_fragment:
return N > 1 && getElement(N-2) == dwarf::DW_OP_stack_value;
default: break;
diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index abbe5801de1..6d70e3bcbf0 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -21,6 +21,7 @@
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
@@ -205,8 +206,10 @@ public:
bool tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag);
Value *tagPointer(IRBuilder<> &IRB, Type *Ty, Value *PtrLong, Value *Tag);
Value *untagPointer(IRBuilder<> &IRB, Value *PtrLong);
- bool instrumentStack(SmallVectorImpl<AllocaInst *> &Allocas,
- SmallVectorImpl<Instruction *> &RetVec, Value *StackTag);
+ bool instrumentStack(
+ SmallVectorImpl<AllocaInst *> &Allocas,
+ DenseMap<AllocaInst *, std::vector<DbgDeclareInst *>> &AllocaDeclareMap,
+ SmallVectorImpl<Instruction *> &RetVec, Value *StackTag);
bool instrumentLandingPads(SmallVectorImpl<Instruction *> &RetVec);
Value *getNextTagWithCall(IRBuilder<> &IRB);
Value *getStackBaseTag(IRBuilder<> &IRB);
@@ -984,6 +987,7 @@ bool HWAddressSanitizer::instrumentLandingPads(
bool HWAddressSanitizer::instrumentStack(
SmallVectorImpl<AllocaInst *> &Allocas,
+ DenseMap<AllocaInst *, std::vector<DbgDeclareInst *>> &AllocaDeclareMap,
SmallVectorImpl<Instruction *> &RetVec, Value *StackTag) {
// Ideally, we want to calculate tagged stack base pointer, and rewrite all
// alloca addresses using that. Unfortunately, offsets are not known yet
@@ -1008,6 +1012,13 @@ bool HWAddressSanitizer::instrumentStack(
U.set(Replacement);
}
+ for (auto *DDI : AllocaDeclareMap.lookup(AI)) {
+ DIExpression *OldExpr = DDI->getExpression();
+ DIExpression *NewExpr = DIExpression::append(
+ OldExpr, {dwarf::DW_OP_LLVM_tag_offset, RetagMask(N)});
+ DDI->setArgOperand(2, MetadataAsValue::get(*C, NewExpr));
+ }
+
tagAlloca(IRB, AI, Tag);
for (auto RI : RetVec) {
@@ -1051,6 +1062,7 @@ bool HWAddressSanitizer::sanitizeFunction(Function &F) {
SmallVector<AllocaInst*, 8> AllocasToInstrument;
SmallVector<Instruction*, 8> RetVec;
SmallVector<Instruction*, 8> LandingPadVec;
+ DenseMap<AllocaInst *, std::vector<DbgDeclareInst *>> AllocaDeclareMap;
for (auto &BB : F) {
for (auto &Inst : BB) {
if (ClInstrumentStack)
@@ -1069,6 +1081,10 @@ bool HWAddressSanitizer::sanitizeFunction(Function &F) {
isa<CleanupReturnInst>(Inst))
RetVec.push_back(&Inst);
+ if (auto *DDI = dyn_cast<DbgDeclareInst>(&Inst))
+ if (auto *Alloca = dyn_cast_or_null<AllocaInst>(DDI->getAddress()))
+ AllocaDeclareMap[Alloca].push_back(DDI);
+
if (ClInstrumentLandingPads && isa<LandingPadInst>(Inst))
LandingPadVec.push_back(&Inst);
@@ -1107,7 +1123,8 @@ bool HWAddressSanitizer::sanitizeFunction(Function &F) {
if (!AllocasToInstrument.empty()) {
Value *StackTag =
ClGenerateTagsWithCalls ? nullptr : getStackBaseTag(EntryIRB);
- Changed |= instrumentStack(AllocasToInstrument, RetVec, StackTag);
+ Changed |= instrumentStack(AllocasToInstrument, AllocaDeclareMap, RetVec,
+ StackTag);
}
// If we split the entry block, move any allocas that were originally in the
OpenPOWER on IntegriCloud