about summary refs log blame commit diff stats
path: root/config.mk
blob: 1431e22251623615bc14ddd7a04e102d1c140f1b (plain) (tree)
"c1">// no source line info; do what you can trace(Callstack_depth, "run") << "inst: " << debug_info(EIP) << end(); :(code) string debug_info(uint32_t inst_address) { uint8_t op = read_mem_u8(inst_address); if (op != 0xe8) { ostringstream out; out << HEXBYTE << NUM(op); return out.str(); } int32_t offset = read_mem_i32(inst_address+/*skip op*/1); uint32_t next_eip = inst_address+/*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 //: trace after every subsequent instruction. :(after "Run One Instruction") dump_watch_points(); :(before "End Globals") map<string, uint32_t> Watch_points; :(before "End Reset") Watch_points.clear(); :(code) void dump_watch_points() { if (Watch_points.empty()) return; trace(Callstack_depth, "dbg") << "watch points:" << end(); for (map<string, uint32_t>::iterator p = Watch_points.begin(); p != Watch_points.end(); ++p) trace(Callstack_depth, "dbg") << " " << p->first << ": " << HEXWORD << p->second << " -> " << HEXWORD << read_mem_u32(p->second) << end(); } :(before "End Globals") string Watch_this_effective_address; :(after "Run One Instruction") Watch_this_effective_address = ""; if (contains_key(Symbol_name, EIP) && starts_with(get(Symbol_name, EIP), "$watch-")) Watch_this_effective_address = get(Symbol_name, EIP); :(after "Found effective_address(addr)") 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); } //: Special label that dumps regions of memory. //: Not a general mechanism; by the time you get here you're willing to hack //: on the emulator. :(after "Run One Instruction") if (contains_key(Symbol_name, EIP) && get(Symbol_name, EIP) == "$dump-stream-at-EAX") dump_stream_at(Reg[EAX].u); :(code) void dump_stream_at(uint32_t stream_start) { int32_t stream_length = read_mem_i32(stream_start + 8); dbg << "stream length: " << std::dec << stream_length << end(); for (int i = 0; i < stream_length + 12; ++i) dbg << "0x" << HEXWORD << (stream_start+i) << ": " << HEXBYTE << NUM(read_mem_u8(stream_start+i)) << end(); } //: 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(); }