Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b2cf722
pkg/symbolizer: generate x86_64 version
tarasmadan Jan 27, 2026
cf291b3
syzkaller: fix verification scripts lint errors
tarasmadan Jan 27, 2026
70091d0
syzkaller: fix compilation error in pkg/cover/backend
tarasmadan Jan 27, 2026
4e820f2
syzkaller: fix linter errors
tarasmadan Jan 27, 2026
f875dc2
syzkaller: fix final lint errors
tarasmadan Jan 27, 2026
29d356f
syzkaller: fix lint errors (round 2)
tarasmadan Jan 27, 2026
8dcbda3
syzkaller: fix final final lint errors
tarasmadan Jan 27, 2026
c772613
syzkaller: fix verification comments style
tarasmadan Jan 27, 2026
b5191c4
syzkaller: fix verification comments style (final)
tarasmadan Jan 27, 2026
112de25
syzkaller: fix lint comments (deletion)
tarasmadan Jan 27, 2026
2b510f1
syzkaller: fix verification comments (remove fragments)
tarasmadan Jan 27, 2026
832e870
syzkaller: fix lint comment at line 165
tarasmadan Jan 27, 2026
a3e8897
syzkaller: fix panic in symbolizer.Make with nil target
tarasmadan Jan 27, 2026
bf20e6e
syzkaller: fallback to addr2line if elf symbolizer fails
tarasmadan Jan 27, 2026
b02b0e0
pkg/symbolizer: it works and passes all the tests
tarasmadan Jan 28, 2026
b84e759
pkg/symbolizer: it claims to be fast and stable
tarasmadan Jan 29, 2026
0010d7f
pkg/symbolizer: add symbolization logs
tarasmadan Jan 29, 2026
91ed048
pkg/symbolizer: propagate kernel path and fix PC forwarding issue
tarasmadan Jan 29, 2026
7b77f05
pkg/symbolizer: fix performance issues
tarasmadan Jan 29, 2026
0db00df
pkg/symbolizer: enable by flag and log report build time
tarasmadan Jan 29, 2026
877aec0
pkg/symbolizer: fix linter problems
tarasmadan Jan 29, 2026
391b9fd
pkg/symbolizer: some bench files
tarasmadan Jan 29, 2026
9ea3bdb
tools/syz-sym-check: test scalability
tarasmadan Jan 29, 2026
ae0a6a4
tools/syz-sym-check: enable symbolize=source
tarasmadan Feb 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pkg/cover/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ type Impl struct {
Units []*CompileUnit
Symbols []*Symbol
Frames []*Frame
Symbolize func(pcs map[*vminfo.KernelModule][]uint64) ([]*Frame, error)
Symbolize func(pcs map[*vminfo.KernelModule][]uint64, symbolizer string) ([]*Frame, error)
CallbackPoints []uint64
PreciseCoverage bool
SymbolizerName string
}

type CompileUnit struct {
Expand Down
53 changes: 46 additions & 7 deletions pkg/cover/backend/dwarf.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"sort"
"strconv"
"strings"
"sync"

"github.com/google/syzkaller/pkg/log"
"github.com/google/syzkaller/pkg/mgrconfig"
Expand Down Expand Up @@ -249,14 +250,26 @@ func makeDWARFUnsafe(params *dwarfParams) (*Impl, error) {
return nil, fmt.Errorf("failed to parse DWARF (set CONFIG_DEBUG_INFO=y on linux)")
}
var interner symbolizer.Interner
var lcCache sync.Map
bin := filepath.Join(kernelDirs.Obj, target.KernelObject)
symb, _ := symbolizer.Make(target, bin)
symbName := "unknown"
if symb != nil {
symbName = symb.Name()
symb.Close()
}
impl := &Impl{
Units: allUnits,
Symbols: allSymbols,
Symbolize: func(pcs map[*vminfo.KernelModule][]uint64) ([]*Frame, error) {
return symbolize(target, &interner, kernelDirs, splitBuildDelimiters, pcs)
Symbolize: func(pcs map[*vminfo.KernelModule][]uint64, symbolizer string) ([]*Frame, error) {
if symbolizer == "source" {
return symbolizeSource(target, &interner, kernelDirs, splitBuildDelimiters, pcs, &lcCache)
}
return symbolize(target, &interner, kernelDirs, splitBuildDelimiters, pcs, symbolizer)
},
CallbackPoints: allCoverPoints[0],
PreciseCoverage: preciseCoverage,
SymbolizerName: symbName,
}
return impl, nil
}
Expand Down Expand Up @@ -496,7 +509,7 @@ func rustRanges(debugInfo *dwarf.Data, ent *dwarf.Entry) ([]rustRange, error) {
}

func symbolizeModule(target *targets.Target, interner *symbolizer.Interner, kernelDirs *mgrconfig.KernelDirs,
splitBuildDelimiters []string, mod *vminfo.KernelModule, pcs []uint64) ([]*Frame, error) {
splitBuildDelimiters []string, mod *vminfo.KernelModule, pcs []uint64, symbolizerType string) ([]*Frame, error) {
procs := min(runtime.GOMAXPROCS(0)/2, len(pcs)/1000)
const (
minProcs = 1
Expand All @@ -511,10 +524,36 @@ func symbolizeModule(target *targets.Target, interner *symbolizer.Interner, kern
}
symbolizerC := make(chan symbolizerResult, procs)
pcchan := make(chan []uint64, procs)

bin := mod.Path
if symbolizerType == "addr2line" {
bin = "" // Forces fallback to addr2line in symbolizer.Make.
}

var sharedSymb symbolizer.Symbolizer
if s, err := symbolizer.Make(target, bin); err == nil {
if s.Name() == "native" {
sharedSymb = s
defer s.Close()
} else {
s.Close()
}
}

for p := 0; p < procs; p++ {
go func() {
symb := symbolizer.Make(target)
defer symb.Close()
var symb symbolizer.Symbolizer
var err error
if sharedSymb != nil {
symb = sharedSymb
} else {
symb, err = symbolizer.Make(target, bin)
if err != nil {
symbolizerC <- symbolizerResult{err: fmt.Errorf("failed to create symbolizer: %w", err)}
return
}
defer symb.Close()
}
var res symbolizerResult
for pcs := range pcchan {
for i, pc := range pcs {
Expand Down Expand Up @@ -575,7 +614,7 @@ func symbolizeModule(target *targets.Target, interner *symbolizer.Interner, kern
}

func symbolize(target *targets.Target, interner *symbolizer.Interner, kernelDirs *mgrconfig.KernelDirs,
splitBuildDelimiters []string, pcs map[*vminfo.KernelModule][]uint64) ([]*Frame, error) {
splitBuildDelimiters []string, pcs map[*vminfo.KernelModule][]uint64, symbolizerType string) ([]*Frame, error) {
var frames []*Frame
type frameResult struct {
frames []*Frame
Expand All @@ -584,7 +623,7 @@ func symbolize(target *targets.Target, interner *symbolizer.Interner, kernelDirs
frameC := make(chan frameResult, len(pcs))
for mod, pcs1 := range pcs {
go func(mod *vminfo.KernelModule, pcs []uint64) {
frames, err := symbolizeModule(target, interner, kernelDirs, splitBuildDelimiters, mod, pcs)
frames, err := symbolizeModule(target, interner, kernelDirs, splitBuildDelimiters, mod, pcs, symbolizerType)
frameC <- frameResult{frames: frames, err: err}
}(mod, pcs1)
}
Expand Down
33 changes: 17 additions & 16 deletions pkg/cover/html.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@ import (
)

type HandlerParams struct {
Progs []Prog
Filter map[uint64]struct{}
Debug bool
Force bool
Progs []Prog
Filter map[uint64]struct{}
Debug bool
Force bool
Symbolizer string
}

func (rg *ReportGenerator) DoHTML(w io.Writer, params HandlerParams) error {
var progs = fixUpPCs(params.Progs, params.Filter)
files, err := rg.prepareFileMap(progs, params.Force, params.Debug)
files, err := rg.prepareFileMap(progs, params.Force, params.Debug, params.Symbolizer)
if err != nil {
return err
}
Expand Down Expand Up @@ -129,7 +130,7 @@ type lineCoverExport struct {

func (rg *ReportGenerator) DoLineJSON(w io.Writer, params HandlerParams) error {
var progs = fixUpPCs(params.Progs, params.Filter)
files, err := rg.prepareFileMap(progs, params.Force, params.Debug)
files, err := rg.prepareFileMap(progs, params.Force, params.Debug, params.Symbolizer)
if err != nil {
return err
}
Expand Down Expand Up @@ -178,7 +179,7 @@ func fileLineContents(file *file, lines [][]byte) lineCoverExport {

func (rg *ReportGenerator) DoRawCoverFiles(w io.Writer, params HandlerParams) error {
progs := fixUpPCs(params.Progs, params.Filter)
if err := rg.symbolizePCs(uniquePCs(progs...)); err != nil {
if err := rg.symbolizePCs(uniquePCs(progs...), params.Symbolizer); err != nil {
return err
}

Expand Down Expand Up @@ -218,12 +219,12 @@ type CoverageInfo struct {
// DoCoverJSONL is a handler for "/cover?jsonl=1".
func (rg *ReportGenerator) DoCoverJSONL(w io.Writer, params HandlerParams) error {
if rg.CallbackPoints != nil {
if err := rg.symbolizePCs(rg.CallbackPoints); err != nil {
if err := rg.symbolizePCs(rg.CallbackPoints, params.Symbolizer); err != nil {
return fmt.Errorf("failed to symbolize PCs(): %w", err)
}
}
progs := fixUpPCs(params.Progs, params.Filter)
if err := rg.symbolizePCs(uniquePCs(progs...)); err != nil {
if err := rg.symbolizePCs(uniquePCs(progs...), params.Symbolizer); err != nil {
return err
}
pcProgCount := make(map[uint64]int)
Expand Down Expand Up @@ -288,7 +289,7 @@ type Block struct {
// Each line is a single ProgramCoverage record.
func (rg *ReportGenerator) DoCoverPrograms(w io.Writer, params HandlerParams) error {
if rg.CallbackPoints != nil {
if err := rg.symbolizePCs(rg.CallbackPoints); err != nil {
if err := rg.symbolizePCs(rg.CallbackPoints, params.Symbolizer); err != nil {
return fmt.Errorf("failed to symbolize PCs(): %w", err)
}
}
Expand Down Expand Up @@ -432,8 +433,8 @@ var csvFilesHeader = []string{
"TotalPCsInCoveredFunctions",
}

func (rg *ReportGenerator) convertToStats(progs []Prog) ([]fileStats, error) {
files, err := rg.prepareFileMap(progs, false, false)
func (rg *ReportGenerator) convertToStats(progs []Prog, symbolizer string) ([]fileStats, error) {
files, err := rg.prepareFileMap(progs, false, false, symbolizer)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -485,7 +486,7 @@ func (rg *ReportGenerator) convertToStats(progs []Prog) ([]fileStats, error) {

func (rg *ReportGenerator) DoFileCover(w io.Writer, params HandlerParams) error {
var progs = fixUpPCs(params.Progs, params.Filter)
data, err := rg.convertToStats(progs)
data, err := rg.convertToStats(progs, params.Symbolizer)
if err != nil {
return err
}
Expand Down Expand Up @@ -608,7 +609,7 @@ func isExcluded(path string, excludes []string) bool {

func (rg *ReportGenerator) DoSubsystemCover(w io.Writer, params HandlerParams) error {
var progs = fixUpPCs(params.Progs, params.Filter)
data, err := rg.convertToStats(progs)
data, err := rg.convertToStats(progs, params.Symbolizer)
if err != nil {
return err
}
Expand Down Expand Up @@ -684,7 +685,7 @@ func groupCoverByModule(datas []fileStats) map[string]map[string]string {

func (rg *ReportGenerator) DoModuleCover(w io.Writer, params HandlerParams) error {
var progs = fixUpPCs(params.Progs, params.Filter)
data, err := rg.convertToStats(progs)
data, err := rg.convertToStats(progs, params.Symbolizer)
if err != nil {
return err
}
Expand All @@ -704,7 +705,7 @@ var csvHeader = []string{

func (rg *ReportGenerator) DoFuncCover(w io.Writer, params HandlerParams) error {
var progs = fixUpPCs(params.Progs, params.Filter)
files, err := rg.prepareFileMap(progs, params.Force, params.Debug)
files, err := rg.prepareFileMap(progs, params.Force, params.Debug, params.Symbolizer)
if err != nil {
return err
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/cover/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ type line struct {

type fileMap map[string]*file

func (rg *ReportGenerator) prepareFileMap(progs []Prog, force, debug bool) (fileMap, error) {
if err := rg.symbolizePCs(uniquePCs(progs...)); err != nil {
func (rg *ReportGenerator) prepareFileMap(progs []Prog, force, debug bool, symbolizer string) (fileMap, error) {
if err := rg.symbolizePCs(uniquePCs(progs...), symbolizer); err != nil {
return nil, err
}
files := make(fileMap)
Expand Down Expand Up @@ -206,7 +206,7 @@ func uniquePCs(progs ...Prog) []uint64 {
return maps.Keys(PCs)
}

func (rg *ReportGenerator) symbolizePCs(PCs []uint64) error {
func (rg *ReportGenerator) symbolizePCs(PCs []uint64, symbolizer string) error {
if len(PCs) == 0 {
return fmt.Errorf("no coverage collected so far to symbolize")
}
Expand All @@ -223,7 +223,7 @@ func (rg *ReportGenerator) symbolizePCs(PCs []uint64) error {
symbolize[sym] = true
pcs[sym.Module] = append(pcs[sym.Module], sym.PCs...)
}
frames, err := rg.Symbolize(pcs)
frames, err := rg.Symbolize(pcs, symbolizer)
if err != nil {
return err
}
Expand Down
7 changes: 5 additions & 2 deletions pkg/ifaceprobe/ifaceprobe.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ type fileDesc struct {
}

func (pr *prober) run() (*Info, error) {
symb := symbolizer.Make(pr.cfg.SysTarget)
kernelObj := filepath.Join(pr.cfg.KernelObj, pr.cfg.SysTarget.KernelObject)
symb, err := symbolizer.Make(pr.cfg.SysTarget, kernelObj)
if err != nil {
return nil, err
}
defer symb.Close()

for _, glob := range globList() {
Expand All @@ -82,7 +86,6 @@ func (pr *prober) run() (*Info, error) {

info := &Info{}
pcIndexes := make(map[uint64]int)
kernelObj := filepath.Join(pr.cfg.KernelObj, pr.cfg.SysTarget.KernelObject)
sourceBase := filepath.Clean(pr.cfg.KernelSrc) + string(filepath.Separator)
i := 0
for desc := range pr.done {
Expand Down
15 changes: 11 additions & 4 deletions pkg/manager/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ func (serv *HTTPServer) httpCoverCover(w http.ResponseWriter, r *http.Request, f
http.Error(w, "coverage is not ready, please try again later after fuzzer started", http.StatusInternalServerError)
return
}
start := time.Now()

corpus := serv.Corpus.Load()
if corpus == nil {
Expand Down Expand Up @@ -588,10 +589,11 @@ func (serv *HTTPServer) httpCoverCover(w http.ResponseWriter, r *http.Request, f
}

params := cover.HandlerParams{
Progs: serv.serializeCoverProgs(progs),
Filter: coverFilter,
Debug: r.FormValue("debug") != "",
Force: r.FormValue("force") != "",
Progs: serv.serializeCoverProgs(progs),
Filter: coverFilter,
Debug: r.FormValue("debug") != "",
Force: r.FormValue("force") != "",
Symbolizer: r.FormValue("symbolizer"),
}

type handlerFuncType func(w io.Writer, params cover.HandlerParams) error
Expand Down Expand Up @@ -619,6 +621,11 @@ func (serv *HTTPServer) httpCoverCover(w http.ResponseWriter, r *http.Request, f
http.Error(w, fmt.Sprintf("failed to generate coverage profile: %v", err), http.StatusInternalServerError)
return
}
symbName := rg.SymbolizerName
if params.Symbolizer != "" {
symbName = params.Symbolizer
}
log.Logf(0, "generated coverage report: symbolizer=%v duration=%v", symbName, time.Since(start))
}

type coverProgRaw struct {
Expand Down
5 changes: 4 additions & 1 deletion pkg/report/bsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ func (ctx *bsd) Parse(output []byte) *Report {
}

func (ctx *bsd) Symbolize(rep *Report) error {
symb := symbolizer.Make(ctx.config.target)
symb, err := symbolizer.Make(ctx.config.target, ctx.kernelObject)
if err != nil {
return err
}
defer symb.Close()
var symbolized []byte
prefix := rep.reportPrefixLen
Expand Down
5 changes: 4 additions & 1 deletion pkg/report/fuchsia.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,10 @@ func (ctx *fuchsia) shortenReport(report []byte) []byte {
func (ctx *fuchsia) symbolize(output []byte) ([]byte, map[int]int) {
l2l := map[int]int{}
var inPos int
symb := symbolizer.Make(ctx.config.target)
symb, err := symbolizer.Make(ctx.config.target, ctx.obj)
if err != nil {
return output, nil // Fallback to raw output if symbolizer fails.
}
defer symb.Close()
out := new(bytes.Buffer)

Expand Down
5 changes: 4 additions & 1 deletion pkg/report/linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,10 @@ func (ctx *linux) extractContext(line []byte) string {
func (ctx *linux) Symbolize(rep *Report) error {
var symbFunc symbFuncCb
if ctx.vmlinux != "" {
symb := symbolizer.Make(ctx.config.target)
symb, err := symbolizer.Make(ctx.config.target, ctx.vmlinux)
if err != nil {
return err
}
defer symb.Close()
symbFunc = func(bin string, pc uint64) ([]symbolizer.Frame, error) {
return ctx.symbolizerCache.Symbolize(symb.Symbolize, bin, pc)
Expand Down
Loading
Loading