Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i#6751 trace_entry_t: pretty printer #6771

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions clients/drcachesim/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,15 @@ add_exported_library(drmemtrace_opcode_mix STATIC tools/opcode_mix.cpp)
add_exported_library(drmemtrace_syscall_mix STATIC tools/syscall_mix.cpp)
edeiana marked this conversation as resolved.
Show resolved Hide resolved
edeiana marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To test the correctness of the printed values we compare them with the raw data using:
zcat path/to/trace.zip | od -A x -t x2 -w12 | awk '{printf "%s | %s %s %s%s%s%s\n", $1, $2, $3, $7, $6, $5, $4}'
as described here: https://dynamorio.org/page_debug_memtrace.html#autotoc_md136.

That page should be updated to point at this new tool, but please leave the od commands: as noted below some on-disk-format debugging needs to be at the real file level and not the trace_entry_t-stream level.

add_exported_library(drmemtrace_view STATIC tools/view.cpp)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a unit test similar to clients/drcachesim/tests/view_test.cpp.

Also some test that verifies the output for some checked in raw trace (e.g. clients/drcachesim/tests/drmemtrace.threadsig.aarch64.raw/raw) like clients/drcachesim/tests/offline-view.templatex.

Copy link
Contributor Author

@edeiana edeiana Apr 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's in the TODO (see PR description).
However, before working on that, I'd like to come to a consensus on the pretty printed output of internal_record_view (<--- new tool name), as that is what I will test against.

Here's what it prints now (a short "representative" snippet, note that I OMITTED a few things because I wasn't sure I could share them here... the actual output has those values):

The internal_record_view tool is a pretty printer for trace_entry_t records.
The trace_entry_t internal record format is not a public interface and is subject to change without notice.
This tool is meant for debugging only, please do not rely on the details here.
<header, trace_version: 6 == frequent_timestamps>
<marker: version 6 frequent_timestamps>
<marker: filetype 0xe40 x86_64>
<thread, tid: 259013>
<pid, pid: 259013>
<marker: cache line size OMITTED>
<marker: chunk instruction count 10000000>
<marker: page size OMITTED>
<marker: timestamp 13352585958813850>
<marker: cpu id 3>
<encoding, num_encoding_bytes: 8, encoding_bytes: OMITTED>
<instr, length: 8, pc: 0x7f6fdd3ec360>
<encoding, num_encoding_bytes: 8, encoding_bytes: OMITTED>
<direct_call, length: 8, pc: 0x7f6fdd3ec368>
<write, memref_size: 8, memref_addr: 0x7fffa4ef43c8>
<encoding, num_encoding_bytes: 8, encoding_bytes: OMITTED>
<instr, length: 8, pc: 0x7f6fdd3ec370>
<write, memref_size: 8, memref_addr: 0x7fffa4ef43c0>
...

Is it acceptable? Do we need "--------" dividers? A header at the top? Do we want to number each line? Tabs?
I'm fine with how it looks now, just wondering.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's worth spending any more time on this (esp for things like dividers and ordinals that the main view tool already has): this PR is just adding an internal tool that honestly will likely be rarely used, as evidenced by it not being needed in the past. Even now there likely is no use case where you wouldn't also go run the final view tool afterward, since that's the real view seen by tools. E.g., for your own ISA transform and filtering, you can't just go by the output of this record view tool: you have to make sure it works at the memref_t layer, so you have to use the real view tool plus invariant checks anyway. This internal tool is only a limited-use debugging step pretty much always followed up by using the "real" pretty printer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking more about when I've looked at the on-disk view with od: the most recent was debugging record_filter zip chunking support. There I had to look just before and after the 10M-instr chunk boundaries. Running od on one particular zipfile subfile at a time made this very easy. Looking at the output above with no ordinals, and having to pass in the whole trace file/dir at once: how would I focus on chunk boundaries? I might end up going back to od! I guess -skip_instructions is technically implemented for record_reader_t? But it's slow: the fast chunk skips are not implemented. Plus if the record_filter being debugged got the chunk boundary wrong I would have to go search for the chunk ord marker; if that's missing or wrong: would have to fall back to od.

Not sure there's an action item here: just an observation that this new tool is not enough to debug all on-disk issues as it abstracts away the file splits and I'm not sure it would have been useful the last time I did that. Adding ordinals would help -- but I don't know it's worth the effort. I would probably go run the regular view tool skipped to the chunk transition and take the closest timestamps and search for that in this tool's output or sthg. But I would again want to be at the real file layer instead of the trace_entry_t stream layer's abstracting away of the file divisions.

add_exported_library(drmemtrace_func_view STATIC tools/func_view.cpp)
add_exported_library(drmemtrace_record_view STATIC tools/record_view.cpp)
add_exported_library(drmemtrace_invariant_checker STATIC tools/invariant_checker.cpp)
add_exported_library(drmemtrace_schedule_stats STATIC tools/schedule_stats.cpp)

target_link_libraries(drmemtrace_invariant_checker drdecode)

configure_DynamoRIO_standalone(drmemtrace_opcode_mix)
configure_DynamoRIO_standalone(drmemtrace_view)
configure_DynamoRIO_standalone(drmemtrace_record_view)
configure_DynamoRIO_standalone(drmemtrace_invariant_checker)

# We combine the cache and TLB simulators as they share code already.
Expand Down Expand Up @@ -276,8 +278,8 @@ configure_DynamoRIO_standalone(drcachesim)
target_link_libraries(drcachesim drmemtrace_simulator drmemtrace_reuse_distance
drmemtrace_histogram drmemtrace_reuse_time drmemtrace_basic_counts
drmemtrace_opcode_mix drmemtrace_syscall_mix drmemtrace_view drmemtrace_func_view
drmemtrace_raw2trace directory_iterator drmemtrace_invariant_checker
drmemtrace_schedule_stats drmemtrace_record_filter)
drmemtrace_record_view drmemtrace_raw2trace directory_iterator
drmemtrace_invariant_checker drmemtrace_schedule_stats drmemtrace_record_filter)
if (UNIX)
target_link_libraries(drcachesim dl)
endif ()
Expand Down Expand Up @@ -357,6 +359,7 @@ install_client_nonDR_header(drmemtrace simulator/cache_simulator_create.h)
install_client_nonDR_header(drmemtrace simulator/tlb_simulator_create.h)
install_client_nonDR_header(drmemtrace tools/view_create.h)
install_client_nonDR_header(drmemtrace tools/func_view_create.h)
install_client_nonDR_header(drmemtrace tools/record_view_create.h)
# TODO i#6412: Create a separate directory for non-tracer headers so that
# we can more cleanly separate tracer and raw2trace code.
install_client_nonDR_header(drmemtrace tracer/raw2trace.h)
Expand Down Expand Up @@ -578,6 +581,7 @@ restore_nonclient_flags(drmemtrace_opcode_mix)
restore_nonclient_flags(drmemtrace_syscall_mix)
restore_nonclient_flags(drmemtrace_view)
restore_nonclient_flags(drmemtrace_func_view)
restore_nonclient_flags(drmemtrace_record_view)
restore_nonclient_flags(drmemtrace_record_filter)
restore_nonclient_flags(drmemtrace_analyzer)
restore_nonclient_flags(drmemtrace_invariant_checker)
Expand Down Expand Up @@ -644,6 +648,7 @@ add_win32_flags(drmemtrace_opcode_mix)
add_win32_flags(drmemtrace_syscall_mix)
add_win32_flags(drmemtrace_view)
add_win32_flags(drmemtrace_func_view)
add_win32_flags(drmemtrace_record_view)
add_win32_flags(drmemtrace_record_filter)
add_win32_flags(drmemtrace_analyzer)
add_win32_flags(drmemtrace_invariant_checker)
Expand Down Expand Up @@ -821,8 +826,9 @@ if (BUILD_TESTS)
drmemtrace_raw2trace drmemtrace_simulator drmemtrace_reuse_distance
drmemtrace_histogram drmemtrace_reuse_time drmemtrace_basic_counts
drmemtrace_opcode_mix drmemtrace_syscall_mix drmemtrace_view drmemtrace_func_view
drmemtrace_raw2trace directory_iterator drmemtrace_invariant_checker
drmemtrace_schedule_stats drmemtrace_analyzer drmemtrace_record_filter)
drmemtrace_record_view drmemtrace_raw2trace directory_iterator
drmemtrace_invariant_checker drmemtrace_schedule_stats drmemtrace_analyzer
drmemtrace_record_filter)
if (UNIX)
target_link_libraries(tool.drcachesim.core_sharded dl)
endif ()
Expand Down
3 changes: 3 additions & 0 deletions clients/drcachesim/analyzer_multi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
#include "tools/reuse_distance_create.h"
#include "tools/reuse_time_create.h"
#include "tools/view_create.h"
#include "tools/record_view_create.h"
#include "tools/loader/external_config_file.h"
#include "tools/loader/external_tool_creator.h"
#include "tools/filter/record_filter_create.h"
Expand Down Expand Up @@ -335,6 +336,8 @@ record_analyzer_multi_t::create_analysis_tool_from_options(
op_filter_cache_size.get_value(), op_filter_trace_types.get_value(),
op_filter_marker_types.get_value(), op_trim_before_timestamp.get_value(),
op_trim_after_timestamp.get_value(), op_verbose.get_value());
} else if (simulator_type == RECORD_VIEW) {
return record_view_tool_create(op_sim_refs.get_value());
}
ERRMSG("Usage error: unsupported record analyzer type \"%s\". Only " RECORD_FILTER
" is supported.\n",
Expand Down
1 change: 1 addition & 0 deletions clients/drcachesim/common/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#define SYSCALL_MIX "syscall_mix"
#define VIEW "view"
#define FUNC_VIEW "func_view"
#define RECORD_VIEW "record_view"
edeiana marked this conversation as resolved.
Show resolved Hide resolved
#define INVARIANT_CHECKER "invariant_checker"
#define SCHEDULE_STATS "schedule_stats"
#define RECORD_FILTER "record_filter"
Expand Down
50 changes: 50 additions & 0 deletions clients/drcachesim/common/trace_entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,55 @@ const char *const trace_type_names[] = {
"untaken_jump",
};

const char *const trace_version_names[] = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since for trace version the enum value matters, let's add the corresponding enum value too to these strings.

Copy link
Contributor Author

@edeiana edeiana Apr 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As in, for example: "trace_entry_version_no_kernel_pc" -> "trace_entry_version_no_kernel_pc_2" ? (2 is the enum value)
Although I'm not quite understanding why the enum value matters in the string representation of TRACE_ENTRY_VERSION_ enum. They have different names after all.
Unless you're referring to trace_version_names[0] (and [1]), which are "unknown"? If so, you mean I should just differentiate those 2?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I'm not quite understanding why the enum value matters in the string representation of TRACE_ENTRY_VERSION_ enum

I'm considering a use case where the user wants to know whether their trace has a version more recent than some other version (some of our tools want a minimum trace version). Having the enum value would be easier, but I guess the user can always look up the enum value themselves using just the enum string. So it's fine either way I guess.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we print the enum value along side the string?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, I didn't understand that the enum value had a meaning (larger == more recent trace version?).
I like @xdje42 suggestion. Now printing it when we print the trace_entry_t record (but not including it in trace_version_names[]).

"<unknown>",
"<unknown>",
"trace_entry_version_no_kernel_pc",
"trace_entry_version_kernel_pc",
"trace_entry_version_encodings",
"trace_entry_version_branch_info",
"trace_entry_version_frequent_timestamps",
};

const char *const trace_marker_names[] = {
edeiana marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would we want the strings at clients/drcachesim/tools/view.cpp to be replaced by these? Maybe. Add a TODO at view.cpp.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would change all the output recorded in the docs here and in the sample traces repo and in internal docs so would not be taken lightly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reverse might be an easier thing to do. See all the comments about sharing code: eliminate this array and use the existing public pretty-printer's marker printing code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

@edeiana edeiana Apr 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reverse might be an easier thing to do. See all the comments about sharing code: eliminate this array and use the existing public pretty-printer's marker printing code.

I modified this array to be consistent with view.cpp (which, now, view.cpp also uses).
I think we still want a simple string representation of a marker type, we don't want to get rid of this array.
What view.cpp does is merging together the string representation of a marker type + a marker value.

Now, trace_marker_names[] contains the string representation of marker types only, and it's used in the new trace_marker_type_value_as_string(), which returns a string representation of marker type + value (and it's, for the most part, in common between view.cpp and record_view.cpp).

"trace_marker_type_kernel_event",
"trace_marker_type_kernel_xfer",
"trace_marker_type_timestamp",
"trace_marker_type_cpu_id",
"trace_marker_type_func_id",
"trace_marker_type_func_retaddr",
"trace_marker_type_func_arg",
"trace_marker_type_func_retval",
"trace_marker_type_split_value",
"trace_marker_type_filetype",
"trace_marker_type_cache_line_size",
"trace_marker_type_instruction_count",
"trace_marker_type_version",
"trace_marker_type_rseq_abort",
"trace_marker_type_window_id",
"trace_marker_type_physical_address",
"trace_marker_type_physical_address_not_available",
"trace_marker_type_virtual_address",
"trace_marker_type_page_size",
"trace_marker_type_syscall_idx",
edeiana marked this conversation as resolved.
Show resolved Hide resolved
"trace_marker_type_chunk_instr_count",
"trace_marker_type_chunk_footer",
"trace_marker_type_record_ordinal",
"trace_marker_type_filter_endpoint",
"trace_marker_type_rseq_entry",
"trace_marker_type_syscall",
"trace_marker_type_maybe_blocking_syscall",
"trace_marker_type_syscall_trace_start",
"trace_marker_type_syscall_trace_end",
"trace_marker_type_branch_target",
"trace_marker_type_syscall_failed",
"trace_marker_type_direct_thread_switch",
"trace_marker_type_core_wait",
"trace_marker_type_core_idle",
"trace_marker_type_context_switch_start",
"trace_marker_type_context_switch_end",
"trace_marker_type_vector_length",
};
edeiana marked this conversation as resolved.
Show resolved Hide resolved

} // namespace drmemtrace
} // namespace dynamorio
2 changes: 2 additions & 0 deletions clients/drcachesim/common/trace_entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,8 @@ enum class func_trace_t : uint64_t { // VS2019 won't infer 64-bit with "enum {".
};

extern const char *const trace_type_names[];
extern const char *const trace_version_names[];
extern const char *const trace_marker_names[];

/**
* Returns whether the type represents an instruction fetch.
Expand Down
3 changes: 2 additions & 1 deletion clients/drcachesim/launcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,8 @@ _tmain(int argc, const TCHAR *targv[])
FATAL_ERROR("invalid -outdir %s", op_outdir.get_value().c_str());
}
} else {
if (op_simulator_type.get_value() == RECORD_FILTER) {
if (op_simulator_type.get_value() == RECORD_FILTER ||
op_simulator_type.get_value() == RECORD_VIEW) {
record_analyzer = new record_analyzer_multi_t;
if (!*record_analyzer) {
std::string error_string_ = record_analyzer->get_error_string();
Expand Down
215 changes: 215 additions & 0 deletions clients/drcachesim/tools/record_view.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
/* **********************************************************
* Copyright (c) 2024 Google, Inc. All rights reserved.
* **********************************************************/

/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Google, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/

#include "record_view.h"

#include <cstdio>
#include <inttypes.h>
#include <iostream>
#include <stdint.h>
#include <string>

#include "memtrace_stream.h"
#include "trace_entry.h"

namespace dynamorio {
namespace drmemtrace {

typedef unsigned int uint;

record_analysis_tool_t *
record_view_tool_create(uint64_t sim_refs)
{
return new dynamorio::drmemtrace::record_view_t(sim_refs);
}

record_view_t::record_view_t(uint64_t sim_refs)
: sim_refs_(sim_refs)
edeiana marked this conversation as resolved.
Show resolved Hide resolved
{
}

record_view_t::~record_view_t()
{
}

bool
record_view_t::should_skip(void)
{
if (sim_refs_ > 0) {
--sim_refs_;
return false;
}
return true;
}

bool
record_view_t::parallel_shard_supported()
{
return false;
}

std::string
record_view_t::initialize_shard_type(shard_type_t shard_type)
{
return "";
}

void *
record_view_t::parallel_shard_init_stream(int shard_index, void *worker_data,
memtrace_stream_t *shard_stream)
{
return shard_stream;
}

bool
record_view_t::parallel_shard_exit(void *shard_data)
{
return true;
}

std::string
record_view_t::parallel_shard_error(void *shard_data)
{
return "";
}

bool
record_view_t::parallel_shard_memref(void *shard_data, const trace_entry_t &entry)
{
if (should_skip())
return true;

trace_type_t trace_type = (trace_type_t)entry.type;
if (trace_type == TRACE_TYPE_INVALID) {
std::cerr << "ERROR: trace_entry_t invalid.\n";
return false;
}

std::string trace_type_name = std::string(trace_type_names[trace_type]);

/* Large if-else for all TRACE_TYPE_. Prints one line per trace_entry_t.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replacing this with a switch-case may be more readable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would make it even larger though, and we'd be basically replicating utility functions like: type_is_intr() or type_has_address().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would make it even larger though

Do you mean there'd be more lines of code? I'd still suggest that a switch fits the bill better. It makes it clear that we're only doing equality checks. Also: https://stackoverflow.com/questions/427760/when-to-use-if-else-if-else-over-switch-statements-and-vice-versa.

we'd be basically replicating utility functions like: type_is_intr() or type_has_address().

Can you clarify this concern? I don't understand.

Copy link
Contributor Author

@edeiana edeiana Apr 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it would be larger (not my main concern though).
With "replicating utility functions like type_is_instr()" I mean that if we move to a switch we can't use type_is_instr() or type_has_address() anymore, and a case like:

...
} else if (type_is_instr(trace_type)) {
...

Becomes:

switch (...) {
...
case TRACE_TYPE_INSTR:
case TRACE_TYPE_DIRECT_JUMP:
...
case <all remaining TRACE_TYPE_ covered by type_is_instr()>:
...
}

Listing all the TRACE_TYPE_ cases in the switch for which type_is_instr() returns true is basically replicating what type_is_instr() does, which also means that if in the future we add a new TRACE_TYPE_ that is supposed to represent an instr, then we'd have (at least) two places to update (the switch in record_view.cpp and type_is_instr() in trace_entry.h) instead of one.

I do agree that a switch would look more readable, but I think the cons outweight the pros in this case.

Unless I'm missing something?
Perhaps you meant replacing with a switch only the simple cases like:

if (trace_type == TRACE_TYPE_)

And not the whole if-else-if?

* In some cases we use some helper functions (e.g., type_is_instr()), which group
* similar TRACE_TYPE_ together, otherwise we compare trace_type against one or two
* specific TRACE_TYPE_ directly.
*/
if (trace_type == TRACE_TYPE_HEADER) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should try to share more code with clients/drcachesim/tools/view.cpp where possible; e.g. see other comments.

Copy link
Contributor Author

@edeiana edeiana Apr 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For sharing of TRACE_TYPE_ pretty printing between view.cpp and record_view.cpp we need to come to a decision for what is the right way to print TRACE_TYPE_ enum values.
Right now there are two string representations: one hardcoded in view.cpp and one in trace_type_names[] (used by other tools).
#6771 (comment)

trace_version_t trace_version = (trace_version_t)entry.addr;
std::string trace_version_name = std::string(trace_version_names[trace_version]);
std::cerr << trace_type_name << ", trace_version: " << trace_version_name << "\n";
} else if (trace_type == TRACE_TYPE_FOOTER) {
std::cerr << trace_type_name << "\n";
} else if ((trace_type == TRACE_TYPE_THREAD) ||
(trace_type == TRACE_TYPE_THREAD_EXIT)) {
uint tid = (uint)entry.addr;
std::cerr << trace_type_name << ", tid: " << tid << "\n";
} else if (trace_type == TRACE_TYPE_PID) {
uint pid = (uint)entry.addr;
std::cerr << trace_type_name << ", pid: " << pid << "\n";
} else if (trace_type == TRACE_TYPE_MARKER) {
/* XXX i#6751: we have a lot of different types of markers; we should use some
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clients/drcachesim/tools/view.cpp already has an exhaustive switch-case. It can be shared with this tool.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok.
Although not all of it can be shared.
view.cpp does some delayed printing and extra processing, which would defeat the purpose of "record_view": we want one line per trace_entry_t to show the exact sequence of on-disk records, we don't want to do the extra processing of view.cpp, it should be a 1 to 1 "mirror" of the trace file, just human readable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now sharing (between view and record_view) the printing of all TRACE_MARKER_TYPE_ cases that do not require extra processing.

* kind of dispatching mechanism to print a more informative output for each of
* them. For now we do so only for a few markers here.
*/
trace_marker_type_t trace_marker_type = (trace_marker_type_t)entry.size;
std::string trace_marker_name =
std::string(trace_marker_names[trace_marker_type]);
addr_t trace_marker_value = entry.addr;
if (trace_marker_type == TRACE_MARKER_TYPE_FILETYPE) {
std::string file_type =
std::string(trace_arch_string((offline_file_type_t)trace_marker_value));
std::cerr << trace_type_name << ", trace_marker_type: " << trace_marker_name
<< ", trace_marker_value: " << file_type << "\n";
} else if (trace_marker_type == TRACE_MARKER_TYPE_VERSION) {
trace_version_t trace_version = (trace_version_t)entry.addr;
std::string trace_version_name =
std::string(trace_version_names[trace_version]);
std::cerr << trace_type_name << ", trace_marker_type: " << trace_marker_name
<< ", trace_marker_value: " << trace_version_name << "\n";
} else { // For all remaining markers we print their value in hex.
std::cerr << trace_type_name << ", trace_marker_type: " << trace_marker_name
<< ", trace_marker_value: 0x" << std::hex << trace_marker_value
<< std::dec << "\n";
}
} else if (trace_type == TRACE_TYPE_ENCODING) {
unsigned short num_encoding_bytes = entry.size;
std::cerr << trace_type_name << ", num_encoding_bytes: " << num_encoding_bytes
<< ", encoding_bytes: 0x" << std::hex;
/* Print encoding byte by byte (little-endian).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not how encodings should be printed for AArch{32,64}.

*/
for (int i = num_encoding_bytes - 1; i >= 0; --i) {
uint encoding_byte = static_cast<uint>(entry.encoding[i]);
std::cerr << encoding_byte;
}
std::cerr << std::dec << "\n";
} else if (trace_type == TRACE_TYPE_INSTR_BUNDLE) {
unsigned short num_instructions_in_bundle = entry.size;
std::cerr << trace_type_name
<< ", num_instructions_in_bundle: " << num_instructions_in_bundle
<< ", instrs_length:";
/* Print length of each instr in the bundle.
*/
for (int i = 0; i < num_instructions_in_bundle; ++i) {
unsigned char instr_length = entry.length[i];
std::cerr << " " << instr_length;
}
std::cerr << "\n";
} else if (type_is_instr(trace_type)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clients/drcachesim/tools/view.cpp disambiguates various kinds of instrs. We should share that logic with this tool.

Copy link
Contributor Author

@edeiana edeiana Apr 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mhm, view.cpp is actually just renaming trace_type_names[], which is weird, because every other tool uses trace_type_names[], but view.cpp does not.
Should we switch this around and have view.cpp use trace_type_names[]?
Or change trace_type_names[] with what view.cpp prints?
Or does this break too much documentation and/or other assumptions I'm not aware of?
(If we decide to go this way, the aforementioned changes should go in a separate PR IMHO).

unsigned short instr_length = entry.size;
addr_t pc = entry.addr;
std::cerr << trace_type_name << ", length: " << instr_length << ", pc: 0x"
<< std::hex << pc << std::dec << "\n";
} else if (type_has_address(trace_type)) { // Includes no-fetch, prefetch, and flush.
unsigned short memref_size = entry.size;
addr_t memref_addr = entry.addr;
std::cerr << trace_type_name << ", memref_size: " << memref_size
<< ", memref_addr: 0x" << std::hex << memref_addr << std::dec << "\n";
} else {
std::cerr << "ERROR: unrecognized trace_entry_t.\n";
return false;
}
return true;
}

bool
record_view_t::process_memref(const trace_entry_t &entry)
{
return parallel_shard_memref(NULL, entry);
}

bool
record_view_t::print_results()
{
return true;
}

} // namespace drmemtrace
} // namespace dynamorio
Loading
Loading