def test_read_jitlog_counter(): forest = TraceForest(1) ta = forest.add_trace('loop', 1, 0) ta.start_mark(const.MARK_TRACE_ASM) op = FlatOp(0, 'hello', '', '?', 0, 2) ta.add_instr(op) op2 = FlatOp(0, 'increment_debug_counter', '', '?', 0, 2) ta.add_instr(op2) tb = forest.add_trace('bridge', 22, 101) fw = FileObjWrapper(FileObj([encode_le_u64(0x0), b'l', encode_le_u64(20)])) assert marks.read_jitlog_counter(ParseContext(forest), None, fw) == False, \ "must not find trace" fw = FileObjWrapper( FileObj([ encode_le_u64(1), b'e', encode_le_u64(145), encode_le_u64(2), b'l', encode_le_u64(45), encode_le_u64(22), b'b', encode_le_u64(100), ])) # read the entry, the label, and the bridge assert marks.read_jitlog_counter(ParseContext(forest), None, fw) == True assert marks.read_jitlog_counter(ParseContext(forest), None, fw) == True assert marks.read_jitlog_counter(ParseContext(forest), None, fw) == True assert ta.counter == 145 assert ta.point_counters[1] == 45 assert tb.counter == 100
def test_exception_recover(): # weird file provided, fails without returning anything fobj = FileObj([0x0]) with pytest.raises(ParseException): _parse_jitlog(fobj) # incomplete log, bails and adds exception fobj = FileObj([ const.MARK_JITLOG_HEADER, b'\x01\x00\x00', encode_str('x86_64'), b'\x00' ]) f = _parse_jitlog(fobj) assert hasattr(f, 'exc') assert "marker unknown" in f.exc.args[0] # some valid data, but most of it missing fobj = FileObj([ const.MARK_JITLOG_HEADER, b'\x01\x00\x00', encode_str('x86_64'), const.MARK_START_TRACE, encode_le_u64(0xffaa), encode_str('loop'), encode_le_u64(0), const.MARK_TRACE, encode_le_u64(0xffaa), const.MARK_START_TRACE # uff, trace ends here, data missing ]) f = _parse_jitlog(fobj) assert len(f.traces) == 1 assert hasattr(f, 'exc')
def test_asm_positions(): name = struct.pack("<i", 3) + b"zAz" descr_nmr = encode_le_u64(0) fobj = FileObj([ const.MARK_RESOP_META, b"\x02\x00", b"\xff\x00\x04\x00\x00\x00fire\x00\xfe\x02\x00\x00\x00on", const.MARK_START_TRACE, encode_le_u64(0xffaa), encode_str('loop'), encode_le_u64(0), const.MARK_TRACE, encode_le_u64(0xffaa), const.MARK_INPUT_ARGS, b"\x05\x00\x00\x00i1,i2", # input args const.MARK_RESOP_DESCR, b"\xff\x00\x10\x00\x00\x00i3,i2,i1,descr()" + descr_nmr, # resop const.MARK_ASM, b"\x04\x00\x08\x00\x00\x00DEADBEEF", # resop ]) fw = FileObjWrapper(fobj) forest = construct_forest(fw) assert forest.traces[0xFFAA].inputargs == ['i1', 'i2'] assert str(forest.traces[0xFFAA].get_stage( 'noopt').ops[0]) == 'i3 = fire(i2, i1, @descr())' assert forest.traces[0xFFAA].get_stage('noopt').ops[0].core_dump == ( 4, b'DEADBEEF')
def test_v3_redirect_assembler(): # prepare a forest that already got two traces, # the first with call assembler and the target of # call assembler already included. then a read mark # redirect assembler is emulated. forest = TraceForest(3) trace = forest.add_trace('loop', 0, 0) trace.start_mark(const.MARK_TRACE_ASM) op = FlatOp(0, 'call_assembler_i', '', 'i0', 0, 15) trace.add_instr(op) # trace2 = forest.add_trace('loop', 16, 0) trace2.start_mark(const.MARK_TRACE_ASM) trace2.set_addr_bounds(42, 44) # fobj = FileObj([ const.MARK_REDIRECT_ASSEMBLER, encode_le_u64(15), encode_le_u64(17), encode_le_u64(16), ]) fw = FileObjWrapper(fobj) forest = construct_forest(fw, forest=forest) asm = forest.get_trace(16) parent = forest.get_trace(0) assert asm.get_parent() == parent assert len(parent.links) == 1
def test_32bit_log_header(): fobj = FileObj([const.MARK_JITLOG_HEADER+ b"\x01\x00\x01"+\ encode_str('ppc64le')]) forest = _parse_jitlog(fobj) assert forest.version == 1 assert forest.word_size == 4 assert forest.machine == 'ppc64le'
def test_read_resop(): fobj = FileObj([ const.MARK_RESOP_META + b"\x02\x00", b"\xff\x00\x04\x00\x00\x00call", b"\x00\xfe\x02\x00\x00\x00me" ]) fw = FileObjWrapper(fobj) forest = construct_forest(fw) assert forest.resops[0xff] == 'call' assert forest.resops[0xfe00] == 'me'
def test_v2_start_trace(): fobj = FileObj([ const.MARK_START_TRACE, encode_le_u64(0x15), encode_str('loop'), encode_le_u64(0), encode_str('jd_is_a_hippy'), ]) fw = FileObjWrapper(fobj) forest = construct_forest(fw, version=2) assert forest.get_trace(0x15).jd_name == 'jd_is_a_hippy'
def test_32bit_read_trace(): fobj = FileObj([ const.MARK_JITLOG_HEADER + b"\x01\x00\x01" + encode_str('s390x'), const.MARK_START_TRACE, encode_le_u32(0x15), encode_str('loop'), encode_le_u32(0), ]) forest = _parse_jitlog(fobj) assert forest.version == 1 assert forest.word_size == 4 assert len(forest.traces) == 1 assert forest.machine == 's390x'
def test_asm_addr(): fobj = FileObj([ const.MARK_START_TRACE, encode_le_u64(0x15), encode_str('loop'), encode_le_u64(0), const.MARK_TRACE, encode_le_u64(0x15), const.MARK_ASM_ADDR, encode_le_u64(0xAFFE), encode_le_u64(0xFEED) ]) fw = FileObjWrapper(fobj) forest = construct_forest(fw) trace = forest.get_trace(0x15) assert trace.addrs == (0xAFFE, 0xFEED) assert trace.jd_name == None
def test_counters(): descr_nmr = encode_le_u64(10) addr_len = struct.pack("<i", 8) fobj = FileObj([ const.MARK_RESOP_META + b"\x01\x00\xff\x00", encode_str("python"), const.MARK_START_TRACE, encode_le_u64(0xffaa), encode_str('loop'), encode_le_u64(0), const.MARK_TRACE, encode_le_u64(0xffaa), const.MARK_INPUT_ARGS, encode_str("i1,i2"), # input args const.MARK_RESOP_DESCR, b"\xff\x00", encode_str("i3,i2,i1,descr()") + descr_nmr, # resop const.MARK_ASM, b"\x04\x00", encode_str("DEADBEEF"), # coredump const.MARK_ASM_ADDR, encode_le_u64(0xabcdef), encode_le_u64(0xabcdff), const.MARK_JITLOG_COUNTER, encode_le_u64(0xabcdef), b'l', 15, const.MARK_JITLOG_COUNTER, encode_le_u64(0xabcdef), b'l', 0, const.MARK_JITLOG_COUNTER, encode_le_u64(0xabcdef), b'l', 15, const.MARK_JITLOG_COUNTER, encode_le_u64(0xabcfff), b'l', 5, # not counted to 0xabcdef ]) fw = FileObjWrapper(fobj) forest = construct_forest(fw) forest.get_trace_by_addr(0xabcdef).counter == 30