//===-- SectionLoadList.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/Target/SectionLoadList.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"

using namespace lldb;
using namespace lldb_private;

SectionLoadList::SectionLoadList(const SectionLoadList &rhs) : m_addr_to_sect(), m_sect_to_addr(), m_mutex()
{
    std::lock_guard<std::recursive_mutex> guard(rhs.m_mutex);
    m_addr_to_sect = rhs.m_addr_to_sect;
    m_sect_to_addr = rhs.m_sect_to_addr;
}

void
SectionLoadList::operator=(const SectionLoadList &rhs)
{
    std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
    std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
    m_addr_to_sect = rhs.m_addr_to_sect;
    m_sect_to_addr = rhs.m_sect_to_addr;
}

bool
SectionLoadList::IsEmpty() const
{
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    return m_addr_to_sect.empty();
}

void
SectionLoadList::Clear ()
{
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    m_addr_to_sect.clear();
    m_sect_to_addr.clear();
}

addr_t
SectionLoadList::GetSectionLoadAddress (const lldb::SectionSP &section) const
{
    // TODO: add support for the same section having multiple load addresses
    addr_t section_load_addr = LLDB_INVALID_ADDRESS;
    if (section)
    {
        std::lock_guard<std::recursive_mutex> guard(m_mutex);
        sect_to_addr_collection::const_iterator pos = m_sect_to_addr.find (section.get());
        
        if (pos != m_sect_to_addr.end())
            section_load_addr = pos->second;
    }
    return section_load_addr;
}

bool
SectionLoadList::SetSectionLoadAddress (const lldb::SectionSP &section, addr_t load_addr, bool warn_multiple)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));

    ModuleSP module_sp (section->GetModule());

    if (module_sp)
    {
        if (log)
        {
            const FileSpec &module_file_spec (module_sp->GetFileSpec());
            log->Printf ("SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64 ") module = %p",
                         __FUNCTION__, static_cast<void*>(section.get()),
                         module_file_spec.GetPath().c_str(),
                         section->GetName().AsCString(), load_addr,
                         static_cast<void*>(module_sp.get()));
        }

        if (section->GetByteSize() == 0)
            return false; // No change

        // Fill in the section -> load_addr map
        std::lock_guard<std::recursive_mutex> guard(m_mutex);
        sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section.get());
        if (sta_pos != m_sect_to_addr.end())
        {
            if (load_addr == sta_pos->second)
                return false; // No change...
            else
                sta_pos->second = load_addr;
        }
        else
            m_sect_to_addr[section.get()] = load_addr;

        // Fill in the load_addr -> section map
        addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
        if (ats_pos != m_addr_to_sect.end())
        {
            // Some sections are ok to overlap, and for others we should warn. When
            // we have multiple load addresses that correspond to a section, we will
            // always attribute the section to the be last section that claims it
            // exists at that address. Sometimes it is ok for more that one section
            // to be loaded at a specific load address, and other times it isn't.
            // The "warn_multiple" parameter tells us if we should warn in this case
            // or not. The DynamicLoader plug-in subclasses should know which
            // sections should warn and which shouldn't (darwin shared cache modules
            // all shared the same "__LINKEDIT" sections, so the dynamic loader can
            // pass false for "warn_multiple").
            if (warn_multiple && section != ats_pos->second)
            {
                ModuleSP module_sp (section->GetModule());
                if (module_sp)
                {
                    ModuleSP curr_module_sp (ats_pos->second->GetModule());
                    if (curr_module_sp)
                    {
                        module_sp->ReportWarning ("address 0x%16.16" PRIx64 " maps to more than one section: %s.%s and %s.%s",
                                                  load_addr, 
                                                  module_sp->GetFileSpec().GetFilename().GetCString(), 
                                                  section->GetName().GetCString(),
                                                  curr_module_sp->GetFileSpec().GetFilename().GetCString(),
                                                  ats_pos->second->GetName().GetCString());
                    }
                }
            }
            ats_pos->second = section;
        }
        else
            m_addr_to_sect[load_addr] = section;
        return true;    // Changed

    }
    else
    {
        if (log)
        {
            log->Printf ("SectionLoadList::%s (section = %p (%s), load_addr = 0x%16.16" PRIx64 ") error: module has been deleted",
                         __FUNCTION__, static_cast<void*>(section.get()),
                         section->GetName().AsCString(),
                         load_addr);
        }
    }
    return false;
}

size_t
SectionLoadList::SetSectionUnloaded (const lldb::SectionSP &section_sp)
{
    size_t unload_count = 0;

    if (section_sp)
    {
        Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));

        if (log)
        {
            ModuleSP module_sp = section_sp->GetModule();
            std::string module_name("<Unknown>");
            if (module_sp)
            {
                const FileSpec &module_file_spec (section_sp->GetModule()->GetFileSpec());
                module_name = module_file_spec.GetPath();
            }
            log->Printf ("SectionLoadList::%s (section = %p (%s.%s))",
                         __FUNCTION__, static_cast<void*>(section_sp.get()),
                         module_name.c_str(),
                         section_sp->GetName().AsCString());
        }

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

        sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section_sp.get());
        if (sta_pos != m_sect_to_addr.end())
        {
            ++unload_count;
            addr_t load_addr = sta_pos->second;
            m_sect_to_addr.erase (sta_pos);

            addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
            if (ats_pos != m_addr_to_sect.end())
                m_addr_to_sect.erase (ats_pos);
        }
    }
    return unload_count;
}

bool
SectionLoadList::SetSectionUnloaded (const lldb::SectionSP &section_sp, addr_t load_addr)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));

    if (log)
    {
        ModuleSP module_sp = section_sp->GetModule();
        std::string module_name("<Unknown>");
        if (module_sp)
        {
            const FileSpec &module_file_spec (section_sp->GetModule()->GetFileSpec());
            module_name = module_file_spec.GetPath();
        }
        log->Printf ("SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64 ")",
                     __FUNCTION__, static_cast<void*>(section_sp.get()),
                     module_name.c_str(),
                     section_sp->GetName().AsCString(), load_addr);
    }
    bool erased = false;
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section_sp.get());
    if (sta_pos != m_sect_to_addr.end())
    {
        erased = true;
        m_sect_to_addr.erase (sta_pos);
    }

    addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
    if (ats_pos != m_addr_to_sect.end())
    {
        erased = true;
        m_addr_to_sect.erase (ats_pos);
    }

    return erased;
}


bool
SectionLoadList::ResolveLoadAddress (addr_t load_addr, Address &so_addr) const
{
    // First find the top level section that this load address exists in
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    if (!m_addr_to_sect.empty())
    {
        addr_to_sect_collection::const_iterator pos = m_addr_to_sect.lower_bound (load_addr);
        if (pos != m_addr_to_sect.end())
        {
            if (load_addr != pos->first && pos != m_addr_to_sect.begin())
                --pos;
            const addr_t pos_load_addr = pos->first;
            if (load_addr >= pos_load_addr)
            {
                addr_t offset = load_addr - pos_load_addr;
                if (offset < pos->second->GetByteSize())
                {
                    // We have found the top level section, now we need to find the
                    // deepest child section.
                    return pos->second->ResolveContainedAddress (offset, so_addr);
                }
            }
        }
        else
        {
            // There are no entries that have an address that is >= load_addr,
            // so we need to check the last entry on our collection.
            addr_to_sect_collection::const_reverse_iterator rpos = m_addr_to_sect.rbegin();
            if (load_addr >= rpos->first)
            {
                addr_t offset = load_addr - rpos->first;
                if (offset < rpos->second->GetByteSize())
                {
                    // We have found the top level section, now we need to find the
                    // deepest child section.
                    return rpos->second->ResolveContainedAddress (offset, so_addr);
                }
            }
        }
    }
    so_addr.Clear();
    return false;
}

void
SectionLoadList::Dump (Stream &s, Target *target)
{
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    addr_to_sect_collection::const_iterator pos, end;
    for (pos = m_addr_to_sect.begin(), end = m_addr_to_sect.end(); pos != end; ++pos)
    {
        s.Printf("addr = 0x%16.16" PRIx64 ", section = %p: ",
                 pos->first, static_cast<void*>(pos->second.get()));
        pos->second->Dump (&s, target, 0);
    }
}


