github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/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  		// Instrument dst argument of runtime.writebarrier* calls
   212  		// as we do not instrument runtime code.
   213  		if(n->left->sym != S && n->left->sym->pkg == runtimepkg && strncmp(n->left->sym->name, "writebarrier", 12) == 0) {
   214  			// Find the dst argument.
   215  			// The list can be reordered, so it's not necessary just the first or the second element.
   216  			for(l = n->list; l; l = l->next) {
   217  				if(strcmp(n->left->sym->name, "writebarrierfat") == 0) {
   218  					if(l->n->left->xoffset == widthptr)
   219  						break;
   220  				} else {
   221  					if(l->n->left->xoffset == 0)
   222  						break;
   223  				}
   224  			}
   225  			if(l == nil)
   226  				fatal("racewalk: writebarrier no arg");
   227  			if(l->n->right->op != OADDR)
   228  				fatal("racewalk: writebarrier bad arg");
   229  			callinstr(&l->n->right->left, init, 1, 0);
   230  		}
   231  		racewalknode(&n->left, init, 0, 0);
   232  		goto ret;
   233  
   234  	case ONOT:
   235  	case OMINUS:
   236  	case OPLUS:
   237  	case OREAL:
   238  	case OIMAG:
   239  	case OCOM:
   240  		racewalknode(&n->left, init, wr, 0);
   241  		goto ret;
   242  
   243  	case ODOTINTER:
   244  		racewalknode(&n->left, init, 0, 0);
   245  		goto ret;
   246  
   247  	case ODOT:
   248  		racewalknode(&n->left, init, 0, 1);
   249  		callinstr(&n, init, wr, skip);
   250  		goto ret;
   251  
   252  	case ODOTPTR: // dst = (*x).f with implicit *; otherwise it's ODOT+OIND
   253  		racewalknode(&n->left, init, 0, 0);
   254  		callinstr(&n, init, wr, skip);
   255  		goto ret;
   256  
   257  	case OIND: // *p
   258  		racewalknode(&n->left, init, 0, 0);
   259  		callinstr(&n, init, wr, skip);
   260  		goto ret;
   261  
   262  	case OSPTR:
   263  	case OLEN:
   264  	case OCAP:
   265  		racewalknode(&n->left, init, 0, 0);
   266  		if(istype(n->left->type, TMAP)) {
   267  			n1 = nod(OCONVNOP, n->left, N);
   268  			n1->type = ptrto(types[TUINT8]);
   269  			n1 = nod(OIND, n1, N);
   270  			typecheck(&n1, Erv);
   271  			callinstr(&n1, init, 0, skip);
   272  		}
   273  		goto ret;
   274  
   275  	case OLSH:
   276  	case ORSH:
   277  	case OLROT:
   278  	case OAND:
   279  	case OANDNOT:
   280  	case OOR:
   281  	case OXOR:
   282  	case OSUB:
   283  	case OMUL:
   284  	case OHMUL:
   285  	case OEQ:
   286  	case ONE:
   287  	case OLT:
   288  	case OLE:
   289  	case OGE:
   290  	case OGT:
   291  	case OADD:
   292  	case OCOMPLEX:
   293  		racewalknode(&n->left, init, wr, 0);
   294  		racewalknode(&n->right, init, wr, 0);
   295  		goto ret;
   296  
   297  	case OANDAND:
   298  	case OOROR:
   299  		racewalknode(&n->left, init, wr, 0);
   300  		// walk has ensured the node has moved to a location where
   301  		// side effects are safe.
   302  		// n->right may not be executed,
   303  		// so instrumentation goes to n->right->ninit, not init.
   304  		racewalknode(&n->right, &n->right->ninit, wr, 0);
   305  		goto ret;
   306  
   307  	case ONAME:
   308  		callinstr(&n, init, wr, skip);
   309  		goto ret;
   310  
   311  	case OCONV:
   312  		racewalknode(&n->left, init, wr, 0);
   313  		goto ret;
   314  
   315  	case OCONVNOP:
   316  		racewalknode(&n->left, init, wr, 0);
   317  		goto ret;
   318  
   319  	case ODIV:
   320  	case OMOD:
   321  		racewalknode(&n->left, init, wr, 0);
   322  		racewalknode(&n->right, init, wr, 0);
   323  		goto ret;
   324  
   325  	case OINDEX:
   326  		if(!isfixedarray(n->left->type))
   327  			racewalknode(&n->left, init, 0, 0);
   328  		else if(!islvalue(n->left)) {
   329  			// index of unaddressable array, like Map[k][i].
   330  			racewalknode(&n->left, init, wr, 0);
   331  			racewalknode(&n->right, init, 0, 0);
   332  			goto ret;
   333  		}
   334  		racewalknode(&n->right, init, 0, 0);
   335  		if(n->left->type->etype != TSTRING)
   336  			callinstr(&n, init, wr, skip);
   337  		goto ret;
   338  
   339  	case OSLICE:
   340  	case OSLICEARR:
   341  	case OSLICE3:
   342  	case OSLICE3ARR:
   343  		// Seems to only lead to double instrumentation.
   344  		//racewalknode(&n->left, init, 0, 0);
   345  		goto ret;
   346  
   347  	case OADDR:
   348  		racewalknode(&n->left, init, 0, 1);
   349  		goto ret;
   350  
   351  	case OEFACE:
   352  		racewalknode(&n->left, init, 0, 0);
   353  		racewalknode(&n->right, init, 0, 0);
   354  		goto ret;
   355  
   356  	case OITAB:
   357  		racewalknode(&n->left, init, 0, 0);
   358  		goto ret;
   359  
   360  	// should not appear in AST by now
   361  	case OSEND:
   362  	case ORECV:
   363  	case OCLOSE:
   364  	case ONEW:
   365  	case OXCASE:
   366  	case OXFALL:
   367  	case OCASE:
   368  	case OPANIC:
   369  	case ORECOVER:
   370  	case OCONVIFACE:
   371  	case OCMPIFACE:
   372  	case OMAKECHAN:
   373  	case OMAKEMAP:
   374  	case OMAKESLICE:
   375  	case OCALL:
   376  	case OCOPY:
   377  	case OAPPEND:
   378  	case ORUNESTR:
   379  	case OARRAYBYTESTR:
   380  	case OARRAYRUNESTR:
   381  	case OSTRARRAYBYTE:
   382  	case OSTRARRAYRUNE:
   383  	case OINDEXMAP:  // lowered to call
   384  	case OCMPSTR:
   385  	case OADDSTR:
   386  	case ODOTTYPE:
   387  	case ODOTTYPE2:
   388  	case OAS2DOTTYPE:
   389  	case OCALLPART: // lowered to PTRLIT
   390  	case OCLOSURE:  // lowered to PTRLIT
   391  	case ORANGE:    // lowered to ordinary for loop
   392  	case OARRAYLIT: // lowered to assignments
   393  	case OMAPLIT:
   394  	case OSTRUCTLIT:
   395  		yyerror("racewalk: %O must be lowered by now", n->op);
   396  		goto ret;
   397  
   398  	// impossible nodes: only appear in backend.
   399  	case ORROTC:
   400  	case OEXTEND:
   401  		yyerror("racewalk: %O cannot exist now", n->op);
   402  		goto ret;
   403  
   404  	// just do generic traversal
   405  	case OFOR:
   406  	case OIF:
   407  	case OCALLMETH:
   408  	case ORETURN:
   409  	case ORETJMP:
   410  	case OSWITCH:
   411  	case OSELECT:
   412  	case OEMPTY:
   413  	case OBREAK:
   414  	case OCONTINUE:
   415  	case OFALL:
   416  	case OGOTO:
   417  	case OLABEL:
   418  		goto ret;
   419  
   420  	// does not require instrumentation
   421  	case OPRINT:     // don't bother instrumenting it
   422  	case OPRINTN:    // don't bother instrumenting it
   423  	case OCHECKNIL: // always followed by a read.
   424  	case OPARAM:     // it appears only in fn->exit to copy heap params back
   425  	case OCLOSUREVAR:// immutable pointer to captured variable
   426  	case ODOTMETH:   // either part of CALLMETH or CALLPART (lowered to PTRLIT)
   427  	case OINDREG:    // at this stage, only n(SP) nodes from nodarg
   428  	case ODCL:       // declarations (without value) cannot be races
   429  	case ODCLCONST:
   430  	case ODCLTYPE:
   431  	case OTYPE:
   432  	case ONONAME:
   433  	case OLITERAL:
   434  	case OSLICESTR:  // always preceded by bounds checking, avoid double instrumentation.
   435  	case OTYPESW:    // ignored by code generation, do not instrument.
   436  		goto ret;
   437  	}
   438  
   439  ret:
   440  	if(n->op != OBLOCK)  // OBLOCK is handled above in a special way.
   441  		racewalklist(n->list, init);
   442  	if(n->ntest != N)
   443  		racewalknode(&n->ntest, &n->ntest->ninit, 0, 0);
   444  	if(n->nincr != N)
   445  		racewalknode(&n->nincr, &n->nincr->ninit, 0, 0);
   446  	racewalklist(n->nbody, nil);
   447  	racewalklist(n->nelse, nil);
   448  	racewalklist(n->rlist, nil);
   449  	*np = n;
   450  }
   451  
   452  static int
   453  isartificial(Node *n)
   454  {
   455  	// compiler-emitted artificial things that we do not want to instrument,
   456  	// cant' possibly participate in a data race.
   457  	if(n->op == ONAME && n->sym != S && n->sym->name != nil) {
   458  		if(strcmp(n->sym->name, "_") == 0)
   459  			return 1;
   460  		// autotmp's are always local
   461  		if(strncmp(n->sym->name, "autotmp_", sizeof("autotmp_")-1) == 0)
   462  			return 1;
   463  		// statictmp's are read-only
   464  		if(strncmp(n->sym->name, "statictmp_", sizeof("statictmp_")-1) == 0)
   465  			return 1;
   466  		// go.itab is accessed only by the compiler and runtime (assume safe)
   467  		if(n->sym->pkg && n->sym->pkg->name && strcmp(n->sym->pkg->name, "go.itab") == 0)
   468  			return 1;
   469  	}
   470  	return 0;
   471  }
   472  
   473  static int
   474  callinstr(Node **np, NodeList **init, int wr, int skip)
   475  {
   476  	Node *f, *b, *n;
   477  	Type *t;
   478  	int class, hascalls;
   479  
   480  	n = *np;
   481  	//print("callinstr for %+N [ %O ] etype=%E class=%d\n",
   482  	//	  n, n->op, n->type ? n->type->etype : -1, n->class);
   483  
   484  	if(skip || n->type == T || n->type->etype >= TIDEAL)
   485  		return 0;
   486  	t = n->type;
   487  	if(isartificial(n))
   488  		return 0;
   489  
   490  	b = basenod(n);
   491  	// it skips e.g. stores to ... parameter array
   492  	if(isartificial(b))
   493  		return 0;
   494  	class = b->class;
   495  	// BUG: we _may_ want to instrument PAUTO sometimes
   496  	// e.g. if we've got a local variable/method receiver
   497  	// that has got a pointer inside. Whether it points to
   498  	// the heap or not is impossible to know at compile time
   499  	if((class&PHEAP) || class == PPARAMREF || class == PEXTERN
   500  		|| b->op == OINDEX || b->op == ODOTPTR || b->op == OIND || b->op == OXDOT) {
   501  		hascalls = 0;
   502  		foreach(n, hascallspred, &hascalls);
   503  		if(hascalls) {
   504  			n = detachexpr(n, init);
   505  			*np = n;
   506  		}
   507  		n = treecopy(n);
   508  		makeaddable(n);
   509  		if(t->etype == TSTRUCT || isfixedarray(t)) {
   510  			f = mkcall(wr ? "racewriterange" : "racereadrange", T, init, uintptraddr(n),
   511  					nodintconst(t->width));
   512  		} else
   513  			f = mkcall(wr ? "racewrite" : "raceread", T, init, uintptraddr(n));
   514  		*init = list(*init, f);
   515  		return 1;
   516  	}
   517  	return 0;
   518  }
   519  
   520  // makeaddable returns a node whose memory location is the
   521  // same as n, but which is addressable in the Go language
   522  // sense.
   523  // This is different from functions like cheapexpr that may make
   524  // a copy of their argument.
   525  static void
   526  makeaddable(Node *n)
   527  {
   528  	// The arguments to uintptraddr technically have an address but
   529  	// may not be addressable in the Go sense: for example, in the case
   530  	// of T(v).Field where T is a struct type and v is
   531  	// an addressable value.
   532  	switch(n->op) {
   533  	case OINDEX:
   534  		if(isfixedarray(n->left->type))
   535  			makeaddable(n->left);
   536  		break;
   537  	case ODOT:
   538  	case OXDOT:
   539  		// Turn T(v).Field into v.Field
   540  		if(n->left->op == OCONVNOP)
   541  			n->left = n->left->left;
   542  		makeaddable(n->left);
   543  		break;
   544  	case ODOTPTR:
   545  	default:
   546  		// nothing to do
   547  		break;
   548  	}
   549  }
   550  
   551  static Node*
   552  uintptraddr(Node *n)
   553  {
   554  	Node *r;
   555  
   556  	r = nod(OADDR, n, N);
   557  	r->bounded = 1;
   558  	r = conv(r, types[TUNSAFEPTR]);
   559  	r = conv(r, types[TUINTPTR]);
   560  	return r;
   561  }
   562  
   563  // basenod returns the simplest child node of n pointing to the same
   564  // memory area.
   565  static Node*
   566  basenod(Node *n)
   567  {
   568  	for(;;) {
   569  		if(n->op == ODOT || n->op == OXDOT || n->op == OCONVNOP || n->op == OCONV || n->op == OPAREN) {
   570  			n = n->left;
   571  			continue;
   572  		}
   573  		if(n->op == OINDEX && isfixedarray(n->type)) {
   574  			n = n->left;
   575  			continue;
   576  		}
   577  		break;
   578  	}
   579  	return n;
   580  }
   581  
   582  static Node*
   583  detachexpr(Node *n, NodeList **init)
   584  {
   585  	Node *addr, *as, *ind, *l;
   586  
   587  	addr = nod(OADDR, n, N);
   588  	l = temp(ptrto(n->type));
   589  	as = nod(OAS, l, addr);
   590  	typecheck(&as, Etop);
   591  	walkexpr(&as, init);
   592  	*init = list(*init, as);
   593  	ind = nod(OIND, l, N);
   594  	typecheck(&ind, Erv);
   595  	walkexpr(&ind, init);
   596  	return ind;
   597  }
   598  
   599  static void
   600  foreachnode(Node *n, void(*f)(Node*, void*), void *c)
   601  {
   602  	if(n)
   603  		f(n, c);
   604  }
   605  
   606  static void
   607  foreachlist(NodeList *l, void(*f)(Node*, void*), void *c)
   608  {
   609  	for(; l; l = l->next)
   610  		foreachnode(l->n, f, c);
   611  }
   612  
   613  static void
   614  foreach(Node *n, void(*f)(Node*, void*), void *c)
   615  {
   616  	foreachlist(n->ninit, f, c);
   617  	foreachnode(n->left, f, c);
   618  	foreachnode(n->right, f, c);
   619  	foreachlist(n->list, f, c);
   620  	foreachnode(n->ntest, f, c);
   621  	foreachnode(n->nincr, f, c);
   622  	foreachlist(n->nbody, f, c);
   623  	foreachlist(n->nelse, f, c);
   624  	foreachlist(n->rlist, f, c);
   625  }
   626  
   627  static void
   628  hascallspred(Node *n, void *c)
   629  {
   630  	switch(n->op) {
   631  	case OCALL:
   632  	case OCALLFUNC:
   633  	case OCALLMETH:
   634  	case OCALLINTER:
   635  		(*(int*)c)++;
   636  	}
   637  }
   638  
   639  // appendinit is like addinit in subr.c
   640  // but appends rather than prepends.
   641  static void
   642  appendinit(Node **np, NodeList *init)
   643  {
   644  	Node *n;
   645  
   646  	if(init == nil)
   647  		return;
   648  
   649  	n = *np;
   650  	switch(n->op) {
   651  	case ONAME:
   652  	case OLITERAL:
   653  		// There may be multiple refs to this node;
   654  		// introduce OCONVNOP to hold init list.
   655  		n = nod(OCONVNOP, n, N);
   656  		n->type = n->left->type;
   657  		n->typecheck = 1;
   658  		*np = n;
   659  		break;
   660  	}
   661  	n->ninit = concat(n->ninit, init);
   662  	n->ullman = UINF;
   663  }
   664