diff --git a/lib/AST/IRToASTVisitor.cpp b/lib/AST/IRToASTVisitor.cpp index 7eb6496e..9760667b 100755 --- a/lib/AST/IRToASTVisitor.cpp +++ b/lib/AST/IRToASTVisitor.cpp @@ -181,8 +181,42 @@ void ExprGen::VisitGlobalVar(llvm::GlobalVariable &gvar) { } } +static bool IsGVarAString(llvm::GlobalVariable *gvar) { + if (!gvar->hasInitializer()) { + return false; + } + + auto constant{gvar->getInitializer()}; + // Check if constant can be considered a string literal + auto arr_type{llvm::dyn_cast(constant->getType())}; + if (!arr_type) { + return false; + } + + auto elm_type{arr_type->getElementType()}; + if (!elm_type->isIntegerTy(8U)) { + return false; + } + + auto arr{llvm::dyn_cast(constant)}; + if (!arr) { + return false; + } + + auto init{arr->getAsString().str()}; + if (init.find('\0') != init.size() - 1) { + return false; + } + + return true; +} + clang::Expr *ExprGen::CreateConstantExpr(llvm::Constant *constant) { if (auto gvar = llvm::dyn_cast(constant)) { + if (IsGVarAString(gvar)) { + auto arr{llvm::cast(gvar->getInitializer())}; + return ast.CreateStrLit(arr->getAsString().str().c_str()); + } VisitGlobalVar(*gvar); } @@ -518,33 +552,7 @@ clang::Expr *ExprGen::visitGetElementPtrInst(llvm::GetElementPtrInst &inst) { return false; } - if (!gvar->hasInitializer()) { - return false; - } - - auto constant{gvar->getInitializer()}; - // Check if constant can be considered a string literal - auto arr_type{llvm::dyn_cast(constant->getType())}; - if (!arr_type) { - return false; - } - - auto elm_type{arr_type->getElementType()}; - if (!elm_type->isIntegerTy(8U)) { - return false; - } - - auto arr{llvm::dyn_cast(constant)}; - if (!arr) { - return false; - } - - auto init{arr->getAsString().str()}; - if (init.find('\0') != init.size() - 1) { - return false; - } - - return true; + return IsGVarAString(gvar); }; // Maybe we're inspecting a string reference diff --git a/lib/BC/Util.cpp b/lib/BC/Util.cpp index 63f7dd0f..21aedadc 100644 --- a/lib/BC/Util.cpp +++ b/lib/BC/Util.cpp @@ -306,7 +306,7 @@ void ConvertArrayArguments(llvm::Module &m) { std::unordered_map conv_types; std::vector indices; indices.push_back(0); - std::vector funcs_to_remove; + std::vector> funcs_to_remove; auto &ctx{m.getContext()}; auto ConvertType = [&](llvm::Type *t) -> llvm::Type * { if (!t->isArrayTy()) { @@ -364,7 +364,7 @@ void ConvertArrayArguments(llvm::Module &m) { ret->eraseFromParent(); } } - funcs_to_remove.push_back(orig_func); + funcs_to_remove.push_back(std::make_pair(orig_func, new_func)); return new_func; }; @@ -425,12 +425,19 @@ void ConvertArrayArguments(llvm::Module &m) { } } - for (auto func : funcs_to_remove) { + for (auto [func_to_remove, replacement] : funcs_to_remove) { // TODO(frabert): Sometimes uses stick around which are not calls (e.g. // references in globals). How do we replace those? Cannot use - // `func->replaceAllUsesWith` because types don't match. - if (func->use_empty()) { - func->eraseFromParent(); + // `func->replaceAllUsesWith` because types don't match + const llvm::User *user; + if (!func_to_remove->hasAddressTaken(&user, false, false, true, false)) { + auto orig_name = func_to_remove->getName().str(); + func_to_remove->replaceAllUsesWith(replacement); + func_to_remove->eraseFromParent(); + replacement->setName(orig_name); + } else { + DLOG(ERROR) << "Keeping around old array function: " + << func_to_remove->getName().str(); } } diff --git a/lib/Decompiler.cpp b/lib/Decompiler.cpp index ebd7b48f..7bcbe5dd 100644 --- a/lib/Decompiler.cpp +++ b/lib/Decompiler.cpp @@ -81,6 +81,12 @@ Result Decompile( std::vector args{"-Wno-pointer-to-int-cast", "-Wno-pointer-sign", "-target", module->getTargetTriple()}; + // Silence clang warning + // warning: unknown platform, assumming -mfloat-abi=soft + const auto& triple{llvm::Triple(module->getTargetTriple())}; + if (triple.isARM()) { + args.push_back("-mfloat-abi=soft"); + } auto ast_unit{clang::tooling::buildASTFromCodeWithArgs("", args, "out.c")}; rellic::DecompilationContext dec_ctx(*ast_unit); @@ -167,4 +173,4 @@ Result Decompile( return Result(std::move(error)); } } -} // namespace rellic \ No newline at end of file +} // namespace rellic