//===-- IRExecutionUnit.cpp -------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"

#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Utility/LLDBAssert.h"

#include "lldb/../../source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"

using namespace lldb_private;

IRExecutionUnit::IRExecutionUnit (std::unique_ptr<llvm::LLVMContext> &context_ap,
                                  std::unique_ptr<llvm::Module> &module_ap,
                                  ConstString &name,
                                  const lldb::TargetSP &target_sp,
                                  const SymbolContext &sym_ctx,
                                  std::vector<std::string> &cpu_features) :
    IRMemoryMap(target_sp),
    m_context_ap(context_ap.release()),
    m_module_ap(module_ap.release()),
    m_module(m_module_ap.get()),
    m_cpu_features(cpu_features),
    m_name(name),
    m_sym_ctx(sym_ctx),
    m_did_jit(false),
    m_function_load_addr(LLDB_INVALID_ADDRESS),
    m_function_end_load_addr(LLDB_INVALID_ADDRESS),
    m_reported_allocations(false)
{
}

lldb::addr_t
IRExecutionUnit::WriteNow (const uint8_t *bytes,
                           size_t size,
                           Error &error)
{
    const bool zero_memory = false;
    lldb::addr_t allocation_process_addr = Malloc (size,
                                                   8,
                                                   lldb::ePermissionsWritable | lldb::ePermissionsReadable,
                                                   eAllocationPolicyMirror,
                                                   zero_memory,
                                                   error);

    if (!error.Success())
        return LLDB_INVALID_ADDRESS;

    WriteMemory(allocation_process_addr, bytes, size, error);

    if (!error.Success())
    {
        Error err;
        Free (allocation_process_addr, err);

        return LLDB_INVALID_ADDRESS;
    }

    if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
    {
        DataBufferHeap my_buffer(size, 0);
        Error err;
        ReadMemory(my_buffer.GetBytes(), allocation_process_addr, size, err);

        if (err.Success())
        {
            DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8);
            my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), allocation_process_addr, 16, DataExtractor::TypeUInt8);
        }
    }

    return allocation_process_addr;
}

void
IRExecutionUnit::FreeNow (lldb::addr_t allocation)
{
    if (allocation == LLDB_INVALID_ADDRESS)
        return;

    Error err;

    Free(allocation, err);
}

Error
IRExecutionUnit::DisassembleFunction (Stream &stream,
                                      lldb::ProcessSP &process_wp)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    ExecutionContext exe_ctx(process_wp);

    Error ret;

    ret.Clear();

    lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
    lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;

    for (JittedFunction &function : m_jitted_functions)
    {
        if (function.m_name == m_name)
        {
            func_local_addr = function.m_local_addr;
            func_remote_addr = function.m_remote_addr;
        }
    }

    if (func_local_addr == LLDB_INVALID_ADDRESS)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", m_name.AsCString());
        return ret;
    }

    if (log)
        log->Printf("Found function, has local address 0x%" PRIx64 " and remote address 0x%" PRIx64, (uint64_t)func_local_addr, (uint64_t)func_remote_addr);

    std::pair <lldb::addr_t, lldb::addr_t> func_range;

    func_range = GetRemoteRangeForLocal(func_local_addr);

    if (func_range.first == 0 && func_range.second == 0)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find code range for function %s", m_name.AsCString());
        return ret;
    }

    if (log)
        log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", func_range.first, func_range.second);

    Target *target = exe_ctx.GetTargetPtr();
    if (!target)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the target");
        return ret;
    }

    lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0));

    Process *process = exe_ctx.GetProcessPtr();
    Error err;
    process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);

    if (!err.Success())
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
        return ret;
    }

    ArchSpec arch(target->GetArchitecture());

    const char *plugin_name = NULL;
    const char *flavor_string = NULL;
    lldb::DisassemblerSP disassembler_sp = Disassembler::FindPlugin(arch, flavor_string, plugin_name);

    if (!disassembler_sp)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName());
        return ret;
    }

    if (!process)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the process");
        return ret;
    }

    DataExtractor extractor(buffer_sp,
                            process->GetByteOrder(),
                            target->GetArchitecture().GetAddressByteSize());

    if (log)
    {
        log->Printf("Function data has contents:");
        extractor.PutToLog (log,
                            0,
                            extractor.GetByteSize(),
                            func_remote_addr,
                            16,
                            DataExtractor::TypeUInt8);
    }

    disassembler_sp->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false, false);

    InstructionList &instruction_list = disassembler_sp->GetInstructionList();
    instruction_list.Dump(&stream, true, true, &exe_ctx);
    return ret;
}

static void ReportInlineAsmError(const llvm::SMDiagnostic &diagnostic, void *Context, unsigned LocCookie)
{
    Error *err = static_cast<Error*>(Context);

    if (err && err->Success())
    {
        err->SetErrorToGenericError();
        err->SetErrorStringWithFormat("Inline assembly error: %s", diagnostic.getMessage().str().c_str());
    }
}

void
IRExecutionUnit::ReportSymbolLookupError(const ConstString &name)
{
    m_failed_lookups.push_back(name);
}

void
IRExecutionUnit::GetRunnableInfo(Error &error,
                                 lldb::addr_t &func_addr,
                                 lldb::addr_t &func_end)
{
    lldb::ProcessSP process_sp(GetProcessWP().lock());

    static std::recursive_mutex s_runnable_info_mutex;

    func_addr = LLDB_INVALID_ADDRESS;
    func_end = LLDB_INVALID_ADDRESS;

    if (!process_sp)
    {
        error.SetErrorToGenericError();
        error.SetErrorString("Couldn't write the JIT compiled code into the process because the process is invalid");
        return;
    }

    if (m_did_jit)
    {
        func_addr = m_function_load_addr;
        func_end = m_function_end_load_addr;

        return;
    };

    std::lock_guard<std::recursive_mutex> guard(s_runnable_info_mutex);

    m_did_jit = true;

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    std::string error_string;

    if (log)
    {
        std::string s;
        llvm::raw_string_ostream oss(s);

        m_module->print(oss, NULL);

        oss.flush();

        log->Printf ("Module being sent to JIT: \n%s", s.c_str());
    }

    llvm::Triple triple(m_module->getTargetTriple());
    llvm::Reloc::Model relocModel;
    llvm::CodeModel::Model codeModel;

    if (triple.isOSBinFormatELF())
    {
        relocModel = llvm::Reloc::Static;
    }
    else
    {
        relocModel = llvm::Reloc::PIC_;
    }

    // This will be small for 32-bit and large for 64-bit.
    codeModel = llvm::CodeModel::JITDefault;

    m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error);

    llvm::EngineBuilder builder(std::move(m_module_ap));

    builder.setEngineKind(llvm::EngineKind::JIT)
    .setErrorStr(&error_string)
    .setRelocationModel(relocModel)
    .setMCJITMemoryManager(std::unique_ptr<MemoryManager>(new MemoryManager(*this)))
    .setCodeModel(codeModel)
    .setOptLevel(llvm::CodeGenOpt::Less);

    llvm::StringRef mArch;
    llvm::StringRef mCPU;
    llvm::SmallVector<std::string, 0> mAttrs;

    for (std::string &feature : m_cpu_features)
        mAttrs.push_back(feature);

    llvm::TargetMachine *target_machine = builder.selectTarget(triple,
                                                               mArch,
                                                               mCPU,
                                                               mAttrs);

    m_execution_engine_ap.reset(builder.create(target_machine));

    m_strip_underscore = (m_execution_engine_ap->getDataLayout().getGlobalPrefix() == '_');

    if (!m_execution_engine_ap.get())
    {
        error.SetErrorToGenericError();
        error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
        return;
    }

    // Make sure we see all sections, including ones that don't have relocations...
    m_execution_engine_ap->setProcessAllSections(true);

    m_execution_engine_ap->DisableLazyCompilation();

    for (llvm::Function &function : *m_module)
    {
        if (function.isDeclaration() || function.hasPrivateLinkage())
            continue;
        
        const bool external = function.hasExternalLinkage() || function.hasLinkOnceODRLinkage();
        
        void *fun_ptr = m_execution_engine_ap->getPointerToFunction(&function);
        
        if (!error.Success())
        {
            // We got an error through our callback!
            return;
        }
        
        if (!fun_ptr)
        {
            error.SetErrorToGenericError();
            error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", function.getName().str().c_str());
            return;
        }
        m_jitted_functions.push_back (JittedFunction(function.getName().str().c_str(), external, (lldb::addr_t)fun_ptr));
    }

    CommitAllocations(process_sp);
    ReportAllocations(*m_execution_engine_ap);
    
    // We have to do this after calling ReportAllocations because for the MCJIT, getGlobalValueAddress
    // will cause the JIT to perform all relocations.  That can only be done once, and has to happen
    // after we do the remapping from local -> remote.
    // That means we don't know the local address of the Variables, but we don't need that for anything,
    // so that's okay.
    
    std::function<void (llvm::GlobalValue &)> RegisterOneValue = [this] (llvm::GlobalValue &val) {
        if (val.hasExternalLinkage() && !val.isDeclaration())
        {
            uint64_t var_ptr_addr = m_execution_engine_ap->getGlobalValueAddress(val.getName().str());
            
            lldb::addr_t remote_addr = GetRemoteAddressForLocal(var_ptr_addr);
            
            // This is a really unfortunae API that sometimes returns local addresses and sometimes returns remote addresses, based on whether
            // the variable was relocated during ReportAllocations or not.
            
            if (remote_addr == LLDB_INVALID_ADDRESS)
            {
                remote_addr = var_ptr_addr;
            }
                
            if (var_ptr_addr != 0)
                m_jitted_global_variables.push_back (JittedGlobalVariable (val.getName().str().c_str(), LLDB_INVALID_ADDRESS, remote_addr));
        }
    };
    
    for (llvm::GlobalVariable &global_var : m_module->getGlobalList())
    {
        RegisterOneValue(global_var);
    }
    
    for (llvm::GlobalAlias &global_alias : m_module->getAliasList())
    {
        RegisterOneValue(global_alias);
    }

    WriteData(process_sp);

    if (m_failed_lookups.size())
    {
        StreamString ss;

        ss.PutCString("Couldn't lookup symbols:\n");

        bool emitNewLine = false;

        for (const ConstString &failed_lookup : m_failed_lookups)
        {
            if (emitNewLine)
                ss.PutCString("\n");
            emitNewLine = true;
            ss.PutCString("  ");
            ss.PutCString(Mangled(failed_lookup).GetDemangledName(lldb::eLanguageTypeObjC_plus_plus).AsCString());
        }

        m_failed_lookups.clear();

        error.SetErrorString(ss.GetData());

        return;
    }

    m_function_load_addr = LLDB_INVALID_ADDRESS;
    m_function_end_load_addr = LLDB_INVALID_ADDRESS;

    for (JittedFunction &jitted_function : m_jitted_functions)
    {
        jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr);

        if (!m_name.IsEmpty() && jitted_function.m_name == m_name)
        {
            AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr);
            m_function_end_load_addr = func_range.first + func_range.second;
            m_function_load_addr = jitted_function.m_remote_addr;
        }
    }

    if (log)
    {
        log->Printf("Code can be run in the target.");

        StreamString disassembly_stream;

        Error err = DisassembleFunction(disassembly_stream, process_sp);

        if (!err.Success())
        {
            log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
        }
        else
        {
            log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
        }

        log->Printf("Sections: ");
        for (AllocationRecord &record : m_records)
        {
            if (record.m_process_address != LLDB_INVALID_ADDRESS)
            {
                record.dump(log);

                DataBufferHeap my_buffer(record.m_size, 0);
                Error err;
                ReadMemory(my_buffer.GetBytes(), record.m_process_address, record.m_size, err);

                if (err.Success())
                {
                    DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8);
                    my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), record.m_process_address, 16, DataExtractor::TypeUInt8);
                }
            }
            else
            {
                record.dump(log);

                DataExtractor my_extractor ((const void*)record.m_host_address, record.m_size, lldb::eByteOrderBig, 8);
                my_extractor.PutToLog(log, 0, record.m_size, record.m_host_address, 16, DataExtractor::TypeUInt8);
            }
        }
    }

    func_addr = m_function_load_addr;
    func_end = m_function_end_load_addr;

    return;
}

IRExecutionUnit::~IRExecutionUnit ()
{
    m_module_ap.reset();
    m_execution_engine_ap.reset();
    m_context_ap.reset();
}

IRExecutionUnit::MemoryManager::MemoryManager (IRExecutionUnit &parent) :
    m_default_mm_ap (new llvm::SectionMemoryManager()),
    m_parent (parent)
{
}

IRExecutionUnit::MemoryManager::~MemoryManager ()
{
}

lldb::SectionType
IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRExecutionUnit::AllocationKind alloc_kind)
{
    lldb::SectionType sect_type = lldb::eSectionTypeCode;
    switch (alloc_kind)
    {
        case AllocationKind::Stub:  sect_type = lldb::eSectionTypeCode; break;
        case AllocationKind::Code:  sect_type = lldb::eSectionTypeCode; break;
        case AllocationKind::Data:  sect_type = lldb::eSectionTypeData; break;
        case AllocationKind::Global:sect_type = lldb::eSectionTypeData; break;
        case AllocationKind::Bytes: sect_type = lldb::eSectionTypeOther; break;
    }

    if (!name.empty())
    {
        if (name.equals("__text") || name.equals(".text"))
            sect_type = lldb::eSectionTypeCode;
        else if (name.equals("__data") || name.equals(".data"))
            sect_type = lldb::eSectionTypeCode;
        else if (name.startswith("__debug_") || name.startswith(".debug_"))
        {
            const uint32_t name_idx = name[0] == '_' ? 8 : 7;
            llvm::StringRef dwarf_name(name.substr(name_idx));
            switch (dwarf_name[0])
            {
                case 'a':
                    if (dwarf_name.equals("abbrev"))
                        sect_type = lldb::eSectionTypeDWARFDebugAbbrev;
                    else if (dwarf_name.equals("aranges"))
                        sect_type = lldb::eSectionTypeDWARFDebugAranges;
                    else if (dwarf_name.equals("addr"))
                        sect_type = lldb::eSectionTypeDWARFDebugAddr;
                    break;

                case 'f':
                    if (dwarf_name.equals("frame"))
                        sect_type = lldb::eSectionTypeDWARFDebugFrame;
                    break;

                case 'i':
                    if (dwarf_name.equals("info"))
                        sect_type = lldb::eSectionTypeDWARFDebugInfo;
                    break;

                case 'l':
                    if (dwarf_name.equals("line"))
                        sect_type = lldb::eSectionTypeDWARFDebugLine;
                    else if (dwarf_name.equals("loc"))
                        sect_type = lldb::eSectionTypeDWARFDebugLoc;
                    break;

                case 'm':
                    if (dwarf_name.equals("macinfo"))
                        sect_type = lldb::eSectionTypeDWARFDebugMacInfo;
                    break;

                case 'p':
                    if (dwarf_name.equals("pubnames"))
                        sect_type = lldb::eSectionTypeDWARFDebugPubNames;
                    else if (dwarf_name.equals("pubtypes"))
                        sect_type = lldb::eSectionTypeDWARFDebugPubTypes;
                    break;

                case 's':
                    if (dwarf_name.equals("str"))
                        sect_type = lldb::eSectionTypeDWARFDebugStr;
                    else if (dwarf_name.equals("str_offsets"))
                        sect_type = lldb::eSectionTypeDWARFDebugStrOffsets;
                    break;

                case 'r':
                    if (dwarf_name.equals("ranges"))
                        sect_type = lldb::eSectionTypeDWARFDebugRanges;
                    break;

                default:
                    break;
            }
        }
        else if (name.startswith("__apple_") || name.startswith(".apple_"))
        {
#if 0
            const uint32_t name_idx = name[0] == '_' ? 8 : 7;
            llvm::StringRef apple_name(name.substr(name_idx));
            switch (apple_name[0])
            {
                case 'n':
                    if (apple_name.equals("names"))
                        sect_type = lldb::eSectionTypeDWARFAppleNames;
                    else if (apple_name.equals("namespac") || apple_name.equals("namespaces"))
                        sect_type = lldb::eSectionTypeDWARFAppleNamespaces;
                    break;
                case 't':
                    if (apple_name.equals("types"))
                        sect_type = lldb::eSectionTypeDWARFAppleTypes;
                    break;
                case 'o':
                    if (apple_name.equals("objc"))
                        sect_type = lldb::eSectionTypeDWARFAppleObjC;
                    break;
                default:
                    break;
            }
#else
            sect_type = lldb::eSectionTypeInvalid;
#endif
        }
        else if (name.equals("__objc_imageinfo"))
            sect_type = lldb::eSectionTypeOther;
    }
    return sect_type;
}

uint8_t *
IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size,
                                                    unsigned Alignment,
                                                    unsigned SectionID,
                                                    llvm::StringRef SectionName)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID, SectionName);

    m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
                                                  lldb::ePermissionsReadable | lldb::ePermissionsExecutable,
                                                  GetSectionTypeFromSectionName (SectionName, AllocationKind::Code),
                                                  Size,
                                                  Alignment,
                                                  SectionID,
                                                  SectionName.str().c_str()));

    if (log)
    {
        log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
                    (uint64_t)Size, Alignment, SectionID, (void *)return_value);
    }
    
    if (m_parent.m_reported_allocations)
    {
        Error err;
        lldb::ProcessSP process_sp = m_parent.GetBestExecutionContextScope()->CalculateProcess();
        
        m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back());
    }

    return return_value;
}

uint8_t *
IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size,
                                                    unsigned Alignment,
                                                    unsigned SectionID,
                                                    llvm::StringRef SectionName,
                                                    bool IsReadOnly)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, SectionName, IsReadOnly);

    uint32_t permissions = lldb::ePermissionsReadable;
    if (!IsReadOnly)
        permissions |= lldb::ePermissionsWritable;
    m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
                                                  permissions,
                                                  GetSectionTypeFromSectionName (SectionName, AllocationKind::Data),
                                                  Size,
                                                  Alignment,
                                                  SectionID,
                                                  SectionName.str().c_str()));
    if (log)
    {
        log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
                    (uint64_t)Size, Alignment, SectionID, (void *)return_value);
    }
    
    if (m_parent.m_reported_allocations)
    {
        Error err;
        lldb::ProcessSP process_sp = m_parent.GetBestExecutionContextScope()->CalculateProcess();
        
        m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back());
    }

    return return_value;
}

static ConstString
FindBestAlternateMangledName(const ConstString &demangled,
                             const lldb::LanguageType &lang_type,
                             const SymbolContext &sym_ctx)
{
    CPlusPlusLanguage::MethodName cpp_name(demangled);
    std::string scope_qualified_name = cpp_name.GetScopeQualifiedName();

    if (!scope_qualified_name.size())
        return ConstString();

    if (!sym_ctx.module_sp)
        return ConstString();

    SymbolVendor *sym_vendor = sym_ctx.module_sp->GetSymbolVendor();
    if (!sym_vendor)
        return ConstString();

    lldb_private::SymbolFile *sym_file = sym_vendor->GetSymbolFile();
    if (!sym_file)
        return ConstString();

    std::vector<ConstString> alternates;
    sym_file->GetMangledNamesForFunction(scope_qualified_name, alternates);

    std::vector<ConstString> param_and_qual_matches;
    std::vector<ConstString> param_matches;
    for (size_t i = 0; i < alternates.size(); i++)
    {
        ConstString alternate_mangled_name = alternates[i];
        Mangled mangled(alternate_mangled_name, true);
        ConstString demangled = mangled.GetDemangledName(lang_type);

        CPlusPlusLanguage::MethodName alternate_cpp_name(demangled);
        if (!cpp_name.IsValid())
            continue;

        if (alternate_cpp_name.GetArguments() == cpp_name.GetArguments())
        {
            if (alternate_cpp_name.GetQualifiers() == cpp_name.GetQualifiers())
                param_and_qual_matches.push_back(alternate_mangled_name);
            else
                param_matches.push_back(alternate_mangled_name);
        }
    }

    if (param_and_qual_matches.size())
        return param_and_qual_matches[0]; // It is assumed that there will be only one!
    else if (param_matches.size())
        return param_matches[0]; // Return one of them as a best match
    else
        return ConstString();
}

struct IRExecutionUnit::SearchSpec
{
    ConstString name;
    uint32_t    mask;

    SearchSpec(ConstString n, uint32_t m = lldb::eFunctionNameTypeFull) :
        name(n),
        mask(m)
    {
    }
};

void
IRExecutionUnit::CollectCandidateCNames(std::vector<IRExecutionUnit::SearchSpec> &C_specs, const ConstString &name)
{
    if (m_strip_underscore && name.AsCString()[0] == '_')
        C_specs.insert(C_specs.begin(), ConstString(&name.AsCString()[1]));
    C_specs.push_back(SearchSpec(name));
}

void
IRExecutionUnit::CollectCandidateCPlusPlusNames(std::vector<IRExecutionUnit::SearchSpec> &CPP_specs, const std::vector<SearchSpec> &C_specs, const SymbolContext &sc)
{
    for (const SearchSpec &C_spec : C_specs)
    {
        const ConstString &name = C_spec.name;

        if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString()))
        {
            Mangled mangled(name, true);
            ConstString demangled = mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus);

            if (demangled)
            {
                ConstString best_alternate_mangled_name = FindBestAlternateMangledName(demangled, lldb::eLanguageTypeC_plus_plus, sc);

                if (best_alternate_mangled_name)
                {
                    CPP_specs.push_back(best_alternate_mangled_name);
                }

                CPP_specs.push_back(SearchSpec(demangled, lldb::eFunctionNameTypeFull));
            }
        }

        // Maybe we're looking for a const symbol but the debug info told us it was const...
        if (!strncmp(name.GetCString(), "_ZN", 3) &&
            strncmp(name.GetCString(), "_ZNK", 4))
        {
            std::string fixed_scratch("_ZNK");
            fixed_scratch.append(name.GetCString() + 3);
            CPP_specs.push_back(ConstString(fixed_scratch.c_str()));
        }

        // Maybe we're looking for a static symbol but we thought it was global...
        if (!strncmp(name.GetCString(), "_Z", 2) &&
            strncmp(name.GetCString(), "_ZL", 3))
        {
            std::string fixed_scratch("_ZL");
            fixed_scratch.append(name.GetCString() + 2);
            CPP_specs.push_back(ConstString(fixed_scratch.c_str()));
        }

    }
}

void
IRExecutionUnit::CollectFallbackNames(std::vector<SearchSpec> &fallback_specs,
                                      const std::vector<SearchSpec> &C_specs)
{
    // As a last-ditch fallback, try the base name for C++ names.  It's terrible,
    // but the DWARF doesn't always encode "extern C" correctly.
    
    for (const SearchSpec &C_spec : C_specs)
    {
        const ConstString &name = C_spec.name;
        
        if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString()))
        {
            Mangled mangled_name(name);
            ConstString demangled_name = mangled_name.GetDemangledName(lldb::eLanguageTypeC_plus_plus);
            if (!demangled_name.IsEmpty())
            {
                const char *demangled_cstr = demangled_name.AsCString();
                const char *lparen_loc = strchr(demangled_cstr, '(');
                if (lparen_loc)
                {
                    llvm::StringRef base_name(demangled_cstr, lparen_loc-demangled_cstr);
                    fallback_specs.push_back(ConstString(base_name));
                }
            }
        }
    }
}


lldb::addr_t
IRExecutionUnit::FindInSymbols(const std::vector<IRExecutionUnit::SearchSpec> &specs, const lldb_private::SymbolContext &sc)
{
    Target *target = sc.target_sp.get();

    if (!target)
    {
        // we shouldn't be doing any symbol lookup at all without a target
        return LLDB_INVALID_ADDRESS;
    }

    for (const SearchSpec &spec : specs)
    {
        SymbolContextList sc_list;

        lldb::addr_t best_internal_load_address = LLDB_INVALID_ADDRESS;

        std::function<bool (lldb::addr_t &, SymbolContextList &, const lldb_private::SymbolContext &)> get_external_load_address =
            [&best_internal_load_address, target](lldb::addr_t &load_address,
                                                  SymbolContextList &sc_list,
                                                  const lldb_private::SymbolContext &sc) -> lldb::addr_t
        {
            load_address = LLDB_INVALID_ADDRESS;

            for (size_t si = 0, se = sc_list.GetSize(); si < se; ++si)
            {
                SymbolContext candidate_sc;

                sc_list.GetContextAtIndex(si, candidate_sc);

                const bool is_external = (candidate_sc.function) ||
                                         (candidate_sc.symbol && candidate_sc.symbol->IsExternal());
                if (candidate_sc.symbol)
                {
                    load_address = candidate_sc.symbol->ResolveCallableAddress(*target);

                    if (load_address == LLDB_INVALID_ADDRESS)
                    {
                        if (target->GetProcessSP())
                            load_address = candidate_sc.symbol->GetAddress().GetLoadAddress(target);
                        else
                            load_address = candidate_sc.symbol->GetAddress().GetFileAddress();
                    }
                }

                if (load_address == LLDB_INVALID_ADDRESS && candidate_sc.function)
                {
                        if (target->GetProcessSP())
                            load_address = candidate_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(target);
                        else
                            load_address = candidate_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
                }

                if (load_address != LLDB_INVALID_ADDRESS)
                {
                    if (is_external)
                    {
                        return true;
                    }
                    else if (best_internal_load_address == LLDB_INVALID_ADDRESS)
                    {
                        best_internal_load_address = load_address;
                        load_address = LLDB_INVALID_ADDRESS;
                    }
                }
            }

            return false;
        };

        if (sc.module_sp)
        {
            sc.module_sp->FindFunctions(spec.name,
                                        NULL,
                                        spec.mask,
                                        true,  // include_symbols
                                        false, // include_inlines
                                        true,  // append
                                        sc_list);
        }

        lldb::addr_t load_address = LLDB_INVALID_ADDRESS;

        if (get_external_load_address(load_address, sc_list, sc))
        {
            return load_address;
        }
        else
        {
            sc_list.Clear();
        }

        if (sc_list.GetSize() == 0 && sc.target_sp)
        {
            sc.target_sp->GetImages().FindFunctions(spec.name,
                                                    spec.mask,
                                                    true,  // include_symbols
                                                    false, // include_inlines
                                                    true,  // append
                                                    sc_list);
        }

        if (get_external_load_address(load_address, sc_list, sc))
        {
            return load_address;
        }
        else
        {
            sc_list.Clear();
        }

        if (sc_list.GetSize() == 0 && sc.target_sp)
        {
            sc.target_sp->GetImages().FindSymbolsWithNameAndType(spec.name, lldb::eSymbolTypeAny, sc_list);
        }

        if (get_external_load_address(load_address, sc_list, sc))
        {
            return load_address;
        }
        // if there are any searches we try after this, add an sc_list.Clear() in an "else" clause here

        if (best_internal_load_address != LLDB_INVALID_ADDRESS)
        {
            return best_internal_load_address;
        }
    }

    return LLDB_INVALID_ADDRESS;
}

lldb::addr_t
IRExecutionUnit::FindInRuntimes(const std::vector<SearchSpec> &specs, const lldb_private::SymbolContext &sc)
{
    lldb::TargetSP target_sp = sc.target_sp;

    if (!target_sp)
    {
        return LLDB_INVALID_ADDRESS;
    }

    lldb::ProcessSP process_sp = sc.target_sp->GetProcessSP();

    if (!process_sp)
    {
        return LLDB_INVALID_ADDRESS;
    }

    ObjCLanguageRuntime *runtime = process_sp->GetObjCLanguageRuntime();

    if (runtime)
    {
        for (const SearchSpec &spec : specs)
        {
            lldb::addr_t symbol_load_addr = runtime->LookupRuntimeSymbol(spec.name);

            if (symbol_load_addr != LLDB_INVALID_ADDRESS)
                return symbol_load_addr;
        }
    }

    return LLDB_INVALID_ADDRESS;
}

lldb::addr_t
IRExecutionUnit::FindInUserDefinedSymbols(const std::vector<SearchSpec> &specs, const lldb_private::SymbolContext &sc)
{
    lldb::TargetSP target_sp = sc.target_sp;
    
    for (const SearchSpec &spec : specs)
    {
        lldb::addr_t symbol_load_addr = target_sp->GetPersistentSymbol(spec.name);
        
        if (symbol_load_addr != LLDB_INVALID_ADDRESS)
            return symbol_load_addr;
    }
    
    return LLDB_INVALID_ADDRESS;
}

lldb::addr_t
IRExecutionUnit::FindSymbol(const lldb_private::ConstString &name)
{
    std::vector<SearchSpec> candidate_C_names;
    std::vector<SearchSpec> candidate_CPlusPlus_names;

    CollectCandidateCNames(candidate_C_names, name);

    lldb::addr_t ret = FindInSymbols(candidate_C_names, m_sym_ctx);
    if (ret == LLDB_INVALID_ADDRESS)
        ret = FindInRuntimes(candidate_C_names, m_sym_ctx);

    if (ret == LLDB_INVALID_ADDRESS)
        ret = FindInUserDefinedSymbols(candidate_C_names, m_sym_ctx);

    if (ret == LLDB_INVALID_ADDRESS)
    {
        CollectCandidateCPlusPlusNames(candidate_CPlusPlus_names, candidate_C_names, m_sym_ctx);
        ret = FindInSymbols(candidate_CPlusPlus_names, m_sym_ctx);
    }
    
    if (ret == LLDB_INVALID_ADDRESS)
    {
        std::vector<SearchSpec> candidate_fallback_names;

        CollectFallbackNames(candidate_fallback_names, candidate_C_names);
        ret = FindInSymbols(candidate_fallback_names, m_sym_ctx);
    }

    return ret;
}

void
IRExecutionUnit::GetStaticInitializers(std::vector <lldb::addr_t> &static_initializers)
{
    if (llvm::GlobalVariable *global_ctors = m_module->getNamedGlobal("llvm.global_ctors"))
    {
        if (llvm::ConstantArray *ctor_array = llvm::dyn_cast<llvm::ConstantArray>(global_ctors->getInitializer()))
        {
            for (llvm::Use &ctor_use : ctor_array->operands())
            {
                if (llvm::ConstantStruct *ctor_struct = llvm::dyn_cast<llvm::ConstantStruct>(ctor_use))
                {
                    lldbassert(ctor_struct->getNumOperands() == 3); // this is standardized
                    if (llvm::Function *ctor_function = llvm::dyn_cast<llvm::Function>(ctor_struct->getOperand(1)))
                    {
                        ctor_function->dump();

                        ConstString ctor_function_name_cs(ctor_function->getName().str());
                        
                        for (JittedFunction &jitted_function : m_jitted_functions)
                        {
                            if (ctor_function_name_cs == jitted_function.m_name)
                            {
                                if (jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS)
                                {
                                    static_initializers.push_back(jitted_function.m_remote_addr);
                                }
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
}

uint64_t
IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    ConstString name_cs(Name.c_str());

    lldb::addr_t ret = m_parent.FindSymbol(name_cs);

    if (ret == LLDB_INVALID_ADDRESS)
    {
        if (log)
            log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = <not found>",
                        Name.c_str());

        m_parent.ReportSymbolLookupError(name_cs);
        return 0xbad0bad0;
    }
    else
    {
        if (log)
            log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64,
                        Name.c_str(),
                        ret);
        return ret;
    }
}

void *
IRExecutionUnit::MemoryManager::getPointerToNamedFunction(const std::string &Name,
                                                          bool AbortOnFailure) {
    assert (sizeof(void *) == 8);

    return (void*)getSymbolAddress(Name);
}

lldb::addr_t
IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    for (AllocationRecord &record : m_records)
    {
        if (local_address >= record.m_host_address &&
            local_address < record.m_host_address + record.m_size)
        {
            if (record.m_process_address == LLDB_INVALID_ADDRESS)
                return LLDB_INVALID_ADDRESS;

            lldb::addr_t ret = record.m_process_address + (local_address - record.m_host_address);

            if (log)
            {
                log->Printf("IRExecutionUnit::GetRemoteAddressForLocal() found 0x%" PRIx64 " in [0x%" PRIx64 "..0x%" PRIx64 "], and returned 0x%" PRIx64 " from [0x%" PRIx64 "..0x%" PRIx64 "].",
                            local_address,
                            (uint64_t)record.m_host_address,
                            (uint64_t)record.m_host_address + (uint64_t)record.m_size,
                            ret,
                            record.m_process_address,
                            record.m_process_address + record.m_size);
            }

            return ret;
        }
    }

    return LLDB_INVALID_ADDRESS;
}

IRExecutionUnit::AddrRange
IRExecutionUnit::GetRemoteRangeForLocal (lldb::addr_t local_address)
{
    for (AllocationRecord &record : m_records)
    {
        if (local_address >= record.m_host_address &&
            local_address < record.m_host_address + record.m_size)
        {
            if (record.m_process_address == LLDB_INVALID_ADDRESS)
                return AddrRange(0, 0);

            return AddrRange(record.m_process_address, record.m_size);
        }
    }

    return AddrRange (0, 0);
}

bool
IRExecutionUnit::CommitOneAllocation (lldb::ProcessSP &process_sp,
                                      Error &error,
                                      AllocationRecord &record)
{
    if (record.m_process_address != LLDB_INVALID_ADDRESS)
    {
        return true;
    }
    
    switch (record.m_sect_type)
    {
        case lldb::eSectionTypeInvalid:
        case lldb::eSectionTypeDWARFDebugAbbrev:
        case lldb::eSectionTypeDWARFDebugAddr:
        case lldb::eSectionTypeDWARFDebugAranges:
        case lldb::eSectionTypeDWARFDebugFrame:
        case lldb::eSectionTypeDWARFDebugInfo:
        case lldb::eSectionTypeDWARFDebugLine:
        case lldb::eSectionTypeDWARFDebugLoc:
        case lldb::eSectionTypeDWARFDebugMacInfo:
        case lldb::eSectionTypeDWARFDebugPubNames:
        case lldb::eSectionTypeDWARFDebugPubTypes:
        case lldb::eSectionTypeDWARFDebugRanges:
        case lldb::eSectionTypeDWARFDebugStr:
        case lldb::eSectionTypeDWARFDebugStrOffsets:
        case lldb::eSectionTypeDWARFAppleNames:
        case lldb::eSectionTypeDWARFAppleTypes:
        case lldb::eSectionTypeDWARFAppleNamespaces:
        case lldb::eSectionTypeDWARFAppleObjC:
            error.Clear();
            break;
        default:
            const bool zero_memory = false;
            record.m_process_address = Malloc (record.m_size,
                                               record.m_alignment,
                                               record.m_permissions,
                                               eAllocationPolicyProcessOnly,
                                               zero_memory,
                                               error);
            break;
    }
    
    return error.Success();
}

bool
IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
{
    bool ret = true;

    lldb_private::Error err;

    for (AllocationRecord &record : m_records)
    {
        ret = CommitOneAllocation(process_sp, err, record);
        
        if (!ret)
        {
            break;
        }
    }

    if (!ret)
    {
        for (AllocationRecord &record : m_records)
        {
            if (record.m_process_address != LLDB_INVALID_ADDRESS)
            {
                Free(record.m_process_address, err);
                record.m_process_address = LLDB_INVALID_ADDRESS;
            }
        }
    }

    return ret;
}

void
IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine)
{
    m_reported_allocations = true;
    
    for (AllocationRecord &record : m_records)
    {
        if (record.m_process_address == LLDB_INVALID_ADDRESS)
            continue;

        if (record.m_section_id == eSectionIDInvalid)
            continue;

        engine.mapSectionAddress((void*)record.m_host_address, record.m_process_address);
    }

    // Trigger re-application of relocations.
    engine.finalizeObject();
}

bool
IRExecutionUnit::WriteData (lldb::ProcessSP &process_sp)
{
    bool wrote_something = false;
    for (AllocationRecord &record : m_records)
    {
        if (record.m_process_address != LLDB_INVALID_ADDRESS)
        {
            lldb_private::Error err;
            WriteMemory (record.m_process_address, (uint8_t*)record.m_host_address, record.m_size, err);
            if (err.Success())
                wrote_something = true;
        }
    }
    return wrote_something;
}

void
IRExecutionUnit::AllocationRecord::dump (Log *log)
{
    if (!log)
        return;

    log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d, name %s)",
                (unsigned long long)m_host_address,
                (unsigned long long)m_size,
                (unsigned long long)m_process_address,
                (unsigned)m_alignment,
                (unsigned)m_section_id,
                m_name.c_str());
}


lldb::ByteOrder
IRExecutionUnit::GetByteOrder () const
{
    ExecutionContext exe_ctx (GetBestExecutionContextScope());
    return exe_ctx.GetByteOrder();
}

uint32_t
IRExecutionUnit::GetAddressByteSize () const
{
    ExecutionContext exe_ctx (GetBestExecutionContextScope());
    return exe_ctx.GetAddressByteSize();
}

void
IRExecutionUnit::PopulateSymtab (lldb_private::ObjectFile *obj_file,
                                 lldb_private::Symtab &symtab)
{
    // No symbols yet...
}


void
IRExecutionUnit::PopulateSectionList (lldb_private::ObjectFile *obj_file,
                                      lldb_private::SectionList &section_list)
{
    for (AllocationRecord &record : m_records)
    {
        if (record.m_size > 0)
        {
            lldb::SectionSP section_sp (new lldb_private::Section (obj_file->GetModule(),
                                                                   obj_file,
                                                                   record.m_section_id,
                                                                   ConstString(record.m_name),
                                                                   record.m_sect_type,
                                                                   record.m_process_address,
                                                                   record.m_size,
                                                                   record.m_host_address,   // file_offset (which is the host address for the data)
                                                                   record.m_size,           // file_size
                                                                   0,
                                                                   record.m_permissions));  // flags
            section_list.AddSection (section_sp);
        }
    }
}

bool
IRExecutionUnit::GetArchitecture (lldb_private::ArchSpec &arch)
{
    ExecutionContext exe_ctx (GetBestExecutionContextScope());
    Target *target = exe_ctx.GetTargetPtr();
    if (target)
        arch = target->GetArchitecture();
    else
        arch.Clear();
    return arch.IsValid();
}

lldb::ModuleSP
IRExecutionUnit::GetJITModule ()
{
    ExecutionContext exe_ctx (GetBestExecutionContextScope());
    Target *target = exe_ctx.GetTargetPtr();
    if (target)
    {
        lldb::ModuleSP jit_module_sp = lldb_private::Module::CreateJITModule (std::static_pointer_cast<lldb_private::ObjectFileJITDelegate>(shared_from_this()));
        if (jit_module_sp)
        {
            bool changed = false;
            jit_module_sp->SetLoadAddress(*target, 0, true, changed);
        }
        return jit_module_sp;
    }
    return lldb::ModuleSP();
}
