func()

in tool/instrument/inst_func.go [341:428]


func (rp *RuleProcessor) applyFuncRules(bundle *resource.RuleBundle) (err error) {
	// Nothing to do if no func rules
	if len(bundle.File2FuncRules) == 0 {
		return nil
	}
	// Copy API file to compilation working directory
	err = rp.copyOtelApi(bundle.PackageName)
	if err != nil {
		return err
	}
	// Applied all matched func rules, either inserting raw code or inserting
	// our trampoline calls.
	for file, fn2rules := range bundle.File2FuncRules {
		util.Assert(filepath.IsAbs(file), "file path must be absolute")
		astRoot, err := rp.loadAst(file)
		if err != nil {
			return err
		}
		rp.trampolineJumps = make([]*TJump, 0)
		// Since we may genarate many functions into the same file, while we dont
		// want to further instrument these functions, we need to make sure that
		// the generated function are exclued from the instrumented file.
		oldDecls := make([]dst.Decl, len(astRoot.Decls))
		copy(oldDecls, astRoot.Decls)
		for fnName, rules := range fn2rules {
			for _, decl := range oldDecls {
				nameAndRecvType := strings.Split(fnName, ",")
				name := nameAndRecvType[0]
				recvType := nameAndRecvType[1]
				if util.MatchFuncDecl(decl, name, recvType) {
					fnDecl := decl.(*dst.FuncDecl)
					util.Assert(fnDecl.Body != nil, "target func boby is empty")
					fnName := fnDecl.Name.Name
					// Save raw function declaration
					rp.rawFunc = fnDecl
					// The func rule can either fully match the target function
					// or use a regexp to match a batch of functions. The
					// generation of tjump differs slightly between these two
					// cases. In the former case, the hook function is required
					// to have the same signature as the target function, while
					// the latter does not have this requirement.
					rp.exact = fnName == name
					// Add explicit names for return values, they can be further
					// referenced if we're willing
					nameReturnValues(fnDecl)

					// Apply all matched rules for this function
					fnRules := sortFuncRules(rules)
					for _, rule := range fnRules {
						if rule.UseRaw {
							err = rp.insertRaw(rule, fnDecl)
						} else {
							err = rp.insertTJump(rule, fnDecl)
						}
						if err != nil {
							return err
						}
						util.Log("Apply func rule %s (%v)", rule, rp.compileArgs)
					}
					// break
				}
			}
		}
		// Optimize generated trampoline-jump-ifs
		err = rp.optimizeTJumps()
		if err != nil {
			return err
		}
		// Restore the ast to original file once all rules are applied
		newFile, err := rp.restoreAst(file, astRoot)
		if err != nil {
			return err
		}
		// Line directive must be placed at the beginning of the line, otherwise
		// it will be ignored by the compiler
		err = rp.enableLineDirective(newFile)
		if err != nil {
			return err
		}
		rp.saveDebugFile(newFile)
	}

	err = rp.writeTrampoline(bundle.PackageName)
	if err != nil {
		return err
	}
	return nil
}