github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/gc/racewalk.c (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  // The racewalk pass modifies the code tree for the function as follows:
     6  //
     7  // 1. It inserts a call to racefuncenter at the beginning of each function.
     8  // 2. It inserts a call to racefuncexit at the end of each function.
     9  // 3. It inserts a call to raceread before each memory read.
    10  // 4. It inserts a call to racewrite before each memory write.
    11  //
    12  // The rewriting is not yet complete. Certain nodes are not rewritten
    13  // but should be.
    14  
    15  #include <u.h>
    16  #include <libc.h>
    17  #include "go.h"
    18  
    19  // TODO(dvyukov): do not instrument initialization as writes:
    20  // a := make([]int, 10)
    21  
    22  static void racewalklist(NodeList *l, NodeList **init);
    23  static void racewalknode(Node **np, NodeList **init, int wr, int skip);
    24  static int callinstr(Node **n, NodeList **init, int wr, int skip);
    25  static Node* uintptraddr(Node *n);
    26  static void makeaddable(Node *n);
    27  static Node* basenod(Node *n);
    28  static void foreach(Node *n, void(*f)(Node*, void*), void *c);
    29  static void hascallspred(Node *n, void *c);
    30  static void appendinit(Node **np, NodeList *init);
    31  static Node* detachexpr(Node *n, NodeList **init);
    32  
    33  // Do not instrument the following packages at all,
    34  // at best instrumentation would cause infinite recursion.
    35  static const char *omit_pkgs[] = {"runtime", "runtime/race"};
    36  // Only insert racefuncenter/racefuncexit into the following packages.
    37  // Memory accesses in the packages are either uninteresting or will cause false positives.
    38  static const char *noinst_pkgs[] = {"sync", "sync/atomic"};
    39  
    40  static int
    41  ispkgin(const char **pkgs, int n)
    42  {
    43  	int i;
    44  
    45  	if(myimportpath) {
    46  		for(i=0; i<n; i++) {
    47  			if(strcmp(myimportpath, pkgs[i]) == 0)
    48  				return 1;
    49  		}
    50  	}
    51  	return 0;
    52  }
    53  
    54  static int
    55  isforkfunc(Node *fn)
    56  {
    57  	// Special case for syscall.forkAndExecInChild.
    58  	// In the child, this function must not acquire any locks, because
    59  	// they might have been locked at the time of the fork.  This means
    60  	// no rescheduling, no malloc calls, and no new stack segments.
    61  	// Race instrumentation does all of the above.
    62  	return myimportpath != nil && strcmp(myimportpath, "syscall") == 0 &&
    63  		strcmp(fn->nname->sym->name, "forkAndExecInChild") == 0;
    64  }
    65  
    66  void
    67  racewalk(Node *fn)
    68  {
    69  	Node *nd;
    70  	Node *nodpc;
    71  	char s[1024];
    72  
    73  	if(ispkgin(omit_pkgs, nelem(omit_pkgs)) || isforkfunc(fn))
    74  		return;
    75  
    76  	if(!ispkgin(noinst_pkgs, nelem(noinst_pkgs))) {
    77  		racewalklist(fn->nbody, nil);
    78  		// nothing interesting for race detector in fn->enter
    79  		racewalklist(fn->exit, nil);
    80  	}
    81  
    82  	// nodpc is the PC of the caller as extracted by
    83  	// getcallerpc. We use -widthptr(FP) for x86.
    84  	// BUG: this will not work on arm.
    85  	nodpc = nod(OXXX, nil, nil);
    86  	*nodpc = *nodfp;
    87  	nodpc->type = types[TUINTPTR];
    88  	nodpc->xoffset = -widthptr;
    89  	nd = mkcall("racefuncenter", T, nil, nodpc);
    90  	fn->enter = concat(list1(nd), fn->enter);
    91  	nd = mkcall("racefuncexit", T, nil);
    92  	fn->exit = list(fn->exit, nd);
    93  
    94  	if(debug['W']) {
    95  		snprint(s, sizeof(s), "after racewalk %S", fn->nname->sym);
    96  		dumplist(s, fn->nbody);
    97  		snprint(s, sizeof(s), "enter %S", fn->nname->sym);
    98  		dumplist(s, fn->enter);
    99  		snprint(s, sizeof(s), "exit %S", fn->nname->sym);
   100  		dumplist(s, fn->exit);
   101  	}
   102  }
   103  
   104  static void
   105  racewalklist(NodeList *l, NodeList **init)
   106  {
   107  	NodeList *instr;
   108  
   109  	for(; l; l = l->next) {
   110  		instr = nil;
   111  		racewalknode(&l->n, &instr, 0, 0);
   112  		if(init == nil)
   113  			l->n->ninit = concat(l->n->ninit, instr);
   114  		else
   115  			*init = concat(*init, instr);
   116  	}
   117  }
   118  
   119  // walkexpr and walkstmt combined
   120  // walks the tree and adds calls to the
   121  // instrumentation code to top-level (statement) nodes' init
   122  static void
   123  racewalknode(Node **np, NodeList **init, int wr, int skip)
   124  {
   125  	Node *n, *n1;
   126  	NodeList *l;
   127  	NodeList *fini;
   128  
   129  	n = *np;
   130  
   131  	if(n == N)
   132  		return;
   133  
   134  	if(debug['w'] > 1)
   135  		dump("racewalk-before", n);
   136  	setlineno(n);
   137  	if(init == nil)
   138  		fatal("racewalk: bad init list");
   139  	if(init == &n->ninit) {
   140  		// If init == &n->ninit and n->ninit is non-nil,
   141  		// racewalknode might append it to itself.
   142  		// nil it out and handle it separately before putting it back.
   143  		l = n->ninit;
   144  		n->ninit = nil;
   145  		racewalklist(l, nil);
   146  		racewalknode(&n, &l, wr, skip);  // recurse with nil n->ninit
   147  		appendinit(&n, l);
   148  		*np = n;
   149  		return;
   150  	}
   151  
   152  	racewalklist(n->ninit, nil);
   153  
   154  	switch(n->op) {
   155  	default:
   156  		fatal("racewalk: unknown node type %O", n->op);
   157  
   158  	case OASOP:
   159  	case OAS:
   160  	case OAS2:
   161  	case OAS2RECV:
   162  	case OAS2FUNC:
   163  	case OAS2MAPR:
   164  		racewalknode(&n->left, init, 1, 0);
   165  		racewalknode(&n->right, init, 0, 0);
   166  		goto ret;
   167  
   168  	case OCFUNC:
   169  	case OVARKILL:
   170  		// can't matter
   171  		goto ret;
   172  
   173  	case OBLOCK:
   174  		if(n->list == nil)
   175  			goto ret;
   176  
   177  		switch(n->list->n->op) {
   178  		case OCALLFUNC:
   179  		case OCALLMETH:
   180  		case OCALLINTER:
   181  			// Blocks are used for multiple return function calls.
   182  			// x, y := f() becomes BLOCK{CALL f, AS x [SP+0], AS y [SP+n]}
   183  			// We don't want to instrument between the statements because it will
   184  			// smash the results.
   185  			racewalknode(&n->list->n, &n->list->n->ninit, 0, 0);
   186  			fini = nil;
   187  			racewalklist(n->list->next, &fini);
   188  			n->list = concat(n->list, fini);
   189  			break;
   190  
   191  		default:
   192  			// Ordinary block, for loop initialization or inlined bodies.
   193  			racewalklist(n->list, nil);
   194  			break;
   195  		}
   196  		goto ret;
   197  
   198  	case ODEFER:
   199  		racewalknode(&n->left, init, 0, 0);
   200  		goto ret;
   201  
   202  	case OPROC:
   203  		racewalknode(&n->left, init, 0, 0);
   204  		goto ret;
   205  
   206  	case OCALLINTER:
   207  		racewalknode(&n->left, init, 0, 0);
   208  		goto ret;
   209  
   210  	case OCALLFUNC:
   211  		racewalknode(&n->left, init, 0, 0);
   212  		goto ret;
   213  
   214  	case ONOT:
   215  	case OMINUS:
   216  	case OPLUS:
   217  	case OREAL:
   218  	case OIMAG:
   219  	case OCOM:
   220  		racewalknode(&n->left, init, wr, 0);
   221  		goto ret;
   222  
   223  	case ODOTINTER:
   224  		racewalknode(&n->left, init, 0, 0);
   225  		goto ret;
   226  
   227  	case ODOT:
   228  		racewalknode(&n->left, init, 0, 1);
   229  		callinstr(&n, init, wr, skip);
   230  		goto ret;
   231  
   232  	case ODOTPTR: // dst = (*x).f with implicit *; otherwise it's ODOT+OIND
   233  		racewalknode(&n->left, init, 0, 0);
   234  		callinstr(&n, init, wr, skip);
   235  		goto ret;
   236  
   237  	case OIND: // *p
   238  		racewalknode(&n->left, init, 0, 0);
   239  		callinstr(&n, init, wr, skip);
   240  		goto ret;
   241  
   242  	case OSPTR:
   243  	case OLEN:
   244  	case OCAP:
   245  		racewalknode(&n->left, init, 0, 0);
   246  		if(istype(n->left->type, TMAP)) {
   247  			n1 = nod(OCONVNOP, n->left, N);
   248  			n1->type = ptrto(types[TUINT8]);
   249  			n1 = nod(OIND, n1, N);
   250  			typecheck(&n1, Erv);
   251  			callinstr(&n1, init, 0, skip);
   252  		}
   253  		goto ret;
   254  
   255  	case OLSH:
   256  	case ORSH:
   257  	case OLROT:
   258  	case OAND:
   259  	case OANDNOT:
   260  	case OOR:
   261  	case OXOR:
   262  	case OSUB:
   263  	case OMUL:
   264  	case OHMUL:
   265  	case OEQ:
   266  	case ONE:
   267  	case OLT:
   268  	case OLE:
   269  	case OGE:
   270  	case OGT:
   271  	case OADD:
   272  	case OCOMPLEX:
   273  		racewalknode(&n->left, init, wr, 0);
   274  		racewalknode(&n->right, init, wr, 0);
   275  		goto ret;
   276  
   277  	case OANDAND:
   278  	case OOROR:
   279  		racewalknode(&n->left, init, wr, 0);
   280  		// walk has ensured the node has moved to a location where
   281  		// side effects are safe.
   282  		// n->right may not be executed,
   283  		// so instrumentation goes to n->right->ninit, not init.
   284  		racewalknode(&n->right, &n->right->ninit, wr, 0);
   285  		goto ret;
   286  
   287  	case ONAME:
   288  		callinstr(&n, init, wr, skip);
   289  		goto ret;
   290  
   291  	case OCONV:
   292  		racewalknode(&n->left, init, wr, 0);
   293  		goto ret;
   294  
   295  	case OCONVNOP:
   296  		racewalknode(&n->left, init, wr, 0);
   297  		goto ret;
   298  
   299  	case ODIV:
   300  	case OMOD:
   301  		racewalknode(&n->left, init, wr, 0);
   302  		racewalknode(&n->right, init, wr, 0);
   303  		goto ret;
   304  
   305  	case OINDEX:
   306  		if(!isfixedarray(n->left->type))
   307  			racewalknode(&n->left, init, 0, 0);
   308  		else if(!islvalue(n->left)) {
   309  			// index of unaddressable array, like Map[k][i].
   310  			racewalknode(&n->left, init, wr, 0);
   311  			racewalknode(&n->right, init, 0, 0);
   312  			goto ret;
   313  		}
   314  		racewalknode(&n->right, init, 0, 0);
   315  		if(n->left->type->etype != TSTRING)
   316  			callinstr(&n, init, wr, skip);
   317  		goto ret;
   318  
   319  	case OSLICE:
   320  	case OSLICEARR:
   321  	case OSLICE3:
   322  	case OSLICE3ARR:
   323  		// Seems to only lead to double instrumentation.
   324  		//racewalknode(&n->left, init, 0, 0);
   325  		goto ret;
   326  
   327  	case OADDR:
   328  		racewalknode(&n->left, init, 0, 1);
   329  		goto ret;
   330  
   331  	case OEFACE:
   332  		racewalknode(&n->left, init, 0, 0);
   333  		racewalknode(&n->right, init, 0, 0);
   334  		goto ret;
   335  
   336  	case OITAB:
   337  		racewalknode(&n->left, init, 0, 0);
   338  		goto ret;
   339  
   340  	// should not appear in AST by now
   341  	case OSEND:
   342  	case ORECV:
   343  	case OCLOSE:
   344  	case ONEW:
   345  	case OXCASE:
   346  	case OXFALL:
   347  	case OCASE:
   348  	case OPANIC:
   349  	case ORECOVER:
   350  	case OCONVIFACE:
   351  	case OCMPIFACE:
   352  	case OMAKECHAN:
   353  	case OMAKEMAP:
   354  	case OMAKESLICE:
   355  	case OCALL:
   356  	case OCOPY:
   357  	case OAPPEND:
   358  	case ORUNESTR:
   359  	case OARRAYBYTESTR:
   360  	case OARRAYRUNESTR:
   361  	case OSTRARRAYBYTE:
   362  	case OSTRARRAYRUNE:
   363  	case OINDEXMAP:  // lowered to call
   364  	case OCMPSTR:
   365  	case OADDSTR:
   366  	case ODOTTYPE:
   367  	case ODOTTYPE2:
   368  	case OAS2DOTTYPE:
   369  	case OCALLPART: // lowered to PTRLIT
   370  	case OCLOSURE:  // lowered to PTRLIT
   371  	case ORANGE:    // lowered to ordinary for loop
   372  	case OARRAYLIT: // lowered to assignments
   373  	case OMAPLIT:
   374  	case OSTRUCTLIT:
   375  		yyerror("racewalk: %O must be lowered by now", n->op);
   376  		goto ret;
   377  
   378  	// impossible nodes: only appear in backend.
   379  	case ORROTC:
   380  	case OEXTEND:
   381  		yyerror("racewalk: %O cannot exist now", n->op);
   382  		goto ret;
   383  
   384  	// just do generic traversal
   385  	case OFOR:
   386  	case OIF:
   387  	case OCALLMETH:
   388  	case ORETURN:
   389  	case ORETJMP:
   390  	case OSWITCH:
   391  	case OSELECT:
   392  	case OEMPTY:
   393  	case OBREAK:
   394  	case OCONTINUE:
   395  	case OFALL:
   396  	case OGOTO:
   397  	case OLABEL:
   398  		goto ret;
   399  
   400  	// does not require instrumentation
   401  	case OPRINT:     // don't bother instrumenting it
   402  	case OPRINTN:    // don't bother instrumenting it
   403  	case OCHECKNIL: // always followed by a read.
   404  	case OPARAM:     // it appears only in fn->exit to copy heap params back
   405  	case OCLOSUREVAR:// immutable pointer to captured variable
   406  	case ODOTMETH:   // either part of CALLMETH or CALLPART (lowered to PTRLIT)
   407  	case OINDREG:    // at this stage, only n(SP) nodes from nodarg
   408  	case ODCL:       // declarations (without value) cannot be races
   409  	case ODCLCONST:
   410  	case ODCLTYPE:
   411  	case OTYPE:
   412  	case ONONAME:
   413  	case OLITERAL:
   414  	case OSLICESTR:  // always preceded by bounds checking, avoid double instrumentation.
   415  	case OTYPESW:    // ignored by code generation, do not instrument.
   416  		goto ret;
   417  	}
   418  
   419  ret:
   420  	if(n->op != OBLOCK)  // OBLOCK is handled above in a special way.
   421  		racewalklist(n->list, init);
   422  	racewalknode(&n->ntest, &n->ntest->ninit, 0, 0);
   423  	racewalknode(&n->nincr, &n->nincr->ninit, 0, 0);
   424  	racewalklist(n->nbody, nil);
   425  	racewalklist(n->nelse, nil);
   426  	racewalklist(n->rlist, nil);
   427  	*np = n;
   428  }
   429  
   430  static int
   431  isartificial(Node *n)
   432  {
   433  	// compiler-emitted artificial things that we do not want to instrument,
   434  	// cant' possibly participate in a data race.
   435  	if(n->op == ONAME && n->sym != S && n->sym->name != nil) {
   436  		if(strcmp(n->sym->name, "_") == 0)
   437  			return 1;
   438  		// autotmp's are always local
   439  		if(strncmp(n->sym->name, "autotmp_", sizeof("autotmp_")-1) == 0)
   440  			return 1;
   441  		// statictmp's are read-only
   442  		if(strncmp(n->sym->name, "statictmp_", sizeof("statictmp_")-1) == 0)
   443  			return 1;
   444  		// go.itab is accessed only by the compiler and runtime (assume safe)
   445  		if(n->sym->pkg && n->sym->pkg->name && strcmp(n->sym->pkg->name, "go.itab") == 0)
   446  			return 1;
   447  	}
   448  	return 0;
   449  }
   450  
   451  static int
   452  callinstr(Node **np, NodeList **init, int wr, int skip)
   453  {
   454  	Node *f, *b, *n;
   455  	Type *t;
   456  	int class, hascalls;
   457  
   458  	n = *np;
   459  	//print("callinstr for %+N [ %O ] etype=%E class=%d\n",
   460  	//	  n, n->op, n->type ? n->type->etype : -1, n->class);
   461  
   462  	if(skip || n->type == T || n->type->etype >= TIDEAL)
   463  		return 0;
   464  	t = n->type;
   465  	if(isartificial(n))
   466  		return 0;
   467  
   468  	b = basenod(n);
   469  	// it skips e.g. stores to ... parameter array
   470  	if(isartificial(b))
   471  		return 0;
   472  	class = b->class;
   473  	// BUG: we _may_ want to instrument PAUTO sometimes
   474  	// e.g. if we've got a local variable/method receiver
   475  	// that has got a pointer inside. Whether it points to
   476  	// the heap or not is impossible to know at compile time
   477  	if((class&PHEAP) || class == PPARAMREF || class == PEXTERN
   478  		|| b->op == OINDEX || b->op == ODOTPTR || b->op == OIND || b->op == OXDOT) {
   479  		hascalls = 0;
   480  		foreach(n, hascallspred, &hascalls);
   481  		if(hascalls) {
   482  			n = detachexpr(n, init);
   483  			*np = n;
   484  		}
   485  		n = treecopy(n);
   486  		makeaddable(n);
   487  		if(t->etype == TSTRUCT || isfixedarray(t)) {
   488  			f = mkcall(wr ? "racewriterange" : "racereadrange", T, init, uintptraddr(n),
   489  					nodintconst(t->width));
   490  		} else
   491  			f = mkcall(wr ? "racewrite" : "raceread", T, init, uintptraddr(n));
   492  		*init = list(*init, f);
   493  		return 1;
   494  	}
   495  	return 0;
   496  }
   497  
   498  // makeaddable returns a node whose memory location is the
   499  // same as n, but which is addressable in the Go language
   500  // sense.
   501  // This is different from functions like cheapexpr that may make
   502  // a copy of their argument.
   503  static void
   504  makeaddable(Node *n)
   505  {
   506  	// The arguments to uintptraddr technically have an address but
   507  	// may not be addressable in the Go sense: for example, in the case
   508  	// of T(v).Field where T is a struct type and v is
   509  	// an addressable value.
   510  	switch(n->op) {
   511  	case OINDEX:
   512  		if(isfixedarray(n->left->type))
   513  			makeaddable(n->left);
   514  		break;
   515  	case ODOT:
   516  	case OXDOT:
   517  		// Turn T(v).Field into v.Field
   518  		if(n->left->op == OCONVNOP)
   519  			n->left = n->left->left;
   520  		makeaddable(n->left);
   521  		break;
   522  	case ODOTPTR:
   523  	default:
   524  		// nothing to do
   525  		break;
   526  	}
   527  }
   528  
   529  static Node*
   530  uintptraddr(Node *n)
   531  {
   532  	Node *r;
   533  
   534  	r = nod(OADDR, n, N);
   535  	r->bounded = 1;
   536  	r = conv(r, types[TUNSAFEPTR]);
   537  	r = conv(r, types[TUINTPTR]);
   538  	return r;
   539  }
   540  
   541  // basenod returns the simplest child node of n pointing to the same
   542  // memory area.
   543  static Node*
   544  basenod(Node *n)
   545  {
   546  	for(;;) {
   547  		if(n->op == ODOT || n->op == OXDOT || n->op == OCONVNOP || n->op == OCONV || n->op == OPAREN) {
   548  			n = n->left;
   549  			continue;
   550  		}
   551  		if(n->op == OINDEX && isfixedarray(n->type)) {
   552  			n = n->left;
   553  			continue;
   554  		}
   555  		break;
   556  	}
   557  	return n;
   558  }
   559  
   560  static Node*
   561  detachexpr(Node *n, NodeList **init)
   562  {
   563  	Node *addr, *as, *ind, *l;
   564  
   565  	addr = nod(OADDR, n, N);
   566  	l = temp(ptrto(n->type));
   567  	as = nod(OAS, l, addr);
   568  	typecheck(&as, Etop);
   569  	walkexpr(&as, init);
   570  	*init = list(*init, as);
   571  	ind = nod(OIND, l, N);
   572  	typecheck(&ind, Erv);
   573  	walkexpr(&ind, init);
   574  	return ind;
   575  }
   576  
   577  static void
   578  foreachnode(Node *n, void(*f)(Node*, void*), void *c)
   579  {
   580  	if(n)
   581  		f(n, c);
   582  }
   583  
   584  static void
   585  foreachlist(NodeList *l, void(*f)(Node*, void*), void *c)
   586  {
   587  	for(; l; l = l->next)
   588  		foreachnode(l->n, f, c);
   589  }
   590  
   591  static void
   592  foreach(Node *n, void(*f)(Node*, void*), void *c)
   593  {
   594  	foreachlist(n->ninit, f, c);
   595  	foreachnode(n->left, f, c);
   596  	foreachnode(n->right, f, c);
   597  	foreachlist(n->list, f, c);
   598  	foreachnode(n->ntest, f, c);
   599  	foreachnode(n->nincr, f, c);
   600  	foreachlist(n->nbody, f, c);
   601  	foreachlist(n->nelse, f, c);
   602  	foreachlist(n->rlist, f, c);
   603  }
   604  
   605  static void
   606  hascallspred(Node *n, void *c)
   607  {
   608  	switch(n->op) {
   609  	case OCALL:
   610  	case OCALLFUNC:
   611  	case OCALLMETH:
   612  	case OCALLINTER:
   613  		(*(int*)c)++;
   614  	}
   615  }
   616  
   617  // appendinit is like addinit in subr.c
   618  // but appends rather than prepends.
   619  static void
   620  appendinit(Node **np, NodeList *init)
   621  {
   622  	Node *n;
   623  
   624  	if(init == nil)
   625  		return;
   626  
   627  	n = *np;
   628  	switch(n->op) {
   629  	case ONAME:
   630  	case OLITERAL:
   631  		// There may be multiple refs to this node;
   632  		// introduce OCONVNOP to hold init list.
   633  		n = nod(OCONVNOP, n, N);
   634  		n->type = n->left->type;
   635  		n->typecheck = 1;
   636  		*np = n;
   637  		break;
   638  	}
   639  	n->ninit = concat(n->ninit, init);
   640  	n->ullman = UINF;
   641  }
   642