OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <errno.h> | 5 #include <errno.h> |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <set> | 8 #include <set> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 // common code paths in the topo-sort algorithm. | 136 // common code paths in the topo-sort algorithm. |
137 // This also gives us a diamond-shaped pattern in our graph, which stresses | 137 // This also gives us a diamond-shaped pattern in our graph, which stresses |
138 // another aspect of the topo-sort algorithm (namely, the ability to | 138 // another aspect of the topo-sort algorithm (namely, the ability to |
139 // correctly count the incoming branches for subtrees that are not disjunct). | 139 // correctly count the incoming branches for subtrees that are not disjunct). |
140 Instruction *insn6 = codegen->MakeInstruction(BPF_JMP+BPF_JEQ+BPF_K, 42, | 140 Instruction *insn6 = codegen->MakeInstruction(BPF_JMP+BPF_JEQ+BPF_K, 42, |
141 insn5, insn4); | 141 insn5, insn4); |
142 | 142 |
143 return insn6; | 143 return insn6; |
144 } | 144 } |
145 | 145 |
| 146 Instruction* SampleProgramConfusingTails(CodeGen* codegen, int* flags) { |
| 147 // This simple program demonstrates https://crbug.com/351103/ |
| 148 // The two "LOAD 0" instructions are blocks of their own. MergeTails() could |
| 149 // be tempted to merge them since they are the same. However, they are |
| 150 // not mergeable because they fall-through to non semantically equivalent |
| 151 // blocks. |
| 152 // Without the fix for this bug, this program should trigger the check in |
| 153 // CompileAndCompare: the serialized graphs from the program and its compiled |
| 154 // version will differ. |
| 155 // |
| 156 // 0) LOAD 1 // ??? |
| 157 // 1) if A == 0x1; then JMP 2 else JMP 3 |
| 158 // 2) LOAD 0 // System call number |
| 159 // 3) if A == 0x2; then JMP 4 else JMP 5 |
| 160 // 4) LOAD 0 // System call number |
| 161 // 5) if A == 0x1; then JMP 6 else JMP 7 |
| 162 // 6) RET 0x50000 // errno = 0 |
| 163 // 7) RET 0x50001 // errno = 1 |
| 164 *flags = NO_FLAGS; |
| 165 |
| 166 Instruction* i7 = codegen->MakeInstruction(BPF_RET, ErrorCode(1)); |
| 167 Instruction* i6 = codegen->MakeInstruction(BPF_RET, ErrorCode(0)); |
| 168 Instruction* i5 = |
| 169 codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i6, i7); |
| 170 Instruction* i4 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0, i5); |
| 171 Instruction* i3 = |
| 172 codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 2, i4, i5); |
| 173 Instruction* i2 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0, i3); |
| 174 Instruction* i1 = |
| 175 codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i2, i3); |
| 176 Instruction* i0 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 1, i1); |
| 177 |
| 178 return i0; |
| 179 } |
| 180 |
| 181 Instruction* SampleProgramConfusingTailsBasic(CodeGen* codegen, int* flags) { |
| 182 // Without the fix for https://crbug.com/351103/, (see |
| 183 // SampleProgramConfusingTails()), this would generate a cyclic graph and |
| 184 // crash as the two "LOAD 0" instructions would get merged. |
| 185 // |
| 186 // 0) LOAD 1 // ??? |
| 187 // 1) if A == 0x1; then JMP 2 else JMP 3 |
| 188 // 2) LOAD 0 // System call number |
| 189 // 3) if A == 0x2; then JMP 4 else JMP 5 |
| 190 // 4) LOAD 0 // System call number |
| 191 // 5) RET 0x50001 // errno = 1 |
| 192 *flags = NO_FLAGS; |
| 193 |
| 194 Instruction* i5 = codegen->MakeInstruction(BPF_RET, ErrorCode(1)); |
| 195 Instruction* i4 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0, i5); |
| 196 Instruction* i3 = |
| 197 codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 2, i4, i5); |
| 198 Instruction* i2 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0, i3); |
| 199 Instruction* i1 = |
| 200 codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i2, i3); |
| 201 Instruction* i0 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 1, i1); |
| 202 |
| 203 return i0; |
| 204 } |
| 205 |
| 206 Instruction* SampleProgramConfusingTailsMergeable(CodeGen* codegen, |
| 207 int* flags) { |
| 208 // This is similar to SampleProgramConfusingTails(), except that |
| 209 // instructions 2 and 4 are now RET instructions. |
| 210 // In PointerCompare(), this exercises the path where two blocks are of the |
| 211 // same length and identical and the last instruction is a JMP or RET, so the |
| 212 // following blocks don't need to be looked at and the blocks are mergeable. |
| 213 // |
| 214 // 0) LOAD 1 // ??? |
| 215 // 1) if A == 0x1; then JMP 2 else JMP 3 |
| 216 // 2) RET 0x5002a // errno = 42 |
| 217 // 3) if A == 0x2; then JMP 4 else JMP 5 |
| 218 // 4) RET 0x5002a // errno = 42 |
| 219 // 5) if A == 0x1; then JMP 6 else JMP 7 |
| 220 // 6) RET 0x50000 // errno = 0 |
| 221 // 7) RET 0x50001 // errno = 1 |
| 222 *flags = HAS_MERGEABLE_TAILS; |
| 223 |
| 224 Instruction* i7 = codegen->MakeInstruction(BPF_RET, ErrorCode(1)); |
| 225 Instruction* i6 = codegen->MakeInstruction(BPF_RET, ErrorCode(0)); |
| 226 Instruction* i5 = |
| 227 codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i6, i7); |
| 228 Instruction* i4 = codegen->MakeInstruction(BPF_RET, ErrorCode(42)); |
| 229 Instruction* i3 = |
| 230 codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 2, i4, i5); |
| 231 Instruction* i2 = codegen->MakeInstruction(BPF_RET, ErrorCode(42)); |
| 232 Instruction* i1 = |
| 233 codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i2, i3); |
| 234 Instruction* i0 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 1, i1); |
| 235 |
| 236 return i0; |
| 237 } |
| 238 |
146 void ForAllPrograms(void (*test)(CodeGenUnittestHelper *, Instruction *, int)){ | 239 void ForAllPrograms(void (*test)(CodeGenUnittestHelper *, Instruction *, int)){ |
147 Instruction *(*function_table[])(CodeGen *codegen, int *flags) = { | 240 Instruction *(*function_table[])(CodeGen *codegen, int *flags) = { |
148 SampleProgramOneInstruction, | 241 SampleProgramOneInstruction, |
149 SampleProgramSimpleBranch, | 242 SampleProgramSimpleBranch, |
150 SampleProgramAtypicalBranch, | 243 SampleProgramAtypicalBranch, |
151 SampleProgramComplex, | 244 SampleProgramComplex, |
| 245 SampleProgramConfusingTails, |
| 246 SampleProgramConfusingTailsBasic, |
| 247 SampleProgramConfusingTailsMergeable, |
152 }; | 248 }; |
153 | 249 |
154 for (size_t i = 0; i < arraysize(function_table); ++i) { | 250 for (size_t i = 0; i < arraysize(function_table); ++i) { |
155 CodeGenUnittestHelper codegen; | 251 CodeGenUnittestHelper codegen; |
156 int flags = NO_FLAGS; | 252 int flags = NO_FLAGS; |
157 Instruction *prg = function_table[i](&codegen, &flags); | 253 Instruction *prg = function_table[i](&codegen, &flags); |
158 test(&codegen, prg, flags); | 254 test(&codegen, prg, flags); |
159 } | 255 } |
160 } | 256 } |
161 | 257 |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 assembly.append(reinterpret_cast<char *>(&insn.k), sizeof(insn.k)); | 534 assembly.append(reinterpret_cast<char *>(&insn.k), sizeof(insn.k)); |
439 } | 535 } |
440 SANDBOX_ASSERT(source == assembly); | 536 SANDBOX_ASSERT(source == assembly); |
441 } | 537 } |
442 | 538 |
443 SANDBOX_TEST(CodeGen, All) { | 539 SANDBOX_TEST(CodeGen, All) { |
444 ForAllPrograms(CompileAndCompare); | 540 ForAllPrograms(CompileAndCompare); |
445 } | 541 } |
446 | 542 |
447 } // namespace sandbox | 543 } // namespace sandbox |
OLD | NEW |