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