//===-- 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/Module.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Symbol.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()))
        {
            Log *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;

    Log *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 include_inlines = true;
    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,
                                              NULL,
                                              eFunctionNameTypeAuto,
                                              include_symbols,
                                              include_inlines,
                                              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,
                                              include_inlines,
                                              append, 
                                              func_list);
        }
        break;

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

    // Remove any duplicates between the function 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->ValueIsAddress())
                    {
                        if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRef())
                        {
                            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->ValueIsAddress())
            {
                func_addr = sc.symbol->GetAddressRef();
                addr_t byte_size = sc.symbol->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());
}

