about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
Diffstat (limited to 'subx')
-rw-r--r--subx/001help.cc6
-rw-r--r--subx/010---vm.cc4
-rw-r--r--subx/035labels.cc9
-rw-r--r--subx/038---literal_strings.cc1
-rw-r--r--subx/039debug.cc83
-rw-r--r--subx/Readme.md1
6 files changed, 94 insertions, 10 deletions
diff --git a/subx/001help.cc b/subx/001help.cc
index 1b3f64dd..79589cf8 100644
--- a/subx/001help.cc
+++ b/subx/001help.cc
@@ -81,10 +81,8 @@ void init_help() {
     "- Add '--trace' to any of these commands to print a trace to stderr\n"
     "  for debugging purposes.\n"
     "- Add '--debug' to add information to traces. 'subx --debug translate' will\n"
-    "  save (to a file called 'labels') the mapping from labels to addresses that\n"
-    "  it computes during translation. This file is then available to\n"
-    "  'subx --debug --trace run' which prints out label names in the trace as it\n"
-    "  encounters them.\n"
+    "  save various mappings to files that 'subx --debug --trace run'\n"
+    "  can use to make traces more informative.\n"
     "\n"
     "Options starting with '--' must always come before any other arguments.\n"
     "\n"
diff --git a/subx/010---vm.cc b/subx/010---vm.cc
index f4fb8119..31e5608f 100644
--- a/subx/010---vm.cc
+++ b/subx/010---vm.cc
@@ -305,7 +305,7 @@ void run_one_instruction() {
   }
   uint32_t inst_start_address = EIP;
   op = next();
-  trace(Callstack_depth, "run") << "0x" << HEXWORD << inst_start_address << " opcode: " << HEXBYTE << NUM(op) << end();
+  trace(Callstack_depth+1, "run") << "0x" << HEXWORD << inst_start_address << " opcode: " << HEXBYTE << NUM(op) << end();
   switch (op) {
   case 0xf4:  // hlt
     EIP = End_of_program;
@@ -369,7 +369,7 @@ inline uint8_t next() {
 
 void dump_registers() {
   ostringstream out;
-  out << "registers: ";
+  out << "registers before: ";
   for (int i = 0;  i < NUM_INT_REGISTERS;  ++i) {
     if (i > 0) out << "; ";
     out << "  " << i << ": " << std::hex << std::setw(8) << std::setfill('_') << Reg[i].u;
diff --git a/subx/035labels.cc b/subx/035labels.cc
index f1eb6510..f3131168 100644
--- a/subx/035labels.cc
+++ b/subx/035labels.cc
@@ -138,6 +138,8 @@ void compute_byte_indices_for_labels(const segment& code, map<string, int32_t>&
   int current_byte = 0;
   for (int i = 0;  i < SIZE(code.lines);  ++i) {
     const line& inst = code.lines.at(i);
+    if (Source_lines_file.is_open() && !inst.original.empty() && /*not a label*/ *inst.words.at(0).data.rbegin() != ':')
+      Source_lines_file << "0x" << HEXWORD << (code.start + current_byte) << ' ' << inst.original << '\n';
     for (int j = 0;  j < SIZE(inst.words);  ++j) {
       const word& curr = inst.words.at(j);
       // hack: if we have any operand metadata left after previous transforms,
@@ -185,6 +187,7 @@ void compute_byte_indices_for_labels(const segment& code, map<string, int32_t>&
 :(before "End Globals")
 bool Dump_debug_info = false;  // currently used only by 'subx translate'
 ofstream Labels_file;
+ofstream Source_lines_file;
 :(before "End Commandline Options")
 else if (is_equal(*arg, "--debug")) {
   Dump_debug_info = true;
@@ -195,10 +198,14 @@ else if (is_equal(*arg, "--debug")) {
 if (Dump_debug_info) {
   cerr << "saving address->label information to 'labels'\n";
   Labels_file.open("labels");
+  cerr << "saving address->source information to 'source_lines'\n";
+  Source_lines_file.open("source_lines");
 }
 :(before "End subx translate")
-if (Dump_debug_info)
+if (Dump_debug_info) {
   Labels_file.close();
+  Source_lines_file.close();
+}
 
 :(code)
 void drop_labels(segment& code) {
diff --git a/subx/038---literal_strings.cc b/subx/038---literal_strings.cc
index a795ce23..65a7740b 100644
--- a/subx/038---literal_strings.cc
+++ b/subx/038---literal_strings.cc
@@ -104,6 +104,7 @@ void parse_instruction_character_by_character(const string& line_data, vector<li
   istringstream in(line_data);
   in >> std::noskipws;
   line result;
+  result.original = line_data;
   // add tokens (words or strings) one by one
   while (has_data(in)) {
     skip_whitespace(in);
diff --git a/subx/039debug.cc b/subx/039debug.cc
index ebf39034..26bb5f7a 100644
--- a/subx/039debug.cc
+++ b/subx/039debug.cc
@@ -6,11 +6,13 @@
 
 :(before "End Globals")
 map</*address*/uint32_t, string> Symbol_name;  // used only by 'subx run'
+map</*address*/uint32_t, string> Source_line;  // used only by 'subx run'
 :(before "End --debug Settings")
-load_map("labels");
+load_labels();
+load_source_lines();
 :(code)
-void load_map(const string& map_filename) {
-  ifstream fin(map_filename.c_str());
+void load_labels() {
+  ifstream fin("labels");
   fin >> std::hex;
   while (has_data(fin)) {
     uint32_t addr = 0;
@@ -21,9 +23,43 @@ void load_map(const string& map_filename) {
   }
 }
 
+void load_source_lines() {
+  ifstream fin("source_lines");
+  fin >> std::hex;
+  while (has_data(fin)) {
+    uint32_t addr = 0;
+    fin >> addr;
+    string line;
+    getline(fin, line);
+    put(Source_line, addr, hacky_squeeze_out_whitespace(line));
+  }
+}
+
 :(after "Run One Instruction")
 if (contains_key(Symbol_name, EIP))
   trace(Callstack_depth, "run") << "== label " << get(Symbol_name, EIP) << end();
+if (contains_key(Source_line, EIP))
+  trace(Callstack_depth, "run") << "0x" << HEXWORD << EIP << ": " << get(Source_line, EIP) << end();
+else
+  // no source line info; do what you can
+  trace(Callstack_depth, "run") << "0x" << HEXWORD << EIP << ": " << debug_info(EIP) << end();
+
+:(code)
+string debug_info(uint32_t inst_address) {
+  uint8_t op = read_mem_u8(EIP);
+  if (op != 0xe8) {
+    ostringstream out;
+    out << HEXBYTE << NUM(op);
+    return out.str();
+  }
+  int32_t offset = read_mem_i32(EIP+/*skip op*/1);
+  uint32_t next_eip = EIP+/*inst length*/5+offset;
+  if (contains_key(Symbol_name, next_eip))
+    return "e8/call "+get(Symbol_name, next_eip);
+  ostringstream out;
+  out << "e8/call 0x" << HEXWORD << next_eip;
+  return out.str();
+}
 
 //: If a label starts with '$watch-', make a note of the effective address
 //: computed by the next instruction. Start dumping out its contents to the
@@ -54,3 +90,44 @@ if (!Watch_this_effective_address.empty()) {
   dbg << "now watching " << HEXWORD << addr << " for " << Watch_this_effective_address << end();
   put(Watch_points, Watch_this_effective_address, addr);
 }
+
+//: helpers
+
+:(code)
+string hacky_squeeze_out_whitespace(const string& s) {
+  // strip whitespace at start
+  string::const_iterator first = s.begin();
+  while (first != s.end() && isspace(*first))
+    ++first;
+  if (first == s.end()) return "";
+
+  // strip whitespace at end
+  string::const_iterator last = --s.end();
+  while (last != s.begin() && isspace(*last))
+    --last;
+  ++last;
+
+  // replace runs of spaces/dots with single space until comment or string
+  // TODO:
+  //   leave alone dots not surrounded by whitespace
+  //   leave alone '#' within word
+  //   leave alone '"' within word
+  //   squeeze spaces after end of string
+  ostringstream out;
+  bool previous_was_space = false;
+  bool in_comment_or_string = false;
+  for (string::const_iterator curr = first;  curr != last;  ++curr) {
+    if (in_comment_or_string)
+      out << *curr;
+    else if (isspace(*curr) || *curr == '.')
+      previous_was_space = true;
+    else {
+      if (previous_was_space)
+        out << ' ';
+      out << *curr;
+      previous_was_space = false;
+      if (*curr == '#' || *curr == '"') in_comment_or_string = true;
+    }
+  }
+  return out.str();
+}
diff --git a/subx/Readme.md b/subx/Readme.md
index 15cb9972..e8e4ad6d 100644
--- a/subx/Readme.md
+++ b/subx/Readme.md
@@ -43,6 +43,7 @@ Emulated runs generate a trace that permits [time-travel debugging](https://gith
   ```sh
   $ ./subx --debug translate examples/factorial.subx -o examples/factorial
   saving address->label information to 'labels'
+  saving address->source information to 'source_lines'
   $ ./subx --debug --trace run examples/factorial
   saving trace to 'last_run'
   $ ../browse_trace/browse_trace last_run  # text-mode debugger UI