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#7113 decode cache: Add analyzer library for decode_cache_t #7114

Open
wants to merge 47 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
fca712e
i#7113: Add library to cache information about decoded instructions
abhinav92003 Dec 9, 2024
abebffc
Docx improvement, and handle regdeps branch_target case.
abhinav92003 Dec 9, 2024
18f7028
Use instr_noalloc_t where possible.
abhinav92003 Dec 10, 2024
4487168
Remove redundant test.
abhinav92003 Dec 10, 2024
41595eb
move impl to cpp
abhinav92003 Dec 10, 2024
d2e94c7
Move impl to cpp
abhinav92003 Dec 10, 2024
f0f8a74
Cleanup and aarch64 mov fix.
abhinav92003 Dec 10, 2024
a1b1d63
Fix windows bug
abhinav92003 Dec 10, 2024
db8a3ad
Reviewer suggested changes
abhinav92003 Dec 10, 2024
1e810b5
Cleanup
abhinav92003 Dec 10, 2024
1fc4c04
Merge branch 'master' into i7113-decode-cache-lib
abhinav92003 Dec 14, 2024
bf76f70
Merge branch 'master' into i7113-decode-cache-lib
abhinav92003 Dec 15, 2024
45e062f
Add instr_decode_cache_t support to opcode_mix; add module_mapper_t s…
abhinav92003 Dec 15, 2024
5e28112
Drop instr_ from instr_decode_cache
abhinav92003 Dec 15, 2024
0a33a51
Handle missing use_module_mapper case
abhinav92003 Dec 15, 2024
29d10a3
Fix clang-format
abhinav92003 Dec 15, 2024
0e2df67
Make add_decode_info simpler and fix build error
abhinav92003 Dec 15, 2024
716a0ea
Cleanup
abhinav92003 Dec 15, 2024
fefe38b
Proactive destruction of module mapper
abhinav92003 Dec 16, 2024
2f0a708
Remove stale file
abhinav92003 Dec 16, 2024
84a2039
Move impl to cpp
abhinav92003 Dec 16, 2024
141e3c5
Fix when we use module mapper in opcode mix
abhinav92003 Dec 16, 2024
1092a21
Revert view deps
abhinav92003 Dec 16, 2024
b2ba91c
Use filetype instead of encoding_is_new
abhinav92003 Dec 16, 2024
d70e227
Cleanup
abhinav92003 Dec 16, 2024
d51d823
Add tmate to windows test
abhinav92003 Dec 16, 2024
0000c5b
Remove test filter
abhinav92003 Dec 16, 2024
3737ec5
Add missing standalone_init
abhinav92003 Dec 16, 2024
652bab0
Add tmate again
abhinav92003 Dec 16, 2024
1177304
Remove drmemtrace_static from test deps
abhinav92003 Dec 16, 2024
96efb50
Keep obj count tracking for tests
abhinav92003 Dec 16, 2024
31e1eab
Keep only one bool for use_module_mapper
abhinav92003 Dec 16, 2024
3702f29
Convert to doc comment
abhinav92003 Dec 16, 2024
d7a4d10
Add tmate... again
abhinav92003 Dec 16, 2024
57f34ad
Disable module mapper tests on Windows due to i#5960
abhinav92003 Dec 17, 2024
3f9cc4e
Remove tmate
abhinav92003 Dec 17, 2024
44971f6
Add TODO for some future items
abhinav92003 Dec 17, 2024
3042d6b
More apt function visibility
abhinav92003 Dec 17, 2024
2b301b5
Merge branch 'master' into i7113-decode-cache-lib
abhinav92003 Dec 19, 2024
4157f23
Reviewer suggested changes
abhinav92003 Dec 19, 2024
0f50370
Add clear_cache API for parallel_shard_exit
abhinav92003 Dec 19, 2024
8dc950c
Add optimization to avoid repeated module map lookups
abhinav92003 Dec 19, 2024
160e052
Remove common-case opt. Need add_decode_info for new encodings
abhinav92003 Dec 19, 2024
74da310
Optimize lookups into the cache
abhinav92003 Dec 19, 2024
6bcc33b
Skip re-decoding on invalid cached decode info. It's redundant.
abhinav92003 Dec 19, 2024
b24d79a
Cleanup
abhinav92003 Dec 22, 2024
e175cd9
Avoid DecodeInfo object construction when not needed.
abhinav92003 Dec 22, 2024
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
19 changes: 18 additions & 1 deletion clients/drcachesim/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,13 @@ add_exported_library(drmemtrace_view STATIC tools/view.cpp)
add_exported_library(drmemtrace_func_view STATIC tools/func_view.cpp)
add_exported_library(drmemtrace_invariant_checker STATIC tools/invariant_checker.cpp)
add_exported_library(drmemtrace_schedule_stats STATIC tools/schedule_stats.cpp)
add_exported_library(drmemtrace_instr_decode_cache STATIC
tools/common/instr_decode_cache.cpp)
add_exported_library(drmemtrace_schedule_file STATIC common/schedule_file.cpp)
add_exported_library(drmemtrace_mutex_dbg_owned STATIC common/mutex_dbg_owned.cpp)

target_link_libraries(drmemtrace_invariant_checker drdecode drmemtrace_schedule_file)
target_link_libraries(drmemtrace_invariant_checker drdecode drmemtrace_schedule_file
drmemtrace_instr_decode_cache)

configure_DynamoRIO_standalone(drmemtrace_opcode_mix)
configure_DynamoRIO_standalone(drmemtrace_view)
Expand Down Expand Up @@ -318,6 +321,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/reader)
# so that we can more cleanly separate tracer and raw2trace code.
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/tracer)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/scheduler)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/tools/common)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})

if (BUILD_PT_POST_PROCESSOR)
Expand Down Expand Up @@ -609,6 +613,7 @@ restore_nonclient_flags(drmemtrace_analyzer)
restore_nonclient_flags(drmemtrace_invariant_checker)
restore_nonclient_flags(drmemtrace_schedule_stats)
restore_nonclient_flags(drmemtrace_schedule_file)
restore_nonclient_flags(drmemtrace_instr_decode_cache)

# We need to pass /EHsc and we pull in libcmtd into drcachesim from a dep lib.
# Thus we need to override the /MT with /MTd.
Expand Down Expand Up @@ -682,6 +687,7 @@ add_win32_flags(drmemtrace_analyzer)
add_win32_flags(drmemtrace_invariant_checker)
add_win32_flags(drmemtrace_schedule_stats)
add_win32_flags(drmemtrace_schedule_file)
add_win32_flags(drmemtrace_instr_decode_cache)
add_win32_flags(directory_iterator)
add_win32_flags(test_helpers)
add_win32_flags(drmemtrace_mutex_dbg_owned)
Expand Down Expand Up @@ -940,6 +946,17 @@ if (BUILD_TESTS)
add_win32_flags(tool.drcacheoff.burst_aarch64_sys)
endif ()

add_executable(tool.drcachesim.instr_decode_cache_test
tests/instr_decode_cache_test.cpp)
configure_DynamoRIO_standalone(tool.drcachesim.instr_decode_cache_test)
add_win32_flags(tool.drcachesim.instr_decode_cache_test)
target_link_libraries(tool.drcachesim.instr_decode_cache_test
drmemtrace_static drmemtrace_instr_decode_cache test_helpers)
add_test(NAME tool.drcachesim.instr_decode_cache_test
COMMAND tool.drcachesim.instr_decode_cache_test)
set_tests_properties(tool.drcachesim.instr_decode_cache_test PROPERTIES
TIMEOUT ${test_seconds})

# XXX i#1997: dynamorio_static is not supported on Mac yet
# FIXME i#2949: gcc 7.3 fails to link certain configs
# TODO i#3544: Port tests to RISC-V 64
Expand Down
162 changes: 162 additions & 0 deletions clients/drcachesim/tests/instr_decode_cache_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/* **********************************************************
* Copyright (c) 2024 Google, LLC 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 GOOGLE, LLC 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.
*/

/* Tests for the instr_decode_cache_t library. */

#include <iostream>
#include <vector>

#include "instr_decode_cache.h"
#include "../common/memref.h"
#include "memref_gen.h"

namespace dynamorio {
namespace drmemtrace {

class test_decode_info_t : public decode_info_base_t {
public:
bool is_nop = false;
bool is_ret = false;

private:
void
set_decode_info_derived(void *dcontext,
const dynamorio::drmemtrace::_memref_instr_t &memref_instr,
instr_t *instr) override
{
is_nop = instr_is_nop(instr);
is_ret = instr_is_return(instr);
}
};

std::string
check_decode_caching(bool persist_instrs)
{
static constexpr addr_t BASE_ADDR = 0x123450;
static constexpr addr_t TID_A = 1;
instr_t *nop = XINST_CREATE_nop(GLOBAL_DCONTEXT);
instr_t *ret = XINST_CREATE_return(GLOBAL_DCONTEXT);
instrlist_t *ilist = instrlist_create(GLOBAL_DCONTEXT);
instrlist_append(ilist, nop);
instrlist_append(ilist, ret);
std::vector<memref_with_IR_t> memref_setup = {
{ gen_instr(TID_A), nop },
{ gen_instr(TID_A), ret },
{ gen_instr(TID_A), nop },
};
auto memrefs = add_encodings_to_memrefs(ilist, memref_setup, BASE_ADDR);
// Set up the second nop memref to reuse the same encoding as the first nop.
memrefs[2].instr.encoding_is_new = false;

test_decode_info_t test_decode_info;
if (test_decode_info.is_valid()) {
return "Unexpected valid default-constructed decode info";
}

if (persist_instrs) {
// These are tests to verify the operation of instr_decode_info_t: that it stores
// the instr_t correctly.
// Tests for instr_decode_cache_t are done when persist_instrs = false (see
// the else part below).
instr_decode_cache_t<instr_decode_info_t> decode_cache(
GLOBAL_DCONTEXT,
/*persist_decoded_instr=*/true);
for (const memref_t &memref : memrefs) {
decode_cache.add_decode_info(memref.instr);
}
instr_decode_info_t *decode_info_nop =
decode_cache.get_decode_info(reinterpret_cast<app_pc>(memrefs[0].instr.addr));
if (decode_info_nop == nullptr || !decode_info_nop->is_valid() ||
!instr_is_nop(decode_info_nop->get_decoded_instr())) {
return "Unexpected decode info for nop instr";
}
instr_decode_info_t *decode_info_ret =
decode_cache.get_decode_info(reinterpret_cast<app_pc>(memrefs[1].instr.addr));
if (decode_info_ret == nullptr || !decode_info_ret->is_valid() ||
!instr_is_return(decode_info_ret->get_decoded_instr())) {
return "Unexpected decode info for ret instr";
}
} else {
// These are tests to verify the operation of instr_decode_cache_t: that it caches
// decode info correctly.
instr_decode_cache_t<test_decode_info_t> decode_cache(
GLOBAL_DCONTEXT,
/*persist_decoded_instrs=*/false);
if (decode_cache.get_decode_info(
reinterpret_cast<app_pc>(memrefs[0].instr.addr)) != nullptr) {
return "Unexpected decode info for never-seen pc";
}
decode_cache.add_decode_info(memrefs[0].instr);
test_decode_info_t *decode_info_nop =
decode_cache.get_decode_info(reinterpret_cast<app_pc>(memrefs[0].instr.addr));
if (decode_info_nop == nullptr || !decode_info_nop->is_valid() ||
!decode_info_nop->is_nop) {
return "Unexpected decode info for nop instr";
}
decode_cache.add_decode_info(memrefs[1].instr);
test_decode_info_t *decode_info_ret =
decode_cache.get_decode_info(reinterpret_cast<app_pc>(memrefs[1].instr.addr));
if (decode_info_ret == nullptr || !decode_info_ret->is_valid() ||
!decode_info_ret->is_ret) {
return "Unexpected decode info for ret instr";
}
decode_cache.add_decode_info(memrefs[2].instr);
test_decode_info_t *decode_info_nop_2 =
decode_cache.get_decode_info(reinterpret_cast<app_pc>(memrefs[2].instr.addr));
if (decode_info_nop_2 != decode_info_nop) {
return "Did not see same decode info instance for second instance of nop";
}
}
instrlist_clear_and_destroy(GLOBAL_DCONTEXT, ilist);
std::cerr << "check_decode_caching with persist_instrs: " << persist_instrs
<< " passed\n";
return "";
}

int
test_main(int argc, const char *argv[])
{
std::string err = check_decode_caching(/*persist_instrs=*/false);
if (err != "") {
std::cerr << err << "\n";
exit(1);
}
err = check_decode_caching(/*persist_instrs=*/true);
if (err != "") {
std::cerr << err << "\n";
exit(1);
}
return 0;
}

} // namespace drmemtrace
} // namespace dynamorio
2 changes: 1 addition & 1 deletion clients/drcachesim/tests/invariant_checker_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class checker_no_abort_t : public invariant_checker_t {
parallel_shard_exit(keyval.second.get());
}
}
per_shard_t global;
per_shard_t global(drcontext_);
check_schedule_data(&global);
return true;
}
Expand Down
61 changes: 61 additions & 0 deletions clients/drcachesim/tools/common/instr_decode_cache.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* **********************************************************
* 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 "instr_decode_cache.h"

namespace dynamorio {
namespace drmemtrace {

instr_decode_info_t::~instr_decode_info_t()
{
if (instr_ != nullptr) {
instr_destroy(dcontext_, instr_);
}
}

void
instr_decode_info_t::set_decode_info_derived(
void *dcontext, const dynamorio::drmemtrace::_memref_instr_t &memref_instr,
instr_t *instr)
{
dcontext_ = dcontext;
instr_ = instr;
}

instr_t *
instr_decode_info_t::get_decoded_instr()
{
return instr_;
}

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