@@ -3877,6 +3877,131 @@ test_syscall_injection(void *drcontext)
38773877 check_entry (entries, idx, TRACE_TYPE_THREAD_EXIT, -1 ) &&
38783878 check_entry (entries, idx, TRACE_TYPE_FOOTER, -1 ));
38793879}
3880+ bool
3881+ test_negative_timestamps (void *drcontext)
3882+ {
3883+ std::cerr << " \n ===============\n Testing negative timestamps\n " ;
3884+ {
3885+ // Test timestamp handling thresholds.
3886+ instrlist_t *ilist = instrlist_create (drcontext);
3887+ constexpr uint64_t TIME_A = 100 ;
3888+ constexpr uint64_t TIME_B = 110 ;
3889+ constexpr uint64_t TIME_C = 108 ; // Negative but beyond threshold.
3890+ constexpr uint64_t TIME_D = 111 ;
3891+ constexpr uint64_t TIME_E = 110 ; // Negative and under threshold.
3892+
3893+ std::vector<offline_entry_t > raw;
3894+ raw.push_back (make_header ());
3895+ raw.push_back (make_tid ());
3896+ raw.push_back (make_pid ());
3897+ raw.push_back (make_line_size ());
3898+ raw.push_back (make_timestamp (TIME_A));
3899+ raw.push_back (make_timestamp (TIME_B));
3900+ raw.push_back (make_timestamp (TIME_C));
3901+ raw.push_back (make_timestamp (TIME_D));
3902+ raw.push_back (make_timestamp (TIME_E));
3903+ raw.push_back (make_exit ());
3904+
3905+ std::vector<uint64_t > stats;
3906+ std::vector<trace_entry_t > entries;
3907+ if (!run_raw2trace (drcontext, raw, ilist, entries, &stats))
3908+ return false ;
3909+ int idx = 0 ;
3910+ if (!(stats[RAW2TRACE_STAT_NEGATIVE_TIMES_CORRECTED] == 1 &&
3911+ check_entry (entries, idx, TRACE_TYPE_HEADER, -1 ) &&
3912+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
3913+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
3914+ check_entry (entries, idx, TRACE_TYPE_THREAD, -1 ) &&
3915+ check_entry (entries, idx, TRACE_TYPE_PID, -1 ) &&
3916+ check_entry (entries, idx, TRACE_TYPE_MARKER,
3917+ TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
3918+ check_entry (entries, idx, TRACE_TYPE_MARKER,
3919+ TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
3920+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP,
3921+ TIME_A) &&
3922+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP,
3923+ TIME_B) &&
3924+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP,
3925+ // Remains negative.
3926+ TIME_C) &&
3927+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP,
3928+ TIME_D) &&
3929+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP,
3930+ // Corrected.
3931+ TIME_D) &&
3932+ check_entry (entries, idx, TRACE_TYPE_THREAD_EXIT, -1 ) &&
3933+ check_entry (entries, idx, TRACE_TYPE_FOOTER, -1 )))
3934+ return false ;
3935+ }
3936+ {
3937+ // Test timestamp handling with blocks of instrs.
3938+ instrlist_t *ilist = instrlist_create (drcontext);
3939+ instr_t *nop = XINST_CREATE_nop (drcontext);
3940+ instr_t *move =
3941+ XINST_CREATE_move (drcontext, opnd_create_reg (REG1), opnd_create_reg (REG2));
3942+ instrlist_append (ilist, nop);
3943+ instrlist_append (ilist, move);
3944+ size_t offs_nop = 0 ;
3945+ size_t offs_move = offs_nop + instr_length (drcontext, nop);
3946+
3947+ constexpr uint64_t TIME_A = 100 ;
3948+ constexpr uint64_t TIME_B = 110 ;
3949+ constexpr uint64_t TIME_C = 109 ; // Negative, under threshold.
3950+ constexpr uint64_t TIME_D = 111 ;
3951+
3952+ std::vector<offline_entry_t > raw;
3953+ raw.push_back (make_header ());
3954+ raw.push_back (make_tid ());
3955+ raw.push_back (make_pid ());
3956+ raw.push_back (make_line_size ());
3957+ raw.push_back (make_timestamp (TIME_A));
3958+ raw.push_back (make_core ());
3959+ raw.push_back (make_block (offs_move, /* instr_count=*/ 1 ));
3960+ raw.push_back (make_timestamp (TIME_B));
3961+ raw.push_back (make_core ());
3962+ raw.push_back (make_block (offs_move, /* instr_count=*/ 1 ));
3963+ raw.push_back (make_timestamp (TIME_C));
3964+ raw.push_back (make_core ());
3965+ raw.push_back (make_timestamp (TIME_D));
3966+ raw.push_back (make_core ());
3967+ raw.push_back (make_exit ());
3968+
3969+ std::vector<uint64_t > stats;
3970+ std::vector<trace_entry_t > entries;
3971+ if (!run_raw2trace (drcontext, raw, ilist, entries, &stats))
3972+ return false ;
3973+ int idx = 0 ;
3974+ return (
3975+ stats[RAW2TRACE_STAT_NEGATIVE_TIMES_CORRECTED] == 1 &&
3976+ check_entry (entries, idx, TRACE_TYPE_HEADER, -1 ) &&
3977+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
3978+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
3979+ check_entry (entries, idx, TRACE_TYPE_THREAD, -1 ) &&
3980+ check_entry (entries, idx, TRACE_TYPE_PID, -1 ) &&
3981+ check_entry (entries, idx, TRACE_TYPE_MARKER,
3982+ TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
3983+ check_entry (entries, idx, TRACE_TYPE_MARKER,
3984+ TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
3985+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP,
3986+ TIME_A) &&
3987+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
3988+ check_entry (entries, idx, TRACE_TYPE_ENCODING, -1 ) &&
3989+ check_entry (entries, idx, TRACE_TYPE_INSTR, -1 ) &&
3990+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP,
3991+ TIME_B) &&
3992+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
3993+ check_entry (entries, idx, TRACE_TYPE_INSTR, -1 ) &&
3994+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP,
3995+ // Ensure corrected from C to B:
3996+ TIME_B) &&
3997+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
3998+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP,
3999+ TIME_D) &&
4000+ check_entry (entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
4001+ check_entry (entries, idx, TRACE_TYPE_THREAD_EXIT, -1 ) &&
4002+ check_entry (entries, idx, TRACE_TYPE_FOOTER, -1 ));
4003+ }
4004+ }
38804005
38814006int
38824007test_main (int argc, const char *argv[])
@@ -3900,7 +4025,8 @@ test_main(int argc, const char *argv[])
39004025 !test_branch_decoration (drcontext) ||
39014026 !test_stats_timestamp_instr_count (drcontext) ||
39024027 !test_is_maybe_blocking_syscall (drcontext) || !test_ifiltered (drcontext) ||
3903- !test_asynchronous_signal (drcontext) || !test_syscall_injection (drcontext))
4028+ !test_asynchronous_signal (drcontext) || !test_syscall_injection (drcontext) ||
4029+ !test_negative_timestamps (drcontext))
39044030 return 1 ;
39054031 return 0 ;
39064032}
0 commit comments