From 44a3bec2ff425be06ac26a661a13f4754c7ae7c1 Mon Sep 17 00:00:00 2001 From: Oliver Schranz Date: Fri, 8 Jun 2018 13:26:08 +0200 Subject: [PATCH] Fixes + comments & documentation. Can now be used as a template * adapted to use the new api layout of ARTist * updated with changed signatures from ARTist (updated module-sdk) * added comments and documentation * created 2 artist passes to showcase different use cases and existing boilerplate code, one injection pass (HInjectionArtist) and one basic pass (HArtist) * added small filter to only accept non-static methods (and skip the majority to not bloat logcat too much) --- CMakeLists.txt | 8 +- Manifest.json | 8 +- codelib.apk | Bin 0 -> 8353 bytes src/codelib.cc | 34 +++--- src/codelib.h | 23 ++-- src/instrumentation_pass.cc | 54 --------- src/module.cc | 44 +++++--- src/module.h | 14 ++- src/simple_method_filter.cc | 45 ++++++++ src/simple_method_filter.h | 47 ++++++++ src/template_basic_pass.cc | 104 ++++++++++++++++++ ...mentation_pass.h => template_basic_pass.h} | 22 ++-- src/template_injection_pass.cc | 76 +++++++++++++ src/template_injection_pass.h | 56 ++++++++++ 14 files changed, 422 insertions(+), 113 deletions(-) create mode 100644 codelib.apk delete mode 100644 src/instrumentation_pass.cc create mode 100644 src/simple_method_filter.cc create mode 100644 src/simple_method_filter.h create mode 100644 src/template_basic_pass.cc rename src/{instrumentation_pass.h => template_basic_pass.h} (65%) create mode 100644 src/template_injection_pass.cc create mode 100644 src/template_injection_pass.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e3e8c75..8579b26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,10 +6,12 @@ set(CMAKE_CXX_STANDARD 11) add_executable(template_module src/module.cc src/module.h - src/instrumentation_pass.cc - src/instrumentation_pass.h + src/template_injection_pass.cc + src/template_injection_pass.h + src/template_basic_pass.cc + src/template_basic_pass.h src/codelib.cc - src/codelib.h) + src/codelib.h src/simple_method_filter.cc src/simple_method_filter.h) target_include_directories(template_module PUBLIC /opt/artist-sdk/include/external/valgrind diff --git a/Manifest.json b/Manifest.json index ecbac5f..4d7b870 100644 --- a/Manifest.json +++ b/Manifest.json @@ -1,8 +1,8 @@ { "manifest_version": 1, - "package_name": "com.example.module", - "name": "Artist Module", - "description": "This a template module.", - "author": "John Doe ", + "package_name": "saarland.cispa.artist.module.template", + "name": "Template Module", + "description": "This a template module, all functionality is purely educational. If you want ", + "author": "Parthipan Ramesh , Oliver Schranz ", "version": 1 } diff --git a/codelib.apk b/codelib.apk new file mode 100644 index 0000000000000000000000000000000000000000..def28b21e999357857f1b9214be2395a94fe5cc8 GIT binary patch literal 8353 zcmeHNcT`i$)=vltQX(Q9rAbE(y-OF6i$JJKks>677BF-KDI#b

6tBnn;IG1VKQ$ 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 I!oAP^3-&T4dH?_b literal 0 HcmV?d00001 diff --git a/src/codelib.cc b/src/codelib.cc index bdfaa08..f5d44d1 100644 --- a/src/codelib.cc +++ b/src/codelib.cc @@ -16,29 +16,31 @@ * limitations under the License. * * @author "Parthipan Ramesh " + * @author "Oliver Schranz " * */ #include "codelib.h" -unordered_set &ModuleCodeLib::getMethods() const { - // TODO: implement methods like example below - // static string instanceField = "Lsaarland/cispa/artist/codelib/CodeLib;traceLog()V"; - // static unordered_set methods({instanceField}); - static unordered_set methods({}); - return methods; +const std::string TemplateCodeLib::INJECTION_ARTIST_TARGET("Lsaarland/cispa/artist/codelib/CodeLib;injectionArtistTarget(I)V"); +const std::string TemplateCodeLib::BASIC_ARTIST_TARGET("Lsaarland/cispa/artist/codelib/CodeLib;basicArtistTarget(ILjava/lang/Object;)V"); + + +unordered_set &TemplateCodeLib::getMethods() const { + // here we expose the signatures of codelib methods that are meant to be used from ARTist + static unordered_set methods({INJECTION_ARTIST_TARGET, BASIC_ARTIST_TARGET}); + return methods; } -string &ModuleCodeLib::getInstanceField() const { - // TODO: implement instance fields like example below - // static string instanceField = "Lsaarland/cispa/artist/codelib/CodeLib;INSTANCE"; - static string instanceField; - return instanceField; +string &TemplateCodeLib::getInstanceField() const { + // here we expose the static field with our singleton instance. This will be used by ARTist to obtain an instance + // of the codelib to call methods on it. + static string instanceField = "Lsaarland/cispa/artist/codelib/CodeLib;INSTANCE"; + return instanceField; } -string &ModuleCodeLib::getCodeClass() const { - // TODO: implement code class like example below - // static string codeClass = "Lsaarland/cispa/artist/codelib/CodeLib;"; - static string codeClass; - return codeClass; +string &TemplateCodeLib::getCodeClass() const { + // here we expose the codelib's java class to be able to load it in ARTist + static string codeClass = "Lsaarland/cispa/artist/codelib/CodeLib;"; + return codeClass; } diff --git a/src/codelib.h b/src/codelib.h index 0d71b3a..840f9d8 100644 --- a/src/codelib.h +++ b/src/codelib.h @@ -16,6 +16,7 @@ * limitations under the License. * * @author "Parthipan Ramesh " + * @author "Oliver Schranz " * */ @@ -24,32 +25,36 @@ #include #include -#include +#include using std::string; using std::unordered_set; using art::CodeLib; -class ModuleCodeLib : public CodeLib { +class TemplateCodeLib : public CodeLib { public: - ModuleCodeLib() = default; + static const string INJECTION_ARTIST_TARGET; + static const string BASIC_ARTIST_TARGET; - ModuleCodeLib(const ModuleCodeLib &other) = default; - ModuleCodeLib(ModuleCodeLib &&other) = default; + TemplateCodeLib() = default; - ~ModuleCodeLib() override = default; + TemplateCodeLib(const TemplateCodeLib &other) = default; - ModuleCodeLib &operator=(const ModuleCodeLib &) = default; + TemplateCodeLib(TemplateCodeLib &&other) = default; - ModuleCodeLib &operator=(ModuleCodeLib &&) = default; + ~TemplateCodeLib() override = default; + + TemplateCodeLib &operator=(const TemplateCodeLib &) = default; + + TemplateCodeLib &operator=(TemplateCodeLib &&) = default; unordered_set &getMethods() const override; string &getInstanceField() const override; string &getCodeClass() const override; -}; // class ModuleCodeLib +}; // class TemplateCodeLib #endif // ART_MODULES_CODELIB_H_ diff --git a/src/instrumentation_pass.cc b/src/instrumentation_pass.cc deleted file mode 100644 index 94ab316..0000000 --- a/src/instrumentation_pass.cc +++ /dev/null @@ -1,54 +0,0 @@ -/** - * The ARTist Project (https://artist.cispa.saarland) - * - * Copyright (C) 2018 CISPA (https://cispa.saarland), Saarland University - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @author "Parthipan Ramesh " - * - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "instrumentation_pass.h" - -using std::string; -using std::vector; -using std::shared_ptr; -using std::make_shared; -using std::endl; -using std::sort; - -using art::Target; -using art::Parameter; -using art::Char; -using art::InjectionTarget; - -vector HModule::ProvideInjections() const { - vector results; - - // TODO: Implement injections here - - return results; -} diff --git a/src/module.cc b/src/module.cc index 8580215..56bc29d 100644 --- a/src/module.cc +++ b/src/module.cc @@ -16,33 +16,51 @@ * limitations under the License. * * @author "Parthipan Ramesh " + * @author "Oliver Schranz " * */ -#include +#include #include "module.h" -#include "instrumentation_pass.h" +//#include "template_basic_pass.h" +#include "template_injection_pass.h" #include "codelib.h" +#include "simple_method_filter.h" using std::make_shared; using std::unique_ptr; -shared_ptr ArtistModule::createPass(const MethodInfo &method_info) const { - return make_shared(method_info); +using art::ModuleId; + +TemplateModule::TemplateModule(const shared_ptr fs) : Module(fs) {} + +HArtist * TemplateModule::createPass(const MethodInfo &method_info) const { + // Due to the *clone bug* (https://github.com/Project-ARTist/ARTist/issues/10), we can only define one pass per + // module right now, but this will change as soon as this bug is resolved. + return new (method_info.GetGraph()->GetArena()) HTemplateInjectionArtist(method_info); +// return new (method_info.GetGraph()->GetArena()) HTemplateBasicArtist(method_info); } -shared_ptr ArtistModule::createCodeLib() const { - return make_shared(); +shared_ptr TemplateModule::createCodeLib() const { + return make_shared(); } -// Possible MethodFilter: skip android support lib ui methods since they bloat up the log -unique_ptr ArtistModule::getMethodFilter() const { - const vector ui = {"android.support."}; - return unique_ptr(new art::BlacklistFilter(ui)); + +// Here we can restrict for which methods our module should be executed. +unique_ptr TemplateModule::getMethodFilter() const { + // creating blacklists/whitelists for method names is straightforward: + // const vector ui = {"android.support."}; + // return unique_ptr(new MethodNameBlacklist(ui)); + + // but here we use a custom filter that only excepts non-static methods (and only a fragment of the others) + return unique_ptr(new SimpleMethodFilter()); +} +// the module factory +extern "C" shared_ptr create(shared_ptr fshelper) { + return make_shared(fshelper); } -// the class factories -extern "C" shared_ptr create() { - return make_shared(); +extern "C" ModuleId get_id() { + return "saarland.cispa.artist.module.template"; } diff --git a/src/module.h b/src/module.h index 6e952e5..5a4d0be 100644 --- a/src/module.h +++ b/src/module.h @@ -16,27 +16,31 @@ * limitations under the License. * * @author "Parthipan Ramesh " + * @author "Oliver Schranz " * */ #ifndef ART_MODULES__MODULE_H_ #define ART_MODULES__MODULE_H_ -#include +#include using art::Module; using art::HArtist; using art::MethodInfo; using art::CodeLib; using art::Filter; +using art::FilesystemHelper; -class ArtistModule : public Module { - shared_ptr createPass(const MethodInfo &method_info) const OVERRIDE; +class TemplateModule : public Module { + HArtist * createPass(const MethodInfo &method_info) const OVERRIDE; - shared_ptr createCodeLib() const OVERRIDE; + shared_ptr createCodeLib() const OVERRIDE; public: - unique_ptr getMethodFilter() const OVERRIDE; + explicit TemplateModule(const shared_ptr fs); + + unique_ptr getMethodFilter() const OVERRIDE; }; #endif // ART_MODULES__MODULE_H_ diff --git a/src/simple_method_filter.cc b/src/simple_method_filter.cc new file mode 100644 index 0000000..d170c58 --- /dev/null +++ b/src/simple_method_filter.cc @@ -0,0 +1,45 @@ +/** + * The ARTist Project (https://artist.cispa.saarland) + * + * Copyright (C) 2018 CISPA (https://cispa.saarland), Saarland University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @author "Oliver Schranz " + * + */ + +#include "simple_method_filter.h" + +int SimpleMethodFilter::MOD = 1000000; + +/** + * Simple filter implementation that rejects all static methods and for all others only accepts after seeing `MOD` + * methods. The reason is that in our (template) injection we write a lot to logcat and hence should avoid to inject + * calls to this method too often. + * + * @param info information & data about the currently compiled method + * @return + */ +bool SimpleMethodFilter::accept(const art::MethodInfo &info) { + if (info.IsStatic()) { + return false; + } + + mtx.lock(); + bool res = count == 0; + count = (count + 1) % SimpleMethodFilter::MOD; + mtx.unlock(); + return res; +} + diff --git a/src/simple_method_filter.h b/src/simple_method_filter.h new file mode 100644 index 0000000..572be6d --- /dev/null +++ b/src/simple_method_filter.h @@ -0,0 +1,47 @@ +/** + * The ARTist Project (https://artist.cispa.saarland) + * + * Copyright (C) 2018 CISPA (https://cispa.saarland), Saarland University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @author "Oliver Schranz " + * + */ + + +#ifndef ART_MODULES__STATICMETHODFILTER_H +#define ART_MODULES__STATICMETHODFILTER_H + +#include + +using std::mutex; + +using art::Filter; + +class SimpleMethodFilter : public Filter { +public: + SimpleMethodFilter() : count(0) {}; + + bool accept(const art::MethodInfo &info) override; +private: + // after how many non-static methods we will accept one (restrict number of instrumented methods) + static int MOD; + + // mutex for atomic `check and write` operation on `count` + mutex mtx; + // how many methods did we check already + int count; +}; + +#endif //ART_MODULES__STATICMETHODFILTER_H diff --git a/src/template_basic_pass.cc b/src/template_basic_pass.cc new file mode 100644 index 0000000..7c2f90b --- /dev/null +++ b/src/template_basic_pass.cc @@ -0,0 +1,104 @@ +/** + * The ARTist Project (https://artist.cispa.saarland) + * + * Copyright (C) 2018 CISPA (https://cispa.saarland), Saarland University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @author "Parthipan Ramesh " + * @author "Oliver Schranz " + * + */ + +#include + +#include +#include + +#include "template_basic_pass.h" +#include "codelib.h" + +using std::string; +using std::vector; +using std::find_if; + +using art::Instruction; +using art::INFO; +using art::HIntConstant; +using art::HParameterValue; +using art::ErrorHandler; + + +void HTemplateBasicArtist::RunPass() { + // This method is invoked for each single method that is compiled by ARTist (and passes your defined filters) + + // You can access information about the current method and its graph (linked basic blocks of IR instructions) + auto signature = _method_info.GetMethodName(true); + auto blocks = graph_->GetBlocks(); + + // You can use the following for logging + VLOG(artist) << "Sample log for method " << signature; + + // Now let's inject a call to the codelib method `injectedMethod2`. We will use a utils method to generate an + // `HInvokeVirtual` IR instruction and embed it into the graph + + // first, find the instruction before which we want to inject our method call. For the sake of simplicity, let's + // inject as the last instruction of the first block where (almost) only param and constants are located. + art::HInstruction* cursor = graph_->GetEntryBlock()->GetLastInstruction(); + + // we will add a call to this method + auto codelib_method = TemplateCodeLib::BASIC_ARTIST_TARGET; + + // we will collect all parameters as HInstructions. Instructions also represent their return value, hence if you + // want to use the return value of a method invocation, use the invocation instruction as a parameter. + vector params; + + // Since codelib methods are virtual methods, the first param always needs to be the codelib. + // `GetCodeLibInstruction()` lazily injects a codelib instance into the first block of a method or somewhere else + // if you provide a cursor. + auto codelib_instruction = GetCodeLibInstruction(); + params.push_back(codelib_instruction); + + // Primitive constants can be added to the graph. Strings can't since they are defined in the dex files. + HIntConstant* param1 = graph_->GetIntConstant(1337); + params.push_back(param1); + + // But let's assume the second argument (an object) should be the current method's this pointer. Let's search for it. + auto param_instructions =_method_info.GetParams(); + auto it = find_if (param_instructions.begin(), param_instructions.end(), + [this](HParameterValue* p){return this->_method_info.IsThisParameter(p);}); + auto thiz = *it; + // if our filter for non-static functions (see `module.cc`) is correct, this should not happen + if (!thiz) { + // We can trigger a hard crash at any time (e.g., for debugging reasons). The compilation will stop and a dump + // including your message will be displayed + ErrorHandler::abortCompilation("Possible implementation error! Did not find a this pointer in method " + signature); + } + params.push_back(thiz); + + // The codelib environment can be obtained from the Artist class + auto env = getCodeLibEnvironment(); + + // The return type is picked from an enum. It is the return type of the codelib method defined in `codelib_method` + auto return_type = art::Primitive::Type::kPrimVoid; + + // Also declare whether you want to inject the method call *before* `cursor`. + auto before = false; + + // Finally, create the method call instruction and add it to the method graph + art::ArtUtils::InjectMethodCall(cursor, codelib_method, params, env, return_type, before); + + // If you dump the method graph now, you can see all instructions added by us (bloats the log, but good for debugging) + // art::ArtistLog::LogMethod(_method_info); + +} diff --git a/src/instrumentation_pass.h b/src/template_basic_pass.h similarity index 65% rename from src/instrumentation_pass.h rename to src/template_basic_pass.h index 2147444..017cd04 100644 --- a/src/instrumentation_pass.h +++ b/src/template_basic_pass.h @@ -15,29 +15,33 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * @author "Parthipan Ramesh " + * @author "Oliver Schranz " * */ #ifndef ART_MODULES_ARTIST_H_ #define ART_MODULES_ARTIST_H_ -#include +#include -using art::HUniversalArtist; + +using art::HArtist; using art::MethodInfo; using art::OptimizingCompilerStats; -using art::Injection; -class HModule : public HUniversalArtist { +/** + * Example for an instrumentation pass that makes use of the injection boilerplate code. + * The idea is to declare to *which* of your codelib methods method calls should be injected *where* in the code. + */ +class HTemplateBasicArtist : public HArtist { public: - explicit HModule( + explicit HTemplateBasicArtist( const MethodInfo &method_info, #ifdef BUILD_MARSHMALLOW bool is_in_ssa_form = true, #endif - const char *pass_name = "ArtistModule", OptimizingCompilerStats *stats = nullptr) - : HUniversalArtist(method_info + const char *pass_name = "TemplateBasicArtist", OptimizingCompilerStats *stats = nullptr) + : HArtist(method_info #ifdef BUILD_MARSHMALLOW , is_in_ssa_form #endif @@ -45,7 +49,7 @@ class HModule : public HUniversalArtist { // Nothing } - vector ProvideInjections() const OVERRIDE; + void RunPass() OVERRIDE; }; #endif // ART_MODULES_ARTIST_H_ diff --git a/src/template_injection_pass.cc b/src/template_injection_pass.cc new file mode 100644 index 0000000..b822561 --- /dev/null +++ b/src/template_injection_pass.cc @@ -0,0 +1,76 @@ +/** + * The ARTist Project (https://artist.cispa.saarland) + * + * Copyright (C) 2018 CISPA (https://cispa.saarland), Saarland University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @author "Parthipan Ramesh " + * @author "Oliver Schranz " + * + */ + +#include + +#include +#include +#include +#include + +#include "template_injection_pass.h" +#include "codelib.h" + +using std::string; +using std::vector; +using std::shared_ptr; +using std::make_shared; +using std::endl; +using std::sort; + +using art::Parameter; +using art::Integer; +using art::Target; +using art::InjectionTarget; +using art::Target; + +vector> HTemplateInjectionArtist::ProvideInjections() const { + // You can provide parameters when injecting calls to your methods + vector> params; + // However, only constants are supported currently. + auto param1 = make_shared(42); + params.push_back(param1); + + // Now we define the "Target" which is the definition of *where* to inject. You can define multiple targets here. + vector> targets; + // here we define where exactly in the method graph we want to inject. For example, at the end of a method (before + // each return) or after particular method calls. + auto injection_target = InjectionTarget::METHOD_END; + // The restriction can be a (part of) a (pretty printed) signature or simply `Target::GENERIC_TARGET` if you do not + // want to restrict further. Depending on the injection target defined above, this related to the method currently + // compiled by ARTist or, if your injection target focuses on method *calls*, then this restriction applies to the + // signature of the invoked method. + string target_restriction = Target::GENERIC_TARGET; + auto target = make_shared(target_restriction, injection_target); + targets.push_back(target); + + // The injection combines the signature of the method we want to inject a call to, its parameters, and the targets + // we defined earlier. + auto injection = make_shared(TemplateCodeLib::INJECTION_ARTIST_TARGET, params, targets); + + // In theory, you can have as many injections as you want, but due to the so called *clone bug* + // (https://github.com/Project-ARTist/ARTist/issues/10), this is currently not possible. + vector> results; + results.push_back(injection); + + return results; +} diff --git a/src/template_injection_pass.h b/src/template_injection_pass.h new file mode 100644 index 0000000..b001ed0 --- /dev/null +++ b/src/template_injection_pass.h @@ -0,0 +1,56 @@ +/** + * The ARTist Project (https://artist.cispa.saarland) + * + * Copyright (C) 2018 CISPA (https://cispa.saarland), Saarland University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @author "Parthipan Ramesh " + * @author "Oliver Schranz " + * + */ + +#ifndef ART_MODULES_ARTIST_H_ +#define ART_MODULES_ARTIST_H_ + +#include + +using art::HInjectionArtist; +using art::MethodInfo; +using art::OptimizingCompilerStats; +using art::Injection; + +/** + * Example for an instrumentation pass that makes use of the injection boilerplate code. + * The idea is to declare to *which* of your codelib methods method calls should be injected *where* in the code. + */ +class HTemplateInjectionArtist : public HInjectionArtist { +public: + explicit HTemplateInjectionArtist( + const MethodInfo &method_info, +#ifdef BUILD_MARSHMALLOW + bool is_in_ssa_form = true, +#endif + const char *pass_name = "TemplateInjectionArtist", OptimizingCompilerStats *stats = nullptr) + : HInjectionArtist(method_info +#ifdef BUILD_MARSHMALLOW + , is_in_ssa_form +#endif + , pass_name, stats) { + // Nothing + } + + vector> ProvideInjections() const OVERRIDE; +}; + +#endif // ART_MODULES_ARTIST_H_