//===-- 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/ClangNamespaceDecl.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Symbol.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()))
        {
            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->GetAddress())
                        {
                            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->GetAddress();
                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());
}

