~ubuntu-branches/ubuntu/jaunty/clamav/jaunty-backports

« back to all changes in this revision

Viewing changes to libclamav/c++/bytecode2llvm.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-10-02 17:11:00 UTC
  • mfrom: (0.3.1 lucid-proposed)
  • Revision ID: james.westby@ubuntu.com-20101002171100-0erjjoucua6kw2pc
Tags: 0.96.3+dfsg-2ubuntu0.10.04.1~jaunty1
* Source backport for Jaunty
  - Change build-dep on libtdl-dev to libtdl7-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
196
196
    return CLI_SRS(a, b);//CLI_./..
197
197
}
198
198
 
 
199
static void rtlib_bzero(void *s, size_t n)
 
200
{
 
201
    memset(s, 0, n);
 
202
}
 
203
 
199
204
// Resolve integer libcalls, but nothing else.
200
205
static void* noUnknownFunctions(const std::string& name) {
201
206
    void *addr =
208
213
        .Case("__ashrdi3", (void*)(intptr_t)rtlib_sra_i64)
209
214
        .Case("__ashldi3", (void*)(intptr_t)rtlib_shl_i64)
210
215
        .Case("__lshrdi3", (void*)(intptr_t)rtlib_srl_i64)
 
216
        .Case("__bzero", (void*)(intptr_t)rtlib_bzero)
211
217
        .Case("memmove", (void*)(intptr_t)memmove)
212
218
        .Case("memcpy", (void*)(intptr_t)memcpy)
213
219
        .Case("memset", (void*)(intptr_t)memset)
808
814
            // Have an alloca -> some instruction uses its address otherwise
809
815
            // mem2reg would have converted it to an SSA register.
810
816
            // Enable stack protector for this function.
811
 
            F->addFnAttr(Attribute::StackProtect);
812
817
            F->addFnAttr(Attribute::StackProtectReq);
813
818
        }
 
819
        // always add stackprotect attribute (bb #2239), so we know this
 
820
        // function was verified. If there is no alloca it won't actually add
 
821
        // stack protector in emitted code so this won't slow down the app.
 
822
        F->addFnAttr(Attribute::StackProtect);
814
823
    }
815
824
 
816
825
    Value *GEPOperand(Value *V) {
899
908
                                           BytecodeID+"f"+Twine(j), M);
900
909
            Functions[j]->setDoesNotThrow();
901
910
            Functions[j]->setCallingConv(CallingConv::Fast);
 
911
#ifdef C_LINUX
 
912
            /* bb #2270, this should really be fixed either by LLVM or GCC.*/
 
913
            Functions[j]->addFnAttr(Attribute::constructStackAlignmentFromInt(16));
 
914
#endif
902
915
        }
903
916
        const Type *I32Ty = Type::getInt32Ty(Context);
904
917
        PM.add(createDeadCodeEliminationPass());
1634
1647
        0
1635
1648
    };
1636
1649
 
1637
 
    if ((ret = pthread_create(&thread, NULL, bytecode_watchdog, &w))) {
1638
 
        errs() << "Bytecode: failed to create new thread!";
1639
 
        errs() << cli_strerror(ret, buf, sizeof(buf));
1640
 
        errs() << "\n";
1641
 
        return CL_EBYTECODE;
 
1650
    if (ctx->bytecode_timeout) {
 
1651
        /* only spawn if timeout is set.
 
1652
         * we don't set timeout for selfcheck (see bb #2235) */
 
1653
        if ((ret = pthread_create(&thread, NULL, bytecode_watchdog, &w))) {
 
1654
            errs() << "Bytecode: failed to create new thread!";
 
1655
            errs() << cli_strerror(ret, buf, sizeof(buf));
 
1656
            errs() << "\n";
 
1657
            return CL_EBYTECODE;
 
1658
        }
1642
1659
    }
1643
1660
 
1644
1661
    ret = bytecode_execute((intptr_t)code, ctx);
1646
1663
    w.finished = 1;
1647
1664
    pthread_cond_signal(&w.cond);
1648
1665
    pthread_mutex_unlock(&w.mutex);
1649
 
    pthread_join(thread, NULL);
 
1666
    if (ctx->bytecode_timeout) {
 
1667
        pthread_join(thread, NULL);
 
1668
    }
1650
1669
 
1651
1670
    if (cli_debug_flag) {
1652
1671
        gettimeofday(&tv1, NULL);
1800
1819
 
1801
1820
        for (unsigned i=0;i<bcs->count;i++) {
1802
1821
            const struct cli_bc *bc = &bcs->all_bcs[i];
1803
 
            if (bc->state == bc_skip)
 
1822
            if (bc->state == bc_skip || bc->state == bc_interp)
1804
1823
                continue;
1805
1824
            LLVMCodegen Codegen(bc, M, &CF, bcs->engine->compiledFunctions, EE,
1806
1825
                                OurFPM, apiFuncs, apiMap);
1821
1840
        }
1822
1841
        delete [] apiFuncs;
1823
1842
    }
1824
 
    return -1;
 
1843
    return CL_SUCCESS;
1825
1844
  } catch (std::bad_alloc &badalloc) {
1826
1845
      errs() << MODULE << badalloc.what() << "\n";
1827
1846
      return CL_EMEM;
1872
1891
int cli_bytecode_init_jit(struct cli_all_bc *bcs, unsigned dconfmask)
1873
1892
{
1874
1893
    LLVMApiScopedLock scopedLock;
1875
 
    bcs->engine = NULL;
1876
 
    Triple triple(sys::getHostTriple());
1877
 
    if (cli_debug_flag)
1878
 
        errs() << "host triple is: " << sys::getHostTriple() << "\n";
1879
 
    enum Triple::ArchType arch = triple.getArch();
1880
 
    switch (arch) {
1881
 
        case Triple::arm:
1882
 
            if (!(dconfmask & BYTECODE_JIT_ARM)) {
1883
 
                if (cli_debug_flag)
1884
 
                    errs() << "host triple is: " << sys::getHostTriple() << "\n";
1885
 
                return 0;
1886
 
            }
1887
 
            break;
1888
 
        case Triple::ppc:
1889
 
        case Triple::ppc64:
1890
 
            if (!(dconfmask & BYTECODE_JIT_PPC)) {
1891
 
                if (cli_debug_flag)
1892
 
                    errs() << "JIT disabled for ppc\n";
1893
 
                return 0;
1894
 
            }
1895
 
            break;
1896
 
        case Triple::x86:
1897
 
        case Triple::x86_64:
1898
 
            if (!(dconfmask & BYTECODE_JIT_X86)) {
1899
 
                if (cli_debug_flag)
1900
 
                    errs() << "JIT disabled for x86\n";
1901
 
                return 0;
1902
 
            }
1903
 
            break;
1904
 
        default:
1905
 
            errs() << "Not supported architecture for " << triple.str() << "\n";
1906
 
            return CL_EBYTECODE;
1907
 
    }
1908
 
 
1909
 
    std::string cpu = sys::getHostCPUName();
1910
 
    if (cli_debug_flag)
1911
 
        errs() << "host cpu is: " << cpu << "\n";
1912
 
    if (!cpu.compare("i386") ||
1913
 
        !cpu.compare("i486")) {
1914
 
        bcs->engine = 0;
1915
 
        DEBUG(errs() << "i[34]86 detected, falling back to interpreter (JIT needs pentium or better\n");
1916
 
        /* i386 and i486 has to fallback to interpreter */
1917
 
        return 0;
1918
 
    }
1919
 
    std::string ErrMsg;
1920
 
    sys::MemoryBlock B = sys::Memory::AllocateRWX(4096, NULL, &ErrMsg);
1921
 
    if (B.base() == 0) {
1922
 
        errs() << MODULE << ErrMsg << "\n";
1923
 
#ifdef __linux__
1924
 
        errs() << MODULE << "SELinux is preventing 'execmem' access. Run 'setsebool -P clamd_use_jit on' to allow access\n";
1925
 
#endif
1926
 
        errs() << MODULE << "falling back to interpreter mode\n";
1927
 
        return 0;
1928
 
    } else {
1929
 
        sys::Memory::ReleaseRWX(B);
1930
 
    }
1931
 
 
1932
1894
    bcs->engine = new(std::nothrow) cli_bcengine;
1933
1895
    if (!bcs->engine)
1934
1896
        return CL_EMEM;
1937
1899
    return 0;
1938
1900
}
1939
1901
 
1940
 
int cli_bytecode_done_jit(struct cli_all_bc *bcs)
 
1902
int cli_bytecode_done_jit(struct cli_all_bc *bcs, int partial)
1941
1903
{
1942
1904
    LLVMApiScopedLock scopedLock;
1943
1905
    if (bcs->engine) {
1945
1907
            if (bcs->engine->Listener)
1946
1908
                bcs->engine->EE->UnregisterJITEventListener(bcs->engine->Listener);
1947
1909
            delete bcs->engine->EE;
 
1910
            bcs->engine->EE = 0;
1948
1911
        }
1949
1912
        delete bcs->engine->Listener;
1950
 
        delete bcs->engine;
1951
 
        bcs->engine = 0;
 
1913
        bcs->engine->Listener = 0;
 
1914
        if (!partial) {
 
1915
            delete bcs->engine;
 
1916
            bcs->engine = 0;
 
1917
        }
1952
1918
    }
1953
1919
    return 0;
1954
1920
}
2046
2012
namespace ClamBCModule {
2047
2013
void stop(const char *msg, llvm::Function* F, llvm::Instruction* I)
2048
2014
{
 
2015
    if (F && F->hasName())
 
2016
        llvm::errs() << "in function " << F->getName() << ": ";
2049
2017
    llvm::errs() << msg << "\n";
2050
2018
}
2051
2019
}