From ac07e589b3e912c704c2011d543f18b16712ff15 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 29 Dec 2018 15:27:18 -0800 Subject: 4890 - new html renderings a) Switch to a light background. b) Linkify calls in .subx files. c) Keep all colorization in the Vim colorscheme, get rid of hacky special-cases in update_html. --- html/subx/036global_variables.cc.html | 436 +++++++++++++++++----------------- 1 file changed, 223 insertions(+), 213 deletions(-) (limited to 'html/subx/036global_variables.cc.html') diff --git a/html/subx/036global_variables.cc.html b/html/subx/036global_variables.cc.html index c26d5b53..919e77a9 100644 --- a/html/subx/036global_variables.cc.html +++ b/html/subx/036global_variables.cc.html @@ -7,29 +7,24 @@ - + @@ -86,202 +81,217 @@ if ('onhashchange' in window) { 19 :(code) 20 void rewrite_global_variables(program& p) { 21 trace(99, "transform") << "-- rewrite global variables" << end(); - 22 map<string, uint32_t> address; - 23 compute_addresses_for_global_variables(p, address); - 24 if (trace_contains_errors()) return; - 25 drop_global_variables(p); - 26 replace_global_variables_with_addresses(p, address); - 27 } - 28 - 29 void compute_addresses_for_global_variables(const program& p, map<string, uint32_t>& address) { - 30 for (int i = /*skip code segment*/1; i < SIZE(p.segments); ++i) - 31 compute_addresses_for_global_variables(p.segments.at(i), address); - 32 } - 33 - 34 void compute_addresses_for_global_variables(const segment& s, map<string, uint32_t>& address) { - 35 int current_address = s.start; - 36 for (int i = 0; i < SIZE(s.lines); ++i) { - 37 const line& inst = s.lines.at(i); - 38 for (int j = 0; j < SIZE(inst.words); ++j) { - 39 const word& curr = inst.words.at(j); - 40 if (*curr.data.rbegin() != ':') { - 41 current_address += size_of(curr); - 42 } - 43 else { - 44 string variable = drop_last(curr.data); - 45 // ensure variables look sufficiently different from raw hex - 46 check_valid_name(variable); - 47 if (trace_contains_errors()) return; - 48 if (j > 0) - 49 raise << "'" << to_string(inst) << "': global variable names can only be the first word in a line.\n" << end(); - 50 if (Map_file.is_open()) - 51 Map_file << "0x" << HEXWORD << current_address << ' ' << variable << '\n'; - 52 put(address, variable, current_address); - 53 trace(99, "transform") << "global variable '" << variable << "' is at address 0x" << HEXWORD << current_address << end(); - 54 // no modifying current_address; global variable definitions won't be in the final binary - 55 } - 56 } - 57 } - 58 } - 59 - 60 void drop_global_variables(program& p) { - 61 for (int i = /*skip code segment*/1; i < SIZE(p.segments); ++i) - 62 drop_labels(p.segments.at(i)); + 22 // Begin rewrite_global_variables + 23 map<string, uint32_t> address; + 24 compute_addresses_for_global_variables(p, address); + 25 if (trace_contains_errors()) return; + 26 drop_global_variables(p); + 27 replace_global_variables_with_addresses(p, address); + 28 } + 29 + 30 void compute_addresses_for_global_variables(const program& p, map<string, uint32_t>& address) { + 31 for (int i = /*skip code segment*/1; i < SIZE(p.segments); ++i) + 32 compute_addresses_for_global_variables(p.segments.at(i), address); + 33 } + 34 + 35 void compute_addresses_for_global_variables(const segment& s, map<string, uint32_t>& address) { + 36 int current_address = s.start; + 37 for (int i = 0; i < SIZE(s.lines); ++i) { + 38 const line& inst = s.lines.at(i); + 39 for (int j = 0; j < SIZE(inst.words); ++j) { + 40 const word& curr = inst.words.at(j); + 41 if (*curr.data.rbegin() != ':') { + 42 current_address += size_of(curr); + 43 } + 44 else { + 45 string variable = drop_last(curr.data); + 46 // ensure variables look sufficiently different from raw hex + 47 check_valid_name(variable); + 48 if (trace_contains_errors()) return; + 49 if (j > 0) + 50 raise << "'" << to_string(inst) << "': global variable names can only be the first word in a line.\n" << end(); + 51 if (Map_file.is_open()) + 52 Map_file << "0x" << HEXWORD << current_address << ' ' << variable << '\n'; + 53 if (contains_key(address, variable)) { + 54 raise << "duplicate global '" << variable << "'\n" << end(); + 55 return; + 56 } + 57 put(address, variable, current_address); + 58 trace(99, "transform") << "global variable '" << variable << "' is at address 0x" << HEXWORD << current_address << end(); + 59 // no modifying current_address; global variable definitions won't be in the final binary + 60 } + 61 } + 62 } 63 } 64 - 65 void replace_global_variables_with_addresses(program& p, const map<string, uint32_t>& address) { - 66 if (p.segments.empty()) return; - 67 replace_global_variables_in_code_segment(p.segments.at(0), address); - 68 for (int i = /*skip code*/1; i < SIZE(p.segments); ++i) - 69 replace_global_variables_in_data_segment(p.segments.at(i), address); - 70 } - 71 - 72 void replace_global_variables_in_code_segment(segment& code, const map<string, uint32_t>& address) { - 73 for (int i = 0; i < SIZE(code.lines); ++i) { - 74 line& inst = code.lines.at(i); - 75 line new_inst; - 76 for (int j = 0; j < SIZE(inst.words); ++j) { - 77 const word& curr = inst.words.at(j); - 78 if (!contains_key(address, curr.data)) { - 79 if (!looks_like_hex_int(curr.data)) - 80 raise << "missing reference to global '" << curr.data << "'\n" << end(); - 81 new_inst.words.push_back(curr); - 82 continue; - 83 } - 84 if (!valid_use_of_global_variable(curr)) { - 85 raise << "'" << to_string(inst) << "': can't refer to global variable '" << curr.data << "'\n" << end(); - 86 return; - 87 } - 88 emit_hex_bytes(new_inst, get(address, curr.data), 4); - 89 } - 90 inst.words.swap(new_inst.words); - 91 trace(99, "transform") << "instruction after transform: '" << data_to_string(inst) << "'" << end(); - 92 } - 93 } - 94 - 95 void replace_global_variables_in_data_segment(segment& data, const map<string, uint32_t>& address) { - 96 for (int i = 0; i < SIZE(data.lines); ++i) { - 97 line& l = data.lines.at(i); - 98 line new_l; - 99 for (int j = 0; j < SIZE(l.words); ++j) { -100 const word& curr = l.words.at(j); -101 if (!contains_key(address, curr.data)) { -102 if (!looks_like_hex_int(curr.data)) -103 raise << "missing reference to global '" << curr.data << "'\n" << end(); -104 new_l.words.push_back(curr); -105 continue; -106 } -107 trace(99, "transform") << curr.data << " maps to " << HEXWORD << get(address, curr.data) << end(); -108 emit_hex_bytes(new_l, get(address, curr.data), 4); -109 } -110 l.words.swap(new_l.words); -111 trace(99, "transform") << "after transform: '" << data_to_string(l) << "'" << end(); -112 } -113 } -114 -115 bool valid_use_of_global_variable(const word& curr) { -116 if (has_operand_metadata(curr, "imm32")) return true; -117 // End Valid Uses Of Global Variable(curr) -118 return false; -119 } -120 -121 //:: a more complex sanity check for how we use global variables -122 //: requires first saving some data early before we pack operands -123 -124 :(after "Begin Level-2 Transforms") -125 Transform.push_back(correlate_disp32_with_mod); -126 :(code) -127 void correlate_disp32_with_mod(program& p) { -128 if (p.segments.empty()) return; -129 segment& code = p.segments.at(0); -130 for (int i = 0; i < SIZE(code.lines); ++i) { -131 line& inst = code.lines.at(i); -132 for (int j = 0; j < SIZE(inst.words); ++j) { -133 word& curr = inst.words.at(j); -134 if (has_operand_metadata(curr, "disp32") -135 && has_operand_metadata(inst, "mod")) -136 curr.metadata.push_back("has_mod"); -137 } -138 } -139 } -140 -141 :(before "End Valid Uses Of Global Variable(curr)") -142 if (has_operand_metadata(curr, "disp32")) -143 return has_metadata(curr, "has_mod"); -144 // todo: more sophisticated check, to ensure we don't use global variable -145 // addresses as a real displacement added to other operands. -146 -147 :(code) -148 bool has_metadata(const word& w, const string& m) { -149 for (int i = 0; i < SIZE(w.metadata); ++i) -150 if (w.metadata.at(i) == m) return true; -151 return false; -152 } -153 -154 :(scenario global_variable_disallowed_in_jump) -155 % Hide_errors = true; -156 == code -157 eb/jump x/disp8 -158 == data -159 x: -160 00 00 00 00 -161 +error: 'eb/jump x/disp8': can't refer to global variable 'x' -162 # sub-optimal error message; should be -163 #? +error: can't jump to data (variable 'x') -164 -165 :(scenario global_variable_disallowed_in_call) -166 % Hide_errors = true; -167 == code -168 e8/call x/disp32 -169 == data -170 x: -171 00 00 00 00 -172 +error: 'e8/call x/disp32': can't refer to global variable 'x' -173 # sub-optimal error message; should be -174 #? +error: can't call to the data segment ('x') -175 -176 :(scenario global_variable_in_data_segment) -177 == 0x1 -178 b9 x/imm32 -179 == 0x0a000000 -180 x: -181 y/imm32 -182 y: -183 00 00 00 00 -184 # check that we loaded 'x' with the address of 'y' -185 +load: 0x0a000000 -> 04 -186 +load: 0x0a000001 -> 00 -187 +load: 0x0a000002 -> 00 -188 +load: 0x0a000003 -> 0a -189 $error: 0 -190 -191 :(scenario disp32_data_with_modrm) -192 == code -193 8b/copy 0/mod/indirect 5/rm32/.disp32 2/r32/EDX x/disp32 -194 == data -195 x: -196 00 00 00 00 -197 $error: 0 -198 -199 :(scenarios transform) -200 :(scenario disp32_data_with_call) -201 == code -202 foo: -203 e8/call bar/disp32 -204 bar: -205 $error: 0 -206 -207 :(code) -208 string to_full_string(const line& in) { -209 ostringstream out; -210 for (int i = 0; i < SIZE(in.words); ++i) { -211 if (i > 0) out << ' '; -212 out << in.words.at(i).data; -213 for (int j = 0; j < SIZE(in.words.at(i).metadata); ++j) -214 out << '/' << in.words.at(i).metadata.at(j); -215 } -216 return out.str(); -217 } + 65 void drop_global_variables(program& p) { + 66 for (int i = /*skip code segment*/1; i < SIZE(p.segments); ++i) + 67 drop_labels(p.segments.at(i)); + 68 } + 69 + 70 void replace_global_variables_with_addresses(program& p, const map<string, uint32_t>& address) { + 71 if (p.segments.empty()) return; + 72 replace_global_variables_in_code_segment(p.segments.at(0), address); + 73 for (int i = /*skip code*/1; i < SIZE(p.segments); ++i) + 74 replace_global_variables_in_data_segment(p.segments.at(i), address); + 75 } + 76 + 77 void replace_global_variables_in_code_segment(segment& code, const map<string, uint32_t>& address) { + 78 for (int i = 0; i < SIZE(code.lines); ++i) { + 79 line& inst = code.lines.at(i); + 80 line new_inst; + 81 for (int j = 0; j < SIZE(inst.words); ++j) { + 82 const word& curr = inst.words.at(j); + 83 if (!contains_key(address, curr.data)) { + 84 if (!looks_like_hex_int(curr.data)) + 85 raise << "missing reference to global '" << curr.data << "'\n" << end(); + 86 new_inst.words.push_back(curr); + 87 continue; + 88 } + 89 if (!valid_use_of_global_variable(curr)) { + 90 raise << "'" << to_string(inst) << "': can't refer to global variable '" << curr.data << "'\n" << end(); + 91 return; + 92 } + 93 emit_hex_bytes(new_inst, get(address, curr.data), 4); + 94 } + 95 inst.words.swap(new_inst.words); + 96 trace(99, "transform") << "instruction after transform: '" << data_to_string(inst) << "'" << end(); + 97 } + 98 } + 99 +100 void replace_global_variables_in_data_segment(segment& data, const map<string, uint32_t>& address) { +101 for (int i = 0; i < SIZE(data.lines); ++i) { +102 line& l = data.lines.at(i); +103 line new_l; +104 for (int j = 0; j < SIZE(l.words); ++j) { +105 const word& curr = l.words.at(j); +106 if (!contains_key(address, curr.data)) { +107 if (!looks_like_hex_int(curr.data)) +108 raise << "missing reference to global '" << curr.data << "'\n" << end(); +109 new_l.words.push_back(curr); +110 continue; +111 } +112 trace(99, "transform") << curr.data << " maps to " << HEXWORD << get(address, curr.data) << end(); +113 emit_hex_bytes(new_l, get(address, curr.data), 4); +114 } +115 l.words.swap(new_l.words); +116 trace(99, "transform") << "after transform: '" << data_to_string(l) << "'" << end(); +117 } +118 } +119 +120 bool valid_use_of_global_variable(const word& curr) { +121 if (has_operand_metadata(curr, "imm32")) return true; +122 // End Valid Uses Of Global Variable(curr) +123 return false; +124 } +125 +126 //:: a more complex sanity check for how we use global variables +127 //: requires first saving some data early before we pack operands +128 +129 :(after "Begin Level-2 Transforms") +130 Transform.push_back(correlate_disp32_with_mod); +131 :(code) +132 void correlate_disp32_with_mod(program& p) { +133 if (p.segments.empty()) return; +134 segment& code = p.segments.at(0); +135 for (int i = 0; i < SIZE(code.lines); ++i) { +136 line& inst = code.lines.at(i); +137 for (int j = 0; j < SIZE(inst.words); ++j) { +138 word& curr = inst.words.at(j); +139 if (has_operand_metadata(curr, "disp32") +140 && has_operand_metadata(inst, "mod")) +141 curr.metadata.push_back("has_mod"); +142 } +143 } +144 } +145 +146 :(before "End Valid Uses Of Global Variable(curr)") +147 if (has_operand_metadata(curr, "disp32")) +148 return has_metadata(curr, "has_mod"); +149 // todo: more sophisticated check, to ensure we don't use global variable +150 // addresses as a real displacement added to other operands. +151 +152 :(code) +153 bool has_metadata(const word& w, const string& m) { +154 for (int i = 0; i < SIZE(w.metadata); ++i) +155 if (w.metadata.at(i) == m) return true; +156 return false; +157 } +158 +159 :(scenario global_variable_disallowed_in_jump) +160 % Hide_errors = true; +161 == code +162 eb/jump x/disp8 +163 == data +164 x: +165 00 00 00 00 +166 +error: 'eb/jump x/disp8': can't refer to global variable 'x' +167 # sub-optimal error message; should be +168 #? +error: can't jump to data (variable 'x') +169 +170 :(scenario global_variable_disallowed_in_call) +171 % Hide_errors = true; +172 == code +173 e8/call x/disp32 +174 == data +175 x: +176 00 00 00 00 +177 +error: 'e8/call x/disp32': can't refer to global variable 'x' +178 # sub-optimal error message; should be +179 #? +error: can't call to the data segment ('x') +180 +181 :(scenario global_variable_in_data_segment) +182 == 0x1 +183 b9 x/imm32 +184 == 0x0a000000 +185 x: +186 y/imm32 +187 y: +188 00 00 00 00 +189 # check that we loaded 'x' with the address of 'y' +190 +load: 0x0a000000 -> 04 +191 +load: 0x0a000001 -> 00 +192 +load: 0x0a000002 -> 00 +193 +load: 0x0a000003 -> 0a +194 $error: 0 +195 +196 :(scenario duplicate_global_variable) +197 % Hide_errors = true; +198 == 0x1 +199 40/increment-EAX +200 == 0x0a000000 +201 x: +202 x: +203 00 +204 +error: duplicate global 'x' +205 +206 :(scenario disp32_data_with_modrm) +207 == code +208 8b/copy 0/mod/indirect 5/rm32/.disp32 2/r32/EDX x/disp32 +209 == data +210 x: +211 00 00 00 00 +212 $error: 0 +213 +214 :(scenarios transform) +215 :(scenario disp32_data_with_call) +216 == code +217 foo: +218 e8/call bar/disp32 +219 bar: +220 $error: 0 +221 +222 :(code) +223 string to_full_string(const line& in) { +224 ostringstream out; +225 for (int i = 0; i < SIZE(in.words); ++i) { +226 if (i > 0) out << ' '; +227 out << in.words.at(i).data; +228 for (int j = 0; j < SIZE(in.words.at(i).metadata); ++j) +229 out << '/' << in.words.at(i).metadata.at(j); +230 } +231 return out.str(); +232 } -- cgit 1.4.1-2-gfad0