二 Syzkaller学习笔记---更新syz-manager( 五 )


例如,你可以调用该函数如下:
os := "Linux"archArray := []string{"x86", "x64"}files := []string{"file1.txt", "file2.txt"}arches, count, err := createArches(os, archArray, files)if err != nil {fmt.Println(err)} else {fmt.Println("Arches:", arches)fmt.Println("Count:", count)}
功能:执行真正的变量解析工作 。分别对Arch和File 调用 () 函数和 () 函数处理 。
参数: 传给 () 的 jobC 参数就是 Arch 结构体数组 。所以在 () 函数中会进入 case *Arch 分支 。
func worker(extractor Extractor, jobC chan interface{}) {for job := range jobC {switch j := job.(type) { // [1] j 赋值为 jobC 管道中的对象,初始时为 Arch 结构体case *Arch:infos, err := processArch(extractor, j) // [2] 执行 processArch(), 生成 const 信息j.err = errclose(j.done)if j.err == nil {for _, f := range j.files {f.info = infos[filepath.Join("sys", j.target.OS, f.name)]jobC <- f // [3] processArch() 执行完后,从 infos 映射中遍历取出对应文件的信息,并将其填充至 arch 结构体中 files 结构体数组内的各个元素字段里; 将这个 File 结构体放入 jobC 管道中} //"jobC <- f" 表示将一个 "f" 变量写入 "jobC" 通道 。}case *File:j.consts, j.undeclared, j.err = processFile(extractor, j.arch, j)close(j.done)}}}
? 该函数在一个 for 循环中不断读取 “jobC” 通道中的任务,并对其进行处理 。每个任务是一个接口类型,该程序通过一个语句判断每个任务的具体类型 。
? 如果任务的类型为 *Arch,则使用 “” 函数处理该任务,并关闭 “j.done” 通道,如果 “j.err” 等于 nil,则对每个 “j.files” 中的文件再次进行处理并写入 “jobC” 通道 。
? 如果任务的类型为 *File,则使用 “” 函数处理该任务,并将处理结果写入 “j.”,“j.” 和 “j.err” 字段,然后关闭 “j.done” 通道 。
这个代码是一个并行处理任务的示例,通过不断读取通道中的任务并处理,实现了并行的效果 。
流程说明:由于 () 会循环读取 jobC 内数据,因此接下来便会取出刚刚新放入的 File 结构体,执行 () 函数 。在 () 中,syz- 将会获取各个 const 变量(例如 )所对应的整型值(例如2) 。
注意:() 中需注意,当 () 执行完成后, 函数接下来都会执行 close(j.done) ,将通信管道关闭 。这样做的是为了通知 main() 函数“某部分工作已经完成” 。这个操作有点类似于使用信号量来保证线程同步 。
功能: 的作用是,处理传入的和 Arch 结构体,生成 const 信息 。
func processArch(extractor Extractor, arch *Arch) (map[string]*compiler.ConstInfo, error) {errBuf := new(bytes.Buffer)// 定义 error handler 函数eh := func(pos ast.Pos, msg string) {fmt.Fprintf(errBuf, "%v: %v\n", pos, msg)}// 解析 sys/linux/*.txt 的 syzlang 文件,形成一个 AST 数组// 因此 top 变量就是 ast 森林的根节点top := ast.ParseGlob(filepath.Join("sys", arch.target.OS, "*.txt"), eh)if top == nil {return nil, fmt.Errorf("%v", errBuf.String())}// 调用 compiler.ExtractConsts 获取每个 syzlang 文件中所对应的 const 信息infos := compiler.ExtractConsts(top, arch.target, eh)if infos == nil {return nil, fmt.Errorf("%v", errBuf.String())}// 让 Extractor 为 arch 做些准备if err := extractor.prepareArch(arch); err != nil {return nil, err}return infos, nil //将获取到的consts infos 返回给调用者}
调用了库函数 pkg\\const..() ,主要调用pkg\\.go () 提取出常量标识符 。返回编译结果中的 res. 字段.
其中,. 只是一个简单的函数,获取编译结果中的字段:
func ExtractConsts(desc *ast.Description, target *targets.Target, eh ast.ErrorHandler) map[string]*ConstInfo {res := Compile(desc, nil, target, eh)if res == nil {return nil}return res.fileConsts}
? 字段 res. 包含了文件名与其用到的常量数组的映射,以及其所的头文件数组的映射;这些东西都将会用到获取对应的具体整数操作中 。