| OLD | NEW |
| (Empty) | |
| 1 package fuzz |
| 2 |
| 3 import ( |
| 4 "bufio" |
| 5 "bytes" |
| 6 "fmt" |
| 7 "regexp" |
| 8 "strconv" |
| 9 "strings" |
| 10 |
| 11 "github.com/skia-dev/glog" |
| 12 ) |
| 13 |
| 14 type StackTrace struct { |
| 15 Frames []StackTraceFrame `json:"frames"` |
| 16 } |
| 17 |
| 18 type StackTraceFrame struct { |
| 19 PackageName string `json:"packageName"` |
| 20 FileName string `json:"fileName"` |
| 21 LineNumber int `json:"lineNumber"` |
| 22 FunctionName string `json:"functionName"` |
| 23 } |
| 24 |
| 25 // The `?:` at the beginning of the groups prevent them from being captured |
| 26 var stackTraceLine = regexp.MustCompile(`(?:\.\./)+((?:\w+/)+)(.+):(\d+)\(`) |
| 27 |
| 28 // Given the files of a dump file (created through get_stack_trace [which uses c
atchsegv], return the stack trace) |
| 29 func ParseStackTrace(contents string) StackTrace { |
| 30 r := bytes.NewReader([]byte(contents)) |
| 31 scan := bufio.NewScanner(r) |
| 32 |
| 33 hasBegun := false |
| 34 |
| 35 frames := make([]StackTraceFrame, 0, 5) |
| 36 |
| 37 for scan.Scan() { |
| 38 line := scan.Text() |
| 39 if strings.Contains(line, "Backtrace") { |
| 40 hasBegun = true |
| 41 } |
| 42 if strings.Contains(line, "Memory map") { |
| 43 break |
| 44 } |
| 45 if !hasBegun { |
| 46 continue |
| 47 } |
| 48 |
| 49 if match := stackTraceLine.FindStringSubmatch(line); match != ni
l { |
| 50 // match[0] is the entire matched portion, [1] is the "p
ackage", [2] is the file name, [3] is the line number |
| 51 |
| 52 lineNumber, err := strconv.Atoi(match[3]) |
| 53 if err != nil { |
| 54 glog.Errorf("Could not parse line number from st
acktrace line %q: %s", match[0], err) |
| 55 continue |
| 56 } |
| 57 newFrame := BasicStackFrame(match[1], match[2], lineNumb
er) |
| 58 frames = append(frames, newFrame) |
| 59 } |
| 60 } |
| 61 |
| 62 return StackTrace{frames} |
| 63 } |
| 64 |
| 65 func BasicStackFrame(packageName, fileName string, lineNumber int) StackTraceFra
me { |
| 66 return StackTraceFrame{packageName, fileName, lineNumber, ""} |
| 67 } |
| 68 |
| 69 type FindFunctionName func(packageName string, fileName string, lineNumber int)
string |
| 70 |
| 71 // LookUpFunctions will go through all the stacktraces and call the passed in fu
nction to find the approximate function name the stacktrace is referring to |
| 72 func (st *StackTrace) LookUpFunctions(findFunctionName FindFunctionName) { |
| 73 for i, f := range st.Frames { |
| 74 // this awkward syntax is required to write to the actual StackT
raceFrame, not the copy generated by range |
| 75 st.Frames[i].FunctionName = findFunctionName(f.PackageName, f.Fi
leName, f.LineNumber) |
| 76 } |
| 77 } |
| 78 |
| 79 func (f *StackTraceFrame) String() string { |
| 80 return fmt.Sprintf("%s%s:%d %s", f.PackageName, f.FileName, f.LineNumber
, f.FunctionName) |
| 81 } |
| 82 |
| 83 func (st *StackTrace) String() string { |
| 84 s := fmt.Sprintf("StackTrace with %d frames:\n", len(st.Frames)) |
| 85 for _, f := range st.Frames { |
| 86 s += fmt.Sprintf("\t%s\n", f.String()) |
| 87 } |
| 88 return s |
| 89 } |
| 90 |
| 91 func (st *StackTrace) IsEmpty() bool { |
| 92 return len(st.Frames) == 0 |
| 93 } |
| OLD | NEW |