/* * Copyright 2002-2019 Intel Corporation. * * This software is provided to you as Sample Source Code as defined in the accompanying * End User License Agreement for the Intel(R) Software Development Products ("Agreement") * section 1.L. * * This software and the related documents are provided as is, with no express or implied * warranties, other than those that are expressly stated in the License. */ /* * This is a test application for the extended debugger commands in the * "debugger-shell" instrumenation library. Since those commands are * non-symbolic, the input commands must reference raw addresses in this * application not symbol names. It would be difficult to keep the * addresses in the input commands in sync with the addresses in this * application, so the application itself prints out the debugger commands. * To run this test, we run the application twice. The first run generates * the debugger command script, and the second run executes under the debugger. */ #include #include #include #if defined(_MSC_VER) typedef unsigned __int64 ADDR; #elif defined(__GNUC__) #include typedef uint64_t ADDR; #endif #if defined(TARGET_IA32) # define REGAX "$eax" #elif defined(TARGET_IA32E) # define REGAX "$rax" #endif volatile unsigned Value = 0; volatile unsigned Index = 0; volatile unsigned Max = 10; static void GenerateBreakpointScripts(const char *, const char *); static void GenerateTracepointScripts(const char *, const char *); static void RunTest(); extern "C" unsigned AssemblyReturn(unsigned); extern "C" char Label_WriteAx; int main(int argc, char **argv) { if (argc != 1 && argc != 4) { std::cerr << "Must specify three arguments or none\n"; return 1; } // When arguments are specified, just generate the // debugger scripts. // if (argc == 4 && strcmp(argv[1], "breakpoints") == 0) { GenerateBreakpointScripts(argv[2], argv[3]); return 0; } if (argc == 4 && strcmp(argv[1], "tracepoints") == 0) { GenerateTracepointScripts(argv[2], argv[3]); return 0; } // When run with no arguments, execute the test code. // RunTest(); return 0; } static void RunTest() { for (unsigned i = 0; i < Max; i++) { Index = i; Value = Index; } for (unsigned i = 0; i < Max; i++) { Index = i; Value = AssemblyReturn(Index); } } static void GenerateBreakpointScripts(const char *inFile, const char *compareFile) { std::ofstream in(inFile); std::ofstream compare(compareFile); in << "monitor break if icount 100\n"; in << "monitor break if mcount 100\n"; in << "monitor break if jump to 0x" << std::hex << reinterpret_cast(&RunTest) << "\n"; in << "monitor break if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; in << "monitor break if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; in << "monitor list breakpoints\n"; compare << "Breakpoint #1: break thread 0 if icount 100\n"; compare << "Breakpoint #2: break thread 0 if mcount 100\n"; compare << "Breakpoint #3:\\s+break if jump to 0x" << std::hex << reinterpret_cast(&RunTest) << "\n"; compare << "Breakpoint #4:\\s+break if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; compare << "Breakpoint #5:\\s+break if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; in << "cont\n"; /* stop at icount 100 */ in << "cont\n"; /* stop at mcount 100 */ in << "cont\n"; /* stop at RunTest */ in << "cont\n"; /* stop at Index = 0 */ in << "cont\n"; /* stop at Value = 0 */ in << "print i\n"; in << "cont\n"; /* stop at Index = 1 */ in << "cont\n"; /* stop at Value = 1 */ in << "print i\n"; in << "monitor delete breakpoint 4\n"; /* delete "break if load from " */ in << "monitor delete breakpoint 5\n"; /* delete "break if store to " */ compare << "Triggered breakpoint #1:\n"; compare << "Triggered breakpoint #2:\n"; compare << "Triggered breakpoint #3:\n"; compare << "Triggered breakpoint #4:\n"; compare << "Triggered breakpoint #5:\n"; compare << ".*= 0\n"; compare << "Triggered breakpoint #4:\n"; compare << "Triggered breakpoint #5:\n"; compare << ".*= 1\n"; in << "monitor break before load from 0x" << std::hex << reinterpret_cast(&Index) << " == 5\n"; in << "monitor break after store to 0x" << std::hex << reinterpret_cast(&Value) << " == 5\n"; in << "cont\n"; /* stop at Index = 5 */ in << "cont\n"; /* stop at Value = 5 */ in << "print i\n"; in << "monitor break at 0x" << std::hex << reinterpret_cast(&Label_WriteAx) << " if " REGAX " == 2\n"; in << "cont\n"; /* stop in AssemblyReturn(2) */ in << "print " REGAX "\n"; in << "cont\n"; /* stop at Index = 5 */ in << "cont\n"; /* stop at Value = 5 */ in << "cont\n"; /* program terminates */ in << "quit\n"; compare << "Triggered breakpoint #6:\n"; compare << "Triggered breakpoint #7:\n"; compare << ".*= 5\n"; compare << "Triggered breakpoint #8:\n"; compare << ".*= 2\n"; compare << "Triggered breakpoint #6:\n"; compare << "Triggered breakpoint #7:\n"; compare << "(Program exited normally|\\[Inferior 1 \\(Remote target\\) exited normally\\])\n"; } static void GenerateTracepointScripts(const char *inFile, const char *compareFile) { std::ofstream in(inFile); std::ofstream compare(compareFile); in << "monitor trace at 0x" << std::hex << reinterpret_cast(&main) << "\n"; in << "break RunTest\n"; in << "cont\n"; /* stop at RunTest */ in << "monitor trace print\n"; compare << "Tracepoint #1:\\s+trace at 0x" << std::hex << reinterpret_cast(&main) << "\n"; compare << "Breakpoint 1,\\s*RunTest\n"; compare << "0x0*" << std::hex << reinterpret_cast(&main) << "\n"; in << "monitor trace clear\n"; in << "monitor trace if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; in << "monitor break if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; in << "monitor trace if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; in << "monitor break if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; in << "cont\n"; /* stop at Index = 0 (before trace occured) */ in << "cont\n"; /* stop at Value = 0 (before trace occured) */ in << "monitor trace print\n"; compare << "Tracepoint #2:\\s*trace if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; compare << "Breakpoint #3:\\s*break if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; compare << "Tracepoint #4:\\s*trace if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; compare << "Breakpoint #5:\\s*break if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; compare << "Triggered breakpoint #5:\n"; compare << "Triggered breakpoint #3:\n"; /* no trace records printed */ in << "monitor delete breakpoint 3\n"; in << "monitor delete breakpoint 5\n"; in << "monitor break before load from 0x" << std::hex << reinterpret_cast(&Index) << " == 0x" << std::dec << Max-1 << "\n"; in << "monitor break after store to 0x" << std::hex << reinterpret_cast(&Value) << " == 0x" << std::dec << Max-1 << "\n"; in << "cont\n"; /* stop after Index = Max (end of first loop) */ in << "cont\n"; /* stop after Value = Max (end of first loop) */ in << "monitor trace print\n"; compare << "Breakpoint #6:\n"; compare << "Breakpoint #7:\n"; compare << "Triggered breakpoint #6:\n"; compare << "Triggered breakpoint #7:\n"; compare << "0x[0-9,a-f]+:\\s*if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; compare << "0x[0-9,a-f]+:\\s*if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; compare << "0x[0-9,a-f]+:\\s*if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; compare << "0x[0-9,a-f]+:\\s*if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; compare << "0x[0-9,a-f]+:\\s*if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; compare << "0x[0-9,a-f]+:\\s*if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; compare << "0x[0-9,a-f]+:\\s*if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; compare << "0x[0-9,a-f]+:\\s*if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; compare << "0x[0-9,a-f]+:\\s*if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; compare << "0x[0-9,a-f]+:\\s*if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; compare << "0x[0-9,a-f]+:\\s*if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; compare << "0x[0-9,a-f]+:\\s*if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; compare << "0x[0-9,a-f]+:\\s*if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; compare << "0x[0-9,a-f]+:\\s*if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; compare << "0x[0-9,a-f]+:\\s*if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; compare << "0x[0-9,a-f]+:\\s*if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; compare << "0x[0-9,a-f]+:\\s*if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; compare << "0x[0-9,a-f]+:\\s*if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; compare << "0x[0-9,a-f]+:\\s*if load from 0x" << std::hex << reinterpret_cast(&Index) << "\n"; compare << "0x[0-9,a-f]+:\\s*if store to 0x" << std::hex << reinterpret_cast(&Value) << "\n"; in << "monitor trace disable\n"; in << "monitor list tracepoints\n"; in << "monitor trace clear\n"; compare << "#1:\\s*trace at 0x" << std::hex << reinterpret_cast(&main) << "\\s*\\(disabled\\)\n"; compare << "#2:\\s*trace if store to 0x" << std::hex << reinterpret_cast(&Value) << "\\s*\\(disabled\\)\n"; compare << "#4:\\s*trace if load from 0x" << std::hex << reinterpret_cast(&Index) << "\\s*\\(disabled\\)\n"; in << "monitor trace before load from 0x" << std::hex << reinterpret_cast(&Index) << " == 2\n"; in << "monitor trace before load from 0x" << std::hex << reinterpret_cast(&Index) << " == 4\n"; in << "monitor trace after store to 0x" << std::hex << reinterpret_cast(&Value) << " == 2\n"; in << "monitor trace after store to 0x" << std::hex << reinterpret_cast(&Value) << " == 4\n"; in << "cont\n"; /* stop after Index = Max (end of second loop) */ in << "cont\n"; /* stop after Value = Max (end of second loop) */ in << "monitor trace print\n"; compare << "Tracepoint #8:\\s*trace before load from 0x" << std::hex << reinterpret_cast(&Index) << " == 0x2\n"; compare << "Tracepoint #9:\\s*trace before load from 0x" << std::hex << reinterpret_cast(&Index) << " == 0x4\n"; compare << "Tracepoint #10:\\s*trace after store to 0x" << std::hex << reinterpret_cast(&Value) << " == 0x2\n"; compare << "Tracepoint #11:\\s*trace after store to 0x" << std::hex << reinterpret_cast(&Value) << " == 0x4\n"; compare << "Triggered breakpoint #6:\n"; compare << "Triggered breakpoint #7:\n"; compare << "0x[0-9,a-f]+:\\s*before load from 0x" << std::hex << reinterpret_cast(&Index) << " == 0x2\n"; compare << "0x[0-9,a-f]+:\\s*after store to 0x" << std::hex << reinterpret_cast(&Value) << " == 0x2\n"; compare << "0x[0-9,a-f]+:\\s*before load from 0x" << std::hex << reinterpret_cast(&Index) << " == 0x4\n"; compare << "0x[0-9,a-f]+:\\s*after store to 0x" << std::hex << reinterpret_cast(&Value) << " == 0x4\n"; in << "quit\n"; }