Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Backtracker ¶
type Backtracker struct {
// contains filtered or unexported fields
}
Backtracker is an iterator that walks backwards through a Block's instructions.
This is useful for finding the last instruction that wrote to a register before it is read, by following the control flow backwards.
func (*Backtracker) Clone ¶
func (bt *Backtracker) Clone() *Backtracker
Clone creates a copy of the Backtracker at its current position.
func (*Backtracker) Instruction ¶
func (bt *Backtracker) Instruction() *asm.Instruction
Instruction returns the current instruction.
func (*Backtracker) Previous ¶
func (bt *Backtracker) Previous() bool
Previous moves to the previous instruction within the block. Returns false when reaching the start of the block.
func (*Backtracker) Seek ¶
func (bt *Backtracker) Seek(index int) *Backtracker
Seek moves the Backtracker to the given instruction index within the block and pulls the instruction.
Panics if the index is out of bounds of the block.
type Bitmap ¶
type Bitmap []uint64
Bitmap is a Bitmap used to track which blocks are reachable in the control flow graph.
func NewBitmap ¶
NewBitmap returns a bitmap capable of tracking at least n items. All bits are false by default.
func (Bitmap) Get ¶
Get returns the value of the bit at index i. If i is out of bounds, it returns false.
type Block ¶
type Block struct {
// contains filtered or unexported fields
}
A Block is a contiguous sequence of instructions that are executed together. Boundaries are defined by branching instructions.
Blocks are attached to instructions via metadata and should not be modified after being created.
It should never contain direct references to the original asm.Instructions since copying the ProgramSpec won't update pointers to the new copied insns. This is a problem when modifying instructions through [Blocks.LiveInstructions] after reachability analysis, since it would modify the original ProgramSpec's instructions.
type BlockIterator ¶
type BlockIterator struct {
// contains filtered or unexported fields
}
BlockIterator is an iterator over the instructions in a block or a list of blocks.
It can be configured to iterate locally within a block or globally across multiple blocks. When iterating globally, it will roll over to the next or previous block when reaching the end or start of the current block, respectively.
The iterator tracks the raw instruction offset of the current instruction when iterating forwards, but not when iterating backwards since that would require summing up instruction sizes from the start of the block. Raw offsets are only used for dumping instructions in forward order.
func (*BlockIterator) Backtrack ¶
func (i *BlockIterator) Backtrack() *Backtracker
Backtrack returns a Backtracker starting at the current instruction of the BlockIterator.
Backtracker.Instruction will return the same instruction as the current instruction of the BlockIterator.
Backtracker.Previous will return the instruction preceding the current one, if any.
func (*BlockIterator) Index ¶
func (i *BlockIterator) Index() int
func (*BlockIterator) Instruction ¶
func (i *BlockIterator) Instruction() *asm.Instruction
func (*BlockIterator) Next ¶
func (i *BlockIterator) Next() bool
Next advances the iterator to the next instruction in the block. If the end of the block is reached, it will either stop (if iterating locally) or roll over to the next block (if iterating globally).
func (*BlockIterator) Offset ¶
func (i *BlockIterator) Offset() asm.RawInstructionOffset
type Blocks ¶
type Blocks []*Block
Blocks is a list of basic blocks.
func MakeBlocks ¶
func MakeBlocks(insns asm.Instructions) (Blocks, error)
MakeBlocks returns a list of basic blocks of instructions that are always executed together. Multiple calls on the same insns will return the same Blocks object.
Blocks are created by finding branches and jump targets in the given insns and cutting up the instruction stream accordingly.
type Reachable ¶
type Reachable struct {
// contains filtered or unexported fields
}
func Reachability ¶
func Reachability(blocks Blocks, insns asm.Instructions, variables map[string]*ebpf.VariableSpec) (*Reachable, error)
Reachability determines whether or not each Block in blocks is reachable given the variables.
Reachability of blocks is determined by predicting branches on BPF runtime constants. A subsequent call to [Blocks.LiveInstructions] will iterate over all instructions deemed reachable given the set of VariableSpecs.
Given a piece of code like:
if (CONFIG(enable_feature_a)) {
or
if (CONFIG(number_of_something) > 5) {
It looks for the following bytecode:
LoadMapValue dst: Rx, fd: 0 off: {offset of variable} <{name of global data map}>
LdXMem{B,H,W,DW} dst: Ry src: Rx off: 0
J{OP}IMM dst: Ry off:{relative jump offset} imm: {constant value}
func (*Reachable) Iterate ¶
func (r *Reachable) Iterate() iter.Seq2[*BlockIterator, bool]
Iterate returns an iterator that wraps an internal BlockIterator. The internal iterator is yielded along with a bool indicating whether the current instruction is reachable.
The BlockIterator itself is yielded so it can be cloned to start a backtracking session.