Class AddressRangeMapDB

java.lang.Object
ghidra.program.database.util.AddressRangeMapDB
All Implemented Interfaces:
DBListener

public class AddressRangeMapDB extends Object implements DBListener
AddressRangeMapDB provides a generic value range map backed by a database table. Values can be stored for ranges of addresses. When a value is stored for a range, it replaces any previous values for that range. It is kind of like painting. If you first paint a region red, but then later paint a region in the middle of the red region green, you end up with three regions - a green region surrounded by two red regions.

This is implemented by storing records for each contiguous range with the same value.

  • The key is the encoded start address of the range.
  • The TO_COL column of the record stores the encoded end address of the range.
  • The VALUE_COL column of the record stores the value for the range.

This implementation is complicated by several issues.

  1. Addresses stored in Ghidra database records are encoded as long keys (see AddressMap). Encoded addresses do not necessarily encode to keys that have the same ordering. Therefore, all comparisons must be done in address space and not in the encoded space. Also, record iterators must use the AddressKeyRecordIterator which will return records in address order versus encoded key order.
  2. The default space's image base can be changed after records have been created. This can cause the address ranges represented by a record to wrap around. For example, suppose the image base is 0 and you paint a range from address 0 to 0x20, which say maps to keys 0 and 20, respectively. Now suppose the image base changes to 0xfffffffe, which means key 0 maps to address 0xfffffffe and key 0x20 maps to address 0x1e,(the addresses have been effectively shifted down by 2). So now the stored record has a start key of 0 and an end key of 0x20 which now maps to start address of 0xfffffffe and an end address of 0x1e. For our purposes, it is important that we don't just flip the start and end address which be a very large range instead of a small range. Instead, we need to interpret that as 2 ranges (0xfffffffe - 0xffffffff) and (0 - 0x1e). So all methods in this class have be coded to handle this special case. To simplify the painting logic, any wrapping record will first be split into two records before painting. However we can only do this during a write operation (when we can make changes). Since the getter methods and iterators cannot modify the database, they have to deal with wrapping records on the fly.
  • Field Details

  • Constructor Details

    • AddressRangeMapDB

      public AddressRangeMapDB(DBHandle dbHandle, AddressMap addressMap, Lock lock, String name, ErrorHandler errHandler, Field valueField, boolean indexed)
      Construct a generic range map
      Parameters:
      dbHandle - database handle
      addressMap - the address map
      lock - the program lock
      name - map name used in naming the underlying database table This name must be unique across all range maps
      errHandler - database error handler
      valueField - specifies the type for the values stored in this map
      indexed - if true, values will be indexed allowing use of the getValueRangeIterator method
  • Method Details

    • exists

      public static boolean exists(DBHandle dbHandle, String name)
      Tests if an AddressRangeMap table exists with the given name
      Parameters:
      dbHandle - the database handle
      name - the name to test for
      Returns:
      true if the a table exists for the given name
    • setName

      public boolean setName(String newName) throws DuplicateNameException
      Set the name associated with this range map
      Parameters:
      newName - the new name for this range map
      Returns:
      true if successful, else false
      Throws:
      DuplicateNameException - if there is already range map with that name
    • isEmpty

      public boolean isEmpty()
      Returns true if this map is empty
      Returns:
      true if this map is empty
    • getRecordCount

      public int getRecordCount()
      Returns the number of records contained within this map. NOTE: This number will be greater or equal to the number of address ranges contained within the map.
      Returns:
      record count
    • getValue

      public Field getValue(Address address)
      Returns the value associated with the given address
      Parameters:
      address - the address of the value
      Returns:
      value or null no value exists
    • paintRange

      public void paintRange(Address startAddress, Address endAddress, Field value)
      Associates the given value with every address from start to end (inclusive) Any previous associates are overwritten.
      Parameters:
      startAddress - the start address.
      endAddress - the end address.
      value - value to be painted, or null for value removal.
      Throws:
      IllegalArgumentException - if the start and end addresses are not in the same address space
      IllegalArgumentException - if the end address is greater then the start address
    • moveAddressRange

      public void moveAddressRange(Address fromAddr, Address toAddr, long length, TaskMonitor monitor) throws CancelledException
      Move all values within an address range to a new range.
      Parameters:
      fromAddr - the first address of the range to be moved.
      toAddr - the address where to the range is to be moved.
      length - the number of addresses to move.
      monitor - the task monitor.
      Throws:
      CancelledException - if the user canceled the operation via the task monitor.
    • clearRange

      public void clearRange(Address startAddr, Address endAddr)
      Remove values from the given range.
      Parameters:
      startAddr - the start address.
      endAddr - the end address.
    • getAddressSet

      public AddressSet getAddressSet()
      Returns set of addresses where a values has been set
      Returns:
      set of addresses where a values has been set
    • getAddressSet

      public AddressSet getAddressSet(Field value)
      Returns set of addresses where the given value has been set
      Parameters:
      value - the value to search for
      Returns:
      set of addresses where the given value has been set
    • getAddressRanges

      public AddressRangeIterator getAddressRanges()
      Returns an address range iterator over all ranges in the map where a value has been set
      Returns:
      AddressRangeIterator that iterates over all occupied ranges in the map
    • getAddressRanges

      public AddressRangeIterator getAddressRanges(Address startAddress)
      Returns an address range iterator over all ranges in the map where a value has been set starting with the given address
      Parameters:
      startAddress - The address at which to start iterating ranges
      Returns:
      AddressRangeIterator that iterates over all occupied ranges in the map from the given start address
    • getAddressRanges

      public AddressRangeIterator getAddressRanges(Address startAddress, Address endAddr)
      Returns an address range iterator over all ranges in the map where a value has been set starting with the given address and ending with the given end address
      Parameters:
      startAddress - the address at which to start iterating ranges
      endAddr - the address at which to end the iterator
      Returns:
      AddressRangeIterator that iterates over all occupied ranges in the map from the given start address
    • dbRestored

      public void dbRestored(DBHandle dbh)
      Description copied from interface: DBListener
      Provides notification that an undo or redo was performed. During the restore process DBListener.tableAdded(DBHandle, Table) and DBListener.tableDeleted(DBHandle, Table) notifications will be supressed. Any listener concerned with tables added or removed should reacquire their table(s).
      Specified by:
      dbRestored in interface DBListener
      Parameters:
      dbh - associated database handle
    • dbClosed

      public void dbClosed(DBHandle dbh)
      Description copied from interface: DBListener
      Database has been closed
      Specified by:
      dbClosed in interface DBListener
      Parameters:
      dbh - associated database handle
    • tableDeleted

      public void tableDeleted(DBHandle dbh, Table table)
      Description copied from interface: DBListener
      Provides notification that a table was deleted. The state of the database may still be in transition and should not be accessed by this callback method.
      Specified by:
      tableDeleted in interface DBListener
      Parameters:
      dbh - associated database handle
    • tableAdded

      public void tableAdded(DBHandle dbh, Table table)
      Description copied from interface: DBListener
      Provides notification that a table was added. The state of the database may still be in transition and should not be accessed by this callback method.
      Specified by:
      tableAdded in interface DBListener
      Parameters:
      dbh - associated database handle
    • dispose

      public void dispose()
      Deletes the database table used to store this range map.
    • invalidate

      public void invalidate()
      Notification that that something may have changed (undo/redo/image base change) and we need to invalidate our cache and possibly have a wrapping record again.
    • getAddressRangeContaining

      public AddressRange getAddressRangeContaining(Address address)
      Returns the bounding address range for the given address where all addresses in that range have the same value (this also works for now value. i.e finding a gap)
      Parameters:
      address - the address to find a range for
      Returns:
      an address range that contains the given address and has all the same value