Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Standalone View
llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
Show All 36 Lines | ||||||||||
#include "llvm/IR/InstIterator.h" | #include "llvm/IR/InstIterator.h" | |||||||||
#include "llvm/IR/Instruction.h" | #include "llvm/IR/Instruction.h" | |||||||||
#include "llvm/IR/Instructions.h" | #include "llvm/IR/Instructions.h" | |||||||||
#include "llvm/IR/IntrinsicInst.h" | #include "llvm/IR/IntrinsicInst.h" | |||||||||
#include "llvm/IR/Intrinsics.h" | #include "llvm/IR/Intrinsics.h" | |||||||||
#include "llvm/IR/LLVMContext.h" | #include "llvm/IR/LLVMContext.h" | |||||||||
#include "llvm/IR/MDBuilder.h" | #include "llvm/IR/MDBuilder.h" | |||||||||
#include "llvm/IR/Module.h" | #include "llvm/IR/Module.h" | |||||||||
#include "llvm/IR/NoFolder.h" | ||||||||||
#include "llvm/IR/Type.h" | #include "llvm/IR/Type.h" | |||||||||
#include "llvm/IR/Value.h" | #include "llvm/IR/Value.h" | |||||||||
#include "llvm/Support/Casting.h" | #include "llvm/Support/Casting.h" | |||||||||
#include "llvm/Support/CommandLine.h" | #include "llvm/Support/CommandLine.h" | |||||||||
#include "llvm/Support/Debug.h" | #include "llvm/Support/Debug.h" | |||||||||
#include "llvm/Support/raw_ostream.h" | #include "llvm/Support/raw_ostream.h" | |||||||||
#include "llvm/Transforms/Instrumentation/AddressSanitizerCommon.h" | #include "llvm/Transforms/Instrumentation/AddressSanitizerCommon.h" | |||||||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h" | #include "llvm/Transforms/Utils/BasicBlockUtils.h" | |||||||||
▲ Show 20 Lines • Show All 521 Lines • ▼ Show 20 Lines | void HWAddressSanitizer::initializeModule() { | |||||||||
// short granules, global or personality function instrumentation. On other | // short granules, global or personality function instrumentation. On other | |||||||||
// platforms we currently require using the latest version of the runtime. | // platforms we currently require using the latest version of the runtime. | |||||||||
bool NewRuntime = | bool NewRuntime = | |||||||||
!TargetTriple.isAndroid() || !TargetTriple.isAndroidVersionLT(30); | !TargetTriple.isAndroid() || !TargetTriple.isAndroidVersionLT(30); | |||||||||
UseShortGranules = | UseShortGranules = | |||||||||
ClUseShortGranules.getNumOccurrences() ? ClUseShortGranules : NewRuntime; | ClUseShortGranules.getNumOccurrences() ? ClUseShortGranules : NewRuntime; | |||||||||
OutlinedChecks = | OutlinedChecks = | |||||||||
TargetTriple.isAArch64() && TargetTriple.isOSBinFormatELF() && | (TargetTriple.isAArch64() || TargetTriple.isRISCV64()) && | |||||||||
TargetTriple.isOSBinFormatELF() && | ||||||||||
(ClInlineAllChecks.getNumOccurrences() ? !ClInlineAllChecks : !Recover); | (ClInlineAllChecks.getNumOccurrences() ? !ClInlineAllChecks : !Recover); | |||||||||
vitalybuka: clang-format please | ||||||||||
It's already formatted smd: It's already formatted | ||||||||||
if (ClMatchAllTag.getNumOccurrences()) { | if (ClMatchAllTag.getNumOccurrences()) { | |||||||||
if (ClMatchAllTag != -1) { | if (ClMatchAllTag != -1) { | |||||||||
HasMatchAllTag = true; | HasMatchAllTag = true; | |||||||||
MatchAllTag = ClMatchAllTag & 0xFF; | MatchAllTag = ClMatchAllTag & 0xFF; | |||||||||
} | } | |||||||||
} else if (CompileKernel) { | } else if (CompileKernel) { | |||||||||
HasMatchAllTag = true; | HasMatchAllTag = true; | |||||||||
MatchAllTag = 0xFF; | MatchAllTag = 0xFF; | |||||||||
} | } | |||||||||
// If we don't have personality function support, fall back to landing pads. | // If we don't have personality function support, fall back to landing pads. | |||||||||
InstrumentLandingPads = ClInstrumentLandingPads.getNumOccurrences() | InstrumentLandingPads = ClInstrumentLandingPads.getNumOccurrences() | |||||||||
? ClInstrumentLandingPads | ? ClInstrumentLandingPads | |||||||||
: !NewRuntime; | : !NewRuntime; | |||||||||
if (!CompileKernel) { | if (!CompileKernel) { | |||||||||
createHwasanCtorComdat(); | createHwasanCtorComdat(); | |||||||||
bool InstrumentGlobals = | bool InstrumentGlobals = | |||||||||
ClGlobals.getNumOccurrences() ? ClGlobals : NewRuntime; | ClGlobals.getNumOccurrences() ? ClGlobals : NewRuntime; | |||||||||
Not Done ReplyInline Actions
vitalybuka: | ||||||||||
Fixed, thanks smd: Fixed, thanks | ||||||||||
if (InstrumentGlobals && !UsePageAliases) | // Currently we do not instrumentation of globals for RISCV | |||||||||
// The reason is that the existing memory models does not allow us | ||||||||||
// to use tagged pointers in la/lla expressions | ||||||||||
if (InstrumentGlobals && !UsePageAliases && !TargetTriple.isRISCV64()) | ||||||||||
instrumentGlobals(); | instrumentGlobals(); | |||||||||
bool InstrumentPersonalityFunctions = | bool InstrumentPersonalityFunctions = | |||||||||
ClInstrumentPersonalityFunctions.getNumOccurrences() | ClInstrumentPersonalityFunctions.getNumOccurrences() | |||||||||
? ClInstrumentPersonalityFunctions | ? ClInstrumentPersonalityFunctions | |||||||||
: NewRuntime; | : NewRuntime; | |||||||||
if (InstrumentPersonalityFunctions) | if (InstrumentPersonalityFunctions) | |||||||||
instrumentPersonalityFunctions(); | instrumentPersonalityFunctions(); | |||||||||
▲ Show 20 Lines • Show All 172 Lines • ▼ Show 20 Lines | ||||||||||
static size_t TypeSizeToSizeIndex(uint32_t TypeSize) { | static size_t TypeSizeToSizeIndex(uint32_t TypeSize) { | |||||||||
size_t Res = countTrailingZeros(TypeSize / 8); | size_t Res = countTrailingZeros(TypeSize / 8); | |||||||||
assert(Res < kNumberOfAccessSizes); | assert(Res < kNumberOfAccessSizes); | |||||||||
return Res; | return Res; | |||||||||
} | } | |||||||||
void HWAddressSanitizer::untagPointerOperand(Instruction *I, Value *Addr) { | void HWAddressSanitizer::untagPointerOperand(Instruction *I, Value *Addr) { | |||||||||
if (TargetTriple.isAArch64() || TargetTriple.getArch() == Triple::x86_64) | if (TargetTriple.isAArch64() || TargetTriple.getArch() == Triple::x86_64 || | |||||||||
TargetTriple.isRISCV64()) | ||||||||||
return; | return; | |||||||||
IRBuilder<> IRB(I); | IRBuilder<> IRB(I); | |||||||||
Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); | Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); | |||||||||
Value *UntaggedPtr = | Value *UntaggedPtr = | |||||||||
IRB.CreateIntToPtr(untagPointer(IRB, AddrLong), Addr->getType()); | IRB.CreateIntToPtr(untagPointer(IRB, AddrLong), Addr->getType()); | |||||||||
I->setOperand(getPointerOperandIndex(I), UntaggedPtr); | I->setOperand(getPointerOperandIndex(I), UntaggedPtr); | |||||||||
} | } | |||||||||
Show All 20 Lines | ||||||||||
void HWAddressSanitizer::instrumentMemAccessOutline(Value *Ptr, bool IsWrite, | void HWAddressSanitizer::instrumentMemAccessOutline(Value *Ptr, bool IsWrite, | |||||||||
unsigned AccessSizeIndex, | unsigned AccessSizeIndex, | |||||||||
Instruction *InsertBefore) { | Instruction *InsertBefore) { | |||||||||
assert(!UsePageAliases); | assert(!UsePageAliases); | |||||||||
const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex); | const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex); | |||||||||
IRBuilder<> IRB(InsertBefore); | IRBuilder<> IRB(InsertBefore); | |||||||||
Module *M = IRB.GetInsertBlock()->getParent()->getParent(); | Module *M = IRB.GetInsertBlock()->getParent()->getParent(); | |||||||||
Ptr = IRB.CreateBitCast(Ptr, Int8PtrTy); | Ptr = IRB.CreateBitCast(Ptr, Int8PtrTy); | |||||||||
// In case of RISC-V always use shortgranules | ||||||||||
IRB.CreateCall(Intrinsic::getDeclaration( | IRB.CreateCall(Intrinsic::getDeclaration( | |||||||||
Not Done ReplyInline ActionsCode should respect ClUseShortGranules, even if it's not useful mode. vitalybuka: Code should respect ClUseShortGranules, even if it's not useful mode.
Otherwise… | ||||||||||
@vitalybuka fatal error: error in backend: Cannot select: intrinsic %llvm.hwasan.check.memaccess which is sort of ok, I guess. But maybe an explicit check like (isRISCV64() && !UseShortGranules) with an error message would be a better idea? smd: @vitalybuka
Could you please clarify:
If I get you right, you're suggesting allowing users to… | ||||||||||
Not Done ReplyInline Actions
I assume hwasan.check.memaccess is just not implemented yet? in this case these lines not need to change vitalybuka: > @vitalybuka
> Could you please clarify:
> If I get you right, you're suggesting allowing… | ||||||||||
Indeed it's not implemented, but to be honest I didn't think it should be implemented. I got an impression that short_granules(v2) is a preferred way of checking tags, while v1 function is kept for older targets. smd: >I assume hwasan.check.memaccess is just not implemented yet?
Indeed it's not implemented, but… | ||||||||||
M, UseShortGranules | M, UseShortGranules || TargetTriple.isRISCV64() | |||||||||
? Intrinsic::hwasan_check_memaccess_shortgranules | ? Intrinsic::hwasan_check_memaccess_shortgranules | |||||||||
: Intrinsic::hwasan_check_memaccess), | : Intrinsic::hwasan_check_memaccess), | |||||||||
{ShadowBase, Ptr, ConstantInt::get(Int32Ty, AccessInfo)}); | {ShadowBase, Ptr, ConstantInt::get(Int32Ty, AccessInfo)}); | |||||||||
} | } | |||||||||
void HWAddressSanitizer::instrumentMemAccessInline(Value *Ptr, bool IsWrite, | void HWAddressSanitizer::instrumentMemAccessInline(Value *Ptr, bool IsWrite, | |||||||||
unsigned AccessSizeIndex, | unsigned AccessSizeIndex, | |||||||||
Instruction *InsertBefore) { | Instruction *InsertBefore) { | |||||||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | void HWAddressSanitizer::instrumentMemAccessInline(Value *Ptr, bool IsWrite, | |||||||||
case Triple::aarch64_be: | case Triple::aarch64_be: | |||||||||
// The signal handler will find the data address in x0. | // The signal handler will find the data address in x0. | |||||||||
Asm = InlineAsm::get( | Asm = InlineAsm::get( | |||||||||
FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false), | FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false), | |||||||||
"brk #" + itostr(0x900 + (AccessInfo & HWASanAccessInfo::RuntimeMask)), | "brk #" + itostr(0x900 + (AccessInfo & HWASanAccessInfo::RuntimeMask)), | |||||||||
"{x0}", | "{x0}", | |||||||||
/*hasSideEffects=*/true); | /*hasSideEffects=*/true); | |||||||||
break; | break; | |||||||||
case Triple::riscv64: | ||||||||||
// The signal handler will find the data address in x10. | ||||||||||
Asm = InlineAsm::get( | ||||||||||
FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false), | ||||||||||
"ebreak\naddiw x0, x0, " + itostr(0x40 + AccessInfo), "{x10}", "{x11}", | ||||||||||
Not Done ReplyInline Actions/home/matt/src/llvm-project/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp:923:72: warning: implicit conversion turns string literal into bool: 'const char[6]' to 'bool' [-Wstring-conversion] "ebreak\naddiw x0, x0, " + itostr(0x40 + AccessInfo), "{x10}", "{x11}", arsenm: /home/matt/src/llvm-project/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp:923:72… | ||||||||||
For some reason this code works with g++, but indeed fails with clang++. I'll investigate this, thanks: g++ -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/tank/work/dev/share/nfs/ablue/hwasan_upstream/riscv_hwasan/build/llvm-project/lib/Transforms/Instrumentation -I/tank/work/dev/share/nfs/ablue/hwasan_upstream/riscv_hwasan/src/llvm-project/llvm/lib/Transforms/Instrumentation -I/tank/work/dev/share/nfs/ablue/hwasan_upstream/riscv_hwasan/build/llvm-project/include -I/tank/work/dev/share/nfs/ablue/hwasan_upstream/riscv_hwasan/src/llvm-project/llvm/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-uninitialized -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wdelete-non-virtual-dtor -Wsuggest-override -Wno-comment -Wno-misleading-indentation -g -fno-exceptions -fno-rtti -std=c++17 -o CMakeFiles/LLVMInstrumentation.dir/HWAddressSanitizer.cpp.o -c /tank/work/dev/share/nfs/ablue/hwasan_upstream/riscv_hwasan/src/llvm-project/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp -Wall -Werror smd@neptune:/tank/work/dev/share/nfs/ablue/hwasan_upstream/riscv_hwasan/build/llvm-project/lib/Transforms/Instrumentation$ clang++ -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/tank/work/dev/share/nfs/ablue/hwasan_upstream/riscv_hwasan/build/llvm-project/lib/Transforms/Instrumentation -I/tank/work/dev/share/nfs/ablue/hwasan_upstream/riscv_hwasan/src/llvm-project/llvm/lib/Transforms/Instrumentation -I/tank/work/dev/share/nfs/ablue/hwasan_upstream/riscv_hwasan/build/llvm-project/include -I/tank/work/dev/share/nfs/ablue/hwasan_upstream/riscv_hwasan/src/llvm-project/llvm/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-uninitialized -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wdelete-non-virtual-dtor -Wsuggest-override -Wno-comment -Wno-misleading-indentation -g -fno-exceptions -fno-rtti -std=c++17 -o CMakeFiles/LLVMInstrumentation.dir/HWAddressSanitizer.cpp.o -c /tank/work/dev/share/nfs/ablue/hwasan_upstream/riscv_hwasan/src/llvm-project/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp -Wall -Werror -Wstring-conversion /tank/work/dev/share/nfs/ablue/hwasan_upstream/riscv_hwasan/src/llvm-project/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp:923:72: error: implicit conversion turns string literal into bool: 'const char [6]' to 'bool' [-Werror,-Wstring-conversion] "ebreak\naddiw x0, x0, " + itostr(0x40 + AccessInfo), "{x10}", "{x11}", ^~~~~~~ 1 error generated. smd: For some reason this code works with g++, but indeed fails with clang++. I'll investigate this… | ||||||||||
/*hasSideEffects=*/true); | ||||||||||
break; | ||||||||||
default: | default: | |||||||||
report_fatal_error("unsupported architecture"); | report_fatal_error("unsupported architecture"); | |||||||||
} | } | |||||||||
IRB.CreateCall(Asm, PtrLong); | IRB.CreateCall(Asm, PtrLong); | |||||||||
if (Recover) | if (Recover) | |||||||||
cast<BranchInst>(CheckFailTerm)->setSuccessor(0, CheckTerm->getParent()); | cast<BranchInst>(CheckFailTerm)->setSuccessor(0, CheckTerm->getParent()); | |||||||||
} | } | |||||||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | bool HWAddressSanitizer::instrumentMemAccess(InterestingMemoryOperand &O) { | |||||||||
untagPointerOperand(O.getInsn(), Addr); | untagPointerOperand(O.getInsn(), Addr); | |||||||||
return true; | return true; | |||||||||
} | } | |||||||||
void HWAddressSanitizer::tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag, | void HWAddressSanitizer::tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag, | |||||||||
size_t Size) { | size_t Size) { | |||||||||
size_t AlignedSize = alignTo(Size, Mapping.getObjectAlignment()); | size_t AlignedSize = alignTo(Size, Mapping.getObjectAlignment()); | |||||||||
if (!UseShortGranules) | if (!UseShortGranules) | |||||||||
Not Done ReplyInline ActionsWhy not here? vitalybuka: Why not here? | ||||||||||
Size = AlignedSize; | Size = AlignedSize; | |||||||||
Value *JustTag = IRB.CreateTrunc(Tag, IRB.getInt8Ty()); | Value *JustTag = IRB.CreateTrunc(Tag, IRB.getInt8Ty()); | |||||||||
if (InstrumentWithCalls) { | if (InstrumentWithCalls) { | |||||||||
IRB.CreateCall(HwasanTagMemoryFunc, | IRB.CreateCall(HwasanTagMemoryFunc, | |||||||||
{IRB.CreatePointerCast(AI, Int8PtrTy), JustTag, | {IRB.CreatePointerCast(AI, Int8PtrTy), JustTag, | |||||||||
ConstantInt::get(IntptrTy, AlignedSize)}); | ConstantInt::get(IntptrTy, AlignedSize)}); | |||||||||
} else { | } else { | |||||||||
▲ Show 20 Lines • Show All 732 Lines • Show Last 20 Lines |
clang-format please