示例#1
0
 def test_overlap_segment_head(self):
     # Existing segment:     |_______|
     # New segment:      |_______|
     prog = Program()
     segment1 = unittest.mock.Mock(side_effect=zero_memory_read)
     segment2 = unittest.mock.Mock(side_effect=zero_memory_read)
     prog.add_memory_segment(0xffff0040, 128, segment1)
     prog.add_memory_segment(0xffff0000, 128, segment2)
     prog.read(0xffff0000, 192)
     segment1.assert_called_once_with(0xffff0080, 64, 64, False)
     segment2.assert_called_once_with(0xffff0000, 128, 0, False)
示例#2
0
 def test_overlap_same_segment(self):
     # Existing segment: |_______|
     # New segment:      |_______|
     prog = Program(MOCK_PLATFORM)
     segment1 = unittest.mock.Mock(side_effect=zero_memory_read)
     segment2 = unittest.mock.Mock(side_effect=zero_memory_read)
     prog.add_memory_segment(0xFFFF0000, 128, segment1)
     prog.add_memory_segment(0xFFFF0000, 128, segment2)
     prog.read(0xFFFF0000, 128)
     segment1.assert_not_called()
     segment2.assert_called_once_with(0xFFFF0000, 128, 0, False)
示例#3
0
 def test_overlap_same_address_larger_size(self):
     # Existing segment: |___|
     # New segment:      |_______|
     prog = Program()
     segment1 = unittest.mock.Mock(side_effect=zero_memory_read)
     segment2 = unittest.mock.Mock(side_effect=zero_memory_read)
     prog.add_memory_segment(0xffff0000, 64, segment1)
     prog.add_memory_segment(0xffff0000, 128, segment2)
     prog.read(0xffff0000, 128)
     segment1.assert_not_called()
     segment2.assert_called_once_with(0xffff0000, 128, 0, False)
示例#4
0
 def test_overlap_subsume_at_and_after(self):
     # Existing segments: |_|_|_|_|
     # New segment:       |_______|
     prog = Program()
     segment1 = unittest.mock.Mock(side_effect=zero_memory_read)
     segment2 = unittest.mock.Mock(side_effect=zero_memory_read)
     prog.add_memory_segment(0xffff0000, 32, segment1)
     prog.add_memory_segment(0xffff0020, 32, segment1)
     prog.add_memory_segment(0xffff0040, 32, segment1)
     prog.add_memory_segment(0xffff0060, 32, segment1)
     prog.add_memory_segment(0xffff0000, 128, segment2)
     prog.read(0xffff0000, 128)
     segment1.assert_not_called()
     segment2.assert_called_once_with(0xffff0000, 128, 0, False)
示例#5
0
 def test_overlap_within_segment(self):
     # Existing segment: |_______|
     # New segment:        |___|
     prog = Program()
     segment1 = unittest.mock.Mock(side_effect=zero_memory_read)
     segment2 = unittest.mock.Mock(side_effect=zero_memory_read)
     prog.add_memory_segment(0xffff0000, 128, segment1)
     prog.add_memory_segment(0xffff0020, 64, segment2)
     prog.read(0xffff0000, 128)
     segment1.assert_has_calls([
         unittest.mock.call(0xffff0000, 32, 00, False),
         unittest.mock.call(0xffff0060, 32, 96, False),
     ])
     segment2.assert_called_once_with(0xffff0020, 64, 0, False)
示例#6
0
 def test_overlap_segment_head_and_tail(self):
     # Existing segment: |_______||_______|
     # New segment:          |_______|
     prog = Program(MOCK_PLATFORM)
     segment1 = unittest.mock.Mock(side_effect=zero_memory_read)
     segment2 = unittest.mock.Mock(side_effect=zero_memory_read)
     segment3 = unittest.mock.Mock(side_effect=zero_memory_read)
     prog.add_memory_segment(0xFFFF0000, 128, segment1)
     prog.add_memory_segment(0xFFFF0080, 128, segment2)
     prog.add_memory_segment(0xFFFF0040, 128, segment3)
     prog.read(0xFFFF0000, 256)
     segment1.assert_called_once_with(0xFFFF0000, 64, 0, False)
     segment2.assert_called_once_with(0xFFFF00C0, 64, 64, False)
     segment3.assert_called_once_with(0xFFFF0040, 128, 0, False)
示例#7
0
 def test_overlap_subsume_after(self):
     # Existing segments:   |_|_|_|_|
     # New segment:       |_______|
     prog = Program(MOCK_PLATFORM)
     segment1 = unittest.mock.Mock(side_effect=zero_memory_read)
     segment2 = unittest.mock.Mock(side_effect=zero_memory_read)
     segment3 = unittest.mock.Mock(side_effect=zero_memory_read)
     prog.add_memory_segment(0xFFFF0020, 32, segment1)
     prog.add_memory_segment(0xFFFF0040, 32, segment1)
     prog.add_memory_segment(0xFFFF0060, 32, segment1)
     prog.add_memory_segment(0xFFFF0080, 64, segment2)
     prog.add_memory_segment(0xFFFF0000, 128, segment3)
     prog.read(0xFFFF0000, 192)
     segment1.assert_not_called()
     segment2.assert_called_once_with(0xFFFF0080, 64, 0, False)
     segment3.assert_called_once_with(0xFFFF0000, 128, 0, False)
示例#8
0
 def test_physical(self):
     data = b'hello, world'
     prog = Program()
     with tempfile.NamedTemporaryFile() as f:
         f.write(
             create_elf_file(ET.CORE, [
                 ElfSection(
                     p_type=PT.LOAD,
                     vaddr=0xffff0000,
                     paddr=0xa0,
                     data=data,
                 ),
             ]))
         f.flush()
         prog.set_core_dump(f.name)
     self.assertEqual(prog.read(0xffff0000, len(data)), data)
     self.assertEqual(prog.read(0xa0, len(data), physical=True), data)
示例#9
0
 def test_set_pid(self):
     # Debug the running Python interpreter itself.
     prog = Program()
     self.assertEqual(prog.arch, Architecture.AUTO)
     prog.set_pid(os.getpid())
     self.assertEqual(prog.arch, Architecture.HOST)
     data = b'hello, world!'
     buf = ctypes.create_string_buffer(data)
     self.assertEqual(prog.read(ctypes.addressof(buf), len(data)), data)
     self.assertRaisesRegex(ValueError,
                            'program memory was already initialized',
                            prog.set_pid, os.getpid())
示例#10
0
 def test_simple(self):
     data = b"hello, world"
     prog = Program()
     with tempfile.NamedTemporaryFile() as f:
         f.write(
             create_elf_file(
                 ET.CORE,
                 [ElfSection(p_type=PT.LOAD, vaddr=0xFFFF0000, data=data)]))
         f.flush()
         prog.set_core_dump(f.name)
     self.assertEqual(prog.read(0xFFFF0000, len(data)), data)
     self.assertRaises(FaultError, prog.read, 0x0, len(data), physical=True)
示例#11
0
文件: printk.py 项目: osandov/drgn
def _get_printk_records_structured(prog: Program) -> List[PrintkRecord]:
    printk_logp_type = prog.type("struct printk_log *")
    have_caller_id = printk_logp_type.type.has_member("caller_id")
    LOG_CONT = prog["LOG_CONT"].value_()

    result = []
    log_buf = prog["log_buf"].read_()
    current_idx = prog["log_first_idx"].read_()
    next_idx = prog["log_next_idx"].read_()
    seq = prog["log_first_seq"].value_()
    while current_idx != next_idx:
        logp = cast(printk_logp_type, log_buf + current_idx)
        log = logp[0].read_()
        text_len = log.text_len.value_()
        dict_len = log.dict_len.value_()
        text_dict = prog.read(logp + 1, text_len + dict_len)

        if have_caller_id:
            caller_tid, caller_cpu = _caller_id(log.caller_id.value_())
        else:
            caller_tid = caller_cpu = None

        context = {}
        if dict_len:
            for elmt in text_dict[text_len:].split(b"\0"):
                key, value = elmt.split(b"=", 1)
                context[key] = value

        result.append(
            PrintkRecord(
                text=text_dict[:text_len],
                facility=log.facility.value_(),
                level=log.level.value_(),
                seq=seq,
                timestamp=log.ts_nsec.value_(),
                caller_tid=caller_tid,
                caller_cpu=caller_cpu,
                continuation=bool(log.flags.value_() & LOG_CONT),
                context=context,
            ))
        log_len = log.len.read_()
        if log_len:
            current_idx += log_len
        else:
            # Zero means the buffer wrapped around.
            if current_idx < next_idx:
                # Avoid getting into an infinite loop if the buffer is
                # corrupted.
                break
            current_idx -= current_idx
        seq += 1
    return result
示例#12
0
 def test_unsaved(self):
     data = b"hello, world"
     prog = Program()
     with tempfile.NamedTemporaryFile() as f:
         f.write(
             create_elf_file(
                 ET.CORE,
                 [
                     ElfSection(
                         p_type=PT.LOAD,
                         vaddr=0xFFFF0000,
                         data=data,
                         memsz=len(data) + 4,
                     ),
                 ],
             )
         )
         f.flush()
         prog.set_core_dump(f.name)
     with self.assertRaisesRegex(FaultError, "memory not saved in core dump") as cm:
         prog.read(0xFFFF0000, len(data) + 4)
     self.assertEqual(cm.exception.address, 0xFFFF000C)
示例#13
0
 def test_set_pid(self):
     # Debug the running Python interpreter itself.
     prog = Program()
     self.assertIsNone(prog.platform)
     self.assertFalse(prog.flags & ProgramFlags.IS_LIVE)
     prog.set_pid(os.getpid())
     self.assertEqual(prog.platform, host_platform)
     self.assertTrue(prog.flags & ProgramFlags.IS_LIVE)
     data = b'hello, world!'
     buf = ctypes.create_string_buffer(data)
     self.assertEqual(prog.read(ctypes.addressof(buf), len(data)), data)
     self.assertRaisesRegex(ValueError,
                            'program memory was already initialized',
                            prog.set_pid, os.getpid())
示例#14
0
def get_kconfig(prog: Program) -> Mapping[str, str]:
    """
    Get the kernel build configuration as a mapping from the option name to the
    value.

    >>> get_kconfig(prog)['CONFIG_SMP']
    'y'
    >>> get_kconfig(prog)['CONFIG_HZ']
    '300'

    This is only supported if the kernel was compiled with ``CONFIG_IKCONFIG``.
    Note that most Linux distributions do not enable this option.
    """
    try:
        return prog.cache["kconfig_map"]
    except KeyError:
        pass

    try:
        start = prog.symbol("kernel_config_data").address
        size = prog.symbol("kernel_config_data_end").address - start
    except LookupError:
        # Before Linux kernel commit 13610aa908dc ("kernel/configs: use .incbin
        # directive to embed config_data.gz") (in v5.1), the data is a variable
        # rather than two symbols.
        try:
            kernel_config_data = prog["kernel_config_data"]
        except KeyError:
            raise LookupError(
                "kernel configuration data not found; kernel must be compiled with CONFIG_IKCONFIG"
            )
        # The data is delimited by the magic strings "IKCFG_ST" and "IKCFG_ED"
        # plus a NUL byte.
        start = kernel_config_data.address_ + 8  # type: ignore[operator]
        size = len(kernel_config_data) - 17

    data = prog.read(start, size)
    kconfig = {}
    for line in gzip.decompress(data).decode().splitlines():
        if not line or line.startswith("#"):
            continue
        name, _, value = line.partition("=")
        if value:
            kconfig[name] = value

    # Make result mapping 'immutable', so changes cannot propagate to the cache
    result = types.MappingProxyType(kconfig)
    prog.cache["kconfig_map"] = result
    return result
示例#15
0
 def test_zero_fill(self):
     data = b'hello, world'
     prog = Program()
     with tempfile.NamedTemporaryFile() as f:
         f.write(
             create_elf_file(ET.CORE, [
                 ElfSection(
                     p_type=PT.LOAD,
                     vaddr=0xffff0000,
                     data=data,
                     memsz=len(data) + 4,
                 ),
             ]))
         f.flush()
         prog.set_core_dump(f.name)
     self.assertEqual(prog.read(0xffff0000, len(data) + 4), data + bytes(4))
示例#16
0
    def test_pid_memory(self):
        data = b"hello, world!"
        buf = ctypes.create_string_buffer(data)
        address = ctypes.addressof(buf)

        # QEMU user-mode emulation doesn't seem to emulate /proc/$pid/mem
        # correctly on a 64-bit host with a 32-bit guest; see
        # https://gitlab.com/qemu-project/qemu/-/issues/698. Packit uses mock
        # to cross-compile and test packages, which in turn uses QEMU user-mode
        # emulation. Skip this test if /proc/$pid/mem doesn't work so that
        # those builds succeed.
        try:
            with open("/proc/self/mem", "rb") as f:
                f.seek(address)
                functional_proc_pid_mem = f.read(len(data)) == data
        except OSError:
            functional_proc_pid_mem = False
        if not functional_proc_pid_mem:
            self.skipTest("/proc/$pid/mem is not functional")

        prog = Program()
        prog.set_pid(os.getpid())

        self.assertEqual(prog.read(ctypes.addressof(buf), len(data)), data)