diff --git a/bundle.json b/bundle.json index a67b055123..5a4b06772e 100644 --- a/bundle.json +++ b/bundle.json @@ -37,7 +37,13 @@ "libuv", "zlib", "bounds_checking_function", - "icu" + "icu", + "access_token", + "eventhandler", + "hisysevent", + "ipc", + "safwk", + "samgr" ], "third_party": [ ] @@ -48,7 +54,8 @@ "//arkcompiler/ets_runtime:app_aot_disable_list", "//arkcompiler/ets_runtime:app_jit_enable_list", "//arkcompiler/ets_runtime:ark_js_packages", - "//arkcompiler/ets_runtime/etc:arkcompiler.para.dac" + "//arkcompiler/ets_runtime/etc:arkcompiler.para.dac", + "//arkcompiler/ets_runtime/compiler_service:compiler_service" ], "inner_kits": [ { @@ -72,10 +79,20 @@ ], "header_base": "//arkcompiler/ets_runtime/ecmascript/napi/include" } + }, + { + "name": "//arkcompiler/ets_runtime/compiler_service:libcompiler_service", + "header": { + "header_files": [ + "aot_compiler_client.h" + ], + "header_base": "//arkcompiler/ets_runtime/compiler_service/include" + } } ], "test": [ - "//arkcompiler/ets_runtime:ark_js_unittest" + "//arkcompiler/ets_runtime:ark_js_unittest", + "//arkcompiler/ets_runtime/compiler_service/test:compiler_service_unittest" ] } } diff --git a/compiler_service/BUILD.gn b/compiler_service/BUILD.gn new file mode 100644 index 0000000000..c355ab560b --- /dev/null +++ b/compiler_service/BUILD.gn @@ -0,0 +1,76 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# 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. + +import("//build/ohos.gni") +import("//build/ohos/sa_profile/sa_profile.gni") + +config("aot_compiler_service_config") { + visibility = [ ":*" ] + include_dirs = [ + "include", + "interface", + ] +} + +ohos_shared_library("libcompiler_service") { + public_configs = [ ":aot_compiler_service_config" ] + shlib_type = "sa" + version_script = "libaot_compiler_service.map" + sources = [ + "interface/aot_compiler_interface_proxy.cpp", + "interface/aot_compiler_interface_stub.cpp", + "src/aot_compiler_client.cpp", + "src/aot_compiler_error_utils.cpp", + "src/aot_compiler_impl.cpp", + "src/aot_compiler_load_callback.cpp", + "src/aot_compiler_service.cpp", + ] + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "c_utils:utils", + "code_signature:liblocal_code_sign_sdk", + "eventhandler:libeventhandler", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + install_enable = true + install_images = [ "system" ] + + part_name = "ets_runtime" + subsystem_name = "arkcompiler" +} + +ohos_prebuilt_etc("compiler_service_cfg") { + source = "compiler_service.cfg" + relative_install_dir = "init" + part_name = "ets_runtime" + subsystem_name = "arkcompiler" +} + +ohos_sa_profile("compiler_sa_profile") { + sources = [ "sa_profile/5300.json" ] + part_name = "ets_runtime" +} + +group("compiler_service") { + deps = [ + ":compiler_sa_profile", + ":compiler_service_cfg", + ":libcompiler_service", + ] +} diff --git a/compiler_service/compiler_service.cfg b/compiler_service/compiler_service.cfg new file mode 100644 index 0000000000..79408c3390 --- /dev/null +++ b/compiler_service/compiler_service.cfg @@ -0,0 +1,12 @@ +{ + "services" : [{ + "name" : "compiler_service", + "path" : ["/system/bin/sa_main", "/system/profile/compiler_service.json"], + "ondemand" : true, + "uid" : "compiler_service", + "gid" : ["compiler_service"], + "caps" : ["SETUID", "SETGID"], + "secon" : "u:object_r:compiler_service:s0" + } + ] +} \ No newline at end of file diff --git a/compiler_service/include/aot_compiler_client.h b/compiler_service/include/aot_compiler_client.h new file mode 100644 index 0000000000..b171052464 --- /dev/null +++ b/compiler_service/include/aot_compiler_client.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef OHOS_ARKCOMPILER_AOTCOMPILER_CLIENT_H +#define OHOS_ARKCOMPILER_AOTCOMPILER_CLIENT_H + +#include +#include +#include +#include +#include + +#include "iaot_compiler_interface.h" +#include "singleton.h" + +namespace OHOS::ArkCompiler { +class AotCompilerClient { +public: + AotCompilerClient() = default; + virtual ~AotCompilerClient() = default; + static AotCompilerClient &GetInstance(); + int32_t AotCompiler(const std::unordered_map &argsMap, + std::vector &sigData); + int32_t StopAotCompiler(); + void OnLoadSystemAbilitySuccess(const sptr &remoteObject); + void OnLoadSystemAbilityFail(); + +private: + sptr GetAotCompilerProxy(); + bool LoadAotCompilerService(); + void SetAotCompiler(const sptr &remoteObject); + sptr GetAotCompiler(); + +private: + std::condition_variable loadSaCondition_; + std::mutex loadSaMutex_; + bool loadSaFinished_; + std::mutex mutex_; + sptr aotCompilerProxy_ = nullptr; + DISALLOW_COPY_AND_MOVE(AotCompilerClient); +}; +} // namespace OHOS::ArkCompiler +#endif // OHOS_ARKCOMPILER_AOTCOMPILER_CLIENT_H \ No newline at end of file diff --git a/compiler_service/include/aot_compiler_constants.h b/compiler_service/include/aot_compiler_constants.h new file mode 100644 index 0000000000..c062809ec6 --- /dev/null +++ b/compiler_service/include/aot_compiler_constants.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef OHOS_ARKCOMPILER_AOTCOMPILER_CONSTANTS_H +#define OHOS_ARKCOMPILER_AOTCOMPILER_CONSTANTS_H + +#include +#include + +namespace OHOS::ArkCompiler { +namespace Cmds { +constexpr const char* ARK_AOT_COMPILER = "/system/bin/ark_aot_compiler"; +} // namespace Cmds + +namespace ArgsIdx { +const std::string BUNDLE_UID = "BundleUid"; +const std::string BUNDLE_GID = "BundleGid"; +const std::string AN_FILE_NAME = "anFileName"; +const std::string APP_SIGNATURE = "appIdentifier"; +const std::string ABC_PATH = "ABC-Path"; +} // namespace ArgsIdx + +namespace Symbols { +constexpr const char* PREFIX = "--"; +constexpr const char* EQ = "="; +} // namespace Symbols + +std::unordered_set AotArgsSet { + "aot-file", + "ark-properties", + "ark-bundleName", + "asm-interpreter", + "asm-opcode-disable-range", + "builtins-lazy", + "compiler-log", + "compiler-log-methods", + "compiler-log-snapshot", + "compiler-log-time", + "compiler-type-threshold", + "enable-ark-tools", + "compiler-trace-bc", + "compiler-trace-deopt", + "compiler-trace-inline", + "compiler-trace-value-numbering", + "compiler-trace-instruction-combine", + "compiler-max-inline-bytecodes", + "compiler-deopt-threshold", + "compiler-device-state", + "compiler-stress-deopt", + "compiler-opt-code-profiler", + "compiler-opt-bc-range", + "compiler-opt-bc-range-help", + "enable-force-gc", + "enable-ic", + "enable-runtime-stat", + "compiler-opt-constant-folding", + "compiler-opt-array-bounds-check-elimination", + "compiler-opt-type-lowering", + "compiler-opt-early-elimination", + "compiler-opt-later-elimination", + "compiler-opt-instr-combine", + "compiler-opt-string", + "compiler-opt-value-numbering", + "compiler-opt-new-value-numbering", + "compiler-opt-inlining", + "compiler-opt-pgotype", + "compiler-opt-track-field", + "entry-point", + "force-full-gc", + "force-shared-gc-frequency", + "gc-thread-num", + "heap-size-limit", + "icu-data-path", + "enable-worker", + "log-components", + "log-debug", + "log-error", + "log-fatal", + "log-info", + "log-level", + "log-warning", + "gc-long-paused-time", + "compiler-opt-max-method", + "compiler-module-methods", + "max-unmovable-space", + "merge-abc", + "enable-context", + "compiler-opt-level", + "reloc-mode", + "serializer-buffer-size-limit", + "startup-time", + "stub-file", + "compiler-target-triple", + "enable-print-execute-time", + "enable-pgo-profiler", + "enable-elements-kind", + "compiler-pgo-profiler-path", + "compiler-pgo-hotness-threshold", + "compiler-pgo-save-min-interval", + "compiler-verify-vtable", + "compiler-select-methods", + "compiler-skip-methods", + "target-compiler-mode", + "hap-path", + "hap-abc-offset", + "hap-abc-size", + "compiler-no-check", + "compiler-fast-compile", + "compiler-opt-loop-peeling", + "compiler-opt-array-onheap-check", + "compiler-pkg-info", + "compiler-external-pkg-info", + "compiler-enable-external-pkg", + "compiler-framework-abc-path", + "compiler-enable-lexenv-specialization", + "compiler-enable-native-inline", + "compiler-enable-lowering-builtin", + "compiler-enable-litecg", + "compiler-enable-jit", + "compiler-enable-osr", + "compiler-trace-jit", + "compiler-jit-hotness-threshold", + "compiler-osr-hotness-threshold", + "compiler-force-jit-compile-main", + "compiler-enable-jit-pgo", + "compiler-enable-aot-pgo", + "compiler-enable-profile-dump", + "compiler-typed-op-profiler", + "compiler-opt-branch-profiling", + "test-assert", + "compiler-methods-range", + "compiler-codegen-options", + "compiler-opt-escape-analysis", + "compiler-trace-escape-analysis", + "compiler-opt-induction-variable", + "compiler-trace-induction-variable", + "compiler-memory-analysis", + "compiler-check-pgo-version", + "compiler-enable-baselinejit", + "compiler-baselinejit-hotness-threshold", + "compiler-force-baselinejit-compile-main", +}; + +enum ErrOfCompile { + COMPILE_OK = (0), + ERR_COMPILE_FAIL = (-1), + ERR_COMPILE_HELP = (1), + COMPILE_NO_AP = (2), +}; +} // namespace OHOS::ArkCompiler +#endif // OHOS_ARKCOMPILER_AOTCOMPILER_CONSTANTS_H \ No newline at end of file diff --git a/compiler_service/include/aot_compiler_error_utils.h b/compiler_service/include/aot_compiler_error_utils.h new file mode 100644 index 0000000000..c0731ca5a4 --- /dev/null +++ b/compiler_service/include/aot_compiler_error_utils.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef OHOS_ARKCOMPILER_AOTCOMPILER_ERROR_UTILS_H +#define OHOS_ARKCOMPILER_AOTCOMPILER_ERROR_UTILS_H + +#include +#include + +namespace OHOS::ArkCompiler { +enum { + ERR_OK = 0, + ERR_AOT_COMPILER_PARAM_FAILED, + ERR_AOT_COMPILER_CONNECT_FAILED, + ERR_AOT_COMPILER_CALL_FAILED, + ERR_AOT_COMPILER_SIGNATURE_FAILED, + ERR_OK_NO_AOT_FILE, + ERR_AOT_COMPILER_STOP_FAILED, + INVALID_ERR_CODE = 9999, +}; + +class AotCompilerErrorUtil { +public: + static std::string GetErrorMessage(int32_t errCode); +}; +} // namespace OHOS::ArkCompiler +#endif // OHOS_ARKCOMPILER_AOTCOMPILER_ERROR_UTILS_H \ No newline at end of file diff --git a/compiler_service/include/aot_compiler_impl.h b/compiler_service/include/aot_compiler_impl.h new file mode 100644 index 0000000000..379e963f5e --- /dev/null +++ b/compiler_service/include/aot_compiler_impl.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef OHOS_ARKCOMPILER_AOTCOMPILER_IMPL_H +#define OHOS_ARKCOMPILER_AOTCOMPILER_IMPL_H + +#include +#include +#include +#include + +namespace OHOS::ArkCompiler { +class AotCompilerImpl { +public: + static AotCompilerImpl &GetInstance(); + /** + * @brief ecmascript aot_compiler + * @param argsMap input command strings + * @param sigData contain signature string data for EnforceCodeSignForFile() + * @return err code + */ + int32_t EcmascriptAotCompiler(const std::unordered_map &argsMap, + std::vector &sigData); + int32_t StopAotCompiler(); + +private: + void PrepareArgs(const std::unordered_map &argsMap); + void DropCapabilities(const int32_t &bundleUid, const int32_t &bundleGid) const; + void ExecuteInChildProcess(const std::vector &aotVector) const; + void ExecuteInParentProcess(pid_t childPid, int32_t &ret); + int32_t AOTLocalCodeSign(const std::string &fileName, const std::string &appSignature, + std::vector &sigData); + void InitState(const pid_t childPid); + void ResetState(); + AotCompilerImpl() = default; + ~AotCompilerImpl() = default; + + AotCompilerImpl(const AotCompilerImpl&) = delete; + AotCompilerImpl(AotCompilerImpl&&) = delete; + AotCompilerImpl& operator=(const AotCompilerImpl&) = delete; + AotCompilerImpl& operator=(AotCompilerImpl&&) = delete; +private: + mutable std::mutex mutex_; + mutable std::mutex stateMutex_; + struct HapArgs { + std::vector argVector; + std::string fileName; + std::string signature; + int32_t bundleUid; + int32_t bundleGid; + } hapArgs; + struct AOTState { + bool running = false; + pid_t childPid = -1; + } state_; +}; +} // namespace OHOS::ArkCompiler +#endif // OHOS_ARKCOMPILER_AOTCOMPILER_IMPL_H \ No newline at end of file diff --git a/compiler_service/include/aot_compiler_load_callback.h b/compiler_service/include/aot_compiler_load_callback.h new file mode 100644 index 0000000000..aaf66b11bb --- /dev/null +++ b/compiler_service/include/aot_compiler_load_callback.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef OHOS_ARKCOMPILER_AOTCOMPILER_CALLBACK_H +#define OHOS_ARKCOMPILER_AOTCOMPILER_CALLBACK_H + +#include "iremote_object.h" +#include "system_ability_load_callback_stub.h" + +namespace OHOS::ArkCompiler { +class AotCompilerLoadCallback : public SystemAbilityLoadCallbackStub { +public: + AotCompilerLoadCallback() = default; + virtual ~AotCompilerLoadCallback() = default; + + void OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr &remoteObject) override; + void OnLoadSystemAbilityFail(int32_t systemAbilityId) override; +}; +} // namespace OHOS::ArkCompiler +#endif // OHOS_ARKCOMPILER_AOTCOMPILER_CALLBACK_H \ No newline at end of file diff --git a/compiler_service/include/aot_compiler_service.h b/compiler_service/include/aot_compiler_service.h new file mode 100644 index 0000000000..2776853633 --- /dev/null +++ b/compiler_service/include/aot_compiler_service.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef OHOS_ARKCOMPILER_AOTCOMPILER_SERVICE_H +#define OHOS_ARKCOMPILER_AOTCOMPILER_SERVICE_H + +#include +#include + +#include "aot_compiler_interface_stub.h" +#include "event_handler.h" +#include "event_runner.h" +#include "refbase.h" +#include "singleton.h" +#include "system_ability.h" + +namespace OHOS::ArkCompiler { +enum class ServiceRunningState { + STATE_NOT_START, + STATE_RUNNING +}; +class AotCompilerService : public SystemAbility, public AotCompilerInterfaceStub { + DECLARE_SYSTEM_ABILITY(AotCompilerService); + DECLARE_DELAYED_SINGLETON(AotCompilerService); +public: + AotCompilerService(int32_t systemAbilityId, bool runOnCreate); + int32_t AotCompiler(const std::unordered_map &argsMap, + std::vector &sigData) override; + int32_t StopAotCompiler() override; + void DelayUnloadTask(); +protected: + void OnStart() override; + void OnStop() override; +private: + bool Init(); + std::shared_ptr unLoadHandler_; + ServiceRunningState state_; +}; +} // namespace OHOS::ArkCompiler +#endif // OHOS_ARKCOMPILER_AOTCOMPILER_SERVICE_H \ No newline at end of file diff --git a/compiler_service/interface/aot_compiler_interface_proxy.cpp b/compiler_service/interface/aot_compiler_interface_proxy.cpp new file mode 100644 index 0000000000..7fdaf282e5 --- /dev/null +++ b/compiler_service/interface/aot_compiler_interface_proxy.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#include "aot_compiler_interface_proxy.h" +#include "hilog/log.h" +#include "hitrace_meter.h" + +using OHOS::HiviewDFX::HiLog; + +namespace OHOS { +namespace ArkCompiler { +ErrCode AotCompilerInterfaceProxy::AotCompiler( + const std::unordered_map& argsMap, + std::vector& sigData) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + + if (!data.WriteInterfaceToken(GetDescriptor())) { + HiLog::Error(LABEL, "Write interface token failed!"); + return ERR_INVALID_VALUE; + } + + if (argsMap.size() > mapMaxSize) { + HiLog::Error(LABEL, "The map size exceeds the security limit!"); + return ERR_INVALID_DATA; + } + + data.WriteInt32(argsMap.size()); + for (auto it = argsMap.begin(); it != argsMap.end(); ++it) { + if (!data.WriteString16(Str8ToStr16((it->first)))) { + HiLog::Error(LABEL, "Write [(it->first)] failed!"); + return ERR_INVALID_DATA; + } + if (!data.WriteString16(Str8ToStr16((it->second)))) { + HiLog::Error(LABEL, "Write [(it->second)] failed!"); + return ERR_INVALID_DATA; + } + } + + sptr remote = Remote(); + if (remote == nullptr) { + HiLog::Error(LABEL, "Remote is nullptr!"); + return ERR_INVALID_DATA; + } + int32_t result = remote->SendRequest(COMMAND_AOT_COMPILER, data, reply, option); + if (FAILED(result)) { + HiLog::Error(LABEL, "Send request failed!"); + return result; + } + + ErrCode errCode = reply.ReadInt32(); + if (FAILED(errCode)) { + HiLog::Error(LABEL, "Read Int32 failed!"); + return errCode; + } + + int32_t sigDataSize = reply.ReadInt32(); + if (sigDataSize > vectorMaxSize) { + HiLog::Error(LABEL, "The vector/array size exceeds the security limit!"); + return ERR_INVALID_DATA; + } + for (int32_t i = 0; i < sigDataSize; ++i) { + int16_t value = reply.ReadInt16(); + sigData.push_back(value); + } + return ERR_OK; +} + +ErrCode AotCompilerInterfaceProxy::StopAotCompiler() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_SYNC); + + if (!data.WriteInterfaceToken(GetDescriptor())) { + HiLog::Error(LABEL, "Write interface token failed!"); + return ERR_INVALID_VALUE; + } + + sptr remote = Remote(); + if (remote == nullptr) { + HiLog::Error(LABEL, "Remote is nullptr!"); + return ERR_INVALID_DATA; + } + int32_t result = remote->SendRequest(COMMAND_STOP_AOT_COMPILER, data, reply, option); + if (FAILED(result)) { + HiLog::Error(LABEL, "Send request failed!"); + return result; + } + + ErrCode errCode = reply.ReadInt32(); + if (FAILED(errCode)) { + HiLog::Error(LABEL, "Read Int32 failed!"); + return errCode; + } + + return ERR_OK; +} +} // namespace ArkCompiler +} // namespace OHOS diff --git a/compiler_service/interface/aot_compiler_interface_proxy.h b/compiler_service/interface/aot_compiler_interface_proxy.h new file mode 100644 index 0000000000..0bccc9d035 --- /dev/null +++ b/compiler_service/interface/aot_compiler_interface_proxy.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef OHOS_ARKCOMPILER_AOTCOMPILER_INTERFACE_PROXY_H +#define OHOS_ARKCOMPILER_AOTCOMPILER_INTERFACE_PROXY_H + +#include +#include "iaot_compiler_interface.h" + +namespace OHOS { +namespace ArkCompiler { +class AotCompilerInterfaceProxy : public IRemoteProxy { +public: + explicit AotCompilerInterfaceProxy( + const sptr& remote) + : IRemoteProxy(remote) + {} + + virtual ~AotCompilerInterfaceProxy() + {} + + ErrCode AotCompiler( + const std::unordered_map& argsMap, + std::vector& sigData) override; + + ErrCode StopAotCompiler() override; + +private: + static constexpr int32_t COMMAND_AOT_COMPILER = MIN_TRANSACTION_ID + 0; + static constexpr int32_t COMMAND_STOP_AOT_COMPILER = MIN_TRANSACTION_ID + 1; + + static inline BrokerDelegator delegator_; +}; +} // namespace ArkCompiler +} // namespace OHOS +#endif // OHOS_ARKCOMPILER_AOTCOMPILER_INTERFACE_PROXY_H + diff --git a/compiler_service/interface/aot_compiler_interface_stub.cpp b/compiler_service/interface/aot_compiler_interface_stub.cpp new file mode 100644 index 0000000000..1fef836457 --- /dev/null +++ b/compiler_service/interface/aot_compiler_interface_stub.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#include "aot_compiler_interface_stub.h" +#include "hilog/log.h" +#include "hitrace_meter.h" + +using OHOS::HiviewDFX::HiLog; + +namespace OHOS { +namespace ArkCompiler { +int32_t AotCompilerInterfaceStub::OnRemoteRequest( + uint32_t code, + MessageParcel& data, + MessageParcel& reply, + MessageOption& option) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + std::u16string localDescriptor = GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (localDescriptor != remoteDescriptor) { + return ERR_TRANSACTION_FAILED; + } + switch (code) { + case COMMAND_AOT_COMPILER: { + return CommandAOTCompiler(data, reply); + } + case COMMAND_STOP_AOT_COMPILER: { + return CommandStopAOTCompiler(reply); + } + default: + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + return ERR_TRANSACTION_FAILED; +} + +int32_t AotCompilerInterfaceStub::CommandAOTCompiler(MessageParcel &data, + MessageParcel &reply) +{ + std::unordered_map argsMap; + int32_t argsMapSize = data.ReadInt32(); + for (int32_t i = 0; i < argsMapSize; ++i) { + std::string key = Str16ToStr8(data.ReadString16()); + std::string value = Str16ToStr8(data.ReadString16()); + argsMap[key] = value; + } + std::vector sigData; + ErrCode errCode = AotCompiler(argsMap, sigData); + if (!reply.WriteInt32(errCode)) { + HiLog::Error(LABEL, "Write Int32 failed!"); + return ERR_INVALID_VALUE; + } + if (SUCCEEDED(errCode)) { + if (sigData.size() > vectorMaxSize) { + HiLog::Error(LABEL, "The vector size exceeds the security limit!"); + return ERR_INVALID_DATA; + } + reply.WriteInt32(sigData.size()); + for (auto it = sigData.begin(); it != sigData.end(); ++it) { + if (!reply.WriteInt32(*it)) { + HiLog::Error(LABEL, "Write sigData array failed!"); + return ERR_INVALID_DATA; + } + } + } + return ERR_NONE; +} + +int32_t AotCompilerInterfaceStub::CommandStopAOTCompiler(MessageParcel& reply) +{ + ErrCode errCode = StopAotCompiler(); + if (!reply.WriteInt32(errCode)) { + HiLog::Error(LABEL, "Write Int32 failed!"); + return ERR_INVALID_VALUE; + } + return ERR_NONE; +} + +} // namespace ArkCompiler +} // namespace OHOS diff --git a/compiler_service/interface/aot_compiler_interface_stub.h b/compiler_service/interface/aot_compiler_interface_stub.h new file mode 100644 index 0000000000..4dce29765f --- /dev/null +++ b/compiler_service/interface/aot_compiler_interface_stub.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef OHOS_ARKCOMPILER_AOTCOMPILER_INTERFACE_STUB_H +#define OHOS_ARKCOMPILER_AOTCOMPILER_INTERFACE_STUB_H + +#include +#include "iaot_compiler_interface.h" + +namespace OHOS { +namespace ArkCompiler { +class AotCompilerInterfaceStub : public IRemoteStub { +public: + int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) override; +private: + int32_t CommandAOTCompiler(MessageParcel &data, MessageParcel &reply); + int32_t CommandStopAOTCompiler(MessageParcel &reply); + static constexpr int32_t COMMAND_AOT_COMPILER = MIN_TRANSACTION_ID + 0; + static constexpr int32_t COMMAND_STOP_AOT_COMPILER = MIN_TRANSACTION_ID + 1; +}; +} // namespace ArkCompiler +} // namespace OHOS +#endif // OHOS_ARKCOMPILER_AOTCOMPILER_INTERFACE_STUB_H + diff --git a/compiler_service/interface/iaot_compiler_interface.h b/compiler_service/interface/iaot_compiler_interface.h new file mode 100644 index 0000000000..05bdbd99b2 --- /dev/null +++ b/compiler_service/interface/iaot_compiler_interface.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef OHOS_ARKCOMPILER_IAOTCOMPILER_INTERFACE_H +#define OHOS_ARKCOMPILER_IAOTCOMPILER_INTERFACE_H + +#include +#include +#include +#include +#include +#include "hilog/log.h" + +namespace OHOS { +namespace ArkCompiler { +class IAotCompilerInterface : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.ArkCompiler.IAotCompilerInterface"); + + virtual ErrCode AotCompiler( + const std::unordered_map& argsMap, + std::vector& sigData) = 0; + + virtual ErrCode StopAotCompiler() = 0; +protected: + static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { + LOG_CORE, 0xD003900, "AotCompilerInterfaceService" + }; + const unsigned long vectorMaxSize = 102400; + const unsigned long mapMaxSize = 102400; +}; +} // namespace ArkCompiler +} // namespace OHOS +#endif // OHOS_ARKCOMPILER_IAOTCOMPILER_INTERFACE_H + diff --git a/compiler_service/libaot_compiler_service.map b/compiler_service/libaot_compiler_service.map new file mode 100644 index 0000000000..227a8412f6 --- /dev/null +++ b/compiler_service/libaot_compiler_service.map @@ -0,0 +1,10 @@ +{ + global: + extern "C++" { + OHOS::ArkCompiler::AotCompilerClient::GetInstance*; + OHOS::ArkCompiler::AotCompilerClient::AotCompiler*; + OHOS::ArkCompiler::AotCompilerClient::StopAotCompiler*; + }; + local: + *; +}; \ No newline at end of file diff --git a/compiler_service/sa_profile/5300.json b/compiler_service/sa_profile/5300.json new file mode 100644 index 0000000000..285e0a95c9 --- /dev/null +++ b/compiler_service/sa_profile/5300.json @@ -0,0 +1,12 @@ +{ + "process": "compiler_service", + "systemability": [ + { + "name": 5300, + "libpath": "libcompiler_service.z.so", + "run-on-create": false, + "distributed": false, + "dump-level": 1 + } + ] +} \ No newline at end of file diff --git a/compiler_service/src/aot_compiler_client.cpp b/compiler_service/src/aot_compiler_client.cpp new file mode 100644 index 0000000000..776f78ec21 --- /dev/null +++ b/compiler_service/src/aot_compiler_client.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#include "aot_compiler_client.h" +#include "aot_compiler_error_utils.h" +#include "aot_compiler_load_callback.h" +#include "hilog/log.h" +#include "hitrace_meter.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" + +namespace OHOS::ArkCompiler { +namespace { + const int LOAD_SA_TIMEOUT_MS = 6 * 1000; + constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0xD001800, "aot_compiler_service"}; +} // namespace + +AotCompilerClient &AotCompilerClient::GetInstance() +{ + static AotCompilerClient singleAotCompilerClient; + return singleAotCompilerClient; +} + +int32_t AotCompilerClient::AotCompiler(const std::unordered_map &argsMap, + std::vector &sigData) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + HiviewDFX::HiLog::Debug(LABEL, "aot compiler function called"); + auto aotCompilerProxy = GetAotCompilerProxy(); + if (aotCompilerProxy == nullptr) { + HiviewDFX::HiLog::Error(LABEL, "get aot compiler service failed"); + return ERR_AOT_COMPILER_CONNECT_FAILED; + } + return aotCompilerProxy->AotCompiler(argsMap, sigData); +} + +int32_t AotCompilerClient::StopAotCompiler() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + HiviewDFX::HiLog::Debug(LABEL, "aot compiler function called"); + auto aotCompilerProxy = GetAotCompilerProxy(); + if (aotCompilerProxy == nullptr) { + HiviewDFX::HiLog::Error(LABEL, "get aot compiler service failed"); + return ERR_AOT_COMPILER_CONNECT_FAILED; + } + return aotCompilerProxy->StopAotCompiler(); +} + +sptr AotCompilerClient::GetAotCompilerProxy() +{ + HiviewDFX::HiLog::Debug(LABEL, "get aot compiler proxy function called"); + auto aotCompilerProxy = GetAotCompiler(); + if (aotCompilerProxy != nullptr) { + HiviewDFX::HiLog::Debug(LABEL, "aot compiler service proxy has been started"); + return aotCompilerProxy; + } + if (!LoadAotCompilerService()) { + HiviewDFX::HiLog::Error(LABEL, "load aot compiler service failed"); + return nullptr; + } + aotCompilerProxy = GetAotCompiler(); + if (aotCompilerProxy == nullptr || aotCompilerProxy->AsObject() == nullptr) { + HiviewDFX::HiLog::Error(LABEL, "failed to get aot compiler service"); + return nullptr; + } + HiviewDFX::HiLog::Debug(LABEL, "get aot compiler proxy function finished"); + return aotCompilerProxy; +} + +bool AotCompilerClient::LoadAotCompilerService() +{ + { + std::unique_lock lock(loadSaMutex_); + loadSaFinished_ = false; + } + auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemAbilityMgr == nullptr) { + HiviewDFX::HiLog::Error(LABEL, "failed to get system ability manager"); + return false; + } + sptr loadCallback = new (std::nothrow) AotCompilerLoadCallback(); + if (loadCallback == nullptr) { + HiviewDFX::HiLog::Error(LABEL, "failed to create load callback."); + return false; + } + auto ret = systemAbilityMgr->LoadSystemAbility(AOT_COMPILER_SERVICE_ID, loadCallback); + if (ret != 0) { + HiviewDFX::HiLog::Error(LABEL, "load system ability %{public}d failed with %{public}d", + AOT_COMPILER_SERVICE_ID, ret); + return false; + } + { + std::unique_lock lock(loadSaMutex_); + auto waitStatus = loadSaCondition_.wait_for(lock, std::chrono::milliseconds(LOAD_SA_TIMEOUT_MS), + [this]() { + return loadSaFinished_; + }); + if (!waitStatus) { + HiviewDFX::HiLog::Error(LABEL, "wait for load SA timeout"); + return false; + } + } + return true; +} + +void AotCompilerClient::SetAotCompiler(const sptr &remoteObject) +{ + std::lock_guard lock(mutex_); + aotCompilerProxy_ = iface_cast(remoteObject); +} + +sptr AotCompilerClient::GetAotCompiler() +{ + std::lock_guard lock(mutex_); + return aotCompilerProxy_; +} + +void AotCompilerClient::OnLoadSystemAbilitySuccess(const sptr &remoteObject) +{ + SetAotCompiler(remoteObject); + std::unique_lock lock(loadSaMutex_); + loadSaFinished_ = true; + loadSaCondition_.notify_one(); +} + +void AotCompilerClient::OnLoadSystemAbilityFail() +{ + SetAotCompiler(nullptr); + std::unique_lock lock(loadSaMutex_); + loadSaFinished_ = true; + loadSaCondition_.notify_one(); +} +} // namespace OHOS::ArkCompiler \ No newline at end of file diff --git a/compiler_service/src/aot_compiler_error_utils.cpp b/compiler_service/src/aot_compiler_error_utils.cpp new file mode 100644 index 0000000000..36d85f0353 --- /dev/null +++ b/compiler_service/src/aot_compiler_error_utils.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#include "aot_compiler_error_utils.h" +#include + +namespace OHOS::ArkCompiler { +namespace { +const std::map ERR_MSG_MAP = { + { ERR_OK, "success" }, + { ERR_AOT_COMPILER_PARAM_FAILED, "aot compiler arguments error" }, + { ERR_AOT_COMPILER_CONNECT_FAILED, "connect failed" }, + { ERR_AOT_COMPILER_CALL_FAILED, "call failed" }, + { ERR_AOT_COMPILER_SIGNATURE_FAILED, "local code sign failed" }, + { ERR_OK_NO_AOT_FILE, "no aot file save" }, + { ERR_AOT_COMPILER_STOP_FAILED, "aot compiler stop error" } +}; +} // namespace + +std::string AotCompilerErrorUtil::GetErrorMessage(int32_t errCode) +{ + std::string errMsg; + auto iter = ERR_MSG_MAP.find(errCode); + if (iter != ERR_MSG_MAP.end()) { + errMsg = iter->second; + } else { + errMsg = "invalid errCode"; + } + return errMsg; +} +} // namespace OHOS::ArkCompiler \ No newline at end of file diff --git a/compiler_service/src/aot_compiler_impl.cpp b/compiler_service/src/aot_compiler_impl.cpp new file mode 100644 index 0000000000..d53a9735f0 --- /dev/null +++ b/compiler_service/src/aot_compiler_impl.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#include "aot_compiler_impl.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "aot_compiler_constants.h" +#include "aot_compiler_error_utils.h" +#include "aot_compiler_service.h" +#include "hilog/log.h" +#include "hitrace_meter.h" +#include "local_code_sign_kit.h" +#include "system_ability_definition.h" + +namespace OHOS::ArkCompiler { +namespace { +constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0xD001800, "aot_compiler_service"}; +} // namespace + +AotCompilerImpl& AotCompilerImpl::GetInstance() +{ + static AotCompilerImpl aotCompiler; + return aotCompiler; +} + +void AotCompilerImpl::PrepareArgs(const std::unordered_map &argsMap) +{ + for (const auto &arg : argsMap) { + HiviewDFX::HiLog::Debug(LABEL, "%{public}s: %{public}s", arg.first.c_str(), arg.second.c_str()); + } + hapArgs.bundleUid = static_cast(std::stoi(argsMap.at(ArgsIdx::BUNDLE_UID))); + hapArgs.bundleGid = static_cast(std::stoi(argsMap.at(ArgsIdx::BUNDLE_GID))); + hapArgs.fileName = argsMap.at(ArgsIdx::AN_FILE_NAME); + hapArgs.signature = argsMap.at(ArgsIdx::APP_SIGNATURE); + hapArgs.argVector.clear(); + hapArgs.argVector.emplace_back(Cmds::ARK_AOT_COMPILER); + for (auto &argPair : argsMap) { + if (AotArgsSet.find(argPair.first) != AotArgsSet.end()) { + hapArgs.argVector.emplace_back(Symbols::PREFIX + argPair.first + Symbols::EQ + argPair.second); + } + } + hapArgs.argVector.emplace_back(argsMap.at(ArgsIdx::ABC_PATH)); +} + +void AotCompilerImpl::DropCapabilities(const int32_t &bundleUid, const int32_t &bundleGid) const +{ + if (setuid(bundleUid)) { + HiviewDFX::HiLog::Error(LABEL, "dropCapabilities setuid failed : %{public}s", strerror(errno)); + exit(-1); + } + if (setgid(bundleGid)) { + HiviewDFX::HiLog::Error(LABEL, "dropCapabilities setgid failed : %{public}s", strerror(errno)); + exit(-1); + } + struct __user_cap_header_struct capHeader; + if (memset_s(&capHeader, sizeof(capHeader), 0, sizeof(capHeader)) != EOK) { + HiviewDFX::HiLog::Error(LABEL, "memset_s capHeader failed : %{public}s", strerror(errno)); + exit(-1); + } + capHeader.version = _LINUX_CAPABILITY_VERSION_3; + capHeader.pid = 0; + + struct __user_cap_data_struct capData[2]; + if (memset_s(&capData, sizeof(capData), 0, sizeof(capData)) != EOK) { + HiviewDFX::HiLog::Error(LABEL, "memset_s capData failed : %{public}s", strerror(errno)); + exit(-1); + } + if (capset(&capHeader, capData) != 0) { + HiviewDFX::HiLog::Error(LABEL, "capset failed : %{public}s", strerror(errno)); + exit(-1); + } +} + +void AotCompilerImpl::ExecuteInChildProcess(const std::vector &aotVector) const +{ + std::vector argv; + argv.reserve(aotVector.size() + 1); + for (auto &arg : aotVector) { + argv.emplace_back(arg.c_str()); + } + argv.emplace_back(nullptr); + HiviewDFX::HiLog::Debug(LABEL, "argv size : %{public}zu", argv.size()); + for (const auto &arg : argv) { + HiviewDFX::HiLog::Debug(LABEL, "%{public}s", arg); + } + execv(argv[0], const_cast(argv.data())); + HiviewDFX::HiLog::Error(LABEL, "execv failed : %{public}s", strerror(errno)); + exit(-1); +} + +void AotCompilerImpl::ExecuteInParentProcess(const pid_t childPid, int32_t &ret) +{ + { + std::lock_guard lock(stateMutex_); + InitState(childPid); + } + int status; + int waitRet = waitpid(childPid, &status, 0); + if (waitRet == -1) { + HiviewDFX::HiLog::Error(LABEL, "waitpid failed"); + ret = ERR_AOT_COMPILER_CALL_FAILED; + } else if (WIFEXITED(status)) { + int exit_status = WEXITSTATUS(status); + HiviewDFX::HiLog::Info(LABEL, "child process exited with status: %{public}d", exit_status); + switch (exit_status) { + case ErrOfCompile::COMPILE_OK: + ret = ERR_OK; break; + case ErrOfCompile::COMPILE_NO_AP: + ret = ERR_OK_NO_AOT_FILE; break; + default: + ret = ERR_AOT_COMPILER_CALL_FAILED; break; + } + } else if (WIFSIGNALED(status)) { + int signal_number = WTERMSIG(status); + HiviewDFX::HiLog::Warn(LABEL, "child process terminated by signal: %{public}d", signal_number); + ret = ERR_AOT_COMPILER_CALL_FAILED; + } else if (WIFSTOPPED(status)) { + int signal_number = WSTOPSIG(status); + HiviewDFX::HiLog::Warn(LABEL, "child process was stopped by signal: %{public}d", signal_number); + ret = ERR_AOT_COMPILER_CALL_FAILED; + } else if (WIFCONTINUED(status)) { + HiviewDFX::HiLog::Warn(LABEL, "child process was resumed"); + ret = ERR_AOT_COMPILER_CALL_FAILED; + } else { + HiviewDFX::HiLog::Warn(LABEL, "unknown"); + ret = ERR_AOT_COMPILER_CALL_FAILED; + } + { + std::lock_guard lock(stateMutex_); + ResetState(); + } +} + +int32_t AotCompilerImpl::EcmascriptAotCompiler(const std::unordered_map &argsMap, + std::vector &sigData) +{ + if (argsMap.empty()) { + HiviewDFX::HiLog::Error(LABEL, "aot compiler arguments error"); + return ERR_AOT_COMPILER_PARAM_FAILED; + } + PrepareArgs(argsMap); + int32_t ret = ERR_OK; + std::lock_guard lock(mutex_); + HiviewDFX::HiLog::Debug(LABEL, "begin to fork"); + pid_t pid = fork(); + if (pid == -1) { + HiviewDFX::HiLog::Error(LABEL, "fork process failed : %{public}s", strerror(errno)); + return ERR_AOT_COMPILER_CALL_FAILED; + } else if (pid == 0) { + DropCapabilities(hapArgs.bundleUid, hapArgs.bundleGid); + ExecuteInChildProcess(hapArgs.argVector); + } else { + ExecuteInParentProcess(pid, ret); + } + if (ret == ERR_OK_NO_AOT_FILE) { + return ERR_OK; + } + return ret ? ERR_AOT_COMPILER_CALL_FAILED : AOTLocalCodeSign(hapArgs.fileName, hapArgs.signature, sigData); +} + +int32_t AotCompilerImpl::AOTLocalCodeSign(const std::string &fileName, const std::string &appSignature, + std::vector &sigData) +{ + Security::CodeSign::ByteBuffer sig; + if (Security::CodeSign::LocalCodeSignKit::SignLocalCode(appSignature, fileName, sig) + != CommonErrCode::CS_SUCCESS) { + HiviewDFX::HiLog::Error(LABEL, "failed to sign the aot file"); + return ERR_AOT_COMPILER_CALL_FAILED; + } + HiviewDFX::HiLog::Debug(LABEL, "aot file local sign success"); + uint8_t *dataPtr = sig.GetBuffer(); + for (uint32_t i = 0; i < sig.GetSize(); ++i) { + sigData.emplace_back(static_cast(dataPtr[i])); + } + return ERR_OK; +} + +int32_t AotCompilerImpl::StopAotCompiler() +{ + HiviewDFX::HiLog::Info(LABEL, "begin to stop AOT"); + std::lock_guard lock(stateMutex_); + if (!state_.running) { + HiviewDFX::HiLog::Info(LABEL, "AOT not running, return directly"); + return ERR_AOT_COMPILER_STOP_FAILED; + } + if (state_.childPid <= 0) { + HiviewDFX::HiLog::Error(LABEL, "invalid child pid"); + return ERR_AOT_COMPILER_STOP_FAILED; + } + HiviewDFX::HiLog::Info(LABEL, "begin to kill child process : %{public}d", state_.childPid); + (void)kill(state_.childPid, SIGKILL); + ResetState(); + return ERR_OK; +} + +void AotCompilerImpl::InitState(const pid_t childPid) +{ + state_.running = true; + state_.childPid = childPid; +} + +void AotCompilerImpl::ResetState() +{ + state_.running = false; + state_.childPid = -1; +} +} // namespace ArkCompiler::OHOS \ No newline at end of file diff --git a/compiler_service/src/aot_compiler_load_callback.cpp b/compiler_service/src/aot_compiler_load_callback.cpp new file mode 100644 index 0000000000..3035063577 --- /dev/null +++ b/compiler_service/src/aot_compiler_load_callback.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#include "aot_compiler_load_callback.h" +#include "aot_compiler_client.h" +#include "hilog/log.h" +#include "system_ability_definition.h" + +namespace OHOS::ArkCompiler { +namespace { +constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0xD001800, "aot_compiler_service"}; +} // namespace + +void AotCompilerLoadCallback::OnLoadSystemAbilitySuccess(int32_t systemAbilityId, + const sptr &remoteObject) +{ + if (systemAbilityId != AOT_COMPILER_SERVICE_ID) { + HiviewDFX::HiLog::Error(LABEL, "system ability id %{public}d mismatch", systemAbilityId); + return; + } + + if (remoteObject == nullptr) { + HiviewDFX::HiLog::Error(LABEL, "remoteObject is nullptr"); + return; + } + + HiviewDFX::HiLog::Debug(LABEL, "load system ability %{public}d succeed", systemAbilityId); + AotCompilerClient::GetInstance().OnLoadSystemAbilitySuccess(remoteObject); +} + +void AotCompilerLoadCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId) +{ + if (systemAbilityId != AOT_COMPILER_SERVICE_ID) { + HiviewDFX::HiLog::Error(LABEL, "system ability id %{public}d mismatch", systemAbilityId); + return; + } + + HiviewDFX::HiLog::Debug(LABEL, "load system ability %{public}d failed", systemAbilityId); + AotCompilerClient::GetInstance().OnLoadSystemAbilityFail(); +} +} // namespace OHOS::ArkCompiler \ No newline at end of file diff --git a/compiler_service/src/aot_compiler_service.cpp b/compiler_service/src/aot_compiler_service.cpp new file mode 100644 index 0000000000..25c8b8aeb3 --- /dev/null +++ b/compiler_service/src/aot_compiler_service.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#include "aot_compiler_service.h" +#include "aot_compiler_error_utils.h" +#include "aot_compiler_impl.h" +#include "hilog/log.h" +#include "iservice_registry.h" +#include "ipc_skeleton.h" +#include "iremote_object.h" +#include "system_ability_definition.h" + +namespace OHOS::ArkCompiler { +namespace { +const std::string TASK_ID = "UnLoadSA"; +constexpr int32_t DELAY_TIME = 180000; +} + +REGISTER_SYSTEM_ABILITY_BY_ID(AotCompilerService, AOT_COMPILER_SERVICE_ID, false); + +AotCompilerService::AotCompilerService() + : SystemAbility(AOT_COMPILER_SERVICE_ID, false), state_(ServiceRunningState::STATE_NOT_START) +{ +} + +AotCompilerService::AotCompilerService(int32_t systemAbilityId, bool runOnCreate) + : SystemAbility(systemAbilityId, runOnCreate), state_(ServiceRunningState::STATE_NOT_START) +{ +} + +AotCompilerService::~AotCompilerService() +{ +} + +void AotCompilerService::OnStart() +{ + HiviewDFX::HiLog::Info(LABEL, "aot compiler service is onStart"); + if (state_ == ServiceRunningState::STATE_RUNNING) { + HiviewDFX::HiLog::Info(LABEL, "aot compiler service has already started"); + return; + } + if (!Init()) { + HiviewDFX::HiLog::Info(LABEL, "init aot compiler service failed"); + return; + } + bool ret = Publish(this); + if (!ret) { + HiviewDFX::HiLog::Error(LABEL, "publish service failed"); + return; + } + state_ = ServiceRunningState::STATE_RUNNING; +} + +bool AotCompilerService::Init() +{ + auto runner = AppExecFwk::EventRunner::Create(TASK_ID); + if (unLoadHandler_ == nullptr) { + unLoadHandler_ = std::make_shared(runner); + } + return true; +} + +void AotCompilerService::DelayUnloadTask() +{ + auto task = [this]() { + sptr samgr = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (samgr == nullptr) { + HiviewDFX::HiLog::Error(LABEL, "fail to get system ability manager"); + return; + } + int32_t ret = samgr->UnloadSystemAbility(AOT_COMPILER_SERVICE_ID); + if (ret != ERR_OK) { + HiviewDFX::HiLog::Error(LABEL, "remove system ability failed"); + return; + } + }; + unLoadHandler_->RemoveTask(TASK_ID); + unLoadHandler_->PostTask(task, TASK_ID, DELAY_TIME); +} + +void AotCompilerService::OnStop() +{ + HiviewDFX::HiLog::Info(LABEL, "aot compiler service has been onStop"); + state_ = ServiceRunningState::STATE_NOT_START; +} + +int32_t AotCompilerService::AotCompiler(const std::unordered_map &argsMap, + std::vector &sigData) +{ + HiviewDFX::HiLog::Debug(LABEL, "begin to call aot compiler"); + int32_t ret = AotCompilerImpl::GetInstance().EcmascriptAotCompiler(argsMap, sigData); + HiviewDFX::HiLog::Debug(LABEL, "finish aot compiler"); + DelayUnloadTask(); + return ret; +} + +int32_t AotCompilerService::StopAotCompiler() +{ + HiviewDFX::HiLog::Debug(LABEL, "stop aot compiler service"); + int32_t ret = AotCompilerImpl::GetInstance().StopAotCompiler(); + DelayUnloadTask(); + return ret; +} +} // namespace OHOS::ArkCompiler \ No newline at end of file diff --git a/compiler_service/test/BUILD.gn b/compiler_service/test/BUILD.gn new file mode 100644 index 0000000000..50b2f38826 --- /dev/null +++ b/compiler_service/test/BUILD.gn @@ -0,0 +1,64 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# 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. + +import("//build/test.gni") + +compiler_service_root = "../../../ets_runtime/compiler_service" +module_output_path = "arkcompiler/ets_runtime/compiler_service" + +aot_compiler_service_sources = [ + "${compiler_service_root}/interface/aot_compiler_interface_proxy.cpp", + "${compiler_service_root}/interface/aot_compiler_interface_stub.cpp", + "${compiler_service_root}/src/aot_compiler_client.cpp", + "${compiler_service_root}/src/aot_compiler_error_utils.cpp", + "${compiler_service_root}/src/aot_compiler_impl.cpp", + "${compiler_service_root}/src/aot_compiler_load_callback.cpp", + "${compiler_service_root}/src/aot_compiler_service.cpp", +] + +config("module_private_config") { + visibility = [ ":*" ] + include_dirs = [ + "${compiler_service_root}/include", + "${compiler_service_root}/interface", + ] +} + +ohos_unittest("AotCompilerServiceTest") { + module_out_path = module_output_path + sources = [ "aot_compiler_service_test.cpp" ] + sources += aot_compiler_service_sources + configs = [ ":module_private_config" ] + deps = [ + "${compiler_service_root}:libcompiler_service", + "//third_party/googletest:gtest_main", + ] + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "c_utils:utils", + "code_signature:liblocal_code_sign_sdk", + "eventhandler:libeventhandler", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] +} + +group("compiler_service_unittest") { + testonly = true + deps = [ ":AotCompilerServiceTest" ] +} diff --git a/compiler_service/test/aot_compiler_service_test.cpp b/compiler_service/test/aot_compiler_service_test.cpp new file mode 100644 index 0000000000..bbee14751b --- /dev/null +++ b/compiler_service/test/aot_compiler_service_test.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#include "aot_compiler_client.h" +#include "aot_compiler_service.h" +#include "aot_compiler_error_utils.h" +#include "aot_compiler_load_callback.h" +#include "system_ability_definition.h" +#include +#include +#include +#include + +using namespace testing::ext; + +namespace OHOS { +namespace ArkCompiler { +class AotCompilerServiceTest : public testing::Test { +public: + AotCompilerServiceTest() {} + virtual ~AotCompilerServiceTest() {} + + static void SetUpTestCase() {} + static void TearDownTestCase() {} + void SetUp() override {} + void TearDown() override {} +}; + +/** + * @tc.name: AotCompilerServiceTest_001 + * @tc.desc: invoke aot_compiler service in client program. + * @tc.type: Func + * @tc.require: IR/AR/SR +*/ +HWTEST_F(AotCompilerServiceTest, AotCompilerServiceTest_001, TestSize.Level0) +{ + std::unordered_map argsMap; + std::vector sigData; + int32_t ret = AotCompilerClient::GetInstance().AotCompiler(argsMap, sigData); + EXPECT_EQ(ret, ERR_AOT_COMPILER_PARAM_FAILED); + EXPECT_EQ(argsMap.empty(), true); + EXPECT_EQ(sigData.empty(), true); +} + +/** + * @tc.name: AotCompilerServiceTest_002 + * @tc.desc: Load SA fail. + * @tc.type: Func + * @tc.require: IR/AR/SR +*/ +HWTEST_F(AotCompilerServiceTest, AotCompilerServiceTest_002, TestSize.Level0) +{ + AotCompilerLoadCallback cb; + cb.OnLoadSystemAbilityFail(AOT_COMPILER_SERVICE_ID); +} + +/** + * @tc.name: AotCompilerServiceTest_003 + * @tc.desc: Load SA success and returned SA_ID doesn't match. + * @tc.type: Func + * @tc.require: IR/AR/SR +*/ +HWTEST_F(AotCompilerServiceTest, AotCompilerServiceTest_003, TestSize.Level0) +{ + AotCompilerLoadCallback cb; + cb.OnLoadSystemAbilitySuccess(AOT_COMPILER_SERVICE_ID - 1, nullptr); +} + +/** + * @tc.name: AotCompilerServiceTest_004 + * @tc.desc: Load SA success and returned remote object is null. + * @tc.type: Func + * @tc.require: IR/AR/SR +*/ +HWTEST_F(AotCompilerServiceTest, AotCompilerServiceTest_004, TestSize.Level0) +{ + AotCompilerLoadCallback cb; + cb.OnLoadSystemAbilitySuccess(AOT_COMPILER_SERVICE_ID, nullptr); +} +} // namespace OHOS +} // namespace ArkCompiler \ No newline at end of file diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index 7f43e7fcd5..b8740fbdc9 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -334,9 +334,6 @@ ohos_source_set("libark_jsoptimizer_set") { # hiviewdfx libraries external_deps += hiviewdfx_ext_deps - if (enable_local_code_sign) { - external_deps += [ "code_signature:liblocal_code_sign_sdk" ] - } deps += hiviewdfx_deps part_name = "ets_runtime" @@ -381,9 +378,6 @@ ohos_source_set("libark_jsoptimizer_set_with_maple") { # hiviewdfx libraries external_deps += hiviewdfx_ext_deps - if (enable_local_code_sign) { - external_deps += [ "code_signature:liblocal_code_sign_sdk" ] - } part_name = "ets_runtime" subsystem_name = "arkcompiler" diff --git a/ecmascript/compiler/aot_compiler.cpp b/ecmascript/compiler/aot_compiler.cpp index b44722f094..837bf1e557 100644 --- a/ecmascript/compiler/aot_compiler.cpp +++ b/ecmascript/compiler/aot_compiler.cpp @@ -36,6 +36,13 @@ namespace panda::ecmascript::kungfu { namespace { +enum ErrCode { + ERR_OK = (0), + ERR_FAIL = (-1), + ERR_HELP = (1), + ERR_NO_AP = (2), +}; + void CompileValidFiles(PassManager &passManager, AOTFileGenerator &generator, bool &ret, const CVector &fileInfos, AotCompilerStats &compilerStats) { @@ -72,14 +79,14 @@ int Main(const int argc, const char **argv) { if (argc < 2) { // 2: at least have two arguments LOG_COMPILER(ERROR) << AotCompilerPreprocessor::GetHelper(); - return -1; + return ERR_FAIL; } JSRuntimeOptions runtimeOptions; bool retOpt = runtimeOptions.ParseCommand(argc, argv); if (!retOpt) { LOG_COMPILER(ERROR) << AotCompilerPreprocessor::GetHelper(); - return 1; + return ERR_HELP; } if (runtimeOptions.WasSetDeviceState()) { @@ -97,7 +104,7 @@ int Main(const int argc, const char **argv) EcmaVM *vm = JSNApi::CreateEcmaVM(runtimeOptions); if (vm == nullptr) { LOG_COMPILER(ERROR) << "Cannot Create vm"; - return -1; + return ERR_FAIL; } { @@ -115,11 +122,11 @@ int Main(const int argc, const char **argv) AotCompilerPreprocessor cPreprocessor(vm, runtimeOptions, pkgArgsMap, profilerDecoder, pandaFileNames); if (!cPreprocessor.HandleTargetCompilerMode(cOptions) || !cPreprocessor.HandlePandaFileNames(argc, argv)) { - return 1; + return ERR_HELP; } if (runtimeOptions.IsPartialCompilerMode() && cOptions.profilerIn_.empty()) { // no need to compile in partial mode without any ap files. - return 0; + return ERR_NO_AP; } AotCompilerStats compilerStats; @@ -210,7 +217,7 @@ int Main(const int argc, const char **argv) LOG_COMPILER(INFO) << (ret ? "ts aot compile success" : "ts aot compile failed"); JSNApi::DestroyJSVM(vm); - return ret ? 0 : -1; + return ret ? ERR_OK : ERR_FAIL; } } // namespace panda::ecmascript::kungfu diff --git a/ecmascript/platform/file.h b/ecmascript/platform/file.h index 35e87860bd..d2c385a905 100644 --- a/ecmascript/platform/file.h +++ b/ecmascript/platform/file.h @@ -78,8 +78,8 @@ JSHandle ResolveFilenameFromNative(JSThread *thread, JSTaggedValue d bool PUBLIC_API FileExist(const char *filename); int PUBLIC_API Unlink(const char *filename); bool TryToRemoveSO(JSThread *thread, JSHandle module); -void *PUBLIC_API LoadLib(const std::string &libname); -void *PUBLIC_API FindSymbol(void *handle, const char *symbol); -int PUBLIC_API CloseLib(void *handle); +void *LoadLib(const std::string &libname); +void *FindSymbol(void *handle, const char *symbol); +int CloseLib(void *handle); } // namespace panda::ecmascript #endif // ECMASCRIPT_PLATFORM_FILE_H diff --git a/ecmascript/platform/unix/ohos/code_sign.cpp b/ecmascript/platform/unix/ohos/code_sign.cpp index cbfdf3211a..494b8835cc 100644 --- a/ecmascript/platform/unix/ohos/code_sign.cpp +++ b/ecmascript/platform/unix/ohos/code_sign.cpp @@ -14,42 +14,12 @@ */ #include "ecmascript/platform/code_sign.h" - -#include - #include "ecmascript/log_wrapper.h" -#include "ecmascript/platform/file.h" -using namespace OHOS::Security::CodeSign; namespace panda::ecmascript { void CodeSignatureForAOTFile(const std::string &filename, const std::string &appSignature) { - LOG_ECMA(DEBUG) << "start to sign the aot file!"; - ByteBuffer sig; - if (LocalCodeSignKit::SignLocalCode(appSignature, filename, sig) != CommonErrCode::CS_SUCCESS) { - LOG_ECMA(ERROR) << "Failed to sign the aot file!"; - return; - } - - const std::string codeSignLib = "libcode_sign_utils.z.so"; - // mangle for func: int32_t CodeSignUtils::EnforceCodeSignForFile(const std::string&, const ByteBuffer&) - const char *codeSignFuncStr = "_ZN4OHOS8Security8CodeSign13CodeSignUtils22EnforceCodeSignForFile\ -ERKNSt3__h12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERKNS1_10ByteBufferE"; - void *libHandle = LoadLib(codeSignLib); - if (libHandle == nullptr) { - LOG_ECMA(FATAL) << "Failed to load libcode_sign_utils.z.so!"; - } - auto enforceCodeSignForFile = reinterpret_cast( - FindSymbol(libHandle, codeSignFuncStr)); - if (enforceCodeSignForFile == nullptr) { - LOG_ECMA(FATAL) << "Failed to find symbol enforceCodeSignForFile"; - } - - if (enforceCodeSignForFile(filename, sig) != CommonErrCode::CS_SUCCESS) { - LOG_ECMA(ERROR) << "Failed to enable code signature for the aot file!"; - return; - } - CloseLib(libHandle); - LOG_ECMA(DEBUG) << "sign the aot file success"; + (void)filename; + (void)appSignature; } } // namespace panda::ecmascript \ No newline at end of file diff --git a/libark_jsruntime.map b/libark_jsruntime.map index 47b7dbbb6d..1af5f0b487 100644 --- a/libark_jsruntime.map +++ b/libark_jsruntime.map @@ -154,9 +154,6 @@ panda::ecmascript::FileMapForAlignAddress*; panda::ecmascript::FileMap*; panda::ecmascript::FileUnMap*; - panda::ecmascript::LoadLib*; - panda::ecmascript::FindSymbol*; - panda::ecmascript::CloseLib*; panda::ecmascript::ForceCreateDirectory*; panda::ecmascript::GetFileDelimiter*; panda::ecmascript::GetPathSeparator*;