diff --git a/libclambcc/CMakeLists.txt b/libclambcc/CMakeLists.txt index f2b2b92eaf..8bfb8b551f 100644 --- a/libclambcc/CMakeLists.txt +++ b/libclambcc/CMakeLists.txt @@ -5,4 +5,5 @@ add_subdirectory(ClamBCRemoveUndefs) add_subdirectory(ClamBCPreserveABIs) add_subdirectory(ClamBCAnalyzer) add_subdirectory(Common) +add_subdirectory(ClamBCLowering) diff --git a/libclambcc/ClamBCLowering/CMakeLists.txt b/libclambcc/ClamBCLowering/CMakeLists.txt new file mode 100644 index 0000000000..d3317a939d --- /dev/null +++ b/libclambcc/ClamBCLowering/CMakeLists.txt @@ -0,0 +1,150 @@ +# Copyright (C) 2021 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + +# +# The clambcloweringf object library +# +add_library(clambcloweringf_obj OBJECT) +target_sources(clambcloweringf_obj + PRIVATE + ClamBCLowering.cpp + ClamBCLoweringF.cpp +) + +target_include_directories(clambcloweringf_obj + PRIVATE + ${CMAKE_BINARY_DIR} # For clambc-version.h (generated file) + . # For Common/clambc.h + .. # For clambc.h #TODO: change all passes to use "Common" and then delete this line. + ${LLVM_INCLUDE_DIRS} +) + +set_target_properties(clambcloweringf_obj PROPERTIES COMPILE_FLAGS "${WARNCXXFLAGS}") + +# +# For testing +# +#target_compile_definitions(clambcloweringf_obj -DLOG_BEFORE_AFTER=1) + +# +# The clambcloweringf shared library. +# +add_library( clambcloweringf SHARED ) +target_link_libraries( clambcloweringf + PUBLIC + clambcloweringf_obj ) +set_target_properties( clambcloweringf PROPERTIES + VERSION ${LIBCLAMBC_VERSION} + SOVERSION ${LIBCLAMBC_SOVERSION} ) + +target_link_directories(clambcloweringf PRIVATE ${LLVM_LIBRARY_DIRS}) +target_link_libraries(clambcloweringf PUBLIC ${LLVM_LIBS}) + +if(WIN32) + install(TARGETS clambcloweringf DESTINATION .) + + # Also install shared library (DLL) dependencies + install(CODE [[ + file(GET_RUNTIME_DEPENDENCIES + LIBRARIES + $ + RESOLVED_DEPENDENCIES_VAR _r_deps + UNRESOLVED_DEPENDENCIES_VAR _u_deps + DIRECTORIES + ${LLVM_LIBRARY_DIRS} + ) + foreach(_file ${_r_deps}) + string(TOLOWER ${_file} _file_lower) + if(NOT ${_file_lower} MATCHES "c:[\\/]windows[\\/]system32.*") + file(INSTALL + DESTINATION "${CMAKE_INSTALL_PREFIX}" + TYPE SHARED_LIBRARY + FOLLOW_SYMLINK_CHAIN + FILES "${_file}" + ) + endif() + endforeach() + #message("UNRESOLVED_DEPENDENCIES_VAR: ${_u_deps}") + ]]) +else() + install(TARGETS clambcloweringf DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif() + + + + + + + +# +# The clambcloweringnf object library +# +add_library(clambcloweringnf_obj OBJECT) +target_sources(clambcloweringnf_obj + PRIVATE + ClamBCLowering.cpp + ClamBCLoweringNF.cpp +) + +target_include_directories(clambcloweringnf_obj + PRIVATE + ${CMAKE_BINARY_DIR} # For clambc-version.h (generated file) + . # For Common/clambc.h + .. # For clambc.h #TODO: change all passes to use "Common" and then delete this line. + ${LLVM_INCLUDE_DIRS} +) + +set_target_properties(clambcloweringnf_obj PROPERTIES COMPILE_FLAGS "${WARNCXXFLAGS}") + +# +# For testing +# +#target_compile_definitions(clambcloweringnf_obj -DLOG_BEFORE_AFTER=1) + +# +# The clambcloweringnf shared library. +# +add_library( clambcloweringnf SHARED ) +target_link_libraries( clambcloweringnf + PUBLIC + clambcloweringnf_obj ) +set_target_properties( clambcloweringnf PROPERTIES + VERSION ${LIBCLAMBC_VERSION} + SOVERSION ${LIBCLAMBC_SOVERSION} ) + +target_link_directories(clambcloweringnf PRIVATE ${LLVM_LIBRARY_DIRS}) +target_link_libraries(clambcloweringnf PUBLIC ${LLVM_LIBS}) + +if(WIN32) + install(TARGETS clambcloweringnf DESTINATION .) + + # Also install shared library (DLL) dependencies + install(CODE [[ + file(GET_RUNTIME_DEPENDENCIES + LIBRARIES + $ + RESOLVED_DEPENDENCIES_VAR _r_deps + UNRESOLVED_DEPENDENCIES_VAR _u_deps + DIRECTORIES + ${LLVM_LIBRARY_DIRS} + ) + foreach(_file ${_r_deps}) + string(TOLOWER ${_file} _file_lower) + if(NOT ${_file_lower} MATCHES "c:[\\/]windows[\\/]system32.*") + file(INSTALL + DESTINATION "${CMAKE_INSTALL_PREFIX}" + TYPE SHARED_LIBRARY + FOLLOW_SYMLINK_CHAIN + FILES "${_file}" + ) + endif() + endforeach() + #message("UNRESOLVED_DEPENDENCIES_VAR: ${_u_deps}") + ]]) +else() + install(TARGETS clambcloweringnf DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif() + + + + + diff --git a/libclambcc/ClamBCLowering/ClamBCLowering.cpp b/libclambcc/ClamBCLowering/ClamBCLowering.cpp index 95ce631502..2dd5f674c7 100644 --- a/libclambcc/ClamBCLowering/ClamBCLowering.cpp +++ b/libclambcc/ClamBCLowering/ClamBCLowering.cpp @@ -19,101 +19,20 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ -#define DEBUG_TYPE "bclowering" -#include -#include "clambc.h" -#include "ClamBCModule.h" - -#include "llvm/ADT/STLExtras.h" -#include "llvm/Analysis/ConstantFolding.h" -#include -#include -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/Analysis/ValueTracking.h" -#include -#include -#include "llvm/CodeGen/IntrinsicLowering.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include "llvm/Support/CommandLine.h" -#include -#include -#include -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/raw_ostream.h" -#include -#include "llvm/Transforms/Scalar.h" -#include "llvm/CodeGen/IntrinsicLowering.h" - -using namespace llvm; - -namespace -{ -class ClamBCLowering : public ModulePass -{ - public: - static char ID; - ClamBCLowering() - : ModulePass(ID) {} - - virtual ~ClamBCLowering() {} - - virtual llvm::StringRef getPassName() const - { - return "ClamAV Bytecode Lowering"; - } - virtual bool runOnModule(Module &M); - virtual void getAnalysisUsage(AnalysisUsage &AU) const - { - } - - protected: - virtual bool isFinal() = 0; +//#define DEBUG_TYPE "bclowering" +#include "ClamBCLowering.h" - private: - void lowerIntrinsics(IntrinsicLowering *IL, Function &F); - void simplifyOperands(Function &F); - void downsizeIntrinsics(Function &F); - void splitGEPZArray(Function &F); - void fixupBitCasts(Function &F); - void fixupGEPs(Function &F); - void fixupPtrToInts(Function &F); -}; +#include "Common/clambc.h" +#include "Common/ClamBCModule.h" -class ClamBCLoweringNF : public ClamBCLowering -{ - public: - ClamBCLoweringNF() {} - virtual ~ClamBCLoweringNF() {} +#include +#include - protected: - virtual bool isFinal() - { - return false; - } -}; -class ClamBCLoweringF : public ClamBCLowering -{ - public: - ClamBCLoweringF() {} - virtual ~ClamBCLoweringF() {} +using namespace llvm; - protected: - virtual bool isFinal() - { - return true; - } -}; +namespace ClamBCLowering { -char ClamBCLowering::ID = 0; void ClamBCLowering::lowerIntrinsics(IntrinsicLowering *IL, Function &F) { std::vector prototypesToGen; @@ -156,7 +75,11 @@ void ClamBCLowering::lowerIntrinsics(IntrinsicLowering *IL, Function &F) Builder.SetInsertPoint(BO); Value *V = Builder.CreatePointerCast(PII->getOperand(0), PointerType::getUnqual(Type::getInt8Ty(F.getContext()))); +#if 0 V = Builder.CreateGEP(V, Idx); +#else + V = Builder.CreateGEP(V->getType(), V, Idx); +#endif V = Builder.CreatePtrToInt(V, BO->getType()); BO->replaceAllUsesWith(V); } else if (GetElementPtrInst *GEPI = dyn_cast(II)) { @@ -284,7 +207,13 @@ void ClamBCLowering::simplifyOperands(Function &F) if (ConstantExpr *CE = dyn_cast(II->getOperand(i))) { if (CE->getOpcode() == Instruction::GetElementPtr) { // rip out GEP expr and load it +#if 0 Ops.push_back(new LoadInst(CE, "gepex_load", SI)); +#else + llvm::errs() << "<" << __LINE__ << ">" << "I am expecting this to throw an assert, so check here" << "\n"; + llvm::errs() << "<" << __LINE__ << ">" << *CE << "\n"; + Ops.push_back(new LoadInst(CE->getType(), CE, "gepex_load", SI)); +#endif Changed = true; } } else { @@ -368,47 +297,47 @@ static inline void addIntrinsicFunctions(llvm::Module *pMod, Intrinsic::getDeclaration(pMod, Intrinsic::memmove, {i8Ptr, i8Ptr, i32, i1}))); } -static llvm::Value *getReplacementSizeOperand(llvm::CallSite &CS, llvm::Value *Len) +static llvm::Value *getReplacementSizeOperand(llvm::CallInst * pCallInst, llvm::Value *Len) { - llvm::LLVMContext &Context = CS.getParent()->getParent()->getParent()->getContext(); + LLVMContext & context = pCallInst->getParent()->getParent()->getParent()->getContext(); Value *NewLen = NULL; if (ConstantInt *C = dyn_cast(Len)) { - NewLen = ConstantInt::get(Type::getInt32Ty(Context), + NewLen = ConstantInt::get(Type::getInt32Ty(context), C->getValue().getLimitedValue((1ULL << 32) - 1)); } else { - NewLen = new TruncInst(Len, Type::getInt32Ty(Context), "lvl_dwn", CS.getInstruction()); + NewLen = new TruncInst(Len, Type::getInt32Ty(context), "lvl_dwn", pCallInst); } return NewLen; } -static void populateArgumentList(llvm::CallSite &CS, llvm::Value *newLen, size_t idx, std::vector &Ops) +static void populateArgumentList(llvm::CallInst * pCallInst, llvm::Value *newLen, size_t idx, std::vector &Ops) { - for (unsigned i = 0; i < CS.arg_size(); ++i) { + for (unsigned i = 0; i < pCallInst->arg_size(); ++i) { if (i == idx) { Ops.push_back(newLen); } else { - Ops.push_back(CS.getArgument(i)); + Ops.push_back(pCallInst->getArgOperand(i)); } } } -static bool replaceIntrinsicCalls(llvm::MemIntrinsic *MI, std::pair rep, size_t idx) +static bool replaceIntrinsicCalls(llvm::MemIntrinsic *pMemIntrinsic, std::pair rep, size_t idx) { - llvm::Function *pCalled = MI->getCalledFunction(); + llvm::Function *pCalled = pMemIntrinsic->getCalledFunction(); { if (rep.first == pCalled) { - llvm::CallSite CS(MI); - Value *Len = CS.getArgument(2); - llvm::Value *newLen = getReplacementSizeOperand(CS, Len); + //llvm::CallSite CS(MI); + Value *Len = pMemIntrinsic->getArgOperand(2); + llvm::Value *newLen = getReplacementSizeOperand(pMemIntrinsic, Len); std::vector args; - populateArgumentList(CS, newLen, idx, args); + populateArgumentList(pMemIntrinsic, newLen, idx, args); assert(args.size() == 4 && "malformed intrinsic call!"); - llvm::Instruction *i = CallInst::Create(rep.second, args, MI->getName(), MI); + llvm::Instruction *i = CallInst::Create(rep.second, args, pMemIntrinsic->getName(), pMemIntrinsic); assert(i && "Failed to create new CallInst"); return true; @@ -570,8 +499,8 @@ void ClamBCLowering::fixupGEPs(Function &F) //AllocaInst *AI = new AllocaInst(GC->getType(), "", Entry->begin()); AllocaInst *AI = new AllocaInst(GC->getType(), 0, "ClamBCLowering_fixupGEPs", llvm::cast(Entry->begin())); new StoreInst(GC, AI, GEPI); - Value *L = new LoadInst(AI, "ClamBCLowering_fixupGEPs", GEPI); - Value *V = GetElementPtrInst::CreateInBounds(L, indexes, "ClamBCLowering_fixupGEPs", GEPI); + Value *L = new LoadInst(AI->getType(), AI, "ClamBCLowering_fixupGEPs", GEPI); + Value *V = GetElementPtrInst::CreateInBounds(L->getType(), L, indexes, "ClamBCLowering_fixupGEPs", GEPI); GEPI->replaceAllUsesWith(V); GEPI->eraseFromParent(); } else { @@ -629,7 +558,7 @@ void ClamBCLowering::splitGEPZArray(Function &F) continue; } const PointerType *Ty = cast(GEPI->getPointerOperand()->getType()); - const ArrayType *ATy = dyn_cast(Ty->getElementType()); + const ArrayType *ATy = dyn_cast(Ty->getArrayElementType()); if (!ATy) { continue; } @@ -637,18 +566,27 @@ void ClamBCLowering::splitGEPZArray(Function &F) Constant *Zero = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 0); Value *VZ[] = {Zero, Zero}; // transform GEPZ: [4 x i16]* %p, 0, %i -> GEP1 i16* (bitcast)%p, %i - Value *C = GetElementPtrInst::CreateInBounds(GEPI->getPointerOperand(), VZ, "ClamBCLowering_splitGEPZArray", GEPI); - Value *NG = GetElementPtrInst::CreateInBounds(C, V, "ClamBCLowering_splitGEPZArray", GEPI); + Value *C = GetElementPtrInst::CreateInBounds(GEPI->getPointerOperand()->getType(), GEPI->getPointerOperand(), VZ, "ClamBCLowering_splitGEPZArray", GEPI); + Value *NG = GetElementPtrInst::CreateInBounds(C->getType(), C, V, "ClamBCLowering_splitGEPZArray", GEPI); GEPI->replaceAllUsesWith(NG); GEPI->eraseFromParent(); } } } +#if 0 bool ClamBCLowering::runOnModule(Module &M) +#else +PreservedAnalyses ClamBCLowering::run(Module & m, ModuleAnalysisManager & MAM) +#endif { - for (Module::iterator I = M.begin(), E = M.end(); + pMod = &m; + pContext = &(pMod->getContext()); + + //llvm::errs() << "<" << __FUNCTION__ << "::" << __LINE__ << ">" << "isFinal = " << isFinal() << "\n"; + + for (Module::iterator I = pMod->begin(), E = pMod->end(); I != E; ++I) { if (I->isDeclaration()) continue; @@ -663,14 +601,11 @@ bool ClamBCLowering::runOnModule(Module &M) } } - return true; + return PreservedAnalyses::none(); } -} // namespace -static RegisterPass X("clambc-lowering-notfinal", "ClamBC Lowering Pass", - false /* Only looks at CFG */, - false /* Analysis Pass */); -static RegisterPass XX("clambc-lowering-final", "ClamBC Lowering Pass", - false /* Only looks at CFG */, - false /* Analysis Pass */); + +} //namespace + + diff --git a/libclambcc/ClamBCLowering/ClamBCLowering.h b/libclambcc/ClamBCLowering/ClamBCLowering.h new file mode 100644 index 0000000000..e6b3cbf3b2 --- /dev/null +++ b/libclambcc/ClamBCLowering/ClamBCLowering.h @@ -0,0 +1,61 @@ +/* + * Compile LLVM bytecode to ClamAV bytecode. + * + * Copyright (C) 2009-2010 Sourcefire, Inc. + * + * Authors: Török Edvin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Softwaref + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +//#define DEBUG_TYPE "bclowering" + +#include +#include + +namespace ClamBCLowering +{ + +class ClamBCLowering : public llvm::PassInfoMixin +{ + public: + ClamBCLowering() {} + + virtual ~ClamBCLowering() {} + + virtual llvm::StringRef getPassName() const + { + return "ClamAV Bytecode Lowering"; + } + virtual llvm::PreservedAnalyses run(llvm::Module & m, llvm::ModuleAnalysisManager & MAM) ; + virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const + { + } + + protected: + virtual bool isFinal() = 0; + llvm::LLVMContext * pContext = nullptr; + llvm::Module * pMod = nullptr; + + private: + void lowerIntrinsics(llvm::IntrinsicLowering *IL, llvm::Function &F); + void simplifyOperands(llvm::Function &F); + void downsizeIntrinsics(llvm::Function &F); + void splitGEPZArray(llvm::Function &F); + void fixupBitCasts(llvm::Function &F); + void fixupGEPs(llvm::Function &F); + void fixupPtrToInts(llvm::Function &F); +}; + +} diff --git a/libclambcc/ClamBCLowering/ClamBCLoweringF.cpp b/libclambcc/ClamBCLowering/ClamBCLoweringF.cpp new file mode 100644 index 0000000000..73ae35425a --- /dev/null +++ b/libclambcc/ClamBCLowering/ClamBCLoweringF.cpp @@ -0,0 +1,70 @@ +/* + * Compile LLVM bytecode to ClamAV bytecode. + * + * Copyright (C) 2009-2010 Sourcefire, Inc. + * + * Authors: Török Edvin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Softwaref + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +//#define DEBUG_TYPE "bcloweringf" +#include "Common/clambc.h" +#include "Common/ClamBCModule.h" + +#include + +#include "ClamBCLowering.h" + + +using namespace llvm; + +namespace ClamBCLowering { + +class ClamBCLoweringF : public ClamBCLowering +{ + public: + ClamBCLoweringF() {} + virtual ~ClamBCLoweringF() {} + + protected: + virtual bool isFinal() + { + return true; + } +}; + + +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + return { + LLVM_PLUGIN_API_VERSION, "ClamBCLowering", "v0.1", + [](PassBuilder &PB) { + PB.registerPipelineParsingCallback( + [](StringRef Name, ModulePassManager &FPM, + ArrayRef) { + if(Name == "clambc-lowering-final"){ + FPM.addPass(ClamBCLoweringF()); + return true; + } + return false; + } + ); + } + }; +} + + +} + diff --git a/libclambcc/ClamBCLowering/ClamBCLoweringNF.cpp b/libclambcc/ClamBCLowering/ClamBCLoweringNF.cpp new file mode 100644 index 0000000000..8d7b035a8d --- /dev/null +++ b/libclambcc/ClamBCLowering/ClamBCLoweringNF.cpp @@ -0,0 +1,69 @@ +/* + * Compile LLVM bytecode to ClamAV bytecode. + * + * Copyright (C) 2009-2010 Sourcefire, Inc. + * + * Authors: Török Edvin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Softwaref + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +//#define DEBUG_TYPE "bcloweringnf" +#include "Common/clambc.h" +#include "Common/ClamBCModule.h" + +#include + +#include "ClamBCLowering.h" + +using namespace llvm; + +namespace ClamBCLowering { + +class ClamBCLoweringNF : public ClamBCLowering +{ + public: + ClamBCLoweringNF() {} + virtual ~ClamBCLoweringNF() {} + + protected: + virtual bool isFinal() + { + return false; + } +}; + +// This part is the new way of registering your pass +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + return { + LLVM_PLUGIN_API_VERSION, "ClamBCLowering", "v0.1", + [](PassBuilder &PB) { + PB.registerPipelineParsingCallback( + [](StringRef Name, ModulePassManager &FPM, + ArrayRef) { + if(Name == "clambc-lowering-notfinal"){ + FPM.addPass(ClamBCLoweringNF()); + return true; + } + return false; + } + ); + } + }; +} + + +} //namespace +