/* * Copyright (c) 2020 Trail of Bits, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #include "mcsema/BC/External.h" #include #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wsign-conversion" #pragma clang diagnostic ignored "-Wconversion" #pragma clang diagnostic ignored "-Wold-style-cast" #pragma clang diagnostic ignored "-Wdocumentation" #pragma clang diagnostic ignored "-Wswitch-enum" #include #include #include #include #include #include #pragma clang diagnostic pop #include #include #include #include #include #include "mcsema/Arch/Arch.h" #include "mcsema/BC/Callback.h" #include "mcsema/BC/Util.h" #include "mcsema/CFG/CFG.h" DECLARE_bool(explicit_args); namespace mcsema { llvm::Constant *NativeExternalFunction::Pointer(void) const { const auto prev_function = function; function = gModule->getFunction(name); if (!function && decl) { function = decl->DeclareInModule(name, *gModule); if (!prev_function) { module->AddNameToAddress(name, ea); } } if (function) { if (function == prev_function) { return prev_function; } // The function exists and isn't varargs; use it. if (is_weak) { if (function->isDeclaration()) { function->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); } else { function->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage); } } else { function->setLinkage(llvm::GlobalValue::ExternalLinkage); } remill::Annotate(function); return function; // The function doesn't exist in the module, and we need to declare it with // the information we have from CFG extraction. } else { CHECK(is_external); std::vector param_types(num_args, gWordType); module->AddNameToAddress(name, ea); function = llvm::Function::Create( llvm::FunctionType::get(gWordType, param_types, false), llvm::GlobalValue::ExternalLinkage, name, gModule.get()); if (is_weak) { function->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); } function->setCallingConv(cc); function->removeFnAttr(llvm::Attribute::InlineHint); function->removeFnAttr(llvm::Attribute::AlwaysInline); function->removeFnAttr(llvm::Attribute::ReadNone); function->removeFnAttr(llvm::Attribute::ReadOnly); function->removeFnAttr(llvm::Attribute::ArgMemOnly); function->addFnAttr(llvm::Attribute::NoInline); function->addFnAttr(llvm::Attribute::NoBuiltin); remill::Annotate(function); return function; } } llvm::Constant *NativeExternalVariable::Pointer(void) const { CHECK(is_external); CHECK_NOTNULL(segment); const auto seg = segment->Get(); CHECK(seg->is_external); CHECK_EQ(ea, seg->ea); CHECK(!seg->padding); return seg->Pointer(); } llvm::Constant *NativeExternalVariable::Address(void) const { return llvm::ConstantExpr::getPtrToInt(Pointer(), gWordType); } } // namespace mcsema