[llvm] r308387 - [asan] Copy arguments passed by value into explicit allocas for ASan
Vitaly Buka via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 7 00:46:26 PDT 2017
Disabled for -asan-force-dynamic-shadow with r310241
Matt, could you please investigate if we can make dynamic-shadow compatible?
On Fri, Aug 4, 2017 at 10:07 PM, Vitaly Buka <vitalybuka at google.com> wrote:
> I'll take a look
>
> On Fri, Aug 4, 2017 at 9:28 PM, Kuba Mracek <mracek at apple.com> wrote:
>
>> Hi Vitaly!
>>
>> This commit seems to be causing compile-time failures when using
>> "-asan-force-dynamic-shadow":
>>
>> $ cat a.c
>> typedef struct {
>> unsigned char buf[16];
>> } my_struct_t;
>>
>> void fn1(int p1, int p2, int p3, my_struct_t p4, my_struct_t p5)
>> {
>> }
>> $ ~/llvm-ninja-debug/bin/clang -fsanitize=address -mllvm
>> -asan-force-dynamic-shadow -c a.c
>> Instruction does not dominate all uses!
>> %28 = load i64, i64* @__asan_shadow_memory_dynamic_address
>> %21 = add i64 %20, %28
>> fatal error: error in backend: Broken function found, compilation aborted!
>>
>> It looks like when using dynamic shadow, we will emit the load of the
>> shadow offset into the beginning of the first BB,
>> but copyArgsPassedByValToAllocas also tries to emit instructions into
>> the beginning of the entry block. In the end, we just end up emitting in
>> the wrong order.
>>
>> Do you think you could take a look at it?
>>
>> Thanks!
>> Kuba
>>
>>
>> On 18 Jul 2017, at 15:28, Vitaly Buka via llvm-commits <
>> llvm-commits at lists.llvm.org> wrote:
>>
>> Author: vitalybuka
>> Date: Tue Jul 18 15:28:03 2017
>> New Revision: 308387
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=308387&view=rev
>> Log:
>> [asan] Copy arguments passed by value into explicit allocas for ASan
>>
>> Summary:
>> ASan determines the stack layout from alloca instructions. Since
>> arguments marked as "byval" do not have an explicit alloca instruction,
>> ASan
>> does not produce red zones for them. This commit produces an explicit
>> alloca
>> instruction and copies the byval argument into the allocated memory so
>> that red
>> zones are produced.
>>
>> Submitted on behalf of @morehouse (Matt Morehouse)
>>
>> Reviewers: eugenis, vitalybuka
>>
>> Reviewed By: eugenis
>>
>> Subscribers: hiraditya, llvm-commits
>>
>> Differential Revision: https://reviews.llvm.org/D34789
>>
>> Added:
>> llvm/trunk/test/Instrumentation/AddressSanitizer/stack-po
>> isoning-byval-args.ll
>> Modified:
>> llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
>>
>> Modified: llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transform
>> s/Instrumentation/AddressSanitizer.cpp?rev=308387&r1=308386&
>> r2=308387&view=diff
>> ============================================================
>> ==================
>> --- llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
>> (original)
>> +++ llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp Tue
>> Jul 18 15:28:03 2017
>> @@ -22,9 +22,11 @@
>> #include "llvm/ADT/Statistic.h"
>> #include "llvm/ADT/StringExtras.h"
>> #include "llvm/ADT/Triple.h"
>> +#include "llvm/ADT/Twine.h"
>> #include "llvm/Analysis/MemoryBuiltins.h"
>> #include "llvm/Analysis/TargetLibraryInfo.h"
>> #include "llvm/Analysis/ValueTracking.h"
>> +#include "llvm/IR/Argument.h"
>> #include "llvm/IR/CallSite.h"
>> #include "llvm/IR/DIBuilder.h"
>> #include "llvm/IR/DataLayout.h"
>> @@ -43,6 +45,7 @@
>> #include "llvm/Support/DataTypes.h"
>> #include "llvm/Support/Debug.h"
>> #include "llvm/Support/Endian.h"
>> +#include "llvm/Support/ScopedPrinter.h"
>> #include "llvm/Support/SwapByteOrder.h"
>> #include "llvm/Support/raw_ostream.h"
>> #include "llvm/Transforms/Instrumentation.h"
>> @@ -192,6 +195,11 @@ static cl::opt<uint32_t> ClMaxInlinePois
>> static cl::opt<bool> ClUseAfterReturn("asan-use-after-return",
>> cl::desc("Check
>> stack-use-after-return"),
>> cl::Hidden, cl::init(true));
>> +static cl::opt<bool> ClRedzoneByvalArgs("asan-redzone-byval-args",
>> + cl::desc("Create redzones for
>> byval "
>> + "arguments (extra copy
>> "
>> + "required)"),
>> cl::Hidden,
>> + cl::init(true));
>> static cl::opt<bool> ClUseAfterScope("asan-use-after-scope",
>> cl::desc("Check
>> stack-use-after-scope"),
>> cl::Hidden, cl::init(false));
>> @@ -747,6 +755,9 @@ struct FunctionStackPoisoner : public In
>>
>> bool runOnFunction() {
>> if (!ClStack) return false;
>> +
>> + if (ClRedzoneByvalArgs) copyArgsPassedByValToAllocas();
>> +
>> // Collect alloca, ret, lifetime instructions etc.
>> for (BasicBlock *BB : depth_first(&F.getEntryBlock())) visit(*BB);
>>
>> @@ -763,6 +774,11 @@ struct FunctionStackPoisoner : public In
>> return true;
>> }
>>
>> + // Arguments marked with the "byval" attribute are implicitly copied
>> without
>> + // using an alloca instruction. To produce redzones for those
>> arguments, we
>> + // copy them a second time into memory allocated with an alloca
>> instruction.
>> + void copyArgsPassedByValToAllocas();
>> +
>> // Finds all Alloca instructions and puts
>> // poisoned red zones around all of them.
>> // Then unpoison everything back before the function returns.
>> @@ -2528,6 +2544,28 @@ static int StackMallocSizeClass(uint64_t
>> llvm_unreachable("impossible LocalStackSize");
>> }
>>
>> +void FunctionStackPoisoner::copyArgsPassedByValToAllocas() {
>> + BasicBlock &FirstBB = *F.begin();
>> + IRBuilder<> IRB(&FirstBB, FirstBB.getFirstInsertionPt());
>> + const DataLayout &DL = F.getParent()->getDataLayout();
>> + for (Argument &Arg : F.args()) {
>> + if (Arg.hasByValAttr()) {
>> + Type *Ty = Arg.getType()->getPointerElementType();
>> + unsigned Align = Arg.getParamAlignment();
>> + if (Align == 0) Align = DL.getABITypeAlignment(Ty);
>> +
>> + const std::string &Name = Arg.hasName() ? Arg.getName().str() :
>> + "Arg" + llvm::to_string(Arg.getArgNo());
>> + AllocaInst *AI = IRB.CreateAlloca(Ty, nullptr, Twine(Name) +
>> ".byval");
>> + AI->setAlignment(Align);
>> + Arg.replaceAllUsesWith(AI);
>> +
>> + uint64_t AllocSize = DL.getTypeAllocSize(Ty);
>> + IRB.CreateMemCpy(AI, &Arg, AllocSize, Align);
>> + }
>> + }
>> +}
>> +
>> PHINode *FunctionStackPoisoner::createPHI(IRBuilder<> &IRB, Value *Cond,
>> Value *ValueIfTrue,
>> Instruction *ThenTerm,
>>
>> Added: llvm/trunk/test/Instrumentation/AddressSanitizer/stack-poiso
>> ning-byval-args.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrume
>> ntation/AddressSanitizer/stack-poisoning-byval-args.ll?
>> rev=308387&view=auto
>> ============================================================
>> ==================
>> --- llvm/trunk/test/Instrumentation/AddressSanitizer/stack-poisoning-byval-args.ll
>> (added)
>> +++ llvm/trunk/test/Instrumentation/AddressSanitizer/stack-poisoning-byval-args.ll
>> Tue Jul 18 15:28:03 2017
>> @@ -0,0 +1,48 @@
>> +; This check verifies that arguments passed by value get redzones.
>> +; RUN: opt < %s -asan -asan-realign-stack=32 -S | FileCheck %s
>> +
>> +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i1
>> 6:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v1
>> 28:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
>> +target triple = "x86_64-unknown-linux-gnu"
>> +
>> +%struct.A = type { [8 x i32] }
>> +
>> +declare i32 @bar(%struct.A*)
>> +
>> +; Test behavior for named argument with explicit alignment. The memcpy
>> and
>> +; alloca alignments should match the explicit alignment of 64.
>> +define void @foo(%struct.A* byval align 64 %a) sanitize_address {
>> +entry:
>> +; CHECK-LABEL: foo
>> +; CHECK: call i64 @__asan_stack_malloc
>> +; CHECK: alloca i8, i64 {{.*}} align 64
>> +; CHECK: [[copyPtr:%[^ \t]+]] = inttoptr i64 %{{[^ \t]+}} to %struct.A*
>> +; CHECK: [[copyBytePtr:%[^ \t]+]] = bitcast %struct.A* [[copyPtr]]
>> +; CHECK: [[aBytePtr:%[^ \t]+]] = bitcast %struct.A* %a
>> +; CHECK: call void @llvm.memcpy{{[^%]+}}[[copyByt
>> ePtr]]{{[^%]+}}[[aBytePtr]],{{[^,]+}}, i32 64
>> +; CHECK: call i32 @bar(%struct.A* [[copyPtr]])
>> +; CHECK: ret void
>> +
>> + %call = call i32 @bar(%struct.A* %a)
>> + ret void
>> +}
>> +
>> +; Test behavior for unnamed argument without explicit alignment. In
>> this case,
>> +; the first argument is referenced by the identifier %0 and the ABI
>> requires a
>> +; minimum alignment of 4 bytes since struct.A contains i32s which have
>> 4-byte
>> +; alignment. However, the alloca alignment will be 32 since that is the
>> value
>> +; passed via the -asan-realign-stack option, which is greater than 4.
>> +define void @baz(%struct.A* byval) sanitize_address {
>> +entry:
>> +; CHECK-LABEL: baz
>> +; CHECK: call i64 @__asan_stack_malloc
>> +; CHECK: alloca i8, i64 {{.*}} align 32
>> +; CHECK: [[copyPtr:%[^ \t]+]] = inttoptr i64 %{{[^ \t]+}} to %struct.A*
>> +; CHECK: [[copyBytePtr:%[^ \t]+]] = bitcast %struct.A* [[copyPtr]]
>> +; CHECK: [[aBytePtr:%[^ \t]+]] = bitcast %struct.A* %0
>> +; CHECK: call void @llvm.memcpy{{[^%]+}}[[copyByt
>> ePtr]]{{[^%]+}}[[aBytePtr]],{{[^,]+}}, i32 4
>> +; CHECK: call i32 @bar(%struct.A* [[copyPtr]])
>> +; CHECK: ret void
>> +
>> + %call = call i32 @bar(%struct.A* %0)
>> + ret void
>> +}
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170807/3f77cc09/attachment.html>
More information about the llvm-commits
mailing list