Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(44)

Side by Side Diff: src/processor/disassembler_x86.cc

Issue 203001: Added libdisasm to the repository. This library is no longer under developmen... (Closed) Base URL: http://google-breakpad.googlecode.com/svn/trunk/
Patch Set: '' Created 14 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // copyright notice, this list of conditions and the following disclaimer
2 // in the documentation and/or other materials provided with the
3 // distribution.
4 // * Neither the name of Google Inc. nor the names of its
5 // contributors may be used to endorse or promote products derived from
6 // this software without specific prior written permission.
7 //
8 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
9 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
10 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
11 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
12 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
13 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
14 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
15 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
16 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
18 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
20 // disassembler_x86.cc: simple x86 disassembler.
21 //
22 // Provides single step disassembly of x86 bytecode and flags instructions
23 // that utilize known bad register values.
24 //
25 // Author: Cris Neckar
26
27 #include "processor/disassembler_x86.h"
28
29 #include <string.h>
30 #include <unistd.h>
31
32 namespace google_breakpad {
33
34 DisassemblerX86::DisassemblerX86(const u_int8_t *bytecode,
35 u_int32_t size,
36 u_int32_t virtual_address) :
37 bytecode_(bytecode),
38 size_(size),
39 virtual_address_(virtual_address),
40 current_byte_offset_(0),
41 current_inst_offset_(0),
42 instr_valid_(false),
43 register_valid_(false),
44 pushed_bad_value_(false),
45 end_of_block_(false),
46 flags_(0) {
47 libdis::x86_init(libdis::opt_none, NULL, NULL);
48 }
49
50 DisassemblerX86::~DisassemblerX86() {
51 libdis::x86_cleanup();
52 }
53
54 u_int32_t DisassemblerX86::NextInstruction() {
55 if (instr_valid_)
56 libdis::x86_oplist_free(&current_instr_);
57
58 if (current_byte_offset_ >= size_) {
59 instr_valid_ = false;
60 return 0;
61 }
62 u_int32_t instr_size = 0;
63 instr_size = libdis::x86_disasm((unsigned char *)bytecode_, size_,
64 virtual_address_, current_byte_offset_,
65 &current_instr_);
66 if (instr_size == 0) {
67 instr_valid_ = false;
68 return 0;
69 }
70
71 current_byte_offset_ += instr_size;
72 current_inst_offset_++;
73 instr_valid_ = libdis::x86_insn_is_valid(&current_instr_);
74 if (!instr_valid_)
75 return 0;
76
77 if (current_instr_.type == libdis::insn_return)
78 end_of_block_ = true;
79 libdis::x86_op_t *src = libdis::x86_get_src_operand(&current_instr_);
80 libdis::x86_op_t *dest = libdis::x86_get_dest_operand(&current_instr_);
81
82 if (register_valid_) {
83 switch (current_instr_.group) {
84 // Flag branches based off of bad registers and calls that occur
85 // after pushing bad values.
86 case libdis::insn_controlflow:
87 switch (current_instr_.type) {
88 case libdis::insn_jmp:
89 case libdis::insn_jcc:
90 case libdis::insn_call:
91 case libdis::insn_callcc:
92 if (dest) {
93 switch (dest->type) {
94 case libdis::op_expression:
95 if (dest->data.expression.base.id == bad_register_.id)
96 flags_ |= DISX86_BAD_BRANCH_TARGET;
97 break;
98 case libdis::op_register:
99 if (dest->data.reg.id == bad_register_.id)
100 flags_ |= DISX86_BAD_BRANCH_TARGET;
101 break;
102 default:
103 if (pushed_bad_value_ &&
104 (current_instr_.type == libdis::insn_call ||
105 current_instr_.type == libdis::insn_callcc))
106 flags_ |= DISX86_BAD_ARGUMENT_PASSED;
107 break;
108 }
109 }
110 break;
111 }
112 break;
113
114 // Flag block data operations that use bad registers for src or dest.
115 case libdis::insn_string:
116 if (dest && dest->type == libdis::op_expression &&
117 dest->data.expression.base.id == bad_register_.id)
118 flags_ |= DISX86_BAD_BLOCK_WRITE;
119 if (src && src->type == libdis::op_expression &&
120 src->data.expression.base.id == bad_register_.id)
121 flags_ |= DISX86_BAD_BLOCK_READ;
122 break;
123
124 // Flag comparisons based on bad data.
125 case libdis::insn_comparison:
126 if ((dest && dest->type == libdis::op_expression &&
127 dest->data.expression.base.id == bad_register_.id) ||
128 (src && src->type == libdis::op_expression &&
129 src->data.expression.base.id == bad_register_.id) ||
130 (dest && dest->type == libdis::op_register &&
131 dest->data.reg.id == bad_register_.id) ||
132 (src && src->type == libdis::op_register &&
133 src->data.reg.id == bad_register_.id))
134 flags_ |= DISX86_BAD_COMPARISON;
135 break;
136
137 // Flag any other instruction which derefs a bad register for
138 // src or dest.
139 default:
140 if (dest && dest->type == libdis::op_expression &&
141 dest->data.expression.base.id == bad_register_.id)
142 flags_ |= DISX86_BAD_WRITE;
143 if (src && src->type == libdis::op_expression &&
144 src->data.expression.base.id == bad_register_.id)
145 flags_ |= DISX86_BAD_READ;
146 break;
147 }
148 }
149
150 // When a register is marked as tainted check if it is pushed.
151 // TODO(cdn): may also want to check for MOVs into EBP offsets.
152 if (register_valid_ && dest && current_instr_.type == libdis::insn_push) {
153 switch (dest->type) {
154 case libdis::op_expression:
155 if (dest->data.expression.base.id == bad_register_.id ||
156 dest->data.expression.index.id == bad_register_.id)
157 pushed_bad_value_ = true;
158 break;
159 case libdis::op_register:
160 if (dest->data.reg.id == bad_register_.id)
161 pushed_bad_value_ = true;
162 break;
163 }
164 }
165
166 // Check if a tainted register value is clobbered.
167 // For conditional MOVs and XCHGs assume that
168 // there is a hit.
169 if (register_valid_) {
170 switch (current_instr_.type) {
171 case libdis::insn_xor:
172 if (src && src->type == libdis::op_register &&
173 dest->type == libdis::op_register &&
174 src->data.reg.id == bad_register_.id &&
175 src->data.reg.id == dest->data.reg.id)
176 register_valid_ = false;
177 break;
178 case libdis::insn_pop:
179 case libdis::insn_mov:
180 case libdis::insn_movcc:
181 if (dest && dest->type == libdis::op_register &&
182 dest->data.reg.id == bad_register_.id)
183 register_valid_ = false;
184 break;
185 case libdis::insn_popregs:
186 register_valid_ = false;
187 break;
188 case libdis::insn_xchg:
189 case libdis::insn_xchgcc:
190 if (dest && dest->type == libdis::op_register &&
191 src->type == libdis::op_register) {
192 if (dest->data.reg.id == bad_register_.id)
193 memcpy(&bad_register_, &src->data.reg, sizeof(libdis::x86_reg_t));
194 else if (src->data.reg.id == bad_register_.id)
195 memcpy(&bad_register_, &dest->data.reg, sizeof(libdis::x86_reg_t));
196 }
197 break;
198 }
199 }
200
201 return instr_size;
202 }
203
204 bool DisassemblerX86::setBadRead() {
205 if (!instr_valid_)
206 return false;
207
208 libdis::x86_op_t *operand = libdis::x86_get_src_operand(&current_instr_);
209 if (operand->type != libdis::op_expression)
210 return false;
211
212 memcpy(&bad_register_, &operand->data.expression.base,
213 sizeof(libdis::x86_reg_t));
214 register_valid_ = true;
215 return true;
216 }
217
218 bool DisassemblerX86::setBadWrite() {
219 if (!instr_valid_)
220 return false;
221
222 libdis::x86_op_t *operand = libdis::x86_get_dest_operand(&current_instr_);
223 if (operand->type != libdis::op_expression)
224 return false;
225
226 memcpy(&bad_register_, &operand->data.expression.base,
227 sizeof(libdis::x86_reg_t));
228 register_valid_ = true;
229 return true;
230 }
231
232 } // namespace google_breakpad
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld 1004:630ec63f810e-tainted