[docs]classRegions(Generic[R]):""" A container class acting as a list of regions (sections or segments). Additionally, it keeps an sorted list of all regions that are mapped into memory to allow fast lookups. We assume none of the regions overlap with others. """
@propertydefraw_list(self)->list[R]:""" Get the internal list. Any change to it is not tracked, and therefore _sorted_list will not be updated. Therefore you probably does not want to modify the list. :return: The internal list container. :rtype: list """returnself._list@propertydefmax_addr(self)->int|None:""" Get the highest address of all regions. :return: The highest address of all regions, or None if there is no region available. :rtype: int or None """ifself._sorted_list:returnself._sorted_list[-1].max_addrreturnNonedef__getitem__(self,idx:int)->R:returnself._list[idx]def__setitem__(self,idx:int,item:R)->None:self._list[idx]=item# update self._sorted_listself._sorted_list=self._make_sorted(self._list)def__iter__(self)->Iterator[R]:returniter(self._list)def__len__(self)->int:returnlen(self._list)def__repr__(self):returnf"<Regions: {repr(self._list)}>"def_rebase(self,delta):""" Does regions rebasing to other base address. Modifies state of each internal object, so the list reference doesn't need to be updated, the same is also valid for sorted list as operation preserves the ordering. :param delta: Delta offset between an old and a new image bases :type delta: int """forxinself._list:x._rebase(delta)
[docs]defappend(self,region:R):""" Append a new Region instance into the list. :param region: The region to append. """self._list.append(region)ifself._is_region_mapped(region):key_bisect_insort_left(self._sorted_list,region,keyfunc=lambdax:x.vaddr)
[docs]defremove(self,region:R)->None:""" Remove an existing Region instance from the list. :param region: The region to remove. """ifself._is_region_mapped(region):self._sorted_list.remove(region)self._list.remove(region)
[docs]deffind_region_containing(self,addr:int)->R|None:""" Find the region that contains a specific address. Returns None if none of the regions covers the address. :param addr: The address. :return: The region that covers the specific address, or None if no such region is found. """pos=key_bisect_find(self._sorted_list,addr,keyfunc=lambdax:xifisinstance(x,int)elsex.vaddr+x.memsize)ifpos>=len(self._sorted_list):returnNoneregion=self._sorted_list[pos]ifregion.contains_addr(addr):returnregionreturnNone
[docs]deffind_region_next_to(self,addr:int)->R|None:""" Find the next region after the given address. :param addr: The address to test. :return: The next region that goes after the given address, or None if there is no section after the address, """pos=key_bisect_find(self._sorted_list,addr,keyfunc=lambdax:xifisinstance(x,int)elsex.vaddr+x.memsize)ifpos>=len(self._sorted_list):returnNonereturnself._sorted_list[pos]
@staticmethoddef_is_region_mapped(region:R)->bool:# delayed import# pylint: disable=import-outside-toplevelfrom.elf.regionsimportELFSectionmapped=Trueifregion.memsize==0:mapped=Falseelifisinstance(region,ELFSection)andnotregion.occupies_memory:mapped=Falsereturnmapped@staticmethoddef_make_sorted(lst:list[R])->list[R]:""" Return a sorted list of regions that are mapped into memory. :param lst: A list of regions. :return: A sorted list of regions. :rtype: list """returnsorted([rforrinlstifRegions._is_region_mapped(r)],key=lambdax:x.vaddr)