diff options
Diffstat (limited to 'subx')
-rw-r--r-- | subx/001help.cc | 6 | ||||
-rw-r--r-- | subx/010---vm.cc | 4 | ||||
-rw-r--r-- | subx/035labels.cc | 9 | ||||
-rw-r--r-- | subx/038---literal_strings.cc | 1 | ||||
-rw-r--r-- | subx/039debug.cc | 83 | ||||
-rw-r--r-- | subx/Readme.md | 1 |
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 |