Ignore:
Timestamp:
Jun 1, 2017, 1:00:08 PM (2 years ago)
Author:
nmedfort
Message:

Bug fix for memory check and issues found parsing internal 'files'. Added backtrace option from execinfo.h

File:
1 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/IR_Gen/CBuilder.cpp

    r5486 r5489  
    2424#include <sanitizer/asan_interface.h>
    2525#endif
    26 #ifdef HAVE_LIBUNWIND
     26#ifdef HAS_LIBUNWIND
    2727#define UNW_LOCAL_ONLY
    2828#include <libunwind.h>
     29using unw_word_t = unw_word_t;
     30#elif HAS_EXECINFO
     31#include <execinfo.h>
     32#include <boost/integer.hpp>
     33using unw_word_t = boost::uint_t<sizeof(void *) * CHAR_BIT>::exact;
    2934#else
    3035using unw_word_t = uint64_t;
     
    3237
    3338using namespace llvm;
    34 
    35 void __report_failure(const char * msg, const unw_word_t * trace) {
    36     raw_fd_ostream out(STDERR_FILENO, false);
    37     #ifdef HAVE_LIBUNWIND
    38     if (trace) {
    39         out.changeColor(raw_fd_ostream::WHITE, true);
    40         out << "Compilation Stacktrace:\n";
    41         out.resetColor();
    42         while (*trace) {
    43             const auto pc = *trace++;
    44             out << format_hex(pc, 16) << "   ";
    45             const auto len = codegen::ProgramName.length() + 32;
    46             char cmd[len];
    47             snprintf(cmd, len,"addr2line -fpCe %s %p", codegen::ProgramName.data(), reinterpret_cast<void *>(pc));
    48             FILE * f = popen(cmd, "r");
    49             if (f) {
    50                 char buffer[1024] = {0};
    51                 while(fgets(buffer, sizeof(buffer), f)) {
    52                     out << buffer;
    53                 }
    54                 pclose(f);
    55             }
    56             ++trace;
    57         }
    58     }
    59     #endif
    60     out.changeColor(raw_fd_ostream::WHITE, true);
    61     out << "Assertion `" << msg << "' failed.\n";
    62     out.resetColor();
    63     out.flush();
    64 }
    6539
    6640Value * CBuilder::CreateOpenCall(Value * filename, Value * oflag, Value * mode) {
     
    213187        IRBuilder<> builder(entry);
    214188        std::vector<Value *> args;
    215         args.push_back(getInt32(2));    // fd 2 (stderr)
     189        args.push_back(getInt32(STDERR_FILENO));
    216190        args.push_back(GetString(out.c_str()));
    217191        Value * const name = &*(arg++);
     
    247221        IRBuilder<> builder(entry);
    248222        std::vector<Value *> args;
    249         args.push_back(getInt32(2));    // fd 2 (stderr)
    250         args.push_back(GetString(out.c_str()));
     223        args.push_back(getInt32(STDERR_FILENO));
     224        args.push_back(GetString(out));
    251225        Value * const msg = &*(arg++);
    252226        msg->setName("msg");
     
    667641}
    668642
     643void __report_failure(const char * msg, const unw_word_t * trace, const uint32_t n) {
     644    raw_fd_ostream out(STDERR_FILENO, false);
     645    #if defined(HAS_LIBUNWIND) || defined(HAS_EXECINFO)
     646    if (trace) {
     647        SmallVector<char, 4096> tmp;
     648        raw_svector_ostream trace_string(tmp);
     649        for (uint32_t i = 0; i < n; ++i) {
     650            const auto pc = trace[i];
     651            trace_string << format_hex(pc, 16) << "   ";
     652            const auto len = codegen::ProgramName.length() + 32;
     653            char cmd[len];
     654            snprintf(cmd, len,"addr2line -fpCe %s %p", codegen::ProgramName.data(), reinterpret_cast<void *>(pc));
     655            FILE * f = popen(cmd, "r");
     656            if (f) {
     657                char buffer[1024] = {0};
     658                while(fgets(buffer, sizeof(buffer), f)) {
     659                    trace_string << buffer;
     660                }
     661                pclose(f);
     662            }
     663        }
     664        out.changeColor(raw_fd_ostream::WHITE, true);
     665        out << "Compilation Stacktrace:\n";
     666        out.resetColor();
     667        out << trace_string.str();
     668    }
     669    #endif
     670    out.changeColor(raw_fd_ostream::WHITE, true);
     671    out << "Assertion `" << msg << "' failed.\n";
     672    out.resetColor();
     673    out.flush();
     674}
     675
    669676void CBuilder::CreateAssert(Value * assertion, StringRef failureMessage) {
    670677    if (LLVM_UNLIKELY(codegen::EnableAsserts)) {
     
    677684            IntegerType * const unwWordTy = TypeBuilder<unw_word_t, false>::get(getContext());
    678685            PointerType * const unwWordPtrTy = unwWordTy->getPointerTo();
    679             FunctionType * fty = FunctionType::get(getVoidTy(), { int1Ty, int8PtrTy, unwWordPtrTy }, false);
     686            FunctionType * fty = FunctionType::get(getVoidTy(), { int1Ty, int8PtrTy, unwWordPtrTy, getInt32Ty() }, false);
    680687            function = Function::Create(fty, Function::PrivateLinkage, "assert", m);
    681688            function->setDoesNotThrow();
     
    691698            arg->setName("trace");
    692699            Value * trace = &*arg++;
     700            arg->setName("depth");
     701            Value * depth = &*arg++;
    693702            SetInsertPoint(entry);
    694703            IRBuilder<>::CreateCondBr(assertion, success, failure);
    695704            IRBuilder<>::SetInsertPoint(failure);
    696             IRBuilder<>::CreateCall(LinkFunction("__report_failure", __report_failure), { msg, trace });
     705            IRBuilder<>::CreateCall(LinkFunction("__report_failure", __report_failure), { msg, trace, depth });
    697706            CreateExit(-1);
    698707            IRBuilder<>::CreateBr(success); // necessary to satisfy the LLVM verifier. this is never executed.
     
    704713            assertion = CreateICmpNE(assertion, Constant::getNullValue(assertion->getType()));
    705714        }
    706         IntegerType * const unwWordTy = TypeBuilder<unw_word_t, false>::get(getContext());
    707         PointerType * const unwWordPtrTy = unwWordTy->getPointerTo();
    708         #ifdef HAVE_LIBUNWIND
    709         std::vector<unw_word_t> stack;
     715        SmallVector<unw_word_t, 64> stack;
     716        #ifdef HAS_LIBUNWIND
    710717        unw_context_t context;
    711         unw_cursor_t cursor;
    712718        // Initialize cursor to current frame for local unwinding.
    713719        unw_getcontext(&context);
     720        unw_cursor_t cursor;
    714721        unw_init_local(&cursor, &context);
    715722        // Unwind frames one by one, going up the frame stack.
    716         stack.reserve(64);
    717723        while (unw_step(&cursor) > 0) {
    718724            unw_word_t pc;
    719725            unw_get_reg(&cursor, UNW_REG_IP, &pc);
    720             stack.push_back(pc);
    721726            if (pc == 0) {
    722727                break;
    723728            }
    724         }
    725         GlobalVariable * global = nullptr;
     729            stack.push_back(pc);
     730        }
     731        #elif defined(HAS_EXECINFO)
     732        for (;;) {
     733            const auto n = backtrace(reinterpret_cast<void **>(stack.data()), stack.capacity());
     734            if (LLVM_LIKELY(n < (int)stack.capacity())) {
     735                stack.set_size(n);
     736                break;
     737            }
     738            stack.reserve(n * 2);
     739        }
     740        #endif
     741        IntegerType * const stackTy = TypeBuilder<unw_word_t, false>::get(getContext());
     742        PointerType * const stackPtrTy = stackTy->getPointerTo();
     743        GlobalVariable * ip_trace = nullptr;
    726744        const auto n = stack.size();
    727         IntegerType * const unwTy = TypeBuilder<unw_word_t, false>::get(getContext());
    728745        for (GlobalVariable & gv : m->getGlobalList()) {
    729746            Type * const ty = gv.getValueType();
    730             if (ty->isArrayTy() && ty->getArrayElementType() == unwTy && ty->getArrayNumElements() == n) {
     747            if (ty->isArrayTy() && ty->getArrayElementType() == stackTy && ty->getArrayNumElements() == n) {
    731748                const ConstantDataArray * const array = cast<ConstantDataArray>(gv.getOperand(0));
    732749                bool found = true;
     
    738755                }
    739756                if (LLVM_UNLIKELY(found)) {
    740                     global = &gv;
     757                    ip_trace = &gv;
    741758                    break;
    742759                }
    743760            }
    744761        }
    745         if (LLVM_LIKELY(global == nullptr)) {
     762        if (LLVM_LIKELY(ip_trace == nullptr)) {
    746763            Constant * const initializer = ConstantDataArray::get(getContext(), stack);
    747             global = new GlobalVariable(*m, initializer->getType(), true, GlobalVariable::InternalLinkage, initializer);
    748         }
    749         Value * const trace = CreatePointerCast(global, unwWordPtrTy);
    750         #else
    751         Constant * const trace = ConstantPointerNull::get(unwWordPtrTy);
    752         #endif
    753         IRBuilder<>::CreateCall(function, {assertion, GetString(failureMessage), trace});
     764            ip_trace = new GlobalVariable(*m, initializer->getType(), true, GlobalVariable::InternalLinkage, initializer);
     765        }
     766        Value * const trace = CreatePointerCast(ip_trace, stackPtrTy);
     767        IRBuilder<>::CreateCall(function, {assertion, GetString(failureMessage), trace, getInt32(n)});
    754768    }
    755769}
     
    847861#define CHECK_ADDRESS(Ptr) \
    848862    if (codegen::EnableAsserts) { \
    849         Module * const m = getModule(); \
    850         PointerType * voidPtrTy = getVoidPtrTy(); \
    851         IntegerType * sizeTy = getSizeTy(); \
    852         Function * isPoisoned = m->getFunction("__asan_region_is_poisoned"); \
    853         if (isPoisoned == nullptr) { \
    854             auto isPoisonedTy = FunctionType::get(voidPtrTy, {voidPtrTy, sizeTy}, false); \
    855             isPoisoned = Function::Create(isPoisonedTy, Function::ExternalLinkage, "__asan_region_is_poisoned", m); \
    856         } \
    857         Value * const addr = CreatePointerCast(Ptr, voidPtrTy); \
    858         Constant * const size = ConstantInt::get(sizeTy, Ptr->getType()->getPointerElementType()->getPrimitiveSizeInBits()); \
     863        Function * const isPoisoned = LinkFunction("__asan_region_is_poisoned", __asan_region_is_poisoned); \
     864        auto arg = isPoisoned->arg_begin(); \
     865        Value * const addr = CreatePointerCast(Ptr, arg->getType()); \
     866        Constant * const size = ConstantInt::get((++arg)->getType(), Ptr->getType()->getPointerElementType()->getPrimitiveSizeInBits() / 8); \
    859867        Value * check = CreateCall(isPoisoned, { addr, size }); \
    860         check = CreateICmpEQ(check, ConstantPointerNull::get(voidPtrTy)); \
     868        check = CreateICmpEQ(check, ConstantPointerNull::get(cast<PointerType>(isPoisoned->getReturnType()))); \
    861869        CreateAssert(check, "Valid memory address"); \
    862870    }
     
    891899#endif
    892900
    893 CBuilder::CBuilder(LLVMContext & C, const unsigned GeneralRegisterWidthInBits)
     901CBuilder::CBuilder(LLVMContext & C)
    894902: IRBuilder<>(C)
    895903, mCacheLineAlignment(64)
    896 , mSizeType(getIntNTy(GeneralRegisterWidthInBits))
     904, mSizeType(TypeBuilder<size_t, false>::get(C))
    897905, mFILEtype(nullptr)
    898906, mDriver(nullptr) {
Note: See TracChangeset for help on using the changeset viewer.