GoPLS Viewer

Home|gopls/cmd/toolstash/cmp.go
1// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package main
6
7import (
8    "bufio"
9    "bytes"
10    "fmt"
11    "io"
12    "log"
13    "os"
14    "regexp"
15    "strconv"
16    "strings"
17)
18
19var (
20    hexDumpRE = regexp.MustCompile(`^\t(0x[0-9a-f]{4,})(( ([0-9a-f]{2}|  )){16})  [ -\x7F]{1,16}\n`)
21    listingRE = regexp.MustCompile(`^\t(0x[0-9a-f]{4,}) ([0-9]{4,}) \(.*:[0-9]+\)\t`)
22)
23
24// okdiffs lists regular expressions for lines to consider minor mismatches.
25// If one of these regexps matches both of a pair of unequal lines, the mismatch
26// is reported but not treated as the one worth looking for.
27// For example, differences in the TEXT line are typically frame size
28// changes due to optimization decisions made in the body of the function.
29// Better to keep looking for the actual difference.
30// Similarly, forward jumps might have different offsets due to a
31// change in instruction encoding later on.
32// Better to find that change.
33var okdiffs = []*regexp.Regexp{
34    regexp.MustCompile(`\)    TEXT[     ].*,\$`),
35    regexp.MustCompile(`\)    WORD[     ].*,\$`),
36    regexp.MustCompile(`\)    (B|BR|JMP)    `),
37    regexp.MustCompile(`\)    FUNCDATA    `),
38    regexp.MustCompile(`\\(z|x00)`),
39    regexp.MustCompile(`\$\([0-9]\.[0-9]+e[+\-][0-9]+\)`),
40    regexp.MustCompile(`size=.*value=.*args=.*locals=`),
41}
42
43func compareLogs(outfile stringstring {
44    f1err := os.Open(outfile + ".log")
45    if err != nil {
46        log.Fatal(err)
47    }
48    defer f1.Close()
49
50    f2err := os.Open(outfile + ".stash.log")
51    if err != nil {
52        log.Fatal(err)
53    }
54    defer f2.Close()
55
56    b1 := bufio.NewReader(f1)
57    b2 := bufio.NewReader(f2)
58
59    offset := int64(0)
60    textOffset := offset
61    textLineno := 0
62    lineno := 0
63    var line1line2 string
64    var prefix bytes.Buffer
65Reading:
66    for {
67        var err1err2 error
68        line1err1 = b1.ReadString('\n')
69        line2err2 = b2.ReadString('\n')
70        if strings.Contains(line1")\tTEXT\t") {
71            textOffset = offset
72            textLineno = lineno
73        }
74        offset += int64(len(line1))
75        lineno++
76        if err1 == io.EOF && err2 == io.EOF {
77            return "no differences in debugging output"
78        }
79
80        if lineno == 1 || line1 == line2 && err1 == nil && err2 == nil {
81            continue
82        }
83        // Lines are inconsistent. Worth stopping?
84        for _re := range okdiffs {
85            if re.MatchString(line1) && re.MatchString(line2) {
86                fmt.Fprintf(&prefix"inconsistent log line:\n%s:%d:\n\t%s\n%s:%d:\n\t%s\n\n",
87                    f1.Name(), linenostrings.TrimSuffix(line1"\n"),
88                    f2.Name(), linenostrings.TrimSuffix(line2"\n"))
89                continue Reading
90            }
91        }
92
93        if err1 != nil {
94            line1 = err1.Error()
95        }
96        if err2 != nil {
97            line2 = err2.Error()
98        }
99        break
100    }
101
102    msg := fmt.Sprintf("inconsistent log line:\n%s:%d:\n\t%s\n%s:%d:\n\t%s",
103        f1.Name(), linenostrings.TrimSuffix(line1"\n"),
104        f2.Name(), linenostrings.TrimSuffix(line2"\n"))
105
106    if m := hexDumpRE.FindStringSubmatch(line1); m != nil {
107        targeterr := strconv.ParseUint(m[1], 064)
108        if err != nil {
109            goto Skip
110        }
111
112        m2 := hexDumpRE.FindStringSubmatch(line2)
113        if m2 == nil {
114            goto Skip
115        }
116
117        fields1 := strings.Fields(m[2])
118        fields2 := strings.Fields(m2[2])
119        i := 0
120        for i < len(fields1) && i < len(fields2) && fields1[i] == fields2[i] {
121            i++
122        }
123        target += uint64(i)
124
125        f1.Seek(textOffset0)
126        b1 = bufio.NewReader(f1)
127        last := ""
128        lineno := textLineno
129        limitAddr := uint64(0)
130        lastAddr := uint64(0)
131        for {
132            line1err1 := b1.ReadString('\n')
133            if err1 != nil {
134                break
135            }
136            lineno++
137            if m := listingRE.FindStringSubmatch(line1); m != nil {
138                addr_ := strconv.ParseUint(m[1], 064)
139                if addr > target {
140                    limitAddr = addr
141                    break
142                }
143                last = line1
144                lastAddr = addr
145            } else if hexDumpRE.FindStringSubmatch(line1) != nil {
146                break
147            }
148        }
149        if last != "" {
150            msg = fmt.Sprintf("assembly instruction at %#04x-%#04x:\n%s:%d\n\t%s\n\n%s",
151                lastAddrlimitAddrf1.Name(), lineno-1strings.TrimSuffix(last"\n"), msg)
152        }
153    }
154Skip:
155
156    return prefix.String() + msg
157}
158
MembersX
log
compareLogs.BlockStmt.err
compareLogs.BlockStmt.BlockStmt.line1
compareLogs.BlockStmt.BlockStmt.BlockStmt._
compareLogs.textLineno
compareLogs.line1
compareLogs.msg
compareLogs.BlockStmt.target
compareLogs.BlockStmt.last
compareLogs.BlockStmt.BlockStmt.BlockStmt.addr
os
compareLogs.f1
compareLogs.b1
compareLogs.offset
compareLogs.BlockStmt.lastAddr
compareLogs.BlockStmt.BlockStmt.m
bufio
compareLogs.lineno
compareLogs.m
compareLogs.BlockStmt.i
bytes
compareLogs.line2
compareLogs.BlockStmt.m2
compareLogs.BlockStmt.lineno
compareLogs.b2
compareLogs.prefix
compareLogs.BlockStmt.err1
fmt
io
compareLogs
compareLogs.err
compareLogs.BlockStmt.fields2
compareLogs.BlockStmt.limitAddr
compareLogs.BlockStmt.BlockStmt.err1
strconv
compareLogs.outfile
compareLogs.f2
compareLogs.textOffset
compareLogs.BlockStmt.fields1
regexp
strings
compareLogs.BlockStmt.err2
compareLogs.BlockStmt.RangeStmt_2229.re
Members
X