# Copyright 2018, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# * Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
import mmap
class Rangeable:
"""
Interface for all rangeable objects.
All rangeable objects must be able to return their base and max
addresses.
"""
def get_base_address(self):
"""
Getter for the base address of the object.
:return: The base address of the object.
:rtype: int
"""
raise NotImplementedError
def get_max_address(self):
"""
Getter for the max address of the object.
:return: The max address of the object.
:rtype: int
"""
raise NotImplementedError
class StackTrace:
def __init__(self, trace=None):
self.trace = trace
def __str__(self):
ret = ""
if self.trace is not None:
for line in self.trace:
ret += " by\t{}\n".format(line)
return ret
def memory_map(filename, size=0, access=mmap.ACCESS_WRITE, offset=0):
"""
Memory map a file.
:Warning:
`offset` has to be a non-negative multiple of PAGESIZE or
ALLOCATIONGRANULARITY
:param filename: The file to be mapped.
:type filename: str
:param size: Number of bytes to be mapped. If is equal 0, the
whole file at the moment of the call will be mapped.
:type size: int
:param offset: The offset within the file to be mapped.
:type offset: int
:param access: The type of access provided to mmap.
:return: The mapped file.
:rtype: mmap.mmap
"""
fd = os.open(filename, os.O_RDWR)
m_file = mmap.mmap(fd, size, access=access, offset=offset)
os.close(fd)
return m_file
def range_cmp(lhs, rhs):
"""
A range compare function.
:param lhs: The left hand side of the comparison.
:type lhs: Rangeable
:param rhs: The right hand side of the comparison.
:type rhs: Rangeable
:return: -1 if lhs is before rhs, 1 when after and 0 on overlap.
:rtype: int
The comparison function may be explained as::
Will return -1:
|___lhs___|
|___rhs___|
Will return +1:
|___rhs___|
|___lhs___|
Will return 0:
|___lhs___|
|___rhs___|
"""
if lhs.get_max_address() <= rhs.get_base_address():
return -1
elif lhs.get_base_address() >= rhs.get_max_address():
return 1
else:
return 0