diff --git a/CMakeLists.txt b/CMakeLists.txt index b53cfc0..16b9509 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,4 +81,5 @@ if(NYXSTONE_BUILD_EXAMPLES) include(CTest) add_test(NAME TestExample COMMAND $) + add_test(NAME TestCLI COMMAND "${CMAKE_CURRENT_LIST_DIR}/tool/test-cli.sh") endif() diff --git a/examples/nyxstone-cli.cpp b/examples/nyxstone-cli.cpp index e105231..bd3fe0b 100644 --- a/examples/nyxstone-cli.cpp +++ b/examples/nyxstone-cli.cpp @@ -31,6 +31,7 @@ constexpr auto USAGE = R"(Usage: nyxstone [-t=] [-p=] [-d] -p, --address= Initial address to assemble/disassemble relative to -l, --labels= Label-to-address mappings (used when assembling only) -d, --disassemble Treat as bytes to disassemble instead of assembly + -b, --bytes-only Only output assembled bytes -h, --help Show this help and usage message Notes: @@ -56,6 +57,7 @@ struct Options { std::vector labels; bool disassemble = false; bool show_help = false; + bool bytes_only = false; std::string input; @@ -77,6 +79,8 @@ tl::expected Options::parse(int argc, char const** argv) "--address", "-l", "--labels", + "-b" + "--bytes-only" }); args.parse(argc, argv); @@ -117,6 +121,8 @@ tl::expected Options::parse(int argc, char const** argv) options.disassemble = args[{ "-d", "--disassemble" }]; + options.bytes_only = args[{ "-b", "--bytes-only" }]; + if (args.pos_args().size() < 2) { return tl::unexpected("Missing input"); } @@ -172,12 +178,21 @@ int main(int argc, char const** argv) .map(print_instructions); } else { const auto& assembly = options.input; - nyxstone->assemble_to_instructions(assembly, options.address, options.labels) - .map_error([&assembly](const auto& error) { - std::cerr << "Could not assemble " << assembly << " (" << error << ")\n"; - exit(1); - }) - .map(print_instructions); + if (!options.bytes_only) { + nyxstone->assemble_to_instructions(assembly, options.address, options.labels) + .map_error([&assembly](const auto& error) { + std::cerr << "Could not assemble " << assembly << " (" << error << ")\n"; + exit(1); + }) + .map(print_instructions); + } else { + nyxstone->assemble(assembly, options.address, options.labels) + .map_error([&assembly](const auto& error) { + std::cerr << "Could not assemble " << assembly << " (" << error << ")\n"; + exit(1); + }) + .map(print_bytes); + } } } diff --git a/tool/test-cli.sh b/tool/test-cli.sh new file mode 100755 index 0000000..0a7d733 --- /dev/null +++ b/tool/test-cli.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +set -eu + +# Sanity check that assembling and disassembling yields the same output +# NOTE: Currently we cannot test using labels, since we keep them when assembling. +assembly="cmp rax, rbx; inc rax; add rsp, 8; ret" +address="0xdeadbeef" + +assembled=$(./nyxstone -t "x86_64" -p "$address" "$assembly") +assembled_bytes=$(./nyxstone -t "x86_64" --bytes-only -p "$address" "$assembly") +# assembled_bytes="03 02" +disassembled=$(./nyxstone -t "x86_64" -p "$address" -d "$assembled_bytes") + +if [[ "$assembled" = "$disassembled" ]]; then + exit 0 +else + echo "Output Mismatch" + echo "---------------" + echo "Assembled:" + echo "$assembled" + echo "Disassembled:" + echo "$disassembled" + exit -1 +fi