Documentation ¶
Index ¶
- func ApplyCoverMapToBlockList(coverMap *ebpf.Map, blockList [][]CoverBlock) error
- func BlockListFilePaths(blockList [][]CoverBlock) []string
- func BlockListToGoCover(blockList [][]CoverBlock, out io.Writer, mode string)
- func BlockListToHTML(blockList [][]CoverBlock, out io.Writer, mode string) error
- func CFGToBlockList(cfg []*BasicBlock) [][]CoverBlock
- func HTMLOutput(profiles []*cover.Profile, out io.Writer) error
- func ProfilesToGoCover(profiles []*cover.Profile, out io.Writer, mode string)
- func SourceCodeInterpolation(coverageBlockList [][]CoverBlock, additionalFilePaths []string) ([][]CoverBlock, error)
- type BasicBlock
- func InstrumentAndLoadCollection(coll *ebpf.CollectionSpec, opts ebpf.CollectionOptions, logWriter io.Writer) (*ebpf.Collection, []*BasicBlock, error)
- func InstrumentCollection(coll *ebpf.CollectionSpec, logWriter io.Writer) ([]*BasicBlock, error)
- func ProgramBlocks(prog asm.Instructions) []*BasicBlock
- type CoverBlock
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ApplyCoverMapToBlockList ¶
func ApplyCoverMapToBlockList(coverMap *ebpf.Map, blockList [][]CoverBlock) error
ApplyCoverMapToBlockList reads from the coverage map and applies the counts inside the map to the block list. The blocklist can be iterated after this to create a go-cover coverage file.
func BlockListFilePaths ¶ added in v0.2.0
func BlockListFilePaths(blockList [][]CoverBlock) []string
BlockListFilePaths returns a sorted and deduplicateed list of file paths included in the block list
func BlockListToGoCover ¶
func BlockListToGoCover(blockList [][]CoverBlock, out io.Writer, mode string)
BlockListToGoCover convert a block-list into a go-cover file which can be interpreted by `go tool cover`. `mode` value can be `set` or `count`, see `go tool cover -h` for details.
func BlockListToHTML ¶
func BlockListToHTML(blockList [][]CoverBlock, out io.Writer, mode string) error
BlockListToHTML converts a block-list into a HTML coverage report.
func CFGToBlockList ¶
func CFGToBlockList(cfg []*BasicBlock) [][]CoverBlock
CFGToBlockList convert a CFG to a "BlockList", the outer slice indexed by BlockID which maps to an inner slice, each element of which is a reference to a specific block of code inside a source file. Thus the resulting block list can be used to translate blockID's into the pieces of source code to apply coverage mapping.
func HTMLOutput ¶
HTMLOutput generates an HTML page from profile data. coverage report is written to the out writer.
func ProfilesToGoCover ¶ added in v0.2.1
ProfilesToGoCover convert a profile list into a go-cover file which can be interpreted by `go tool cover`. `mode` value can be `set` or `count`, see `go tool cover -h` for details.
func SourceCodeInterpolation ¶ added in v0.2.0
func SourceCodeInterpolation(coverageBlockList [][]CoverBlock, additionalFilePaths []string) ([][]CoverBlock, error)
SourceCodeInterpolation parses all files referenced in the coverage block list and the additional file paths as C code. It then uses the parsed code to construct coverage blocks from the source code instead of the compiled object. This results in a more "complete" negative profile since it also will include lines which the compiler tends to optimize out. It then applies the measured coverage to the source blocks. Lastly it will infer / interpolate which lines of code must also have been evaluated given the AST and the coverage blocklist. The intended goal being a more accurate report.
Types ¶
type BasicBlock ¶
type BasicBlock struct { Index int // The current block of code Block asm.Instructions // The next block of we don't branch NoBranch *BasicBlock // The next block if we do branch Branch *BasicBlock }
BasicBlock is a block of non-branching code, which makes up a node within the CFG.
func InstrumentAndLoadCollection ¶
func InstrumentAndLoadCollection( coll *ebpf.CollectionSpec, opts ebpf.CollectionOptions, logWriter io.Writer, ) (*ebpf.Collection, []*BasicBlock, error)
InstrumentAndLoadCollection will instrument the given collection spec and proceed to load it using the provided options. Please refer to `InstrumentCollection` for more information about the instrumentation process.
func InstrumentCollection ¶ added in v0.3.0
func InstrumentCollection(coll *ebpf.CollectionSpec, logWriter io.Writer) ([]*BasicBlock, error)
InstrumentCollection adds instrumentation instructions to all programs contained within the given collection. This "instrumentation" consists of an additional map with a single key and a value which is an array of 16-bit counters. Each index of the array corresponds to the basic block index. The instrumentation code will increment the counter just before the basic block is executed.
The given spec is modified with this instrumentation. The whole process is logged to the `logWriter` and a list of all the basic blocks are returned and can later be matched to the counters in the map.
Steps of the function:
- Load the original programs and collect the verbose verifier log
- Parse the verifier log, which tells us which registers and stack slots are occupied at any given time.
- Convert the program into a CFG(Control Flow Graph)
- At the start of each program and bpf-to-bpf function, load the cover-map's index 0 and store the map value in a available slot on the stack.
- At the start of each block, load an offset into the cover-map value, increment it, write it back. This requires 2 registers which can be clobbered. If only 1 or no registers are unused, store the register values to the stack and restore values afterwards.
- Move symbols of the original code to the instrumented code so jumps and functions calls first pass by the instrumentation.
- Load all modified program into the kernel.
func ProgramBlocks ¶
func ProgramBlocks(prog asm.Instructions) []*BasicBlock
ProgramBlocks takes a list of instructions and converts it into a a CFG(Control Flow Graph). Which works as follows:
- Construct a translation map from RawOffsets to the instructions(since index within the slice doesn't account for LDIMM64 instructions which use two instructions).
- Apply a label to every jump target and set that label as a reference in the branching instruction. This does two things. First, it makes it easy to find all block boundaries since each block has a function name or jump label. The second is that cilium/ebpf will recalculate the offsets of the jumps based on the symbols when loading, so we can easily add instructions to blocks without fear of breaking offsets.
- Loop over all instructions, creating a block at each branching instruction or symbol/jump label.
- Build a translation map from symbol/jump label to block.
- Loop over all blocks, using the map from step 4 to link blocks together on the branching and non-branching edges.
type CoverBlock ¶
type CoverBlock struct { Filename string ProfileBlock cover.ProfileBlock }
CoverBlock wraps the ProfileBlock, adding a filename so each CoverBlock can be turned into a line on a go coverage file.
func CTranslationUnitToBlocks ¶ added in v0.2.0
func CTranslationUnitToBlocks(tu *cparser.TranslationUnit) ([]*CoverBlock, map[cparser.ASTNode][]*CoverBlock)
CTranslationUnitToBlocks turns a TranslationUnit into a list of cover blocks and a map which can be used to see which AST nodes generated which blocks.
func (CoverBlock) String ¶
func (cb CoverBlock) String() string