diff options
Diffstat (limited to 'source/Expression/IRForTarget.cpp')
-rw-r--r-- | source/Expression/IRForTarget.cpp | 2819 |
1 files changed, 0 insertions, 2819 deletions
diff --git a/source/Expression/IRForTarget.cpp b/source/Expression/IRForTarget.cpp deleted file mode 100644 index cf2a93b..0000000 --- a/source/Expression/IRForTarget.cpp +++ /dev/null @@ -1,2819 +0,0 @@ -//===-- IRForTarget.cpp -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Expression/IRForTarget.h" - -#include "llvm/Support/raw_ostream.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/IR/Metadata.h" -#include "llvm/IR/ValueSymbolTable.h" - -#include "clang/AST/ASTContext.h" - -#include "lldb/Core/dwarf.h" -#include "lldb/Core/ConstString.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/Scalar.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Expression/ClangExpressionDeclMap.h" -#include "lldb/Expression/IRExecutionUnit.h" -#include "lldb/Expression/IRInterpreter.h" -#include "lldb/Host/Endian.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangASTType.h" -#include "lldb/Target/CPPLanguageRuntime.h" - -#include <map> - -using namespace llvm; - -static char ID; - -IRForTarget::StaticDataAllocator::StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit) : - m_execution_unit(execution_unit), - m_stream_string(lldb_private::Stream::eBinary, execution_unit.GetAddressByteSize(), execution_unit.GetByteOrder()), - m_allocation(LLDB_INVALID_ADDRESS) -{ -} - -IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker) : - m_maker(maker), - m_values() -{ -} - -IRForTarget::FunctionValueCache::~FunctionValueCache() -{ -} - -llvm::Value * -IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) -{ - if (!m_values.count(function)) - { - llvm::Value *ret = m_maker(function); - m_values[function] = ret; - return ret; - } - return m_values[function]; -} - -lldb::addr_t -IRForTarget::StaticDataAllocator::Allocate() -{ - lldb_private::Error err; - - if (m_allocation != LLDB_INVALID_ADDRESS) - { - m_execution_unit.FreeNow(m_allocation); - m_allocation = LLDB_INVALID_ADDRESS; - } - - m_allocation = m_execution_unit.WriteNow((const uint8_t*)m_stream_string.GetData(), m_stream_string.GetSize(), err); - - return m_allocation; -} - -lldb::TargetSP -IRForTarget::StaticDataAllocator::GetTarget() -{ - return m_execution_unit.GetTarget(); -} - -static llvm::Value * -FindEntryInstruction (llvm::Function *function) -{ - if (function->empty()) - return NULL; - - return function->getEntryBlock().getFirstNonPHIOrDbg(); -} - -IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map, - bool resolve_vars, - lldb_private::IRExecutionUnit &execution_unit, - lldb_private::Stream *error_stream, - const char *func_name) : - ModulePass(ID), - m_resolve_vars(resolve_vars), - m_func_name(func_name), - m_module(NULL), - m_decl_map(decl_map), - m_data_allocator(execution_unit), - m_CFStringCreateWithBytes(NULL), - m_sel_registerName(NULL), - m_intptr_ty(NULL), - m_error_stream(error_stream), - m_result_store(NULL), - m_result_is_pointer(false), - m_reloc_placeholder(NULL), - m_entry_instruction_finder (FindEntryInstruction) -{ -} - -/* Handy utility functions used at several places in the code */ - -static std::string -PrintValue(const Value *value, bool truncate = false) -{ - std::string s; - if (value) - { - raw_string_ostream rso(s); - value->print(rso); - rso.flush(); - if (truncate) - s.resize(s.length() - 1); - } - return s; -} - -static std::string -PrintType(const llvm::Type *type, bool truncate = false) -{ - std::string s; - raw_string_ostream rso(s); - type->print(rso); - rso.flush(); - if (truncate) - s.resize(s.length() - 1); - return s; -} - -IRForTarget::~IRForTarget() -{ -} - -bool -IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) -{ - llvm_function.setLinkage(GlobalValue::ExternalLinkage); - - std::string name = llvm_function.getName().str(); - - return true; -} - -IRForTarget::LookupResult -IRForTarget::GetFunctionAddress (llvm::Function *fun, - uint64_t &fun_addr, - lldb_private::ConstString &name, - Constant **&value_ptr) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - fun_addr = LLDB_INVALID_ADDRESS; - name.Clear(); - value_ptr = NULL; - - if (fun->isIntrinsic()) - { - Intrinsic::ID intrinsic_id = (Intrinsic::ID)fun->getIntrinsicID(); - - switch (intrinsic_id) - { - default: - if (log) - log->Printf("Unresolved intrinsic \"%s\"", Intrinsic::getName(intrinsic_id).c_str()); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Call to unhandled compiler intrinsic '%s'\n", Intrinsic::getName(intrinsic_id).c_str()); - - return LookupResult::Fail; - case Intrinsic::memcpy: - { - static lldb_private::ConstString g_memcpy_str ("memcpy"); - name = g_memcpy_str; - } - break; - case Intrinsic::memset: - { - static lldb_private::ConstString g_memset_str ("memset"); - name = g_memset_str; - } - break; - case Intrinsic::dbg_declare: - case Intrinsic::dbg_value: - return LookupResult::Ignore; - } - - if (log && name) - log->Printf("Resolved intrinsic name \"%s\"", name.GetCString()); - } - else - { - name.SetCStringWithLength (fun->getName().data(), fun->getName().size()); - } - - // Find the address of the function. - - clang::NamedDecl *fun_decl = DeclForGlobal (fun); - - if (fun_decl) - { - if (!m_decl_map->GetFunctionInfo (fun_decl, fun_addr)) - { - std::vector<lldb_private::ConstString> alternates; - bool found_it = m_decl_map->GetFunctionAddress (name, fun_addr); - if (!found_it) - { - if (log) - log->Printf("Address of function \"%s\" not found.\n", name.GetCString()); - // Check for an alternate mangling for names from the standard library. - // For example, "std::basic_string<...>" has an alternate mangling scheme per - // the Itanium C++ ABI. - lldb::ProcessSP process_sp = m_data_allocator.GetTarget()->GetProcessSP(); - if (process_sp) - { - lldb_private::CPPLanguageRuntime *cpp_runtime = process_sp->GetCPPLanguageRuntime(); - if (cpp_runtime && cpp_runtime->GetAlternateManglings(name, alternates)) - { - for (size_t i = 0; i < alternates.size(); ++i) - { - const lldb_private::ConstString &alternate_name = alternates[i]; - if (log) - log->Printf("Looking up address of function \"%s\" with alternate name \"%s\"", - name.GetCString(), alternate_name.GetCString()); - if ((found_it = m_decl_map->GetFunctionAddress (alternate_name, fun_addr))) - { - if (log) - log->Printf("Found address of function \"%s\" with alternate name \"%s\"", - name.GetCString(), alternate_name.GetCString()); - break; - } - } - } - } - } - - if (!found_it) - { - lldb_private::Mangled mangled_name(name); - if (m_error_stream) - { - if (mangled_name.GetMangledName()) - m_error_stream->Printf("error: call to a function '%s' ('%s') that is not present in the target\n", - mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString(), - mangled_name.GetMangledName().GetCString()); - else - m_error_stream->Printf("error: call to a function '%s' that is not present in the target\n", - mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString()); - } - return LookupResult::Fail; - } - } - } - else - { - if (!m_decl_map->GetFunctionAddress (name, fun_addr)) - { - if (log) - log->Printf ("Metadataless function \"%s\" had no address", name.GetCString()); - - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Call to a symbol-only function '%s' that is not present in the target\n", name.GetCString()); - - return LookupResult::Fail; - } - } - - if (log) - log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), fun_addr); - - return LookupResult::Success; -} - -llvm::Constant * -IRForTarget::BuildFunctionPointer (llvm::Type *type, - uint64_t ptr) -{ - PointerType *fun_ptr_ty = PointerType::getUnqual(type); - Constant *fun_addr_int = ConstantInt::get(m_intptr_ty, ptr, false); - return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty); -} - -void -IRForTarget::RegisterFunctionMetadata(LLVMContext &context, - llvm::Value *function_ptr, - const char *name) -{ - for (llvm::User *user : function_ptr->users()) - { - if (Instruction *user_inst = dyn_cast<Instruction>(user)) - { - MDString* md_name = MDString::get(context, StringRef(name)); - - MDNode *metadata = MDNode::get(context, md_name); - - user_inst->setMetadata("lldb.call.realName", metadata); - } - else - { - RegisterFunctionMetadata (context, user, name); - } - } -} - -bool -IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - for (llvm::Module::iterator fi = llvm_module.begin(); - fi != llvm_module.end(); - ++fi) - { - Function *fun = fi; - - bool is_decl = fun->isDeclaration(); - - if (log) - log->Printf("Examining %s function %s", (is_decl ? "declaration" : "non-declaration"), fun->getName().str().c_str()); - - if (!is_decl) - continue; - - if (fun->use_empty()) - continue; // ignore - - uint64_t addr = LLDB_INVALID_ADDRESS; - lldb_private::ConstString name; - Constant **value_ptr = NULL; - - LookupResult result = GetFunctionAddress(fun, - addr, - name, - value_ptr); - - switch (result) - { - case LookupResult::Fail: - return false; // GetFunctionAddress reports its own errors - - case LookupResult::Ignore: - break; // Nothing to do - - case LookupResult::Success: - { - Constant *value = BuildFunctionPointer(fun->getFunctionType(), addr); - - RegisterFunctionMetadata (llvm_module.getContext(), fun, name.AsCString()); - - if (value_ptr) - *value_ptr = value; - - // If we are replacing a function with the nobuiltin attribute, it may - // be called with the builtin attribute on call sites. Remove any such - // attributes since it's illegal to have a builtin call to something - // other than a nobuiltin function. - if (fun->hasFnAttribute(llvm::Attribute::NoBuiltin)) { - llvm::Attribute builtin = llvm::Attribute::get(fun->getContext(), llvm::Attribute::Builtin); - - for (auto u : fun->users()) { - if (auto call = dyn_cast<CallInst>(u)) { - call->removeAttribute(AttributeSet::FunctionIndex, builtin); - } - } - } - - fun->replaceAllUsesWith(value); - } - break; - } - } - - return true; -} - - -clang::NamedDecl * -IRForTarget::DeclForGlobal (const GlobalValue *global_val, Module *module) -{ - NamedMDNode *named_metadata = module->getNamedMetadata("clang.global.decl.ptrs"); - - if (!named_metadata) - return NULL; - - unsigned num_nodes = named_metadata->getNumOperands(); - unsigned node_index; - - for (node_index = 0; - node_index < num_nodes; - ++node_index) - { - llvm::MDNode *metadata_node = dyn_cast<llvm::MDNode>(named_metadata->getOperand(node_index)); - if (!metadata_node) - return NULL; - - if (metadata_node->getNumOperands() != 2) - continue; - - if (mdconst::dyn_extract_or_null<GlobalValue>(metadata_node->getOperand(0)) != global_val) - continue; - - ConstantInt *constant_int = mdconst::dyn_extract<ConstantInt>(metadata_node->getOperand(1)); - - if (!constant_int) - return NULL; - - uintptr_t ptr = constant_int->getZExtValue(); - - return reinterpret_cast<clang::NamedDecl *>(ptr); - } - - return NULL; -} - -clang::NamedDecl * -IRForTarget::DeclForGlobal (GlobalValue *global_val) -{ - return DeclForGlobal(global_val, m_module); -} - -bool -IRForTarget::CreateResultVariable (llvm::Function &llvm_function) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (!m_resolve_vars) - return true; - - // Find the result variable. If it doesn't exist, we can give up right here. - - ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable(); - - std::string result_name_str; - const char *result_name = NULL; - - for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); - vi != ve; - ++vi) - { - result_name_str = vi->first().str(); - const char *value_name = result_name_str.c_str(); - - if (strstr(value_name, "$__lldb_expr_result_ptr") && - strncmp(value_name, "_ZGV", 4)) - { - result_name = value_name; - m_result_is_pointer = true; - break; - } - - if (strstr(value_name, "$__lldb_expr_result") && - strncmp(value_name, "_ZGV", 4)) - { - result_name = value_name; - m_result_is_pointer = false; - break; - } - } - - if (!result_name) - { - if (log) - log->PutCString("Couldn't find result variable"); - - return true; - } - - if (log) - log->Printf("Result name: \"%s\"", result_name); - - Value *result_value = m_module->getNamedValue(result_name); - - if (!result_value) - { - if (log) - log->PutCString("Result variable had no data"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Result variable's name (%s) exists, but not its definition\n", result_name); - - return false; - } - - if (log) - log->Printf("Found result in the IR: \"%s\"", PrintValue(result_value, false).c_str()); - - GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value); - - if (!result_global) - { - if (log) - log->PutCString("Result variable isn't a GlobalVariable"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) is defined, but is not a global variable\n", result_name); - - return false; - } - - clang::NamedDecl *result_decl = DeclForGlobal (result_global); - if (!result_decl) - { - if (log) - log->PutCString("Result variable doesn't have a corresponding Decl"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) does not have a corresponding Clang entity\n", result_name); - - return false; - } - - if (log) - { - std::string decl_desc_str; - raw_string_ostream decl_desc_stream(decl_desc_str); - result_decl->print(decl_desc_stream); - decl_desc_stream.flush(); - - log->Printf("Found result decl: \"%s\"", decl_desc_str.c_str()); - } - - clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl); - if (!result_var) - { - if (log) - log->PutCString("Result variable Decl isn't a VarDecl"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s)'s corresponding Clang entity isn't a variable\n", result_name); - - return false; - } - - // Get the next available result name from m_decl_map and create the persistent - // variable for it - - // If the result is an Lvalue, it is emitted as a pointer; see - // ASTResultSynthesizer::SynthesizeBodyResult. - if (m_result_is_pointer) - { - clang::QualType pointer_qual_type = result_var->getType(); - const clang::Type *pointer_type = pointer_qual_type.getTypePtr(); - - const clang::PointerType *pointer_pointertype = pointer_type->getAs<clang::PointerType>(); - const clang::ObjCObjectPointerType *pointer_objcobjpointertype = pointer_type->getAs<clang::ObjCObjectPointerType>(); - - if (pointer_pointertype) - { - clang::QualType element_qual_type = pointer_pointertype->getPointeeType(); - - m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(), - &result_decl->getASTContext()); - } - else if (pointer_objcobjpointertype) - { - clang::QualType element_qual_type = clang::QualType(pointer_objcobjpointertype->getObjectType(), 0); - - m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(), - &result_decl->getASTContext()); - } - else - { - if (log) - log->PutCString("Expected result to have pointer type, but it did not"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Lvalue result (%s) is not a pointer variable\n", result_name); - - return false; - } - } - else - { - m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(), - &result_decl->getASTContext()); - } - - - lldb::TargetSP target_sp (m_data_allocator.GetTarget()); - lldb_private::ExecutionContext exe_ctx (target_sp, true); - if (m_result_type.GetBitSize(exe_ctx.GetBestExecutionContextScope()) == 0) - { - lldb_private::StreamString type_desc_stream; - m_result_type.DumpTypeDescription(&type_desc_stream); - - if (log) - log->Printf("Result type has size 0"); - - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Size of result type '%s' couldn't be determined\n", - type_desc_stream.GetData()); - return false; - } - - if (log) - { - lldb_private::StreamString type_desc_stream; - m_result_type.DumpTypeDescription(&type_desc_stream); - - log->Printf("Result decl type: \"%s\"", type_desc_stream.GetData()); - } - - m_result_name = lldb_private::ConstString("$RESULT_NAME"); - - if (log) - log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64, - m_result_name.GetCString(), - m_result_type.GetByteSize(nullptr)); - - // Construct a new result global and set up its metadata - - GlobalVariable *new_result_global = new GlobalVariable((*m_module), - result_global->getType()->getElementType(), - false, /* not constant */ - GlobalValue::ExternalLinkage, - NULL, /* no initializer */ - m_result_name.GetCString ()); - - // It's too late in compilation to create a new VarDecl for this, but we don't - // need to. We point the metadata at the old VarDecl. This creates an odd - // anomaly: a variable with a Value whose name is something like $0 and a - // Decl whose name is $__lldb_expr_result. This condition is handled in - // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is - // fixed up. - - ConstantInt *new_constant_int = ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()), - reinterpret_cast<uint64_t>(result_decl), - false); - - llvm::Metadata *values[2]; - values[0] = ConstantAsMetadata::get(new_result_global); - values[1] = ConstantAsMetadata::get(new_constant_int); - - ArrayRef<Metadata *> value_ref(values, 2); - - MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); - NamedMDNode *named_metadata = m_module->getNamedMetadata("clang.global.decl.ptrs"); - named_metadata->addOperand(persistent_global_md); - - if (log) - log->Printf("Replacing \"%s\" with \"%s\"", - PrintValue(result_global).c_str(), - PrintValue(new_result_global).c_str()); - - if (result_global->use_empty()) - { - // We need to synthesize a store for this variable, because otherwise - // there's nothing to put into its equivalent persistent variable. - - BasicBlock &entry_block(llvm_function.getEntryBlock()); - Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg()); - - if (!first_entry_instruction) - return false; - - if (!result_global->hasInitializer()) - { - if (log) - log->Printf("Couldn't find initializer for unused variable"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) has no writes and no initializer\n", result_name); - - return false; - } - - Constant *initializer = result_global->getInitializer(); - - StoreInst *synthesized_store = new StoreInst(initializer, - new_result_global, - first_entry_instruction); - - if (log) - log->Printf("Synthesized result store \"%s\"\n", PrintValue(synthesized_store).c_str()); - } - else - { - result_global->replaceAllUsesWith(new_result_global); - } - - if (!m_decl_map->AddPersistentVariable(result_decl, - m_result_name, - m_result_type, - true, - m_result_is_pointer)) - return false; - - result_global->eraseFromParent(); - - return true; -} - -bool -IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str, - llvm::GlobalVariable *cstr) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - Type *ns_str_ty = ns_str->getType(); - - Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext()); - Type *i32_ty = Type::getInt32Ty(m_module->getContext()); - Type *i8_ty = Type::getInt8Ty(m_module->getContext()); - - if (!m_CFStringCreateWithBytes) - { - lldb::addr_t CFStringCreateWithBytes_addr; - - static lldb_private::ConstString g_CFStringCreateWithBytes_str ("CFStringCreateWithBytes"); - - if (!m_decl_map->GetFunctionAddress (g_CFStringCreateWithBytes_str, CFStringCreateWithBytes_addr)) - { - if (log) - log->PutCString("Couldn't find CFStringCreateWithBytes in the target"); - - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Rewriting an Objective-C constant string requires CFStringCreateWithBytes\n"); - - return false; - } - - if (log) - log->Printf("Found CFStringCreateWithBytes at 0x%" PRIx64, CFStringCreateWithBytes_addr); - - // Build the function type: - // - // CFStringRef CFStringCreateWithBytes ( - // CFAllocatorRef alloc, - // const UInt8 *bytes, - // CFIndex numBytes, - // CFStringEncoding encoding, - // Boolean isExternalRepresentation - // ); - // - // We make the following substitutions: - // - // CFStringRef -> i8* - // CFAllocatorRef -> i8* - // UInt8 * -> i8* - // CFIndex -> long (i32 or i64, as appropriate; we ask the module for its pointer size for now) - // CFStringEncoding -> i32 - // Boolean -> i8 - - Type *arg_type_array[5]; - - arg_type_array[0] = i8_ptr_ty; - arg_type_array[1] = i8_ptr_ty; - arg_type_array[2] = m_intptr_ty; - arg_type_array[3] = i32_ty; - arg_type_array[4] = i8_ty; - - ArrayRef<Type *> CFSCWB_arg_types(arg_type_array, 5); - - llvm::Type *CFSCWB_ty = FunctionType::get(ns_str_ty, CFSCWB_arg_types, false); - - // Build the constant containing the pointer to the function - PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty); - Constant *CFSCWB_addr_int = ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false); - m_CFStringCreateWithBytes = ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty); - } - - ConstantDataSequential *string_array = NULL; - - if (cstr) - string_array = dyn_cast<ConstantDataSequential>(cstr->getInitializer()); - - Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty); - Constant *bytes_arg = cstr ? ConstantExpr::getBitCast(cstr, i8_ptr_ty) : Constant::getNullValue(i8_ptr_ty); - Constant *numBytes_arg = ConstantInt::get(m_intptr_ty, cstr ? string_array->getNumElements() - 1 : 0, false); - Constant *encoding_arg = ConstantInt::get(i32_ty, 0x0600, false); /* 0x0600 is kCFStringEncodingASCII */ - Constant *isExternal_arg = ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */ - - Value *argument_array[5]; - - argument_array[0] = alloc_arg; - argument_array[1] = bytes_arg; - argument_array[2] = numBytes_arg; - argument_array[3] = encoding_arg; - argument_array[4] = isExternal_arg; - - ArrayRef <Value *> CFSCWB_arguments(argument_array, 5); - - FunctionValueCache CFSCWB_Caller ([this, &CFSCWB_arguments] (llvm::Function *function)->llvm::Value * { - return CallInst::Create(m_CFStringCreateWithBytes, - CFSCWB_arguments, - "CFStringCreateWithBytes", - llvm::cast<Instruction>(m_entry_instruction_finder.GetValue(function))); - }); - - if (!UnfoldConstant(ns_str, CFSCWB_Caller, m_entry_instruction_finder)) - { - if (log) - log->PutCString("Couldn't replace the NSString with the result of the call"); - - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Couldn't replace an Objective-C constant string with a dynamic string\n"); - - return false; - } - - ns_str->eraseFromParent(); - - return true; -} - -bool -IRForTarget::RewriteObjCConstStrings() -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable(); - - for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); - vi != ve; - ++vi) - { - std::string value_name = vi->first().str(); - const char *value_name_cstr = value_name.c_str(); - - if (strstr(value_name_cstr, "_unnamed_cfstring_")) - { - Value *nsstring_value = vi->second; - - GlobalVariable *nsstring_global = dyn_cast<GlobalVariable>(nsstring_value); - - if (!nsstring_global) - { - if (log) - log->PutCString("NSString variable is not a GlobalVariable"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a global variable\n"); - - return false; - } - - if (!nsstring_global->hasInitializer()) - { - if (log) - log->PutCString("NSString variable does not have an initializer"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have an initializer\n"); - - return false; - } - - ConstantStruct *nsstring_struct = dyn_cast<ConstantStruct>(nsstring_global->getInitializer()); - - if (!nsstring_struct) - { - if (log) - log->PutCString("NSString variable's initializer is not a ConstantStruct"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a structure constant\n"); - - return false; - } - - // We expect the following structure: - // - // struct { - // int *isa; - // int flags; - // char *str; - // long length; - // }; - - if (nsstring_struct->getNumOperands() != 4) - { - if (log) - log->Printf("NSString variable's initializer structure has an unexpected number of members. Should be 4, is %d", nsstring_struct->getNumOperands()); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: The struct for an Objective-C constant string is not as expected\n"); - - return false; - } - - Constant *nsstring_member = nsstring_struct->getOperand(2); - - if (!nsstring_member) - { - if (log) - log->PutCString("NSString initializer's str element was empty"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have a string initializer\n"); - - return false; - } - - ConstantExpr *nsstring_expr = dyn_cast<ConstantExpr>(nsstring_member); - - if (!nsstring_expr) - { - if (log) - log->PutCString("NSString initializer's str element is not a ConstantExpr"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not constant\n"); - - return false; - } - - if (nsstring_expr->getOpcode() != Instruction::GetElementPtr) - { - if (log) - log->Printf("NSString initializer's str element is not a GetElementPtr expression, it's a %s", nsstring_expr->getOpcodeName()); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not an array\n"); - - return false; - } - - Constant *nsstring_cstr = nsstring_expr->getOperand(0); - - GlobalVariable *cstr_global = dyn_cast<GlobalVariable>(nsstring_cstr); - - if (!cstr_global) - { - if (log) - log->PutCString("NSString initializer's str element is not a GlobalVariable"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a global\n"); - - return false; - } - - if (!cstr_global->hasInitializer()) - { - if (log) - log->PutCString("NSString initializer's str element does not have an initializer"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to initialized data\n"); - - return false; - } - - /* - if (!cstr_array) - { - if (log) - log->PutCString("NSString initializer's str element is not a ConstantArray"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to an array\n"); - - return false; - } - - if (!cstr_array->isCString()) - { - if (log) - log->PutCString("NSString initializer's str element is not a C string array"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a C string\n"); - - return false; - } - */ - - ConstantDataArray *cstr_array = dyn_cast<ConstantDataArray>(cstr_global->getInitializer()); - - if (log) - { - if (cstr_array) - log->Printf("Found NSString constant %s, which contains \"%s\"", value_name_cstr, cstr_array->getAsString().str().c_str()); - else - log->Printf("Found NSString constant %s, which contains \"\"", value_name_cstr); - } - - if (!cstr_array) - cstr_global = NULL; - - if (!RewriteObjCConstString(nsstring_global, cstr_global)) - { - if (log) - log->PutCString("Error rewriting the constant string"); - - // We don't print an error message here because RewriteObjCConstString has done so for us. - - return false; - } - } - } - - for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); - vi != ve; - ++vi) - { - std::string value_name = vi->first().str(); - const char *value_name_cstr = value_name.c_str(); - - if (!strcmp(value_name_cstr, "__CFConstantStringClassReference")) - { - GlobalVariable *gv = dyn_cast<GlobalVariable>(vi->second); - - if (!gv) - { - if (log) - log->PutCString("__CFConstantStringClassReference is not a global variable"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Found a CFConstantStringClassReference, but it is not a global object\n"); - - return false; - } - - gv->eraseFromParent(); - - break; - } - } - - return true; -} - -static bool IsObjCSelectorRef (Value *value) -{ - GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value); - - if (!global_variable || !global_variable->hasName() || !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_")) - return false; - - return true; -} - -// This function does not report errors; its callers are responsible. -bool -IRForTarget::RewriteObjCSelector (Instruction* selector_load) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - LoadInst *load = dyn_cast<LoadInst>(selector_load); - - if (!load) - return false; - - // Unpack the message name from the selector. In LLVM IR, an objc_msgSend gets represented as - // - // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; <i8*> - // %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; <i8*> - // - // where %obj is the object pointer and %tmp is the selector. - // - // @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_". - // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_" contains the string. - - // Find the pointer's initializer (a ConstantExpr with opcode GetElementPtr) and get the string from its target - - GlobalVariable *_objc_selector_references_ = dyn_cast<GlobalVariable>(load->getPointerOperand()); - - if (!_objc_selector_references_ || !_objc_selector_references_->hasInitializer()) - return false; - - Constant *osr_initializer = _objc_selector_references_->getInitializer(); - - ConstantExpr *osr_initializer_expr = dyn_cast<ConstantExpr>(osr_initializer); - - if (!osr_initializer_expr || osr_initializer_expr->getOpcode() != Instruction::GetElementPtr) - return false; - - Value *osr_initializer_base = osr_initializer_expr->getOperand(0); - - if (!osr_initializer_base) - return false; - - // Find the string's initializer (a ConstantArray) and get the string from it - - GlobalVariable *_objc_meth_var_name_ = dyn_cast<GlobalVariable>(osr_initializer_base); - - if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer()) - return false; - - Constant *omvn_initializer = _objc_meth_var_name_->getInitializer(); - - ConstantDataArray *omvn_initializer_array = dyn_cast<ConstantDataArray>(omvn_initializer); - - if (!omvn_initializer_array->isString()) - return false; - - std::string omvn_initializer_string = omvn_initializer_array->getAsString(); - - if (log) - log->Printf("Found Objective-C selector reference \"%s\"", omvn_initializer_string.c_str()); - - // Construct a call to sel_registerName - - if (!m_sel_registerName) - { - lldb::addr_t sel_registerName_addr; - - static lldb_private::ConstString g_sel_registerName_str ("sel_registerName"); - if (!m_decl_map->GetFunctionAddress (g_sel_registerName_str, sel_registerName_addr)) - return false; - - if (log) - log->Printf("Found sel_registerName at 0x%" PRIx64, sel_registerName_addr); - - // Build the function type: struct objc_selector *sel_registerName(uint8_t*) - - // The below code would be "more correct," but in actuality what's required is uint8_t* - //Type *sel_type = StructType::get(m_module->getContext()); - //Type *sel_ptr_type = PointerType::getUnqual(sel_type); - Type *sel_ptr_type = Type::getInt8PtrTy(m_module->getContext()); - - Type *type_array[1]; - - type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext()); - - ArrayRef<Type *> srN_arg_types(type_array, 1); - - llvm::Type *srN_type = FunctionType::get(sel_ptr_type, srN_arg_types, false); - - // Build the constant containing the pointer to the function - PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type); - Constant *srN_addr_int = ConstantInt::get(m_intptr_ty, sel_registerName_addr, false); - m_sel_registerName = ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty); - } - - Value *argument_array[1]; - - Constant *omvn_pointer = ConstantExpr::getBitCast(_objc_meth_var_name_, Type::getInt8PtrTy(m_module->getContext())); - - argument_array[0] = omvn_pointer; - - ArrayRef<Value *> srN_arguments(argument_array, 1); - - CallInst *srN_call = CallInst::Create(m_sel_registerName, - srN_arguments, - "sel_registerName", - selector_load); - - // Replace the load with the call in all users - - selector_load->replaceAllUsesWith(srN_call); - - selector_load->eraseFromParent(); - - return true; -} - -bool -IRForTarget::RewriteObjCSelectors (BasicBlock &basic_block) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - BasicBlock::iterator ii; - - typedef SmallVector <Instruction*, 2> InstrList; - typedef InstrList::iterator InstrIterator; - - InstrList selector_loads; - - for (ii = basic_block.begin(); - ii != basic_block.end(); - ++ii) - { - Instruction &inst = *ii; - - if (LoadInst *load = dyn_cast<LoadInst>(&inst)) - if (IsObjCSelectorRef(load->getPointerOperand())) - selector_loads.push_back(&inst); - } - - InstrIterator iter; - - for (iter = selector_loads.begin(); - iter != selector_loads.end(); - ++iter) - { - if (!RewriteObjCSelector(*iter)) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Couldn't change a static reference to an Objective-C selector to a dynamic reference\n"); - - if (log) - log->PutCString("Couldn't rewrite a reference to an Objective-C selector"); - - return false; - } - } - - return true; -} - -// This function does not report errors; its callers are responsible. -bool -IRForTarget::RewritePersistentAlloc (llvm::Instruction *persistent_alloc) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc); - - MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr"); - - if (!alloc_md || !alloc_md->getNumOperands()) - return false; - - ConstantInt *constant_int = mdconst::dyn_extract<ConstantInt>(alloc_md->getOperand(0)); - - if (!constant_int) - return false; - - // We attempt to register this as a new persistent variable with the DeclMap. - - uintptr_t ptr = constant_int->getZExtValue(); - - clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr); - - lldb_private::TypeFromParser result_decl_type (decl->getType().getAsOpaquePtr(), - &decl->getASTContext()); - - StringRef decl_name (decl->getName()); - lldb_private::ConstString persistent_variable_name (decl_name.data(), decl_name.size()); - if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type, false, false)) - return false; - - GlobalVariable *persistent_global = new GlobalVariable((*m_module), - alloc->getType(), - false, /* not constant */ - GlobalValue::ExternalLinkage, - NULL, /* no initializer */ - alloc->getName().str().c_str()); - - // What we're going to do here is make believe this was a regular old external - // variable. That means we need to make the metadata valid. - - NamedMDNode *named_metadata = m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs"); - - llvm::Metadata *values[2]; - values[0] = ConstantAsMetadata::get(persistent_global); - values[1] = ConstantAsMetadata::get(constant_int); - - ArrayRef<llvm::Metadata *> value_ref(values, 2); - - MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); - named_metadata->addOperand(persistent_global_md); - - // Now, since the variable is a pointer variable, we will drop in a load of that - // pointer variable. - - LoadInst *persistent_load = new LoadInst (persistent_global, "", alloc); - - if (log) - log->Printf("Replacing \"%s\" with \"%s\"", - PrintValue(alloc).c_str(), - PrintValue(persistent_load).c_str()); - - alloc->replaceAllUsesWith(persistent_load); - alloc->eraseFromParent(); - - return true; -} - -bool -IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) -{ - if (!m_resolve_vars) - return true; - - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - BasicBlock::iterator ii; - - typedef SmallVector <Instruction*, 2> InstrList; - typedef InstrList::iterator InstrIterator; - - InstrList pvar_allocs; - - for (ii = basic_block.begin(); - ii != basic_block.end(); - ++ii) - { - Instruction &inst = *ii; - - if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst)) - { - llvm::StringRef alloc_name = alloc->getName(); - - if (alloc_name.startswith("$") && - !alloc_name.startswith("$__lldb")) - { - if (alloc_name.find_first_of("0123456789") == 1) - { - if (log) - log->Printf("Rejecting a numeric persistent variable."); - - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Names starting with $0, $1, ... are reserved for use as result names\n"); - - return false; - } - - pvar_allocs.push_back(alloc); - } - } - } - - InstrIterator iter; - - for (iter = pvar_allocs.begin(); - iter != pvar_allocs.end(); - ++iter) - { - if (!RewritePersistentAlloc(*iter)) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite the creation of a persistent variable\n"); - - if (log) - log->PutCString("Couldn't rewrite the creation of a persistent variable"); - - return false; - } - } - - return true; -} - -bool -IRForTarget::MaterializeInitializer (uint8_t *data, Constant *initializer) -{ - if (!initializer) - return true; - - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log && log->GetVerbose()) - log->Printf(" MaterializeInitializer(%p, %s)", (void *)data, PrintValue(initializer).c_str()); - - Type *initializer_type = initializer->getType(); - - if (ConstantInt *int_initializer = dyn_cast<ConstantInt>(initializer)) - { - memcpy (data, int_initializer->getValue().getRawData(), m_target_data->getTypeStoreSize(initializer_type)); - return true; - } - else if (ConstantDataArray *array_initializer = dyn_cast<ConstantDataArray>(initializer)) - { - if (array_initializer->isString()) - { - std::string array_initializer_string = array_initializer->getAsString(); - memcpy (data, array_initializer_string.c_str(), m_target_data->getTypeStoreSize(initializer_type)); - } - else - { - ArrayType *array_initializer_type = array_initializer->getType(); - Type *array_element_type = array_initializer_type->getElementType(); - - size_t element_size = m_target_data->getTypeAllocSize(array_element_type); - - for (unsigned i = 0; i < array_initializer->getNumOperands(); ++i) - { - Value *operand_value = array_initializer->getOperand(i); - Constant *operand_constant = dyn_cast<Constant>(operand_value); - - if (!operand_constant) - return false; - - if (!MaterializeInitializer(data + (i * element_size), operand_constant)) - return false; - } - } - return true; - } - else if (ConstantStruct *struct_initializer = dyn_cast<ConstantStruct>(initializer)) - { - StructType *struct_initializer_type = struct_initializer->getType(); - const StructLayout *struct_layout = m_target_data->getStructLayout(struct_initializer_type); - - for (unsigned i = 0; - i < struct_initializer->getNumOperands(); - ++i) - { - if (!MaterializeInitializer(data + struct_layout->getElementOffset(i), struct_initializer->getOperand(i))) - return false; - } - return true; - } - else if (isa<ConstantAggregateZero>(initializer)) - { - memset(data, 0, m_target_data->getTypeStoreSize(initializer_type)); - return true; - } - return false; -} - -bool -IRForTarget::MaterializeInternalVariable (GlobalVariable *global_variable) -{ - if (GlobalVariable::isExternalLinkage(global_variable->getLinkage())) - return false; - - if (global_variable == m_reloc_placeholder) - return true; - - uint64_t offset = m_data_allocator.GetStream().GetSize(); - - llvm::Type *variable_type = global_variable->getType(); - - Constant *initializer = global_variable->getInitializer(); - - llvm::Type *initializer_type = initializer->getType(); - - size_t size = m_target_data->getTypeAllocSize(initializer_type); - size_t align = m_target_data->getPrefTypeAlignment(initializer_type); - - const size_t mask = (align - 1); - uint64_t aligned_offset = (offset + mask) & ~mask; - m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0); - offset = aligned_offset; - - lldb_private::DataBufferHeap data(size, '\0'); - - if (initializer) - if (!MaterializeInitializer(data.GetBytes(), initializer)) - return false; - - m_data_allocator.GetStream().Write(data.GetBytes(), data.GetByteSize()); - - Constant *new_pointer = BuildRelocation(variable_type, offset); - - global_variable->replaceAllUsesWith(new_pointer); - - global_variable->eraseFromParent(); - - return true; -} - -// This function does not report errors; its callers are responsible. -bool -IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - log->Printf("MaybeHandleVariable (%s)", PrintValue(llvm_value_ptr).c_str()); - - if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr)) - { - switch (constant_expr->getOpcode()) - { - default: - break; - case Instruction::GetElementPtr: - case Instruction::BitCast: - Value *s = constant_expr->getOperand(0); - if (!MaybeHandleVariable(s)) - return false; - } - } - else if (GlobalVariable *global_variable = dyn_cast<GlobalVariable>(llvm_value_ptr)) - { - if (!GlobalValue::isExternalLinkage(global_variable->getLinkage())) - return MaterializeInternalVariable(global_variable); - - clang::NamedDecl *named_decl = DeclForGlobal(global_variable); - - if (!named_decl) - { - if (IsObjCSelectorRef(llvm_value_ptr)) - return true; - - if (!global_variable->hasExternalLinkage()) - return true; - - if (log) - log->Printf("Found global variable \"%s\" without metadata", global_variable->getName().str().c_str()); - - return false; - } - - std::string name (named_decl->getName().str()); - - clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl); - if (value_decl == NULL) - return false; - - lldb_private::ClangASTType clang_type(&value_decl->getASTContext(), value_decl->getType()); - - const Type *value_type = NULL; - - if (name[0] == '$') - { - // The $__lldb_expr_result name indicates the return value has allocated as - // a static variable. Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, - // accesses to this static variable need to be redirected to the result of dereferencing - // a pointer that is passed in as one of the arguments. - // - // Consequently, when reporting the size of the type, we report a pointer type pointing - // to the type of $__lldb_expr_result, not the type itself. - // - // We also do this for any user-declared persistent variables. - clang_type = clang_type.GetPointerType(); - value_type = PointerType::get(global_variable->getType(), 0); - } - else - { - value_type = global_variable->getType(); - } - - const uint64_t value_size = clang_type.GetByteSize(nullptr); - lldb::offset_t value_alignment = (clang_type.GetTypeBitAlign() + 7ull) / 8ull; - - if (log) - { - log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 ", align %" PRIu64 "]", - name.c_str(), - clang_type.GetQualType().getAsString().c_str(), - PrintType(value_type).c_str(), - value_size, - value_alignment); - } - - - if (named_decl && !m_decl_map->AddValueToStruct(named_decl, - lldb_private::ConstString (name.c_str()), - llvm_value_ptr, - value_size, - value_alignment)) - { - if (!global_variable->hasExternalLinkage()) - return true; - else if (HandleSymbol (global_variable)) - return true; - else - return false; - } - } - else if (dyn_cast<llvm::Function>(llvm_value_ptr)) - { - if (log) - log->Printf("Function pointers aren't handled right now"); - - return false; - } - - return true; -} - -// This function does not report errors; its callers are responsible. -bool -IRForTarget::HandleSymbol (Value *symbol) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - lldb_private::ConstString name(symbol->getName().str().c_str()); - - lldb::addr_t symbol_addr = m_decl_map->GetSymbolAddress (name, lldb::eSymbolTypeAny); - - if (symbol_addr == LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf ("Symbol \"%s\" had no address", name.GetCString()); - - return false; - } - - if (log) - log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), symbol_addr); - - Type *symbol_type = symbol->getType(); - - Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false); - - Value *symbol_addr_ptr = ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type); - - if (log) - log->Printf("Replacing %s with %s", PrintValue(symbol).c_str(), PrintValue(symbol_addr_ptr).c_str()); - - symbol->replaceAllUsesWith(symbol_addr_ptr); - - return true; -} - -bool -IRForTarget::MaybeHandleCallArguments (CallInst *Old) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - log->Printf("MaybeHandleCallArguments(%s)", PrintValue(Old).c_str()); - - for (unsigned op_index = 0, num_ops = Old->getNumArgOperands(); - op_index < num_ops; - ++op_index) - if (!MaybeHandleVariable(Old->getArgOperand(op_index))) // conservatively believe that this is a store - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite one of the arguments of a function call.\n"); - - return false; - } - - return true; -} - -bool -IRForTarget::HandleObjCClass(Value *classlist_reference) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - GlobalVariable *global_variable = dyn_cast<GlobalVariable>(classlist_reference); - - if (!global_variable) - return false; - - Constant *initializer = global_variable->getInitializer(); - - if (!initializer) - return false; - - if (!initializer->hasName()) - return false; - - StringRef name(initializer->getName()); - lldb_private::ConstString name_cstr(name.str().c_str()); - lldb::addr_t class_ptr = m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass); - - if (log) - log->Printf("Found reference to Objective-C class %s (0x%llx)", name_cstr.AsCString(), (unsigned long long)class_ptr); - - if (class_ptr == LLDB_INVALID_ADDRESS) - return false; - - if (global_variable->use_empty()) - return false; - - SmallVector<LoadInst *, 2> load_instructions; - - for (llvm::User *u : global_variable->users()) - { - if (LoadInst *load_instruction = dyn_cast<LoadInst>(u)) - load_instructions.push_back(load_instruction); - } - - if (load_instructions.empty()) - return false; - - Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr); - - for (LoadInst *load_instruction : load_instructions) - { - Constant *class_bitcast = ConstantExpr::getIntToPtr(class_addr, load_instruction->getType()); - - load_instruction->replaceAllUsesWith(class_bitcast); - - load_instruction->eraseFromParent(); - } - - return true; -} - -bool -IRForTarget::RemoveCXAAtExit (BasicBlock &basic_block) -{ - BasicBlock::iterator ii; - - std::vector<CallInst *> calls_to_remove; - - for (ii = basic_block.begin(); - ii != basic_block.end(); - ++ii) - { - Instruction &inst = *ii; - - CallInst *call = dyn_cast<CallInst>(&inst); - - // MaybeHandleCallArguments handles error reporting; we are silent here - if (!call) - continue; - - bool remove = false; - - llvm::Function *func = call->getCalledFunction(); - - if (func && func->getName() == "__cxa_atexit") - remove = true; - - llvm::Value *val = call->getCalledValue(); - - if (val && val->getName() == "__cxa_atexit") - remove = true; - - if (remove) - calls_to_remove.push_back(call); - } - - for (std::vector<CallInst *>::iterator ci = calls_to_remove.begin(), ce = calls_to_remove.end(); - ci != ce; - ++ci) - { - (*ci)->eraseFromParent(); - } - - return true; -} - -bool -IRForTarget::ResolveCalls(BasicBlock &basic_block) -{ - ///////////////////////////////////////////////////////////////////////// - // Prepare the current basic block for execution in the remote process - // - - BasicBlock::iterator ii; - - for (ii = basic_block.begin(); - ii != basic_block.end(); - ++ii) - { - Instruction &inst = *ii; - - CallInst *call = dyn_cast<CallInst>(&inst); - - // MaybeHandleCallArguments handles error reporting; we are silent here - if (call && !MaybeHandleCallArguments(call)) - return false; - } - - return true; -} - -bool -IRForTarget::ResolveExternals (Function &llvm_function) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - for (GlobalVariable &global_var : m_module->globals()) - { - std::string global_name = global_var.getName().str(); - - if (log) - log->Printf("Examining %s, DeclForGlobalValue returns %p", - global_name.c_str(), - static_cast<void*>(DeclForGlobal(&global_var))); - - if (global_name.find("OBJC_IVAR") == 0) - { - if (!HandleSymbol(&global_var)) - { - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol %s\n", global_name.c_str()); - - return false; - } - } - else if (global_name.find("OBJC_CLASSLIST_REFERENCES_$") != global_name.npos) - { - if (!HandleObjCClass(&global_var)) - { - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n"); - - return false; - } - } - else if (global_name.find("OBJC_CLASSLIST_SUP_REFS_$") != global_name.npos) - { - if (!HandleObjCClass(&global_var)) - { - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n"); - - return false; - } - } - else if (DeclForGlobal(&global_var)) - { - if (!MaybeHandleVariable (&global_var)) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite external variable %s\n", global_name.c_str()); - - return false; - } - } - } - - return true; -} - -bool -IRForTarget::ReplaceStrings () -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - typedef std::map <GlobalVariable *, size_t> OffsetsTy; - - OffsetsTy offsets; - - for (GlobalVariable &gv : m_module->globals()) - { - if (!gv.hasInitializer()) - continue; - - Constant *gc = gv.getInitializer(); - - std::string str; - - if (gc->isNullValue()) - { - Type *gc_type = gc->getType(); - - ArrayType *gc_array_type = dyn_cast<ArrayType>(gc_type); - - if (!gc_array_type) - continue; - - Type *gc_element_type = gc_array_type->getElementType(); - - IntegerType *gc_integer_type = dyn_cast<IntegerType>(gc_element_type); - - if (gc_integer_type->getBitWidth() != 8) - continue; - - str = ""; - } - else - { - ConstantDataArray *gc_array = dyn_cast<ConstantDataArray>(gc); - - if (!gc_array) - continue; - - if (!gc_array->isCString()) - continue; - - if (log) - log->Printf("Found a GlobalVariable with string initializer %s", PrintValue(gc).c_str()); - - str = gc_array->getAsString(); - } - - offsets[&gv] = m_data_allocator.GetStream().GetSize(); - - m_data_allocator.GetStream().Write(str.c_str(), str.length() + 1); - } - - Type *char_ptr_ty = Type::getInt8PtrTy(m_module->getContext()); - - for (OffsetsTy::iterator oi = offsets.begin(), oe = offsets.end(); - oi != oe; - ++oi) - { - GlobalVariable *gv = oi->first; - size_t offset = oi->second; - - Constant *new_initializer = BuildRelocation(char_ptr_ty, offset); - - if (log) - log->Printf("Replacing GV %s with %s", PrintValue(gv).c_str(), PrintValue(new_initializer).c_str()); - - for (llvm::User *u : gv->users()) - { - if (log) - log->Printf("Found use %s", PrintValue(u).c_str()); - - ConstantExpr *const_expr = dyn_cast<ConstantExpr>(u); - StoreInst *store_inst = dyn_cast<StoreInst>(u); - - if (const_expr) - { - if (const_expr->getOpcode() != Instruction::GetElementPtr) - { - if (log) - log->Printf("Use (%s) of string variable is not a GetElementPtr constant", PrintValue(const_expr).c_str()); - - return false; - } - - Constant *bit_cast = ConstantExpr::getBitCast(new_initializer, const_expr->getOperand(0)->getType()); - Constant *new_gep = const_expr->getWithOperandReplaced(0, bit_cast); - - const_expr->replaceAllUsesWith(new_gep); - } - else if (store_inst) - { - Constant *bit_cast = ConstantExpr::getBitCast(new_initializer, store_inst->getValueOperand()->getType()); - - store_inst->setOperand(0, bit_cast); - } - else - { - if (log) - log->Printf("Use (%s) of string variable is neither a constant nor a store", PrintValue(const_expr).c_str()); - - return false; - } - } - - gv->eraseFromParent(); - } - - return true; -} - -bool -IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - typedef SmallVector <Value*, 2> ConstantList; - typedef SmallVector <llvm::Instruction*, 2> UserList; - typedef ConstantList::iterator ConstantIterator; - typedef UserList::iterator UserIterator; - - ConstantList static_constants; - UserList static_users; - - for (BasicBlock::iterator ii = basic_block.begin(), ie = basic_block.end(); - ii != ie; - ++ii) - { - llvm::Instruction &inst = *ii; - - for (Value *operand_val : inst.operand_values()) - { - ConstantFP *operand_constant_fp = dyn_cast<ConstantFP>(operand_val); - - if (operand_constant_fp/* && operand_constant_fp->getType()->isX86_FP80Ty()*/) - { - static_constants.push_back(operand_val); - static_users.push_back(ii); - } - } - } - - ConstantIterator constant_iter; - UserIterator user_iter; - - for (constant_iter = static_constants.begin(), user_iter = static_users.begin(); - constant_iter != static_constants.end(); - ++constant_iter, ++user_iter) - { - Value *operand_val = *constant_iter; - llvm::Instruction *inst = *user_iter; - - ConstantFP *operand_constant_fp = dyn_cast<ConstantFP>(operand_val); - - if (operand_constant_fp) - { - Type *operand_type = operand_constant_fp->getType(); - - APFloat operand_apfloat = operand_constant_fp->getValueAPF(); - APInt operand_apint = operand_apfloat.bitcastToAPInt(); - - const uint8_t* operand_raw_data = (const uint8_t*)operand_apint.getRawData(); - size_t operand_data_size = operand_apint.getBitWidth() / 8; - - if (log) - { - std::string s; - raw_string_ostream ss(s); - for (size_t index = 0; - index < operand_data_size; - ++index) - { - ss << (uint32_t)operand_raw_data[index]; - ss << " "; - } - ss.flush(); - - log->Printf("Found ConstantFP with size %" PRIu64 " and raw data %s", (uint64_t)operand_data_size, s.c_str()); - } - - lldb_private::DataBufferHeap data(operand_data_size, 0); - - if (lldb::endian::InlHostByteOrder() != m_data_allocator.GetStream().GetByteOrder()) - { - uint8_t *data_bytes = data.GetBytes(); - - for (size_t index = 0; - index < operand_data_size; - ++index) - { - data_bytes[index] = operand_raw_data[operand_data_size - (1 + index)]; - } - } - else - { - memcpy(data.GetBytes(), operand_raw_data, operand_data_size); - } - - uint64_t offset = m_data_allocator.GetStream().GetSize(); - - size_t align = m_target_data->getPrefTypeAlignment(operand_type); - - const size_t mask = (align - 1); - uint64_t aligned_offset = (offset + mask) & ~mask; - m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0); - - m_data_allocator.GetStream().Write(data.GetBytes(), operand_data_size); - - llvm::Type *fp_ptr_ty = operand_constant_fp->getType()->getPointerTo(); - - Constant *new_pointer = BuildRelocation(fp_ptr_ty, aligned_offset); - - llvm::LoadInst *fp_load = new llvm::LoadInst(new_pointer, "fp_load", inst); - - operand_constant_fp->replaceAllUsesWith(fp_load); - } - } - - return true; -} - -static bool isGuardVariableRef(Value *V) -{ - Constant *Old = NULL; - - if (!(Old = dyn_cast<Constant>(V))) - return false; - - ConstantExpr *CE = NULL; - - if ((CE = dyn_cast<ConstantExpr>(V))) - { - if (CE->getOpcode() != Instruction::BitCast) - return false; - - Old = CE->getOperand(0); - } - - GlobalVariable *GV = dyn_cast<GlobalVariable>(Old); - - if (!GV || !GV->hasName() || - (!GV->getName().startswith("_ZGV") && // Itanium ABI guard variable - !GV->getName().endswith("@4IA"))) // Microsoft ABI guard variable - { - return false; - } - - return true; -} - -void -IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction* guard_load) -{ - Constant *zero(Constant::getNullValue(guard_load->getType())); - guard_load->replaceAllUsesWith(zero); - guard_load->eraseFromParent(); -} - -static void ExciseGuardStore(Instruction* guard_store) -{ - guard_store->eraseFromParent(); -} - -bool -IRForTarget::RemoveGuards(BasicBlock &basic_block) -{ - /////////////////////////////////////////////////////// - // Eliminate any reference to guard variables found. - // - - BasicBlock::iterator ii; - - typedef SmallVector <Instruction*, 2> InstrList; - typedef InstrList::iterator InstrIterator; - - InstrList guard_loads; - InstrList guard_stores; - - for (ii = basic_block.begin(); - ii != basic_block.end(); - ++ii) - { - Instruction &inst = *ii; - - if (LoadInst *load = dyn_cast<LoadInst>(&inst)) - if (isGuardVariableRef(load->getPointerOperand())) - guard_loads.push_back(&inst); - - if (StoreInst *store = dyn_cast<StoreInst>(&inst)) - if (isGuardVariableRef(store->getPointerOperand())) - guard_stores.push_back(&inst); - } - - InstrIterator iter; - - for (iter = guard_loads.begin(); - iter != guard_loads.end(); - ++iter) - TurnGuardLoadIntoZero(*iter); - - for (iter = guard_stores.begin(); - iter != guard_stores.end(); - ++iter) - ExciseGuardStore(*iter); - - return true; -} - -// This function does not report errors; its callers are responsible. -bool -IRForTarget::UnfoldConstant(Constant *old_constant, - FunctionValueCache &value_maker, - FunctionValueCache &entry_instruction_finder) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - SmallVector<User*, 16> users; - - // We do this because the use list might change, invalidating our iterator. - // Much better to keep a work list ourselves. - for (llvm::User *u : old_constant->users()) - users.push_back(u); - - for (size_t i = 0; - i < users.size(); - ++i) - { - User *user = users[i]; - - if (Constant *constant = dyn_cast<Constant>(user)) - { - // synthesize a new non-constant equivalent of the constant - - if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) - { - switch (constant_expr->getOpcode()) - { - default: - if (log) - log->Printf("Unhandled constant expression type: \"%s\"", PrintValue(constant_expr).c_str()); - return false; - case Instruction::BitCast: - { - FunctionValueCache bit_cast_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* { - // UnaryExpr - // OperandList[0] is value - - if (constant_expr->getOperand(0) != old_constant) - return constant_expr; - - return new BitCastInst(value_maker.GetValue(function), - constant_expr->getType(), - "", - llvm::cast<Instruction>(entry_instruction_finder.GetValue(function))); - }); - - if (!UnfoldConstant(constant_expr, bit_cast_maker, entry_instruction_finder)) - return false; - } - break; - case Instruction::GetElementPtr: - { - // GetElementPtrConstantExpr - // OperandList[0] is base - // OperandList[1]... are indices - - FunctionValueCache get_element_pointer_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* { - Value *ptr = constant_expr->getOperand(0); - - if (ptr == old_constant) - ptr = value_maker.GetValue(function); - - std::vector<Value*> index_vector; - - unsigned operand_index; - unsigned num_operands = constant_expr->getNumOperands(); - - for (operand_index = 1; - operand_index < num_operands; - ++operand_index) - { - Value *operand = constant_expr->getOperand(operand_index); - - if (operand == old_constant) - operand = value_maker.GetValue(function); - - index_vector.push_back(operand); - } - - ArrayRef <Value*> indices(index_vector); - - return GetElementPtrInst::Create(nullptr, ptr, indices, "", llvm::cast<Instruction>(entry_instruction_finder.GetValue(function))); - }); - - if (!UnfoldConstant(constant_expr, get_element_pointer_maker, entry_instruction_finder)) - return false; - } - break; - } - } - else - { - if (log) - log->Printf("Unhandled constant type: \"%s\"", PrintValue(constant).c_str()); - return false; - } - } - else - { - if (Instruction *inst = llvm::dyn_cast<Instruction>(user)) - { - inst->replaceUsesOfWith(old_constant, value_maker.GetValue(inst->getParent()->getParent())); - } - else - { - if (log) - log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(user).c_str()); - return false; - } - } - } - - if (!isa<GlobalValue>(old_constant)) - { - old_constant->destroyConstant(); - } - - return true; -} - -bool -IRForTarget::ReplaceVariables (Function &llvm_function) -{ - if (!m_resolve_vars) - return true; - - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - m_decl_map->DoStructLayout(); - - if (log) - log->Printf("Element arrangement:"); - - uint32_t num_elements; - uint32_t element_index; - - size_t size; - lldb::offset_t alignment; - - if (!m_decl_map->GetStructInfo (num_elements, size, alignment)) - return false; - - Function::arg_iterator iter(llvm_function.getArgumentList().begin()); - - if (iter == llvm_function.getArgumentList().end()) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes no arguments (should take at least a struct pointer)"); - - return false; - } - - Argument *argument = iter; - - if (argument->getName().equals("this")) - { - ++iter; - - if (iter == llvm_function.getArgumentList().end()) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'this' argument (should take a struct pointer too)"); - - return false; - } - - argument = iter; - } - else if (argument->getName().equals("self")) - { - ++iter; - - if (iter == llvm_function.getArgumentList().end()) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' argument (should take '_cmd' and a struct pointer too)"); - - return false; - } - - if (!iter->getName().equals("_cmd")) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes '%s' after 'self' argument (should take '_cmd')", iter->getName().str().c_str()); - - return false; - } - - ++iter; - - if (iter == llvm_function.getArgumentList().end()) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' and '_cmd' arguments (should take a struct pointer too)"); - - return false; - } - - argument = iter; - } - - if (!argument->getName().equals("$__lldb_arg")) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes an argument named '%s' instead of the struct pointer", argument->getName().str().c_str()); - - return false; - } - - if (log) - log->Printf("Arg: \"%s\"", PrintValue(argument).c_str()); - - BasicBlock &entry_block(llvm_function.getEntryBlock()); - Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg()); - - if (!FirstEntryInstruction) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find the first instruction in the wrapper for use in rewriting"); - - return false; - } - - LLVMContext &context(m_module->getContext()); - IntegerType *offset_type(Type::getInt32Ty(context)); - - if (!offset_type) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Couldn't produce an offset type"); - - return false; - } - - for (element_index = 0; element_index < num_elements; ++element_index) - { - const clang::NamedDecl *decl = NULL; - Value *value = NULL; - lldb::offset_t offset; - lldb_private::ConstString name; - - if (!m_decl_map->GetStructElement (decl, value, offset, name, element_index)) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Structure information is incomplete"); - - return false; - } - - if (log) - log->Printf(" \"%s\" (\"%s\") placed at %" PRIu64, - name.GetCString(), - decl->getNameAsString().c_str(), - offset); - - if (value) - { - if (log) - log->Printf(" Replacing [%s]", PrintValue(value).c_str()); - - FunctionValueCache body_result_maker ([this, name, offset_type, offset, argument, value] (llvm::Function *function)->llvm::Value * { - // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result - // variable is an rvalue, we have to synthesize a dereference of the appropriate structure - // entry in order to produce the static variable that the AST thinks it is accessing. - - llvm::Instruction *entry_instruction = llvm::cast<Instruction>(m_entry_instruction_finder.GetValue(function)); - - ConstantInt *offset_int(ConstantInt::get(offset_type, offset, true)); - GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(nullptr, - argument, - offset_int, - "", - entry_instruction); - - if (name == m_result_name && !m_result_is_pointer) - { - BitCastInst *bit_cast = new BitCastInst(get_element_ptr, - value->getType()->getPointerTo(), - "", - entry_instruction); - - LoadInst *load = new LoadInst(bit_cast, "", entry_instruction); - - return load; - } - else - { - BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", entry_instruction); - - return bit_cast; - } - }); - - if (Constant *constant = dyn_cast<Constant>(value)) - { - UnfoldConstant(constant, body_result_maker, m_entry_instruction_finder); - } - else if (Instruction *instruction = dyn_cast<Instruction>(value)) - { - value->replaceAllUsesWith(body_result_maker.GetValue(instruction->getParent()->getParent())); - } - else - { - if (log) - log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(value).c_str()); - return false; - } - - if (GlobalVariable *var = dyn_cast<GlobalVariable>(value)) - var->eraseFromParent(); - } - } - - if (log) - log->Printf("Total structure [align %" PRId64 ", size %" PRIu64 "]", (int64_t)alignment, (uint64_t)size); - - return true; -} - -llvm::Constant * -IRForTarget::BuildRelocation(llvm::Type *type, uint64_t offset) -{ - llvm::Constant *offset_int = ConstantInt::get(m_intptr_ty, offset); - - llvm::Constant *offset_array[1]; - - offset_array[0] = offset_int; - - llvm::ArrayRef<llvm::Constant *> offsets(offset_array, 1); - llvm::Type *char_type = llvm::Type::getInt8Ty(m_module->getContext()); - llvm::Type *char_pointer_type = char_type->getPointerTo(); - - llvm::Constant *reloc_placeholder_bitcast = ConstantExpr::getBitCast(m_reloc_placeholder, char_pointer_type); - llvm::Constant *reloc_getelementptr = ConstantExpr::getGetElementPtr(char_type, reloc_placeholder_bitcast, offsets); - llvm::Constant *reloc_bitcast = ConstantExpr::getBitCast(reloc_getelementptr, type); - - return reloc_bitcast; -} - -bool -IRForTarget::CompleteDataAllocation () -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (!m_data_allocator.GetStream().GetSize()) - return true; - - lldb::addr_t allocation = m_data_allocator.Allocate(); - - if (log) - { - if (allocation) - log->Printf("Allocated static data at 0x%llx", (unsigned long long)allocation); - else - log->Printf("Failed to allocate static data"); - } - - if (!allocation || allocation == LLDB_INVALID_ADDRESS) - return false; - - Constant *relocated_addr = ConstantInt::get(m_intptr_ty, (uint64_t)allocation); - Constant *relocated_bitcast = ConstantExpr::getIntToPtr(relocated_addr, llvm::Type::getInt8PtrTy(m_module->getContext())); - - m_reloc_placeholder->replaceAllUsesWith(relocated_bitcast); - - m_reloc_placeholder->eraseFromParent(); - - return true; -} - -bool -IRForTarget::StripAllGVs (Module &llvm_module) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - std::vector<GlobalVariable *> global_vars; - std::set<GlobalVariable *>erased_vars; - - bool erased = true; - - while (erased) - { - erased = false; - - for (GlobalVariable &global_var : llvm_module.globals()) - { - global_var.removeDeadConstantUsers(); - - if (global_var.use_empty()) - { - if (log) - log->Printf("Did remove %s", - PrintValue(&global_var).c_str()); - global_var.eraseFromParent(); - erased = true; - break; - } - } - } - - for (GlobalVariable &global_var : llvm_module.globals()) - { - GlobalValue::user_iterator ui = global_var.user_begin(); - - if (log) - log->Printf("Couldn't remove %s because of %s", - PrintValue(&global_var).c_str(), - PrintValue(*ui).c_str()); - } - - return true; -} - -bool -IRForTarget::runOnModule (Module &llvm_module) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - m_module = &llvm_module; - m_target_data.reset(new DataLayout(m_module)); - m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(), m_target_data->getPointerSizeInBits()); - - if (log) - { - std::string s; - raw_string_ostream oss(s); - - m_module->print(oss, NULL); - - oss.flush(); - - log->Printf("Module as passed in to IRForTarget: \n\"%s\"", s.c_str()); - } - - Function* main_function = m_module->getFunction(StringRef(m_func_name.c_str())); - - if (!main_function) - { - if (log) - log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str()); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module", m_func_name.c_str()); - - return false; - } - - if (!FixFunctionLinkage (*main_function)) - { - if (log) - log->Printf("Couldn't fix the linkage for the function"); - - return false; - } - - llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext()); - - m_reloc_placeholder = new llvm::GlobalVariable((*m_module), - int8_ty, - false /* IsConstant */, - GlobalVariable::InternalLinkage, - Constant::getNullValue(int8_ty), - "reloc_placeholder", - NULL /* InsertBefore */, - GlobalVariable::NotThreadLocal /* ThreadLocal */, - 0 /* AddressSpace */); - - //////////////////////////////////////////////////////////// - // Replace $__lldb_expr_result with a persistent variable - // - - if (!CreateResultVariable(*main_function)) - { - if (log) - log->Printf("CreateResultVariable() failed"); - - // CreateResultVariable() reports its own errors, so we don't do so here - - return false; - } - - if (log && log->GetVerbose()) - { - std::string s; - raw_string_ostream oss(s); - - m_module->print(oss, NULL); - - oss.flush(); - - log->Printf("Module after creating the result variable: \n\"%s\"", s.c_str()); - } - - for (Module::iterator fi = m_module->begin(), fe = m_module->end(); - fi != fe; - ++fi) - { - llvm::Function *function = fi; - - if (function->begin() == function->end()) - continue; - - Function::iterator bbi; - - for (bbi = function->begin(); - bbi != function->end(); - ++bbi) - { - if (!RemoveGuards(*bbi)) - { - if (log) - log->Printf("RemoveGuards() failed"); - - // RemoveGuards() reports its own errors, so we don't do so here - - return false; - } - - if (!RewritePersistentAllocs(*bbi)) - { - if (log) - log->Printf("RewritePersistentAllocs() failed"); - - // RewritePersistentAllocs() reports its own errors, so we don't do so here - - return false; - } - - if (!RemoveCXAAtExit(*bbi)) - { - if (log) - log->Printf("RemoveCXAAtExit() failed"); - - // RemoveCXAAtExit() reports its own errors, so we don't do so here - - return false; - } - } - } - - /////////////////////////////////////////////////////////////////////////////// - // Fix all Objective-C constant strings to use NSStringWithCString:encoding: - // - - if (!RewriteObjCConstStrings()) - { - if (log) - log->Printf("RewriteObjCConstStrings() failed"); - - // RewriteObjCConstStrings() reports its own errors, so we don't do so here - - return false; - } - - /////////////////////////////// - // Resolve function pointers - // - - if (!ResolveFunctionPointers(llvm_module)) - { - if (log) - log->Printf("ResolveFunctionPointers() failed"); - - // ResolveFunctionPointers() reports its own errors, so we don't do so here - - return false; - } - - for (Module::iterator fi = m_module->begin(), fe = m_module->end(); - fi != fe; - ++fi) - { - llvm::Function *function = fi; - - for (llvm::Function::iterator bbi = function->begin(), bbe = function->end(); - bbi != bbe; - ++bbi) - { - if (!RewriteObjCSelectors(*bbi)) - { - if (log) - log->Printf("RewriteObjCSelectors() failed"); - - // RewriteObjCSelectors() reports its own errors, so we don't do so here - - return false; - } - } - } - - for (Module::iterator fi = m_module->begin(), fe = m_module->end(); - fi != fe; - ++fi) - { - llvm::Function *function = fi; - - for (llvm::Function::iterator bbi = function->begin(), bbe = function->end(); - bbi != bbe; - ++bbi) - { - if (!ResolveCalls(*bbi)) - { - if (log) - log->Printf("ResolveCalls() failed"); - - // ResolveCalls() reports its own errors, so we don't do so here - - return false; - } - - if (!ReplaceStaticLiterals(*bbi)) - { - if (log) - log->Printf("ReplaceStaticLiterals() failed"); - - return false; - } - } - } - - //////////////////////////////////////////////////////////////////////// - // Run function-level passes that only make sense on the main function - // - - if (!ResolveExternals(*main_function)) - { - if (log) - log->Printf("ResolveExternals() failed"); - - // ResolveExternals() reports its own errors, so we don't do so here - - return false; - } - - if (!ReplaceVariables(*main_function)) - { - if (log) - log->Printf("ReplaceVariables() failed"); - - // ReplaceVariables() reports its own errors, so we don't do so here - - return false; - } - - if (!ReplaceStrings()) - { - if (log) - log->Printf("ReplaceStrings() failed"); - - return false; - } - - if (!CompleteDataAllocation()) - { - if (log) - log->Printf("CompleteDataAllocation() failed"); - - return false; - } - - if (!StripAllGVs(llvm_module)) - { - if (log) - log->Printf("StripAllGVs() failed"); - } - - if (log && log->GetVerbose()) - { - std::string s; - raw_string_ostream oss(s); - - m_module->print(oss, NULL); - - oss.flush(); - - log->Printf("Module after preparing for execution: \n\"%s\"", s.c_str()); - } - - return true; -} - -void -IRForTarget::assignPassManager (PMStack &pass_mgr_stack, PassManagerType pass_mgr_type) -{ -} - -PassManagerType -IRForTarget::getPotentialPassManagerType() const -{ - return PMT_ModulePassManager; -} |