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

#include "DWARFDebugRanges.h"
#include "SymbolFileDWARF.h"
#include "lldb/Core/Stream.h"
#include <assert.h>

using namespace lldb_private;
using namespace std;

DWARFDebugRanges::DWARFDebugRanges() :
    m_range_map()
{
}

DWARFDebugRanges::~DWARFDebugRanges()
{
}

void
DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data)
{
    RangeList range_list;
    dw_offset_t offset = 0;
    dw_offset_t debug_ranges_offset = offset;
    while (range_list.Extract(dwarf2Data, &offset))
    {
        m_range_map[debug_ranges_offset] = range_list;
        debug_ranges_offset = offset;
    }
}

bool
DWARFDebugRanges::RangeList::AddRange(dw_addr_t lo_addr, dw_addr_t hi_addr)
{
    if (lo_addr <= hi_addr)
    {
        Range range(lo_addr, hi_addr);
        ranges.push_back(range);
        return true;
    }
    return false;
}

const DWARFDebugRanges::Range*
DWARFDebugRanges::RangeList::Lookup(dw_addr_t offset) const
{
    Range::const_iterator pos = ranges.begin();
    Range::const_iterator end_pos = ranges.end();
    for (pos = ranges.begin(); pos != end_pos; ++pos)
    {
        if (pos->begin_offset <= offset && offset < pos->end_offset)
        {
            return &(*pos);
        }
    }
    return NULL;
}

size_t
DWARFDebugRanges::RangeList::Size() const
{
    return ranges.size();
}

void
DWARFDebugRanges::RangeList::AddOffset(dw_addr_t offset)
{
    if (!ranges.empty())
    {
        Range::iterator pos = ranges.begin();
        Range::iterator end_pos = ranges.end();
        for (pos = ranges.begin(); pos != end_pos; ++pos)
        {
            // assert for unsigned overflows
            assert (~pos->begin_offset >= offset);
            assert (~pos->end_offset >= offset);
            pos->begin_offset += offset;
            pos->end_offset += offset;
        }
    }
}

void
DWARFDebugRanges::RangeList::SubtractOffset(dw_addr_t offset)
{
    if (!ranges.empty())
    {
        Range::iterator pos = ranges.begin();
        Range::iterator end_pos = ranges.end();
        for (pos = ranges.begin(); pos != end_pos; ++pos)
        {
            assert (pos->begin_offset >= offset);
            assert (pos->end_offset >= offset);
            pos->begin_offset -= offset;
            pos->end_offset -= offset;
        }
    }
}


const DWARFDebugRanges::Range*
DWARFDebugRanges::RangeList::RangeAtIndex(size_t i) const
{
    if (i < ranges.size())
        return &ranges[i];
    return NULL;
}

bool
DWARFDebugRanges::RangeList::Extract(SymbolFileDWARF* dwarf2Data, uint32_t* offset_ptr)
{
    Clear();
    uint32_t range_offset = *offset_ptr;
    const DataExtractor& debug_ranges_data = dwarf2Data->get_debug_ranges_data();
    uint32_t addr_size = debug_ranges_data.GetAddressByteSize();

    while (debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size))
    {
        dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
        dw_addr_t end   = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
        if (!begin && !end)
        {
            // End of range list
            break;
        }
        // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits
        // of ones
        switch (addr_size)
        {
        case 2:
            if (begin == 0xFFFFull)
                begin = DW_INVALID_ADDRESS;
            break;

        case 4:
            if (begin == 0xFFFFFFFFull)
                begin = DW_INVALID_ADDRESS;
            break;

        case 8:
            break;

        default:
            assert(!"DWARFDebugRanges::RangeList::Extract() unsupported address size.");
            break;
        }

        // Filter out empty ranges
        if (begin != end)
            ranges.push_back(Range(begin, end));
    }

    // Make sure we consumed at least something
    return range_offset != *offset_ptr;
}


dw_addr_t
DWARFDebugRanges::RangeList::LowestAddress(const dw_addr_t cu_base_addr) const
{
    dw_addr_t addr = DW_INVALID_ADDRESS;
    dw_addr_t curr_base_addr = cu_base_addr;
    if (!ranges.empty())
    {
        Range::const_iterator pos = ranges.begin();
        Range::const_iterator end_pos = ranges.end();
        for (pos = ranges.begin(); pos != end_pos; ++pos)
        {
            if (pos->begin_offset == DW_INVALID_ADDRESS)
                curr_base_addr = pos->end_offset;
            else if (curr_base_addr != DW_INVALID_ADDRESS)
            {
                dw_addr_t curr_addr = curr_base_addr + pos->begin_offset;
                if (addr > curr_addr)
                    addr = curr_addr;
            }
        }
    }
    return addr;
}

dw_addr_t
DWARFDebugRanges::RangeList::HighestAddress(const dw_addr_t cu_base_addr) const
{
    dw_addr_t addr = 0;
    dw_addr_t curr_base_addr = cu_base_addr;
    if (!ranges.empty())
    {
        Range::const_iterator pos = ranges.begin();
        Range::const_iterator end_pos = ranges.end();
        for (pos = ranges.begin(); pos != end_pos; ++pos)
        {
            if (pos->begin_offset == DW_INVALID_ADDRESS)
                curr_base_addr = pos->end_offset;
            else if (curr_base_addr != DW_INVALID_ADDRESS)
            {
                dw_addr_t curr_addr = curr_base_addr + pos->end_offset;
                if (addr < curr_addr)
                    addr = curr_addr;
            }
        }
    }
    if (addr != 0)
        return addr;
    return DW_INVALID_ADDRESS;
}


void
DWARFDebugRanges::Dump(Stream *s, const DataExtractor& debug_ranges_data, uint32_t* offset_ptr, dw_addr_t cu_base_addr)
{
    uint32_t addr_size = s->GetAddressByteSize();
    bool verbose = s->GetVerbose();

    dw_addr_t base_addr = cu_base_addr;
    while (debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size))
    {
        dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
        dw_addr_t end   = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
        // Extend 4 byte addresses that consits of 32 bits of 1's to be 64 bits
        // of ones
        if (begin == 0xFFFFFFFFull && addr_size == 4)
            begin = DW_INVALID_ADDRESS;

        s->Indent();
        if (verbose)
        {
            s->AddressRange(begin, end, sizeof (dw_addr_t), " offsets = ");
        }


        if (begin == 0 && end == 0)
        {
            s->PutCString(" End");
            break;
        }
        else if (begin == DW_INVALID_ADDRESS)
        {
            // A base address selection entry
            base_addr = end;
            s->Address(base_addr, sizeof (dw_addr_t), " Base address = ");
        }
        else
        {
            // Convert from offset to an address
            dw_addr_t begin_addr = begin + base_addr;
            dw_addr_t end_addr = end + base_addr;

            s->AddressRange(begin_addr, end_addr, sizeof (dw_addr_t), verbose ? " ==> addrs = " : NULL);
        }
    }
}

bool
DWARFDebugRanges::FindRanges(dw_offset_t debug_ranges_offset, RangeList& range_list) const
{
    range_map_const_iterator pos = m_range_map.find(debug_ranges_offset);
    if (pos != m_range_map.end())
    {
        range_list = pos->second;
        return true;
    }
    return false;
}



