Пример #1
0
def test_signedness():
    #       0000001          item_count<<1
    #              7         item_size
    #               ffffffe0 offset<<2
    #                      1 kind
    p = 0x00000017ffffffe1
    assert ptr.offset(p) == -8
Пример #2
0
def test_new_struct():
    p = ptr.new_struct(100, 2, 4)
    assert ptr.kind(p) == ptr.STRUCT
    assert ptr.offset(p) == 100
    assert ptr.struct_data_size(p) == 2
    assert ptr.struct_ptrs_size(p) == 4
    assert p == 0x0004000200000190
Пример #3
0
def test_new_list():
    p = ptr.new_list(64, 7, 200)
    assert ptr.kind(p) == ptr.LIST
    assert ptr.offset(p) == 64
    assert ptr.list_size_tag(p) == 7
    assert ptr.list_item_count(p) == 200
    assert p == 0x0000064700000101
Пример #4
0
def test_kind_offset():
    p = 0x0004000200000190
    assert ptr.kind(p) == ptr.STRUCT
    assert ptr.offset(p) == 100
    #
    p2 = 0x0000064700000101
    assert ptr.kind(p2) == ptr.LIST
Пример #5
0
 def visit(self, buf, p, offset):
     kind = ptr.kind(p)
     offset = ptr.deref(p, offset)
     if kind == ptr.STRUCT:
         data_size = ptr.struct_data_size(p)
         ptrs_size = ptr.struct_ptrs_size(p)
         return self.visit_struct(buf, p, offset, data_size, ptrs_size)
     elif kind == ptr.LIST:
         item_size = ptr.list_size_tag(p)
         count = ptr.list_item_count(p)
         if item_size == ptr.LIST_SIZE_COMPOSITE:
             tag = buf.read_ptr(offset)
             count = ptr.offset(tag)
             data_size = ptr.struct_data_size(tag)
             ptrs_size = ptr.struct_ptrs_size(tag)
             return self.visit_list_composite(buf, p, offset,
                                               count, data_size, ptrs_size)
         elif item_size == ptr.LIST_SIZE_PTR:
             return self.visit_list_ptr(buf, p, offset, count)
         elif item_size == ptr.LIST_SIZE_BIT:
             return self.visit_list_bit(buf, p, offset, count)
         else:
             return self.visit_list_primitive(buf, p, offset, item_size, count)
     elif kind == ptr.FAR:
         raise NotImplementedError('Far pointer not supported')
     else:
         assert False, 'unknown ptr kind'
Пример #6
0
def _copy_list_composite(src, p, src_pos, dst, dst_pos):
    src_pos = ptr.deref(p, src_pos)
    total_words = ptr.list_item_count(p)  # n of words NOT including the tag
    body_length = (total_words + 1) * 8  # total length INCLUDING the tag
    #
    # check that there is enough data for both the tag AND the whole body;
    # this way we do the bound checking only once
    check_bounds(src, body_length, src_pos)
    tag = read_int64_fast(src, src_pos)
    count = ptr.offset(tag)
    data_size = ptr.struct_data_size(tag)
    ptrs_size = ptr.struct_ptrs_size(tag)
    #
    # allocate the list and copy the whole body at once
    dst_pos = dst.alloc_list(dst_pos, ptr.LIST_SIZE_COMPOSITE, total_words,
                             body_length)
    dst.write_slice(dst_pos, src, src_pos, body_length)
    #
    # iterate over the elements, fix the pointers and copy the content
    i = 0
    item_length = (data_size + ptrs_size) * 8
    ptrs_section_offset = 0
    for i in range(count):
        ptrs_section_offset = 8 + item_length * i + data_size * 8
        _copy_many_ptrs(ptrs_size, src, src_pos + ptrs_section_offset, dst,
                        dst_pos + ptrs_section_offset)
Пример #7
0
 def _split(self, extra_offset):
     """
     Split the body and the extra part.  The extra part must be placed at the
     specified offset, in words. The ptrs in the body will be adjusted
     accordingly.
     """
     body_start = self._get_body_start()
     body_end = self._get_body_end()
     if self._ptrs_size == 0:
         # easy case, just copy the body
         return self._buf.s[body_start:body_end], ''
     #
     # hard case. The layout of self._buf is like this:
     # +----------+------+------+----------+-------------+
     # | garbage0 | data | ptrs | garbage1 |    extra    |
     # +----------+------+------+----------+-------------+
     #                    |   |             ^     ^
     #                    +-----------------+     |
     #                        |                   |
     #                        +-------------------+
     #
     # We recompute the pointers assumining len(garbage1) == extra_offset
     #
     # 1) the data section is copied verbatim
     # 2) the offset of pointers in ptrs are adjusted
     # 3) extra is copied verbatim
     #
     extra_start = self._get_extra_start()
     extra_end = self._get_end()
     #
     # 1) data section
     data_size = self._data_size
     data_buf = self._buf.s[body_start:body_start+data_size*8]
     #
     # 2) ptrs section
     #    for each ptr:
     #        ptr.offset += (extra_offset - old_extra_offset)/8
     #
     # NOTE: ptr.offset is in words, extra_start and body_end in bytes
     old_extra_offset = (extra_start - body_end)/8
     additional_offset = extra_offset - old_extra_offset
     #
     # iterate over and fix the pointers
     parts = [data_buf]
     for j in range(self._ptrs_size):
         # read pointer, update its offset, and pack it
         p = self._read_raw_ptr(j*8)
         if p != 0:
             assert ptr.kind(p) != ptr.FAR
             p = ptr.new_generic(ptr.kind(p),
                                 ptr.offset(p)+additional_offset,
                                 ptr.extra(p))
         s = struct.pack('q', p)
         parts.append(s)
     #
     body_buf = ''.join(parts)
     # 3) extra part
     extra_buf = self._buf.s[extra_start:extra_end]
     #
     return body_buf, extra_buf
Пример #8
0
def test_ListPtr():
    #       0000064          item_count<<1
    #              7         item_size
    #               00000100 offset<<2
    #                      1 kind
    p = 0x0000064700000101
    assert ptr.kind(p) == ptr.LIST
    assert ptr.offset(p) == 64
    assert ptr.list_size_tag(p) == 7
    assert ptr.list_item_count(p) == 200
Пример #9
0
def test_struct_ptr():
    #       0004             ptrs size
    #           0002         data size
    #               00000190 offset<<2
    #                      0 kind
    p = 0x0004000200000190
    assert ptr.kind(p) == ptr.STRUCT
    assert ptr.offset(p) == 100
    assert ptr.struct_data_size(p) == 2
    assert ptr.struct_ptrs_size(p) == 4
Пример #10
0
 def _set_list_tag(self, size_tag, item_count):
     self._size_tag = size_tag
     if size_tag == ptr.LIST_SIZE_COMPOSITE:
         tag = self._seg.read_ptr(self._offset)
         self._tag = tag
         self._item_count = ptr.offset(tag)
         self._item_length = (ptr.struct_data_size(tag)+ptr.struct_ptrs_size(tag))*8
         self._item_offset = 8
     else:
         self._tag = -1
         self._item_count = item_count
         self._item_length = ptr.list_item_length(size_tag)
         self._item_offset = 0
Пример #11
0
    def ptr(self, offset, s):
        p = struct.unpack('q', s)[0]
        if ptr.kind(p) not in (ptr.STRUCT, ptr.LIST, ptr.FAR):
            return ' ' * 25
        #
        # try to display only "reasonable" ptrs; if the fields are too big, it
        # probably means that the current word is not a pointer
        def if_in_range(x, min, max):
            if min <= x < max:
                return str(x)
            else:
                return '?'

        #
        if p == 0:
            return 'NULL'.ljust(25)
        if ptr.kind(p) == ptr.STRUCT:
            descr = 'struct {:>4} {:>3}'.format(
                if_in_range(ptr.struct_data_size(p), 0, 100),
                if_in_range(ptr.struct_ptrs_size(p), 0, 100))

        elif ptr.kind(p) == ptr.LIST:
            tag = '<%s>' % self._list_tag(ptr.list_size_tag(p))
            descr = 'list{:<5} {:>5}'.format(
                tag, if_in_range(ptr.list_item_count(p), 0, 65536))

        elif ptr.kind(p) == ptr.FAR:
            descr = 'far {:>7} {:>3}'.format(
                ptr.far_landing_pad(p), if_in_range(ptr.far_target(p), 0, 100))
        else:
            descr = 'unknown ptr '
        #
        if -1000 < ptr.offset(p) < 1000:
            dest = ptr.deref(p, offset)
            dest = self.addr(dest)
            dest = dest.ljust(16)
        else:
            dest = '?     '
        line = '{0} to {1}'.format(descr, dest)
        if '?' in line:
            return Color.set(Color.lightgray, line)
        else:
            return line
Пример #12
0
def endof(seg, p, offset):
    """
    Check whether the given object is compact, and in that case compute its
    end boundary. If it's not compact, return -1.

    An object is compact if:

      1. there is no gap between its data section and its ptrs section

      2. there is no gap between children

      3. its children are compact

      4. there are no FAR pointers
    """
    kind = ptr.kind(p)
    offset = ptr.deref(p, offset)
    if kind == ptr.STRUCT:
        data_size = ptr.struct_data_size(p)
        ptrs_size = ptr.struct_ptrs_size(p)
        return _endof_struct(seg, p, offset, data_size, ptrs_size)
    elif kind == ptr.LIST:
        item_size = ptr.list_size_tag(p)
        count = ptr.list_item_count(p)
        if item_size == ptr.LIST_SIZE_COMPOSITE:
            tag = seg.read_ptr(offset)
            count = ptr.offset(tag)
            data_size = ptr.struct_data_size(tag)
            ptrs_size = ptr.struct_ptrs_size(tag)
            return _endof_list_composite(seg, p, offset, count, data_size,
                                         ptrs_size)
        elif item_size == ptr.LIST_SIZE_PTR:
            return _endof_list_ptr(seg, p, offset, count)
        elif item_size == ptr.LIST_SIZE_BIT:
            return _endof_list_bit(seg, p, offset, count)
        else:
            return _endof_list_primitive(seg, p, offset, item_size, count)
    elif kind == ptr.FAR:
        return -1
    else:
        assert False, 'unknown ptr kind'
Пример #13
0
 def read_far_ptr(self, offset):
     """
     Read and return the ptr referenced by this far pointer
     """
     p = self.read_ptr(offset)
     segment_start = self.segment_offsets[ptr.far_target(p)]  # in bytes
     offset = segment_start + ptr.far_offset(p) * 8
     if ptr.far_landing_pad(p) == 0:
         # simple case: the landing pad is a normal pointer, just read it
         p = self.read_ptr(offset)
         return offset, p
     else:
         # complex case. From capnproto specs:
         #     If B == 1, then the "landing pad" is itself another far
         #     pointer that is interpreted differently: This far pointer
         #     (which always has B = 0) points to the start of the object's
         #     content, located in some other segment. The landing pad is
         #     itself immediately followed by a tag word. The tag word
         #     looks exactly like an intra-segment pointer to the target
         #     object would look, except that the offset is always zero.
         #
         # read the 2nd far pointer and the tag word
         p = self.read_ptr(offset)
         ptag = self.read_ptr(offset + 8)
         assert ptr.kind(p) == ptr.FAR
         assert ptr.far_landing_pad(p) == 0
         assert ptr.offset(ptag) == 0
         # compute the absolute offset which the object is located at
         segment_start = self.segment_offsets[ptr.far_target(p)]  # in bytes
         offset = segment_start + ptr.far_offset(p) * 8
         #
         # ptag is a pointer which perfectly describes the object we want
         # to read. Remember that normally when ptr_offset==0, capnproto
         # expects the object to start at offset+8. So here we return
         # offset-8, so that the object will be read at the expected place
         return offset - 8, ptag
Пример #14
0
def test_deref():
    p = 0x0004000200000190
    assert ptr.offset(p) == 100
    offset = ptr.deref(p, 8)
    assert offset == 816
Пример #15
0
 def unpack(p):
     assert ptr.kind(p) == ptr.LIST
     return ptr.offset(p), ptr.list_size_tag(p), ptr.list_item_count(p)
Пример #16
0
 def unpack(p):
     assert ptr.kind(p) == ptr.STRUCT
     return ptr.offset(p), ptr.struct_data_size(p), ptr.struct_ptrs_size(p)