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