| 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 "sandbox/linux/bpf_dsl/codegen.h" | 5 #include "sandbox/linux/bpf_dsl/codegen.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <limits> | 10 #include <limits> |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 *node = AppendInstruction(code, k, jt, jf); | 73 *node = AppendInstruction(code, k, jt, jf); |
| 74 } | 74 } |
| 75 return *node; | 75 return *node; |
| 76 } | 76 } |
| 77 | 77 |
| 78 CodeGen::Node CodeGen::AppendInstruction(uint16_t code, | 78 CodeGen::Node CodeGen::AppendInstruction(uint16_t code, |
| 79 uint32_t k, | 79 uint32_t k, |
| 80 Node jt, | 80 Node jt, |
| 81 Node jf) { | 81 Node jf) { |
| 82 if (BPF_CLASS(code) == BPF_JMP) { | 82 if (BPF_CLASS(code) == BPF_JMP) { |
| 83 CHECK_NE(BPF_JA, BPF_OP(code)) << "CodeGen inserts JAs as needed"; | 83 // CodeGen inserts JAs as needed |
| 84 CHECK_NE(BPF_JA, BPF_OP(code)); |
| 84 | 85 |
| 85 // Optimally adding jumps is rather tricky, so we use a quick | 86 // Optimally adding jumps is rather tricky, so we use a quick |
| 86 // approximation: by artificially reducing |jt|'s range, |jt| will | 87 // approximation: by artificially reducing |jt|'s range, |jt| will |
| 87 // stay within its true range even if we add a jump for |jf|. | 88 // stay within its true range even if we add a jump for |jf|. |
| 88 jt = WithinRange(jt, kBranchRange - 1); | 89 jt = WithinRange(jt, kBranchRange - 1); |
| 89 jf = WithinRange(jf, kBranchRange); | 90 jf = WithinRange(jf, kBranchRange); |
| 90 return Append(code, k, Offset(jt), Offset(jf)); | 91 return Append(code, k, Offset(jt), Offset(jf)); |
| 91 } | 92 } |
| 92 | 93 |
| 93 CHECK_EQ(kNullNode, jf) << "Non-branch instructions shouldn't provide jf"; | 94 // Non-branch instructions shouldn't provide jf |
| 95 CHECK_EQ(kNullNode, jf); |
| 94 if (BPF_CLASS(code) == BPF_RET) { | 96 if (BPF_CLASS(code) == BPF_RET) { |
| 95 CHECK_EQ(kNullNode, jt) << "Return instructions shouldn't provide jt"; | 97 // Return instructions shouldn't provide jt |
| 98 CHECK_EQ(kNullNode, jt); |
| 96 } else { | 99 } else { |
| 97 // For non-branch/non-return instructions, execution always | 100 // For non-branch/non-return instructions, execution always |
| 98 // proceeds to the next instruction; so we need to arrange for | 101 // proceeds to the next instruction; so we need to arrange for |
| 99 // that to be |jt|. | 102 // that to be |jt|. |
| 100 jt = WithinRange(jt, 0); | 103 jt = WithinRange(jt, 0); |
| 101 CHECK_EQ(0U, Offset(jt)) << "ICE: Failed to setup next instruction"; | 104 // ICE: Failed to setup next instruction |
| 105 CHECK_EQ(0U, Offset(jt)); |
| 102 } | 106 } |
| 103 return Append(code, k, 0, 0); | 107 return Append(code, k, 0, 0); |
| 104 } | 108 } |
| 105 | 109 |
| 106 CodeGen::Node CodeGen::WithinRange(Node target, size_t range) { | 110 CodeGen::Node CodeGen::WithinRange(Node target, size_t range) { |
| 107 // Just use |target| if it's already within range. | 111 // Just use |target| if it's already within range. |
| 108 if (Offset(target) <= range) { | 112 if (Offset(target) <= range) { |
| 109 return target; | 113 return target; |
| 110 } | 114 } |
| 111 | 115 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 133 CHECK_EQ(program_.size(), equivalent_.size()); | 137 CHECK_EQ(program_.size(), equivalent_.size()); |
| 134 | 138 |
| 135 Node res = program_.size(); | 139 Node res = program_.size(); |
| 136 program_.push_back(sock_filter{ | 140 program_.push_back(sock_filter{ |
| 137 code, static_cast<uint8_t>(jt), static_cast<uint8_t>(jf), k}); | 141 code, static_cast<uint8_t>(jt), static_cast<uint8_t>(jf), k}); |
| 138 equivalent_.push_back(res); | 142 equivalent_.push_back(res); |
| 139 return res; | 143 return res; |
| 140 } | 144 } |
| 141 | 145 |
| 142 size_t CodeGen::Offset(Node target) const { | 146 size_t CodeGen::Offset(Node target) const { |
| 143 CHECK_LT(target, program_.size()) << "Bogus offset target node"; | 147 // Bogus offset target node |
| 148 CHECK_LT(target, program_.size()); |
| 144 return (program_.size() - 1) - target; | 149 return (program_.size() - 1) - target; |
| 145 } | 150 } |
| 146 | 151 |
| 147 } // namespace sandbox | 152 } // namespace sandbox |
| OLD | NEW |