user2712836
user2712836

Reputation: 76

How to get method's *ssa.Function

hello i am new to static analysis and try to use golang's SSA package to analyze function code. i want to get a function's or a method's *ssa.Function in the package, get a function's *ssa.Function code is down, work success:

func GenBlockGraph(filename string, name string) *ssa.Function {
    // Parse the source files.
    fset := token.NewFileSet()

    // read file content
    src, err := os.ReadFile(filename)
    if err != nil {
        log.LogError.Println("Error reading file:", err)
    }
    f, err := parser.ParseFile(fset, filename, src, parser.ParseComments)
    if err != nil {
        log.LogError.Print(err) // parse error
    }
    files := []*ast.File{f}

    // Create the type-checker's package.
    pkg := types.NewPackage(f.Name.Name, "")

    // Type-check the package, load dependencies.
    // Create and build the SSA program.
    res, _, err := ssautil.BuildPackage(
        &types.Config{Importer: importer.Default()}, fset, pkg, files, ssa.SanityCheckFunctions)
    if err != nil {
        log.LogError.Print(err) // type error in some package
    }
    // Print out the package.
    res.WriteTo(os.Stdout)

    // Print out the package-level functions.
    res.Func(name).WriteTo(os.Stdout)
    return res.Func(name)
}

My question is how to get a method's *ssa.Function? For example get "func (p *China) Speak(slogan string) string"'s *ssa.Function:

package scene

import "fmt"

type Human interface {
    Speak(str string) string
    Language() string
}

type China struct {
    name string
    age  int
}

func (p *China) Speak(slogan string) string {
    return fmt.Sprintf("I am chinese, my name is %s, age is %s. my slogan is %s!", p.name, p.age, slogan)
}

func (p *China) Language() string {
    return "Chinese"
}

type Germany struct {
    name string
    age  int
}

func (p *Germany) Speak(slogan string) string {
    return fmt.Sprintf("I am Germany, my name is %s, age is %s. my slogan is %s!", p.name, p.age, slogan)
}

func (p *Germany) Language() string {
    return "Germany"
}

Upvotes: 0

Views: 66

Answers (1)

user2712836
user2712836

Reputation: 76

func GetSSAFunction(ssaPkg *ssa.Package, structName string, funcName string) *ssa.Function {
    if len(structName) == 0 {
        return ssaPkg.Func(funcName)
    } else {
        t := ssaPkg.Type(structName)
        ti := t.Type()

        named, ok := ti.(*types.Named)
        if !ok {
            return nil
        }

        var key *types.Func
        for i, n := 0, named.NumMethods(); i < n; i++ {
            method := named.Method(i)
            if method.Name() == funcName {
                key = method
                break
            }
        }
        return ssaPkg.Prog.FuncValue(key)
    }
}

this function solve my problem.

Upvotes: 0

Related Questions