// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "sandbox/linux/bpf_dsl/codegen.h" #include <stddef.h> #include <stdint.h> #include <limits> #include <ostream> #include <utility> #include "base/check_op.h" #include "sandbox/linux/system_headers/linux_filter.h" // This CodeGen implementation strives for simplicity while still // generating acceptable BPF programs under typical usage patterns // (e.g., by PolicyCompiler). // // The key to its simplicity is that BPF programs only support forward // jumps/branches, which allows constraining the DAG construction API // to make instruction nodes immutable. Immutable nodes admits a // simple greedy approach of emitting new instructions as needed and // then reusing existing ones that have already been emitted. This // cleanly avoids any need to compute basic blocks or apply // topological sorting because the API effectively sorts instructions // for us (e.g., before MakeInstruction() can be called to emit a // branch instruction, it must have already been called for each // branch path). // // This greedy algorithm is not without (theoretical) weakness though: // // 1. In the general case, we don't eliminate dead code. If needed, // we could trace back through the program in Compile() and elide // any unneeded instructions, but in practice we only emit live // instructions anyway. // // 2. By not dividing instructions into basic blocks and sorting, we // lose an opportunity to move non-branch/non-return instructions // adjacent to their successor instructions, which means we might // need to emit additional jumps. But in practice, they'll // already be nearby as long as callers don't go out of their way // to interleave MakeInstruction() calls for unrelated code // sequences. namespace sandbox { // kBranchRange is the maximum value that can be stored in // sock_filter's 8-bit jt and jf fields. const size_t kBranchRange = …; const CodeGen::Node CodeGen::kNullNode; CodeGen::CodeGen() : … { … } CodeGen::~CodeGen() { … } CodeGen::Program CodeGen::Compile(CodeGen::Node head) { … } CodeGen::Node CodeGen::MakeInstruction(uint16_t code, uint32_t k, Node jt, Node jf) { … } CodeGen::Node CodeGen::AppendInstruction(uint16_t code, uint32_t k, Node jt, Node jf) { … } CodeGen::Node CodeGen::WithinRange(Node target, size_t range) { … } CodeGen::Node CodeGen::Append(uint16_t code, uint32_t k, size_t jt, size_t jf) { … } size_t CodeGen::Offset(Node target) const { … } } // namespace sandbox