Skip to content

Commit 2b088db

Browse files
abhinav92003derekbruening
authored andcommitted
i#7470: Fix order of unreading split trace entries (#7469)
Fixes the order in which split trace entries such as TRACE_MARKER_TYPE_SPLIT_VALUE are unread in unread_last_entry. TRACE_MARKER_TYPE_SPLIT_VALUE must be at the front of the pre_read deque so that it is returned _before_ the actual marker, in the same order it is read from the raw trace. Adds a raw2trace_unit_test that fails with "SPLIT_VALUE marker is not adjacent to 2nd entry" due to the previously incorrect order of the split_value marker wrt the actual marker in the deque. The error was demonstrated using a large enough kernel_event marker value. This was not seen on a real trace probably because kernel_event marker values do not need the additional marker usually. There is an additional bug where raw2trace does not fully take into account the fact that some markers may be preceded by the TRACE_MARKER_TYPE_SPLIT_VALUE marker. Added a TODO for now. Issue: #7470
1 parent c689911 commit 2b088db

2 files changed

Lines changed: 38 additions & 2 deletions

File tree

clients/drcachesim/tests/raw2trace_unit_tests.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* **********************************************************
2-
* Copyright (c) 2021-2023 Google, Inc. All rights reserved.
2+
* Copyright (c) 2021-2025 Google, Inc. All rights reserved.
33
* **********************************************************/
44

55
/*
@@ -441,15 +441,27 @@ test_branch_delays(void *drcontext)
441441
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
442442
instr_t *jmp = XINST_CREATE_jump(drcontext, opnd_create_instr(move));
443443
instr_t *jcc = XINST_CREATE_jump_cond(drcontext, DR_PRED_EQ, opnd_create_instr(jmp));
444+
instr_t *jump_reg = XINST_CREATE_jump_reg(drcontext, opnd_create_reg(REG1));
445+
instr_t *move2 =
446+
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
444447
instrlist_append(ilist, nop);
445448
instrlist_append(ilist, jcc);
446449
instrlist_append(ilist, jmp);
447450
instrlist_append(ilist, move);
451+
instrlist_append(ilist, jump_reg);
452+
instrlist_append(ilist, move2);
448453
size_t offs_nop = 0;
449454
size_t offs_jz = offs_nop + instr_length(drcontext, nop);
450455
size_t offs_jmp = offs_jz + instr_length(drcontext, jcc);
451456
size_t offs_mov = offs_jmp + instr_length(drcontext, jmp);
457+
size_t offs_jump_reg = offs_mov + instr_length(drcontext, move);
458+
size_t offs_mov2 = offs_jump_reg + instr_length(drcontext, jump_reg);
452459

460+
#ifdef X64
461+
constexpr uint64_t kernel_event_value = 0x9abc12345678;
462+
#else
463+
constexpr uint32_t kernel_event_value = 0x12345678;
464+
#endif
453465
// Now we synthesize our raw trace itself, including a valid header sequence.
454466
std::vector<offline_entry_t> raw;
455467
raw.push_back(make_header());
@@ -461,6 +473,13 @@ test_branch_delays(void *drcontext)
461473
raw.push_back(make_core());
462474
raw.push_back(make_block(offs_jmp, 1));
463475
raw.push_back(make_block(offs_mov, 1));
476+
raw.push_back(make_block(offs_jump_reg, 1));
477+
#ifdef X64
478+
raw.push_back(make_marker(TRACE_MARKER_TYPE_SPLIT_VALUE, (kernel_event_value >> 32)));
479+
#endif
480+
raw.push_back(
481+
make_marker(TRACE_MARKER_TYPE_KERNEL_EVENT, (kernel_event_value & 0xffffffff)));
482+
raw.push_back(make_block(offs_mov2, 1));
464483
raw.push_back(make_exit());
465484

466485
std::vector<trace_entry_t> entries;
@@ -493,6 +512,23 @@ test_branch_delays(void *drcontext)
493512
check_entry(entries, idx, TRACE_TYPE_INSTR_DIRECT_JUMP, -1) &&
494513
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
495514
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
515+
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
516+
#ifdef X64
517+
// TODO i#7470: This is a bug. When looking for the kernel_event marker,
518+
// raw2trace doesn't look for the ones preceded by the split_value marker
519+
// because the address was too large for a single marker. Some other marker
520+
// related logic also needs to expect the split_value marker.
521+
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_BRANCH_TARGET,
522+
offs_mov2) &&
523+
#else
524+
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_BRANCH_TARGET,
525+
kernel_event_value) &&
526+
#endif
527+
check_entry(entries, idx, TRACE_TYPE_INSTR_INDIRECT_JUMP, -1) &&
528+
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_KERNEL_EVENT,
529+
kernel_event_value) &&
530+
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
531+
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
496532
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
497533
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
498534
}

clients/drcachesim/tracer/raw2trace.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2794,12 +2794,12 @@ void
27942794
raw2trace_t::unread_last_entry(raw2trace_thread_data_t *tdata)
27952795
{
27962796
VPRINT(5, "Unreading last entry\n");
2797+
tdata->pre_read.push_front(tdata->last_entry);
27972798
if (tdata->last_entry_is_split) {
27982799
VPRINT(4, "Unreading both parts of split entry at once\n");
27992800
tdata->pre_read.push_front(tdata->last_split_first_entry);
28002801
tdata->last_entry_is_split = false;
28012802
}
2802-
tdata->pre_read.push_front(tdata->last_entry);
28032803
}
28042804

28052805
void

0 commit comments

Comments
 (0)