//===-- AddressResolverName.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/Core/AddressResolverName.h"

// Project includes
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
#include "lldb/lldb-private-log.h"

using namespace lldb;
using namespace lldb_private;

AddressResolverName::AddressResolverName
(
    const char *func_name,
    AddressResolver::MatchType type
) :
    AddressResolver (),
    m_func_name (func_name),
    m_class_name (NULL),
    m_regex (),
    m_match_type (type)
{
    if (m_match_type == AddressResolver::Regexp)
    {
        if (!m_regex.Compile (m_func_name.AsCString()))
        {
            LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));

            if (log)
                log->Warning ("function name regexp: \"%s\" did not compile.", m_func_name.AsCString());
        }
    }
}

AddressResolverName::AddressResolverName
(
    RegularExpression &func_regex
) :
    AddressResolver (),
    m_func_name (NULL),
    m_class_name (NULL),
    m_regex (func_regex),
    m_match_type (AddressResolver::Regexp)
{

}

AddressResolverName::AddressResolverName
(
    const char *class_name,
    const char *method,
    AddressResolver::MatchType type
) :
    AddressResolver (),
    m_func_name (method),
    m_class_name (class_name),
    m_regex (),
    m_match_type (type)
{

}

AddressResolverName::~AddressResolverName ()
{
}

// FIXME: Right now we look at the module level, and call the module's "FindFunctions".
// Greg says he will add function tables, maybe at the CompileUnit level to accelerate function
// lookup.  At that point, we should switch the depth to CompileUnit, and look in these tables.

Searcher::CallbackReturn
AddressResolverName::SearchCallback
(
    SearchFilter &filter,
    SymbolContext &context,
    Address *addr,
    bool containing
)
{
    SymbolContextList func_list;
    SymbolContextList sym_list;

    bool skip_prologue = true;
    uint32_t i;
    SymbolContext sc;
    Address func_addr;

    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));

    if (m_class_name)
    {
        if (log)
            log->Warning ("Class/method function specification not supported yet.\n");
        return Searcher::eCallbackReturnStop;
    }

    const bool include_symbols = false;
    const bool append = false;
    switch (m_match_type)
    {
    case AddressResolver::Exact:
        if (context.module_sp)
        {
            context.module_sp->FindSymbolsWithNameAndType (m_func_name, 
                                                           eSymbolTypeCode, 
                                                           sym_list);
            context.module_sp->FindFunctions (m_func_name, 
                                              eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector,
                                              include_symbols,
                                              append, 
                                              func_list);
        }
        break;

    case AddressResolver::Regexp:
        if (context.module_sp)
        {
            context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, 
                                                                eSymbolTypeCode, 
                                                                sym_list);
            context.module_sp->FindFunctions (m_regex, 
                                              include_symbols,
                                              append, 
                                              func_list);
        }
        break;

    case AddressResolver::Glob:
        if (log)
            log->Warning ("glob is not supported yet.");
        break;
    }

    // Remove any duplicates between the funcion list and the symbol list
    if (func_list.GetSize())
    {
        for (i = 0; i < func_list.GetSize(); i++)
        {
            if (func_list.GetContextAtIndex(i, sc) == false)
                continue;

            if (sc.function == NULL)
                continue;
            uint32_t j = 0;
            while (j < sym_list.GetSize())
            {
                SymbolContext symbol_sc;
                if (sym_list.GetContextAtIndex(j, symbol_sc))
                {
                    if (symbol_sc.symbol && symbol_sc.symbol->GetAddressRangePtr())
                    {
                        if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRangePtr()->GetBaseAddress())
                        {
                            sym_list.RemoveContextAtIndex(j);
                            continue;   // Don't increment j
                        }
                    }
                }

                j++;
            }
        }

        for (i = 0; i < func_list.GetSize(); i++)
        {
            if (func_list.GetContextAtIndex(i, sc))
            {
                if (sc.function)
                {
                    func_addr = sc.function->GetAddressRange().GetBaseAddress();
                    addr_t byte_size = sc.function->GetAddressRange().GetByteSize();
                    if (skip_prologue)
                    {
                        const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
                        if (prologue_byte_size)
                        {
                            func_addr.SetOffset (func_addr.GetOffset() + prologue_byte_size);
                            byte_size -= prologue_byte_size;
                        }
                    }

                    if (filter.AddressPasses (func_addr))
                    {
                        AddressRange new_range (func_addr, byte_size);
                        m_address_ranges.push_back (new_range);
                    }
                }
            }
        }
    }

    for (i = 0; i < sym_list.GetSize(); i++)
    {
        if (sym_list.GetContextAtIndex(i, sc))
        {
            if (sc.symbol && sc.symbol->GetAddressRangePtr())
            {
                func_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress();
                addr_t byte_size = sc.symbol->GetAddressRangePtr()->GetByteSize();

                if (skip_prologue)
                {
                    const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
                    if (prologue_byte_size)
                    {
                        func_addr.SetOffset (func_addr.GetOffset() + prologue_byte_size);
                        byte_size -= prologue_byte_size;
                    }
                }

                if (filter.AddressPasses (func_addr))
                {
                    AddressRange new_range (func_addr, byte_size);
                    m_address_ranges.push_back (new_range);
                }
            }
        }
    }
    return Searcher::eCallbackReturnContinue;
}

Searcher::Depth
AddressResolverName::GetDepth()
{
    return Searcher::eDepthModule;
}

void
AddressResolverName::GetDescription (Stream *s)
{
    s->PutCString("Address by function name: ");

    if (m_match_type == AddressResolver::Regexp)
        s->Printf("'%s' (regular expression)", m_regex.GetText());
    else
        s->Printf("'%s'", m_func_name.AsCString());
}

