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


而 . 函数在 linux.go 中,做的操作主要是定义了几个头文件:
"stdarg.h": `#pragma once#define va_list __builtin_va_list#define va_start __builtin_va_start#define va_end __builtin_va_end#define va_arg __builtin_va_arg#define va_copy __builtin_va_copy#define __va_copy __builtin_va_copy`,"asm/a.out.h":"","asm/prctl.h":"","asm/mce.h":"","uapi/asm/msr.h": "",
因为某些 arch 的src 可能会缺失这些文件,需要自己手动补全 。补全之后 . 会重新执行一次 linuxmake 生成 。
回到函数,该函数最后会把先前获取到的info 返回给调用者:
编译并搜集常量
功能:sys/syz-/.go: () 只是封装了 sys/syz-/linux.go: () 。查找const值(主要在 [3] 处调用 sys/syz-/fetch.go: () 函数) 。
说明:最后生成的 res 映射和集合 。res 是 const 字符串与整型的映射; 是未声明 const 字符串与 bool 值的映射,通常这里的 bool 值都为 true 。
所对应的常量将在 .const 文件中标明其值为 ???,例如
= 2= ???
type Extractor interface {prepare(sourcedir string, build bool, arches []*Arch) errorprepareArch(arch *Arch) errorprocessFile(arch *Arch, info *compiler.ConstInfo) (map[string]uint64, map[string]bool, error)}func processFile(extractor Extractor, arch *Arch, file *File) (map[string]uint64, map[string]bool, error) {inname := filepath.Join("sys", arch.target.OS, file.name)if file.info == nil {return nil, nil, fmt.Errorf("const info for input file %v is missing", inname)}if len(file.info.Consts) == 0 {return nil, nil, nil}return extractor.processFile(arch, file.info)}
//sys/syz-extract/linux.go: processFile()func (*linux) processFile(arch *Arch, info *compiler.ConstInfo) (map[string]uint64, map[string]bool, error) {headerArch := arch.target.KernelHeaderArch // [1] 生成编译代码模板所用到的 gcc 编译参数:argssourceDir := arch.sourceDirbuildDir := arch.buildDirargs := []string{// This makes the build completely hermetic, only kernel headers are used."-nostdinc","-w", "-fmessage-length=0","-O3", // required to get expected values for some __builtin_constant_p"-I.","-D__KERNEL__","-DKBUILD_MODNAME=\"-\"","-I" + sourceDir + "/arch/" + headerArch + "/include","-I" + buildDir + "/arch/" + headerArch + "/include/generated/uapi","-I" + buildDir + "/arch/" + headerArch + "/include/generated","-I" + sourceDir + "/arch/" + headerArch + "/include/asm/mach-malta","-I" + sourceDir + "/arch/" + headerArch + "/include/asm/mach-generic","-I" + buildDir + "/include","-I" + sourceDir + "/include","-I" + sourceDir + "/arch/" + headerArch + "/include/uapi","-I" + buildDir + "/arch/" + headerArch + "/include/generated/uapi","-I" + sourceDir + "/include/uapi","-I" + buildDir + "/include/generated/uapi","-I" + sourceDir,"-I" + sourceDir + "/include/linux","-I" + buildDir + "/syzkaller","-include", sourceDir + "/include/linux/kconfig.h",}args = append(args, arch.target.CFlags...)for _, incdir := range info.Incdirs {args = append(args, "-I"+sourceDir+"/"+incdir)}if arch.includeDirs != "" {for _, dir := range strings.Split(arch.includeDirs, ",") {args = append(args, "-I"+dir)}}params := &extractParams{ // [2] 准备 extract 参数: params, 准备待使用的CC编译器AddSource:"#include ",ExtractFromELF: true,TargetEndian:arch.target.HostEndian,}cc := arch.target.CCompilerres, undeclared, err := extract(info, cc, args, params) // [3] 执行核心函数 extract,生成 res 映射和 undeclared 集合if err != nil {return nil, nil, err}if arch.target.PtrSize == 4 { // [4] 若当前架构是32位, 则 syz-extract 需要使用 mmap2 来替换 mmap,以避免一些可能的错误// mmap syscall on i386/arm is translated to old_mmap and has different signature.// As a workaround fix it up to mmap2, which has signature that we expect.// pkg/csource has the same hack.const mmap = "__NR_mmap"const mmap2 = "__NR_mmap2"if res[mmap] != 0 || undeclared[mmap] {if res[mmap2] == 0 {return nil, nil, fmt.Errorf("%v is missing", mmap2)}res[mmap] = res[mmap2]delete(undeclared, mmap)}}return res, undeclared, nil // [5] 返回结果}