1b8021494Sopenharmony_ci// Copyright 2023, VIXL authors 2b8021494Sopenharmony_ci// All rights reserved. 3b8021494Sopenharmony_ci// 4b8021494Sopenharmony_ci// Redistribution and use in source and binary forms, with or without 5b8021494Sopenharmony_ci// modification, are permitted provided that the following conditions are met: 6b8021494Sopenharmony_ci// 7b8021494Sopenharmony_ci// * Redistributions of source code must retain the above copyright notice, 8b8021494Sopenharmony_ci// this list of conditions and the following disclaimer. 9b8021494Sopenharmony_ci// * Redistributions in binary form must reproduce the above copyright notice, 10b8021494Sopenharmony_ci// this list of conditions and the following disclaimer in the documentation 11b8021494Sopenharmony_ci// and/or other materials provided with the distribution. 12b8021494Sopenharmony_ci// * Neither the name of ARM Limited nor the names of its contributors may be 13b8021494Sopenharmony_ci// used to endorse or promote products derived from this software without 14b8021494Sopenharmony_ci// specific prior written permission. 15b8021494Sopenharmony_ci// 16b8021494Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17b8021494Sopenharmony_ci// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18b8021494Sopenharmony_ci// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19b8021494Sopenharmony_ci// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20b8021494Sopenharmony_ci// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21b8021494Sopenharmony_ci// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22b8021494Sopenharmony_ci// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23b8021494Sopenharmony_ci// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24b8021494Sopenharmony_ci// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25b8021494Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26b8021494Sopenharmony_ci 27b8021494Sopenharmony_ci// Tests for the simulator debugger. 28b8021494Sopenharmony_ci 29b8021494Sopenharmony_ci#include <fstream> 30b8021494Sopenharmony_ci#include <regex> 31b8021494Sopenharmony_ci 32b8021494Sopenharmony_ci#include "test-runner.h" 33b8021494Sopenharmony_ci#include "test-utils.h" 34b8021494Sopenharmony_ci 35b8021494Sopenharmony_ci#include "aarch64/macro-assembler-aarch64.h" 36b8021494Sopenharmony_ci#include "aarch64/simulator-aarch64.h" 37b8021494Sopenharmony_ci#include "aarch64/test-utils-aarch64.h" 38b8021494Sopenharmony_ci 39b8021494Sopenharmony_cinamespace vixl { 40b8021494Sopenharmony_cinamespace aarch64 { 41b8021494Sopenharmony_ci 42b8021494Sopenharmony_ci#define __ masm-> 43b8021494Sopenharmony_ci#define TEST(name) TEST_(AARCH64_DBG_##name) 44b8021494Sopenharmony_ci 45b8021494Sopenharmony_ci// 46b8021494Sopenharmony_ci// Regex for various types of printing/tracing output. 47b8021494Sopenharmony_ci// 48b8021494Sopenharmony_ci 49b8021494Sopenharmony_ci// Matches traced/printed general purpose register output from the simulator, 50b8021494Sopenharmony_ci// e.g: 51b8021494Sopenharmony_ci// "# x0: 0x000000000badbeef" 52b8021494Sopenharmony_ciconst std::string x_register_trace = "#[\\s]+(x\\d{1,2}|lr|sp): 0x[0-9a-f]+"; 53b8021494Sopenharmony_ci// Matches traced/printed vector register output from the simulator, e.g: 54b8021494Sopenharmony_ci// "# v0: 0x7ff0f0007f80f0017ff0f0007f80f000" 55b8021494Sopenharmony_ciconst std::string v_register_trace = "#[\\s]+(v\\d{1,2}): 0x[0-9a-f]+"; 56b8021494Sopenharmony_ci 57b8021494Sopenharmony_ci#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 58b8021494Sopenharmony_ci// Run tests with the simulator. 59b8021494Sopenharmony_ci 60b8021494Sopenharmony_ci// Generate some basic code which immediately breaks into the debugger. 61b8021494Sopenharmony_ci// This serves as a sandbox for all debugger tests to run in. 62b8021494Sopenharmony_civoid GenerateDebuggerAsm(MacroAssembler* masm) { 63b8021494Sopenharmony_ci // Create a breakpoint here to break into the debugger. 64b8021494Sopenharmony_ci __ Brk(0); 65b8021494Sopenharmony_ci 66b8021494Sopenharmony_ci // Do some arithmetic. 67b8021494Sopenharmony_ci __ Add(x1, x0, 5); 68b8021494Sopenharmony_ci __ Mov(x2, 2); 69b8021494Sopenharmony_ci __ Sub(x3, x1, x2); 70b8021494Sopenharmony_ci 71b8021494Sopenharmony_ci __ Ret(); 72b8021494Sopenharmony_ci} 73b8021494Sopenharmony_ci 74b8021494Sopenharmony_ci// Setup the test environment with the debugger assembler and simulator. 75b8021494Sopenharmony_ci#define SETUP() \ 76b8021494Sopenharmony_ci MacroAssembler masm; \ 77b8021494Sopenharmony_ci masm.SetCPUFeatures(CPUFeatures::None()); \ 78b8021494Sopenharmony_ci masm.SetGenerateSimulatorCode(true); \ 79b8021494Sopenharmony_ci GenerateDebuggerAsm(&masm); \ 80b8021494Sopenharmony_ci masm.FinalizeCode(); \ 81b8021494Sopenharmony_ci Instruction* start = masm.GetBuffer()->GetStartAddress<Instruction*>(); \ 82b8021494Sopenharmony_ci Decoder decoder; \ 83b8021494Sopenharmony_ci std::istringstream input_stream; \ 84b8021494Sopenharmony_ci char ostream_filename[] = "/tmp/vixl-test-debugger-XXXXXX"; \ 85b8021494Sopenharmony_ci FILE* output_stream = fdopen(mkstemp(ostream_filename), "w"); \ 86b8021494Sopenharmony_ci /* Disassemble the generated code so we can use the addresses later. */ \ 87b8021494Sopenharmony_ci PrintDisassembler disassembler(output_stream); \ 88b8021494Sopenharmony_ci disassembler.DisassembleBuffer(start, masm.GetSizeOfCodeGenerated()); \ 89b8021494Sopenharmony_ci fflush(output_stream); \ 90b8021494Sopenharmony_ci Simulator simulator(&decoder, output_stream); \ 91b8021494Sopenharmony_ci simulator.GetDebugger()->SetInputStream(&input_stream); \ 92b8021494Sopenharmony_ci simulator.SetColouredTrace(Test::coloured_trace()); \ 93b8021494Sopenharmony_ci simulator.SetCPUFeatures(CPUFeatures::None()); \ 94b8021494Sopenharmony_ci simulator.SetDebuggerEnabled(true); \ 95b8021494Sopenharmony_ci /* Setup a map so that commands and their output can be checked. */ \ 96b8021494Sopenharmony_ci std::unordered_map<std::string, std::string> command_map 97b8021494Sopenharmony_ci 98b8021494Sopenharmony_ci// Add a command to the input stream queue and map its expected output so that 99b8021494Sopenharmony_ci// it can be checked at the end of simulation. 100b8021494Sopenharmony_ci#define SETUP_CMD(cmd, expected_output) \ 101b8021494Sopenharmony_ci { \ 102b8021494Sopenharmony_ci std::string cmd_str(cmd); \ 103b8021494Sopenharmony_ci cmd_str += "\n"; \ 104b8021494Sopenharmony_ci std::string exp_out(expected_output); \ 105b8021494Sopenharmony_ci input_stream.str(input_stream.str() + cmd_str); \ 106b8021494Sopenharmony_ci command_map.insert({cmd_str, exp_out}); \ 107b8021494Sopenharmony_ci } 108b8021494Sopenharmony_ci 109b8021494Sopenharmony_ci// Run the simulator. 110b8021494Sopenharmony_ci#define RUN() \ 111b8021494Sopenharmony_ci simulator.RunFrom(start); \ 112b8021494Sopenharmony_ci fclose(output_stream) 113b8021494Sopenharmony_ci 114b8021494Sopenharmony_ci// Read the output file stream and check that the expected output from each 115b8021494Sopenharmony_ci// command is found directly following it. 116b8021494Sopenharmony_ci#define CHECK_OUTPUT() \ 117b8021494Sopenharmony_ci std::ifstream file_stream(ostream_filename); \ 118b8021494Sopenharmony_ci std::ostringstream ostream; \ 119b8021494Sopenharmony_ci ostream << file_stream.rdbuf(); \ 120b8021494Sopenharmony_ci for (const auto& iter : command_map) { \ 121b8021494Sopenharmony_ci std::string cmd = iter.first; \ 122b8021494Sopenharmony_ci std::string expected = iter.second; \ 123b8021494Sopenharmony_ci /* We assume the expected output follows the command that was issued. */ \ 124b8021494Sopenharmony_ci std::regex regex(cmd + expected); \ 125b8021494Sopenharmony_ci if (!std::regex_search(ostream.str(), regex)) { \ 126b8021494Sopenharmony_ci printf("output = \n\"%s\"\n", ostream.str().c_str()); \ 127b8021494Sopenharmony_ci /* Remove the newlines. */ \ 128b8021494Sopenharmony_ci cmd.erase(cmd.size() - 1, 1); \ 129b8021494Sopenharmony_ci std::string err = \ 130b8021494Sopenharmony_ci cmd + " - failed: \"" + expected + "\" not found in output "; \ 131b8021494Sopenharmony_ci VIXL_ABORT_WITH_MSG(err.c_str()); \ 132b8021494Sopenharmony_ci } \ 133b8021494Sopenharmony_ci } \ 134b8021494Sopenharmony_ci std::remove(ostream_filename) 135b8021494Sopenharmony_ci 136b8021494Sopenharmony_ci#define GET_INSTRUCTION_ADDRESS(instruction) \ 137b8021494Sopenharmony_ci GetInstructionAddress(ostream_filename, instruction) 138b8021494Sopenharmony_ci 139b8021494Sopenharmony_ci// Get the address of an instruction from the given filename. 140b8021494Sopenharmony_cistd::string GetInstructionAddress(std::string filename, 141b8021494Sopenharmony_ci std::string instruction) { 142b8021494Sopenharmony_ci std::ifstream file_stream(filename); 143b8021494Sopenharmony_ci std::ostringstream ostream; 144b8021494Sopenharmony_ci ostream << file_stream.rdbuf(); 145b8021494Sopenharmony_ci 146b8021494Sopenharmony_ci // Match the instruction string and capture the address of that instruction. 147b8021494Sopenharmony_ci // Note: leading 0's are matched but not captured. 148b8021494Sopenharmony_ci std::smatch sub_matches; 149b8021494Sopenharmony_ci std::string str = ostream.str(); 150b8021494Sopenharmony_ci std::string regex_str = "(0x)0*([0-9a-f]+) [0-9a-f]+\t\t"; 151b8021494Sopenharmony_ci regex_str += instruction; 152b8021494Sopenharmony_ci std::regex regex(regex_str); 153b8021494Sopenharmony_ci if (std::regex_search(str, sub_matches, regex) && sub_matches.size() == 3) { 154b8021494Sopenharmony_ci return sub_matches[1].str() + sub_matches[2].str(); 155b8021494Sopenharmony_ci } else { 156b8021494Sopenharmony_ci std::string err = regex_str + " not found in output "; 157b8021494Sopenharmony_ci VIXL_ABORT_WITH_MSG(err.c_str()); 158b8021494Sopenharmony_ci } 159b8021494Sopenharmony_ci} 160b8021494Sopenharmony_ci 161b8021494Sopenharmony_ci#endif // VIXL_INCLUDE_SIMULATOR_AARCH64 162b8021494Sopenharmony_ci 163b8021494Sopenharmony_ci} // namespace aarch64 164b8021494Sopenharmony_ci} // namespace vixl 165