xref: /third_party/node/deps/v8/tools/gcmole/README (revision 1cb0ef41)
11cb0ef41Sopenharmony_ciDESCRIPTION -------------------------------------------------------------------
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_cigcmole is a simple static analysis tool used to find possible evaluation order 
41cb0ef41Sopenharmony_cidependent GC-unsafe places in the V8 codebase and "stale" pointers to the heap
51cb0ef41Sopenharmony_ci(ones whose addresses got invalidated by the GC).
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciFor example the following code is GC-unsafe:
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci    Handle<Object> Foo();  // Assume Foo can trigger a GC.
101cb0ef41Sopenharmony_ci    void Bar(Object, Object);
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci    Handle<Object> baz;
131cb0ef41Sopenharmony_ci    baz->Qux(*Foo());  // (a)
141cb0ef41Sopenharmony_ci    Bar(*Foo(), *baz); // (b)
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ciBoth in cases (a) and (b) compiler is free to evaluate call arguments (that 
171cb0ef41Sopenharmony_ciincludes receiver) in any order. That means it can dereference baz before 
181cb0ef41Sopenharmony_cicalling to Foo and save a raw pointer to a heap object in the register or 
191cb0ef41Sopenharmony_cion the stack.
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ciIn terms of the AST analysis that gcmole does, it warns about places in the
221cb0ef41Sopenharmony_cicode which result in 2 subtrees, the order of execution of which is undefined
231cb0ef41Sopenharmony_ciby C++, one of which causes a GC and the other dereferences a Handle to a raw
241cb0ef41Sopenharmony_ciObject (or its subclasses).
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ciThe following code triggers a stale variable warning (assuming that the Foo
271cb0ef41Sopenharmony_cifunction was detected as potentially allocating, as in the previous example):
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci    JSObject raw_obj = ...;
301cb0ef41Sopenharmony_ci    Foo();
311cb0ef41Sopenharmony_ci    raw_obj.Print();
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ciSince Foo can trigger a GC, it might have moved the raw_obj. The solution is
341cb0ef41Sopenharmony_cisimply to store it as a Handle.
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ciPREREQUISITES -----------------------------------------------------------------
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci(1) Install Python
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci    $ sudo apt-get install python
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci(2) Get LLVM 8.0 and Clang 8.0 sources and build them.
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci    Follow the instructions on http://clang.llvm.org/get_started.html.
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci    Make sure to pass -DCMAKE_BUILD_TYPE=Release to cmake to get Release build 
471cb0ef41Sopenharmony_ci    instead of a Debug one.
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci(3) Build gcmole Clang plugin (libgcmole.so)
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci    In the tools/gcmole directory execute the following command:
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci    $ BUILD_ROOT=<path> LLVM_SRC_ROOT=<path> CLANG_SRC_ROOT=<path> make
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci(*) Note that steps (2) and (3) can also be achieved by just using the included
561cb0ef41Sopenharmony_ci    bootstrapping script in this directory:
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci    $ ./tools/gcmole/bootstrap.sh
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci    This will use "third_party/llvm+clang-build" as a build directory and checkout
611cb0ef41Sopenharmony_ci    required sources in the "third_party" directory.
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ciUSING GCMOLE ------------------------------------------------------------------
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_cigcmole consists of driver script written in Python and Clang plugin that does
661cb0ef41Sopenharmony_ciC++ AST processing. Plugin (libgcmole.so) is expected to be in the same
671cb0ef41Sopenharmony_cifolder as driver (gcmole.py).
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ciTo start analysis cd into the root of v8 checkout and execute the following
701cb0ef41Sopenharmony_cicommand:
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ciCLANG_BIN=<path-to-clang-bin-folder> python tools/gcmole/gcmole.py [<arch>]
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ciwhere arch should be one of architectures supported by V8 (arm, ia32, x64).
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ciAnalysis will be performed in 2 stages: 
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci- on the first stage driver will parse all files and build a global callgraph 
791cb0ef41Sopenharmony_ciapproximation to find all functions that might potentially cause GC, list
801cb0ef41Sopenharmony_ciof this functions will be written into gcsuspects file.
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci- on the second stage driver will parse all files again and will locate all 
831cb0ef41Sopenharmony_cicallsites that might be GC-unsafe based on the list of functions causing GC. 
841cb0ef41Sopenharmony_ciSuch places are marked with a "Possible problem with evaluation order." 
851cb0ef41Sopenharmony_ciwarning. Messages "Failed to resolve v8::internal::Object" are benign and 
861cb0ef41Sopenharmony_cican be ignored.
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ciIf any errors were found driver exits with non-zero status.
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ciTESTING -----------------------------------------------------------------------
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ciTests are automatically run by the main python runner. Expectations are in
931cb0ef41Sopenharmony_citest-expectations.txt and need to be updated whenever the sources of the tests
941cb0ef41Sopenharmony_ciin gcmole-test.cc are modified (line numbers also count).
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ciPACKAGING ---------------------------------------------------------------------
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_cigcmole is deployed on V8's buildbot infrastructure to run it as part of the
991cb0ef41Sopenharmony_cicontinuous integration. A pre-built package of gcmole together with Clang is
1001cb0ef41Sopenharmony_cihosted on Google Cloud Storage for this purpose. To update this package to a
1011cb0ef41Sopenharmony_cinewer version, use the provided packaging script:
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci    $ ./tools/gcmole/package.sh
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ciThis will create a new "tools/gcmole/gcmole-tools.tar.gz" package with the
1061cb0ef41Sopenharmony_cicorresponding SHA1 sum suitable to be used for this purpose. It assumes that
1071cb0ef41Sopenharmony_ciClang was built in "third_party/llvm+clang-build" (e.g. by the bootstrapping
1081cb0ef41Sopenharmony_ciscript "bootstrap.sh" mentioned above).
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ciTROUBLESHOOTING ---------------------------------------------------------------
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_cigcmole is tightly coupled with the AST structure that Clang produces. Therefore
1131cb0ef41Sopenharmony_ciwhen upgrading to a newer Clang version, it might start producing bogus output
1141cb0ef41Sopenharmony_cior completely stop outputting warnings. In such occasion, one might start the
1151cb0ef41Sopenharmony_cidebugging process by checking weather a new AST node type is introduced which
1161cb0ef41Sopenharmony_ciis currently not supported by gcmole. Insert the following code at the end of
1171cb0ef41Sopenharmony_cithe FunctionAnalyzer::VisitExpr method to see the unsupported AST class(es)
1181cb0ef41Sopenharmony_ciand the source position which generates them:
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci    if (expr) {
1211cb0ef41Sopenharmony_ci      clang::Stmt::StmtClass stmtClass = expr->getStmtClass();
1221cb0ef41Sopenharmony_ci      d_.Report(clang::FullSourceLoc(expr->getExprLoc(), sm_),
1231cb0ef41Sopenharmony_ci        d_.getCustomDiagID(clang::DiagnosticsEngine::Remark, "%0")) << stmtClass;
1241cb0ef41Sopenharmony_ci    }
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_ciFor instance, gcmole currently doesn't support AtomicExprClass statements
1271cb0ef41Sopenharmony_ciintroduced for atomic operations.
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ciA convenient way to observe the AST generated by Clang is to pass the following
1301cb0ef41Sopenharmony_ciflags when invoking clang++
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci    -Xclang -ast-dump -fsyntax-only
133