* Copyright (c) 2021-2023 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 GOOGLE, 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 "dr_api.h"
#include "memref_gen.h"
#include "tracer/raw2trace.h"
#include "tracer/raw2trace_directory.h"
#include <iostream>
#include <sstream>
namespace dynamorio {
namespace drmemtrace {
#undef ASSERT
#define ASSERT(cond, msg, ...) \
do { \
if (!(cond)) { \
std::cerr << msg << "\n"; \
abort(); \
} \
} while (0)
#define CHECK(cond, msg, ...) \
do { \
if (!(cond)) { \
std::cerr << msg << "\n"; \
return false; \
} \
} while (0)
class test_multi_module_mapper_t : public module_mapper_t {
public:
struct bounds_t {
bounds_t(addr_t start, addr_t end)
: start(start)
, end(end)
{
}
addr_t start;
addr_t end;
};
test_multi_module_mapper_t(const std::vector<bounds_t> &modules)
: module_mapper_t(nullptr)
, bounds_(modules)
{
last_error_ = "";
}
protected:
void
read_and_map_modules() override
{
for (size_t i = 0; i < bounds_.size(); i++) {
modvec_.push_back(module_t("fake_module",
reinterpret_cast<app_pc>(bounds_[i].start),
nullptr, 0, bounds_[i].end - bounds_[i].start,
bounds_[i].end - bounds_[i].start, true));
}
}
private:
std::vector<bounds_t> bounds_;
};
class raw2trace_test_t : public raw2trace_t {
public:
raw2trace_test_t(const std::vector<std::istream *> &input,
const std::vector<std::ostream *> &output, instrlist_t &instrs,
void *drcontext)
: raw2trace_t(nullptr, input, output, {}, INVALID_FILE, nullptr, nullptr,
drcontext,
4)
{
module_mapper_ = std::unique_ptr<module_mapper_t>(
new test_module_mapper_t(&instrs, drcontext));
set_modmap_(module_mapper_.get());
}
raw2trace_test_t(const std::vector<std::istream *> &input,
const std::vector<archive_ostream_t *> &output, instrlist_t &instrs,
void *drcontext, uint64_t chunk_instr_count = 10 * 1000 * 1000)
: raw2trace_t(nullptr, input, {}, output, INVALID_FILE, nullptr, nullptr,
drcontext,
4, -1, "", chunk_instr_count)
{
module_mapper_ = std::unique_ptr<module_mapper_t>(
new test_module_mapper_t(&instrs, drcontext));
set_modmap_(module_mapper_.get());
}
raw2trace_test_t(const std::vector<std::istream *> &input,
const std::vector<std::ostream *> &output,
const std::vector<test_multi_module_mapper_t::bounds_t> &modules,
void *drcontext)
: raw2trace_t(nullptr, input, output, {}, INVALID_FILE, nullptr, nullptr,
drcontext,
4)
{
module_mapper_ =
std::unique_ptr<module_mapper_t>(new test_multi_module_mapper_t(modules));
set_modmap_(module_mapper_.get());
}
};
class archive_ostream_test_t : public archive_ostream_t {
public:
archive_ostream_test_t()
: archive_ostream_t(new std::basic_stringbuf<char, std::char_traits<char>>)
{
}
std::string
open_new_component(const std::string &name) override
{
return "";
}
std::string
str()
{
return reinterpret_cast<std::basic_stringbuf<char, std::char_traits<char>> *>(
rdbuf())
->str();
}
};
offline_entry_t
make_header(int version = OFFLINE_FILE_VERSION)
{
offline_entry_t entry;
entry.extended.type = OFFLINE_TYPE_EXTENDED;
entry.extended.ext = OFFLINE_EXT_TYPE_HEADER;
entry.extended.valueA = OFFLINE_FILE_TYPE_DEFAULT | OFFLINE_FILE_TYPE_ENCODINGS |
OFFLINE_FILE_TYPE_SYSCALL_NUMBERS;
entry.extended.valueB = version;
return entry;
}
offline_entry_t
make_pid()
{
offline_entry_t entry;
entry.pid.type = OFFLINE_TYPE_PID;
entry.pid.pid = 1;
return entry;
}
offline_entry_t
make_tid()
{
offline_entry_t entry;
entry.tid.type = OFFLINE_TYPE_THREAD;
entry.tid.tid = 1;
return entry;
}
offline_entry_t
make_line_size()
{
offline_entry_t entry;
entry.extended.type = OFFLINE_TYPE_EXTENDED;
entry.extended.ext = OFFLINE_EXT_TYPE_MARKER;
entry.extended.valueA = 64;
entry.extended.valueB = TRACE_MARKER_TYPE_CACHE_LINE_SIZE;
return entry;
}
offline_entry_t
make_exit()
{
offline_entry_t entry;
entry.extended.type = OFFLINE_TYPE_EXTENDED;
entry.extended.ext = OFFLINE_EXT_TYPE_FOOTER;
entry.extended.valueA = 0;
entry.extended.valueB = 0;
return entry;
}
offline_entry_t
make_block(uint64_t offs, uint64_t instr_count)
{
offline_entry_t entry;
entry.pc.type = OFFLINE_TYPE_PC;
entry.pc.modidx = 0;
entry.pc.modoffs = offs;
entry.pc.instr_count = instr_count;
return entry;
}
offline_entry_t
make_memref(uint64_t addr)
{
offline_entry_t entry;
entry.addr.type = OFFLINE_TYPE_MEMREF;
entry.addr.addr = addr;
return entry;
}
offline_entry_t
make_timestamp(uint64_t value = 0)
{
static int timecount;
offline_entry_t entry;
entry.timestamp.type = OFFLINE_TYPE_TIMESTAMP;
entry.timestamp.usec = value == 0 ? ++timecount : value;
return entry;
}
offline_entry_t
make_core()
{
offline_entry_t entry;
entry.extended.type = OFFLINE_TYPE_EXTENDED;
entry.extended.ext = OFFLINE_EXT_TYPE_MARKER;
entry.extended.valueA = 0;
entry.extended.valueB = TRACE_MARKER_TYPE_CPU_ID;
return entry;
}
offline_entry_t
make_window_id(uint64_t id)
{
offline_entry_t entry;
entry.extended.type = OFFLINE_TYPE_EXTENDED;
entry.extended.ext = OFFLINE_EXT_TYPE_MARKER;
entry.extended.valueA = id;
entry.extended.valueB = TRACE_MARKER_TYPE_WINDOW_ID;
return entry;
}
offline_entry_t
make_marker(uint64_t type, int64_t value)
{
offline_entry_t entry;
entry.extended.type = OFFLINE_TYPE_EXTENDED;
entry.extended.ext = OFFLINE_EXT_TYPE_MARKER;
entry.extended.valueA = value;
entry.extended.valueB = type;
return entry;
}
bool
check_entry(std::vector<trace_entry_t> &entries, int &idx, unsigned short expected_type,
int expected_size, addr_t expected_addr = 0)
{
if (expected_type != entries[idx].type ||
(expected_size > 0 &&
static_cast<unsigned short>(expected_size) != entries[idx].size) ||
(expected_addr > 0 && expected_addr != entries[idx].addr)) {
std::cerr << "Entry " << idx << " has type " << entries[idx].type << " and size "
<< entries[idx].size << " and addr " << entries[idx].addr
<< " != expected type " << expected_type << " and expected size "
<< expected_size << " and expected addr " << expected_addr << "\n";
return false;
}
++idx;
return true;
}
bool
run_raw2trace(void *drcontext, const std::vector<offline_entry_t> raw, instrlist_t *ilist,
std::vector<trace_entry_t> &entries, int chunk_instr_count = 0,
const std::vector<test_multi_module_mapper_t::bounds_t> &modules = {})
{
std::ostringstream raw_out;
for (const auto &entry : raw) {
std::string as_string(reinterpret_cast<const char *>(&entry),
reinterpret_cast<const char *>(&entry + 1));
raw_out << as_string;
}
std::istringstream raw_in(raw_out.str());
std::vector<std::istream *> input;
input.push_back(&raw_in);
std::string result;
if (chunk_instr_count > 0) {
archive_ostream_test_t result_stream;
std::vector<archive_ostream_t *> output;
output.push_back(&result_stream);
raw2trace_test_t raw2trace(input, output, *ilist, drcontext, chunk_instr_count);
std::string error = raw2trace.do_conversion();
CHECK(error.empty(), error);
result = result_stream.str();
} else if (modules.empty()) {
std::ostringstream result_stream;
std::vector<std::ostream *> output;
output.push_back(&result_stream);
raw2trace_test_t raw2trace(input, output, *ilist, drcontext);
std::string error = raw2trace.do_conversion();
CHECK(error.empty(), error);
result = result_stream.str();
} else {
std::ostringstream result_stream;
std::vector<std::ostream *> output;
output.push_back(&result_stream);
raw2trace_test_t raw2trace(input, output, modules, drcontext);
std::string error = raw2trace.do_conversion();
CHECK(error.empty(), error);
result = result_stream.str();
}
if (ilist != nullptr)
instrlist_clear_and_destroy(drcontext, ilist);
char *start = &result[0];
char *end = start + result.size();
CHECK(result.size() % sizeof(trace_entry_t) == 0,
"output is not a multiple of trace_entry_t");
while (start < end) {
entries.push_back(*reinterpret_cast<trace_entry_t *>(start));
start += sizeof(trace_entry_t);
}
int idx = 0;
for (const auto &entry : entries) {
std::cerr << idx << " type: " << entry.type << " size: " << entry.size
<< " val: " << entry.addr << "\n";
++idx;
}
return true;
}
bool
test_branch_delays(void *drcontext)
{
std::cerr << "\n===============\nTesting branch delays\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *jmp = XINST_CREATE_jump(drcontext, opnd_create_instr(move));
instr_t *jcc = XINST_CREATE_jump_cond(drcontext, DR_PRED_EQ, opnd_create_instr(jmp));
instrlist_append(ilist, nop);
instrlist_append(ilist, jcc);
instrlist_append(ilist, jmp);
instrlist_append(ilist, move);
size_t offs_nop = 0;
size_t offs_jz = offs_nop + instr_length(drcontext, nop);
size_t offs_jmp = offs_jz + instr_length(drcontext, jcc);
size_t offs_mov = offs_jmp + instr_length(drcontext, jmp);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_block(offs_jz, 1));
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_block(offs_jmp, 1));
raw.push_back(make_block(offs_mov, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_TAKEN_JUMP, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_DIRECT_JUMP, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_marker_placement(void *drcontext)
{
std::cerr << "\n===============\nTesting marker placement\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
#ifdef AARCH64
instr_t *load1 =
INSTR_CREATE_ldr(drcontext, opnd_create_reg(REG1),
OPND_CREATE_ABSMEM(reinterpret_cast<void *>(1024ULL), OPSZ_PTR));
#else
instr_t *load1 = XINST_CREATE_load(drcontext, opnd_create_reg(REG1),
opnd_create_mem_instr(move1, 0, OPSZ_PTR));
#endif
instr_t *move3 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instrlist_append(ilist, nop);
instrlist_append(ilist, move1);
instrlist_append(ilist, move2);
instrlist_append(ilist, load1);
instrlist_append(ilist, move3);
size_t offs_nop = 0;
size_t offs_move1 = offs_nop + instr_length(drcontext, nop);
size_t offs_move2 = offs_move1 + instr_length(drcontext, move1);
size_t offs_load1 = offs_move2 + instr_length(drcontext, move2);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_marker(TRACE_MARKER_TYPE_FUNC_ID, 0));
raw.push_back(make_marker(TRACE_MARKER_TYPE_FUNC_RETADDR, 4));
raw.push_back(make_marker(TRACE_MARKER_TYPE_FUNC_ARG, 2));
raw.push_back(make_block(offs_load1, 2));
raw.push_back(make_marker(TRACE_MARKER_TYPE_FUNC_ID, 0));
raw.push_back(make_marker(TRACE_MARKER_TYPE_FUNC_RETADDR, 4));
raw.push_back(make_marker(TRACE_MARKER_TYPE_FUNC_ARG, 2));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FUNC_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FUNC_RETADDR) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FUNC_ARG) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_READ, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FUNC_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FUNC_RETADDR) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FUNC_ARG) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_marker_delays(void *drcontext)
{
std::cerr << "\n===============\nTesting marker delays\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *jmp1 = XINST_CREATE_jump(drcontext, opnd_create_instr(move1));
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *move3 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *move4 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *move5 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *jmp2 = XINST_CREATE_jump(drcontext, opnd_create_instr(move5));
instrlist_append(ilist, nop);
instrlist_append(ilist, move1);
instrlist_append(ilist, jmp1);
instrlist_append(ilist, move2);
instrlist_append(ilist, move3);
instrlist_append(ilist, move4);
instrlist_append(ilist, move5);
instrlist_append(ilist, jmp2);
size_t offs_nop = 0;
size_t offs_move1 = offs_nop + instr_length(drcontext, nop);
size_t offs_jmp1 = offs_move1 + instr_length(drcontext, move1);
size_t offs_move2 = offs_jmp1 + instr_length(drcontext, jmp1);
size_t offs_move3 = offs_move2 + instr_length(drcontext, move2);
size_t offs_move4 = offs_move3 + instr_length(drcontext, move3);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_FUNC_ID, 0));
raw.push_back(make_marker(TRACE_MARKER_TYPE_FUNC_RETADDR, 4));
raw.push_back(make_marker(TRACE_MARKER_TYPE_FUNC_ARG, 2));
raw.push_back(make_block(offs_move2, 2));
raw.push_back(make_marker(TRACE_MARKER_TYPE_FUNC_ID, 0));
raw.push_back(make_marker(TRACE_MARKER_TYPE_FUNC_RETADDR, 4));
raw.push_back(make_marker(TRACE_MARKER_TYPE_FUNC_ARG, 2));
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_block(offs_move4, 3));
raw.push_back(make_marker(TRACE_MARKER_TYPE_FUNC_ID, 0));
raw.push_back(make_window_id(1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_DIRECT_JUMP, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FUNC_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FUNC_RETADDR) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FUNC_ARG) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FUNC_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FUNC_RETADDR) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FUNC_ARG) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_DIRECT_JUMP, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FUNC_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_WINDOW_ID) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_chunk_boundaries(void *drcontext)
{
std::cerr << "\n===============\nTesting chunk bounds\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *jmp2 = XINST_CREATE_jump(drcontext, opnd_create_instr(move2));
instr_t *jmp1 = XINST_CREATE_jump(drcontext, opnd_create_instr(jmp2));
instr_t *move3 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instrlist_append(ilist, nop);
instrlist_append(ilist, move1);
instrlist_append(ilist, jmp1);
instrlist_append(ilist, jmp2);
instrlist_append(ilist, move2);
instrlist_append(ilist, move3);
size_t offs_nop = 0;
size_t offs_move1 = offs_nop + instr_length(drcontext, nop);
size_t offs_jmp1 = offs_move1 + instr_length(drcontext, move1);
size_t offs_jmp2 = offs_jmp1 + instr_length(drcontext, jmp1);
size_t offs_move2 = offs_jmp2 + instr_length(drcontext, jmp2);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_block(offs_jmp2, 1));
raw.push_back(make_block(offs_move2, 2));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries, 2))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_DIRECT_JUMP, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CHUNK_FOOTER) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RECORD_ORDINAL) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_DIRECT_JUMP, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CHUNK_FOOTER) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RECORD_ORDINAL) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_chunk_encodings(void *drcontext)
{
std::cerr << "\n===============\nTesting chunk encoding\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *jmp2 = XINST_CREATE_jump(drcontext, opnd_create_instr(move2));
instr_t *jmp1 = XINST_CREATE_jump(drcontext, opnd_create_instr(jmp2));
instrlist_append(ilist, nop);
instrlist_append(ilist, move1);
instrlist_append(ilist, jmp1);
instrlist_append(ilist, jmp2);
instrlist_append(ilist, move2);
size_t offs_nop = 0;
size_t offs_move1 = offs_nop + instr_length(drcontext, nop);
size_t offs_jmp1 = offs_move1 + instr_length(drcontext, move1);
size_t offs_jmp2 = offs_jmp1 + instr_length(drcontext, jmp1);
size_t offs_move2 = offs_jmp2 + instr_length(drcontext, jmp2);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_block(offs_jmp2, 1));
raw.push_back(make_block(offs_move2, 1));
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_block(offs_jmp2, 1));
raw.push_back(make_block(offs_move2, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries, 6))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_DIRECT_JUMP, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_DIRECT_JUMP, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR_DIRECT_JUMP, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CHUNK_FOOTER) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RECORD_ORDINAL) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_DIRECT_JUMP, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_duplicate_syscalls(void *drcontext)
{
std::cerr << "\n===============\nTesting dup syscalls\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
#ifdef X86
instr_t *sys = INSTR_CREATE_syscall(drcontext);
#elif defined(AARCHXX)
instr_t *sys = INSTR_CREATE_svc(drcontext, opnd_create_immed_int((sbyte)0x0, OPSZ_1));
#elif defined(RISCV64)
instr_t *sys = INSTR_CREATE_ecall(drcontext);
#else
# error Unsupported architecture.
#endif
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instrlist_append(ilist, nop);
instrlist_append(ilist, move1);
instrlist_append(ilist, sys);
instrlist_append(ilist, move2);
size_t offs_nop = 0;
size_t offs_move1 = offs_nop + instr_length(drcontext, nop);
size_t offs_sys = offs_move1 + instr_length(drcontext, move1);
size_t offs_move2 = offs_sys + instr_length(drcontext, sys);
static constexpr int SYSCALL_NUM = 42;
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp(1));
raw.push_back(make_core());
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_marker(TRACE_MARKER_TYPE_SYSCALL, SYSCALL_NUM));
raw.push_back(make_timestamp(2));
raw.push_back(make_core());
raw.push_back(make_block(offs_sys, 1));
raw.push_back(make_timestamp(3));
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_SYSCALL, SYSCALL_NUM));
raw.push_back(make_timestamp(4));
raw.push_back(make_core());
raw.push_back(make_block(offs_move2, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP, 1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_SYSCALL,
SYSCALL_NUM) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP, 2) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP, 4) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_false_syscalls(void *drcontext)
{
#if defined(WINDOWS) && !defined(X64)
return true;
#else
std::cerr << "\n===============\nTesting false syscalls\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
# ifdef X86
instr_t *sys = INSTR_CREATE_syscall(drcontext);
# elif defined(AARCHXX)
instr_t *sys = INSTR_CREATE_svc(drcontext, opnd_create_immed_int((sbyte)0x0, OPSZ_1));
# elif defined(RISCV64)
instr_t *sys = INSTR_CREATE_ecall(drcontext);
# else
# error Unsupported architecture.
# endif
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instrlist_append(ilist, nop);
instrlist_append(ilist, move1);
instrlist_append(ilist, sys);
instrlist_append(ilist, move2);
size_t offs_nop = 0;
size_t offs_move1 = offs_nop + instr_length(drcontext, nop);
size_t offs_sys = offs_move1 + instr_length(drcontext, move1);
size_t offs_move2 = offs_sys + instr_length(drcontext, sys);
static constexpr int SYSCALL_NUM = 42;
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp(1));
raw.push_back(make_core());
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_timestamp(2));
raw.push_back(make_core());
raw.push_back(make_block(offs_sys, 1));
raw.push_back(make_marker(TRACE_MARKER_TYPE_SYSCALL, SYSCALL_NUM));
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_timestamp(3));
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_SYSCALL, SYSCALL_NUM));
raw.push_back(make_timestamp(4));
raw.push_back(make_core());
raw.push_back(make_block(offs_move2, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP, 1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP, 2) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_SYSCALL,
SYSCALL_NUM) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP, 3) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_SYSCALL,
SYSCALL_NUM) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP, 4) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
#endif
}
bool
test_rseq_fallthrough(void *drcontext)
{
std::cerr << "\n===============\nTesting rseq fallthrough\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *store =
XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(REG2, 0), opnd_create_reg(REG1));
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instrlist_append(ilist, nop);
instrlist_append(ilist, move1);
instrlist_append(ilist, store);
instrlist_append(ilist, move2);
size_t offs_nop = 0;
size_t offs_move1 = offs_nop + instr_length(drcontext, nop);
size_t offs_store = offs_move1 + instr_length(drcontext, move1);
size_t offs_move2 = offs_store + instr_length(drcontext, store);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ENTRY, offs_move2));
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_memref(42));
raw.push_back(make_block(offs_move2, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ENTRY) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_store) &&
check_entry(entries, idx, TRACE_TYPE_WRITE, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move2) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_rseq_rollback_legacy(void *drcontext)
{
std::cerr << "\n===============\nTesting legacy rseq rollback\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *store =
XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(REG2, 0), opnd_create_reg(REG1));
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instrlist_append(ilist, nop);
instrlist_append(ilist, move1);
instrlist_append(ilist, store);
instrlist_append(ilist, move2);
size_t offs_nop = 0;
size_t offs_move1 = offs_nop + instr_length(drcontext, nop);
size_t offs_store = offs_move1 + instr_length(drcontext, move1);
size_t offs_move2 = offs_store + instr_length(drcontext, store);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_memref(42));
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ABORT, offs_store));
raw.push_back(make_marker(TRACE_MARKER_TYPE_KERNEL_EVENT, offs_store));
raw.push_back(make_block(offs_move2, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ABORT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_KERNEL_EVENT) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move2) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_rseq_rollback(void *drcontext)
{
std::cerr << "\n===============\nTesting rseq rollback\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *store =
XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(REG2, 0), opnd_create_reg(REG1));
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instrlist_append(ilist, nop);
instrlist_append(ilist, move1);
instrlist_append(ilist, store);
instrlist_append(ilist, move2);
size_t offs_nop = 0;
size_t offs_move1 = offs_nop + instr_length(drcontext, nop);
size_t offs_store = offs_move1 + instr_length(drcontext, move1);
size_t offs_move2 = offs_store + instr_length(drcontext, store);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ENTRY, offs_move2));
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_memref(42));
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ABORT, offs_move2));
raw.push_back(make_marker(TRACE_MARKER_TYPE_KERNEL_EVENT, offs_move2));
raw.push_back(make_block(offs_move2, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ENTRY) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ABORT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_KERNEL_EVENT) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move2) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_rseq_rollback_with_timestamps(void *drcontext)
{
std::cerr << "\n===============\nTesting rseq rollback with timestamps\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *store =
XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(REG2, 0), opnd_create_reg(REG1));
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instrlist_append(ilist, nop);
instrlist_append(ilist, move1);
instrlist_append(ilist, store);
instrlist_append(ilist, move2);
size_t offs_nop = 0;
size_t offs_move1 = offs_nop + instr_length(drcontext, nop);
size_t offs_store = offs_move1 + instr_length(drcontext, move1);
size_t offs_move2 = offs_store + instr_length(drcontext, store);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ENTRY, offs_move2));
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_memref(42));
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ABORT, offs_move2));
raw.push_back(make_marker(TRACE_MARKER_TYPE_KERNEL_EVENT, offs_move2));
raw.push_back(make_block(offs_move2, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ENTRY) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ABORT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_KERNEL_EVENT) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move2) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_rseq_rollback_with_signal(void *drcontext)
{
std::cerr << "\n===============\nTesting rseq rollback with signal\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *store =
XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(REG2, 0), opnd_create_reg(REG1));
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instrlist_append(ilist, nop);
instrlist_append(ilist, move1);
instrlist_append(ilist, store);
instrlist_append(ilist, move2);
size_t offs_nop = 0;
size_t offs_move1 = offs_nop + instr_length(drcontext, nop);
size_t offs_store = offs_move1 + instr_length(drcontext, move1);
size_t offs_move2 = offs_store + instr_length(drcontext, store);
size_t offs_end = offs_move2 + instr_length(drcontext, move2);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ENTRY, offs_move2));
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_memref(42));
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ABORT, offs_end));
raw.push_back(make_marker(TRACE_MARKER_TYPE_KERNEL_EVENT, offs_end));
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_KERNEL_EVENT, offs_end));
raw.push_back(make_block(offs_move2, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ENTRY) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ABORT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_KERNEL_EVENT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_KERNEL_EVENT) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move2) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_rseq_rollback_with_chunks(void *drcontext)
{
std::cerr << "\n===============\nTesting rseq rollback with chunks\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *store =
XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(REG2, 0), opnd_create_reg(REG1));
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instrlist_append(ilist, nop);
instrlist_append(ilist, move1);
instrlist_append(ilist, store);
instrlist_append(ilist, move2);
size_t offs_nop = 0;
size_t offs_move1 = offs_nop + instr_length(drcontext, nop);
size_t offs_store = offs_move1 + instr_length(drcontext, move1);
size_t offs_move2 = offs_store + instr_length(drcontext, store);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ENTRY, offs_move2));
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_memref(42));
raw.push_back(make_block(offs_move2, 1));
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ENTRY, offs_move2));
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_memref(42));
raw.push_back(make_block(offs_move2, 1));
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ENTRY, offs_move2));
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_memref(42));
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ABORT, offs_move2));
raw.push_back(make_marker(TRACE_MARKER_TYPE_KERNEL_EVENT, offs_move2));
raw.push_back(make_block(offs_move2, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries, 6))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ENTRY) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_store) &&
check_entry(entries, idx, TRACE_TYPE_WRITE, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move2) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ENTRY) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_store) &&
check_entry(entries, idx, TRACE_TYPE_WRITE, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move2) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CHUNK_FOOTER) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RECORD_ORDINAL) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ENTRY) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ABORT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_KERNEL_EVENT) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move2) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
*
* XXX: We could test even more variants, like having multiple potential
* exits.
*/
bool
test_rseq_side_exit(void *drcontext)
{
std::cerr << "\n===============\nTesting rseq side exit\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move3 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *jcc =
XINST_CREATE_jump_cond(drcontext, DR_PRED_EQ, opnd_create_instr(move3));
instr_t *store =
XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(REG2, 0), opnd_create_reg(REG1));
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instrlist_append(ilist, nop);
instrlist_append(ilist, jcc);
instrlist_append(ilist, move1);
instrlist_append(ilist, store);
instrlist_append(ilist, move2);
instrlist_append(ilist, move3);
size_t offs_nop = 0;
size_t offs_jcc = offs_nop + instr_length(drcontext, nop);
size_t offs_move1 = offs_jcc + instr_length(drcontext, jcc);
size_t offs_store = offs_move1 + instr_length(drcontext, move1);
size_t offs_move2 = offs_store + instr_length(drcontext, store);
size_t offs_move3 = offs_move2 + instr_length(drcontext, move2);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ENTRY, offs_move2));
raw.push_back(make_block(offs_jcc, 1));
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_memref(42));
raw.push_back(make_block(offs_move3, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ENTRY) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_TAKEN_JUMP, -1, offs_jcc) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move3) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_rseq_side_exit_signal(void *drcontext)
{
std::cerr << "\n===============\nTesting rseq side exit with signal\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move3 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *jcc =
XINST_CREATE_jump_cond(drcontext, DR_PRED_EQ, opnd_create_instr(move3));
instr_t *store =
XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(REG2, 0), opnd_create_reg(REG1));
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instrlist_append(ilist, nop);
instrlist_append(ilist, jcc);
instrlist_append(ilist, move1);
instrlist_append(ilist, store);
instrlist_append(ilist, move2);
instrlist_append(ilist, move3);
size_t offs_nop = 0;
size_t offs_jcc = offs_nop + instr_length(drcontext, nop);
size_t offs_move1 = offs_jcc + instr_length(drcontext, jcc);
size_t offs_store = offs_move1 + instr_length(drcontext, move1);
size_t offs_move2 = offs_store + instr_length(drcontext, store);
size_t offs_move3 = offs_move2 + instr_length(drcontext, move2);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ENTRY, offs_move2));
raw.push_back(make_block(offs_jcc, 1));
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_memref(42));
raw.push_back(make_marker(TRACE_MARKER_TYPE_KERNEL_EVENT, offs_move3));
raw.push_back(make_block(offs_move1, 1));
raw.push_back(make_marker(TRACE_MARKER_TYPE_KERNEL_XFER, offs_store));
raw.push_back(make_block(offs_move3, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ENTRY) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_TAKEN_JUMP, -1, offs_jcc) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_KERNEL_EVENT) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_KERNEL_XFER) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move3) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_rseq_side_exit_inverted(void *drcontext)
{
std::cerr << "\n===============\nTesting inverted rseq side exit\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *move3 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instr_t *jcc =
XINST_CREATE_jump_cond(drcontext, DR_PRED_EQ, opnd_create_instr(move1));
instr_t *jmp = XINST_CREATE_jump(drcontext, opnd_create_instr(move3));
instr_t *store =
XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(REG2, 0), opnd_create_reg(REG1));
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instrlist_append(ilist, nop);
instrlist_append(ilist, jcc);
instrlist_append(ilist, jmp);
instrlist_append(ilist, move1);
instrlist_append(ilist, store);
instrlist_append(ilist, move2);
instrlist_append(ilist, move3);
size_t offs_nop = 0;
size_t offs_jcc = offs_nop + instr_length(drcontext, nop);
size_t offs_jmp = offs_jcc + instr_length(drcontext, jcc);
size_t offs_move1 = offs_jmp + instr_length(drcontext, jmp);
size_t offs_store = offs_move1 + instr_length(drcontext, move1);
size_t offs_move2 = offs_store + instr_length(drcontext, store);
size_t offs_move3 = offs_move2 + instr_length(drcontext, move2);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ENTRY, offs_move2));
raw.push_back(make_block(offs_jcc, 1));
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_memref(42));
raw.push_back(make_block(offs_move3, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ENTRY) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_UNTAKEN_JUMP, -1, offs_jcc) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_DIRECT_JUMP, -1, offs_jmp) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move3) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_rseq_side_exit_inverted_with_timestamp(void *drcontext)
{
std::cerr << "\n===============\nTesting inverted rseq side exit with timestamp\n";
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop = XINST_CREATE_nop(drcontext);
instr_t *move1 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *move3 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instr_t *jcc =
XINST_CREATE_jump_cond(drcontext, DR_PRED_EQ, opnd_create_instr(move1));
instr_t *jmp = XINST_CREATE_jump(drcontext, opnd_create_instr(move3));
instr_t *store =
XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(REG2, 0), opnd_create_reg(REG1));
instr_t *move2 =
XINST_CREATE_move(drcontext, opnd_create_reg(REG2), opnd_create_reg(REG1));
instrlist_append(ilist, nop);
instrlist_append(ilist, jcc);
instrlist_append(ilist, jmp);
instrlist_append(ilist, move1);
instrlist_append(ilist, store);
instrlist_append(ilist, move2);
instrlist_append(ilist, move3);
size_t offs_nop = 0;
size_t offs_jcc = offs_nop + instr_length(drcontext, nop);
size_t offs_jmp = offs_jcc + instr_length(drcontext, jcc);
size_t offs_move1 = offs_jmp + instr_length(drcontext, jmp);
size_t offs_store = offs_move1 + instr_length(drcontext, move1);
size_t offs_move2 = offs_store + instr_length(drcontext, store);
size_t offs_move3 = offs_move2 + instr_length(drcontext, move2);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ENTRY, offs_move2));
raw.push_back(make_block(offs_jcc, 1));
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_memref(42));
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_block(offs_move3, 1));
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ENTRY, offs_move2));
raw.push_back(make_block(offs_jcc, 1));
raw.push_back(make_block(offs_move1, 2));
raw.push_back(make_memref(42));
raw.push_back(make_block(offs_move2, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ENTRY) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_UNTAKEN_JUMP, -1, offs_jcc) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_DIRECT_JUMP, -1, offs_jmp) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move3) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ENTRY) &&
check_entry(entries, idx, TRACE_TYPE_INSTR_TAKEN_JUMP, -1, offs_jcc) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_store) &&
check_entry(entries, idx, TRACE_TYPE_WRITE, -1) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_move2) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_xfer_modoffs(void *drcontext)
{
#ifndef X64
return true;
#else
std::cerr << "\n===============\nTesting legacy kernel xfer values\n";
std::vector<test_multi_module_mapper_t::bounds_t> modules = {
{ 100, 150 },
{ 400, 450 },
};
kernel_interrupted_raw_pc_t interrupt;
interrupt.pc.modidx = 1;
interrupt.pc.modoffs = 42;
std::vector<offline_entry_t> raw;
raw.push_back(make_header(OFFLINE_FILE_VERSION_ENCODINGS));
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_KERNEL_EVENT, interrupt.combined_value));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, nullptr, entries, 0, modules))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_KERNEL_EVENT,
static_cast<addr_t>(modules[interrupt.pc.modidx].start +
interrupt.pc.modoffs)) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
#endif
}
bool
test_xfer_absolute(void *drcontext)
{
std::cerr << "\n===============\nTesting legacy kernel xfer values\n";
std::vector<test_multi_module_mapper_t::bounds_t> modules = {
{ 100, 150 },
{ 400, 450 },
};
constexpr addr_t INT_PC = 442;
std::vector<offline_entry_t> raw;
raw.push_back(make_header(OFFLINE_FILE_VERSION_XFER_ABS_PC));
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_timestamp());
raw.push_back(make_core());
raw.push_back(make_marker(TRACE_MARKER_TYPE_KERNEL_EVENT, INT_PC));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, nullptr, entries, 0, modules))
return false;
int idx = 0;
return (
check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_KERNEL_EVENT,
INT_PC) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1));
}
bool
test_branch_decoration(void *drcontext)
{
std::cerr << "\n===============\nTesting branch decoration\n";
bool res = true;
{
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop1 = XINST_CREATE_nop(drcontext);
instr_t *move =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *jcc =
XINST_CREATE_jump_cond(drcontext, DR_PRED_EQ, opnd_create_instr(move));
instr_t *nop2 = XINST_CREATE_nop(drcontext);
instrlist_append(ilist, nop1);
instrlist_append(ilist, jcc);
instrlist_append(ilist, nop2);
instrlist_append(ilist, move);
size_t offs_nop1 = 0;
size_t offs_jcc = offs_nop1 + instr_length(drcontext, nop1);
size_t offs_nop2 = offs_jcc + instr_length(drcontext, jcc);
size_t offs_mov = offs_nop2 + instr_length(drcontext, nop2);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_block(offs_jcc, 1));
raw.push_back(make_marker(TRACE_MARKER_TYPE_KERNEL_EVENT, offs_mov));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
res = res && check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_TAKEN_JUMP, -1, offs_jcc) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_KERNEL_EVENT,
offs_mov) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1);
}
{
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop1 = XINST_CREATE_nop(drcontext);
instr_t *move =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *jcc =
XINST_CREATE_jump_cond(drcontext, DR_PRED_EQ, opnd_create_instr(move));
instr_t *nop2 = XINST_CREATE_nop(drcontext);
instrlist_append(ilist, nop1);
instrlist_append(ilist, jcc);
instrlist_append(ilist, nop2);
instrlist_append(ilist, move);
size_t offs_nop1 = 0;
size_t offs_jcc = offs_nop1 + instr_length(drcontext, nop1);
size_t offs_nop2 = offs_jcc + instr_length(drcontext, jcc);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_block(offs_jcc, 1));
raw.push_back(make_marker(TRACE_MARKER_TYPE_KERNEL_EVENT, offs_nop2));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
res = res && check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_UNTAKEN_JUMP, -1, offs_jcc) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_KERNEL_EVENT,
offs_nop2) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1);
}
{
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop1 = XINST_CREATE_nop(drcontext);
instr_t *move =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *jcc =
XINST_CREATE_jump_cond(drcontext, DR_PRED_EQ, opnd_create_instr(move));
instr_t *store = XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(REG2, 0),
opnd_create_reg(REG1));
instrlist_append(ilist, nop1);
instrlist_append(ilist, jcc);
instrlist_append(ilist, store);
instrlist_append(ilist, move);
size_t offs_nop1 = 0;
size_t offs_jcc = offs_nop1 + instr_length(drcontext, nop1);
size_t offs_store = offs_jcc + instr_length(drcontext, jcc);
size_t offs_mov = offs_store + instr_length(drcontext, store);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ENTRY, offs_mov));
raw.push_back(make_block(offs_jcc, 1));
raw.push_back(make_block(offs_store, 1));
raw.push_back(make_memref(42));
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ABORT, offs_mov));
raw.push_back(make_marker(TRACE_MARKER_TYPE_KERNEL_EVENT, offs_mov));
raw.push_back(make_block(offs_mov, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
res = res && check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ENTRY) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_UNTAKEN_JUMP, -1, offs_jcc) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ABORT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_KERNEL_EVENT,
offs_mov) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_mov) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1);
}
{
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop1 = XINST_CREATE_nop(drcontext);
instr_t *nop2 = XINST_CREATE_nop(drcontext);
instr_t *nop3 = XINST_CREATE_nop(drcontext);
instr_t *move =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *store = XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(REG2, 0),
opnd_create_reg(REG1));
instr_t *jcc =
XINST_CREATE_jump_cond(drcontext, DR_PRED_EQ, opnd_create_instr(store));
instrlist_append(ilist, nop1);
instrlist_append(ilist, jcc);
instrlist_append(ilist, nop2);
instrlist_append(ilist, nop3);
instrlist_append(ilist, store);
instrlist_append(ilist, move);
size_t offs_nop1 = 0;
size_t offs_jcc = offs_nop1 + instr_length(drcontext, nop1);
size_t offs_nop2 = offs_jcc + instr_length(drcontext, jcc);
size_t offs_nop3 = offs_nop2 + instr_length(drcontext, nop2);
size_t offs_store = offs_nop3 + instr_length(drcontext, nop3);
size_t offs_mov = offs_store + instr_length(drcontext, store);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ENTRY, offs_mov));
raw.push_back(make_block(offs_jcc, 1));
raw.push_back(make_block(offs_store, 1));
raw.push_back(make_memref(42));
raw.push_back(make_marker(TRACE_MARKER_TYPE_RSEQ_ABORT, offs_mov));
raw.push_back(make_marker(TRACE_MARKER_TYPE_KERNEL_EVENT, offs_mov));
raw.push_back(make_block(offs_mov, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
res = res && check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ENTRY) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_TAKEN_JUMP, -1, offs_jcc) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_RSEQ_ABORT) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_KERNEL_EVENT,
offs_mov) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_mov) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1);
}
{
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop1 = XINST_CREATE_nop(drcontext);
instr_t *nop2 = XINST_CREATE_nop(drcontext);
instr_t *store = XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(REG2, 0),
opnd_create_reg(REG1));
instr_t *jcc =
XINST_CREATE_jump_cond(drcontext, DR_PRED_EQ, opnd_create_instr(store));
instr_t *move =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instrlist_append(ilist, nop1);
instrlist_append(ilist, move);
instrlist_append(ilist, jcc);
instrlist_append(ilist, nop2);
instrlist_append(ilist, store);
size_t offs_nop1 = 0;
size_t offs_mov = offs_nop1 + instr_length(drcontext, nop1);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_block(offs_mov, 2));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
res = res && check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_mov) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1);
}
{
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop1 = XINST_CREATE_nop(drcontext);
instr_t *nop2 = XINST_CREATE_nop(drcontext);
instr_t *store = XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(REG2, 0),
opnd_create_reg(REG1));
instr_t *jcc =
XINST_CREATE_jump_cond(drcontext, DR_PRED_EQ, opnd_create_instr(store));
instr_t *move =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instrlist_append(ilist, nop1);
instrlist_append(ilist, move);
instrlist_append(ilist, jcc);
instrlist_append(ilist, nop2);
instrlist_append(ilist, store);
size_t offs_nop1 = 0;
size_t offs_mov = offs_nop1 + instr_length(drcontext, nop1);
size_t offs_jcc = offs_mov + instr_length(drcontext, move);
size_t offs_nop2 = offs_jcc + instr_length(drcontext, jcc);
size_t offs_store = offs_nop2 + instr_length(drcontext, nop2);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_block(offs_mov, 2));
raw.push_back(make_window_id(1));
raw.push_back(make_block(offs_mov, 2));
raw.push_back(make_block(offs_store, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
res = res && check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_mov) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_WINDOW_ID) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_mov) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_TAKEN_JUMP, -1, offs_jcc) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_store) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1);
}
{
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *nop1 = XINST_CREATE_nop(drcontext);
instr_t *nop2 = XINST_CREATE_nop(drcontext);
instr_t *store = XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(REG2, 0),
opnd_create_reg(REG1));
instr_t *jcc_store =
XINST_CREATE_jump_cond(drcontext, DR_PRED_EQ, opnd_create_instr(store));
instr_t *move =
XINST_CREATE_move(drcontext, opnd_create_reg(REG1), opnd_create_reg(REG2));
instr_t *jcc_move =
XINST_CREATE_jump_cond(drcontext, DR_PRED_EQ, opnd_create_instr(move));
instrlist_append(ilist, nop1);
instrlist_append(ilist, move);
instrlist_append(ilist, jcc_store);
instrlist_append(ilist, jcc_move);
instrlist_append(ilist, nop2);
instrlist_append(ilist, store);
size_t offs_nop1 = 0;
size_t offs_mov = offs_nop1 + instr_length(drcontext, nop1);
size_t offs_jcc_store = offs_mov + instr_length(drcontext, move);
size_t offs_jcc_move = offs_jcc_store + instr_length(drcontext, jcc_store);
size_t offs_nop2 = offs_jcc_move + instr_length(drcontext, jcc_move);
size_t offs_store = offs_nop2 + instr_length(drcontext, nop2);
std::vector<offline_entry_t> raw;
raw.push_back(make_header());
raw.push_back(make_tid());
raw.push_back(make_pid());
raw.push_back(make_line_size());
raw.push_back(make_block(offs_mov, 2));
raw.push_back(make_block(offs_jcc_move, 1));
raw.push_back(make_window_id(1));
raw.push_back(make_block(offs_mov, 2));
raw.push_back(make_block(offs_jcc_move, 1));
raw.push_back(make_block(offs_store, 1));
raw.push_back(make_exit());
std::vector<trace_entry_t> entries;
if (!run_raw2trace(drcontext, raw, ilist, entries))
return false;
int idx = 0;
res = res && check_entry(entries, idx, TRACE_TYPE_HEADER, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_FILETYPE) &&
check_entry(entries, idx, TRACE_TYPE_THREAD, -1) &&
check_entry(entries, idx, TRACE_TYPE_PID, -1) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CACHE_LINE_SIZE) &&
check_entry(entries, idx, TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_mov) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_UNTAKEN_JUMP, -1,
offs_jcc_store) &&
check_entry(entries, idx, TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_WINDOW_ID) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_mov) &&
check_entry(entries, idx, TRACE_TYPE_INSTR_UNTAKEN_JUMP, -1,
offs_jcc_store) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#ifdef X86_32
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
#endif
check_entry(entries, idx, TRACE_TYPE_INSTR_UNTAKEN_JUMP, -1, offs_jcc_move) &&
check_entry(entries, idx, TRACE_TYPE_ENCODING, -1) &&
check_entry(entries, idx, TRACE_TYPE_INSTR, -1, offs_store) &&
check_entry(entries, idx, TRACE_TYPE_THREAD_EXIT, -1) &&
check_entry(entries, idx, TRACE_TYPE_FOOTER, -1);
}
return res;
}
int
test_main(int argc, const char *argv[])
{
void *drcontext = dr_standalone_init();
if (!test_branch_delays(drcontext) || !test_marker_placement(drcontext) ||
!test_marker_delays(drcontext) || !test_chunk_boundaries(drcontext) ||
!test_chunk_encodings(drcontext) || !test_duplicate_syscalls(drcontext) ||
!test_false_syscalls(drcontext) || !test_rseq_fallthrough(drcontext) ||
!test_rseq_rollback_legacy(drcontext) || !test_rseq_rollback(drcontext) ||
!test_rseq_rollback_with_timestamps(drcontext) ||
!test_rseq_rollback_with_signal(drcontext) ||
!test_rseq_rollback_with_chunks(drcontext) || !test_rseq_side_exit(drcontext) ||
!test_rseq_side_exit_signal(drcontext) ||
!test_rseq_side_exit_inverted(drcontext) ||
!test_rseq_side_exit_inverted_with_timestamp(drcontext) ||
!test_xfer_modoffs(drcontext) || !test_xfer_absolute(drcontext) ||
!test_branch_decoration(drcontext))
return 1;
return 0;
}
}
}