Find a sinkhole which is large enough to support `length` bytes.

        This uses first-fit. The first sinkhole (ordered in descending order by their address)
        which can hold `length` bytes is chosen. If there are more than `length` bytes in the
        sinkhole, a new sinkhole is created representing the remaining bytes while the old
        sinkhole is removed.

def get_max_sinkhole(self, length):
        """
        Find a sinkhole which is large enough to support `length` bytes.

        This uses first-fit. The first sinkhole (ordered in descending order by their address)
        which can hold `length` bytes is chosen. If there are more than `length` bytes in the
        sinkhole, a new sinkhole is created representing the remaining bytes while the old
        sinkhole is removed.
        """

        ordered_sinks = sorted(list(self.sinkholes), key=operator.itemgetter(0), reverse=True)
        max_pair = None
        for addr, sz in ordered_sinks:
            if sz >= length:
                max_pair = (addr, sz)
                break

        if max_pair is None:
            return None

        remaining = max_pair[1] - length
        max_addr = max_pair[0] + remaining
        max_length = remaining

        self.sinkholes.remove(max_pair)

        if remaining:
            self.sinkholes.add((max_pair[0], max_length))

        return max_addr