From 6a60a195309f4bb20ddf43fea9fb5b9676d31bf3 Mon Sep 17 00:00:00 2001 From: shankarapailoor Date: Thu, 6 Dec 2018 09:25:37 -0600 Subject: tools/syz-trace2syz: add tool to convert strace output to programs * fixing weird merge error * fixing presubmit * fixing presubmit * removing parsing code because of -Xraw option * fix presubmit * update * deleting vma_call_handlers as we are currently skipping most vma calls. This simplifies memory_tracker as we don't need to keep track of vma allocations * removing custom handling of bpf_instruction union * removing ifconf parsing * update * removed all expression types and replaced them with constant types. removing ipv6_addr parsing while -Xraw is getting fixed. Removing constants.go * removing ipv6 parsing * presubmit * moving direction check from ipv4_addr out to genUnion * removing code that parses kcov * removing redundant test * removing custom code in generate unions to fill ipv4_addr * proggen: changing order of imports to make external packages import first fixing presubmit * changing log messages to lower case to be consistent with other packages. * removing pointer type and simplifying memory_tracker removing comment * moving context and return_cache to seaparate files * deleting default argument generation when we should probably throw an error --- tools/syz-trace2syz/config/unsupported_calls.go | 41 + tools/syz-trace2syz/parser/intermediate_types.go | 155 + tools/syz-trace2syz/parser/lex.go | 5935 ++++++++++++++++++++++ tools/syz-trace2syz/parser/parser.go | 73 + tools/syz-trace2syz/parser/parser_test.go | 196 + tools/syz-trace2syz/parser/strace.go | 983 ++++ tools/syz-trace2syz/parser/strace.y | 165 + tools/syz-trace2syz/parser/straceLex.rl | 133 + tools/syz-trace2syz/proggen/call_selector.go | 118 + tools/syz-trace2syz/proggen/context.go | 37 + tools/syz-trace2syz/proggen/generate_unions.go | 103 + tools/syz-trace2syz/proggen/memory_tracker.go | 62 + tools/syz-trace2syz/proggen/proggen.go | 381 ++ tools/syz-trace2syz/proggen/proggen_test.go | 337 ++ tools/syz-trace2syz/proggen/return_cache.go | 52 + tools/syz-trace2syz/trace2syz.go | 173 + 16 files changed, 8944 insertions(+) create mode 100644 tools/syz-trace2syz/config/unsupported_calls.go create mode 100644 tools/syz-trace2syz/parser/intermediate_types.go create mode 100644 tools/syz-trace2syz/parser/lex.go create mode 100644 tools/syz-trace2syz/parser/parser.go create mode 100644 tools/syz-trace2syz/parser/parser_test.go create mode 100644 tools/syz-trace2syz/parser/strace.go create mode 100644 tools/syz-trace2syz/parser/strace.y create mode 100644 tools/syz-trace2syz/parser/straceLex.rl create mode 100644 tools/syz-trace2syz/proggen/call_selector.go create mode 100644 tools/syz-trace2syz/proggen/context.go create mode 100644 tools/syz-trace2syz/proggen/generate_unions.go create mode 100644 tools/syz-trace2syz/proggen/memory_tracker.go create mode 100644 tools/syz-trace2syz/proggen/proggen.go create mode 100644 tools/syz-trace2syz/proggen/proggen_test.go create mode 100644 tools/syz-trace2syz/proggen/return_cache.go create mode 100644 tools/syz-trace2syz/trace2syz.go (limited to 'tools') diff --git a/tools/syz-trace2syz/config/unsupported_calls.go b/tools/syz-trace2syz/config/unsupported_calls.go new file mode 100644 index 000000000..e2453c2ba --- /dev/null +++ b/tools/syz-trace2syz/config/unsupported_calls.go @@ -0,0 +1,41 @@ +// Copyright 2018 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package config + +var ( + // ShouldSkip lists system calls that we should skip when parsing + // Some of these are unsupported or not worth executing + ShouldSkip = map[string]bool{ + // While we have system call descriptions for execve it is not worth adding + // the ones in traces. Every trace has an execve at the beginning which means + // all the system calls afterwards will not execute + "execve": true, + // Unsafe to set the addr argument to some random argument. Needs more care + "arch_prctl": true, + // Don't produce multithreaded programs. + "wait4": true, + "wait": true, + "futex": true, + // Cannot obtain coverage from the forks. + "clone": true, + // Can support these calls but need to identify the ones in the trace that are worth keeping + "mmap": true, + "msync": true, + "mremap": true, + "mprotect": true, + "madvise": true, + "munmap": true, + // Not interesting coverage + "getcwd": true, + "getcpu": true, + // Cannot evaluate sigset + "rt_sigprocmask": true, + "rt_sigtimedwait": true, + "rt_sigreturn": true, + "rt_sigqueueinfo": true, + "rt_sigsuspend": true, + // Require function pointers which are not recovered by strace + "rt_sigaction": true, + } +) diff --git a/tools/syz-trace2syz/parser/intermediate_types.go b/tools/syz-trace2syz/parser/intermediate_types.go new file mode 100644 index 000000000..3cbf94238 --- /dev/null +++ b/tools/syz-trace2syz/parser/intermediate_types.go @@ -0,0 +1,155 @@ +// Copyright 2018 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package parser + +import ( + "bytes" + "fmt" +) + +// TraceTree struct contains intermediate representation of trace +// If a trace is multiprocess it constructs a trace for each type +type TraceTree struct { + TraceMap map[int64]*Trace + Ptree map[int64][]int64 + RootPid int64 + Filename string +} + +// NewTraceTree initializes a TraceTree +func NewTraceTree() (tree *TraceTree) { + tree = &TraceTree{ + TraceMap: make(map[int64]*Trace), + Ptree: make(map[int64][]int64), + RootPid: -1, + } + return +} + +func (tree *TraceTree) add(call *Syscall) { + if tree.RootPid < 0 { + tree.RootPid = call.Pid + } + + if !call.Resumed { + if tree.TraceMap[call.Pid] == nil { + tree.TraceMap[call.Pid] = new(Trace) + tree.Ptree[call.Pid] = make([]int64, 0) + } + } + c := tree.TraceMap[call.Pid].add(call) + if c.CallName == "clone" && !c.Paused { + tree.Ptree[c.Pid] = append(tree.Ptree[c.Pid], c.Ret) + } +} + +// Trace is just a list of system calls +type Trace struct { + Calls []*Syscall +} + +func (trace *Trace) add(call *Syscall) (ret *Syscall) { + if !call.Resumed { + trace.Calls = append(trace.Calls, call) + ret = call + return + } + lastCall := trace.Calls[len(trace.Calls)-1] + lastCall.Args = append(lastCall.Args, call.Args...) + lastCall.Paused = false + lastCall.Ret = call.Ret + ret = lastCall + return +} + +// IrType is the intermediate representation of the strace output +// Every argument of a system call should be represented in an intermediate type +type IrType interface { + String() string +} + +// Syscall struct is the IR type for any system call +type Syscall struct { + CallName string + Args []IrType + Pid int64 + Ret int64 + Paused bool + Resumed bool +} + +// NewSyscall - constructor +func NewSyscall(pid int64, name string, args []IrType, ret int64, paused, resumed bool) (sys *Syscall) { + return &Syscall{ + CallName: name, + Args: args, + Pid: pid, + Ret: ret, + Paused: paused, + Resumed: resumed, + } +} + +// String +func (s *Syscall) String() string { + buf := new(bytes.Buffer) + + fmt.Fprintf(buf, "Pid: -%v-", s.Pid) + fmt.Fprintf(buf, "Name: -%v-", s.CallName) + for _, typ := range s.Args { + buf.WriteString("-") + buf.WriteString(typ.String()) + buf.WriteString("-") + } + buf.WriteString(fmt.Sprintf("-Ret: %d\n", s.Ret)) + return buf.String() +} + +// GroupType contains arrays and structs +type GroupType struct { + Elems []IrType +} + +func newGroupType(elems []IrType) (typ *GroupType) { + return &GroupType{Elems: elems} +} + +// String implements IrType String() +func (a *GroupType) String() string { + var buf bytes.Buffer + + buf.WriteString("[") + for _, elem := range a.Elems { + buf.WriteString(elem.String()) + buf.WriteString(",") + } + buf.WriteString("]") + return buf.String() +} + +// Constant represents all evaluated expressions produced by strace +// Constant types are evaluated at parse time +type Constant uint64 + +func (c Constant) String() string { + return fmt.Sprintf("%#v", c) +} + +func (c Constant) Val() uint64 { + return uint64(c) +} + +// BufferType contains strings +type BufferType struct { + Val string +} + +func newBufferType(val string) *BufferType { + return &BufferType{Val: val} +} + +// String implements IrType String() +func (b *BufferType) String() string { + return fmt.Sprintf("Buffer: %s with length: %d\n", b.Val, len(b.Val)) +} diff --git a/tools/syz-trace2syz/parser/lex.go b/tools/syz-trace2syz/parser/lex.go new file mode 100644 index 000000000..0aa1f4f43 --- /dev/null +++ b/tools/syz-trace2syz/parser/lex.go @@ -0,0 +1,5935 @@ +//line straceLex.rl:1 + +// Copyright 2018 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// nolint + +package parser + +import ( + "encoding/hex" + "fmt" + "github.com/google/syzkaller/pkg/log" + "strconv" + "strings" +) + +//line lex.go:20 +const strace_start int = 157 +const strace_first_final int = 157 +const strace_error int = 0 + +const strace_en_comment int = 211 +const strace_en_main int = 157 + +//line straceLex.rl:22 +type Stracelexer struct { + result *Syscall + data []byte + p, pe, cs int + ts, te, act int +} + +func newStraceLexer(data []byte) *Stracelexer { + lex := &Stracelexer{ + data: data, + pe: len(data), + } + +//line lex.go:46 + { + lex.cs = strace_start + lex.ts = 0 + lex.te = 0 + lex.act = 0 + } + +//line straceLex.rl:38 + return lex +} + +func (lex *Stracelexer) Lex(out *StraceSymType) int { + eof := lex.pe + tok := 0 + +//line lex.go:62 + { + if (lex.p) == (lex.pe) { + goto _test_eof + } + switch lex.cs { + case 157: + goto st_case_157 + case 0: + goto st_case_0 + case 1: + goto st_case_1 + case 2: + goto st_case_2 + case 158: + goto st_case_158 + case 3: + goto st_case_3 + case 4: + goto st_case_4 + case 5: + goto st_case_5 + case 6: + goto st_case_6 + case 7: + goto st_case_7 + case 8: + goto st_case_8 + case 159: + goto st_case_159 + case 160: + goto st_case_160 + case 9: + goto st_case_9 + case 161: + goto st_case_161 + case 162: + goto st_case_162 + case 10: + goto st_case_10 + case 11: + goto st_case_11 + case 12: + goto st_case_12 + case 13: + goto st_case_13 + case 14: + goto st_case_14 + case 15: + goto st_case_15 + case 16: + goto st_case_16 + case 17: + goto st_case_17 + case 18: + goto st_case_18 + case 19: + goto st_case_19 + case 20: + goto st_case_20 + case 21: + goto st_case_21 + case 22: + goto st_case_22 + case 23: + goto st_case_23 + case 24: + goto st_case_24 + case 25: + goto st_case_25 + case 26: + goto st_case_26 + case 163: + goto st_case_163 + case 27: + goto st_case_27 + case 164: + goto st_case_164 + case 165: + goto st_case_165 + case 166: + goto st_case_166 + case 167: + goto st_case_167 + case 28: + goto st_case_28 + case 29: + goto st_case_29 + case 30: + goto st_case_30 + case 168: + goto st_case_168 + case 169: + goto st_case_169 + case 31: + goto st_case_31 + case 32: + goto st_case_32 + case 170: + goto st_case_170 + case 171: + goto st_case_171 + case 172: + goto st_case_172 + case 173: + goto st_case_173 + case 33: + goto st_case_33 + case 34: + goto st_case_34 + case 35: + goto st_case_35 + case 36: + goto st_case_36 + case 174: + goto st_case_174 + case 175: + goto st_case_175 + case 37: + goto st_case_37 + case 38: + goto st_case_38 + case 39: + goto st_case_39 + case 40: + goto st_case_40 + case 41: + goto st_case_41 + case 42: + goto st_case_42 + case 43: + goto st_case_43 + case 44: + goto st_case_44 + case 45: + goto st_case_45 + case 46: + goto st_case_46 + case 47: + goto st_case_47 + case 48: + goto st_case_48 + case 49: + goto st_case_49 + case 50: + goto st_case_50 + case 176: + goto st_case_176 + case 51: + goto st_case_51 + case 52: + goto st_case_52 + case 53: + goto st_case_53 + case 54: + goto st_case_54 + case 177: + goto st_case_177 + case 55: + goto st_case_55 + case 178: + goto st_case_178 + case 179: + goto st_case_179 + case 180: + goto st_case_180 + case 181: + goto st_case_181 + case 182: + goto st_case_182 + case 56: + goto st_case_56 + case 57: + goto st_case_57 + case 58: + goto st_case_58 + case 59: + goto st_case_59 + case 60: + goto st_case_60 + case 61: + goto st_case_61 + case 62: + goto st_case_62 + case 63: + goto st_case_63 + case 64: + goto st_case_64 + case 65: + goto st_case_65 + case 66: + goto st_case_66 + case 67: + goto st_case_67 + case 68: + goto st_case_68 + case 69: + goto st_case_69 + case 183: + goto st_case_183 + case 70: + goto st_case_70 + case 71: + goto st_case_71 + case 184: + goto st_case_184 + case 185: + goto st_case_185 + case 72: + goto st_case_72 + case 73: + goto st_case_73 + case 74: + goto st_case_74 + case 75: + goto st_case_75 + case 76: + goto st_case_76 + case 77: + goto st_case_77 + case 78: + goto st_case_78 + case 79: + goto st_case_79 + case 80: + goto st_case_80 + case 81: + goto st_case_81 + case 82: + goto st_case_82 + case 83: + goto st_case_83 + case 84: + goto st_case_84 + case 85: + goto st_case_85 + case 186: + goto st_case_186 + case 86: + goto st_case_86 + case 87: + goto st_case_87 + case 88: + goto st_case_88 + case 89: + goto st_case_89 + case 90: + goto st_case_90 + case 91: + goto st_case_91 + case 92: + goto st_case_92 + case 93: + goto st_case_93 + case 94: + goto st_case_94 + case 95: + goto st_case_95 + case 96: + goto st_case_96 + case 97: + goto st_case_97 + case 98: + goto st_case_98 + case 99: + goto st_case_99 + case 100: + goto st_case_100 + case 101: + goto st_case_101 + case 102: + goto st_case_102 + case 103: + goto st_case_103 + case 104: + goto st_case_104 + case 105: + goto st_case_105 + case 106: + goto st_case_106 + case 107: + goto st_case_107 + case 108: + goto st_case_108 + case 109: + goto st_case_109 + case 110: + goto st_case_110 + case 111: + goto st_case_111 + case 112: + goto st_case_112 + case 113: + goto st_case_113 + case 114: + goto st_case_114 + case 115: + goto st_case_115 + case 116: + goto st_case_116 + case 117: + goto st_case_117 + case 118: + goto st_case_118 + case 119: + goto st_case_119 + case 120: + goto st_case_120 + case 121: + goto st_case_121 + case 122: + goto st_case_122 + case 123: + goto st_case_123 + case 124: + goto st_case_124 + case 125: + goto st_case_125 + case 126: + goto st_case_126 + case 127: + goto st_case_127 + case 128: + goto st_case_128 + case 129: + goto st_case_129 + case 130: + goto st_case_130 + case 131: + goto st_case_131 + case 132: + goto st_case_132 + case 133: + goto st_case_133 + case 134: + goto st_case_134 + case 135: + goto st_case_135 + case 136: + goto st_case_136 + case 137: + goto st_case_137 + case 138: + goto st_case_138 + case 139: + goto st_case_139 + case 140: + goto st_case_140 + case 141: + goto st_case_141 + case 142: + goto st_case_142 + case 143: + goto st_case_143 + case 144: + goto st_case_144 + case 145: + goto st_case_145 + case 146: + goto st_case_146 + case 147: + goto st_case_147 + case 148: + goto st_case_148 + case 149: + goto st_case_149 + case 150: + goto st_case_150 + case 151: + goto st_case_151 + case 152: + goto st_case_152 + case 153: + goto st_case_153 + case 154: + goto st_case_154 + case 187: + goto st_case_187 + case 155: + goto st_case_155 + case 188: + goto st_case_188 + case 189: + goto st_case_189 + case 190: + goto st_case_190 + case 191: + goto st_case_191 + case 192: + goto st_case_192 + case 193: + goto st_case_193 + case 194: + goto st_case_194 + case 195: + goto st_case_195 + case 196: + goto st_case_196 + case 197: + goto st_case_197 + case 198: + goto st_case_198 + case 199: + goto st_case_199 + case 200: + goto st_case_200 + case 201: + goto st_case_201 + case 202: + goto st_case_202 + case 203: + goto st_case_203 + case 204: + goto st_case_204 + case 205: + goto st_case_205 + case 206: + goto st_case_206 + case 207: + goto st_case_207 + case 208: + goto st_case_208 + case 209: + goto st_case_209 + case 156: + goto st_case_156 + case 210: + goto st_case_210 + case 211: + goto st_case_211 + case 212: + goto st_case_212 + } + goto st_out + tr9: +//line NONE:1 + switch lex.act { + case 0: + { + { + goto st0 + } + } + case 3: + { + (lex.p) = (lex.te) - 1 + out.val_int, _ = strconv.ParseInt(string(lex.data[lex.ts:lex.te]), 10, 64) + tok = INT + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + case 4: + { + (lex.p) = (lex.te) - 1 + out.val_double, _ = strconv.ParseFloat(string(lex.data[lex.ts:lex.te]), 64) + tok = DOUBLE + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + case 8: + { + (lex.p) = (lex.te) - 1 + tok = NULL + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + case 9: + { + (lex.p) = (lex.te) - 1 + out.data = string(lex.data[lex.ts:lex.te]) + tok = FLAG + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + case 11: + { + (lex.p) = (lex.te) - 1 + out.data = string(lex.data[lex.ts:lex.te]) + tok = IDENTIFIER + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + case 33: + { + (lex.p) = (lex.te) - 1 + tok = COMMA + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + } + + goto st157 + tr11: +//line straceLex.rl:100 + (lex.p) = (lex.te) - 1 + { + tok = COMMA + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr28: +//line straceLex.rl:79 + lex.te = (lex.p) + 1 + { + tok = UNFINISHED + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr30: +//line straceLex.rl:90 + lex.te = (lex.p) + 1 + { + tok = RBRACKET + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr36: +//line straceLex.rl:70 + (lex.p) = (lex.te) - 1 + { + out.val_int, _ = strconv.ParseInt(string(lex.data[lex.ts:lex.te]), 10, 64) + tok = INT + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr55: +//line straceLex.rl:104 + (lex.p) = (lex.te) - 1 + { + out.data = string(lex.data[lex.ts:lex.te]) + tok = DATETIME + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr74: +//line straceLex.rl:81 + lex.te = (lex.p) + 1 + { + out.data = string(lex.data[lex.ts:lex.te]) + tok = MAC + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr78: +//line straceLex.rl:96 + lex.te = (lex.p) + 1 + { + tok = LSHIFT + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr94: +//line straceLex.rl:80 + (lex.p) = (lex.te) - 1 + { + tok = RESUMED + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr95: +//line straceLex.rl:80 + lex.te = (lex.p) + 1 + { + tok = RESUMED + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr162: +//line straceLex.rl:97 + lex.te = (lex.p) + 1 + { + tok = RSHIFT + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr165: +//line straceLex.rl:107 + lex.te = (lex.p) + 1 + + goto st157 + tr166: +//line straceLex.rl:94 + lex.te = (lex.p) + 1 + { + tok = NOT + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr168: +//line straceLex.rl:93 + lex.te = (lex.p) + 1 + { + tok = AND + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr170: +//line straceLex.rl:83 + lex.te = (lex.p) + 1 + { + tok = LPAREN + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr171: +//line straceLex.rl:85 + lex.te = (lex.p) + 1 + { + tok = RPAREN + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr172: +//line straceLex.rl:88 + lex.te = (lex.p) + 1 + { + tok = TIMES + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr173: +//line straceLex.rl:102 + lex.te = (lex.p) + 1 + { + tok = PLUS + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr183: +//line straceLex.rl:106 + lex.te = (lex.p) + 1 + { + tok = QUESTION + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr187: +//line straceLex.rl:86 + lex.te = (lex.p) + 1 + { + tok = LBRACKET_SQUARE + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr188: +//line straceLex.rl:87 + lex.te = (lex.p) + 1 + { + tok = RBRACKET_SQUARE + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr190: +//line straceLex.rl:89 + lex.te = (lex.p) + 1 + { + tok = LBRACKET + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr191: +//line straceLex.rl:91 + lex.te = (lex.p) + 1 + { + tok = OR + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr192: +//line straceLex.rl:95 + lex.te = (lex.p) + 1 + { + tok = ONESCOMP + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr193: +//line straceLex.rl:74 + lex.te = (lex.p) + (lex.p)-- + { + out.data = ParseString(string(lex.data[lex.ts+1 : lex.te-1])) + tok = STRING_LITERAL + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr194: +//line straceLex.rl:78 + lex.te = (lex.p) + (lex.p)-- + { + out.data = string(lex.data[lex.ts:lex.te]) + tok = IDENTIFIER + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr195: +//line straceLex.rl:100 + lex.te = (lex.p) + (lex.p)-- + { + tok = COMMA + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr197: +//line straceLex.rl:101 + lex.te = (lex.p) + (lex.p)-- + { + tok = MINUS + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr198: +//line straceLex.rl:98 + lex.te = (lex.p) + 1 + { + tok = ARROW + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr199: +//line straceLex.rl:103 + lex.te = (lex.p) + (lex.p)-- + { + tok = FORWARDSLASH + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr200: +//line straceLex.rl:105 + lex.te = (lex.p) + 1 + { + { + goto st211 + } + } + goto st157 + tr201: +//line straceLex.rl:70 + lex.te = (lex.p) + (lex.p)-- + { + out.val_int, _ = strconv.ParseInt(string(lex.data[lex.ts:lex.te]), 10, 64) + tok = INT + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr207: +//line straceLex.rl:71 + lex.te = (lex.p) + (lex.p)-- + { + out.val_double, _ = strconv.ParseFloat(string(lex.data[lex.ts:lex.te]), 64) + tok = DOUBLE + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr211: +//line straceLex.rl:78 + lex.te = (lex.p) + 1 + { + out.data = string(lex.data[lex.ts:lex.te]) + tok = IDENTIFIER + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr222: +//line straceLex.rl:104 + lex.te = (lex.p) + (lex.p)-- + { + out.data = string(lex.data[lex.ts:lex.te]) + tok = DATETIME + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr225: +//line straceLex.rl:73 + lex.te = (lex.p) + (lex.p)-- + { + out.val_uint, _ = strconv.ParseUint(string(lex.data[lex.ts:lex.te]), 0, 64) + tok = UINT + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr226: +//line straceLex.rl:80 + lex.te = (lex.p) + (lex.p)-- + { + tok = RESUMED + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr228: +//line straceLex.rl:82 + lex.te = (lex.p) + (lex.p)-- + { + tok = EQUALS + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr229: +//line straceLex.rl:99 + lex.te = (lex.p) + 1 + { + tok = ARROW + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr230: +//line straceLex.rl:84 + lex.te = (lex.p) + 1 + { + tok = EQUALAT + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + tr235: +//line straceLex.rl:76 + lex.te = (lex.p) + (lex.p)-- + { + out.data = string(lex.data[lex.ts:lex.te]) + tok = FLAG + { + (lex.p)++ + lex.cs = 157 + goto _out + } + } + goto st157 + st157: +//line NONE:1 + lex.ts = 0 + +//line NONE:1 + lex.act = 0 + + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof157 + } + st_case_157: +//line NONE:1 + lex.ts = (lex.p) + +//line lex.go:748 + switch lex.data[(lex.p)] { + case 32: + goto tr165 + case 33: + goto tr166 + case 34: + goto st1 + case 38: + goto tr168 + case 39: + goto tr169 + case 40: + goto tr170 + case 41: + goto tr171 + case 42: + goto tr172 + case 43: + goto tr173 + case 44: + goto tr174 + case 45: + goto st163 + case 46: + goto st27 + case 47: + goto st164 + case 48: + goto tr177 + case 58: + goto st160 + case 60: + goto st72 + case 61: + goto st187 + case 62: + goto st155 + case 63: + goto tr183 + case 78: + goto st207 + case 91: + goto tr187 + case 93: + goto tr188 + case 95: + goto st156 + case 123: + goto tr190 + case 124: + goto tr191 + case 125: + goto tr30 + case 126: + goto tr192 + } + switch { + case lex.data[(lex.p)] < 65: + switch { + case lex.data[(lex.p)] > 13: + if 49 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr178 + } + case lex.data[(lex.p)] >= 9: + goto tr165 + } + case lex.data[(lex.p)] > 70: + switch { + case lex.data[(lex.p)] < 97: + if 71 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 90 { + goto tr185 + } + case lex.data[(lex.p)] > 102: + if 103 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + default: + goto tr189 + } + default: + goto st188 + } + goto st0 + st_case_0: + st0: + lex.cs = 0 + goto _out + st1: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof1 + } + st_case_1: + switch lex.data[(lex.p)] { + case 32: + goto st2 + case 34: + goto st158 + case 35: + goto st2 + case 39: + goto st3 + case 78: + goto st6 + case 92: + goto st2 + case 95: + goto st3 + } + switch { + case lex.data[(lex.p)] < 46: + if 40 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 42 { + goto st2 + } + case lex.data[(lex.p)] > 58: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st2 + } + case lex.data[(lex.p)] >= 65: + goto st4 + } + default: + goto st2 + } + goto st0 + st2: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof2 + } + st_case_2: + switch lex.data[(lex.p)] { + case 32: + goto st2 + case 34: + goto st158 + case 35: + goto st2 + case 92: + goto st2 + case 95: + goto st2 + } + switch { + case lex.data[(lex.p)] < 46: + if 39 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 42 { + goto st2 + } + case lex.data[(lex.p)] > 58: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st2 + } + case lex.data[(lex.p)] >= 65: + goto st2 + } + default: + goto st2 + } + goto st0 + st158: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof158 + } + st_case_158: + switch lex.data[(lex.p)] { + case 39: + goto st158 + case 46: + goto st158 + } + goto tr193 + st3: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof3 + } + st_case_3: + switch lex.data[(lex.p)] { + case 32: + goto st2 + case 34: + goto st158 + case 35: + goto st2 + case 39: + goto st3 + case 92: + goto st2 + case 95: + goto st3 + } + switch { + case lex.data[(lex.p)] < 46: + if 40 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 42 { + goto st2 + } + case lex.data[(lex.p)] > 58: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st2 + } + case lex.data[(lex.p)] >= 65: + goto st4 + } + default: + goto st2 + } + goto st0 + st4: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof4 + } + st_case_4: + switch lex.data[(lex.p)] { + case 32: + goto st2 + case 34: + goto st158 + case 35: + goto st2 + case 39: + goto st5 + case 58: + goto st2 + case 92: + goto st2 + case 95: + goto st5 + } + switch { + case lex.data[(lex.p)] < 48: + switch { + case lex.data[(lex.p)] > 42: + if 46 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 47 { + goto st2 + } + case lex.data[(lex.p)] >= 40: + goto st2 + } + case lex.data[(lex.p)] > 57: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st2 + } + case lex.data[(lex.p)] >= 65: + goto st5 + } + default: + goto st5 + } + goto st0 + st5: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof5 + } + st_case_5: + switch lex.data[(lex.p)] { + case 32: + goto st2 + case 34: + goto st158 + case 35: + goto st2 + case 39: + goto st5 + case 58: + goto st2 + case 92: + goto st2 + case 95: + goto st5 + } + switch { + case lex.data[(lex.p)] < 48: + switch { + case lex.data[(lex.p)] > 42: + if 46 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 47 { + goto st2 + } + case lex.data[(lex.p)] >= 40: + goto st2 + } + case lex.data[(lex.p)] > 57: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st2 + } + case lex.data[(lex.p)] >= 65: + goto st5 + } + default: + goto st5 + } + goto st0 + st6: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof6 + } + st_case_6: + switch lex.data[(lex.p)] { + case 32: + goto st2 + case 34: + goto st158 + case 35: + goto st2 + case 39: + goto st5 + case 58: + goto st2 + case 85: + goto st7 + case 92: + goto st2 + case 95: + goto st5 + } + switch { + case lex.data[(lex.p)] < 48: + switch { + case lex.data[(lex.p)] > 42: + if 46 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 47 { + goto st2 + } + case lex.data[(lex.p)] >= 40: + goto st2 + } + case lex.data[(lex.p)] > 57: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st2 + } + case lex.data[(lex.p)] >= 65: + goto st5 + } + default: + goto st5 + } + goto st0 + st7: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof7 + } + st_case_7: + switch lex.data[(lex.p)] { + case 32: + goto st2 + case 34: + goto st158 + case 35: + goto st2 + case 39: + goto st5 + case 58: + goto st2 + case 76: + goto st8 + case 92: + goto st2 + case 95: + goto st5 + } + switch { + case lex.data[(lex.p)] < 48: + switch { + case lex.data[(lex.p)] > 42: + if 46 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 47 { + goto st2 + } + case lex.data[(lex.p)] >= 40: + goto st2 + } + case lex.data[(lex.p)] > 57: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st2 + } + case lex.data[(lex.p)] >= 65: + goto st5 + } + default: + goto st5 + } + goto st0 + st8: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof8 + } + st_case_8: + switch lex.data[(lex.p)] { + case 32: + goto st2 + case 34: + goto st158 + case 35: + goto st2 + case 39: + goto st5 + case 58: + goto st2 + case 76: + goto st4 + case 92: + goto st2 + case 95: + goto st5 + } + switch { + case lex.data[(lex.p)] < 48: + switch { + case lex.data[(lex.p)] > 42: + if 46 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 47 { + goto st2 + } + case lex.data[(lex.p)] >= 40: + goto st2 + } + case lex.data[(lex.p)] > 57: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st2 + } + case lex.data[(lex.p)] >= 65: + goto st5 + } + default: + goto st5 + } + goto st0 + tr169: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:78 + lex.act = 11 + goto st159 + st159: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof159 + } + st_case_159: +//line lex.go:1197 + switch lex.data[(lex.p)] { + case 39: + goto tr169 + case 42: + goto st160 + case 95: + goto tr169 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st160 + } + case lex.data[(lex.p)] > 58: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + case lex.data[(lex.p)] >= 65: + goto st9 + } + default: + goto st160 + } + goto tr194 + st160: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof160 + } + st_case_160: + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st160 + } + case lex.data[(lex.p)] > 58: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + default: + goto st160 + } + goto tr194 + st9: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof9 + } + st_case_9: + switch lex.data[(lex.p)] { + case 39: + goto tr10 + case 95: + goto tr10 + } + switch { + case lex.data[(lex.p)] > 57: + if 65 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 90 { + goto tr10 + } + case lex.data[(lex.p)] >= 48: + goto tr10 + } + goto tr9 + tr10: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:76 + lex.act = 9 + goto st161 + tr252: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:75 + lex.act = 8 + goto st161 + st161: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof161 + } + st_case_161: +//line lex.go:1289 + switch lex.data[(lex.p)] { + case 39: + goto tr10 + case 95: + goto tr10 + } + switch { + case lex.data[(lex.p)] > 57: + if 65 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 90 { + goto tr10 + } + case lex.data[(lex.p)] >= 48: + goto tr10 + } + goto tr9 + tr174: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:100 + lex.act = 33 + goto st162 + st162: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof162 + } + st_case_162: +//line lex.go:1317 + if lex.data[(lex.p)] == 32 { + goto st10 + } + goto tr195 + st10: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof10 + } + st_case_10: + if lex.data[(lex.p)] == 32 { + goto st11 + } + goto tr11 + st11: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof11 + } + st_case_11: + if lex.data[(lex.p)] == 60 { + goto st12 + } + goto tr11 + st12: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof12 + } + st_case_12: + if lex.data[(lex.p)] == 117 { + goto st13 + } + goto tr11 + st13: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof13 + } + st_case_13: + if lex.data[(lex.p)] == 110 { + goto st14 + } + goto tr9 + st14: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof14 + } + st_case_14: + if lex.data[(lex.p)] == 102 { + goto st15 + } + goto tr9 + st15: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof15 + } + st_case_15: + if lex.data[(lex.p)] == 105 { + goto st16 + } + goto tr9 + st16: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof16 + } + st_case_16: + if lex.data[(lex.p)] == 110 { + goto st17 + } + goto tr9 + st17: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof17 + } + st_case_17: + if lex.data[(lex.p)] == 105 { + goto st18 + } + goto tr9 + st18: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof18 + } + st_case_18: + if lex.data[(lex.p)] == 115 { + goto st19 + } + goto tr9 + st19: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof19 + } + st_case_19: + if lex.data[(lex.p)] == 104 { + goto st20 + } + goto tr9 + st20: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof20 + } + st_case_20: + if lex.data[(lex.p)] == 101 { + goto st21 + } + goto tr9 + st21: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof21 + } + st_case_21: + if lex.data[(lex.p)] == 100 { + goto st22 + } + goto tr9 + st22: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof22 + } + st_case_22: + if lex.data[(lex.p)] == 32 { + goto st23 + } + goto tr9 + st23: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof23 + } + st_case_23: + if lex.data[(lex.p)] == 46 { + goto st24 + } + goto tr9 + st24: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof24 + } + st_case_24: + if lex.data[(lex.p)] == 46 { + goto st25 + } + goto tr9 + st25: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof25 + } + st_case_25: + if lex.data[(lex.p)] == 46 { + goto st26 + } + goto tr9 + st26: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof26 + } + st_case_26: + if lex.data[(lex.p)] == 62 { + goto tr28 + } + goto tr9 + st163: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof163 + } + st_case_163: + if lex.data[(lex.p)] == 62 { + goto tr198 + } + goto tr197 + st27: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof27 + } + st_case_27: + switch lex.data[(lex.p)] { + case 46: + goto st27 + case 125: + goto tr30 + } + goto st0 + st164: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof164 + } + st_case_164: + if lex.data[(lex.p)] == 42 { + goto tr200 + } + goto tr199 + tr177: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:70 + lex.act = 3 + goto st165 + st165: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof165 + } + st_case_165: +//line lex.go:1517 + switch lex.data[(lex.p)] { + case 46: + goto st166 + case 120: + goto st71 + } + switch { + case lex.data[(lex.p)] < 56: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 55 { + goto tr203 + } + case lex.data[(lex.p)] > 57: + switch { + case lex.data[(lex.p)] > 70: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 102 { + goto st70 + } + case lex.data[(lex.p)] >= 65: + goto st70 + } + default: + goto tr204 + } + goto tr201 + st166: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof166 + } + st_case_166: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr208 + } + goto tr207 + tr208: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:71 + lex.act = 4 + goto st167 + st167: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof167 + } + st_case_167: +//line lex.go:1563 + if lex.data[(lex.p)] == 46 { + goto st28 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr209 + } + goto tr207 + st28: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof28 + } + st_case_28: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st29 + } + goto tr9 + st29: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof29 + } + st_case_29: + if lex.data[(lex.p)] == 46 { + goto st30 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st31 + } + goto tr9 + st30: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof30 + } + st_case_30: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st168 + } + goto tr9 + st168: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof168 + } + st_case_168: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st169 + } + goto tr194 + st169: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof169 + } + st_case_169: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr211 + } + goto tr194 + st31: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof31 + } + st_case_31: + if lex.data[(lex.p)] == 46 { + goto st30 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st32 + } + goto tr9 + st32: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof32 + } + st_case_32: + if lex.data[(lex.p)] == 46 { + goto st30 + } + goto tr9 + tr209: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:71 + lex.act = 4 + goto st170 + st170: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof170 + } + st_case_170: +//line lex.go:1652 + if lex.data[(lex.p)] == 46 { + goto st28 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr212 + } + goto tr207 + tr212: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:71 + lex.act = 4 + goto st171 + st171: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof171 + } + st_case_171: +//line lex.go:1672 + if lex.data[(lex.p)] == 46 { + goto st28 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st172 + } + goto tr207 + st172: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof172 + } + st_case_172: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st172 + } + goto tr207 + tr203: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:70 + lex.act = 3 + goto st173 + st173: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof173 + } + st_case_173: +//line lex.go:1701 + switch lex.data[(lex.p)] { + case 46: + goto st33 + case 58: + goto st56 + } + switch { + case lex.data[(lex.p)] > 55: + if 56 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr216 + } + case lex.data[(lex.p)] >= 48: + goto tr215 + } + goto tr201 + st33: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof33 + } + st_case_33: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st34 + } + goto tr36 + st34: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof34 + } + st_case_34: + if lex.data[(lex.p)] == 46 { + goto st28 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st35 + } + goto tr36 + st35: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof35 + } + st_case_35: + if lex.data[(lex.p)] == 46 { + goto st28 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st36 + } + goto tr36 + st36: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof36 + } + st_case_36: + if lex.data[(lex.p)] == 46 { + goto st28 + } + goto tr36 + tr215: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:70 + lex.act = 3 + goto st174 + st174: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof174 + } + st_case_174: +//line lex.go:1771 + if lex.data[(lex.p)] == 46 { + goto st33 + } + switch { + case lex.data[(lex.p)] > 55: + if 56 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr218 + } + case lex.data[(lex.p)] >= 48: + goto tr217 + } + goto tr201 + tr217: +//line NONE:1 + lex.te = (lex.p) + 1 + + goto st175 + st175: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof175 + } + st_case_175: +//line lex.go:1794 + switch lex.data[(lex.p)] { + case 45: + goto st37 + case 47: + goto st37 + } + switch { + case lex.data[(lex.p)] > 55: + if 56 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st180 + } + case lex.data[(lex.p)] >= 48: + goto st179 + } + goto tr201 + st37: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof37 + } + st_case_37: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st38 + } + goto tr36 + st38: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof38 + } + st_case_38: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st39 + } + goto tr36 + st39: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof39 + } + st_case_39: + switch lex.data[(lex.p)] { + case 45: + goto st40 + case 47: + goto st40 + } + goto tr36 + st40: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof40 + } + st_case_40: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st41 + } + goto tr36 + st41: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof41 + } + st_case_41: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st42 + } + goto tr36 + st42: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof42 + } + st_case_42: + switch lex.data[(lex.p)] { + case 45: + goto st43 + case 84: + goto st43 + } + goto tr36 + st43: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof43 + } + st_case_43: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st44 + } + goto tr36 + st44: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof44 + } + st_case_44: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st45 + } + goto tr36 + st45: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof45 + } + st_case_45: + if lex.data[(lex.p)] == 58 { + goto st46 + } + goto tr36 + st46: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof46 + } + st_case_46: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st47 + } + goto tr36 + st47: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof47 + } + st_case_47: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st48 + } + goto tr36 + st48: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof48 + } + st_case_48: + if lex.data[(lex.p)] == 58 { + goto st49 + } + goto tr36 + st49: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof49 + } + st_case_49: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st50 + } + goto tr36 + st50: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof50 + } + st_case_50: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr54 + } + goto tr36 + tr54: +//line NONE:1 + lex.te = (lex.p) + 1 + + goto st176 + st176: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof176 + } + st_case_176: +//line lex.go:1952 + switch lex.data[(lex.p)] { + case 43: + goto st51 + case 45: + goto st51 + case 46: + goto st55 + } + goto tr222 + st51: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof51 + } + st_case_51: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st52 + } + goto tr55 + st52: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof52 + } + st_case_52: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st53 + } + goto tr55 + st53: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof53 + } + st_case_53: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st54 + } + goto tr55 + st54: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof54 + } + st_case_54: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr59 + } + goto tr55 + tr59: +//line NONE:1 + lex.te = (lex.p) + 1 + + goto st177 + st177: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof177 + } + st_case_177: +//line lex.go:2008 + if lex.data[(lex.p)] == 46 { + goto st55 + } + goto tr222 + st55: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof55 + } + st_case_55: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st178 + } + goto tr55 + st178: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof178 + } + st_case_178: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st178 + } + goto tr222 + st179: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof179 + } + st_case_179: + switch { + case lex.data[(lex.p)] > 55: + if 56 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st180 + } + case lex.data[(lex.p)] >= 48: + goto st179 + } + goto tr201 + st180: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof180 + } + st_case_180: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st180 + } + goto tr201 + tr218: +//line NONE:1 + lex.te = (lex.p) + 1 + + goto st181 + st181: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof181 + } + st_case_181: +//line lex.go:2064 + switch lex.data[(lex.p)] { + case 45: + goto st37 + case 47: + goto st37 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st180 + } + goto tr201 + tr216: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:70 + lex.act = 3 + goto st182 + st182: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof182 + } + st_case_182: +//line lex.go:2087 + if lex.data[(lex.p)] == 46 { + goto st33 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr218 + } + goto tr201 + st56: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof56 + } + st_case_56: + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st57 + } + case lex.data[(lex.p)] > 70: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 102 { + goto st57 + } + default: + goto st57 + } + goto tr9 + st57: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof57 + } + st_case_57: + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st58 + } + case lex.data[(lex.p)] > 70: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 102 { + goto st58 + } + default: + goto st58 + } + goto tr9 + st58: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof58 + } + st_case_58: + if lex.data[(lex.p)] == 58 { + goto st59 + } + goto tr9 + st59: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof59 + } + st_case_59: + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st60 + } + case lex.data[(lex.p)] > 70: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 102 { + goto st60 + } + default: + goto st60 + } + goto tr9 + st60: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof60 + } + st_case_60: + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st61 + } + case lex.data[(lex.p)] > 70: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 102 { + goto st61 + } + default: + goto st61 + } + goto tr9 + st61: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof61 + } + st_case_61: + if lex.data[(lex.p)] == 58 { + goto st62 + } + goto tr9 + st62: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof62 + } + st_case_62: + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st63 + } + case lex.data[(lex.p)] > 70: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 102 { + goto st63 + } + default: + goto st63 + } + goto tr9 + st63: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof63 + } + st_case_63: + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st64 + } + case lex.data[(lex.p)] > 70: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 102 { + goto st64 + } + default: + goto st64 + } + goto tr9 + st64: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof64 + } + st_case_64: + if lex.data[(lex.p)] == 58 { + goto st65 + } + goto tr9 + st65: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof65 + } + st_case_65: + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st66 + } + case lex.data[(lex.p)] > 70: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 102 { + goto st66 + } + default: + goto st66 + } + goto tr9 + st66: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof66 + } + st_case_66: + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st67 + } + case lex.data[(lex.p)] > 70: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 102 { + goto st67 + } + default: + goto st67 + } + goto tr9 + st67: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof67 + } + st_case_67: + if lex.data[(lex.p)] == 58 { + goto st68 + } + goto tr9 + st68: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof68 + } + st_case_68: + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st69 + } + case lex.data[(lex.p)] > 70: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 102 { + goto st69 + } + default: + goto st69 + } + goto tr9 + st69: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof69 + } + st_case_69: + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr74 + } + case lex.data[(lex.p)] > 70: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 102 { + goto tr74 + } + default: + goto tr74 + } + goto tr9 + tr204: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:70 + lex.act = 3 + goto st183 + st183: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof183 + } + st_case_183: +//line lex.go:2323 + switch lex.data[(lex.p)] { + case 46: + goto st33 + case 58: + goto st56 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr216 + } + goto tr201 + st70: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof70 + } + st_case_70: + if lex.data[(lex.p)] == 58 { + goto st56 + } + goto tr9 + st71: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof71 + } + st_case_71: + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st184 + } + case lex.data[(lex.p)] > 70: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 102 { + goto st184 + } + default: + goto st184 + } + goto tr36 + st184: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof184 + } + st_case_184: + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st184 + } + case lex.data[(lex.p)] > 70: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 102 { + goto st184 + } + default: + goto st184 + } + goto tr225 + tr178: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:70 + lex.act = 3 + goto st185 + st185: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof185 + } + st_case_185: +//line lex.go:2391 + if lex.data[(lex.p)] == 46 { + goto st166 + } + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr204 + } + case lex.data[(lex.p)] > 70: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 102 { + goto st70 + } + default: + goto st70 + } + goto tr201 + st72: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof72 + } + st_case_72: + switch lex.data[(lex.p)] { + case 46: + goto st73 + case 60: + goto tr78 + case 117: + goto st13 + } + goto st0 + st73: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof73 + } + st_case_73: + if lex.data[(lex.p)] == 46 { + goto st74 + } + goto st0 + st74: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof74 + } + st_case_74: + if lex.data[(lex.p)] == 46 { + goto st75 + } + goto st0 + st75: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof75 + } + st_case_75: + if lex.data[(lex.p)] == 32 { + goto st76 + } + goto st0 + st76: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof76 + } + st_case_76: + switch lex.data[(lex.p)] { + case 39: + goto st77 + case 58: + goto st77 + case 114: + goto st102 + } + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st87 + } + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st77 + } + default: + goto st77 + } + goto st0 + st77: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof77 + } + st_case_77: + switch lex.data[(lex.p)] { + case 32: + goto st78 + case 39: + goto st77 + case 42: + goto st77 + case 95: + goto st77 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st77 + } + case lex.data[(lex.p)] > 58: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st77 + } + case lex.data[(lex.p)] >= 65: + goto st77 + } + default: + goto st77 + } + goto st0 + st78: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof78 + } + st_case_78: + if lex.data[(lex.p)] == 114 { + goto st79 + } + goto st0 + st79: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof79 + } + st_case_79: + if lex.data[(lex.p)] == 101 { + goto st80 + } + goto st0 + st80: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof80 + } + st_case_80: + if lex.data[(lex.p)] == 115 { + goto st81 + } + goto st0 + st81: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof81 + } + st_case_81: + if lex.data[(lex.p)] == 117 { + goto st82 + } + goto st0 + st82: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof82 + } + st_case_82: + if lex.data[(lex.p)] == 109 { + goto st83 + } + goto st0 + st83: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof83 + } + st_case_83: + if lex.data[(lex.p)] == 101 { + goto st84 + } + goto st0 + st84: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof84 + } + st_case_84: + if lex.data[(lex.p)] == 100 { + goto st85 + } + goto st0 + st85: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof85 + } + st_case_85: + if lex.data[(lex.p)] == 62 { + goto tr93 + } + goto st0 + tr93: +//line NONE:1 + lex.te = (lex.p) + 1 + + goto st186 + st186: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof186 + } + st_case_186: +//line lex.go:2590 + if lex.data[(lex.p)] == 32 { + goto st86 + } + goto tr226 + st86: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof86 + } + st_case_86: + if lex.data[(lex.p)] == 44 { + goto tr95 + } + goto tr94 + st87: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof87 + } + st_case_87: + if lex.data[(lex.p)] == 46 { + goto st88 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st100 + } + goto st0 + st88: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof88 + } + st_case_88: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st89 + } + goto st0 + st89: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof89 + } + st_case_89: + if lex.data[(lex.p)] == 46 { + goto st90 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st98 + } + goto st0 + st90: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof90 + } + st_case_90: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st91 + } + goto st0 + st91: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof91 + } + st_case_91: + if lex.data[(lex.p)] == 46 { + goto st92 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st96 + } + goto st0 + st92: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof92 + } + st_case_92: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st93 + } + goto st0 + st93: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof93 + } + st_case_93: + switch lex.data[(lex.p)] { + case 32: + goto st78 + case 39: + goto st77 + case 58: + goto st77 + } + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st94 + } + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st77 + } + default: + goto st77 + } + goto st0 + st94: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof94 + } + st_case_94: + switch lex.data[(lex.p)] { + case 32: + goto st78 + case 39: + goto st77 + case 46: + goto st88 + case 58: + goto st77 + } + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st95 + } + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st77 + } + default: + goto st77 + } + goto st0 + st95: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof95 + } + st_case_95: + switch lex.data[(lex.p)] { + case 32: + goto st78 + case 39: + goto st77 + case 46: + goto st88 + case 58: + goto st77 + } + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st87 + } + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st77 + } + default: + goto st77 + } + goto st0 + st96: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof96 + } + st_case_96: + if lex.data[(lex.p)] == 46 { + goto st92 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st97 + } + goto st0 + st97: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof97 + } + st_case_97: + if lex.data[(lex.p)] == 46 { + goto st92 + } + goto st0 + st98: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof98 + } + st_case_98: + if lex.data[(lex.p)] == 46 { + goto st90 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st99 + } + goto st0 + st99: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof99 + } + st_case_99: + if lex.data[(lex.p)] == 46 { + goto st90 + } + goto st0 + st100: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof100 + } + st_case_100: + if lex.data[(lex.p)] == 46 { + goto st88 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st101 + } + goto st0 + st101: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof101 + } + st_case_101: + if lex.data[(lex.p)] == 46 { + goto st88 + } + goto st0 + st102: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof102 + } + st_case_102: + switch lex.data[(lex.p)] { + case 32: + goto st78 + case 39: + goto st77 + case 42: + goto st77 + case 95: + goto st77 + case 101: + goto st103 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st77 + } + case lex.data[(lex.p)] > 58: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st77 + } + case lex.data[(lex.p)] >= 65: + goto st77 + } + default: + goto st77 + } + goto st0 + st103: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof103 + } + st_case_103: + switch lex.data[(lex.p)] { + case 32: + goto st78 + case 39: + goto st77 + case 42: + goto st77 + case 95: + goto st77 + case 115: + goto st104 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st77 + } + case lex.data[(lex.p)] > 58: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st77 + } + case lex.data[(lex.p)] >= 65: + goto st77 + } + default: + goto st77 + } + goto st0 + st104: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof104 + } + st_case_104: + switch lex.data[(lex.p)] { + case 32: + goto st78 + case 39: + goto st77 + case 42: + goto st77 + case 95: + goto st77 + case 117: + goto st105 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st77 + } + case lex.data[(lex.p)] > 58: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st77 + } + case lex.data[(lex.p)] >= 65: + goto st77 + } + default: + goto st77 + } + goto st0 + st105: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof105 + } + st_case_105: + switch lex.data[(lex.p)] { + case 32: + goto st78 + case 39: + goto st77 + case 42: + goto st77 + case 95: + goto st77 + case 109: + goto st106 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st77 + } + case lex.data[(lex.p)] > 58: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st77 + } + case lex.data[(lex.p)] >= 65: + goto st77 + } + default: + goto st77 + } + goto st0 + st106: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof106 + } + st_case_106: + switch lex.data[(lex.p)] { + case 32: + goto st78 + case 39: + goto st77 + case 42: + goto st77 + case 95: + goto st77 + case 105: + goto st107 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st77 + } + case lex.data[(lex.p)] > 58: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st77 + } + case lex.data[(lex.p)] >= 65: + goto st77 + } + default: + goto st77 + } + goto st0 + st107: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof107 + } + st_case_107: + switch lex.data[(lex.p)] { + case 32: + goto st78 + case 39: + goto st77 + case 42: + goto st77 + case 95: + goto st77 + case 110: + goto st108 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st77 + } + case lex.data[(lex.p)] > 58: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st77 + } + case lex.data[(lex.p)] >= 65: + goto st77 + } + default: + goto st77 + } + goto st0 + st108: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof108 + } + st_case_108: + switch lex.data[(lex.p)] { + case 32: + goto st78 + case 39: + goto st77 + case 42: + goto st77 + case 95: + goto st77 + case 103: + goto st109 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st77 + } + case lex.data[(lex.p)] > 58: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st77 + } + case lex.data[(lex.p)] >= 65: + goto st77 + } + default: + goto st77 + } + goto st0 + st109: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof109 + } + st_case_109: + switch lex.data[(lex.p)] { + case 32: + goto st110 + case 39: + goto st77 + case 42: + goto st77 + case 95: + goto st77 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st77 + } + case lex.data[(lex.p)] > 58: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st77 + } + case lex.data[(lex.p)] >= 65: + goto st77 + } + default: + goto st77 + } + goto st0 + st110: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof110 + } + st_case_110: + switch lex.data[(lex.p)] { + case 39: + goto st111 + case 58: + goto st111 + case 114: + goto st148 + } + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st133 + } + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st111 + } + default: + goto st111 + } + goto st0 + st111: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof111 + } + st_case_111: + switch lex.data[(lex.p)] { + case 32: + goto st112 + case 39: + goto st111 + case 42: + goto st111 + case 95: + goto st111 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st111 + } + case lex.data[(lex.p)] > 58: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st111 + } + default: + goto st111 + } + goto st0 + st112: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof112 + } + st_case_112: + switch lex.data[(lex.p)] { + case 39: + goto st113 + case 58: + goto st113 + } + switch { + case lex.data[(lex.p)] < 65: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st118 + } + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st113 + } + default: + goto st113 + } + goto st0 + st113: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof113 + } + st_case_113: + switch lex.data[(lex.p)] { + case 32: + goto st114 + case 39: + goto st113 + case 42: + goto st113 + case 95: + goto st113 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st113 + } + case lex.data[(lex.p)] > 58: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st113 + } + default: + goto st113 + } + goto st0 + st114: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof114 + } + st_case_114: + if lex.data[(lex.p)] == 46 { + goto st115 + } + goto st0 + st115: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof115 + } + st_case_115: + if lex.data[(lex.p)] == 46 { + goto st116 + } + goto st0 + st116: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof116 + } + st_case_116: + if lex.data[(lex.p)] == 46 { + goto st117 + } + goto st0 + st117: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof117 + } + st_case_117: + if lex.data[(lex.p)] == 62 { + goto tr95 + } + goto st0 + st118: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof118 + } + st_case_118: + if lex.data[(lex.p)] == 46 { + goto st119 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st131 + } + goto st0 + st119: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof119 + } + st_case_119: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st120 + } + goto st0 + st120: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof120 + } + st_case_120: + if lex.data[(lex.p)] == 46 { + goto st121 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st129 + } + goto st0 + st121: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof121 + } + st_case_121: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st122 + } + goto st0 + st122: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof122 + } + st_case_122: + if lex.data[(lex.p)] == 46 { + goto st123 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st127 + } + goto st0 + st123: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof123 + } + st_case_123: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st124 + } + goto st0 + st124: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof124 + } + st_case_124: + if lex.data[(lex.p)] == 32 { + goto st114 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st125 + } + goto st0 + st125: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof125 + } + st_case_125: + if lex.data[(lex.p)] == 32 { + goto st114 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st126 + } + goto st0 + st126: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof126 + } + st_case_126: + if lex.data[(lex.p)] == 32 { + goto st114 + } + goto st0 + st127: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof127 + } + st_case_127: + if lex.data[(lex.p)] == 46 { + goto st123 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st128 + } + goto st0 + st128: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof128 + } + st_case_128: + if lex.data[(lex.p)] == 46 { + goto st123 + } + goto st0 + st129: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof129 + } + st_case_129: + if lex.data[(lex.p)] == 46 { + goto st121 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st130 + } + goto st0 + st130: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof130 + } + st_case_130: + if lex.data[(lex.p)] == 46 { + goto st121 + } + goto st0 + st131: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof131 + } + st_case_131: + if lex.data[(lex.p)] == 46 { + goto st119 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st132 + } + goto st0 + st132: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof132 + } + st_case_132: + if lex.data[(lex.p)] == 46 { + goto st119 + } + goto st0 + st133: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof133 + } + st_case_133: + if lex.data[(lex.p)] == 46 { + goto st134 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st146 + } + goto st0 + st134: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof134 + } + st_case_134: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st135 + } + goto st0 + st135: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof135 + } + st_case_135: + if lex.data[(lex.p)] == 46 { + goto st136 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st144 + } + goto st0 + st136: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof136 + } + st_case_136: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st137 + } + goto st0 + st137: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof137 + } + st_case_137: + if lex.data[(lex.p)] == 46 { + goto st138 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st142 + } + goto st0 + st138: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof138 + } + st_case_138: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st139 + } + goto st0 + st139: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof139 + } + st_case_139: + if lex.data[(lex.p)] == 32 { + goto st112 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st140 + } + goto st0 + st140: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof140 + } + st_case_140: + if lex.data[(lex.p)] == 32 { + goto st112 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st141 + } + goto st0 + st141: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof141 + } + st_case_141: + if lex.data[(lex.p)] == 32 { + goto st112 + } + goto st0 + st142: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof142 + } + st_case_142: + if lex.data[(lex.p)] == 46 { + goto st138 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st143 + } + goto st0 + st143: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof143 + } + st_case_143: + if lex.data[(lex.p)] == 46 { + goto st138 + } + goto st0 + st144: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof144 + } + st_case_144: + if lex.data[(lex.p)] == 46 { + goto st136 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st145 + } + goto st0 + st145: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof145 + } + st_case_145: + if lex.data[(lex.p)] == 46 { + goto st136 + } + goto st0 + st146: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof146 + } + st_case_146: + if lex.data[(lex.p)] == 46 { + goto st134 + } + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st147 + } + goto st0 + st147: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof147 + } + st_case_147: + if lex.data[(lex.p)] == 46 { + goto st134 + } + goto st0 + st148: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof148 + } + st_case_148: + switch lex.data[(lex.p)] { + case 32: + goto st112 + case 39: + goto st111 + case 42: + goto st111 + case 95: + goto st111 + case 101: + goto st149 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st111 + } + case lex.data[(lex.p)] > 58: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st111 + } + default: + goto st111 + } + goto st0 + st149: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof149 + } + st_case_149: + switch lex.data[(lex.p)] { + case 32: + goto st112 + case 39: + goto st111 + case 42: + goto st111 + case 95: + goto st111 + case 115: + goto st150 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st111 + } + case lex.data[(lex.p)] > 58: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st111 + } + default: + goto st111 + } + goto st0 + st150: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof150 + } + st_case_150: + switch lex.data[(lex.p)] { + case 32: + goto st112 + case 39: + goto st111 + case 42: + goto st111 + case 95: + goto st111 + case 117: + goto st151 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st111 + } + case lex.data[(lex.p)] > 58: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st111 + } + default: + goto st111 + } + goto st0 + st151: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof151 + } + st_case_151: + switch lex.data[(lex.p)] { + case 32: + goto st112 + case 39: + goto st111 + case 42: + goto st111 + case 95: + goto st111 + case 109: + goto st152 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st111 + } + case lex.data[(lex.p)] > 58: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st111 + } + default: + goto st111 + } + goto st0 + st152: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof152 + } + st_case_152: + switch lex.data[(lex.p)] { + case 32: + goto st112 + case 39: + goto st111 + case 42: + goto st111 + case 95: + goto st111 + case 101: + goto st153 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st111 + } + case lex.data[(lex.p)] > 58: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st111 + } + default: + goto st111 + } + goto st0 + st153: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof153 + } + st_case_153: + switch lex.data[(lex.p)] { + case 32: + goto st112 + case 39: + goto st111 + case 42: + goto st111 + case 95: + goto st111 + case 100: + goto st154 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st111 + } + case lex.data[(lex.p)] > 58: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st111 + } + default: + goto st111 + } + goto st0 + st154: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof154 + } + st_case_154: + switch lex.data[(lex.p)] { + case 32: + goto st112 + case 39: + goto st111 + case 42: + goto st111 + case 62: + goto tr93 + case 95: + goto st111 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st111 + } + case lex.data[(lex.p)] > 58: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st111 + } + default: + goto st111 + } + goto st0 + st187: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof187 + } + st_case_187: + switch lex.data[(lex.p)] { + case 62: + goto tr229 + case 64: + goto tr230 + } + goto tr228 + st155: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof155 + } + st_case_155: + if lex.data[(lex.p)] == 62 { + goto tr162 + } + goto st0 + st188: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof188 + } + st_case_188: + switch lex.data[(lex.p)] { + case 39: + goto tr231 + case 42: + goto st160 + case 58: + goto st160 + case 95: + goto tr231 + } + switch { + case lex.data[(lex.p)] < 65: + switch { + case lex.data[(lex.p)] > 46: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st190 + } + case lex.data[(lex.p)] >= 45: + goto st160 + } + case lex.data[(lex.p)] > 70: + switch { + case lex.data[(lex.p)] < 97: + if 71 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 90 { + goto tr10 + } + case lex.data[(lex.p)] > 102: + if 103 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + default: + goto st206 + } + default: + goto tr233 + } + goto tr194 + tr231: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:76 + lex.act = 9 + goto st189 + tr185: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:78 + lex.act = 11 + goto st189 + st189: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof189 + } + st_case_189: +//line lex.go:3842 + switch lex.data[(lex.p)] { + case 39: + goto tr231 + case 42: + goto st160 + case 58: + goto st160 + case 95: + goto tr231 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st160 + } + case lex.data[(lex.p)] > 57: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + case lex.data[(lex.p)] >= 65: + goto tr10 + } + default: + goto tr231 + } + goto tr9 + st190: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof190 + } + st_case_190: + switch lex.data[(lex.p)] { + case 39: + goto tr231 + case 42: + goto st160 + case 58: + goto tr236 + case 95: + goto tr231 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st160 + } + case lex.data[(lex.p)] > 57: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + case lex.data[(lex.p)] >= 65: + goto tr10 + } + default: + goto tr231 + } + goto tr235 + tr236: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:78 + lex.act = 11 + goto st191 + st191: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof191 + } + st_case_191: +//line lex.go:3916 + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 58: + goto st160 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 65: + switch { + case lex.data[(lex.p)] > 46: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr237 + } + case lex.data[(lex.p)] >= 45: + goto st160 + } + case lex.data[(lex.p)] > 70: + switch { + case lex.data[(lex.p)] > 102: + if 103 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + case lex.data[(lex.p)] >= 97: + goto tr237 + } + default: + goto st57 + } + goto tr194 + tr237: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:78 + lex.act = 11 + goto st192 + st192: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof192 + } + st_case_192: +//line lex.go:3962 + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 58: + goto st160 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 65: + switch { + case lex.data[(lex.p)] > 46: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st193 + } + case lex.data[(lex.p)] >= 45: + goto st160 + } + case lex.data[(lex.p)] > 70: + switch { + case lex.data[(lex.p)] > 102: + if 103 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + case lex.data[(lex.p)] >= 97: + goto st193 + } + default: + goto st58 + } + goto tr194 + st193: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof193 + } + st_case_193: + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 58: + goto tr239 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st160 + } + case lex.data[(lex.p)] > 57: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + default: + goto st160 + } + goto tr194 + tr239: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:78 + lex.act = 11 + goto st194 + st194: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof194 + } + st_case_194: +//line lex.go:4036 + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 58: + goto st160 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 65: + switch { + case lex.data[(lex.p)] > 46: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr240 + } + case lex.data[(lex.p)] >= 45: + goto st160 + } + case lex.data[(lex.p)] > 70: + switch { + case lex.data[(lex.p)] > 102: + if 103 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + case lex.data[(lex.p)] >= 97: + goto tr240 + } + default: + goto st60 + } + goto tr194 + tr240: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:78 + lex.act = 11 + goto st195 + st195: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof195 + } + st_case_195: +//line lex.go:4082 + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 58: + goto st160 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 65: + switch { + case lex.data[(lex.p)] > 46: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st196 + } + case lex.data[(lex.p)] >= 45: + goto st160 + } + case lex.data[(lex.p)] > 70: + switch { + case lex.data[(lex.p)] > 102: + if 103 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + case lex.data[(lex.p)] >= 97: + goto st196 + } + default: + goto st61 + } + goto tr194 + st196: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof196 + } + st_case_196: + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 58: + goto tr242 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st160 + } + case lex.data[(lex.p)] > 57: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + default: + goto st160 + } + goto tr194 + tr242: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:78 + lex.act = 11 + goto st197 + st197: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof197 + } + st_case_197: +//line lex.go:4156 + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 58: + goto st160 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 65: + switch { + case lex.data[(lex.p)] > 46: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr243 + } + case lex.data[(lex.p)] >= 45: + goto st160 + } + case lex.data[(lex.p)] > 70: + switch { + case lex.data[(lex.p)] > 102: + if 103 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + case lex.data[(lex.p)] >= 97: + goto tr243 + } + default: + goto st63 + } + goto tr194 + tr243: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:78 + lex.act = 11 + goto st198 + st198: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof198 + } + st_case_198: +//line lex.go:4202 + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 58: + goto st160 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 65: + switch { + case lex.data[(lex.p)] > 46: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st199 + } + case lex.data[(lex.p)] >= 45: + goto st160 + } + case lex.data[(lex.p)] > 70: + switch { + case lex.data[(lex.p)] > 102: + if 103 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + case lex.data[(lex.p)] >= 97: + goto st199 + } + default: + goto st64 + } + goto tr194 + st199: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof199 + } + st_case_199: + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 58: + goto tr245 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st160 + } + case lex.data[(lex.p)] > 57: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + default: + goto st160 + } + goto tr194 + tr245: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:78 + lex.act = 11 + goto st200 + st200: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof200 + } + st_case_200: +//line lex.go:4276 + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 58: + goto st160 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 65: + switch { + case lex.data[(lex.p)] > 46: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto tr246 + } + case lex.data[(lex.p)] >= 45: + goto st160 + } + case lex.data[(lex.p)] > 70: + switch { + case lex.data[(lex.p)] > 102: + if 103 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + case lex.data[(lex.p)] >= 97: + goto tr246 + } + default: + goto st66 + } + goto tr194 + tr246: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:78 + lex.act = 11 + goto st201 + st201: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof201 + } + st_case_201: +//line lex.go:4322 + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 58: + goto st160 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 65: + switch { + case lex.data[(lex.p)] > 46: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st202 + } + case lex.data[(lex.p)] >= 45: + goto st160 + } + case lex.data[(lex.p)] > 70: + switch { + case lex.data[(lex.p)] > 102: + if 103 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + case lex.data[(lex.p)] >= 97: + goto st202 + } + default: + goto st67 + } + goto tr194 + st202: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof202 + } + st_case_202: + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 58: + goto tr248 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st160 + } + case lex.data[(lex.p)] > 57: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + default: + goto st160 + } + goto tr194 + tr248: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:78 + lex.act = 11 + goto st203 + st203: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof203 + } + st_case_203: +//line lex.go:4396 + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 58: + goto st160 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 65: + switch { + case lex.data[(lex.p)] > 46: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st204 + } + case lex.data[(lex.p)] >= 45: + goto st160 + } + case lex.data[(lex.p)] > 70: + switch { + case lex.data[(lex.p)] > 102: + if 103 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + case lex.data[(lex.p)] >= 97: + goto st204 + } + default: + goto st69 + } + goto tr194 + st204: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof204 + } + st_case_204: + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st160 + } + case lex.data[(lex.p)] > 58: + switch { + case lex.data[(lex.p)] > 70: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + case lex.data[(lex.p)] >= 65: + goto tr74 + } + default: + goto st160 + } + goto tr194 + tr233: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:76 + lex.act = 9 + goto st205 + st205: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof205 + } + st_case_205: +//line lex.go:4473 + switch lex.data[(lex.p)] { + case 39: + goto tr10 + case 58: + goto st56 + case 95: + goto tr10 + } + switch { + case lex.data[(lex.p)] > 57: + if 65 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 90 { + goto tr10 + } + case lex.data[(lex.p)] >= 48: + goto tr10 + } + goto tr235 + st206: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof206 + } + st_case_206: + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 58: + goto tr236 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st160 + } + case lex.data[(lex.p)] > 57: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + default: + goto st160 + } + goto tr194 + st207: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof207 + } + st_case_207: + switch lex.data[(lex.p)] { + case 39: + goto tr231 + case 42: + goto st160 + case 58: + goto st160 + case 85: + goto st208 + case 95: + goto tr231 + } + switch { + case lex.data[(lex.p)] < 48: + if 45 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 46 { + goto st160 + } + case lex.data[(lex.p)] > 57: + switch { + case lex.data[(lex.p)] > 90: + if 97 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + case lex.data[(lex.p)] >= 65: + goto tr10 + } + default: + goto tr231 + } + goto tr194 + st208: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof208 + } + st_case_208: + switch lex.data[(lex.p)] { + case 39: + goto tr10 + case 76: + goto st209 + case 95: + goto tr10 + } + switch { + case lex.data[(lex.p)] > 57: + if 65 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 90 { + goto tr10 + } + case lex.data[(lex.p)] >= 48: + goto tr10 + } + goto tr235 + st209: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof209 + } + st_case_209: + switch lex.data[(lex.p)] { + case 39: + goto tr10 + case 76: + goto tr252 + case 95: + goto tr10 + } + switch { + case lex.data[(lex.p)] > 57: + if 65 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 90 { + goto tr10 + } + case lex.data[(lex.p)] >= 48: + goto tr10 + } + goto tr235 + st156: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof156 + } + st_case_156: + switch lex.data[(lex.p)] { + case 39: + goto st156 + case 95: + goto st156 + } + if 65 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 90 { + goto st9 + } + goto st0 + tr189: +//line NONE:1 + lex.te = (lex.p) + 1 + +//line straceLex.rl:78 + lex.act = 11 + goto st210 + st210: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof210 + } + st_case_210: +//line lex.go:4625 + switch lex.data[(lex.p)] { + case 39: + goto st160 + case 42: + goto st160 + case 58: + goto st160 + case 95: + goto st160 + } + switch { + case lex.data[(lex.p)] < 65: + switch { + case lex.data[(lex.p)] > 46: + if 48 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 57 { + goto st206 + } + case lex.data[(lex.p)] >= 45: + goto st160 + } + case lex.data[(lex.p)] > 70: + switch { + case lex.data[(lex.p)] > 102: + if 103 <= lex.data[(lex.p)] && lex.data[(lex.p)] <= 122 { + goto st160 + } + case lex.data[(lex.p)] >= 97: + goto st206 + } + default: + goto st70 + } + goto tr194 + tr253: +//line straceLex.rl:65 + lex.te = (lex.p) + 1 + + goto st211 + tr255: +//line straceLex.rl:65 + lex.te = (lex.p) + (lex.p)-- + + goto st211 + tr256: +//line straceLex.rl:66 + lex.te = (lex.p) + 1 + { + { + goto st157 + } + } + goto st211 + st211: +//line NONE:1 + lex.ts = 0 + + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof211 + } + st_case_211: +//line NONE:1 + lex.ts = (lex.p) + +//line lex.go:4686 + if lex.data[(lex.p)] == 42 { + goto st212 + } + goto tr253 + st212: + if (lex.p)++; (lex.p) == (lex.pe) { + goto _test_eof212 + } + st_case_212: + if lex.data[(lex.p)] == 47 { + goto tr256 + } + goto tr255 + st_out: + _test_eof157: + lex.cs = 157 + goto _test_eof + _test_eof1: + lex.cs = 1 + goto _test_eof + _test_eof2: + lex.cs = 2 + goto _test_eof + _test_eof158: + lex.cs = 158 + goto _test_eof + _test_eof3: + lex.cs = 3 + goto _test_eof + _test_eof4: + lex.cs = 4 + goto _test_eof + _test_eof5: + lex.cs = 5 + goto _test_eof + _test_eof6: + lex.cs = 6 + goto _test_eof + _test_eof7: + lex.cs = 7 + goto _test_eof + _test_eof8: + lex.cs = 8 + goto _test_eof + _test_eof159: + lex.cs = 159 + goto _test_eof + _test_eof160: + lex.cs = 160 + goto _test_eof + _test_eof9: + lex.cs = 9 + goto _test_eof + _test_eof161: + lex.cs = 161 + goto _test_eof + _test_eof162: + lex.cs = 162 + goto _test_eof + _test_eof10: + lex.cs = 10 + goto _test_eof + _test_eof11: + lex.cs = 11 + goto _test_eof + _test_eof12: + lex.cs = 12 + goto _test_eof + _test_eof13: + lex.cs = 13 + goto _test_eof + _test_eof14: + lex.cs = 14 + goto _test_eof + _test_eof15: + lex.cs = 15 + goto _test_eof + _test_eof16: + lex.cs = 16 + goto _test_eof + _test_eof17: + lex.cs = 17 + goto _test_eof + _test_eof18: + lex.cs = 18 + goto _test_eof + _test_eof19: + lex.cs = 19 + goto _test_eof + _test_eof20: + lex.cs = 20 + goto _test_eof + _test_eof21: + lex.cs = 21 + goto _test_eof + _test_eof22: + lex.cs = 22 + goto _test_eof + _test_eof23: + lex.cs = 23 + goto _test_eof + _test_eof24: + lex.cs = 24 + goto _test_eof + _test_eof25: + lex.cs = 25 + goto _test_eof + _test_eof26: + lex.cs = 26 + goto _test_eof + _test_eof163: + lex.cs = 163 + goto _test_eof + _test_eof27: + lex.cs = 27 + goto _test_eof + _test_eof164: + lex.cs = 164 + goto _test_eof + _test_eof165: + lex.cs = 165 + goto _test_eof + _test_eof166: + lex.cs = 166 + goto _test_eof + _test_eof167: + lex.cs = 167 + goto _test_eof + _test_eof28: + lex.cs = 28 + goto _test_eof + _test_eof29: + lex.cs = 29 + goto _test_eof + _test_eof30: + lex.cs = 30 + goto _test_eof + _test_eof168: + lex.cs = 168 + goto _test_eof + _test_eof169: + lex.cs = 169 + goto _test_eof + _test_eof31: + lex.cs = 31 + goto _test_eof + _test_eof32: + lex.cs = 32 + goto _test_eof + _test_eof170: + lex.cs = 170 + goto _test_eof + _test_eof171: + lex.cs = 171 + goto _test_eof + _test_eof172: + lex.cs = 172 + goto _test_eof + _test_eof173: + lex.cs = 173 + goto _test_eof + _test_eof33: + lex.cs = 33 + goto _test_eof + _test_eof34: + lex.cs = 34 + goto _test_eof + _test_eof35: + lex.cs = 35 + goto _test_eof + _test_eof36: + lex.cs = 36 + goto _test_eof + _test_eof174: + lex.cs = 174 + goto _test_eof + _test_eof175: + lex.cs = 175 + goto _test_eof + _test_eof37: + lex.cs = 37 + goto _test_eof + _test_eof38: + lex.cs = 38 + goto _test_eof + _test_eof39: + lex.cs = 39 + goto _test_eof + _test_eof40: + lex.cs = 40 + goto _test_eof + _test_eof41: + lex.cs = 41 + goto _test_eof + _test_eof42: + lex.cs = 42 + goto _test_eof + _test_eof43: + lex.cs = 43 + goto _test_eof + _test_eof44: + lex.cs = 44 + goto _test_eof + _test_eof45: + lex.cs = 45 + goto _test_eof + _test_eof46: + lex.cs = 46 + goto _test_eof + _test_eof47: + lex.cs = 47 + goto _test_eof + _test_eof48: + lex.cs = 48 + goto _test_eof + _test_eof49: + lex.cs = 49 + goto _test_eof + _test_eof50: + lex.cs = 50 + goto _test_eof + _test_eof176: + lex.cs = 176 + goto _test_eof + _test_eof51: + lex.cs = 51 + goto _test_eof + _test_eof52: + lex.cs = 52 + goto _test_eof + _test_eof53: + lex.cs = 53 + goto _test_eof + _test_eof54: + lex.cs = 54 + goto _test_eof + _test_eof177: + lex.cs = 177 + goto _test_eof + _test_eof55: + lex.cs = 55 + goto _test_eof + _test_eof178: + lex.cs = 178 + goto _test_eof + _test_eof179: + lex.cs = 179 + goto _test_eof + _test_eof180: + lex.cs = 180 + goto _test_eof + _test_eof181: + lex.cs = 181 + goto _test_eof + _test_eof182: + lex.cs = 182 + goto _test_eof + _test_eof56: + lex.cs = 56 + goto _test_eof + _test_eof57: + lex.cs = 57 + goto _test_eof + _test_eof58: + lex.cs = 58 + goto _test_eof + _test_eof59: + lex.cs = 59 + goto _test_eof + _test_eof60: + lex.cs = 60 + goto _test_eof + _test_eof61: + lex.cs = 61 + goto _test_eof + _test_eof62: + lex.cs = 62 + goto _test_eof + _test_eof63: + lex.cs = 63 + goto _test_eof + _test_eof64: + lex.cs = 64 + goto _test_eof + _test_eof65: + lex.cs = 65 + goto _test_eof + _test_eof66: + lex.cs = 66 + goto _test_eof + _test_eof67: + lex.cs = 67 + goto _test_eof + _test_eof68: + lex.cs = 68 + goto _test_eof + _test_eof69: + lex.cs = 69 + goto _test_eof + _test_eof183: + lex.cs = 183 + goto _test_eof + _test_eof70: + lex.cs = 70 + goto _test_eof + _test_eof71: + lex.cs = 71 + goto _test_eof + _test_eof184: + lex.cs = 184 + goto _test_eof + _test_eof185: + lex.cs = 185 + goto _test_eof + _test_eof72: + lex.cs = 72 + goto _test_eof + _test_eof73: + lex.cs = 73 + goto _test_eof + _test_eof74: + lex.cs = 74 + goto _test_eof + _test_eof75: + lex.cs = 75 + goto _test_eof + _test_eof76: + lex.cs = 76 + goto _test_eof + _test_eof77: + lex.cs = 77 + goto _test_eof + _test_eof78: + lex.cs = 78 + goto _test_eof + _test_eof79: + lex.cs = 79 + goto _test_eof + _test_eof80: + lex.cs = 80 + goto _test_eof + _test_eof81: + lex.cs = 81 + goto _test_eof + _test_eof82: + lex.cs = 82 + goto _test_eof + _test_eof83: + lex.cs = 83 + goto _test_eof + _test_eof84: + lex.cs = 84 + goto _test_eof + _test_eof85: + lex.cs = 85 + goto _test_eof + _test_eof186: + lex.cs = 186 + goto _test_eof + _test_eof86: + lex.cs = 86 + goto _test_eof + _test_eof87: + lex.cs = 87 + goto _test_eof + _test_eof88: + lex.cs = 88 + goto _test_eof + _test_eof89: + lex.cs = 89 + goto _test_eof + _test_eof90: + lex.cs = 90 + goto _test_eof + _test_eof91: + lex.cs = 91 + goto _test_eof + _test_eof92: + lex.cs = 92 + goto _test_eof + _test_eof93: + lex.cs = 93 + goto _test_eof + _test_eof94: + lex.cs = 94 + goto _test_eof + _test_eof95: + lex.cs = 95 + goto _test_eof + _test_eof96: + lex.cs = 96 + goto _test_eof + _test_eof97: + lex.cs = 97 + goto _test_eof + _test_eof98: + lex.cs = 98 + goto _test_eof + _test_eof99: + lex.cs = 99 + goto _test_eof + _test_eof100: + lex.cs = 100 + goto _test_eof + _test_eof101: + lex.cs = 101 + goto _test_eof + _test_eof102: + lex.cs = 102 + goto _test_eof + _test_eof103: + lex.cs = 103 + goto _test_eof + _test_eof104: + lex.cs = 104 + goto _test_eof + _test_eof105: + lex.cs = 105 + goto _test_eof + _test_eof106: + lex.cs = 106 + goto _test_eof + _test_eof107: + lex.cs = 107 + goto _test_eof + _test_eof108: + lex.cs = 108 + goto _test_eof + _test_eof109: + lex.cs = 109 + goto _test_eof + _test_eof110: + lex.cs = 110 + goto _test_eof + _test_eof111: + lex.cs = 111 + goto _test_eof + _test_eof112: + lex.cs = 112 + goto _test_eof + _test_eof113: + lex.cs = 113 + goto _test_eof + _test_eof114: + lex.cs = 114 + goto _test_eof + _test_eof115: + lex.cs = 115 + goto _test_eof + _test_eof116: + lex.cs = 116 + goto _test_eof + _test_eof117: + lex.cs = 117 + goto _test_eof + _test_eof118: + lex.cs = 118 + goto _test_eof + _test_eof119: + lex.cs = 119 + goto _test_eof + _test_eof120: + lex.cs = 120 + goto _test_eof + _test_eof121: + lex.cs = 121 + goto _test_eof + _test_eof122: + lex.cs = 122 + goto _test_eof + _test_eof123: + lex.cs = 123 + goto _test_eof + _test_eof124: + lex.cs = 124 + goto _test_eof + _test_eof125: + lex.cs = 125 + goto _test_eof + _test_eof126: + lex.cs = 126 + goto _test_eof + _test_eof127: + lex.cs = 127 + goto _test_eof + _test_eof128: + lex.cs = 128 + goto _test_eof + _test_eof129: + lex.cs = 129 + goto _test_eof + _test_eof130: + lex.cs = 130 + goto _test_eof + _test_eof131: + lex.cs = 131 + goto _test_eof + _test_eof132: + lex.cs = 132 + goto _test_eof + _test_eof133: + lex.cs = 133 + goto _test_eof + _test_eof134: + lex.cs = 134 + goto _test_eof + _test_eof135: + lex.cs = 135 + goto _test_eof + _test_eof136: + lex.cs = 136 + goto _test_eof + _test_eof137: + lex.cs = 137 + goto _test_eof + _test_eof138: + lex.cs = 138 + goto _test_eof + _test_eof139: + lex.cs = 139 + goto _test_eof + _test_eof140: + lex.cs = 140 + goto _test_eof + _test_eof141: + lex.cs = 141 + goto _test_eof + _test_eof142: + lex.cs = 142 + goto _test_eof + _test_eof143: + lex.cs = 143 + goto _test_eof + _test_eof144: + lex.cs = 144 + goto _test_eof + _test_eof145: + lex.cs = 145 + goto _test_eof + _test_eof146: + lex.cs = 146 + goto _test_eof + _test_eof147: + lex.cs = 147 + goto _test_eof + _test_eof148: + lex.cs = 148 + goto _test_eof + _test_eof149: + lex.cs = 149 + goto _test_eof + _test_eof150: + lex.cs = 150 + goto _test_eof + _test_eof151: + lex.cs = 151 + goto _test_eof + _test_eof152: + lex.cs = 152 + goto _test_eof + _test_eof153: + lex.cs = 153 + goto _test_eof + _test_eof154: + lex.cs = 154 + goto _test_eof + _test_eof187: + lex.cs = 187 + goto _test_eof + _test_eof155: + lex.cs = 155 + goto _test_eof + _test_eof188: + lex.cs = 188 + goto _test_eof + _test_eof189: + lex.cs = 189 + goto _test_eof + _test_eof190: + lex.cs = 190 + goto _test_eof + _test_eof191: + lex.cs = 191 + goto _test_eof + _test_eof192: + lex.cs = 192 + goto _test_eof + _test_eof193: + lex.cs = 193 + goto _test_eof + _test_eof194: + lex.cs = 194 + goto _test_eof + _test_eof195: + lex.cs = 195 + goto _test_eof + _test_eof196: + lex.cs = 196 + goto _test_eof + _test_eof197: + lex.cs = 197 + goto _test_eof + _test_eof198: + lex.cs = 198 + goto _test_eof + _test_eof199: + lex.cs = 199 + goto _test_eof + _test_eof200: + lex.cs = 200 + goto _test_eof + _test_eof201: + lex.cs = 201 + goto _test_eof + _test_eof202: + lex.cs = 202 + goto _test_eof + _test_eof203: + lex.cs = 203 + goto _test_eof + _test_eof204: + lex.cs = 204 + goto _test_eof + _test_eof205: + lex.cs = 205 + goto _test_eof + _test_eof206: + lex.cs = 206 + goto _test_eof + _test_eof207: + lex.cs = 207 + goto _test_eof + _test_eof208: + lex.cs = 208 + goto _test_eof + _test_eof209: + lex.cs = 209 + goto _test_eof + _test_eof156: + lex.cs = 156 + goto _test_eof + _test_eof210: + lex.cs = 210 + goto _test_eof + _test_eof211: + lex.cs = 211 + goto _test_eof + _test_eof212: + lex.cs = 212 + goto _test_eof + + _test_eof: + { + } + if (lex.p) == eof { + switch lex.cs { + case 158: + goto tr193 + case 159: + goto tr194 + case 160: + goto tr194 + case 9: + goto tr9 + case 161: + goto tr9 + case 162: + goto tr195 + case 10: + goto tr11 + case 11: + goto tr11 + case 12: + goto tr11 + case 13: + goto tr9 + case 14: + goto tr9 + case 15: + goto tr9 + case 16: + goto tr9 + case 17: + goto tr9 + case 18: + goto tr9 + case 19: + goto tr9 + case 20: + goto tr9 + case 21: + goto tr9 + case 22: + goto tr9 + case 23: + goto tr9 + case 24: + goto tr9 + case 25: + goto tr9 + case 26: + goto tr9 + case 163: + goto tr197 + case 164: + goto tr199 + case 165: + goto tr201 + case 166: + goto tr207 + case 167: + goto tr207 + case 28: + goto tr9 + case 29: + goto tr9 + case 30: + goto tr9 + case 168: + goto tr194 + case 169: + goto tr194 + case 31: + goto tr9 + case 32: + goto tr9 + case 170: + goto tr207 + case 171: + goto tr207 + case 172: + goto tr207 + case 173: + goto tr201 + case 33: + goto tr36 + case 34: + goto tr36 + case 35: + goto tr36 + case 36: + goto tr36 + case 174: + goto tr201 + case 175: + goto tr201 + case 37: + goto tr36 + case 38: + goto tr36 + case 39: + goto tr36 + case 40: + goto tr36 + case 41: + goto tr36 + case 42: + goto tr36 + case 43: + goto tr36 + case 44: + goto tr36 + case 45: + goto tr36 + case 46: + goto tr36 + case 47: + goto tr36 + case 48: + goto tr36 + case 49: + goto tr36 + case 50: + goto tr36 + case 176: + goto tr222 + case 51: + goto tr55 + case 52: + goto tr55 + case 53: + goto tr55 + case 54: + goto tr55 + case 177: + goto tr222 + case 55: + goto tr55 + case 178: + goto tr222 + case 179: + goto tr201 + case 180: + goto tr201 + case 181: + goto tr201 + case 182: + goto tr201 + case 56: + goto tr9 + case 57: + goto tr9 + case 58: + goto tr9 + case 59: + goto tr9 + case 60: + goto tr9 + case 61: + goto tr9 + case 62: + goto tr9 + case 63: + goto tr9 + case 64: + goto tr9 + case 65: + goto tr9 + case 66: + goto tr9 + case 67: + goto tr9 + case 68: + goto tr9 + case 69: + goto tr9 + case 183: + goto tr201 + case 70: + goto tr9 + case 71: + goto tr36 + case 184: + goto tr225 + case 185: + goto tr201 + case 186: + goto tr226 + case 86: + goto tr94 + case 187: + goto tr228 + case 188: + goto tr194 + case 189: + goto tr9 + case 190: + goto tr235 + case 191: + goto tr194 + case 192: + goto tr194 + case 193: + goto tr194 + case 194: + goto tr194 + case 195: + goto tr194 + case 196: + goto tr194 + case 197: + goto tr194 + case 198: + goto tr194 + case 199: + goto tr194 + case 200: + goto tr194 + case 201: + goto tr194 + case 202: + goto tr194 + case 203: + goto tr194 + case 204: + goto tr194 + case 205: + goto tr235 + case 206: + goto tr194 + case 207: + goto tr194 + case 208: + goto tr235 + case 209: + goto tr235 + case 210: + goto tr194 + case 212: + goto tr255 + } + } + + _out: + { + } + } + +//line straceLex.rl:111 + return tok +} + +func (lex *Stracelexer) Error(e string) { + fmt.Println("error:", e) +} + +func ParseString(s string) string { + var decoded []byte + var err error + var strippedStr string + strippedStr = strings.Replace(s, `\x`, "", -1) + strippedStr = strings.Replace(strippedStr, `"`, "", -1) + + if decoded, err = hex.DecodeString(strippedStr); err != nil { + log.Logf(2, "failed to decode string: %s, with error: %s", s, err.Error()) + decoded = []byte(strippedStr) + } + decoded = append(decoded, '\x00') + return string(decoded) +} diff --git a/tools/syz-trace2syz/parser/parser.go b/tools/syz-trace2syz/parser/parser.go new file mode 100644 index 000000000..e79cc5ac2 --- /dev/null +++ b/tools/syz-trace2syz/parser/parser.go @@ -0,0 +1,73 @@ +// Copyright 2018 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package parser + +import ( + "bufio" + "io/ioutil" + "strings" + + "github.com/google/syzkaller/pkg/log" +) + +const ( + maxBufferSize = 64 * 1024 * 1024 // maxBufferSize is maximum size for buffer + sysrestart = "ERESTART" // SYSRESTART corresponds to the error code of ERESTART. + signalPlus = "+++" // SignalPlus marks +++ + signalMinus = "---" // SignalPlus marks --- + noSuchProcess = "" // No such process error. Nothing worth parsing +) + +func parseSyscall(scanner *bufio.Scanner) (int, *Syscall) { + lex := newStraceLexer(scanner.Bytes()) + ret := StraceParse(lex) + return ret, lex.result +} + +func shouldSkip(line string) bool { + restart := strings.Contains(line, sysrestart) + signalPlus := strings.Contains(line, signalPlus) + signalMinus := strings.Contains(line, signalMinus) + noProcess := strings.Contains(line, noSuchProcess) + return restart || signalPlus || signalMinus || noProcess +} + +// ParseLoop parses each line of a strace file in a loop +func ParseLoop(data string) (tree *TraceTree) { + tree = NewTraceTree() + // Creating the process tree + buf := make([]byte, maxBufferSize) + scanner := bufio.NewScanner(strings.NewReader(data)) + scanner.Buffer(buf, maxBufferSize) + + for scanner.Scan() { + line := scanner.Text() + if shouldSkip(line) { + continue + } + log.Logf(4, "scanning call: %s", line) + ret, call := parseSyscall(scanner) + if call == nil || ret != 0 { + log.Fatalf("failed to parse line: %s", line) + } + tree.add(call) + } + if len(tree.Ptree) == 0 { + return nil + } + return +} + +// Parse parses a trace of system calls and returns an intermediate representation +func Parse(filename string) *TraceTree { + data, err := ioutil.ReadFile(filename) + if err != nil { + log.Fatalf("error reading file: %s", err.Error()) + } + tree := ParseLoop(string(data)) + if tree != nil { + tree.Filename = filename + } + return tree +} diff --git a/tools/syz-trace2syz/parser/parser_test.go b/tools/syz-trace2syz/parser/parser_test.go new file mode 100644 index 000000000..5304f4fa3 --- /dev/null +++ b/tools/syz-trace2syz/parser/parser_test.go @@ -0,0 +1,196 @@ +// Copyright 2018 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package parser + +import ( + "testing" + + _ "github.com/google/syzkaller/sys" +) + +func TestParseLoopBasic(t *testing.T) { + + tests := []string{ + `open() = 3 + fstat() = 0`, + `open() = 0x73ffddabc + fstat() = 0`, + `open() = -1 ENOSPEC (something) + fstat() = 0`, + `open( , + <... open resumed>) = 3 + fstat() = 0`, + `open( , + <... open resumed> , 2) = 3 + fstat() = 0`, + `open( + <... open resumed>) = 3 + fstat() = 0`, + `open( + <... open resumed>) = 0x44277ffff + fstat() = 0`, + `open( + <... open resumed>) = ? + fstat() = 0`, + `open( + <... open resumed>) = -1 FLAG (sdfjfjfjf) + fstat() = 0`, + `open(1, + <... open resumed> , 0x1|0x2) = -1 FLAG (sdfjfjfjf) + fstat() = 0`, + `open([0x1, 0x2], NULL, {tv_sec=5, tv_nsec=0}, 8 + <... rt_sigtimedwait resumed> ) = 10 (SIGUSR1) + fstat() = 0`, + `open(0, 536892418, {c_cc[VMIN]=1, c_cc[VTIME]=0} + <... open resumed> , 0x1|0x2) = -1 FLAG (sdfjfjfjf) + fstat() = 0`, + `open(-19) = 0 + fstat() = 0`, + `open(1 + 2) = 0 + fstat() = 0`, + `open(3 - 1) = 0 + fstat() = 0`, + `open(1075599392, 0x20000000) = -1 EBADF (Bad file descriptor) + fstat() = 0`, + `open() = -1 EIO (Input/output error) + fstat() = 0`, + `open(113->114) = -1 EIO (Input/output error) + fstat() = 0`, + } + + for _, test := range tests { + tree := ParseLoop(test) + if tree.RootPid != -1 { + t.Fatalf("Incorrect Root Pid: %d", tree.RootPid) + } + + calls := tree.TraceMap[tree.RootPid].Calls + if len(calls) != 2 { + t.Fatalf("expected 2 calls. Got %d instead", len(calls)) + } + if calls[0].CallName != "open" || calls[1].CallName != "fstat" { + t.Fatalf("call list should be open->fstat. Got %s->%s", calls[0].CallName, calls[1].CallName) + } + } +} + +func TestEvaluateExpressions(t *testing.T) { + type ExprTest struct { + line string + expectedEval uint64 + } + tests := []ExprTest{ + {"open(0x1) = 0", 1}, + {"open(1) = 0", 1}, + {"open(0x1|0x2) = 0", 3}, + {"open(0x1|2) = 0", 3}, + {"open(1 << 5) = 0", 32}, + {"open(1 << 5|1) = 0", 33}, + {"open(1 & 0) = 0", 0}, + {"open(1 + 2) = 0", 3}, + {"open(1-2) = 0", ^uint64(0)}, + {"open(4 >> 1) = 0", 2}, + } + for i, test := range tests { + tree := ParseLoop(test.line) + if tree.RootPid != -1 { + t.Fatalf("failed test: %d. Incorrect Root Pid: %d", i, tree.RootPid) + } + calls := tree.TraceMap[tree.RootPid].Calls + if len(calls) != 1 { + t.Fatalf("failed test: %d. Expected 1 call. Got %d instead", i, len(calls)) + } + arg, ok := calls[0].Args[0].(Constant) + if !ok { + t.Fatalf("first argument expected to be constant. Got: %s", arg.String()) + } + if arg.Val() != test.expectedEval { + t.Fatalf("expected %v != %v", test.expectedEval, arg.Val()) + } + } +} + +func TestParseLoopPid(t *testing.T) { + data := `1 open() = 3 + 1 fstat() = 0` + + tree := ParseLoop(data) + if tree.RootPid != 1 { + t.Fatalf("Incorrect Root Pid: %d", tree.RootPid) + } + + calls := tree.TraceMap[tree.RootPid].Calls + if len(calls) != 2 { + t.Fatalf("Expect 2 calls. Got %d instead", len(calls)) + } + if calls[0].CallName != "open" || calls[1].CallName != "fstat" { + t.Fatalf("call list should be open->fstat. Got %s->%s", calls[0].CallName, calls[1].CallName) + } +} + +func TestParseLoop1Child(t *testing.T) { + data1Child := `1 open() = 3 + 1 clone() = 2 + 2 read() = 16` + + tree := ParseLoop(data1Child) + if len(tree.Ptree) != 2 { + t.Fatalf("Incorrect Root Pid. Expected: 2, Got %d", tree.RootPid) + } + if tree.Ptree[tree.RootPid][0] != 2 { + t.Fatalf("Expected child to have pid: 2. Got %d", tree.Ptree[tree.RootPid][0]) + } else { + if len(tree.TraceMap[2].Calls) != 1 { + t.Fatalf("Child trace should have only 1 call. Got %d", len(tree.TraceMap[2].Calls)) + } + } +} + +func TestParseLoop2Childs(t *testing.T) { + data2Childs := `1 open() = 3 + 1 clone() = 2 + 2 read() = 16 + 1 clone() = 3 + 3 open() = 3` + tree := ParseLoop(data2Childs) + if len(tree.Ptree) != 3 { + t.Fatalf("Incorrect Root Pid. Expected: 3, Got %d", tree.RootPid) + } + if len(tree.Ptree[tree.RootPid]) != 2 { + t.Fatalf("Expected Pid 1 to have 2 children: Got %d", len(tree.Ptree[tree.RootPid])) + } +} + +func TestParseLoop1Grandchild(t *testing.T) { + data1Grandchild := `1 open() = 3 + 1 clone() = 2 + 2 clone() = 3 + 3 open() = 4` + tree := ParseLoop(data1Grandchild) + if len(tree.Ptree[tree.RootPid]) != 1 { + t.Fatalf("Expect RootPid to have 1 child. Got %d", tree.RootPid) + } + if len(tree.Ptree[2]) != 1 { + t.Fatalf("Incorrect Root Pid. Expected: 3, Got %d", tree.RootPid) + + } +} + +func TestParseGroupType(t *testing.T) { + type irTest struct { + test string + } + tests := []irTest{ + {`open({1, 2, 3}) = 0`}, + {`open([1, 2, 3]) = 0`}, + } + for _, test := range tests { + tree := ParseLoop(test.test) + call := tree.TraceMap[tree.RootPid].Calls[0] + _, ok := call.Args[0].(*GroupType) + if !ok { + t.Fatalf("Expected Group type. Got: %#v", call.Args[0]) + } + } +} diff --git a/tools/syz-trace2syz/parser/strace.go b/tools/syz-trace2syz/parser/strace.go new file mode 100644 index 000000000..7f6f3d0a8 --- /dev/null +++ b/tools/syz-trace2syz/parser/strace.go @@ -0,0 +1,983 @@ +// Code generated by goyacc -o strace.go -p Strace -v= strace.y. DO NOT EDIT. + +//line strace.y:2 + +// Copyright 2018 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// nolint +package parser + +import __yyfmt__ "fmt" + +//line strace.y:6 +//line strace.y:12 +type StraceSymType struct { + yys int + data string + val_int int64 + val_double float64 + val_ret_type int64 + val_uint uint64 + val_constant Constant + val_identifiers []*BufferType + val_buf_type *BufferType + val_group_type *GroupType + val_type IrType + val_types []IrType + val_syscall *Syscall +} + +const STRING_LITERAL = 57346 +const IPV6 = 57347 +const IDENTIFIER = 57348 +const FLAG = 57349 +const DATETIME = 57350 +const SIGNAL_PLUS = 57351 +const SIGNAL_MINUS = 57352 +const MAC = 57353 +const INT = 57354 +const UINT = 57355 +const DOUBLE = 57356 +const QUESTION = 57357 +const ARROW = 57358 +const OR = 57359 +const AND = 57360 +const LOR = 57361 +const TIMES = 57362 +const LAND = 57363 +const LEQUAL = 57364 +const ONESCOMP = 57365 +const LSHIFT = 57366 +const RSHIFT = 57367 +const NOT = 57368 +const MINUS = 57369 +const PLUS = 57370 +const COMMA = 57371 +const LBRACKET = 57372 +const RBRACKET = 57373 +const LBRACKET_SQUARE = 57374 +const RBRACKET_SQUARE = 57375 +const LPAREN = 57376 +const RPAREN = 57377 +const EQUALS = 57378 +const UNFINISHED = 57379 +const RESUMED = 57380 +const NULL = 57381 +const EQUALAT = 57382 +const COLON = 57383 +const FORWARDSLASH = 57384 +const NOTYPE = 57385 +const NOFLAG = 57386 + +var StraceToknames = [...]string{ + "$end", + "error", + "$unk", + "STRING_LITERAL", + "IPV6", + "IDENTIFIER", + "FLAG", + "DATETIME", + "SIGNAL_PLUS", + "SIGNAL_MINUS", + "MAC", + "INT", + "UINT", + "DOUBLE", + "QUESTION", + "ARROW", + "OR", + "AND", + "LOR", + "TIMES", + "LAND", + "LEQUAL", + "ONESCOMP", + "LSHIFT", + "RSHIFT", + "NOT", + "MINUS", + "PLUS", + "COMMA", + "LBRACKET", + "RBRACKET", + "LBRACKET_SQUARE", + "RBRACKET_SQUARE", + "LPAREN", + "RPAREN", + "EQUALS", + "UNFINISHED", + "RESUMED", + "NULL", + "EQUALAT", + "COLON", + "FORWARDSLASH", + "NOTYPE", + "NOFLAG", +} +var StraceStatenames = [...]string{} + +const StraceEofCode = 1 +const StraceErrCode = 2 +const StraceInitialStackSize = 16 + +//line yacctab:1 +var StraceExca = [...]int{ + -1, 1, + 1, -1, + -2, 0, +} + +const StracePrivate = 57344 + +const StraceLast = 330 + +var StraceAct = [...]int{ + + 11, 8, 92, 75, 12, 31, 34, 33, 88, 33, + 91, 30, 73, 72, 42, 2, 54, 51, 43, 50, + 53, 4, 52, 28, 45, 106, 31, 89, 48, 49, + 33, 32, 55, 56, 57, 58, 59, 86, 104, 5, + 60, 61, 62, 63, 64, 65, 66, 3, 34, 43, + 30, 98, 101, 74, 90, 30, 29, 102, 103, 68, + 80, 40, 94, 95, 85, 69, 39, 70, 31, 96, + 97, 55, 33, 40, 93, 19, 82, 18, 87, 7, + 114, 39, 20, 21, 84, 26, 100, 99, 40, 41, + 105, 100, 100, 44, 109, 67, 10, 24, 46, 47, + 19, 107, 18, 9, 23, 100, 0, 100, 100, 22, + 109, 100, 100, 109, 109, 110, 0, 111, 98, 101, + 77, 78, 0, 83, 102, 103, 1, 98, 101, 94, + 95, 25, 0, 102, 103, 79, 96, 97, 94, 95, + 0, 93, 19, 0, 18, 96, 97, 113, 0, 0, + 93, 19, 0, 18, 99, 0, 112, 0, 98, 101, + 0, 0, 0, 99, 102, 103, 0, 98, 101, 94, + 95, 0, 0, 102, 103, 0, 96, 97, 94, 95, + 0, 93, 19, 0, 18, 96, 97, 108, 0, 0, + 93, 19, 0, 18, 99, 0, 0, 14, 0, 15, + 0, 16, 0, 99, 17, 20, 21, 0, 0, 0, + 14, 0, 15, 0, 16, 0, 13, 17, 20, 21, + 24, 0, 0, 19, 81, 18, 0, 23, 0, 13, + 0, 0, 22, 24, 77, 78, 19, 76, 18, 14, + 23, 15, 0, 16, 27, 22, 17, 20, 21, 79, + 0, 0, 14, 0, 15, 0, 16, 0, 13, 17, + 20, 21, 24, 0, 0, 19, 0, 18, 0, 23, + 0, 13, 6, 0, 22, 24, 0, 0, 19, 0, + 18, 0, 23, 20, 21, 35, 36, 22, 39, 0, + 0, 0, 37, 38, 44, 40, 41, 0, 24, 0, + 0, 35, 36, 71, 39, 23, 0, 0, 37, 38, + 22, 40, 41, 36, 0, 39, 0, 0, 0, 37, + 38, 39, 40, 41, 0, 37, 38, 0, 40, 41, +} +var StracePact = [...]int{ + + 9, -1000, 5, 235, 9, 206, -12, 21, -10, -1000, + -1000, -1000, 284, 70, -1000, -8, -1000, -1000, 248, 248, + -1000, -1000, -1000, 271, 271, -1000, -18, -13, -16, -20, + 248, 248, 248, 248, 248, 271, 271, 271, 271, 271, + 271, 271, -1000, -1000, 271, 88, 26, 36, 268, -1000, + -1000, -23, -24, 38, 222, -10, -33, 32, -1000, -31, + 295, 301, 61, 61, 34, -1000, 46, 27, -1000, 193, + -1000, -1000, 108, 72, -1000, 30, -1000, -1000, -1000, 66, + -28, -1000, 20, -1000, -1000, 161, 4, -1000, 248, -9, + 161, 152, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 161, -33, 161, 121, -1000, -1000, + 112, 45, -1000, -1000, -1000, +} +var StracePgo = [...]int{ + + 0, 126, 3, 103, 0, 4, 2, 10, 1, 96, + 79, +} +var StraceR1 = [...]int{ + + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 7, 7, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 2, 2, 2, 10, + 10, 10, 8, 8, 8, 8, 8, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 4, 4, 4, 9, 9, 9, 9, 9, 9, 3, + 3, 3, 3, +} +var StraceR2 = [...]int{ + + 0, 4, 5, 6, 5, 5, 8, 9, 6, 6, + 10, 9, 2, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, + 1, 3, 1, 1, 1, 1, 2, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, + 3, 3, 4, 2, 3, 3, 3, 3, 6, 1, + 1, 1, 1, +} +var StraceChk = [...]int{ + + -1000, -1, 6, 38, 12, 34, 37, -10, -8, -3, + -9, -4, -5, 23, 4, 6, 8, 11, 32, 30, + 12, 13, 39, 34, 27, -1, -10, 38, 35, 35, + 29, 36, 41, 40, 16, 17, 18, 24, 25, 20, + 27, 28, -4, -5, 23, 32, -10, -10, -5, -5, + 37, 35, 35, 36, 36, -8, -8, -8, -8, -8, + -5, -5, -5, -5, -5, -5, -5, 7, 33, 29, + 31, 35, 36, 36, 15, -2, 15, 12, 13, 27, + 33, 31, -2, 15, 12, 34, 7, 12, 36, 7, + 34, -7, -6, 29, 17, 18, 24, 25, 6, 42, + -4, 7, 12, 13, 34, -8, 34, -7, 35, -6, + -7, -7, 35, 35, 35, +} +var StraceDef = [...]int{ + + 0, -2, 0, 29, 0, 29, 0, 0, 30, 32, + 33, 34, 35, 0, 59, 60, 61, 62, 29, 29, + 37, 38, 39, 0, 0, 12, 0, 0, 0, 0, + 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 36, 48, 0, 0, 0, 0, 0, 49, + 1, 0, 0, 0, 0, 31, 56, 54, 55, 57, + 40, 41, 42, 43, 45, 46, 47, 0, 50, 0, + 51, 44, 0, 0, 2, 4, 5, 26, 27, 0, + 0, 52, 8, 9, 3, 0, 0, 28, 0, 0, + 0, 0, 13, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 0, 58, 0, 0, 6, 14, + 0, 0, 11, 7, 10, +} +var StraceTok1 = [...]int{ + + 1, +} +var StraceTok2 = [...]int{ + + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, +} +var StraceTok3 = [...]int{ + 0, +} + +var StraceErrorMessages = [...]struct { + state int + token int + msg string +}{} + +//line yaccpar:1 + +/* parser for yacc output */ + +var ( + StraceDebug = 0 + StraceErrorVerbose = false +) + +type StraceLexer interface { + Lex(lval *StraceSymType) int + Error(s string) +} + +type StraceParser interface { + Parse(StraceLexer) int + Lookahead() int +} + +type StraceParserImpl struct { + lval StraceSymType + stack [StraceInitialStackSize]StraceSymType + char int +} + +func (p *StraceParserImpl) Lookahead() int { + return p.char +} + +func StraceNewParser() StraceParser { + return &StraceParserImpl{} +} + +const StraceFlag = -1000 + +func StraceTokname(c int) string { + if c >= 1 && c-1 < len(StraceToknames) { + if StraceToknames[c-1] != "" { + return StraceToknames[c-1] + } + } + return __yyfmt__.Sprintf("tok-%v", c) +} + +func StraceStatname(s int) string { + if s >= 0 && s < len(StraceStatenames) { + if StraceStatenames[s] != "" { + return StraceStatenames[s] + } + } + return __yyfmt__.Sprintf("state-%v", s) +} + +func StraceErrorMessage(state, lookAhead int) string { + const TOKSTART = 4 + + if !StraceErrorVerbose { + return "syntax error" + } + + for _, e := range StraceErrorMessages { + if e.state == state && e.token == lookAhead { + return "syntax error: " + e.msg + } + } + + res := "syntax error: unexpected " + StraceTokname(lookAhead) + + // To match Bison, suggest at most four expected tokens. + expected := make([]int, 0, 4) + + // Look for shiftable tokens. + base := StracePact[state] + for tok := TOKSTART; tok-1 < len(StraceToknames); tok++ { + if n := base + tok; n >= 0 && n < StraceLast && StraceChk[StraceAct[n]] == tok { + if len(expected) == cap(expected) { + return res + } + expected = append(expected, tok) + } + } + + if StraceDef[state] == -2 { + i := 0 + for StraceExca[i] != -1 || StraceExca[i+1] != state { + i += 2 + } + + // Look for tokens that we accept or reduce. + for i += 2; StraceExca[i] >= 0; i += 2 { + tok := StraceExca[i] + if tok < TOKSTART || StraceExca[i+1] == 0 { + continue + } + if len(expected) == cap(expected) { + return res + } + expected = append(expected, tok) + } + + // If the default action is to accept or reduce, give up. + if StraceExca[i+1] != 0 { + return res + } + } + + for i, tok := range expected { + if i == 0 { + res += ", expecting " + } else { + res += " or " + } + res += StraceTokname(tok) + } + return res +} + +func Stracelex1(lex StraceLexer, lval *StraceSymType) (char, token int) { + token = 0 + char = lex.Lex(lval) + if char <= 0 { + token = StraceTok1[0] + goto out + } + if char < len(StraceTok1) { + token = StraceTok1[char] + goto out + } + if char >= StracePrivate { + if char < StracePrivate+len(StraceTok2) { + token = StraceTok2[char-StracePrivate] + goto out + } + } + for i := 0; i < len(StraceTok3); i += 2 { + token = StraceTok3[i+0] + if token == char { + token = StraceTok3[i+1] + goto out + } + } + +out: + if token == 0 { + token = StraceTok2[1] /* unknown char */ + } + if StraceDebug >= 3 { + __yyfmt__.Printf("lex %s(%d)\n", StraceTokname(token), uint(char)) + } + return char, token +} + +func StraceParse(Stracelex StraceLexer) int { + return StraceNewParser().Parse(Stracelex) +} + +func (Stracercvr *StraceParserImpl) Parse(Stracelex StraceLexer) int { + var Stracen int + var StraceVAL StraceSymType + var StraceDollar []StraceSymType + _ = StraceDollar // silence set and not used + StraceS := Stracercvr.stack[:] + + Nerrs := 0 /* number of errors */ + Errflag := 0 /* error recovery flag */ + Stracestate := 0 + Stracercvr.char = -1 + Stracetoken := -1 // Stracercvr.char translated into internal numbering + defer func() { + // Make sure we report no lookahead when not parsing. + Stracestate = -1 + Stracercvr.char = -1 + Stracetoken = -1 + }() + Stracep := -1 + goto Stracestack + +ret0: + return 0 + +ret1: + return 1 + +Stracestack: + /* put a state and value onto the stack */ + if StraceDebug >= 4 { + __yyfmt__.Printf("char %v in %v\n", StraceTokname(Stracetoken), StraceStatname(Stracestate)) + } + + Stracep++ + if Stracep >= len(StraceS) { + nyys := make([]StraceSymType, len(StraceS)*2) + copy(nyys, StraceS) + StraceS = nyys + } + StraceS[Stracep] = StraceVAL + StraceS[Stracep].yys = Stracestate + +Stracenewstate: + Stracen = StracePact[Stracestate] + if Stracen <= StraceFlag { + goto Stracedefault /* simple state */ + } + if Stracercvr.char < 0 { + Stracercvr.char, Stracetoken = Stracelex1(Stracelex, &Stracercvr.lval) + } + Stracen += Stracetoken + if Stracen < 0 || Stracen >= StraceLast { + goto Stracedefault + } + Stracen = StraceAct[Stracen] + if StraceChk[Stracen] == Stracetoken { /* valid shift */ + Stracercvr.char = -1 + Stracetoken = -1 + StraceVAL = Stracercvr.lval + Stracestate = Stracen + if Errflag > 0 { + Errflag-- + } + goto Stracestack + } + +Stracedefault: + /* default state action */ + Stracen = StraceDef[Stracestate] + if Stracen == -2 { + if Stracercvr.char < 0 { + Stracercvr.char, Stracetoken = Stracelex1(Stracelex, &Stracercvr.lval) + } + + /* look through exception table */ + xi := 0 + for { + if StraceExca[xi+0] == -1 && StraceExca[xi+1] == Stracestate { + break + } + xi += 2 + } + for xi += 2; ; xi += 2 { + Stracen = StraceExca[xi+0] + if Stracen < 0 || Stracen == Stracetoken { + break + } + } + Stracen = StraceExca[xi+1] + if Stracen < 0 { + goto ret0 + } + } + if Stracen == 0 { + /* error ... attempt to resume parsing */ + switch Errflag { + case 0: /* brand new error */ + Stracelex.Error(StraceErrorMessage(Stracestate, Stracetoken)) + Nerrs++ + if StraceDebug >= 1 { + __yyfmt__.Printf("%s", StraceStatname(Stracestate)) + __yyfmt__.Printf(" saw %s\n", StraceTokname(Stracetoken)) + } + fallthrough + + case 1, 2: /* incompletely recovered error ... try again */ + Errflag = 3 + + /* find a state where "error" is a legal shift action */ + for Stracep >= 0 { + Stracen = StracePact[StraceS[Stracep].yys] + StraceErrCode + if Stracen >= 0 && Stracen < StraceLast { + Stracestate = StraceAct[Stracen] /* simulate a shift of "error" */ + if StraceChk[Stracestate] == StraceErrCode { + goto Stracestack + } + } + + /* the current p has no shift on "error", pop stack */ + if StraceDebug >= 2 { + __yyfmt__.Printf("error recovery pops state %d\n", StraceS[Stracep].yys) + } + Stracep-- + } + /* there is no state on the stack with an error shift ... abort */ + goto ret1 + + case 3: /* no shift yet; clobber input char */ + if StraceDebug >= 2 { + __yyfmt__.Printf("error recovery discards %s\n", StraceTokname(Stracetoken)) + } + if Stracetoken == StraceEofCode { + goto ret1 + } + Stracercvr.char = -1 + Stracetoken = -1 + goto Stracenewstate /* try again in the same state */ + } + } + + /* reduction by production Stracen */ + if StraceDebug >= 2 { + __yyfmt__.Printf("reduce %v in:\n\t%v\n", Stracen, StraceStatname(Stracestate)) + } + + Stracent := Stracen + Stracept := Stracep + _ = Stracept // guard against "declared and not used" + + Stracep -= StraceR2[Stracen] + // Stracep is now the index of $0. Perform the default action. Iff the + // reduced production is ε, $1 is possibly out of range. + if Stracep+1 >= len(StraceS) { + nyys := make([]StraceSymType, len(StraceS)*2) + copy(nyys, StraceS) + StraceS = nyys + } + StraceVAL = StraceS[Stracep+1] + + /* consult goto table to find next state */ + Stracen = StraceR1[Stracen] + Straceg := StracePgo[Stracen] + Stracej := Straceg + StraceS[Stracep].yys + 1 + + if Stracej >= StraceLast { + Stracestate = StraceAct[Straceg] + } else { + Stracestate = StraceAct[Stracej] + if StraceChk[Stracestate] != -Stracen { + Stracestate = StraceAct[Straceg] + } + } + // dummy call; replaced with literal code + switch Stracent { + + case 1: + StraceDollar = StraceS[Stracept-4 : Stracept+1] +//line strace.y:63 + { + StraceVAL.val_syscall = NewSyscall(-1, StraceDollar[1].data, StraceDollar[3].val_types, int64(-1), true, false) + Stracelex.(*Stracelexer).result = StraceVAL.val_syscall + } + case 2: + StraceDollar = StraceS[Stracept-5 : Stracept+1] +//line strace.y:66 + { + StraceVAL.val_syscall = NewSyscall(-1, "tmp", nil, -1, true, true) + Stracelex.(*Stracelexer).result = StraceVAL.val_syscall + } + case 3: + StraceDollar = StraceS[Stracept-6 : Stracept+1] +//line strace.y:71 + { + StraceVAL.val_syscall = NewSyscall(-1, StraceDollar[1].data, nil, int64(StraceDollar[6].val_int), false, false) + Stracelex.(*Stracelexer).result = StraceVAL.val_syscall + } + case 4: + StraceDollar = StraceS[Stracept-5 : Stracept+1] +//line strace.y:76 + { + StraceVAL.val_syscall = NewSyscall(-1, "tmp", StraceDollar[2].val_types, StraceDollar[5].val_ret_type, false, true) + Stracelex.(*Stracelexer).result = StraceVAL.val_syscall + } + case 5: + StraceDollar = StraceS[Stracept-5 : Stracept+1] +//line strace.y:78 + { + StraceVAL.val_syscall = NewSyscall(-1, "tmp", StraceDollar[2].val_types, -1, false, true) + Stracelex.(*Stracelexer).result = StraceVAL.val_syscall + } + case 6: + StraceDollar = StraceS[Stracept-8 : Stracept+1] +//line strace.y:80 + { + StraceVAL.val_syscall = NewSyscall(-1, "tmp", StraceDollar[2].val_types, StraceDollar[5].val_ret_type, false, true) + Stracelex.(*Stracelexer).result = StraceVAL.val_syscall + } + case 7: + StraceDollar = StraceS[Stracept-9 : Stracept+1] +//line strace.y:83 + { + StraceVAL.val_syscall = NewSyscall(-1, "tmp", StraceDollar[2].val_types, StraceDollar[5].val_ret_type, false, true) + Stracelex.(*Stracelexer).result = StraceVAL.val_syscall + } + case 8: + StraceDollar = StraceS[Stracept-6 : Stracept+1] +//line strace.y:85 + { + StraceVAL.val_syscall = NewSyscall(-1, StraceDollar[1].data, StraceDollar[3].val_types, StraceDollar[6].val_ret_type, false, false) + Stracelex.(*Stracelexer).result = StraceVAL.val_syscall + } + case 9: + StraceDollar = StraceS[Stracept-6 : Stracept+1] +//line strace.y:88 + { + StraceVAL.val_syscall = NewSyscall(-1, StraceDollar[1].data, StraceDollar[3].val_types, -1, false, false) + Stracelex.(*Stracelexer).result = StraceVAL.val_syscall + } + case 10: + StraceDollar = StraceS[Stracept-10 : Stracept+1] +//line strace.y:91 + { + StraceVAL.val_syscall = NewSyscall(-1, StraceDollar[1].data, StraceDollar[3].val_types, StraceDollar[6].val_ret_type, false, false) + Stracelex.(*Stracelexer).result = StraceVAL.val_syscall + } + case 11: + StraceDollar = StraceS[Stracept-9 : Stracept+1] +//line strace.y:94 + { + StraceVAL.val_syscall = NewSyscall(-1, StraceDollar[1].data, StraceDollar[3].val_types, StraceDollar[6].val_ret_type, false, false) + Stracelex.(*Stracelexer).result = StraceVAL.val_syscall + } + case 12: + StraceDollar = StraceS[Stracept-2 : Stracept+1] +//line strace.y:97 + { + call := StraceDollar[2].val_syscall + call.Pid = StraceDollar[1].val_int + Stracelex.(*Stracelexer).result = call + } + case 13: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:100 + { + StraceVAL.val_type = nil + } + case 14: + StraceDollar = StraceS[Stracept-2 : Stracept+1] +//line strace.y:101 + { + StraceVAL.val_type = nil + } + case 15: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:104 + { + StraceVAL.val_type = nil + } + case 16: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:105 + { + StraceVAL.val_type = nil + } + case 17: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:106 + { + StraceVAL.val_type = nil + } + case 18: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:107 + { + StraceVAL.val_type = nil + } + case 19: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:108 + { + StraceVAL.val_type = nil + } + case 20: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:109 + { + StraceVAL.val_type = nil + } + case 21: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:110 + { + StraceVAL.val_type = nil + } + case 22: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:111 + { + StraceVAL.val_type = nil + } + case 23: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:112 + { + StraceVAL.val_type = nil + } + case 24: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:113 + { + StraceVAL.val_type = nil + } + case 25: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:114 + { + StraceVAL.val_type = nil + } + case 26: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:117 + { + StraceVAL.val_ret_type = StraceDollar[1].val_int + } + case 27: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:118 + { + StraceVAL.val_ret_type = int64(StraceDollar[1].val_uint) + } + case 28: + StraceDollar = StraceS[Stracept-2 : Stracept+1] +//line strace.y:119 + { + StraceVAL.val_ret_type = -1 * StraceDollar[2].val_int + } + case 29: + StraceDollar = StraceS[Stracept-0 : Stracept+1] +//line strace.y:121 + { + StraceVAL.val_types = make([]IrType, 0) + } + case 30: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:122 + { + StraceVAL.val_types = []IrType{StraceDollar[1].val_type} + } + case 31: + StraceDollar = StraceS[Stracept-3 : Stracept+1] +//line strace.y:123 + { + StraceDollar[1].val_types = append(StraceDollar[1].val_types, StraceDollar[3].val_type) + StraceVAL.val_types = StraceDollar[1].val_types + } + case 32: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:126 + { + StraceVAL.val_type = StraceDollar[1].val_buf_type + } + case 33: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:127 + { + StraceVAL.val_type = StraceDollar[1].val_type + } + case 34: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:128 + { + StraceVAL.val_type = StraceDollar[1].val_group_type + } + case 35: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:129 + { + StraceVAL.val_type = StraceDollar[1].val_constant + } + case 36: + StraceDollar = StraceS[Stracept-2 : Stracept+1] +//line strace.y:130 + { + StraceVAL.val_type = StraceDollar[2].val_group_type + } + case 37: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:133 + { + StraceVAL.val_constant = Constant(StraceDollar[1].val_int) + } + case 38: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:134 + { + StraceVAL.val_constant = Constant(StraceDollar[1].val_uint) + } + case 39: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:135 + { + StraceVAL.val_constant = Constant(uint64(0)) + } + case 40: + StraceDollar = StraceS[Stracept-3 : Stracept+1] +//line strace.y:136 + { + StraceVAL.val_constant = StraceDollar[1].val_constant | StraceDollar[3].val_constant + } + case 41: + StraceDollar = StraceS[Stracept-3 : Stracept+1] +//line strace.y:137 + { + StraceVAL.val_constant = StraceDollar[1].val_constant & StraceDollar[3].val_constant + } + case 42: + StraceDollar = StraceS[Stracept-3 : Stracept+1] +//line strace.y:138 + { + StraceVAL.val_constant = StraceDollar[1].val_constant << StraceDollar[3].val_constant + } + case 43: + StraceDollar = StraceS[Stracept-3 : Stracept+1] +//line strace.y:139 + { + StraceVAL.val_constant = StraceDollar[1].val_constant >> StraceDollar[3].val_constant + } + case 44: + StraceDollar = StraceS[Stracept-3 : Stracept+1] +//line strace.y:140 + { + StraceVAL.val_constant = StraceDollar[2].val_constant + } + case 45: + StraceDollar = StraceS[Stracept-3 : Stracept+1] +//line strace.y:141 + { + StraceVAL.val_constant = StraceDollar[1].val_constant * StraceDollar[3].val_constant + } + case 46: + StraceDollar = StraceS[Stracept-3 : Stracept+1] +//line strace.y:142 + { + StraceVAL.val_constant = StraceDollar[1].val_constant - StraceDollar[3].val_constant + } + case 47: + StraceDollar = StraceS[Stracept-3 : Stracept+1] +//line strace.y:143 + { + StraceVAL.val_constant = StraceDollar[1].val_constant + StraceDollar[3].val_constant + } + case 48: + StraceDollar = StraceS[Stracept-2 : Stracept+1] +//line strace.y:144 + { + StraceVAL.val_constant = ^StraceDollar[2].val_constant + } + case 49: + StraceDollar = StraceS[Stracept-2 : Stracept+1] +//line strace.y:145 + { + StraceVAL.val_constant = Constant(-int64(StraceDollar[2].val_constant)) + } + case 50: + StraceDollar = StraceS[Stracept-3 : Stracept+1] +//line strace.y:148 + { + StraceVAL.val_group_type = newGroupType(StraceDollar[2].val_types) + } + case 51: + StraceDollar = StraceS[Stracept-3 : Stracept+1] +//line strace.y:149 + { + StraceVAL.val_group_type = newGroupType(StraceDollar[2].val_types) + } + case 52: + StraceDollar = StraceS[Stracept-4 : Stracept+1] +//line strace.y:150 + { + StraceVAL.val_group_type = newGroupType(StraceDollar[2].val_types) + } + case 53: + StraceDollar = StraceS[Stracept-2 : Stracept+1] +//line strace.y:153 + { + StraceVAL.val_type = nil + } + case 54: + StraceDollar = StraceS[Stracept-3 : Stracept+1] +//line strace.y:154 + { + StraceVAL.val_type = StraceDollar[3].val_type + } + case 55: + StraceDollar = StraceS[Stracept-3 : Stracept+1] +//line strace.y:155 + { + StraceVAL.val_type = StraceDollar[3].val_type + } + case 56: + StraceDollar = StraceS[Stracept-3 : Stracept+1] +//line strace.y:156 + { + StraceVAL.val_type = StraceDollar[3].val_type + } + case 57: + StraceDollar = StraceS[Stracept-3 : Stracept+1] +//line strace.y:157 + { + StraceVAL.val_type = StraceDollar[1].val_type + } + case 58: + StraceDollar = StraceS[Stracept-6 : Stracept+1] +//line strace.y:158 + { + StraceVAL.val_type = StraceDollar[6].val_type + } + case 59: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:161 + { + StraceVAL.val_buf_type = newBufferType(StraceDollar[1].data) + } + case 60: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:162 + { + StraceVAL.val_buf_type = newBufferType(StraceDollar[1].data) + } + case 61: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:163 + { + StraceVAL.val_buf_type = newBufferType(StraceDollar[1].data) + } + case 62: + StraceDollar = StraceS[Stracept-1 : Stracept+1] +//line strace.y:164 + { + StraceVAL.val_buf_type = newBufferType(StraceDollar[1].data) + } + } + goto Stracestack /* stack new state and value */ +} diff --git a/tools/syz-trace2syz/parser/strace.y b/tools/syz-trace2syz/parser/strace.y new file mode 100644 index 000000000..47a31c820 --- /dev/null +++ b/tools/syz-trace2syz/parser/strace.y @@ -0,0 +1,165 @@ +%{ +// Copyright 2018 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// nolint +package parser + +%} + +%start syscall + +%union { + data string + val_int int64 + val_double float64 + val_ret_type int64 + val_uint uint64 + val_constant Constant + val_identifiers []*BufferType + val_buf_type *BufferType + val_group_type *GroupType + val_type IrType + val_types []IrType + val_syscall *Syscall +} + +%token STRING_LITERAL IPV6 IDENTIFIER FLAG DATETIME SIGNAL_PLUS SIGNAL_MINUS MAC +%token INT +%token UINT +%token DOUBLE +%type ret_type +%type buf_type +%type group_type +%type constant +%type parenthetical, parentheticals, type, field_type +%type types +%type syscall + +%token STRING_LITERAL MAC IDENTIFIER FLAG INT UINT QUESTION DOUBLE ARROW +%token OR AND LOR TIMES LAND LEQUAL ONESCOMP LSHIFT RSHIFT TIMES NOT MINUS PLUS +%token COMMA LBRACKET RBRACKET LBRACKET_SQUARE RBRACKET_SQUARE LPAREN RPAREN EQUALS +%token UNFINISHED RESUMED +%token SIGNAL_PLUS SIGNAL_MINUS NULL EQUALAT COLON FORWARDSLASH + +%nonassoc NOTYPE +%nonassoc FLAG +%nonassoc NOFLAG + + +%left OR +%left AND +%left LSHIFT RSHIFT +%left PLUS +%left TIMES +%left MINUS ONESCOMP +%left COLON +%left ARROW +%left EQUALS +%left EQUALAT + +%% +syscall: + IDENTIFIER LPAREN types UNFINISHED %prec NOFLAG { $$ = NewSyscall(-1, $1, $3, int64(-1), true, false); + Stracelex.(*Stracelexer).result = $$ } + | RESUMED UNFINISHED RPAREN EQUALS QUESTION %prec NOFLAG + { + $$ = NewSyscall(-1, "tmp", nil, -1, true, true); + Stracelex.(*Stracelexer).result = $$; + } + | IDENTIFIER LPAREN RESUMED RPAREN EQUALS INT %prec NOFLAG + { + $$ = NewSyscall(-1, $1, nil, int64($6), false, false); + Stracelex.(*Stracelexer).result = $$; + } + + | RESUMED types RPAREN EQUALS ret_type %prec NOFLAG { $$ = NewSyscall(-1, "tmp", $2, $5, false, true); + Stracelex.(*Stracelexer).result = $$ } + | RESUMED types RPAREN EQUALS QUESTION %prec NOFLAG { $$ = NewSyscall(-1, "tmp", $2, -1, false, true); + Stracelex.(*Stracelexer).result = $$ } + | RESUMED types RPAREN EQUALS ret_type LPAREN parentheticals RPAREN { $$ = NewSyscall(-1, "tmp", $2, $5, false, true); + Stracelex.(*Stracelexer).result = $$ } + + | RESUMED types RPAREN EQUALS ret_type FLAG LPAREN parentheticals RPAREN { $$ = NewSyscall(-1, "tmp", $2, $5, false, true); + Stracelex.(*Stracelexer).result = $$ } + | IDENTIFIER LPAREN types RPAREN EQUALS ret_type %prec NOFLAG{ + $$ = NewSyscall(-1, $1, $3, $6, false, false); + Stracelex.(*Stracelexer).result = $$;} + | IDENTIFIER LPAREN types RPAREN EQUALS QUESTION %prec NOFLAG { + $$ = NewSyscall(-1, $1, $3, -1, false, false); + Stracelex.(*Stracelexer).result = $$;} + | IDENTIFIER LPAREN types RPAREN EQUALS ret_type FLAG LPAREN parentheticals RPAREN { + $$ = NewSyscall(-1, $1, $3, $6, false, false); + Stracelex.(*Stracelexer).result = $$;} + | IDENTIFIER LPAREN types RPAREN EQUALS ret_type LPAREN parentheticals RPAREN { + $$ = NewSyscall(-1, $1, $3, $6, false, false); + Stracelex.(*Stracelexer).result = $$;} + | INT syscall {call := $2; call.Pid = $1; Stracelex.(*Stracelexer).result = call} + +parentheticals: + parenthetical {$$ = nil;} + | parentheticals parenthetical {$$ = nil;} + +parenthetical: + COMMA {$$=nil} + | OR {$$ = nil} + | AND {$$ = nil} + | LSHIFT {$$ = nil} + | RSHIFT {$$ = nil} + | IDENTIFIER {$$ = nil} + | FORWARDSLASH {$$ = nil} + | group_type {$$ = nil} + | FLAG {$$ = nil} + | INT {$$ = nil} + | UINT {$$ = nil} + +ret_type: + INT {$$ = $1} + | UINT {$$ = int64($1)} + | MINUS INT {$$ = -1 * $2} + +types: {$$ = make([]IrType, 0)} + | type {$$ = []IrType{$1}} + | types COMMA type {$1 = append($1, $3); $$ = $1;} + +type: + buf_type {$$ = $1} + | field_type {$$ = $1} + | group_type {$$ = $1} + | constant {$$ = $1} + | ONESCOMP group_type {$$ = $2} + +constant: + INT {$$ = Constant($1)} + | UINT {$$ = Constant($1)} + | NULL {$$ = Constant(uint64(0))} + | constant OR constant {$$ = $1 | $3} + | constant AND constant {$$ = $1 & $3} + | constant LSHIFT constant {$$ = $1 << $3} + | constant RSHIFT constant {$$ = $1 >> $3} + | LPAREN constant RPAREN {$$ = $2} + | constant TIMES constant {$$ = $1 * $3} + | constant MINUS constant {$$ = $1 - $3} + | constant PLUS constant {$$ = $1 + $3} + | ONESCOMP constant {$$ = ^$2} + | MINUS constant {$$ = Constant(-int64($2))} + +group_type: + LBRACKET_SQUARE types RBRACKET_SQUARE {$$ = newGroupType($2)} + | LBRACKET types RBRACKET {$$ = newGroupType($2)} + | LBRACKET types COMMA RBRACKET {$$ = newGroupType($2)} + +field_type: + type EQUALS %prec NOTYPE {$$ = nil} + | type COLON type {$$ = $3} + | type EQUALAT type {$$ = $3} + | type EQUALS type {$$ = $3} + | type ARROW type {$$ = $1} + | IDENTIFIER LBRACKET_SQUARE FLAG RBRACKET_SQUARE EQUALS type {$$ = $6} + +buf_type: + STRING_LITERAL {$$ = newBufferType($1)} + | IDENTIFIER {$$ = newBufferType($1)} + | DATETIME {$$ = newBufferType($1)} + | MAC {$$ = newBufferType($1)} + diff --git a/tools/syz-trace2syz/parser/straceLex.rl b/tools/syz-trace2syz/parser/straceLex.rl new file mode 100644 index 000000000..973827087 --- /dev/null +++ b/tools/syz-trace2syz/parser/straceLex.rl @@ -0,0 +1,133 @@ +// Copyright 2018 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// nolint + +package parser + +import ( + "fmt" + "encoding/hex" + "strconv" + "strings" + "github.com/google/syzkaller/pkg/log" +) + +%%{ + machine strace; + write data; + access lex.; + variable p lex.p; + variable pe lex.pe; +}%% + +type Stracelexer struct { + result *Syscall + data []byte + p, pe, cs int + ts, te, act int +} + +func newStraceLexer (data []byte) *Stracelexer { + lex := &Stracelexer { + data: data, + pe: len(data), + } + + %% write init; + return lex +} + +func (lex *Stracelexer) Lex(out *StraceSymType) int { + eof := lex.pe + tok := 0 + %%{ + dateSep = '-' | '\/'; + datetimeSep = 'T' | '-'; + microTimeSep = '+' | '-'; + date = digit{4}.dateSep.digit{2}.dateSep.digit{2}; + nullptr = "NULL"; + time = digit{2}.':'.digit{2}.':'.digit{2} | + digit{2}.':'.digit{2}.':'.digit{2}.microTimeSep.digit{4} | + digit{2}.':'.digit{2}.':'.digit{2}.microTimeSep.digit{4}.'.'.digit+ | + digit{2}.':'.digit{2}.':'.digit{2}.'.'.digit+; + datetime = date.datetimeSep.time; + unfinished = '' | ', '; + ipv4 = digit{1,3}.'\.'.digit{1,3}.'\.'.digit{1,3}.'\.'.digit{1,3}; + identifier = ([A-Za-z':'].[0-9a-z'_'\*\.\-':']*) | ipv4; + resumed = '<... '.identifier+.' resumed>' + | '<... '.identifier+.' resumed> ,' + | '<... resuming'.' '.identifier.' '.identifier.' '.'...>'; + flag = (['_']+?upper+ . ['_'A-Z0-9]+)-nullptr; + string = '\"'.['_''\.'('')'' ''#'':'0-9a-zA-Z\/\\\*]*.'\"'; + mac = xdigit{2}.':'.xdigit{2}.':'.xdigit{2}.':'.xdigit{2}.':'.xdigit{2}.':'.xdigit{2}; + comment := |* + ((any-"*\/")); + "*\/" => {fgoto main;}; + *|; + + main := |* + [0-9]* => {out.val_int, _ = strconv.ParseInt(string(lex.data[lex.ts : lex.te]), 10, 64); tok = INT;fbreak;}; + digit . '.' . digit* => {out.val_double, _ = strconv.ParseFloat(string(lex.data[lex.ts : lex.te]), 64); tok= DOUBLE; fbreak;}; + [0].[0-7]* => {out.val_int, _ = strconv.ParseInt(string(lex.data[lex.ts : lex.te]), 8, 64); tok = INT; fbreak;}; + '0x'xdigit+ => {out.val_uint, _ = strconv.ParseUint(string(lex.data[lex.ts:lex.te]), 0, 64); tok = UINT;fbreak;}; + string.['.']* => {out.data = ParseString(string(lex.data[lex.ts+1:lex.te-1])); tok = STRING_LITERAL;fbreak;}; + nullptr => {tok = NULL; fbreak;}; + flag => {out.data = string(lex.data[lex.ts:lex.te]); tok = FLAG; fbreak;}; + '\"'.flag.'\"' => {out.data = string(lex.data[lex.ts+1:lex.te-1]); tok=FLAG; fbreak;}; + identifier => {out.data = string(lex.data[lex.ts:lex.te]); tok = IDENTIFIER;fbreak;}; + unfinished => {tok = UNFINISHED; fbreak;}; + resumed => {tok = RESUMED; fbreak;}; + mac => {out.data = string(lex.data[lex.ts : lex.te]); tok = MAC; fbreak;}; + '=' => {tok = EQUALS;fbreak;}; + '(' => {tok = LPAREN;fbreak;}; + '=@' => {tok = EQUALAT; fbreak;}; + ')' => {tok = RPAREN;fbreak;}; + '[' => {tok = LBRACKET_SQUARE;fbreak;}; + ']' => {tok = RBRACKET_SQUARE;fbreak;}; + '*' => {tok = TIMES; fbreak;}; + '{' => {tok = LBRACKET;fbreak;}; + [.]*.'}' => {tok = RBRACKET;fbreak;}; + '|' => {tok = OR;fbreak;}; + ':' => {tok = COLON; fbreak;}; + '&' => {tok = AND;fbreak;}; + '!' => {tok = NOT;fbreak;}; + '~' => {tok = ONESCOMP; fbreak;}; + '<<' => {tok = LSHIFT; fbreak;}; + '>>' => {tok = RSHIFT; fbreak;}; + '->' => {tok = ARROW; fbreak;}; + '=>' => {tok = ARROW; fbreak;}; + ',' => {tok = COMMA;fbreak;}; + '-' => {tok = MINUS; fbreak;}; + '+' => {tok = PLUS; fbreak;}; + '\/' => {tok = FORWARDSLASH; fbreak;}; + datetime => {out.data = string(lex.data[lex.ts:lex.te]); tok = DATETIME; fbreak;}; + "\/*" => {fgoto comment;}; + "?" => {tok = QUESTION; fbreak;}; + space; + *|; + + write exec; + }%% + + return tok; +} + +func (lex *Stracelexer) Error(e string) { + fmt.Println("error:", e) +} + +func ParseString(s string) string{ + var decoded []byte + var err error + var strippedStr string + strippedStr = strings.Replace(s, `\x`, "", -1) + strippedStr = strings.Replace(strippedStr, `"`, "", -1) + + if decoded, err = hex.DecodeString(strippedStr); err != nil { + log.Logf(2, "failed to decode string: %s, with error: %s", s, err.Error()) + decoded = []byte(strippedStr) + } + decoded = append(decoded, '\x00') + return string(decoded) +} \ No newline at end of file diff --git a/tools/syz-trace2syz/proggen/call_selector.go b/tools/syz-trace2syz/proggen/call_selector.go new file mode 100644 index 000000000..71fd8b643 --- /dev/null +++ b/tools/syz-trace2syz/proggen/call_selector.go @@ -0,0 +1,118 @@ +package proggen + +import ( + "github.com/google/syzkaller/prog" + "github.com/google/syzkaller/tools/syz-trace2syz/parser" +) + +var discriminatorArgs = map[string][]int{ + "bpf": {0}, + "fcntl": {1}, + "ioprio_get": {0}, + "socket": {0, 1, 2}, + "socketpair": {0, 1, 2}, + "ioctl": {0, 1}, + "getsockopt": {1, 2}, + "setsockopt": {1, 2}, + "accept": {0}, + "accept4": {0}, + "bind": {0}, + "connect": {0}, + "recvfrom": {0}, + "sendto": {0}, + "sendmsg": {0}, + "getsockname": {0}, +} + +type CallSelector struct { + callCache map[string][]*prog.Syscall +} + +func NewCallSelector() *CallSelector { + return &CallSelector{callCache: make(map[string][]*prog.Syscall)} +} + +// Select returns the best matching descrimination for this syscall. +func (cs *CallSelector) Select(ctx *Context, call *parser.Syscall) *prog.Syscall { + match := ctx.Target.SyscallMap[call.CallName] + discriminators := discriminatorArgs[call.CallName] + if len(discriminators) == 0 { + return match + } + score := 0 + for _, meta := range cs.callSet(ctx, call.CallName) { + if score1 := matchCall(ctx, meta, call, discriminators); score1 > score { + match, score = meta, score1 + } + } + return match +} + +// callSet returns all syscalls with the given name. +func (cs *CallSelector) callSet(ctx *Context, callName string) []*prog.Syscall { + calls, ok := cs.callCache[callName] + if ok { + return calls + } + for _, call := range ctx.Target.Syscalls { + if call.CallName == callName { + calls = append(calls, call) + } + } + cs.callCache[callName] = calls + return calls +} + +// matchCall returns match score between meta and call. +// Higher score means better match, -1 if they are not matching at all. +func matchCall(ctx *Context, meta *prog.Syscall, call *parser.Syscall, discriminators []int) int { + score := 0 + for _, i := range discriminators { + if i >= len(meta.Args) || i >= len(call.Args) { + return -1 + } + typ := meta.Args[i] + arg := call.Args[i] + switch t := typ.(type) { + case *prog.ConstType: + // Consts must match precisely. + constant, ok := arg.(parser.Constant) + if !ok || constant.Val() != t.Val { + return -1 + } + score += 10 + case *prog.FlagsType: + // Flags may or may not match, but matched flags increase score. + constant, ok := arg.(parser.Constant) + if !ok { + return -1 + } + val := constant.Val() + for _, v := range t.Vals { + if v == val { + score++ + break + } + } + case *prog.ResourceType: + // Resources must match one of subtypes, + // the more precise match, the higher the score. + retArg := ctx.ReturnCache.get(t, arg) + if retArg == nil { + return -1 + } + matched := false + for i, kind := range retArg.Type().(*prog.ResourceType).Desc.Kind { + if kind == t.Desc.Name { + score += i + 1 + matched = true + break + } + } + if !matched { + return -1 + } + } + } + return score +} diff --git a/tools/syz-trace2syz/proggen/context.go b/tools/syz-trace2syz/proggen/context.go new file mode 100644 index 000000000..60a7977e8 --- /dev/null +++ b/tools/syz-trace2syz/proggen/context.go @@ -0,0 +1,37 @@ +package proggen + +import ( + "github.com/google/syzkaller/prog" + "github.com/google/syzkaller/tools/syz-trace2syz/parser" +) + +// Context stores metadata related to a syzkaller program +type Context struct { + ReturnCache returnCache + Prog *prog.Prog + CurrentStraceCall *parser.Syscall + CurrentSyzCall *prog.Call + CurrentStraceArg parser.IrType + Target *prog.Target + Tracker *memoryTracker + CallSelector *CallSelector +} + +func newContext(target *prog.Target, selector *CallSelector) (ctx *Context) { + ctx = &Context{} + ctx.ReturnCache = newRCache() + ctx.CurrentStraceCall = nil + ctx.Tracker = newTracker() + ctx.CurrentStraceArg = nil + ctx.Target = target + ctx.CallSelector = selector + ctx.Prog = new(prog.Prog) + ctx.Prog.Target = target + return +} + +// FillOutMemory determines how much memory to allocate for arguments in a program +// And generates an mmap c to do the allocation.This mmap is prepended to prog.Calls +func (ctx *Context) FillOutMemory() error { + return ctx.Tracker.fillOutPtrArgs(ctx.Prog) +} diff --git a/tools/syz-trace2syz/proggen/generate_unions.go b/tools/syz-trace2syz/proggen/generate_unions.go new file mode 100644 index 000000000..d16e7dc19 --- /dev/null +++ b/tools/syz-trace2syz/proggen/generate_unions.go @@ -0,0 +1,103 @@ +// Copyright 2018 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package proggen + +import ( + "github.com/google/syzkaller/pkg/log" + "github.com/google/syzkaller/prog" + "github.com/google/syzkaller/tools/syz-trace2syz/parser" +) + +func genSockaddrStorage(syzType *prog.UnionType, straceType parser.IrType, ctx *Context) prog.Arg { + var idx = 0 + field2Opt := make(map[string]int) + for i, field := range syzType.Fields { + field2Opt[field.FieldName()] = i + } + // We currently look at the first argument of the system call + // To determine which option of the union we select. + call := ctx.CurrentStraceCall + var straceArg parser.IrType + switch call.CallName { + // May need to handle special cases. + case "recvfrom", "sendto": + straceArg = call.Args[4] + default: + if len(call.Args) >= 2 { + straceArg = call.Args[1] + } else { + log.Fatalf("unable identify union for sockaddr_storage for call: %s", + call.CallName) + } + } + switch strType := straceArg.(type) { + case *parser.GroupType: + socketFamily, ok := strType.Elems[0].(parser.Constant) + if !ok { + log.Fatalf("failed to identify socket family when generating sockaddr stroage union. "+ + "expected constant got: %#v", strType.Elems[0]) + } + switch socketFamily.Val() { + case ctx.Target.ConstMap["AF_INET6"]: + idx = field2Opt["in6"] + case ctx.Target.ConstMap["AF_INET"]: + idx = field2Opt["in"] + case ctx.Target.ConstMap["AF_UNIX"]: + idx = field2Opt["un"] + case ctx.Target.ConstMap["AF_UNSPEC"]: + idx = field2Opt["nl"] + case ctx.Target.ConstMap["AF_NETLINK"]: + idx = field2Opt["nl"] + case ctx.Target.ConstMap["AF_NFC"]: + idx = field2Opt["nfc"] + case ctx.Target.ConstMap["AF_PACKET"]: + idx = field2Opt["ll"] + } + + default: + log.Fatalf("unable to parse sockaddr_storage. Unsupported type: %#v", strType) + } + return prog.MakeUnionArg(syzType, genArgs(syzType.Fields[idx], straceType, ctx)) +} + +func genSockaddrNetlink(syzType *prog.UnionType, straceType parser.IrType, ctx *Context) prog.Arg { + var idx = 2 + field2Opt := make(map[string]int) + for i, field := range syzType.Fields { + field2Opt[field.FieldName()] = i + } + switch a := ctx.CurrentStraceArg.(type) { + case *parser.GroupType: + if len(a.Elems) > 2 { + switch b := a.Elems[1].(type) { + case parser.Constant: + pid := b.Val() + if pid > 0 { + // User + idx = field2Opt["proc"] + } else if pid == 0 { + // Kernel + idx = field2Opt["kern"] + } else { + // Unspec + idx = field2Opt["unspec"] + } + default: + log.Fatalf("unable to parse netlink addr struct. Unsupported type: %#v", a) + } + } + } + return prog.MakeUnionArg(syzType, genArgs(syzType.Fields[idx], straceType, ctx)) +} + +func genIfrIfru(syzType *prog.UnionType, straceType parser.IrType, ctx *Context) prog.Arg { + idx := 0 + switch ctx.CurrentStraceArg.(type) { + case parser.Constant: + idx = 2 + default: + idx = 0 + } + return prog.MakeUnionArg(syzType, genArgs(syzType.Fields[idx], straceType, ctx)) +} diff --git a/tools/syz-trace2syz/proggen/memory_tracker.go b/tools/syz-trace2syz/proggen/memory_tracker.go new file mode 100644 index 000000000..ce05b04bd --- /dev/null +++ b/tools/syz-trace2syz/proggen/memory_tracker.go @@ -0,0 +1,62 @@ +// Copyright 2018 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package proggen + +import ( + "fmt" + + "github.com/google/syzkaller/prog" +) + +const ( + memAllocMaxMem = 16 << 20 +) + +type allocation struct { + numBytes uint64 + arg *prog.PointerArg +} + +// TODO: Replace memory tracker with memAlloc in prog package. +type memoryTracker struct { + allocations map[*prog.Call][]*allocation +} + +func newTracker() *memoryTracker { + return &memoryTracker{ + allocations: make(map[*prog.Call][]*allocation), + } +} + +func (m *memoryTracker) addAllocation(call *prog.Call, size uint64, arg *prog.PointerArg) { + alloc := new(allocation) + alloc.arg = arg + alloc.numBytes = size + + if _, ok := m.allocations[call]; !ok { + m.allocations[call] = make([]*allocation, 0) + } + m.allocations[call] = append(m.allocations[call], alloc) +} + +func (m *memoryTracker) fillOutPtrArgs(p *prog.Prog) error { + offset := uint64(0) + for _, call := range p.Calls { + if _, ok := m.allocations[call]; !ok { + continue + } + for _, a := range m.allocations[call] { + a.arg.Address = offset + offset += a.numBytes + + if a.arg.Address >= memAllocMaxMem { + return fmt.Errorf("unable to allocate space to store arg: %#v"+ + "in Call: %v. Required memory is larger than what we allow."+ + "Offending address: %d. Skipping program generation for this prog...\n", + a.arg, call, a.arg.Address) + } + } + } + return nil +} diff --git a/tools/syz-trace2syz/proggen/proggen.go b/tools/syz-trace2syz/proggen/proggen.go new file mode 100644 index 000000000..a3387ea15 --- /dev/null +++ b/tools/syz-trace2syz/proggen/proggen.go @@ -0,0 +1,381 @@ +// Copyright 2018 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package proggen + +import ( + "encoding/binary" + "math/rand" + + "github.com/google/syzkaller/pkg/log" + "github.com/google/syzkaller/prog" + "github.com/google/syzkaller/tools/syz-trace2syz/config" + "github.com/google/syzkaller/tools/syz-trace2syz/parser" +) + +// GenSyzProg converts a trace to one of our programs +func GenSyzProg(trace *parser.Trace, target *prog.Target, selector *CallSelector) *Context { + ctx := newContext(target, selector) + var call *prog.Call + for _, sCall := range trace.Calls { + if sCall.Paused { + // Probably a case where the call was killed by a signal like the following + // 2179 wait4(2180, + // 2179 <... wait4 resumed> 0x7fff28981bf8, 0, NULL) = ? ERESTARTSYS + // 2179 --- SIGUSR1 {si_signo=SIGUSR1, si_code=SI_USER, si_pid=2180, si_uid=0} --- + continue + } + ctx.CurrentStraceCall = sCall + + if shouldSkip(ctx) { + log.Logf(2, "skipping call: %s", ctx.CurrentStraceCall.CallName) + continue + } + if call = genCall(ctx); call == nil { + continue + } + ctx.Target.AssignSizesCall(call) + ctx.Prog.Calls = append(ctx.Prog.Calls, call) + } + return ctx +} + +func genCall(ctx *Context) *prog.Call { + log.Logf(3, "parsing call: %s", ctx.CurrentStraceCall.CallName) + straceCall := ctx.CurrentStraceCall + ctx.CurrentSyzCall = new(prog.Call) + ctx.CurrentSyzCall.Meta = ctx.CallSelector.Select(ctx, straceCall) + syzCall := ctx.CurrentSyzCall + if ctx.CurrentSyzCall.Meta == nil { + log.Logf(2, "skipping call: %s which has no matching description", ctx.CurrentStraceCall.CallName) + return nil + } + syzCall.Ret = prog.MakeReturnArg(syzCall.Meta.Ret) + + for i := range syzCall.Meta.Args { + var strArg parser.IrType + if i < len(straceCall.Args) { + strArg = straceCall.Args[i] + } + res := genArgs(syzCall.Meta.Args[i], strArg, ctx) + syzCall.Args = append(syzCall.Args, res) + } + genResult(syzCall.Meta.Ret, straceCall.Ret, ctx) + ctx.Target.SanitizeCall(syzCall) + return syzCall +} + +func genResult(syzType prog.Type, straceRet int64, ctx *Context) { + if straceRet > 0 { + straceExpr := parser.Constant(uint64(straceRet)) + switch syzType.(type) { + case *prog.ResourceType: + log.Logf(2, "call: %s returned a resource type with val: %s", + ctx.CurrentStraceCall.CallName, straceExpr.String()) + ctx.ReturnCache.cache(syzType, straceExpr, ctx.CurrentSyzCall.Ret) + } + } +} + +func genArgs(syzType prog.Type, traceArg parser.IrType, ctx *Context) prog.Arg { + if traceArg == nil { + log.Logf(3, "parsing syzType: %s, traceArg is nil. generating default arg...", syzType.Name()) + return prog.DefaultArg(syzType) + } + ctx.CurrentStraceArg = traceArg + log.Logf(3, "parsing arg of syz type: %s, ir type: %#v", syzType.Name(), traceArg) + + if syzType.Dir() == prog.DirOut { + switch syzType.(type) { + case *prog.PtrType, *prog.StructType, *prog.ResourceType, *prog.BufferType: + // Resource Types need special care. Pointers, Structs can have resource fields e.g. pipe, socketpair + // Buffer may need special care in out direction + default: + return prog.DefaultArg(syzType) + } + } + + switch a := syzType.(type) { + case *prog.IntType, *prog.ConstType, *prog.FlagsType, *prog.CsumType: + return genConst(a, traceArg, ctx) + case *prog.LenType: + return prog.DefaultArg(syzType) + case *prog.ProcType: + return parseProc(a, traceArg, ctx) + case *prog.ResourceType: + return genResource(a, traceArg, ctx) + case *prog.PtrType: + return genPtr(a, traceArg, ctx) + case *prog.BufferType: + return genBuffer(a, traceArg, ctx) + case *prog.StructType: + return genStruct(a, traceArg, ctx) + case *prog.ArrayType: + return genArray(a, traceArg, ctx) + case *prog.UnionType: + return genUnionArg(a, traceArg, ctx) + case *prog.VmaType: + return genVma(a, traceArg, ctx) + default: + log.Fatalf("unsupported type: %#v", syzType) + } + return nil +} + +func genVma(syzType *prog.VmaType, _ parser.IrType, ctx *Context) prog.Arg { + var npages uint64 = 1 + if syzType.RangeBegin != 0 || syzType.RangeEnd != 0 { + npages = syzType.RangeEnd + } + arg := prog.MakeVmaPointerArg(syzType, 0, npages) + ctx.Tracker.addAllocation(ctx.CurrentSyzCall, ctx.Target.PageSize, arg) + return arg +} + +func genArray(syzType *prog.ArrayType, traceType parser.IrType, ctx *Context) prog.Arg { + var args []prog.Arg + switch a := traceType.(type) { + case *parser.GroupType: + for i := 0; i < len(a.Elems); i++ { + args = append(args, genArgs(syzType.Type, a.Elems[i], ctx)) + } + default: + log.Fatalf("unsupported type for array: %#v", traceType) + } + return prog.MakeGroupArg(syzType, args) +} + +func genStruct(syzType *prog.StructType, traceType parser.IrType, ctx *Context) prog.Arg { + args := make([]prog.Arg, 0) + switch a := traceType.(type) { + case *parser.GroupType: + j := 0 + reorderStructFields(syzType, a, ctx) + for i := range syzType.Fields { + if prog.IsPad(syzType.Fields[i]) { + args = append(args, prog.DefaultArg(syzType.Fields[i])) + continue + } + // If the last n fields of a struct are zero or NULL, strace will occasionally omit those values + // this creates a mismatch in the number of elements in the ir type and in + // our descriptions. We generate default values for omitted fields + if j >= len(a.Elems) { + args = append(args, prog.DefaultArg(syzType.Fields[i])) + } else { + args = append(args, genArgs(syzType.Fields[i], a.Elems[j], ctx)) + } + j++ + } + case *parser.BufferType: + // We could have a case like the following: + // ioctl(3, 35111, {ifr_name="\x6c\x6f", ifr_hwaddr=00:00:00:00:00:00}) = 0 + // if_hwaddr gets parsed as a BufferType but our syscall descriptions have it as a struct type + return prog.DefaultArg(syzType) + default: + log.Fatalf("unsupported type for struct: %#v", a) + } + return prog.MakeGroupArg(syzType, args) +} + +func genUnionArg(syzType *prog.UnionType, straceType parser.IrType, ctx *Context) prog.Arg { + if straceType == nil { + log.Logf(1, "generating union arg. straceType is nil") + return prog.DefaultArg(syzType) + } + log.Logf(4, "generating union arg: %s %#v", syzType.TypeName, straceType) + + // Unions are super annoying because they sometimes need to be handled case by case + // We might need to lookinto a matching algorithm to identify the union type that most closely + // matches our strace type. + + switch syzType.TypeName { + case "sockaddr_storage": + return genSockaddrStorage(syzType, straceType, ctx) + case "sockaddr_nl": + return genSockaddrNetlink(syzType, straceType, ctx) + case "ifr_ifru": + return genIfrIfru(syzType, straceType, ctx) + } + return prog.MakeUnionArg(syzType, genArgs(syzType.Fields[0], straceType, ctx)) +} + +func genBuffer(syzType *prog.BufferType, traceType parser.IrType, ctx *Context) prog.Arg { + if syzType.Dir() == prog.DirOut { + if !syzType.Varlen() { + return prog.MakeOutDataArg(syzType, syzType.Size()) + } + switch a := traceType.(type) { + case *parser.BufferType: + return prog.MakeOutDataArg(syzType, uint64(len(a.Val))) + default: + switch syzType.Kind { + case prog.BufferBlobRand: + size := rand.Intn(256) + return prog.MakeOutDataArg(syzType, uint64(size)) + + case prog.BufferBlobRange: + max := rand.Intn(int(syzType.RangeEnd) - int(syzType.RangeBegin) + 1) + size := max + int(syzType.RangeBegin) + return prog.MakeOutDataArg(syzType, uint64(size)) + default: + log.Fatalf("unexpected buffer type kind: %v. call %v arg %#v", syzType.Kind, ctx.CurrentSyzCall, traceType) + } + } + } + var bufVal []byte + switch a := traceType.(type) { + case *parser.BufferType: + bufVal = []byte(a.Val) + case parser.Constant: + val := a.Val() + bArr := make([]byte, 8) + binary.LittleEndian.PutUint64(bArr, val) + bufVal = bArr + default: + log.Fatalf("unsupported type for buffer: %#v", traceType) + } + if !syzType.Varlen() { + size := syzType.Size() + for uint64(len(bufVal)) < size { + bufVal = append(bufVal, 0) + } + bufVal = bufVal[:size] + } + return prog.MakeDataArg(syzType, bufVal) +} + +func genPtr(syzType *prog.PtrType, traceType parser.IrType, ctx *Context) prog.Arg { + switch a := traceType.(type) { + case parser.Constant: + if a.Val() == 0 { + return prog.MakeSpecialPointerArg(syzType, 0) + } + // Likely have a type of the form bind(3, 0xfffffffff, [3]); + res := prog.DefaultArg(syzType.Type) + return addr(ctx, syzType, res.Size(), res) + default: + res := genArgs(syzType.Type, a, ctx) + return addr(ctx, syzType, res.Size(), res) + } +} + +func genConst(syzType prog.Type, traceType parser.IrType, ctx *Context) prog.Arg { + switch a := traceType.(type) { + case parser.Constant: + return prog.MakeConstArg(syzType, a.Val()) + case *parser.GroupType: + // Sometimes strace represents a pointer to int as [0] which gets parsed + // as Array([0], len=1). A good example is ioctl(3, FIONBIO, [1]). We may also have an union int type that + // is a represented as a struct in strace e.g. + // sigev_value={sival_int=-2123636944, sival_ptr=0x7ffd816bdf30} + // For now we choose the first option + if len(a.Elems) == 0 { + log.Logf(2, "parsing const type, got array type with len 0") + return prog.DefaultArg(syzType) + } + return genConst(syzType, a.Elems[0], ctx) + case *parser.BufferType: + // The call almost certainly returned an errno + return prog.DefaultArg(syzType) + default: + log.Fatalf("unsupported type for const: %#v", traceType) + } + return nil +} + +func genResource(syzType *prog.ResourceType, traceType parser.IrType, ctx *Context) prog.Arg { + if syzType.Dir() == prog.DirOut { + log.Logf(2, "resource returned by call argument: %s", traceType.String()) + res := prog.MakeResultArg(syzType, nil, syzType.Default()) + ctx.ReturnCache.cache(syzType, traceType, res) + return res + } + switch a := traceType.(type) { + case parser.Constant: + val := a.Val() + if arg := ctx.ReturnCache.get(syzType, traceType); arg != nil { + res := prog.MakeResultArg(syzType, arg.(*prog.ResultArg), syzType.Default()) + return res + } + res := prog.MakeResultArg(syzType, nil, val) + return res + case *parser.GroupType: + if len(a.Elems) == 1 { + // For example: 5028 ioctl(3, SIOCSPGRP, [0]) = 0 + // last argument is a pointer to a resource. Strace will output a pointer to + // a number x as [x]. + res := prog.MakeResultArg(syzType, nil, syzType.Default()) + ctx.ReturnCache.cache(syzType, a.Elems[0], res) + return res + } + log.Fatalf("generating resource type from GroupType with %d elements", len(a.Elems)) + default: + log.Fatalf("unsupported type for resource: %#v", traceType) + } + return nil +} + +func parseProc(syzType *prog.ProcType, traceType parser.IrType, ctx *Context) prog.Arg { + switch a := traceType.(type) { + case parser.Constant: + val := a.Val() + if val >= syzType.ValuesPerProc { + return prog.MakeConstArg(syzType, syzType.ValuesPerProc-1) + } + return prog.MakeConstArg(syzType, val) + case *parser.BufferType: + // Again probably an error case + // Something like the following will trigger this + // bind(3, {sa_family=AF_INET, sa_data="\xac"}, 3) = -1 EINVAL(Invalid argument) + return prog.DefaultArg(syzType) + default: + log.Fatalf("unsupported type for proc: %#v", traceType) + } + return nil +} + +func addr(ctx *Context, syzType prog.Type, size uint64, data prog.Arg) prog.Arg { + arg := prog.MakePointerArg(syzType, uint64(0), data) + ctx.Tracker.addAllocation(ctx.CurrentSyzCall, size, arg) + return arg +} + +func reorderStructFields(syzType *prog.StructType, traceType *parser.GroupType, ctx *Context) { + // Sometimes strace reports struct fields out of order compared to our descriptions + // Example: 5704 bind(3, {sa_family=AF_INET6, + // sin6_port=htons(8888), + // inet_pton(AF_INET6, "::", &sin6_addr), + // sin6_flowinfo=htonl(2206138368), + // sin6_scope_id=2049825634}, 128) = 0 + // The flow_info and pton fields are switched in our description + + switch syzType.TypeName { + case "sockaddr_in6": + log.Logf(5, "reordering in6. trace struct has %d elems", len(traceType.Elems)) + if len(traceType.Elems) < 4 { + return + } + field2 := traceType.Elems[2] + traceType.Elems[2] = traceType.Elems[3] + traceType.Elems[3] = field2 + } +} + +func shouldSkip(ctx *Context) bool { + syscall := ctx.CurrentStraceCall + if config.ShouldSkip[syscall.CallName] { + return true + } + switch syscall.CallName { + case "write": + // We skip all writes to stdout and stderr because they can corrupt our crash summary + switch a := syscall.Args[0].(type) { + case parser.Constant: + val := a.Val() + if val == 1 || val == 2 { + return true + } + } + } + return false +} diff --git a/tools/syz-trace2syz/proggen/proggen_test.go b/tools/syz-trace2syz/proggen/proggen_test.go new file mode 100644 index 000000000..47a879333 --- /dev/null +++ b/tools/syz-trace2syz/proggen/proggen_test.go @@ -0,0 +1,337 @@ +// Copyright 2018 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package proggen + +import ( + "fmt" + "strings" + "testing" + + "github.com/google/syzkaller/pkg/log" + "github.com/google/syzkaller/prog" + _ "github.com/google/syzkaller/sys" + "github.com/google/syzkaller/tools/syz-trace2syz/parser" +) + +var ( + OS = "linux" + Arch = "amd64" +) + +func initializeTarget(os, arch string) *prog.Target { + target, err := prog.GetTarget(os, arch) + if err != nil { + log.Fatalf("%s", err) + } + target.ConstMap = make(map[string]uint64) + for _, c := range target.Consts { + target.ConstMap[c.Name] = c.Value + } + return target +} + +func parseSingleTrace(t *testing.T, data string) *Context { + var traceTree *parser.TraceTree + var ctx *Context + + target := initializeTarget(OS, Arch) + selector := NewCallSelector() + traceTree = parser.ParseLoop(data) + ctx = GenSyzProg(traceTree.TraceMap[traceTree.RootPid], target, selector) + ctx.FillOutMemory() + if err := ctx.Prog.Validate(); err != nil { + t.Fatalf("failed to parse trace: %s", err.Error()) + } + return ctx +} + +func TestParseTraceBasic(t *testing.T) { + test := `open("file", 66) = 3 + write(3, "somedata", 8) = 8` + ctx := parseSingleTrace(t, test) + p := ctx.Prog + expectedSeq := "open-write" + if p.String() != expectedSeq { + t.Fatalf("expected: %s != %s", expectedSeq, p.String()) + } + switch a := p.Calls[1].Args[0].(type) { + case *prog.ResultArg: + if a.Res != p.Calls[0].Ret { + t.Fatalf("first argument of write should equal result of open.") + } + default: + t.Fatalf("expected result arg, got: %s\n", a.Type().Name()) + } +} + +func TestParseTraceInnerResource(t *testing.T) { + test := `pipe([5,6]) = 0 + write(6, "\xff\xff\xfe\xff", 4) = 4` + p := parseSingleTrace(t, test).Prog + expectedSeq := "pipe-write" + if p.String() != expectedSeq { + t.Fatalf("Expected: %s != %s", expectedSeq, p.String()) + } + switch a := p.Calls[1].Args[0].(type) { + case *prog.ResultArg: + pipeSecondFd := p.Calls[0].Args[0].(*prog.PointerArg).Res.(*prog.GroupArg).Inner[1] + if a.Res != pipeSecondFd { + t.Fatalf("first argument of write must match second fd from pipe") + } + default: + t.Fatalf("expected result arg, got: %s\n", a.Type().Name()) + } +} + +func TestNegativeResource(t *testing.T) { + test := `socket(29, 3, 1) = 3 + getsockopt(-1, 132, 119, 0x200005c0, [14]) = -1 EBADF (Bad file descriptor)` + + p := parseSingleTrace(t, test).Prog + expectedSeq := "socket$can_raw-getsockopt$inet_sctp6_SCTP_RESET_STREAMS" + if p.String() != expectedSeq { + t.Fatalf("expected: %s != %s", expectedSeq, p.String()) + } + switch a := p.Calls[1].Args[0].(type) { + case *prog.ResultArg: + if a.Val != ^uint64(0) { + t.Fatalf("expected resource type to be negative, got: %d", a.Val) + } + default: + t.Fatalf("expected result arg, got: %s\n", a.Type().Name()) + } +} + +func TestDistinguishResourceTypes(t *testing.T) { + test := `inotify_init() = 2 + open("tmp", 66) = 3 + inotify_add_watch(3, "\x2e", 0xfff) = 3 + write(3, "temp", 5) = 5 + inotify_rm_watch(2, 3) = 0` + expectedSeq := "inotify_init-open-inotify_add_watch-write-inotify_rm_watch" + p := parseSingleTrace(t, test).Prog + if p.String() != expectedSeq { + t.Fatalf("Expected: %s != %s", expectedSeq, p.String()) + } + write := p.Calls[len(p.Calls)-2] + inotifyRmWatch := p.Calls[len(p.Calls)-1] + switch a := write.Args[0].Type().(type) { + case *prog.ResourceType: + if a.TypeName != "fd" { + t.Fatalf("expected first argument of write to have type fd, got: %s", a.TypeName) + } + default: + t.Fatalf("first argument of write is not resource type: %s", a.Name()) + } + switch a := inotifyRmWatch.Args[1].(type) { + case *prog.ResultArg: + b := a.Type().(*prog.ResourceType) + if b.TypeName != "inotifydesc" { + t.Fatalf("expected second argument of inotify_rm_watch to have type inoitfydesc, got: %s", b.TypeName) + } + if a.Res != p.Calls[2].Ret { + t.Fatalf("inotify_rm_watch's second argument should match the result of inotify_add_watch.") + } + } +} + +func TestSocketLevel(t *testing.T) { + test := `socket(1, 1, 0) = 3 + socket(1, 1 | 2048, 0) = 3 + socket(1, 1 | 524288, 0) = 3 + socket(1, 1 | 524288, 0) = 3` + expectedSeq := "socket$unix-socket$unix-socket$unix-socket$unix" + p := parseSingleTrace(t, test).Prog + if p.String() != expectedSeq { + t.Fatalf("Expected: %s != %s", expectedSeq, p.String()) + } +} + +func TestIdentifySockaddrStorage(t *testing.T) { + type identifyStorageTest struct { + test string + expectedSeq string + callIdx int + argIdx int + fieldName string + } + tests := []identifyStorageTest{ + { + `open("temp", 1) = 3 + connect(3, {sa_family=2, sin_port=37957, sin_addr=0x0}, 16) = -1`, + "open-connect", + 1, + 1, + "sockaddr_in", + }, + { + `open("temp", 1) = 3 + connect(3, {sa_family=1, sun_path="temp"}, 110) = -1`, + "open-connect", + 1, + 1, + "sockaddr_un", + }, + { + `open("temp", 1) = 3 + bind(5, {sa_family=16, nl_pid=0, nl_groups=00000000}, 12) = -1`, + "open-bind", + 1, + 1, + "sockaddr_nl", + }, + } + + validator := func(arg prog.Arg, field string) error { + var ( + storageArg *prog.UnionArg + storagePtr *prog.PointerArg + ok bool + ) + storagePtr = arg.(*prog.PointerArg) + if storageArg, ok = storagePtr.Res.(*prog.UnionArg); !ok { + t.Fatalf("second argument not union: %s", storagePtr.Res.Type().Name()) + } + fieldName := storageArg.Option.Type().Name() + if fieldName != field { + return fmt.Errorf("incorrect storage type, expected %s != %s", field, fieldName) + } + return nil + } + + for i, test := range tests { + p := parseSingleTrace(t, test.test).Prog + if p.String() != test.expectedSeq { + t.Fatalf("failed btest: %d, expected: %s != %s", i, test.expectedSeq, p.String()) + } + err := validator(p.Calls[test.callIdx].Args[test.argIdx], test.fieldName) + if err != nil { + t.Fatalf("failed subtest: %d with err: %s", i, err) + } + } +} + +func TestIdentifyIfru(t *testing.T) { + type testIfru struct { + test string + expectedSeq string + } + tests := []testIfru{ + { + `socket(17, 3, 768) = 3 + ioctl(3, 35111, {ifr_name="\x6c\x6f", ifr_hwaddr=00:00:00:00:00:00}) = 0`, + "socket$packet-ioctl$sock_ifreq", + }, + } + + for i, test := range tests { + p := parseSingleTrace(t, test.test).Prog + if p.String() != test.expectedSeq { + t.Fatalf("failed subtest: %d, expected %s != %s", i, test.expectedSeq, p.String()) + } + } +} + +func TestParseVariants(t *testing.T) { + type variantTest struct { + test string + expectedSeq string + } + tests := []variantTest{ + { + `socket(1, 1, 0) = 3 + connect(3, {sa_family=1, sun_path="temp"}, 110) = -1 ENOENT (Bad file descriptor)`, + "socket$unix-connect$unix", + }, + { + `socket(1, 1, 0) = 3`, + "socket$unix", + }, + { + `socket(2, 1, 0) = 5 + ioctl(5, 21537, [1]) = 0`, + "socket$inet_tcp-ioctl$int_in", + }, + { + `socket(2, 1, 0) = 3 + setsockopt(3, 1, 2, [1], 4) = 0`, + "socket$inet_tcp-setsockopt$sock_int", + }, + { + `9795 socket(17, 3, 768) = 3 + 9795 ioctl(3, 35123, {ifr_name="\x6c\x6f", }) = 0`, + "socket$packet-ioctl$ifreq_SIOCGIFINDEX_team", + }, + { + `open("temp", 1) = 3 + connect(3, {sa_family=2, sin_port=17812, sin_addr=0x0}, 16) = -1`, + "open-connect", + }, + { + `ioprio_get(1, 0) = 4`, + "ioprio_get$pid", + }, + { + `socket(17, 2, 768) = 3`, + "socket$packet", + }, + } + + for i, test := range tests { + p := parseSingleTrace(t, test.test).Prog + if p.String() != test.expectedSeq { + t.Fatalf("failed subtest: %d, expected %s != %s", i, test.expectedSeq, p.String()) + } + } +} + +func TestParseIPv4(t *testing.T) { + type ip4test struct { + test string + expectedSeq string + ip4 uint64 + } + tests := []ip4test{ + { + `socket(2, 1, 0) = 3 + connect(3, {sa_family=2, sin_port=17812, sin_addr=0x0}, 16) = 0`, + "socket$inet_tcp-connect$inet", + 0, + }, + { + `socket(2, 1, 0) = 3 + connect(3, {sa_family=2, sin_port=17812, sin_addr=0x7f000001}, 16) = 0`, + "socket$inet_tcp-connect$inet", + 0x7f000001, + }, + } + testIpv4 := func(expectedIp uint64, a prog.Arg, t *testing.T) { + sockaddr, ok := a.(*prog.PointerArg).Res.(*prog.GroupArg) + if !ok { + t.Fatalf("%s", a.Type().Name()) + } + ipv4Addr, ok := sockaddr.Inner[2].(*prog.UnionArg) + if !ok { + t.Fatalf("expected 3rd argument to be unionArg, got %s", sockaddr.Inner[2].Type().Name()) + } + optName := ipv4Addr.Option.Type().FieldName() + if !strings.Contains(optName, "rand") { + t.Fatalf("expected ip option to be random opt, got: %s", optName) + } + ip, ok := ipv4Addr.Option.(*prog.ConstArg) + if !ok { + t.Fatalf("ipv4Addr option is not IntType") + } + if ip.Val != expectedIp { + t.Fatalf("parsed != expected, %d != %d", ip.Val, expectedIp) + } + } + for i, test := range tests { + p := parseSingleTrace(t, test.test).Prog + if p.String() != test.expectedSeq { + t.Fatalf("failed subtest: %d, expected %s != %s", i, test.expectedSeq, p.String()) + } + testIpv4(test.ip4, p.Calls[1].Args[1], t) + } +} diff --git a/tools/syz-trace2syz/proggen/return_cache.go b/tools/syz-trace2syz/proggen/return_cache.go new file mode 100644 index 000000000..64b0f804d --- /dev/null +++ b/tools/syz-trace2syz/proggen/return_cache.go @@ -0,0 +1,52 @@ +package proggen + +import ( + "github.com/google/syzkaller/pkg/log" + "github.com/google/syzkaller/prog" + "github.com/google/syzkaller/tools/syz-trace2syz/parser" +) + +type resourceDescription struct { + Type string + Val string +} + +type returnCache map[resourceDescription]prog.Arg + +func newRCache() returnCache { + return make(map[resourceDescription]prog.Arg) +} + +func (r *returnCache) buildKey(syzType prog.Type) string { + switch a := syzType.(type) { + case *prog.ResourceType: + return a.Desc.Kind[0] + default: + log.Fatalf("caching non resource type") + } + return "" +} + +func (r *returnCache) cache(syzType prog.Type, traceType parser.IrType, arg prog.Arg) { + log.Logf(2, "caching resource: %s, val: %s", r.buildKey(syzType), traceType.String()) + resDesc := resourceDescription{ + Type: r.buildKey(syzType), + Val: traceType.String(), + } + (*r)[resDesc] = arg +} + +func (r *returnCache) get(syzType prog.Type, traceType parser.IrType) prog.Arg { + log.Logf(2, "fetching resource: %s, val: %s", r.buildKey(syzType), traceType.String()) + resDesc := resourceDescription{ + Type: r.buildKey(syzType), + Val: traceType.String(), + } + if arg, ok := (*r)[resDesc]; ok { + if arg != nil { + log.Logf(2, "cache hit for resource type: %s, val: %s", r.buildKey(syzType), traceType.String()) + return arg + } + } + return nil +} diff --git a/tools/syz-trace2syz/trace2syz.go b/tools/syz-trace2syz/trace2syz.go new file mode 100644 index 000000000..600171bd9 --- /dev/null +++ b/tools/syz-trace2syz/trace2syz.go @@ -0,0 +1,173 @@ +// Copyright 2018 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// syz-trace2syz converts strace traces to syzkaller programs. +// +// Simple usage: +// strace -o trace -a 1 -s 65500 -v -xx -f -Xraw ./a.out +// syz-trace2syz -file trace +// Intended for seed selection or debugging +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strconv" + + "github.com/google/syzkaller/pkg/db" + "github.com/google/syzkaller/pkg/hash" + "github.com/google/syzkaller/pkg/log" + "github.com/google/syzkaller/prog" + _ "github.com/google/syzkaller/sys" + "github.com/google/syzkaller/tools/syz-trace2syz/parser" + "github.com/google/syzkaller/tools/syz-trace2syz/proggen" +) + +var ( + flagFile = flag.String("file", "", "file to parse") + flagDir = flag.String("dir", "", "directory to parse") + flagDeserialize = flag.String("deserialize", "", "(Optional) directory to store deserialized programs") + callSelector = proggen.NewCallSelector() +) + +const ( + goos = "linux" // Target OS + arch = "amd64" // Target architecture + currentDBVersion = 3 // Marked as minimized +) + +func main() { + flag.Parse() + target := initializeTarget(goos, arch) + progs := parseTraces(target) + log.Logf(0, "successfully converted traces; generating corpus.db") + pack(progs) +} + +func initializeTarget(os, arch string) *prog.Target { + target, err := prog.GetTarget(os, arch) + if err != nil { + log.Fatalf("failed to load target: %s", err) + } + target.ConstMap = make(map[string]uint64) + for _, c := range target.Consts { + target.ConstMap[c.Name] = c.Value + } + return target +} + +func parseTraces(target *prog.Target) []*prog.Prog { + var ret []*prog.Prog + var names []string + + if *flagFile != "" { + names = append(names, *flagFile) + } else if *flagDir != "" { + names = getTraceFiles(*flagDir) + } else { + log.Fatalf("-file or -dir must be specified") + } + + deserializeDir := *flagDeserialize + + totalFiles := len(names) + log.Logf(0, "parsing %d traces", totalFiles) + for i, file := range names { + log.Logf(1, "parsing File %d/%d: %s", i+1, totalFiles, filepath.Base(names[i])) + tree := parser.Parse(file) + if tree == nil { + log.Logf(1, "file: %s is empty", filepath.Base(file)) + continue + } + ctxs := parseTree(tree, tree.RootPid, target) + for i, ctx := range ctxs { + ctx.Prog.Target = ctx.Target + err := ctx.FillOutMemory() + if err != nil { + log.Logf(1, "failed to fill out memory %s", err) + continue + } + if err := ctx.Prog.Validate(); err != nil { + log.Fatalf("error validating program: %s", err) + } + if progIsTooLarge(ctx.Prog) { + log.Logf(1, "prog is too large") + continue + } + ret = append(ret, ctx.Prog) + if deserializeDir == "" { + continue + } + progName := filepath.Join(deserializeDir, filepath.Base(file)+strconv.Itoa(i)) + if err := ioutil.WriteFile(progName, ctx.Prog.Serialize(), 0640); err != nil { + log.Fatalf("failed to output file: %v", err) + } + } + + } + return ret +} + +func progIsTooLarge(p *prog.Prog) bool { + buff := make([]byte, prog.ExecBufferSize) + if _, err := p.SerializeForExec(buff); err != nil { + return true + } + return false +} + +func getTraceFiles(dir string) []string { + var names []string + infos, err := ioutil.ReadDir(dir) + if err != nil { + log.Fatalf("%s", err) + + } + for _, info := range infos { + name := filepath.Join(dir, info.Name()) + names = append(names, name) + } + return names +} + +// parseTree groups system calls in the trace by process id. +// The tree preserves process hierarchy i.e. parent->[]child +func parseTree(tree *parser.TraceTree, pid int64, target *prog.Target) []*proggen.Context { + log.Logf(2, "parsing trace: %s", tree.Filename) + var ctxs []*proggen.Context + ctx := proggen.GenSyzProg(tree.TraceMap[pid], target, callSelector) + + ctxs = append(ctxs, ctx) + for _, childPid := range tree.Ptree[pid] { + if tree.TraceMap[childPid] != nil { + ctxs = append(ctxs, parseTree(tree, childPid, target)...) + } + } + return ctxs +} + +func pack(progs []*prog.Prog) { + corpusDb := "corpus.db" + os.Remove(corpusDb) + syzDb, err := db.Open(corpusDb) + + if err != nil { + log.Fatalf("failed to open database file: %v", err) + } + syzDb.BumpVersion(currentDBVersion) + for i, prog := range progs { + data := prog.Serialize() + key := hash.String(data) + if _, ok := syzDb.Records[key]; ok { + key += fmt.Sprint(i) + } + syzDb.Save(key, data, 0) + } + if err := syzDb.Flush(); err != nil { + log.Fatalf("failed to save database file: %v", err) + } + log.Logf(0, "finished!") +} -- cgit mrf-deployment