#-------------------------------------------------------------------------------
# elftools: dwarf/aranges.py
#
# DWARF aranges section decoding (.debug_aranges)
#
# Dorothy Chen (dorothchen@gmail.com)
# This code is in the public domain
#-------------------------------------------------------------------------------
import os
from collections import namedtuple
from ..common.utils import struct_parse
from bisect import bisect_right
import math

# An entry in the aranges table; 
# begin_addr: The beginning address in the CU
# length: The length of the address range in this entry
# info_offset: The CU's offset into .debug_info
# see 6.1.2 in DWARF4 docs for explanation of the remaining fields
ARangeEntry = namedtuple('ARangeEntry', 
    'begin_addr length info_offset unit_length version address_size segment_size')

class ARanges(object):
    """ ARanges table in DWARF

        stream, size: 
            A stream holding the .debug_aranges section, and its size

        structs: 
            A DWARFStructs instance for parsing the data
    """
    def __init__(self, stream, size, structs):
        self.stream = stream
        self.size = size
        self.structs = structs

        # Get entries of aranges table in the form of ARangeEntry tuples
        self.entries = self._get_entries()

        # Sort entries by the beginning address
        self.entries.sort(key=lambda entry: entry.begin_addr)

        # Create list of keys (first addresses) for better searching
        self.keys = [entry.begin_addr for entry in self.entries]


    def cu_offset_at_addr(self, addr):
        """ Given an address, get the offset of the CU it belongs to, where
            'offset' refers to the offset in the .debug_info section.
        """
        tup = self.entries[bisect_right(self.keys, addr) - 1]
        return tup.info_offset
        

    #------ PRIVATE ------#
    def _get_entries(self):
        """ Populate self.entries with ARangeEntry tuples for each range of addresses
        """
        self.stream.seek(0)
        entries = []
        offset = 0

        # one loop == one "set" == one CU
        while offset < self.size :
            aranges_header = struct_parse(self.structs.Dwarf_aranges_header, 
                self.stream, offset)
            addr_size = self._get_addr_size_struct(aranges_header["address_size"])

            # No segmentation
            if aranges_header["segment_size"] == 0:
                # pad to nearest multiple of tuple size
                tuple_size = aranges_header["address_size"] * 2 
                fp = self.stream.tell()
                seek_to = int(math.ceil(fp/float(tuple_size)) * tuple_size)
                self.stream.seek(seek_to)

                # entries in this set/CU
                addr = struct_parse(addr_size('addr'), self.stream)
                length = struct_parse(addr_size('length'), self.stream)
                while addr != 0 or length != 0:
                    # 'begin_addr length info_offset version address_size segment_size'
                    entries.append(
                        ARangeEntry(begin_addr=addr, 
                            length=length, 
                            info_offset=aranges_header["debug_info_offset"],
                            unit_length=aranges_header["unit_length"],
                            version=aranges_header["version"],
                            address_size=aranges_header["address_size"],
                            segment_size=aranges_header["segment_size"]))
                    addr = struct_parse(addr_size('addr'), self.stream)
                    length = struct_parse(addr_size('length'), self.stream)
            # Segmentation exists in executable
            elif aranges_header["segment_size"] != 0:
                raise NotImplementedError("Segmentation not implemented")

            offset = (offset 
                + aranges_header.unit_length 
                + self.structs.initial_length_field_size())

        return entries

    def _get_addr_size_struct(self, addr_header_value):
        """ Given this set's header value (int) for the address size, 
            get the Construct representation of that size
        """
        if addr_header_value == 4:
            return self.structs.Dwarf_uint32
        else: 
            assert addr_header_value == 8
            return self.structs.Dwarf_uint64
