| Index: fuzzer/go/frontend/data/stacktrace.go
|
| diff --git a/fuzzer/go/frontend/data/stacktrace.go b/fuzzer/go/frontend/data/stacktrace.go
|
| deleted file mode 100644
|
| index e39e6cd4ab7936f7a6f655905fcb91be094d4431..0000000000000000000000000000000000000000
|
| --- a/fuzzer/go/frontend/data/stacktrace.go
|
| +++ /dev/null
|
| @@ -1,193 +0,0 @@
|
| -package data
|
| -
|
| -import (
|
| - "bufio"
|
| - "bytes"
|
| - "fmt"
|
| - "regexp"
|
| - "strconv"
|
| - "strings"
|
| -
|
| - "github.com/skia-dev/glog"
|
| - "go.skia.org/infra/fuzzer/go/common"
|
| -)
|
| -
|
| -type StackTrace struct {
|
| - Frames []StackTraceFrame `json:"frames"`
|
| -}
|
| -
|
| -type StackTraceFrame struct {
|
| - PackageName string `json:"packageName"`
|
| - FileName string `json:"fileName"`
|
| - LineNumber int `json:"lineNumber"`
|
| - FunctionName string `json:"functionName"`
|
| -}
|
| -
|
| -// The `?:` at the beginning of the groups prevent them from being captured
|
| -// \1 is the "package", \2 is the file name, \3 is the line number, \4 is the function symbol string
|
| -var segvStackTraceLine = regexp.MustCompile(`(?:\.\./)+(?P<package>(?:\w+/)+)(?P<file>.+):(?P<line>\d+).*\(_(?P<symbol>.*)\)`)
|
| -
|
| -// parseCatchsegvStackTrace takes the contents of a dump file of a catchsegv run, and returns the
|
| -// parsed stacktrace
|
| -func parseCatchsegvStackTrace(contents string) StackTrace {
|
| - r := bytes.NewBufferString(contents)
|
| - scan := bufio.NewScanner(r)
|
| -
|
| - hasBegun := false
|
| -
|
| - frames := make([]StackTraceFrame, 0, 5)
|
| -
|
| - for scan.Scan() {
|
| - line := scan.Text()
|
| - if strings.Contains(line, "Backtrace") {
|
| - hasBegun = true
|
| - }
|
| - if strings.Contains(line, "Memory map") {
|
| - break
|
| - }
|
| - if !hasBegun {
|
| - continue
|
| - }
|
| -
|
| - if match := segvStackTraceLine.FindStringSubmatch(line); match != nil {
|
| - // match[0] is the entire matched portion, [1] is the "package", [2] is the file name,
|
| - // [3] is the line number and [4] is the encoded function symbol string.
|
| - newFrame := FullStackFrame(match[1], match[2], catchsegvFunctionName(match[4]), safeParseInt(match[3]))
|
| - frames = append(frames, newFrame)
|
| - }
|
| - }
|
| - return StackTrace{Frames: frames}
|
| -}
|
| -
|
| -// safeParseInt parses a string that is known to contain digits into an int.
|
| -// It may fail if the number is larger than MAX_INT, but it is unlikely those
|
| -// numbers would come up in the stacktraces.
|
| -func safeParseInt(n string) int {
|
| - if i, err := strconv.Atoi(n); err != nil {
|
| - glog.Errorf("Could not parse number from known digits %q: %v", n, err)
|
| - return 0
|
| - } else {
|
| - return i
|
| - }
|
| -}
|
| -
|
| -var staticStart = regexp.MustCompile(`^ZL(\d+)`)
|
| -var nonstaticStart = regexp.MustCompile(`^Z(\d+)`)
|
| -
|
| -var methodStart = regexp.MustCompile(`^(ZNK?)(\d+)`)
|
| -var methodName = regexp.MustCompile(`^(\d+)`)
|
| -
|
| -// catchsegvFunctionName parses the symbol string from a stacktrace to
|
| -// get the name of the related function.
|
| -//TODO(kjlubick) parse arguments if that helps the readability of the stacktraces
|
| -// Here are some examples of symbol strings and what the various chars mean:
|
| -// (Parameters are after the names, but are unparsed as of yet)
|
| -// ZL12convert_to_8 -> ZL12 -> static function 12 long "convert_to_8"
|
| -// Z9tool_mainiPPc -> non-static function, 9 long "tool_main"
|
| -// ZN14SkBmpMaskCodec10decodeRows -> ZN14 -> type is 14 long, method name is 10 long "decodeRows"
|
| -// ZNK2DM6SKPSrc4drawEP8SkCanvas -> ZNK2 -> type is 2 long (method is konstant) "DM" ->
|
| -// 6 -> Sub type is 6 long "SKPSrc" -> 4 -> method is 4 long "draw"
|
| -// (since there is no number directly after the 3rd step, we have found the param boundary).
|
| -func catchsegvFunctionName(s string) string {
|
| - if match := methodStart.FindStringSubmatch(s); match != nil {
|
| - length := safeParseInt(match[2])
|
| - // ZNK? is 2-3 chars, so slice (num letters + num digits + number of spaces) chars off
|
| - // the beginning.
|
| - s = s[len(match[1])+len(match[2])+length:]
|
| - f := ""
|
| - // We look at the beginning of our trimmed string for numbers.
|
| - // if there are numbers, we pull off a piece of the name and scan again.
|
| - // If there is more than one piece, we separate it with ::, because it is a nested type
|
| - // or enum thing.
|
| - for match := methodName.FindStringSubmatch(s); match != nil; match = methodName.FindStringSubmatch(s) {
|
| - if f != "" {
|
| - f += "::"
|
| - }
|
| - length = safeParseInt(match[1])
|
| - start := len(match[1])
|
| - f += s[start : start+length]
|
| - s = s[start+length:]
|
| - }
|
| - return f
|
| - }
|
| - if match := staticStart.FindStringSubmatch(s); match != nil {
|
| - length := safeParseInt(match[1])
|
| - // ZL is 2 chars, so advance 2 spaces + how many digits there are
|
| - start := 2 + len(match[1])
|
| - return s[start : start+length]
|
| - }
|
| - if match := nonstaticStart.FindStringSubmatch(s); match != nil {
|
| - length := safeParseInt(match[1])
|
| - // Z is 1 char, so advance 1 space + how many digits there are
|
| - start := 1 + len(match[1])
|
| - return s[start : start+length]
|
| - }
|
| - return common.UNKNOWN_FUNCTION
|
| -}
|
| -
|
| -// The `?:` at the beginning of the groups prevent them from being captured
|
| -// \1 is the (hopefully symbolized) function name, \2 is the "package", \3 is the file name,
|
| -// \4 is the line number
|
| -var asanStackTraceLine = regexp.MustCompile(`in (?P<function>[a-zA-Z0-9_:]+).*(?:\.\./)+(?P<package>(?:\w+/)+)(?P<file>.+?):(?P<line>\d+)`)
|
| -
|
| -// parseCatchsegvStackTrace takes the output of an AddressSanitizer crash, and returns the parsed
|
| -// StackTrace, if it is able to find one. If the result is not symbolized, this will return
|
| -// an empty StackTrace.
|
| -func parseASANStackTrace(contents string) StackTrace {
|
| - r := bytes.NewBufferString(contents)
|
| - scan := bufio.NewScanner(r)
|
| -
|
| - hasBegun := false
|
| -
|
| - frames := make([]StackTraceFrame, 0, 5)
|
| -
|
| - for scan.Scan() {
|
| - line := scan.Text()
|
| - if strings.Contains(line, "ERROR: AddressSanitizer:") {
|
| - hasBegun = true
|
| - continue
|
| - }
|
| - if hasBegun && line == "" {
|
| - break
|
| - }
|
| - if !hasBegun {
|
| - continue
|
| - }
|
| -
|
| - line = strings.Replace(line, "(anonymous namespace)::", "", -1)
|
| -
|
| - if match := asanStackTraceLine.FindStringSubmatch(line); match != nil {
|
| - // match[0] is the entire matched portion, [1] is the function name [2] is the
|
| - // "package", [3] is the file name, [4] is the line number
|
| - newFrame := FullStackFrame(match[2], match[3], match[1], safeParseInt(match[4]))
|
| - frames = append(frames, newFrame)
|
| - }
|
| - }
|
| - return StackTrace{Frames: frames}
|
| -}
|
| -
|
| -// FullStackFrame creates a StackTraceFrame with all components
|
| -func FullStackFrame(packageName, fileName, functionName string, lineNumber int) StackTraceFrame {
|
| - return StackTraceFrame{
|
| - PackageName: packageName,
|
| - FileName: fileName,
|
| - LineNumber: lineNumber,
|
| - FunctionName: functionName,
|
| - }
|
| -}
|
| -
|
| -func (f *StackTraceFrame) String() string {
|
| - return fmt.Sprintf("%s%s:%d %s", f.PackageName, f.FileName, f.LineNumber, f.FunctionName)
|
| -}
|
| -
|
| -func (st *StackTrace) String() string {
|
| - s := fmt.Sprintf("StackTrace with %d frames:\n", len(st.Frames))
|
| - for _, f := range st.Frames {
|
| - s += fmt.Sprintf("\t%s\n", f.String())
|
| - }
|
| - return s
|
| -}
|
| -
|
| -func (st *StackTrace) IsEmpty() bool {
|
| - return len(st.Frames) == 0
|
| -}
|
|
|