github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/src/cmd/compile/internal/gc/racewalk.go (about)

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package gc
     6  
     7  import (
     8  	"cmd/compile/internal/types"
     9  	"cmd/internal/src"
    10  	"fmt"
    11  	"strings"
    12  )
    13  
    14  // The instrument pass modifies the code tree for instrumentation.
    15  //
    16  // For flag_race it modifies the function as follows:
    17  //
    18  // 1. It inserts a call to racefuncenterfp at the beginning of each function.
    19  // 2. It inserts a call to racefuncexit at the end of each function.
    20  // 3. It inserts a call to raceread before each memory read.
    21  // 4. It inserts a call to racewrite before each memory write.
    22  //
    23  // For flag_msan:
    24  //
    25  // 1. It inserts a call to msanread before each memory read.
    26  // 2. It inserts a call to msanwrite before each memory write.
    27  //
    28  // The rewriting is not yet complete. Certain nodes are not rewritten
    29  // but should be.
    30  
    31  // TODO(dvyukov): do not instrument initialization as writes:
    32  // a := make([]int, 10)
    33  
    34  // Do not instrument the following packages at all,
    35  // at best instrumentation would cause infinite recursion.
    36  var omit_pkgs = []string{"runtime/internal/atomic", "runtime/internal/sys", "runtime", "runtime/race", "runtime/msan"}
    37  
    38  // Only insert racefuncenterfp/racefuncexit into the following packages.
    39  // Memory accesses in the packages are either uninteresting or will cause false positives.
    40  var norace_inst_pkgs = []string{"sync", "sync/atomic"}
    41  
    42  func ispkgin(pkgs []string) bool {
    43  	if myimportpath != "" {
    44  		for _, p := range pkgs {
    45  			if myimportpath == p {
    46  				return true
    47  			}
    48  		}
    49  	}
    50  
    51  	return false
    52  }
    53  
    54  func instrument(fn *Node) {
    55  	if ispkgin(omit_pkgs) || fn.Func.Pragma&Norace != 0 {
    56  		return
    57  	}
    58  
    59  	if !flag_race || !ispkgin(norace_inst_pkgs) {
    60  		instrumentlist(fn.Nbody, nil)
    61  
    62  		// nothing interesting for race detector in fn->enter
    63  		instrumentlist(fn.Func.Exit, nil)
    64  	}
    65  
    66  	if flag_race {
    67  		// nodpc is the PC of the caller as extracted by
    68  		// getcallerpc. We use -widthptr(FP) for x86.
    69  		// BUG: this will not work on arm.
    70  		nodpc := *nodfp
    71  		nodpc.Type = types.Types[TUINTPTR]
    72  		nodpc.Xoffset = int64(-Widthptr)
    73  		nd := mkcall("racefuncenter", nil, nil, &nodpc)
    74  		fn.Func.Enter.Prepend(nd)
    75  		nd = mkcall("racefuncexit", nil, nil)
    76  		fn.Func.Exit.Append(nd)
    77  		fn.Func.Dcl = append(fn.Func.Dcl, &nodpc)
    78  	}
    79  
    80  	if Debug['W'] != 0 {
    81  		s := fmt.Sprintf("after instrument %v", fn.Func.Nname.Sym)
    82  		dumplist(s, fn.Nbody)
    83  		s = fmt.Sprintf("enter %v", fn.Func.Nname.Sym)
    84  		dumplist(s, fn.Func.Enter)
    85  		s = fmt.Sprintf("exit %v", fn.Func.Nname.Sym)
    86  		dumplist(s, fn.Func.Exit)
    87  	}
    88  }
    89  
    90  func instrumentlist(l Nodes, init *Nodes) {
    91  	s := l.Slice()
    92  	for i := range s {
    93  		var instr Nodes
    94  		instrumentnode(&s[i], &instr, 0, 0)
    95  		if init == nil {
    96  			s[i].Ninit.AppendNodes(&instr)
    97  		} else {
    98  			init.AppendNodes(&instr)
    99  		}
   100  	}
   101  }
   102  
   103  // walkexpr and walkstmt combined
   104  // walks the tree and adds calls to the
   105  // instrumentation code to top-level (statement) nodes' init
   106  func instrumentnode(np **Node, init *Nodes, wr int, skip int) {
   107  	n := *np
   108  
   109  	if n == nil {
   110  		return
   111  	}
   112  
   113  	if Debug['w'] > 1 {
   114  		Dump("instrument-before", n)
   115  	}
   116  	setlineno(n)
   117  	if init == nil {
   118  		Fatalf("instrument: bad init list")
   119  	}
   120  	if init == &n.Ninit {
   121  		// If init == &n->ninit and n->ninit is non-nil,
   122  		// instrumentnode might append it to itself.
   123  		// nil it out and handle it separately before putting it back.
   124  		l := n.Ninit
   125  
   126  		n.Ninit.Set(nil)
   127  		instrumentlist(l, nil)
   128  		instrumentnode(&n, &l, wr, skip) // recurse with nil n->ninit
   129  		appendinit(&n, l)
   130  		*np = n
   131  		return
   132  	}
   133  
   134  	instrumentlist(n.Ninit, nil)
   135  
   136  	switch n.Op {
   137  	default:
   138  		Fatalf("instrument: unknown node type %v", n.Op)
   139  
   140  	case OAS, OAS2FUNC:
   141  		instrumentnode(&n.Left, init, 1, 0)
   142  		instrumentnode(&n.Right, init, 0, 0)
   143  
   144  		// can't matter
   145  	case OCFUNC, OVARKILL, OVARLIVE:
   146  
   147  	case OBLOCK:
   148  		ls := n.List.Slice()
   149  		afterCall := false
   150  		for i := range ls {
   151  			op := ls[i].Op
   152  			// Scan past OAS nodes copying results off stack.
   153  			// Those must not be instrumented, because the
   154  			// instrumentation calls will smash the results.
   155  			// The assignments are to temporaries, so they cannot
   156  			// be involved in races and need not be instrumented.
   157  			if afterCall && op == OAS && iscallret(ls[i].Right) {
   158  				continue
   159  			}
   160  			instrumentnode(&ls[i], &ls[i].Ninit, 0, 0)
   161  			afterCall = (op == OCALLFUNC || op == OCALLMETH || op == OCALLINTER)
   162  		}
   163  
   164  	case ODEFER:
   165  		instrumentnode(&n.Left, init, 0, 0)
   166  
   167  	case OPROC:
   168  		instrumentnode(&n.Left, init, 0, 0)
   169  
   170  	case OCALLINTER:
   171  		instrumentnode(&n.Left, init, 0, 0)
   172  
   173  	case OCALLFUNC:
   174  		// Note that runtime.typedslicecopy is the only
   175  		// assignment-like function call in the AST at this
   176  		// point (between walk and SSA); since we don't
   177  		// instrument it here, typedslicecopy is manually
   178  		// instrumented in runtime. Calls to the write barrier
   179  		// and typedmemmove are created later by SSA, so those
   180  		// still appear as OAS nodes at this point.
   181  		instrumentnode(&n.Left, init, 0, 0)
   182  
   183  	case ONOT,
   184  		OMINUS,
   185  		OPLUS,
   186  		OREAL,
   187  		OIMAG,
   188  		OCOM:
   189  		instrumentnode(&n.Left, init, wr, 0)
   190  
   191  	case ODOTINTER:
   192  		instrumentnode(&n.Left, init, 0, 0)
   193  
   194  	case ODOT:
   195  		instrumentnode(&n.Left, init, 0, 1)
   196  		callinstr(&n, init, wr, skip)
   197  
   198  	case ODOTPTR: // dst = (*x).f with implicit *; otherwise it's ODOT+OIND
   199  		instrumentnode(&n.Left, init, 0, 0)
   200  
   201  		callinstr(&n, init, wr, skip)
   202  
   203  	case OIND: // *p
   204  		instrumentnode(&n.Left, init, 0, 0)
   205  
   206  		callinstr(&n, init, wr, skip)
   207  
   208  	case OSPTR, OLEN, OCAP:
   209  		instrumentnode(&n.Left, init, 0, 0)
   210  		if n.Left.Type.IsMap() {
   211  			n1 := nod(OCONVNOP, n.Left, nil)
   212  			n1.Type = types.NewPtr(types.Types[TUINT8])
   213  			n1 = nod(OIND, n1, nil)
   214  			n1 = typecheck(n1, Erv)
   215  			callinstr(&n1, init, 0, skip)
   216  		}
   217  
   218  	case OLSH,
   219  		ORSH,
   220  		OAND,
   221  		OANDNOT,
   222  		OOR,
   223  		OXOR,
   224  		OSUB,
   225  		OMUL,
   226  		OEQ,
   227  		ONE,
   228  		OLT,
   229  		OLE,
   230  		OGE,
   231  		OGT,
   232  		OADD,
   233  		OCOMPLEX:
   234  		instrumentnode(&n.Left, init, wr, 0)
   235  		instrumentnode(&n.Right, init, wr, 0)
   236  
   237  	case OANDAND, OOROR:
   238  		instrumentnode(&n.Left, init, wr, 0)
   239  
   240  		// walk has ensured the node has moved to a location where
   241  		// side effects are safe.
   242  		// n->right may not be executed,
   243  		// so instrumentation goes to n->right->ninit, not init.
   244  		instrumentnode(&n.Right, &n.Right.Ninit, wr, 0)
   245  
   246  	case ONAME:
   247  		callinstr(&n, init, wr, skip)
   248  
   249  	case OCONV:
   250  		instrumentnode(&n.Left, init, wr, 0)
   251  
   252  	case OCONVNOP:
   253  		instrumentnode(&n.Left, init, wr, 0)
   254  
   255  	case ODIV, OMOD:
   256  		instrumentnode(&n.Left, init, wr, 0)
   257  		instrumentnode(&n.Right, init, wr, 0)
   258  
   259  	case OINDEX:
   260  		if !n.Left.Type.IsArray() {
   261  			instrumentnode(&n.Left, init, 0, 0)
   262  		} else if !islvalue(n.Left) {
   263  			// index of unaddressable array, like Map[k][i].
   264  			instrumentnode(&n.Left, init, wr, 0)
   265  
   266  			instrumentnode(&n.Right, init, 0, 0)
   267  			break
   268  		}
   269  
   270  		instrumentnode(&n.Right, init, 0, 0)
   271  		if !n.Left.Type.IsString() {
   272  			callinstr(&n, init, wr, skip)
   273  		}
   274  
   275  	case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR, OSLICESTR:
   276  		instrumentnode(&n.Left, init, 0, 0)
   277  		low, high, max := n.SliceBounds()
   278  		instrumentnode(&low, init, 0, 0)
   279  		instrumentnode(&high, init, 0, 0)
   280  		instrumentnode(&max, init, 0, 0)
   281  		n.SetSliceBounds(low, high, max)
   282  
   283  	case OADDR:
   284  		instrumentnode(&n.Left, init, 0, 1)
   285  
   286  		// n->left is Type* which is not interesting.
   287  	case OEFACE:
   288  		instrumentnode(&n.Right, init, 0, 0)
   289  
   290  	case OITAB, OIDATA:
   291  		instrumentnode(&n.Left, init, 0, 0)
   292  
   293  	case OSTRARRAYBYTETMP:
   294  		instrumentnode(&n.Left, init, 0, 0)
   295  
   296  	case OAS2DOTTYPE:
   297  		instrumentnode(&n.Left, init, 1, 0)
   298  		instrumentnode(&n.Right, init, 0, 0)
   299  
   300  	case ODOTTYPE, ODOTTYPE2:
   301  		instrumentnode(&n.Left, init, 0, 0)
   302  
   303  		// should not appear in AST by now
   304  	case OSEND,
   305  		ORECV,
   306  		OCLOSE,
   307  		ONEW,
   308  		OXCASE,
   309  		OCASE,
   310  		OPANIC,
   311  		ORECOVER,
   312  		OCONVIFACE,
   313  		OCMPIFACE,
   314  		OMAKECHAN,
   315  		OMAKEMAP,
   316  		OMAKESLICE,
   317  		OCALL,
   318  		OCOPY,
   319  		OAPPEND,
   320  		ORUNESTR,
   321  		OARRAYBYTESTR,
   322  		OARRAYRUNESTR,
   323  		OSTRARRAYBYTE,
   324  		OSTRARRAYRUNE,
   325  		OINDEXMAP,
   326  		// lowered to call
   327  		OCMPSTR,
   328  		OADDSTR,
   329  		OCALLPART,
   330  		// lowered to PTRLIT
   331  		OCLOSURE,  // lowered to PTRLIT
   332  		ORANGE,    // lowered to ordinary for loop
   333  		OARRAYLIT, // lowered to assignments
   334  		OSLICELIT,
   335  		OMAPLIT,
   336  		OSTRUCTLIT,
   337  		OAS2,
   338  		OAS2RECV,
   339  		OAS2MAPR,
   340  		OASOP:
   341  		Fatalf("instrument: %v must be lowered by now", n.Op)
   342  
   343  	case OGETG:
   344  		Fatalf("instrument: OGETG can happen only in runtime which we don't instrument")
   345  
   346  	case OFOR, OFORUNTIL:
   347  		if n.Left != nil {
   348  			instrumentnode(&n.Left, &n.Left.Ninit, 0, 0)
   349  		}
   350  		if n.Right != nil {
   351  			instrumentnode(&n.Right, &n.Right.Ninit, 0, 0)
   352  		}
   353  
   354  	case OIF, OSWITCH:
   355  		if n.Left != nil {
   356  			instrumentnode(&n.Left, &n.Left.Ninit, 0, 0)
   357  		}
   358  
   359  		// just do generic traversal
   360  	case OCALLMETH,
   361  		ORETURN,
   362  		ORETJMP,
   363  		OSELECT,
   364  		OEMPTY,
   365  		OBREAK,
   366  		OCONTINUE,
   367  		OFALL,
   368  		OGOTO,
   369  		OLABEL:
   370  
   371  		// does not require instrumentation
   372  	case OPRINT, // don't bother instrumenting it
   373  		OPRINTN,     // don't bother instrumenting it
   374  		OCHECKNIL,   // always followed by a read.
   375  		OCLOSUREVAR, // immutable pointer to captured variable
   376  		ODOTMETH,    // either part of CALLMETH or CALLPART (lowered to PTRLIT)
   377  		OINDREGSP,   // at this stage, only n(SP) nodes from nodarg
   378  		ODCL,        // declarations (without value) cannot be races
   379  		ODCLCONST,
   380  		ODCLTYPE,
   381  		OTYPE,
   382  		ONONAME,
   383  		OLITERAL,
   384  		OTYPESW: // ignored by code generation, do not instrument.
   385  	}
   386  
   387  	if n.Op != OBLOCK { // OBLOCK is handled above in a special way.
   388  		instrumentlist(n.List, init)
   389  	}
   390  	instrumentlist(n.Nbody, nil)
   391  	instrumentlist(n.Rlist, nil)
   392  	*np = n
   393  }
   394  
   395  func isartificial(n *Node) bool {
   396  	// compiler-emitted artificial things that we do not want to instrument,
   397  	// can't possibly participate in a data race.
   398  	// can't be seen by C/C++ and therefore irrelevant for msan.
   399  	if n.Op == ONAME && n.Sym != nil && n.Sym.Name != "" {
   400  		if n.Sym.Name == "_" {
   401  			return true
   402  		}
   403  
   404  		// autotmp's are always local
   405  		if n.IsAutoTmp() {
   406  			return true
   407  		}
   408  
   409  		// statictmp's are read-only
   410  		if strings.HasPrefix(n.Sym.Name, "statictmp_") {
   411  			return true
   412  		}
   413  
   414  		// go.itab is accessed only by the compiler and runtime (assume safe)
   415  		if n.Sym.Pkg != nil && n.Sym.Pkg.Name != "" && n.Sym.Pkg.Name == "go.itab" {
   416  			return true
   417  		}
   418  	}
   419  
   420  	return false
   421  }
   422  
   423  func callinstr(np **Node, init *Nodes, wr int, skip int) bool {
   424  	n := *np
   425  
   426  	//fmt.Printf("callinstr for %v [ %v ] etype=%v class=%v\n",
   427  	//	n, n.Op, n.Type.Etype, n.Class)
   428  
   429  	if skip != 0 || n.Type == nil || n.Type.Etype >= TIDEAL {
   430  		return false
   431  	}
   432  	t := n.Type
   433  	// dowidth may not have been called for PEXTERN.
   434  	dowidth(t)
   435  	w := t.Width
   436  	if w == BADWIDTH {
   437  		Fatalf("instrument: %v badwidth", t)
   438  	}
   439  	if w == 0 {
   440  		return false // can't race on zero-sized things
   441  	}
   442  	if isartificial(n) {
   443  		return false
   444  	}
   445  
   446  	b := outervalue(n)
   447  
   448  	// it skips e.g. stores to ... parameter array
   449  	if isartificial(b) {
   450  		return false
   451  	}
   452  	class := b.Class()
   453  
   454  	// BUG: we _may_ want to instrument PAUTO sometimes
   455  	// e.g. if we've got a local variable/method receiver
   456  	// that has got a pointer inside. Whether it points to
   457  	// the heap or not is impossible to know at compile time
   458  	if class == PAUTOHEAP || class == PEXTERN || b.Op == OINDEX || b.Op == ODOTPTR || b.Op == OIND {
   459  		hasCalls := false
   460  		inspect(n, func(n *Node) bool {
   461  			switch n.Op {
   462  			case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER:
   463  				hasCalls = true
   464  			}
   465  			return !hasCalls
   466  		})
   467  		if hasCalls {
   468  			n = detachexpr(n, init)
   469  			*np = n
   470  		}
   471  
   472  		n = treecopy(n, src.NoXPos)
   473  		makeaddable(n)
   474  		var f *Node
   475  		if flag_msan {
   476  			name := "msanread"
   477  			if wr != 0 {
   478  				name = "msanwrite"
   479  			}
   480  			f = mkcall(name, nil, init, uintptraddr(n), nodintconst(w))
   481  		} else if flag_race && t.NumComponents() > 1 {
   482  			// for composite objects we have to write every address
   483  			// because a write might happen to any subobject.
   484  			// composites with only one element don't have subobjects, though.
   485  			name := "racereadrange"
   486  			if wr != 0 {
   487  				name = "racewriterange"
   488  			}
   489  			f = mkcall(name, nil, init, uintptraddr(n), nodintconst(w))
   490  		} else if flag_race {
   491  			// for non-composite objects we can write just the start
   492  			// address, as any write must write the first byte.
   493  			name := "raceread"
   494  			if wr != 0 {
   495  				name = "racewrite"
   496  			}
   497  			f = mkcall(name, nil, init, uintptraddr(n))
   498  		}
   499  
   500  		init.Append(f)
   501  		return true
   502  	}
   503  
   504  	return false
   505  }
   506  
   507  // makeaddable returns a node whose memory location is the
   508  // same as n, but which is addressable in the Go language
   509  // sense.
   510  // This is different from functions like cheapexpr that may make
   511  // a copy of their argument.
   512  func makeaddable(n *Node) {
   513  	// The arguments to uintptraddr technically have an address but
   514  	// may not be addressable in the Go sense: for example, in the case
   515  	// of T(v).Field where T is a struct type and v is
   516  	// an addressable value.
   517  	switch n.Op {
   518  	case OINDEX:
   519  		if n.Left.Type.IsArray() {
   520  			makeaddable(n.Left)
   521  		}
   522  
   523  		// Turn T(v).Field into v.Field
   524  	case ODOT, OXDOT:
   525  		if n.Left.Op == OCONVNOP {
   526  			n.Left = n.Left.Left
   527  		}
   528  		makeaddable(n.Left)
   529  
   530  		// nothing to do
   531  	}
   532  }
   533  
   534  func uintptraddr(n *Node) *Node {
   535  	r := nod(OADDR, n, nil)
   536  	r.SetBounded(true)
   537  	r = conv(r, types.Types[TUNSAFEPTR])
   538  	r = conv(r, types.Types[TUINTPTR])
   539  	return r
   540  }
   541  
   542  func detachexpr(n *Node, init *Nodes) *Node {
   543  	addr := nod(OADDR, n, nil)
   544  	l := temp(types.NewPtr(n.Type))
   545  	as := nod(OAS, l, addr)
   546  	as = typecheck(as, Etop)
   547  	as = walkexpr(as, init)
   548  	init.Append(as)
   549  	ind := nod(OIND, l, nil)
   550  	ind = typecheck(ind, Erv)
   551  	ind = walkexpr(ind, init)
   552  	return ind
   553  }
   554  
   555  // appendinit is like addinit in subr.go
   556  // but appends rather than prepends.
   557  func appendinit(np **Node, init Nodes) {
   558  	if init.Len() == 0 {
   559  		return
   560  	}
   561  
   562  	n := *np
   563  	switch n.Op {
   564  	// There may be multiple refs to this node;
   565  	// introduce OCONVNOP to hold init list.
   566  	case ONAME, OLITERAL:
   567  		n = nod(OCONVNOP, n, nil)
   568  
   569  		n.Type = n.Left.Type
   570  		n.SetTypecheck(1)
   571  		*np = n
   572  	}
   573  
   574  	n.Ninit.AppendNodes(&init)
   575  	n.SetHasCall(true)
   576  }