// Copyright 2021, Chef. All rights reserved. // https://github.com/q191201771/naza // // Use of this source code is governed by a MIT-style license // that can be found in the License file. // // Author: Chef (191201771@qq.com) package main import ( "fmt" "io/ioutil" "strconv" "strings" "github.com/q191201771/naza/pkg/nazalog" ) // 分析c++程序pstack的两次结果的差异 type PstackInfo struct { tis []ThreadInfo tim map[string]ThreadInfo } type ThreadInfo struct { Num int P string Id int RawLine string RawStackLines string } func NewPstackInfo(filename string) PstackInfo { var tis []ThreadInfo contents, err := ioutil.ReadFile(filename) nazalog.Assert(nil, err) content := string(contents) lines := strings.Split(content, "\n") //nazalog.Debugf("len(lines)=%d", len(lines)) var ti *ThreadInfo for _, line := range lines { if strings.HasPrefix(line, "Thread") { if ti != nil { tis = append(tis, *ti) } ti = &ThreadInfo{} //nazalog.Debugf("%s", line) ti.RawLine = line ti.Num, ti.P, ti.Id, err = parseThreadLine(line) nazalog.Assert(nil, err) continue } ti.RawStackLines += line + "\n" } if ti != nil { tis = append(tis, *ti) } nazalog.Debugf("len(tis)=%d", len(tis)) tim := make(map[string]ThreadInfo) for _, ti := range tis { tim[ti.Uk()] = ti } return PstackInfo{ tis: tis, tim: tim, } } func (pi *PstackInfo) Find(uk string) (ThreadInfo, bool) { ti, exist := pi.tim[uk] return ti, exist } func (ti *ThreadInfo) Uk() string { return fmt.Sprintf("%s_%d", ti.P, ti.Id) } func parseThreadLine(line string) (num int, p string, id int, err error) { p1 := strings.Index(line, "Thread") p2 := strings.Index(line, "(Thread") num, err = strconv.Atoi(line[p1+7 : p2-1]) if err != nil { return } p3 := strings.Index(line, "(LWP") p = line[p2+8 : p3-1] p4 := strings.Index(line, "))") id, err = strconv.Atoi(line[p3+5 : p4-1]) return } func main() { _ = nazalog.Init(func(option *nazalog.Option) { option.LevelFlag = false option.ShortFileFlag = false option.TimestampFlag = false }) pi1 := NewPstackInfo("old.txt") pi2 := NewPstackInfo("new.txt") for _, ti2 := range pi2.tis { var pre, suf string suf = "\033[0m" ti1, exist := pi1.Find(ti2.Uk()) if exist { if ti2.RawStackLines == ti1.RawStackLines { // 1, 2都有,但是堆栈没变 没色 pre = "" suf = "" nazalog.Debugf("%s-------------------------------------------------------------------------%s", pre, suf) nazalog.Debugf("%s%s%s", pre, ti2.RawLine, suf) nazalog.Debugf("%s%s%s", pre, ti2.RawStackLines, suf) } else { // 1, 2都有,但是堆栈变化 红色 // 注意,断站有变化也可能是函数参数变化了 pre = "\033[22;31m" nazalog.Debugf("%s-------------------------------------------------------------------------%s", pre, suf) nazalog.Debugf("%s%s%s", pre, ti2.RawLine, suf) nazalog.Debugf("%s%s%s", pre, ti2.RawStackLines, suf) } } else { // 只在2有 绿色 pre = "\033[22;36m" nazalog.Debugf("%s-------------------------------------------------------------------------%s", pre, suf) nazalog.Debugf("%s%s%s", pre, ti2.RawLine, suf) nazalog.Debugf("%s%s%s", pre, ti2.RawStackLines, suf) } } }