diff options
| author | Brian Potchik <brian@vector35.com> | 2024-07-18 23:06:19 -0400 |
|---|---|---|
| committer | Brian Potchik <brian@vector35.com> | 2024-07-18 23:06:19 -0400 |
| commit | 5fc08034ea071119c5407898c81d0aa012512430 (patch) | |
| tree | 8aa1b5e8351cb5df68f794a82f0205f213d25869 /python/binaryview.py | |
| parent | 4360736956684054546340387193161131118796 (diff) | |
MemoryMap update with new segment model.
Diffstat (limited to 'python/binaryview.py')
| -rw-r--r-- | python/binaryview.py | 166 |
1 files changed, 103 insertions, 63 deletions
diff --git a/python/binaryview.py b/python/binaryview.py index a18f8d8d..f1d5ff79 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -1528,36 +1528,9 @@ class Segment: return core.BNSegmentGetDataEnd(self.handle) @property - def relocation_count(self) -> int: - return core.BNSegmentGetRelocationsCount(self.handle) - - @property def auto_defined(self) -> bool: return core.BNSegmentIsAutoDefined(self.handle) - @property - def relocation_ranges(self) -> List[Tuple[int, int]]: - """List of relocation range tuples (read-only)""" - - count = ctypes.c_ulonglong() - ranges = core.BNSegmentGetRelocationRanges(self.handle, count) - assert ranges is not None, "core.BNSegmentGetRelocationRanges returned None" - try: - return [(ranges[i].start, ranges[i].end) for i in range(count.value)] - finally: - core.BNFreeRelocationRanges(ranges) - - def relocation_ranges_at(self, addr: int) -> List[Tuple[int, int]]: - """List of relocation range tuples (read-only)""" - - count = ctypes.c_ulonglong() - ranges = core.BNSegmentGetRelocationRangesAtAddress(self.handle, addr, count) - assert ranges is not None, "core.BNSegmentGetRelocationRangesAtAddress returned None" - try: - return [(ranges[i].start, ranges[i].end) for i in range(count.value)] - finally: - core.BNFreeRelocationRanges(ranges) - class Section: """ @@ -2135,35 +2108,35 @@ class MemoryMap: <region: 0x10000 - 0x10004> size: 0x4 objects: - 'origin<Mapped>' | Mapped<Absolute> + 'origin<Mapped>@0x0' | Mapped<Absolute> | <r-x> <region: 0xc0000000 - 0xc0001000> size: 0x1000 objects: - 'origin<Mapped>' | Unmapped | FILL<0x0> + 'origin<Mapped>@0xbfff0000' | Unmapped | <r--> | FILL<0x0> <region: 0xc0001000 - 0xc0001014> size: 0x14 objects: - 'origin<Mapped>' | Unmapped | FILL<0x0> - >>> view.memory_map.add_memory_region("rom", rom_base, b'\x90' * 4096) + 'origin<Mapped>@0xbfff1000' | Unmapped | <---> | FILL<0x0> + >>> view.memory_map.add_memory_region("rom", rom_base, b'\x90' * 4096, SegmentFlag.SegmentReadable | SegmentFlag.SegmentExecutable) True >>> print(view.memory_map) <region: 0x10000 - 0x10004> size: 0x4 objects: - 'origin<Mapped>' | Mapped<Absolute> + 'origin<Mapped>@0x0' | Mapped<Absolute> | <r-x> <region: 0xc0000000 - 0xc0001000> size: 0x1000 objects: - 'rom' | Mapped - 'origin<Mapped>' | Unmapped | FILL<0x0> + 'rom' | Mapped<Relative> | <r-x> + 'origin<Mapped>@0xbfff0000' | Unmapped | <r--> | FILL<0x0> <region: 0xc0001000 - 0xc0001014> size: 0x14 objects: - 'origin<Mapped>' | Unmapped | FILL<0x0> + 'origin<Mapped>@0xbfff1000' | Unmapped | <---> | FILL<0x0> >>> view.read(rom_base, 16) b'\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90' >>> view.memory_map.add_memory_region("pad", rom_base, b'\xa5' * 8) @@ -2174,25 +2147,25 @@ class MemoryMap: <region: 0x10000 - 0x10004> size: 0x4 objects: - 'origin<Mapped>' | Mapped<Absolute> + 'origin<Mapped>@0x0' | Mapped<Absolute> | <r-x> <region: 0xc0000000 - 0xc0000008> size: 0x8 objects: - 'pad' | Mapped<Relative> - 'rom' | Mapped<Relative> - 'origin<Mapped>' | Unmapped | FILL<0x0> + 'pad' | Mapped<Relative> | <---> + 'rom' | Mapped<Relative> | <r-x> + 'origin<Mapped>@0xbfff0000' | Unmapped | <r--> | FILL<0x0> <region: 0xc0000008 - 0xc0001000> size: 0xff8 objects: - 'rom' | Mapped<Relative> - 'origin<Mapped>' | Unmapped | FILL<0x0> + 'rom' | Mapped<Relative> | <r-x> + 'origin<Mapped>@0xbfff0000' | Unmapped | <r--> | FILL<0x0> <region: 0xc0001000 - 0xc0001014> size: 0x14 objects: - 'origin<Mapped>' | Unmapped | FILL<0x0> + 'origin<Mapped>@0xbfff1000' | Unmapped | <---> | FILL<0x0> """ def __repr__(self): @@ -2211,6 +2184,10 @@ class MemoryMap: else: mapped_state = "Unmapped" formatted_description += f"\t\t'{obj['name']}' | {mapped_state}" + r = "r" if obj['flags'] & SegmentFlag.SegmentReadable else "-" + w = "w" if obj['flags'] & SegmentFlag.SegmentWritable else "-" + x = "x" if obj['flags'] & SegmentFlag.SegmentExecutable else "-" + formatted_description += f" | <{r}{w}{x}>" if not obj['target']: formatted_description += f" | FILL<{hex(obj['fill'])}>" if not obj['enabled']: @@ -2233,7 +2210,7 @@ class MemoryMap: def description(self): return json.loads(core.BNGetMemoryMapDescription(self.handle)) - def add_memory_region(self, name: str, start: int, source: Union['os.PathLike', str, bytes, bytearray, 'BinaryView', 'databuffer.DataBuffer', 'fileaccessor.FileAccessor']) -> bool: + def add_memory_region(self, name: str, start: int, source: Union['os.PathLike', str, bytes, bytearray, 'BinaryView', 'databuffer.DataBuffer', 'fileaccessor.FileAccessor'], flags: SegmentFlag = 0) -> bool: """ Adds a memory region into the memory map. There are three types of memory regions that can be added: - BinaryMemoryRegion(*** Unimplemented ***): Creates a memory region from a loadable binary format and provides persistence across sessions. @@ -2272,25 +2249,34 @@ class MemoryMap: name = "" if isinstance(source, BinaryView): - return core.BNAddBinaryMemoryRegion(self.handle, name, start, source.handle) + return core.BNAddBinaryMemoryRegion(self.handle, name, start, source.handle, flags) elif isinstance(source, databuffer.DataBuffer): - return core.BNAddDataMemoryRegion(self.handle, name, start, source.handle) + return core.BNAddDataMemoryRegion(self.handle, name, start, source.handle, flags) elif isinstance(source, fileaccessor.FileAccessor): - return core.BNAddRemoteMemoryRegion(self.handle, name, start, source._cb) + return core.BNAddRemoteMemoryRegion(self.handle, name, start, source._cb, flags) else: raise NotImplementedError def remove_memory_region(self, name: str) -> bool: return core.BNRemoveMemoryRegion(self.handle, name) - def is_memory_region_enabled(self, name: str, start: int) -> bool: - return core.BNIsMemoryRegionEnabled(self.handle, name, start) + def get_active_memory_region_at(self, addr: int) -> str: + return core.BNGetActiveMemoryRegionAt(self.handle, addr) + + def is_memory_region_enabled(self, name: str) -> bool: + return core.BNIsMemoryRegionEnabled(self.handle, name) + + def set_memory_region_enabled(self, name: str, enabled: bool = True) -> bool: + return core.BNSetMemoryRegionEnabled(self.handle, name, enabled) - def set_memory_region_enabled(self, name: str, start: int, enabled: bool = True) -> bool: - return core.BNSetMemoryRegionEnabled(self.handle, name, start, enabled) + def is_memory_region_rebaseable(self, name: str) -> bool: + return core.BNIsMemoryRegionRebaseable(self.handle, name) - def set_memory_region_fill(self, name: str, start: int, fill: int) -> bool: - return core.BNSetMemoryRegionFill(self.handle, name, start, fill) + def set_memory_region_rebaseable(self, name: str, rebaseable: bool = True) -> bool: + return core.BNSetMemoryRegionRebaseable(self.handle, name, rebaseable) + + def set_memory_region_fill(self, name: str, fill: int) -> bool: + return core.BNSetMemoryRegionFill(self.handle, name, fill) def reset(self): core.BNResetMemoryMap(self.handle) @@ -2894,14 +2880,29 @@ class BinaryView: return self._file @property - def original_base(self) -> int: + def image_base(self) -> int: + """Image base of the binary""" + return core.BNGetImageBase(self.handle) + + @property + def original_image_base(self) -> int: """Original image base of the binary""" - return core.BNGetOriginalBase(self.handle) + return core.BNGetOriginalImageBase(self.handle) + + @original_image_base.setter + def original_image_base(self, image_base: int) -> None: + """Set original image base of the binary. Only intended for binary view implementations""" + return core.BNSetOriginalImageBase(self.handle, image_base) + + @property + def original_base(self) -> int: + """Original image base of the binary Deprecated: 4.0.xxxx Use original_image_base instead.""" + return core.BNGetOriginalImageBase(self.handle) @original_base.setter def original_base(self, base: int) -> None: - """Set original image base of the binary. Only intended for binary view implementations""" - return core.BNSetOriginalBase(self.handle, base) + """Set original image base of the binary. Only intended for binary view implementations. Deprecated: 4.0.xxxx Use original_image_base instead.""" + return core.BNSetOriginalImageBase(self.handle, base) @property def start(self) -> int: @@ -3311,7 +3312,7 @@ class BinaryView: @property def allocated_ranges(self) -> List['variable.AddressRange']: - """List of valid address ranges for this view (read-only)""" + """List of valid address ranges for this view (read-only) Deprecated: 4.0.xxxx Use mapped_address_ranges instead.""" count = ctypes.c_ulonglong(0) range_list = core.BNGetAllocatedRanges(self.handle, count) assert range_list is not None, "core.BNGetAllocatedRanges returned None" @@ -3324,6 +3325,34 @@ class BinaryView: core.BNFreeAddressRanges(range_list) @property + def mapped_address_ranges(self) -> List['variable.AddressRange']: + """List of mapped address ranges for this view (read-only)""" + count = ctypes.c_ulonglong(0) + range_list = core.BNGetMappedAddressRanges(self.handle, count) + assert range_list is not None, "core.BNGetMappedAddressRanges returned None" + result = [] + try: + for i in range(0, count.value): + result.append(variable.AddressRange(range_list[i].start, range_list[i].end)) + return result + finally: + core.BNFreeAddressRanges(range_list) + + @property + def backed_address_ranges(self) -> List['variable.AddressRange']: + """List of backed address ranges for this view (read-only)""" + count = ctypes.c_ulonglong(0) + range_list = core.BNGetBackedAddressRanges(self.handle, count) + assert range_list is not None, "core.BNGetBackedAddressRanges returned None" + result = [] + try: + for i in range(0, count.value): + result.append(variable.AddressRange(range_list[i].start, range_list[i].end)) + return result + finally: + core.BNFreeAddressRanges(range_list) + + @property def session_data(self): # TODO add type hint """Dictionary object where plugins can store arbitrary data associated with the view. This data is ephemeral and not saved to a database. Consider using :py:func:`store_metadata` if permanence is needed.""" handle = ctypes.cast(self.handle, ctypes.c_void_p) @@ -3379,6 +3408,17 @@ class BinaryView: finally: core.BNFreeRelocationRanges(ranges) + def relocation_ranges_in_range(self, addr: int, size: int) -> List[Tuple[int, int]]: + """List of relocation range tuples for a given range""" + + count = ctypes.c_ulonglong() + ranges = core.BNGetRelocationRangesInRange(self.handle, addr, size, count) + assert ranges is not None, "core.BNGetRelocationRangesInRange returned None" + try: + return [(ranges[i].start, ranges[i].end) for i in range(count.value)] + finally: + core.BNFreeRelocationRanges(ranges) + def range_contains_relocation(self, addr: int, size: int) -> bool: """Checks if the specified range overlaps with a relocation""" return core.BNRangeContainsRelocation(self.handle, addr, size) @@ -4177,7 +4217,7 @@ class BinaryView: if not (isinstance(data, bytes) or isinstance(data, bytearray) or isinstance(data, str)): raise TypeError("Must be bytes, bytearray, or str") buf = databuffer.DataBuffer(data) - if except_on_relocation and self.range_contains_relocation(addr, addr + len(data)): + if except_on_relocation and self.range_contains_relocation(addr, len(data)): raise RelocationWriteException("Attempting to write to a location which has a relocation") return core.BNWriteViewBuffer(self.handle, addr, buf.handle) @@ -10206,7 +10246,7 @@ class BinaryWriter: if address is not None: self.seek(address) - if except_on_relocation and self._view.range_contains_relocation(self.offset, self.offset + len(value)): + if except_on_relocation and self._view.range_contains_relocation(self.offset, len(value)): raise RelocationWriteException("Attempting to write to a location which has a relocation") if isinstance(value, str): value = value.decode("utf-8") @@ -10234,7 +10274,7 @@ class BinaryWriter: if address is not None: self.seek(address) - if except_on_relocation and self._view.range_contains_relocation(self.offset, self.offset + 1): + if except_on_relocation and self._view.range_contains_relocation(self.offset, 1): raise RelocationWriteException("Attempting to write to a location which has a relocation") return core.BNWrite8(self._handle, value) @@ -10251,7 +10291,7 @@ class BinaryWriter: if address is not None: self.seek(address) - if except_on_relocation and self._view.range_contains_relocation(self.offset, self.offset + 2): + if except_on_relocation and self._view.range_contains_relocation(self.offset, 2): raise RelocationWriteException("Attempting to write to a location which has a relocation") return core.BNWrite16(self._handle, value) @@ -10268,7 +10308,7 @@ class BinaryWriter: if address is not None: self.seek(address) - if except_on_relocation and self._view.range_contains_relocation(self.offset, self.offset + 4): + if except_on_relocation and self._view.range_contains_relocation(self.offset, 4): raise RelocationWriteException("Attempting to write to a location which has a relocation") return core.BNWrite32(self._handle, value) @@ -10285,7 +10325,7 @@ class BinaryWriter: if address is not None: self.seek(address) - if except_on_relocation and self._view.range_contains_relocation(self.offset, self.offset + 8): + if except_on_relocation and self._view.range_contains_relocation(self.offset, 8): raise RelocationWriteException("Attempting to write to a location which has a relocation") return core.BNWrite64(self._handle, value) |
