Skip to content

Address Range

Helper Class For Handling Address Ranges.

Classes:

Name Description
AddrRange

Address range starting at baseaddr with size in bytes.

IntersectError

AddrRange Intersection Error.

AddrRange

Bases: mementos

Address range starting at baseaddr with size in bytes.

Methods:

Name Description
__init__

Address range starting at baseaddr with size in bytes.

__str__

Return String representation.

__repr__

Return extended representation.

__contains__

Check whether value lies within address range.

__iter__

Iterate over all addresses inside range.

is_overlapping

Return True if other overlaps.

get_intersect

Return intersection of self and other.

get_difference

Get difference of self and other.

Attributes:

Name Type Description
endaddr Hex

Hexvalue of end address of range.

nextaddr Hex

Hexvalue of first address after range.

endaddr property

endaddr

Hexvalue of end address of range.

nextaddr property

nextaddr

Hexvalue of first address after range.

__init__

__init__(
    baseaddr, size, addrwidth=None, item=None, is_sub=False
)

Example:

>>> a = AddrRange(0x1000, 0x100)
>>> a
AddrRange(0x1000, '256 bytes')
>>> b = AddrRange(0x1000, 0x100, item='B')
>>> b
AddrRange('B', 0x1000, '256 bytes')
>>> c = AddrRange(0x1000, 0x100, is_sub=True)
>>> c
AddrRange(0x1000, '256 bytes', is_sub=True)
>>> d =  AddrRange(0x1000, 0x100, item='D', is_sub=True)
>>> d
AddrRange('D', 0x1000, '256 bytes', is_sub=True)

The addrwidth just formats the address representation:

>>> a = AddrRange(0x1000, 0x100, addrwidth=32)
>>> a
AddrRange(0x00001000, '256 bytes', addrwidth=32)
>>> str(a)
'0x00001000-0x000010FF(256 bytes)'
>>> str(a.nextaddr)
'0x00001100'

Address ranges can be compared:

>>> AddrRange(0x1000, 0x100) == AddrRange(0x1000, 0x100)
True
>>> AddrRange(0x1000, 0x100) == AddrRange(0x1000, 0x200)
False

Comparing an AddrRange against another type just returns False:

>>> AddrRange(0x1000, 0x100) == 42
False

Addresses can be checked whether they lie within the range:

>>> 0x1008 in a
True
>>> 0x1400 in a
False

Address ranges can be iterated over:

>>> for i in AddrRange(0x200, 6):
...     print(i)
512
513
514
515
516
517

__str__

__str__()

Return String representation.

__repr__

__repr__()

Return extended representation.

__contains__

__contains__(value)

Check whether value lies within address range.

__iter__

__iter__()

Iterate over all addresses inside range.

is_overlapping

is_overlapping(other)

Return True if other overlaps.

Example:

>>> AddrRange(0x1000, '4 KB').is_overlapping(AddrRange(0x3000, '4 KB'))
False
>>> AddrRange(0x1000, '4 KB').is_overlapping(AddrRange(0x2000, '4 KB'))
False
>>> AddrRange(0x1000, '4 KB').is_overlapping(AddrRange(0x2000, 0x1))
False
>>> AddrRange(0x1000, '4 KB').is_overlapping(AddrRange(0x1FFF, 0x1))
True
>>> AddrRange(0x1000, '4 KB').is_overlapping(AddrRange(0x1000, '4 KB'))
True

>>> AddrRange(0x3000, '4 KB').is_overlapping(AddrRange(0x2000, '4 KB'))
False
>>> AddrRange(0x3000, '4 KB').is_overlapping(AddrRange(0x2FFF, 0x1))
False
>>> AddrRange(0x3000, '4 KB').is_overlapping(AddrRange(0x3000, 0x1))
True
>>> AddrRange(0x3000, '4 KB').is_overlapping(AddrRange(0x0000, 0x8000))
True

get_intersect

get_intersect(other, strict=False)

Return intersection of self and other.

Parameters:

Name Type Description Default
other(AddrRange)

The other AddrRange for intersection with self.

required

Other Parameters:

Name Type Description
strict(bool)

Raise IntersectError when True and there is no intersection between self and other.

Absolute AddrRanges just lead to the intersection:

>>> AddrRange(0x1000, '4 KB').get_intersect(AddrRange(0x2000, '4 KB'))
>>> AddrRange(0x1000, '4 KB').get_intersect(AddrRange(0x2000, 0x1))
>>> AddrRange(0x1000, '4 KB').get_intersect(AddrRange(0x1FFF, 0x1))
AddrRange(0x1FFF, '1 byte')

Remark: humandfriendly package is rounding 4095 bytes to 4 KB.

>>> a = AddrRange(0x1000, '4 KB').get_intersect(AddrRange(0x1000, 0xFFF))
>>> a
AddrRange(0x1000, '4095 bytes')
>>> int(a.size)
4095
>>> AddrRange(0x1000, '4 KB').get_intersect(AddrRange(0x1000, '4 KB'))
AddrRange(0x1000, '4 KB')
>>> AddrRange(0x3000, '4 KB').get_intersect(AddrRange(0x2000, '4 KB'))
>>> AddrRange(0x3000, '4 KB').get_intersect(AddrRange(0x2FFF, 0x1))
>>> AddrRange(0x3000, '4 KB').get_intersect(AddrRange(0x3000, 0x1))
AddrRange(0x3000, '1 byte')
>>> AddrRange(0x3000, '4 KB').get_intersect(AddrRange(0x0000, 0x8000))
AddrRange(0x3000, '4 KB')

If strict is set and there is no insersection IntersectError is raised:

>>> AddrRange(0x1000, '4 KB').get_intersect(AddrRange(0x1000, '4 KB'), strict=True)
AddrRange(0x1000, '4 KB')
>>> AddrRange(0x1000, '4 KB').get_intersect(
...     AddrRange(0x3000, '4 KB'), strict=True)  # doctest: +NORMALIZE_WHITESPACE
Traceback (most recent call last):
    ...
icdutil.addrrange.IntersectError: No intersection between AddrRange(0x1000, '4 KB')             and AddrRange(0x3000, '4 KB').

If only one of the AddrRange is absolute, the sub range is taken relative to the absolute. If self is a subrange, then the intersection is again a subrange w/r/t to the absolute range.

>>> AddrRange(0xF0000000, '1 MB').get_intersect(AddrRange(0x2000, '4 KB', is_sub=True))
AddrRange(0xF0002000, '4 KB')
>>> AddrRange(0x2000, '4 KB', is_sub=True).get_intersect(AddrRange(0xF0000000, '1 MB'))
AddrRange(0x2000, '4 KB', is_sub=True)

If there is no overlap b/w absolute range and sub-range at the offset, the result depends on the strict parameter:

>>> AddrRange(0xF0000000, '1 KB').get_intersect(AddrRange(0x2000, '4 KB', is_sub=True))
>>> AddrRange(0xF0000000, '1 KB').get_intersect(
...     AddrRange(0x2000, '4 KB', is_sub=True), strict=True)  # doctest: +NORMALIZE_WHITESPACE
Traceback (most recent call last):
    ...
icdutil.addrrange.IntersectError: No intersection between AddrRange(0xF0000000, '1 KB')             and AddrRange(0x2000, '4 KB', is_sub=True).

If both are sub-ranges it also just leads to an intersection, but the result is a sub-range:

>>> AddrRange(0x3000, '4 KB', is_sub=True).get_intersect(AddrRange(0x0000, 0x8000, is_sub=True))
AddrRange(0x3000, '4 KB', is_sub=True)

The item and aaddrwidth of the intersection is always inherited from self.

>>> AddrRange(0x2000, '1 MB', item='A', addrwidth=20).get_intersect(
...    AddrRange(0x5000, '4 KB', item='B', addrwidth=24))
AddrRange('A', 0x05000, '4 KB', addrwidth=20)

get_difference

get_difference(other)

Get difference of self and other.

Parameters:

Name Type Description Default
other(AddrRange)

The other AddrRange for intersection with self.

required

Absolute AddrRanges just lead to the difference (i.e. the rest of self after the overlapping part has been removed):

>>> AddrRange(0x1000, '4 KB').get_difference(AddrRange(0x2000, '4 KB'))
[AddrRange(0x1000, '4 KB')]
>>> AddrRange(0x1000, '4 KB').get_difference(AddrRange(0x800, '12 KB'))
[]
>>> AddrRange(0x1000, '4 KB').get_difference(AddrRange(0x1FFF, 0x1))
[AddrRange(0x1000, '4095 bytes')]
>>> AddrRange(0x1000, '4 KB').get_difference(AddrRange(0x1001, '8 KB'))
[AddrRange(0x1000, '1 byte')]
>>> AddrRange(0x1000, '4 KB').get_difference(AddrRange(0x1000, 0xFFF))
[AddrRange(0x1FFF, '1 byte')]
>>> AddrRange(0x1000, '4 KB').get_difference(AddrRange(0x1800, 0x1))
[AddrRange(0x1000, '2 KB'), AddrRange(0x1801, '2047 bytes')]

If both are sub-ranges it also just leads to a difference, but the result is a sub-range:

>>> AddrRange(0x1000, '4 KB', is_sub=True).get_difference(AddrRange(0x2000, '4 KB', is_sub=True))
[AddrRange(0x1000, '4 KB', is_sub=True)]
>>> AddrRange(0x1000, '4 KB', is_sub=True).get_difference(AddrRange(0x800, '12 KB', is_sub=True))
[]
>>> AddrRange(0x1000, '4 KB', is_sub=True).get_difference(AddrRange(0x1FFF, 0x1, is_sub=True))
[AddrRange(0x1000, '4095 bytes', is_sub=True)]

If only one of the AddrRange is absolute, the sub range is taken relative to the absolute. If self is a subrange, then the difference is again a subrange w/r/t to the absolute range.

>>> AddrRange(0x1000, '4 KB').get_difference(AddrRange(0x2000, '4 KB', is_sub=True))
[AddrRange(0x1000, '4 KB')]
>>> AddrRange(0x1000, '4 KB', is_sub=True).get_difference(AddrRange(0x2000, '4 KB'))
[AddrRange(0x1000, '4 KB', is_sub=True)]
>>> AddrRange(0x1000, '4 KB').get_difference(AddrRange(0x800, '2 KB', is_sub=True))
[AddrRange(0x1000, '2 KB')]
>>> AddrRange(0x1000, '4 KB').get_difference(AddrRange(0x800, '1 KB', is_sub=True))
[AddrRange(0x1000, '2 KB'), AddrRange(0x1C00, '1 KB')]
>>> AddrRange(0x1000, '4 KB', is_sub=True).get_difference(AddrRange(0x800, '4 KB'))
[AddrRange(0x1000, '4 KB', is_sub=True)]
>>> AddrRange(0x400, '4 KB', is_sub=True).get_difference(AddrRange(0xF0000800, '4 KB'))
[AddrRange(0x1000, '1 KB', is_sub=True)]

Regardless of the other range, the difference always inherits addrwidth, the item (if there is any) and the is_sub attribute:

>>> AddrRange(0x1000, '4 KB', item='A').get_difference(AddrRange(0x1800, '4 KB', item='B'))
[AddrRange('A', 0x1000, '2 KB')]
>>> AddrRange(0x1000, '4 KB', addrwidth=16).get_difference(AddrRange(0x1800, '4 KB', addrwidth=18))
[AddrRange(0x1000, '2 KB', addrwidth=16)]

IntersectError

Bases: RuntimeError

AddrRange Intersection Error.