summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2023-04-24 01:13:28 +0300
committerOxore <oxore@protonmail.com>2023-04-24 01:13:28 +0300
commitaf46d6991ceb719ac59d6218791c41fa3978e695 (patch)
treec82f390402e0000a5a2d9bc88045b91a8810213a
parent30f24b179ced1bf47deb9edfbd4128f16dad42dd (diff)
Impl some feature flags
-rw-r--r--common.h6
-rw-r--r--disasm.cpp5
-rw-r--r--main.cpp140
3 files changed, 113 insertions, 38 deletions
diff --git a/common.h b/common.h
index 5988a29..34ba934 100644
--- a/common.h
+++ b/common.h
@@ -1,6 +1,12 @@
#pragma once
struct Settings {
+ bool marks{};
+ bool rel_marks{};
+ bool abs_marks{};
+ bool xrefs_to{};
+ bool xrefs_from{};
+ bool raw_data_comment{};
};
constexpr size_t kInstructionSizeStepBytes = 2;
diff --git a/disasm.cpp b/disasm.cpp
index 3b09c2d..ebf3926 100644
--- a/disasm.cpp
+++ b/disasm.cpp
@@ -80,6 +80,7 @@ static void disasm_jsr_jmp(
node.branch_addr = static_cast<uint32_t>(dispmt);
node.has_branch_addr = true;
snprintf(node.mnemonic, kMnemonicBufferSize, "%s", mnemonic);
+ // FIXME support s.abs_marks option
snprintf(node.arguments, kArgsBufferSize, "0x%x:w", dispmt);
return;
}
@@ -90,6 +91,7 @@ static void disasm_jsr_jmp(
node.branch_addr = static_cast<uint32_t>(dispmt);
node.has_branch_addr = true;
snprintf(node.mnemonic, kMnemonicBufferSize, "%s", mnemonic);
+ // FIXME support s.abs_marks option
snprintf(node.arguments, kArgsBufferSize, "0x%x:l", dispmt);
return;
}
@@ -101,6 +103,7 @@ static void disasm_jsr_jmp(
node.has_branch_addr = true;
node.size = kInstructionSizeStepBytes * 2;
snprintf(node.mnemonic, kMnemonicBufferSize, "%s", mnemonic);
+ // FIXME support s.rel_marks option
snprintf(node.arguments, kArgsBufferSize, "%%pc@(%d:w)", dispmt);
return;
}
@@ -206,6 +209,7 @@ static void disasm_bra_bsr_bcc(
node.has_branch_addr = true;
const char * const sign = dispmt >= 0 ? "+" : "";
snprintf(node.mnemonic, kMnemonicBufferSize, "%s%s", mnemonic, size_spec);
+ // FIXME support s.rel_marks option
snprintf(node.arguments, kArgsBufferSize, ".%s%d", sign, dispmt);
return;
}
@@ -329,6 +333,7 @@ static void disasm_dbcc(DisasmNode& node, uint16_t instr, const DataBuffer &code
node.has_branch_addr = true;
const char * const sign = dispmt >= 0 ? "+" : "";
snprintf(node.mnemonic, kMnemonicBufferSize, "%s", mnemonic);
+ // FIXME support s.rel_marks option
snprintf(node.arguments, kArgsBufferSize, "%%d%d,.%s%d", regnum, sign, dispmt);
return;
}
diff --git a/main.cpp b/main.cpp
index 5dd27f5..8d1afd6 100644
--- a/main.cpp
+++ b/main.cpp
@@ -18,19 +18,6 @@
#include <cerrno>
#include <climits>
-/*
- * We need to be able to modify output to place a mark when some jumping back
- * is found, hence we should build output table instead of emitting asm right
- * away into the output stream.
- *
- * I think the output should be an ordered map of decoded instructions. When the
- * output is built according to the map we must walk through all the binary file
- * again alongside with the output map and emit the final output right into the
- * output stream.
- *
- * Trace data parser is needed. Maybe just using atol(3) will be ok.
- */
-
class DisasmMap {
DisasmNode *_map[kDisasmMapSizeElements]{};
DisasmNode *findNodeByOffset(uint32_t offset) const;
@@ -127,34 +114,43 @@ static const char *ReferenceTypeToString(ReferenceType type)
}
static void RenderDisassembly(
- FILE *output, const DisasmMap &disasm_map, const DataBuffer &code, const Settings &)
+ FILE *output, const DisasmMap &disasm_map, const DataBuffer &code, const Settings &s)
{
for (size_t i = 0; i < code.occupied_size;) {
const DisasmNode *node = disasm_map.FindNodeByOffset(i);
if (node) {
- char comment[100]{};
- RenderRawDataComment(comment, sizeof(comment) - 1, node->offset, node->size, code);
if (node->ref_by) {
- fprintf(output, "| XREFS:\n");
- for (ReferenceNode *ref{node->ref_by}; ref; ref = ref->next) {
- if (ref->refs_count == 0) {
- continue;
- }
- fprintf(output, "|");
- for (size_t i = 0; i < ref->refs_count; i++) {
- const ReferenceRecord r = ref->refs[i];
- fprintf(output, " %s @%08x", ReferenceTypeToString(r.type), r.address);
+ if (s.xrefs_from) {
+ fprintf(output, "| XREFS:\n");
+ for (ReferenceNode *ref{node->ref_by}; ref; ref = ref->next) {
+ if (ref->refs_count == 0) {
+ continue;
+ }
+ fprintf(output, "|");
+ for (size_t i = 0; i < ref->refs_count; i++) {
+ const ReferenceRecord r = ref->refs[i];
+ fprintf(output, " %s @%08x", ReferenceTypeToString(r.type), r.address);
+ }
+ fprintf(output, "\n");
}
- fprintf(output, "\n");
}
- fprintf(output, ".L%08x:\n", node->offset);
+ if (s.marks) {
+ fprintf(output, ".L%08x:\n", node->offset);
+ }
}
- char branch_addr[12]{};
- if (node->has_branch_addr) {
+ const char *const delimiter = node->arguments[0] != '\0' ? " " : "";
+ fprintf(output, " %s%s%s", node->mnemonic, delimiter, node->arguments);
+ if (node->has_branch_addr && s.xrefs_to) {
+ char branch_addr[12]{};
snprintf(branch_addr, sizeof(branch_addr), " .L%08x", node->branch_addr);
+ fprintf(output, " |%s", branch_addr);
}
- const char *const delimiter = node->arguments[0] != '\0' ? " " : "";
- fprintf(output, " %s%s%s |%s%s\n", node->mnemonic, delimiter, node->arguments, branch_addr, comment);
+ if (s.raw_data_comment) {
+ char raw_data_comment[100]{};
+ RenderRawDataComment(raw_data_comment, sizeof(raw_data_comment) - 1, node->offset, node->size, code);
+ fprintf(output, " |%s", raw_data_comment);
+ }
+ fprintf(output, "\n");
i += node->size;
} else {
fprintf(output, " .short 0x%02x%02x\n", code.buffer[i], code.buffer[i + 1]);
@@ -274,13 +270,73 @@ static int M68kDisasmAll(FILE *input_stream, FILE *output_stream, const Settings
return 0;
}
-static void PrintUsage(FILE *stream, const char *argv0)
+static bool IsValidFeature(const char *feature)
+{
+ constexpr size_t sizeof_no_prefix = strlen("no-");
+ if (0 == memcmp(feature, "no-", sizeof_no_prefix)) {
+ feature += sizeof_no_prefix;
+ }
+ if (0 == strcmp(feature, "rdc")) {
+ return true;
+ } else if (0 == strcmp(feature, "marks")) {
+ return true;
+ } else if (0 == strcmp(feature, "rel-marks")) {
+ return true;
+ } else if (0 == strcmp(feature, "abs-marks")) {
+ return true;
+ } else if (0 == strcmp(feature, "xrefs-from")) {
+ return true;
+ } else if (0 == strcmp(feature, "xrefs-to")) {
+ return true;
+ }
+ return false;
+}
+
+static void ApplyFeature(Settings& s, const char *feature)
+{
+ bool disable{};
+ constexpr size_t sizeof_no_prefix = strlen("no-");
+ if (0 == memcmp(feature, "no-", sizeof_no_prefix)) {
+ disable = true;
+ feature += sizeof_no_prefix;
+ }
+ if (0 == strcmp(feature, "rdc")) {
+ s.raw_data_comment = !disable;
+ } else if (0 == strcmp(feature, "marks")) {
+ s.marks = !disable;
+ } else if (0 == strcmp(feature, "rel-marks")) {
+ s.rel_marks = !disable;
+ } else if (0 == strcmp(feature, "abs-marks")) {
+ s.abs_marks = !disable;
+ } else if (0 == strcmp(feature, "xrefs-from")) {
+ s.xrefs_from = !disable;
+ } else if (0 == strcmp(feature, "xrefs-to")) {
+ s.xrefs_to = !disable;
+ }
+}
+
+static void PrintUsage(FILE *s, const char *argv0)
{
- fprintf(stream, "Usage: %s [options] [<input-file-name>]\n", argv0);
- fprintf(stream, " -h, --help, Show this message\n");
- fprintf(stream, " -o, --output, Where to write disassembly to (stdout if not set)\n");
- fprintf(stream, " -t, --pc-trace, File containing PC trace\n");
- fprintf(stream, " <input_file_name> Binary file with machine code (stdin if not set)\n");
+ fprintf(s, "Usage: %s [options] [<input-file-name>]\n", argv0);
+ fprintf(s, "Options:\n");
+ fprintf(s, " -h, --help, Show this message\n");
+ fprintf(s, " -o, --output, Where to write disassembly to (stdout if not set)\n");
+ fprintf(s, " -t, --pc-trace, File containing PC trace\n");
+ fprintf(s, " -f, --feature=[no-]<feature>\n");
+ fprintf(s, " Enable or disable (with \"no-\" prefix) a feature\n");
+ fprintf(s, " Available features:\n");
+ fprintf(s, " rdc print raw data comment\n");
+ fprintf(s, " marks print marks above all places that have jumps\n");
+ fprintf(s, " from somewhere\n");
+ fprintf(s, " rel-marks use mark instead of number on relative\n");
+ fprintf(s, " branch or call\n");
+ fprintf(s, " abs-marks use mark instead of number on absolute\n");
+ fprintf(s, " branch or call\n");
+ fprintf(s, " xrefs-from print xrefs comments above all places that\n");
+ fprintf(s, " have xrefs\n");
+ fprintf(s, " xrefs-to print xrefs comments after all branch \n");
+ fprintf(s, " instructions\n");
+ fprintf(s, " <input_file_name> Binary file with machine code (stdin if not set)\n");
}
int main(int, char* argv[])
@@ -289,11 +345,13 @@ int main(int, char* argv[])
{"help", 'h', OPTPARSE_NONE},
{"output", 'o', OPTPARSE_REQUIRED},
{"pc-trace", 't', OPTPARSE_REQUIRED},
+ {"feature", 'f', OPTPARSE_OPTIONAL},
{},
};
const char *trace_file_name = nullptr;
const char *output_file_name = nullptr;
const char *input_file_name = nullptr;
+ Settings s{};
struct optparse options;
optparse_init(&options, argv);
// Parse opts
@@ -310,6 +368,13 @@ int main(int, char* argv[])
case 't':
trace_file_name = options.optarg;
break;
+ case 'f':
+ if (!IsValidFeature(options.optarg)) {
+ fprintf(stderr, "main: Error: Unknown feature \"%s\", exiting\n", options.optarg);
+ return EXIT_FAILURE;
+ }
+ ApplyFeature(s, options.optarg);
+ break;
case '?':
fprintf(stderr, "main: optparse_long: Error: \"%s\"\n", options.errmsg);
return EXIT_FAILURE;
@@ -353,7 +418,6 @@ int main(int, char* argv[])
return EXIT_FAILURE;
}
}
- Settings s{};
// Run the program
const int ret = trace_stream
? M68kDisasmByTrace(input_stream, output_stream, trace_stream, s)