diff --git a/test/common/utils/include/func_stub.h b/test/common/utils/include/func_stub.h new file mode 100644 index 0000000000000000000000000000000000000000..f2959cfb82cdedf1a312b59dc42af45cd3fc8f20 --- /dev/null +++ b/test/common/utils/include/func_stub.h @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2025 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_ROSEN_FUNC_STUB_H +#define OHOS_ROSEN_FUNC_STUB_H + +#include +#include +#include +#include +#include +#include +#include + +//General Macro Definitions +#define FUNC_ADDR(className, funcName) (&className::funcName) +#define VALGRIND_CACHE_FLUSH(addr, size) + +// Architecture detection and related configurations +#if defined(__aarch64__) || defined(_M_ARM64) + #define CODESIZE 16U + #define ADR_X9_IMM0 0x58000040 //Address loading instructions + #define BR_X0 0xd61f0000 //Register jump instructions +#elif defined(__arm__) || defined(_M_ARM) + #define CODESIZE 8U +#endif + +constexpr int32_t ADDR_PAGE_FOR_TWO = 2; +constexpr uint8_t IMMEDIATE_X9 = 9; +constexpr uint32_t BR_X9_MODE = (9 << 5); +constexpr size_t ONE_PAGE_SIZE = 4096; +constexpr size_t TWO_OFFSET = 2; +constexpr size_t FOUR_OFFSET = 4; +constexpr size_t SIX_OFFSET = 6; +constexpr uint64_t EIGHT_OFFSET = 8; +constexpr size_t SIXTEEN_OFFSET = 16; + +namespace OHOS::Rosen { +// Type aliases +using BytePtr = unsigned char*; +using PageAddr = void*; + +// Function address management +struct FuncAddrStub { + BytePtr funcPtr; + unsigned char codeBuf[CODESIZE]; +}; + +// Memory management tools +class MemoryManager { +public: + static size_t GetpageSize() + { + return sysconf(_SC_PAGE_SIZE) ? : ONE_PAGE_SIZE; + } + + static PageAddr GetPageStart(BytePtr addr) + { + return reinterpret_cast(reinterpret_cast(addr) & ~(GetpageSize() - 1)); + } + + static bool ProtectMemory(PageAddr addr, size_t size, int prot) + { + return mprotect(addr, size, prot) == 0; + } + + static void CacheFlush(char* addr, size_t size) + { + __builtin___clear_cache(addr, static_cast(addr) + size); + VALGRIND_CACHE_FLUSH(addr, size); + } +}; + +class FuncStub { +public: + FuncStub() : pageSize_(MemoryManager::GetpageSize()) {} + + ~FuncStub() + { + Clear(); + } + + template + void SetStubFunc(T addr, S stubAddr) + { + BytePtr funcPtr = ConvertAddress(addr); + BytePtr stubPtr = ConvertAddress(stubAddr); + std::shared_ptr stubEntry = std::make_shared(); + + Reset(funcPtr); + stubEntry->funcPtr = funcPtr; + memcpy_s(stubEntry->codeBuf, CODESIZE, funcPtr, CODESIZE); + + // Update memory permissions + if (!MemoryManager::ProtectMemory(MemoryManager::GetPageStart(stubEntry->funcPtr), pageSize_ * ADDR_PAGE_FOR_TWO, + PROT_READ | PROT_WRITE | PROT_EXEC)) { + throw std::runtime_error("Failed to set RWX permissions"); + } + + ReplaceFunction(funcPtr, stubPtr); + + // Restore memory permissions + if (!MemoryManager::ProtectMemory(MemoryManager::GetPageStart(stubEntry->funcPtr), pageSize_ * ADDR_PAGE_FOR_TWO, + PROT_READ | PROT_EXEC)) { + throw std::runtime_error("Failed to set RX permissions"); + } + + funcMap_.insert(std::pair>(funcPtr, stubEntry)); + return; + } + +private: + template + unsigned char* ConvertAddress(T addr) + { + union { + T addrIn; + unsigned char* addrOut; + } addrTrans; + + addrTrans.addrIn = addr; + return addrTrans.addrOut; + } + + // Schema-related substitution logic + void ReplaceFunction(BytePtr funcPtr, BytePtr stubPtr) + { +#if defined(__aarch64__) || defined(_M_ARM64) + // _M_ARM64 + reinterpret_cast(funcPtr)[0] = ADR_X9_IMM0 | IMMEDIATE_X9; + reinterpret_cast(funcPtr)[1] = BR_X0 | BR_X9_MODE; + *reinterpret_cast(funcPtr + EIGHT_OFFSET) = reinterpret_cast(stubPtr); +#elif defined(__arm__) || defined(_M_ARM) + // ARM + if ((reinterpret_cast(funcPtr) & 0x1) != 0) { + BytePtr alignedPtr = reinterpret_cast(reinterpret_cast(funcPtr) & ~0x1); + *reinterpret_cast(alignedPtr) = 0xf8df; + *reinterpret_cast(alignedPtr + TWO_OFFSET) = 0xf000; + *reinterpret_cast(alignedPtr + FOUR_OFFSET) = + static_cast(reinterpret_cast(stubPtr) & 0xffff); + *reinterpret_cast(alignedPtr + SIX_OFFSET) = + static_cast(reinterpret_cast(stubPtr) >> SIXTEEN_OFFSET); + } else { + reinterpret_cast(funcPtr)[0] = 0xe51ff004; + reinterpret_cast(funcPtr)[1] = reinterpret_cast(stubPtr); + } +#endif + MemoryManager::CacheFlush(reinterpret_cast(funcPtr), CODESIZE); + } + + template + void Reset(T addr) + { + BytePtr funcPtr = ConvertAddress(addr); + auto iter = funcMap_.find(funcPtr); + if (iter == funcMap_.end()) { + return; + } + + auto stubEntry = std::make_shared(); + stubEntry = iter->second; + // Restore the original code + if (MemoryManager::ProtectMemory(MemoryManager::GetPageStart(stubEntry->funcPtr), pageSize_ * ADDR_PAGE_FOR_TWO, + PROT_READ | PROT_WRITE | PROT_EXEC)) { + memcpy_s(stubEntry->funcPtr, CODESIZE, stubEntry->codeBuf, CODESIZE); + MemoryManager::CacheFlush(reinterpret_cast(stubEntry->funcPtr), CODESIZE); + MemoryManager::ProtectMemory(MemoryManager::GetPageStart(stubEntry->funcPtr), pageSize_ * ADDR_PAGE_FOR_TWO, + PROT_READ | PROT_EXEC); + } + funcMap_.erase(iter); + return; + } + + void Clear() + { + for (auto& [addr, entry] : funcMap_) { + if (MemoryManager::ProtectMemory(MemoryManager::GetPageStart(entry->funcPtr), pageSize_ * ADDR_PAGE_FOR_TWO, + PROT_READ | PROT_WRITE | PROT_EXEC)) { + memcpy_s(entry->funcPtr, CODESIZE, entry->codeBuf, CODESIZE); + MemoryManager::CacheFlush(reinterpret_cast(entry->funcPtr), CODESIZE); + MemoryManager::ProtectMemory(MemoryManager::GetPageStart(entry->funcPtr), pageSize_ * ADDR_PAGE_FOR_TWO, + PROT_READ | PROT_EXEC); + } + } + funcMap_.clear(); + return; + } + + size_t pageSize_; + std::map> funcMap_; +}; +} +#endif \ No newline at end of file diff --git a/window_scene/test/unittest/BUILD.gn b/window_scene/test/unittest/BUILD.gn index 871dd862a0f9efe07d687531985977ed01bc4b05..c7e6f98ebbc95fe691b56a3ae5fe5ac67fdf370a 100644 --- a/window_scene/test/unittest/BUILD.gn +++ b/window_scene/test/unittest/BUILD.gn @@ -534,6 +534,7 @@ ohos_unittest("ws_session_stage_stub_lifecycle_test") { } ohos_unittest("ws_scene_session_manager_test") { + use_exceptions = true module_out_path = module_out_path sources = [ "scene_session_manager_test.cpp" ] @@ -663,6 +664,7 @@ ohos_unittest("ws_scene_session_manager_test6") { } ohos_unittest("ws_scene_session_manager_test7") { + use_exceptions = true module_out_path = module_out_path sources = [ "scene_session_manager_test7.cpp" ] @@ -785,6 +787,7 @@ ohos_unittest("ws_scene_session_manager_test12") { } ohos_unittest("ws_window_manager_service_dump_test") { + use_exceptions = true module_out_path = module_out_path include_dirs = [ "${window_base_path}/test/common/utils/include/" ] @@ -1472,6 +1475,7 @@ ohos_unittest("ws_window_manager_lru_test") { config("ws_unittest_common_public_config") { include_dirs = [ "${window_base_path}/test/common/mock", + "${window_base_path}/test/common/utils/include", # for WMError Code "${window_base_path}/dm/include", diff --git a/window_scene/test/unittest/scene_session_manager_test.cpp b/window_scene/test/unittest/scene_session_manager_test.cpp index 9ce643811c35adaa28648717073b0a4df6444297..ed67646deb8a3c7d6fcaac6c4f10a201311e6d16 100644 --- a/window_scene/test/unittest/scene_session_manager_test.cpp +++ b/window_scene/test/unittest/scene_session_manager_test.cpp @@ -17,6 +17,7 @@ #include #include #include +#include "common/include/session_permission.h" #include "interfaces/include/ws_common.h" #include "iremote_object_mocker.h" #include "screen_fold_data.h" @@ -32,6 +33,7 @@ #include "mock/mock_window_event_channel.h" #include "application_info.h" #include "context.h" +#include "func_stub.h" using namespace testing; using namespace testing::ext; @@ -115,6 +117,16 @@ int32_t SceneSessionManagerTest::GetTaskCount(sptr& session) return taskNum; } +static bool IsStartByHdcdTrueStub() +{ + return true; +} + +static bool IsSACallingTrueStub() +{ + return true; +} + namespace { /** * @tc.name: SetBrightness @@ -1548,18 +1560,24 @@ HWTEST_F(SceneSessionManagerTest, AccessibilityFilterTwoWindowCovered, TestSize. */ HWTEST_F(SceneSessionManagerTest, GetMainWindowInfos, TestSize.Level1) { + FuncStub stub; + stub.SetStubFunc(FUNC_ADDR(SessionPermission, IsSACalling), IsSACallingTrueStub); + stub.SetStubFunc(FUNC_ADDR(SessionPermission, IsStartByHdcd), IsStartByHdcdTrueStub); + int32_t topNum = 1024; std::vector topNInfos; auto result = ssm_->GetMainWindowInfos(topNum, topNInfos); EXPECT_EQ(result, WMError::WM_OK); topNum = 0; - ssm_->GetMainWindowInfos(topNum, topNInfos); + result = ssm_->GetMainWindowInfos(topNum, topNInfos); + EXPECT_EQ(result, WMError::WM_ERROR_INVALID_PARAM); topNum = 1000; MainWindowInfo info; topNInfos.push_back(info); - ssm_->GetMainWindowInfos(topNum, topNInfos); + result = ssm_->GetMainWindowInfos(topNum, topNInfos); + EXPECT_EQ(result, WMError::WM_ERROR_INVALID_PARAM); } /** diff --git a/window_scene/test/unittest/scene_session_manager_test7.cpp b/window_scene/test/unittest/scene_session_manager_test7.cpp index 3000b4a16845e109d4fe4267b4a824da8fc3ac31..f6bdbe16edd7d7d48421a00a085ad6e8d84ffec1 100644 --- a/window_scene/test/unittest/scene_session_manager_test7.cpp +++ b/window_scene/test/unittest/scene_session_manager_test7.cpp @@ -15,12 +15,14 @@ #include +#include "common/include/session_permission.h" #include "interfaces/include/ws_common.h" #include "iremote_object_mocker.h" #include "session_manager/include/scene_session_manager.h" #include "session_info.h" #include "session/host/include/scene_session.h" #include "session_manager.h" +#include "func_stub.h" using namespace testing; using namespace testing::ext; @@ -77,6 +79,16 @@ void SceneSessionManagerTest7::TearDown() ssm_->sceneSessionMap_.clear(); } +static bool IsStartByHdcdTrueStub() +{ + return true; +} + +static bool IsSACallingTrueStub() +{ + return true; +} + namespace { /** * @tc.name: UpdateSessionWindowVisibilityListener @@ -777,6 +789,10 @@ HWTEST_F(SceneSessionManagerTest7, SetSkipSelfWhenShowOnVirtualScreen01, TestSiz */ HWTEST_F(SceneSessionManagerTest7, GetMainWindowInfos, TestSize.Level1) { + FuncStub stub; + stub.SetStubFunc(FUNC_ADDR(SessionPermission, IsSACalling), IsSACallingTrueStub); + stub.SetStubFunc(FUNC_ADDR(SessionPermission, IsStartByHdcd), IsStartByHdcdTrueStub); + int32_t topNum = 1; std::vector topNInfo; topNInfo.clear(); diff --git a/window_scene/test/unittest/window_manager_service_dump_test.cpp b/window_scene/test/unittest/window_manager_service_dump_test.cpp index 134f37dee4f9c420c83a072f004020760c41b75e..0bc388f8ce659182c96ef6cd80f4fc714ff255e6 100644 --- a/window_scene/test/unittest/window_manager_service_dump_test.cpp +++ b/window_scene/test/unittest/window_manager_service_dump_test.cpp @@ -15,6 +15,7 @@ #include +#include "common/include/session_permission.h" #include "mock/mock_session_stage.h" #include "iremote_object_mocker.h" #include "interfaces/include/ws_common.h" @@ -22,6 +23,7 @@ #include "session_manager/include/zidl/scene_session_manager_proxy.h" #include "session_info.h" #include "session/host/include/scene_session.h" +#include "func_stub.h" using namespace testing; using namespace testing::ext; @@ -57,6 +59,16 @@ void WindowManagerServiceDumpTest::TearDown() ssm_ = nullptr; } +static bool IsStartByHdcdTrueStub() +{ + return true; +} + +static bool IsSACallingTrueStub() +{ + return true; +} + namespace { /** @@ -66,6 +78,10 @@ namespace { */ HWTEST_F(WindowManagerServiceDumpTest, GetSessionDumpInfo01, TestSize.Level1) { + FuncStub stub; + stub.SetStubFunc(FUNC_ADDR(SessionPermission, IsSACalling), IsSACallingTrueStub); + stub.SetStubFunc(FUNC_ADDR(SessionPermission, IsStartByHdcd), IsStartByHdcdTrueStub); + ASSERT_NE(ssm_, nullptr); std::string dumpInfo = "testDumpInfo"; std::vector params = { "testDumpInfo" }; @@ -222,6 +238,10 @@ HWTEST_F(WindowManagerServiceDumpTest, DumpSessionElementInfo, TestSize.Level1) */ HWTEST_F(WindowManagerServiceDumpTest, NotifyDumpInfoResult, TestSize.Level1) { + FuncStub stub; + stub.SetStubFunc(FUNC_ADDR(SessionPermission, IsSACalling), IsSACallingTrueStub); + stub.SetStubFunc(FUNC_ADDR(SessionPermission, IsStartByHdcd), IsStartByHdcdTrueStub); + std::vector info = { "std::", "vector", "" }; ssm_->NotifyDumpInfoResult(info); std::vector params = { "-a" };