How to use Scan method of prog Package

Best Syzkaller code snippet using prog.Scan

map.go

Source:map.go Github

copy

Full Screen

...48 print = printText49 case "decoder":50 print = printDecoder51 case "scanner":52 print = printScanner53 }54 p, err := readCSV(flag.Arg(0))55 if err != nil {56 log.Fatal(err)57 }58 //p = mergeTail(p)59 print(p)60}61// readCSV reads the CSV file and returns the corresponding Prog.62// It may print details about problems to standard error using the log package.63func readCSV(file string) (*Prog, error) {64 // Read input.65 // Skip leading blank and # comment lines.66 f, err := os.Open(file)67 if err != nil {68 return nil, err69 }70 b := bufio.NewReader(f)71 for {72 c, err := b.ReadByte()73 if err != nil {74 break75 }76 if c == '\n' {77 continue78 }79 if c == '#' {80 b.ReadBytes('\n')81 continue82 }83 b.UnreadByte()84 break85 }86 table, err := csv.NewReader(b).ReadAll()87 if err != nil {88 return nil, fmt.Errorf("parsing %s: %v", file, err)89 }90 if len(table) == 0 {91 return nil, fmt.Errorf("empty csv input")92 }93 if len(table[0]) < 6 {94 return nil, fmt.Errorf("csv too narrow: need at least six columns")95 }96 p := &Prog{}97 for _, row := range table {98 add(p, row[0], row[1], row[2], row[3], row[4], row[5])99 }100 check(p)101 return p, nil102}103// A Prog is a single node in the tree representing the instruction format.104// Collectively the tree of nodes form a kind of program for decoding.105// Each Prog has a single action, identifying the kind of node it is,106// and then children to be executed according to the action.107// For example, the Prog with Action="decode" has children named for each108// possible next byte in the input, and those children are the decoding109// tree to execute for the corresponding bytes.110type Prog struct {111 Path string112 Action string113 Child map[string]*Prog114 PC int115 TailID int116}117// keys returns the child keys in sorted order.118func (p *Prog) keys() []string {119 var keys []string120 for key := range p.Child {121 keys = append(keys, key)122 }123 sort.Strings(keys)124 return keys125}126// findChildLeaf finds a leaf node in the subtree rooted at p127// and returns that node's full path. The path is useful in error128// messages as an example of where a particular subtree is headed.129func (p *Prog) findChildLeaf() string {130 for {131 if len(p.Child) == 0 {132 return p.Path133 }134 p = p.Child[p.keys()[0]]135 }136}137// walk advances from p to apply the given action and key.138// If p has no action yet, the action is recorded as p.Action.139// Otherwise the action must match p's action: every node in the140// tree can have at most one action, although possibly with many141// alternative keys.142// If p already has an alternative with the given key, walk returns143// that preexisting subtree. Otherwise walk allocates a new Prog144// representing that subtree and returns that node.145func (p *Prog) walk(action, key, text, opcode string) *Prog {146 if p.Action == "" {147 p.Action = action148 } else if p.Action != action {149 log.Printf("%s; %s: conflicting paths %s and %s|%s %s\n", text, opcode, p.findChildLeaf(), p.Path, action, key)150 return new(Prog)151 }152 q := p.Child[key]153 if q == nil {154 if p.Child == nil {155 p.Child = make(map[string]*Prog)156 }157 q = new(Prog)158 q.Path = fmt.Sprintf("%s|%s %s", p.Path, action, key)159 p.Child[key] = q160 }161 return q162}163// add adds a single instructions to the tree rooted at root.164// The string arguments match the CSV: instruction mnemonic,165// opcode encoding, validity in 32- and 64-bit modes, CPUID166// feature set (ignored), and additional tags.167//168// In effect, add adds a new path through the tree leading to169// the given instruction, but it reuses as much of the existing170// tree structure as possible. For example if there have already171// been instructions added starting with 0F and this instruction172// also starts with 0F, that 0F subtree node is reused instead of173// allocating a parallel one. To maximize the reuse, the check action174// sequence along the path being added is the same for every instruction:175// encoding pieces needed to make a decision, 64-bit mode check,176// rex check, prefix check, address size check, data size check,177// register vs memory argument check. Once all those checks have178// been applied, the assumption is that we have uniquely identified179// an instruction, and at that point it is okay to diverge from the180// uniform pattern to set the opcode and read the specific arguments181// corresponding to the instruction at hand.182//183// The maximimal reuse of the existing tree means that the tree184// resulting from all adds have been done amounts to a decision tree.185// There is one detail that makes it non-deterministic: some checks186// do not matter to some instructions and those are recorded as "any" keys.187// If you are decoding and there is a key for the specific thing you are188// seeing as well as the "any" key, both must be considered. To avoid189// adding complexity to the decoder execution, the 'check' function190// removes this case by merging "any" trees into specific keys when191// present.192func add(root *Prog, text, opcode, valid32, valid64, cpuid, tags string) {193 // These are not real instructions: they are either194 // prefixes for other instructions, composite instructions195 // built from multiple individual instructions, or alternate196 // mnemonics of other encodings.197 // Discard for disassembly, because we want a unique decoding.198 if strings.Contains(tags, "pseudo") {199 return200 }201 // Treat REX.W + opcode as being like having an "operand64" tag.202 // The REX.W flag sets the operand size to 64 bits; in this way it is203 // not much different than the 66 prefix that inverts 32 vs 16 bits.204 if strings.Contains(opcode, "REX.W") {205 if !strings.Contains(tags, "operand64") {206 if tags != "" {207 tags += ","208 }209 tags += "operand64"210 }211 }212 // If there is more than one operand size given, we need to do213 // a separate add for each size, because we need multiple214 // keys to be added in the operand size branch, and the code makes215 // a linear pass through the tree adding just one key to each node.216 // We would need to do the same for any other possible repeated tag217 // (for example, if an instruction could have multiple address sizes)218 // but so far operand size is the only tag we have needed to repeat.219 if strings.Count(tags, "operand") > 1 {220 f := strings.Split(tags, ",")221 var ops []string222 w := 0223 for _, tag := range f {224 if strings.HasPrefix(tag, "operand") {225 ops = append(ops, tag)226 } else {227 if strings.Contains(tag, "operand") {228 log.Fatalf("unknown tag %q", tag)229 }230 f[w] = tag231 w++232 }233 }234 f = f[:w]235 for _, op := range ops {236 add(root, text, opcode, valid32, valid64, cpuid, strings.Join(append(f, op), ","))237 }238 return239 }240 p := root241 walk := func(action, item string) {242 p = p.walk(action, item, text, opcode)243 }244 // Ignore VEX instructions for now.245 if strings.HasPrefix(opcode, "VEX") {246 if !strings.HasPrefix(text, "VMOVNTDQ") &&247 !strings.HasPrefix(text, "VMOVDQA") &&248 !strings.HasPrefix(text, "VMOVDQU") &&249 !strings.HasPrefix(text, "VZEROUPPER") {250 return251 }252 if !strings.HasPrefix(opcode, "VEX.256") && !strings.HasPrefix(text, "VZEROUPPER") {253 return254 }255 if !strings.Contains(tags, "VEXC4") {256 add(root, text, opcode, valid32, valid64, cpuid, tags+",VEXC4")257 }258 encoding := strings.Fields(opcode)259 walk("decode", encoding[1])260 walk("is64", "any")261 if strings.Contains(tags, "VEXC4") {262 walk("prefix", "C4")263 } else {264 walk("prefix", "C5")265 }266 for _, pref := range strings.Split(encoding[0], ".") {267 if isVexEncodablePrefix[pref] {268 walk("prefix", pref)269 }270 }271 }272 var rex, prefix string273 encoding := strings.Fields(opcode)274 if len(encoding) > 0 && strings.HasPrefix(encoding[0], "REX") {275 rex = encoding[0]276 encoding = encoding[1:]277 if len(encoding) > 0 && encoding[0] == "+" {278 encoding = encoding[1:]279 }280 }281 if len(encoding) > 0 && isPrefix[encoding[0]] {282 prefix = encoding[0]283 encoding = encoding[1:]284 }285 if rex == "" && len(encoding) > 0 && strings.HasPrefix(encoding[0], "REX") {286 rex = encoding[0]287 if rex == "REX" {288 log.Printf("REX without REX.W: %s %s", text, opcode)289 }290 encoding = encoding[1:]291 if len(encoding) > 0 && encoding[0] == "+" {292 encoding = encoding[1:]293 }294 }295 if len(encoding) > 0 && isPrefix[encoding[0]] {296 log.Printf("%s %s: too many prefixes", text, opcode)297 return298 }299 var haveModRM, havePlus bool300 var usedReg string301 for len(encoding) > 0 && (isHex(encoding[0]) || isSlashNum(encoding[0])) {302 key := encoding[0]303 if isSlashNum(key) {304 if usedReg != "" {305 log.Printf("%s %s: multiple modrm checks", text, opcode)306 }307 haveModRM = true308 usedReg = key309 }310 if i := strings.Index(key, "+"); i >= 0 {311 key = key[:i+1]312 havePlus = true313 }314 walk("decode", key)315 encoding = encoding[1:]316 }317 if valid32 != "V" {318 walk("is64", "1")319 } else if valid64 != "V" {320 walk("is64", "0")321 } else {322 walk("is64", "any")323 }324 if prefix == "" {325 prefix = "0"326 }327 walk("prefix", prefix)328 if strings.Contains(tags, "address16") {329 walk("addrsize", "16")330 } else if strings.Contains(tags, "address32") {331 walk("addrsize", "32")332 } else if strings.Contains(tags, "address64") {333 walk("addrsize", "64")334 } else {335 walk("addrsize", "any")336 }337 if strings.Contains(tags, "operand16") {338 walk("datasize", "16")339 } else if strings.Contains(tags, "operand32") {340 walk("datasize", "32")341 } else if strings.Contains(tags, "operand64") {342 walk("datasize", "64")343 } else {344 walk("datasize", "any")345 }346 if len(encoding) > 0 && encoding[0] == "/r" {347 haveModRM = true348 }349 if haveModRM {350 if strings.Contains(tags, "modrm_regonly") {351 walk("ismem", "0")352 } else if strings.Contains(tags, "modrm_memonly") {353 walk("ismem", "1")354 } else {355 walk("ismem", "any")356 }357 }358 walk("op", strings.Fields(text)[0])359 if len(encoding) > 0 && strings.HasPrefix(encoding[0], "VEX") {360 for _, field := range encoding[2:] {361 walk("read", field)362 }363 } else {364 for _, field := range encoding {365 walk("read", field)366 }367 }368 var usedRM string369 for _, arg := range strings.Fields(text)[1:] {370 arg = strings.TrimRight(arg, ",")371 if usesReg[arg] && !haveModRM && !havePlus {372 log.Printf("%s %s: no modrm field to use for %s", text, opcode, arg)373 continue374 }375 if usesRM[arg] && !haveModRM {376 log.Printf("%s %s: no modrm field to use for %s", text, opcode, arg)377 continue378 }379 if usesReg[arg] {380 if usedReg != "" {381 log.Printf("%s %s: modrm reg field used by both %s and %s", text, opcode, usedReg, arg)382 continue383 }384 usedReg = arg385 }386 if usesRM[arg] {387 if usedRM != "" {388 log.Printf("%s %s: modrm r/m field used by both %s and %s", text, opcode, usedRM, arg)389 continue390 }391 usedRM = arg392 }393 walk("arg", arg)394 }395 walk("match", "!")396}397// allKeys records the list of all possible child keys for actions that support "any".398var allKeys = map[string][]string{399 "is64": {"0", "1"},400 "ismem": {"0", "1"},401 "addrsize": {"16", "32", "64"},402 "datasize": {"16", "32", "64"},403}404// check checks that the program tree is well-formed.405// It also merges "any" keys into specific decoding keys in order to406// create an invariant that a particular check node either has a407// single "any" child - making it a no-op - or has no "any" children.408// See the discussion of "any" in the comment for add above.409func check(p *Prog) {410 if p.Child["any"] != nil && len(p.Child) > 1 {411 for _, key := range p.keys() {412 if key != "any" {413 mergeCopy(p.Child[key], p.Child["any"])414 }415 }416 if allKeys[p.Action] == nil {417 log.Printf("%s: unknown key space for %s=any", p.Path, p.Action)418 }419 for _, key := range allKeys[p.Action] {420 if p.Child[key] == nil {421 p.Child[key] = p.Child["any"]422 }423 }424 delete(p.Child, "any")425 }426 for _, q := range p.Child {427 check(q)428 }429 switch p.Action {430 case "op", "read", "arg":431 if len(p.Child) > 1 {432 log.Printf("%s: multiple children for action=%s: %v", p.Path, p.Action, p.keys())433 }434 }435}436// mergeCopy merges a copy of the tree rooted at src into dst.437// It is only used once no more paths will be added to the tree,438// so it is safe to introduce cross-links that make the program439// a dag rather than a tree.440func mergeCopy(dst, src *Prog) {441 //log.Printf("merge %s|%s and %s|%s\n", dst.Path, dst.Action, src.Path, src.Action)442 if dst.Action != src.Action {443 log.Printf("cannot merge %s|%s and %s|%s", dst.Path, dst.Action, src.Path, src.Action)444 return445 }446 for _, key := range src.keys() {447 if dst.Child[key] == nil {448 // Create new subtree by creating cross-link.449 dst.Child[key] = src.Child[key]450 } else {451 // Merge src subtree into existing dst subtree.452 mergeCopy(dst.Child[key], src.Child[key])453 }454 }455}456// set returns a map mapping each of the words in all to true.457func set(all string) map[string]bool {458 m := map[string]bool{}459 for _, f := range strings.Fields(all) {460 m[f] = true461 }462 return m463}464// isPrefix records the x86 opcode prefix bytes.465var isPrefix = set(`466 26467 2E468 36469 3E470 64471 65472 66473 67474 F0475 F2476 F3477`)478// usesReg records the argument codes that use the modrm reg field.479var usesReg = set(`480 r8481 r16482 r32483 r64484`)485// usesRM records the argument codes that use the modrm r/m field.486var usesRM = set(`487 r/m8488 r/m16489 r/m32490 r/m64491`)492var isVexEncodablePrefix = set(`493 0F494 0F38495 0F3A496 66497 F3498 F2499`)500// isHex reports whether the argument is a two digit hex number501// possibly followed by a +foo suffix.502func isHex(s string) bool {503 if i := strings.Index(s, "+"); i >= 0 {504 s = s[:i]505 }506 if len(s) != 2 {507 return false508 }509 for i := 0; i < len(s); i++ {510 c := s[i]511 if '0' <= c && c <= '9' || 'A' <= c && c <= 'F' {512 continue513 }514 return false515 }516 return true517}518// isSlashNum reports whether the argument is /n for some number n in [0,7].519func isSlashNum(s string) bool {520 return len(s) == 2 && s[0] == '/' && '0' <= s[1] && s[1] <= '7'521}522// mergeTail is supposed to merge common subtrees (program tails),523// reducing the size of the final program code.524// It identifies the subtrees using a bottom-up canonicalization.525//526// THIS CODE DOES NOT WORK. IT NEEDS TO BE DEBUGGED.527func mergeTail(p *Prog, emitted map[string]*Prog) *Prog {528 if emitted == nil {529 emitted = make(map[string]*Prog)530 }531 if p.Action == "match" {532 return p533 }534 for _, key := range p.keys() {535 p.Child[key] = mergeTail(p.Child[key], emitted)536 }537 op := ""538 for _, key := range p.keys() {539 q := p.Child[key]540 if q.Action != "op" || len(q.Child) > 1 {541 op = ""542 break543 }544 qop := q.keys()[0]545 if op == "" {546 op = qop547 } else if op != qop {548 op = ""549 break550 }551 }552 if op != "" {553 // Pull 'op x' up above the discriminator.554 p1 := new(Prog)555 *p1 = *p556 for _, key := range p.keys() {557 p1.Child[key] = p.Child[key].Child[op]558 }559 p.Action = "op"560 p.Child = map[string]*Prog{op: p1}561 }562 var buf bytes.Buffer563 fmt.Fprintf(&buf, "%s\n", p.Action)564 for _, key := range p.keys() {565 fmt.Fprintf(&buf, "%s %d\n", key, p.Child[key].TailID)566 }567 key := buf.String()568 if q := emitted[key]; q != nil {569 return q570 }571 emitted[key] = p572 p.TailID = len(emitted)573 return p574}575// printText prints the tree in textual form.576func printText(p *Prog) {577 printTree(os.Stdout, p, 0, false)578}579var tabs = strings.Repeat(" ", 100)580func printTree(w io.Writer, p *Prog, depth int, compact bool) {581 if compact && len(p.Child) == 1 {582 fmt.Fprintf(w, "%.*s%s", 4*depth, tabs, p.Action)583 for len(p.Child) == 1 {584 key := p.keys()[0]585 child := p.Child[key]586 fmt.Fprintf(w, " %s %s", key, child.Action)587 p = child588 }589 fmt.Fprintf(w, "\n")590 } else {591 fmt.Fprintf(w, "%.*s%s\n", 4*depth, tabs, p.Action)592 }593 for _, key := range p.keys() {594 fmt.Fprintf(w, "%.*s%s\n", 4*(depth+1), tabs, key)595 printTree(w, p.Child[key], depth+2, compact)596 }597}598// printDecoder prints a Go array containing the decoder program.599// It runs in two passes, both of which traverse and could generate600// the entire program. The first pass records the PC for each Prog node,601// and the second pass emits the actual program, using the PCs as jump602// targets in the places where the program is a dag rather than a tree.603func printDecoder(p *Prog) {604 opMap := map[string]bool{605 "PAUSE": true,606 }607 printDecoderPass(p, 1, false, opMap)608 fmt.Printf("// DO NOT EDIT\n")609 fmt.Printf("// generated by: x86map -fmt=decoder %s\n", inputFile)610 fmt.Printf("\n")611 fmt.Printf("package x86asm\n\n")612 fmt.Printf("var decoder = [...]uint16{\n\tuint16(xFail),\n")613 printDecoderPass(p, 1, true, opMap)614 fmt.Printf("}\n\n")615 var ops []string616 for op := range opMap {617 ops = append(ops, op)618 }619 sort.Strings(ops)620 fmt.Printf("const (\n")621 fmt.Printf("\t_ Op = iota\n\n")622 last := ""623 for _, op := range ops {624 fmt.Printf("\t%s\n", op)625 last = op626 }627 fmt.Printf(")\n\n")628 fmt.Printf("const maxOp = %s\n\n", last)629 fmt.Printf("var opNames = [...]string{\n")630 for _, op := range ops {631 fmt.Printf("\t%s: \"%s\",\n", op, op)632 }633 fmt.Printf("}\n")634}635// printScanner prints the decoding table for a scanner.636// The scanner can identify instruction boundaries but does not do637// full decoding. It is meant to be lighter weight than the x86asm638// decoder tables.639func printScanner(p *Prog) {640 walkScanTree(p, -1)641 var out []uint16642 out = append(out, 0)643 emitScanFunc(p, &out)644 fmt.Printf("var scanProg = []uint16{\n")645 fmt.Printf("\t/*0*/ 0, // dead\n")646 for i := 1; i < len(out); i++ {647 fmt.Printf("\t/*%d*/ ", i)648 switch out[i] {649 default:650 log.Fatalf("malformed program %#x", out[i])651 case scanMatch:652 fmt.Printf("scanMatch,\n")653 continue654 case scanJump:655 fmt.Printf("scanJump, %d,\n", out[i+1])656 i++657 continue658 case scanSwitchByte:659 fmt.Printf("scanSwitchByte,\n")660 for j := 0; j < 256/8; j++ {661 fmt.Printf("\t")662 fmt.Printf("/* %#02x-%#02x */", j*8, j*8+7)663 for k := 0; k < 8; k++ {664 fmt.Printf(" %d,", out[i+1+j*8+k])665 }666 fmt.Printf("\n")667 }668 i += 256669 continue670 case scanSwitchSlash:671 fmt.Printf("scanSwitchSlash, %d,\n", out[i+1])672 n := int(out[i+1])673 for j := 0; j < n; j++ {674 fmt.Printf("\t/* byte */ %#x, %d,\n", out[i+2+2*j], out[i+2+2*j+1])675 }676 for j := 0; j < 8; j++ {677 fmt.Printf("\t/* /%d */ %d,\n", j, out[i+2+2*n+j])678 }679 i += 1 + 2*n + 8680 continue681 case scanSwitchPrefix:682 fmt.Printf("scanSwitchPrefix, %d,\n", out[i+1])683 n := int(out[i+1])684 for j := 0; j < n; j++ {685 fmt.Printf("\t/* prefix */ %#x, %d,\n", out[i+2+2*j], out[i+2+2*j+1])686 }687 i += 1 + 2*n688 continue689 case scanSwitchIs64:690 fmt.Printf("scanSwitchIs64, %d, %d\n", out[i+1], out[i+2])691 i += 2692 continue693 case scanSwitchDatasize:694 fmt.Printf("scanSwitchDatasize, %d, %d, %d\n", out[i+1], out[i+2], out[i+3])695 i += 3696 continue697 case scanSwitchIsMem:698 fmt.Printf("scanSwitchIsMem, %d, %d\n", out[i+1], out[i+2])699 i += 2700 continue701 case scanReadModRM:702 fmt.Printf("scanReadModRM,\n")703 continue704 case scanReadIB:705 fmt.Printf("scanReadIB,\n")706 continue707 case scanReadIW:708 fmt.Printf("scanReadIW,\n")709 continue710 case scanReadIWD:711 fmt.Printf("scanReadIWD,\n")712 continue713 case scanReadIWDO:714 fmt.Printf("scanReadIWDO,\n")715 continue716 case scanReadCWD:717 fmt.Printf("scanReadCWD,\n")718 continue719 case scanReadCB:720 fmt.Printf("scanReadCB,\n")721 continue722 case scanReadCDP:723 fmt.Printf("scanReadCDP,\n")724 continue725 case scanReadCM:726 fmt.Printf("scanReadCM,\n")727 continue728 }729 }730 fmt.Printf("}\n")731}732func walkScanTree(p *Prog, is64 int) {733 keys := p.keys()734 for _, key := range keys {735 if p.Action == "is64" {736 switch key {737 case "0":738 is64 = 0739 case "1":740 is64 = 1741 }742 }743 walkScanTree(p.Child[key], is64)744 }745 switch p.Action {746 case "read", "match":747 // keep748 return749 case "decode":750 if len(keys) >= 8 && keys[0] == "/0" && keys[7] == "/7" && allSame(p, keys) {751 p.Action = "read"752 p.Child = map[string]*Prog{"/r": p.Child[keys[0]]}753 return754 }755 case "op", "arg":756 // drop757 *p = *p.Child[keys[0]]758 return759 case "prefix":760 if len(keys) >= 1 && keys[0] == "0" && allSame(p, keys) {761 *p = *p.Child[keys[0]]762 return763 }764 case "is64", "addrsize", "datasize", "ismem":765 if len(keys) == 1 && keys[0] == "any" {766 *p = *p.Child[keys[0]]767 return768 }769 nkey := len(allKeys[p.Action])770 if p.Action == "addrsize" {771 nkey = 2772 }773 if p.Action == "datasize" && is64 == 0 {774 nkey = 2775 }776 if len(keys) == nkey && allSame(p, keys) {777 *p = *p.Child[keys[0]]778 return779 }780 }781 switch p.Action {782 case "datasize":783 if len(keys) == 2 && is64 == 0 || len(keys) == 3 {784 if treeText(p.Child["16"]) == "read iw match ! \n" && treeText(p.Child["32"]) == "read id match ! \n" && (len(keys) == 2 || treeText(p.Child["64"]) == "read id match ! \n") {785 p.Action = "read"786 p.Child = map[string]*Prog{"iwd/d": p.Child["16"].Child["iw"]}787 return788 }789 if len(keys) == 3 && treeText(p.Child["16"]) == "read iw match ! \n" && treeText(p.Child["32"]) == "read id match ! \n" && treeText(p.Child["64"]) == "read io match ! \n" {790 p.Action = "read"791 p.Child = map[string]*Prog{"iwdo/d": p.Child["16"].Child["iw"]}792 return793 }794 if treeText(p.Child["16"]) == "read /r read iw match ! \n" && treeText(p.Child["32"]) == "read /r read id match ! \n" && (len(keys) == 2 || treeText(p.Child["64"]) == "read /r read id match ! \n") {795 p.Action = "read"796 p.Child = map[string]*Prog{"/r": {Action: "read", Child: map[string]*Prog{"iwd/d": p.Child["16"].Child["/r"].Child["iw"]}}}797 return798 }799 if treeText(p.Child["16"]) == "read cw match ! \n" && treeText(p.Child["32"]) == "read cd match ! \n" && (len(keys) == 2 || treeText(p.Child["64"]) == "read cd match ! \n") {800 p.Action = "read"801 p.Child = map[string]*Prog{"cwd/d": p.Child["16"].Child["cw"]}802 return803 }804 if treeText(p.Child["16"]) == "read cd match ! \n" && treeText(p.Child["32"]) == "read cp match ! \n" && (len(keys) == 2 || treeText(p.Child["64"]) == "read cp match ! \n") {805 p.Action = "read"806 p.Child = map[string]*Prog{"cdp/d": p.Child["16"].Child["cd"]}807 return808 }809 fmt.Printf("!! %q\n", treeText(p.Child["16"]))810 }811 case "is64":812 if len(keys) == 2 && treeText(p.Child["0"]) == "read cwd/d match ! \n" && treeText(p.Child["1"]) == "read cd match ! \n" {813 *p = *p.Child["0"]814 return815 }816 if len(keys) == 2 && treeText(p.Child["0"]) == "read iwd/d match ! \n" && treeText(p.Child["1"]) == "read iwdo/d match ! \n" {817 *p = *p.Child["1"]818 return819 }820 }821 /*822 match := make(map[string][]string)823 for _, key := range keys {824 text := treeText(p.Child[key])825 match[text] = append(match[text], key)826 }827 child := make(map[string]*Prog)828 for _, keys := range match {829 child[strings.Join(keys, ",")] = p.Child[keys[0]]830 }831 p.Child = child832 */833}834func treeText(p *Prog) string {835 var buf bytes.Buffer836 printTree(&buf, p, 0, true)837 return buf.String()838}839func allSame(p *Prog, keys []string) bool {840 var tree string841 for i, key := range keys {842 if i == 0 {843 tree = treeText(p.Child[key])844 continue845 }846 if treeText(p.Child[key]) != tree {847 return false848 }849 }850 return true851}852var scanCache = map[string]uint16{}853const (854 _ uint16 = iota855 scanMatch856 scanJump857 scanSwitchByte858 scanSwitchSlash859 scanSwitchIs64860 scanSwitchDatasize861 scanSwitchIsMem862 scanSwitchPrefix863 scanReadModRM864 scanReadIB865 scanReadIW866 scanReadIWD867 scanReadIWDO868 scanReadCWD869 scanReadCB870 scanReadCDP871 scanReadCM872)873func decodeKeyPlus(key string) (val, n int) {874 n = 1875 if strings.HasSuffix(key, "+") {876 n = 8877 key = key[:len(key)-1]878 }879 v, err := strconv.ParseUint(key, 16, 8)880 if err != nil {881 log.Fatalf("unexpected decode key %q", key)882 }883 return int(v), n884}885func decodeKey(key string) int {886 val, n := decodeKeyPlus(key)887 if n != 1 {888 log.Panicf("unexpected decode key+ %q", key)889 }890 return val891}892func emitScanFunc(p *Prog, out *[]uint16) uint16 {893 keys := p.keys()894 text := treeText(p)895 if off, ok := scanCache[text]; ok {896 return off897 }898 start := uint16(len(*out))899 scanCache[text] = start900 switch p.Action {901 case "decode":902 if keys[0][0] != '/' {903 *out = append(*out, scanSwitchByte)904 off := len(*out)905 for i := 0; i < 256; i++ {906 *out = append(*out, 0)907 }908 for _, key := range keys {909 val, n := decodeKeyPlus(key)910 dst := emitScanFunc(p.Child[key], out)911 for j := 0; j < n; j++ {912 (*out)[off+val+j] = dst913 }914 }915 return start916 }917 n := len(keys)918 for n > 0 && keys[n-1][0] != '/' {919 n--920 }921 total := 0922 for i := n; i < len(keys); i++ {923 key := keys[i]924 _, n := decodeKeyPlus(key)925 total += n926 }927 *out = append(*out, scanSwitchSlash, uint16(total))928 off := len(*out)929 for i := 0; i < total; i++ {930 *out = append(*out, 0, 0)931 }932 for i := 0; i < 8; i++ {933 *out = append(*out, 0)934 }935 for i := n; i < len(keys); i++ {936 key := keys[i]937 val, valn := decodeKeyPlus(key)938 targ := emitScanFunc(p.Child[key], out)939 for j := 0; j < valn; j++ {940 (*out)[off] = uint16(val + j)941 off++942 (*out)[off] = targ943 off++944 }945 }946 for i := 0; i < n; i++ {947 key := keys[i]948 if len(key) != 2 || key[0] != '/' || key[1] < '0' || '8' <= key[1] {949 log.Fatalf("unexpected decode key %q", key)950 }951 (*out)[off+int(key[1]-'0')] = emitScanFunc(p.Child[key], out)952 }953 return start954 case "read":955 switch keys[0] {956 default:957 log.Fatalf("unexpected read %q", keys[0])958 case "/r":959 *out = append(*out, scanReadModRM)960 case "ib":961 *out = append(*out, scanReadIB)962 case "iw":963 *out = append(*out, scanReadIW)964 case "cb":965 *out = append(*out, scanReadCB)966 case "cm":967 *out = append(*out, scanReadCM)968 case "iwd/d":969 *out = append(*out, scanReadIWD)970 case "iwdo/d":971 *out = append(*out, scanReadIWDO)972 case "cwd/d":973 *out = append(*out, scanReadCWD)974 case "cdp/d":975 *out = append(*out, scanReadCDP)976 }977 next := p.Child[keys[0]]978 if next.Action == "match" {979 *out = append(*out, scanMatch)980 } else {981 *out = append(*out, scanJump, 0)982 off := len(*out)983 (*out)[off-1] = emitScanFunc(next, out)984 }985 return start986 case "match":987 *out = append(*out, scanMatch)988 return start989 case "is64":990 *out = append(*out, scanSwitchIs64, 0, 0)991 if next := p.Child["0"]; next != nil {992 (*out)[start+1] = emitScanFunc(next, out)993 }994 if next := p.Child["1"]; next != nil {995 (*out)[start+2] = emitScanFunc(next, out)996 }997 return start998 case "ismem":999 *out = append(*out, scanSwitchIsMem, 0, 0)1000 if next := p.Child["0"]; next != nil {1001 (*out)[start+1] = emitScanFunc(next, out)1002 }1003 if next := p.Child["1"]; next != nil {1004 (*out)[start+2] = emitScanFunc(next, out)1005 }1006 return start1007 case "datasize":1008 *out = append(*out, scanSwitchDatasize, 0, 0, 0)1009 if next := p.Child["16"]; next != nil {1010 (*out)[start+1] = emitScanFunc(next, out)1011 }1012 if next := p.Child["32"]; next != nil {1013 (*out)[start+2] = emitScanFunc(next, out)1014 }1015 if next := p.Child["64"]; next != nil {1016 (*out)[start+3] = emitScanFunc(next, out)1017 }1018 return start1019 case "prefix":1020 *out = append(*out, scanSwitchPrefix, uint16(len(keys)))1021 n := len(keys)1022 for i := 0; i < n; i++ {1023 *out = append(*out, uint16(decodeKey(keys[i])), 0)1024 }1025 for i := 0; i < n; i++ {1026 (*out)[int(start)+2+2*i+1] = emitScanFunc(p.Child[keys[i]], out)1027 }1028 return start1029 }1030 log.Fatalf("unexpected action %q", p.Action)1031 return start1032}1033// printDecoderPass prints the decoding table program for p,1034// assuming that we are emitting code at the given program counter.1035// It returns the new current program counter, that is, the program1036// counter after the printed instructions.1037// If printing==false, printDecoderPass does not print the actual1038// code words but still does the PC computation.1039func printDecoderPass(p *Prog, pc int, printing bool, ops map[string]bool) int {1040 // Record PC on first pass....

Full Screen

Full Screen

Scan

Using AI Code Generation

copy

Full Screen

1import "fmt"2func main() {3 fmt.Print("Enter a number: ")4 fmt.Scanf("%f", &input)5 fmt.Println(output)6}7func Scanln(a ...interface{}) (n int, err error)8import "fmt"9func main() {10 fmt.Print("Enter a number: ")11 fmt.Scanln(&input)12 fmt.Println(output)13}14func Scanf(format string, a ...interface{}) (n int, err error)15import "fmt"16func main() {17 fmt.Print("Enter a number: ")18 fmt.Scanf("%f", &input)19 fmt.Println(output)20}21Recommended Posts: Golang | fmt.Scan() method22Golang | fmt.Scanln() method23Golang | fmt.Scanf() method24Golang | fmt.Sscan() method25Golang | fmt.Sscanln() method26Golang | fmt.Sscanf() method27Golang | fmt.Fscan() method28Golang | fmt.Fscanln() method29Golang | fmt.Fscanf() method30Golang | fmt.Fprint() method31Golang | fmt.Fprintln() method32Golang | fmt.Fprintf() method33Golang | fmt.Print() method34Golang | fmt.Println() method35Golang | fmt.Printf() method36Golang | fmt.Sprintf() method

Full Screen

Full Screen

Scan

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println("Enter a string:")4 reader := bufio.NewReader(os.Stdin)5 str, _ := reader.ReadString('6 fmt.Println("Entered string is:", str)7}

Full Screen

Full Screen

Scan

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println("Enter a string")4 reader := bufio.NewReader(os.Stdin)5 str, _ = reader.ReadString('6 str = strings.TrimSpace(str)7 fmt.Println("The string you entered is ", str)8}9Scanln() method10Scanln() method is used to read the input from the user in the form of string. It reads the input till the new line character is encountered. The syntax of this method is:11func (r *Reader) Scanln() (string, error)12import (13func main() {14 fmt.Println("Enter a string")15 reader := bufio.NewReader(os.Stdin)16 str, _ = reader.ReadString('17 str = strings.TrimSpace(str)18 fmt.Println("The string you entered is ", str)19}20Scanf() method21Scanf() method is used to read the input from the user in the form of string. It reads the input till the new line character is encountered. The syntax of this method is:22func (r *Reader) Scanf(format string, a ...interface{}) (int, error)23import (24func main() {25 fmt.Println("Enter a string")26 reader := bufio.NewReader(os.Stdin)27 str, _ = reader.ReadString('28 str = strings.TrimSpace(str)29 fmt.Println("The string you entered is ", str)30}31Scan() method32Scan() method is used to read the input from the user in the form of string. It reads the input till the new line character is encountered. The syntax of this method is:33func (r *Reader) Scan() bool

Full Screen

Full Screen

Scan

Using AI Code Generation

copy

Full Screen

1import "fmt"2func main() {3 fmt.Scan(&a,&b,&c)4 fmt.Println("a=",a,"b=",b,"c=",c)5}6import "fmt"7func main() {8 fmt.Scanln(&a,&b,&c)9 fmt.Println("a=",a,"b=",b,"c=",c)10}11import "fmt"12func main() {13 fmt.Scanf("%d %f %s",&a,&b,&c)14 fmt.Println("a=",a,"b=",b,"c=",c)15}16import (17func main() {18 fmt.Fscan(os.Stdin,&a,&b,&c)19 fmt.Println("a=",a,"b=",b,"c=",c)20}21import (22func main() {23 fmt.Fscanln(os.Stdin,&a,&b,&c)24 fmt.Println("a=",a,"b=",b,"c=",c)25}

Full Screen

Full Screen

Scan

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println("Enter a number:")4 fmt.Scan(&n)5 fmt.Println("The number you entered is:", n)6 fmt.Println("The square of the number is:", prog.Square(n))7 fmt.Println("The cube of the number is:", prog.Cube(n))8}9import (10func main() {11 fmt.Println("Enter two numbers:")12 fmt.Scan(&a, &b)13 fmt.Println("The sum of the numbers is:", prog.Add(a, b))14}15func Add(a, b int) int {16}17func Square(a int) int {18}19func Cube(a int) int {20}

Full Screen

Full Screen

Scan

Using AI Code Generation

copy

Full Screen

1import "fmt"2func main() {3 fmt.Println("Enter your name:")4 fmt.Scan(&name)5 fmt.Println("Enter your age:")6 fmt.Scan(&age)7 fmt.Println("Your Name is", name)8 fmt.Println("Your Age is", age)9}10Scanln() Method11func Scanln(a ...interface{}) (n int, err error)12import "fmt"13func main() {14 fmt.Println("Enter your name:")15 fmt.Scanln(&name)16 fmt.Println("Enter your age:")17 fmt.Scanln(&age)18 fmt.Println("Your Name is", name)19 fmt.Println("Your Age is", age)20}21Scanf() Method22func Scanf(format string, a ...interface{}) (n int, err error)23import "fmt"24func main() {25 fmt.Println("Enter your name:")26 fmt.Scanf("%s", &name)27 fmt.Println("Enter your age:")28 fmt.Scanf("%d", &age)29 fmt.Println("Your Name is", name)30 fmt.Println("Your Age is", age)31}32fmt.Println() Method33func Println(a ...interface{}) (n int,

Full Screen

Full Screen

Scan

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 p := prog.NewProg()4 p.Scan()5 fmt.Println(p.Input)6}7import (8type Prog struct {9}10func NewProg() *Prog {11 return &Prog{}12}13func (p *Prog) Scan() {14 scanner := bufio.NewScanner(os.Stdin)15 if scanner.Scan() {16 p.Input = scanner.Text()17 } else {18 fmt.Println("Error in reading input")19 }20}

Full Screen

Full Screen

Scan

Using AI Code Generation

copy

Full Screen

1import "fmt"2func main() {3 scanner := prog.NewScanner()4 scanner.Scan("test.txt")5 fmt.Println(scanner.Tokens)6}

Full Screen

Full Screen

Scan

Using AI Code Generation

copy

Full Screen

1import "fmt"2func main() {3 var a = prog{10, 20}4 fmt.Println("a=", a)5 fmt.Println("a=", a.Scan())6}7a= {10 20}8a= {10 20}

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Syzkaller automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Most used method in

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful