diff --git a/include/pmu.h b/include/pmu.h index 98fd691bf97f3348cbb5720de7ebb3f4184c34e7..e2f553f7a4c05525bdf38e2c87241c6c048fcd5a 100644 --- a/include/pmu.h +++ b/include/pmu.h @@ -64,6 +64,11 @@ enum SymbolMode { RESOLVE_ELF_DWARF = 2 }; +enum SymMangleMode { + NEED_MANGLE = 0, // need mangle symbol. + NEED_DEMANGLE = 1 // need demangle symbol, default is demangle symbol. +}; + struct PmuAttr { // Event list. // Refer 'perf list' for details about event names. @@ -108,6 +113,8 @@ struct PmuAttr { // This indicates how to analyze symbols of samples. // Refer to comments of SymbolMode. enum SymbolMode symbolMode; + // Refer to comments of SymMangleMode. + enum SymMangleMode symMangleMode; // This indicates whether to collect whole callchains or only top frame. unsigned callStack : 1; diff --git a/pmu/pmu.cpp b/pmu/pmu.cpp index d7b58e70edd3f7419e5a84d80adfb0e7b1be78ee..7909ef4de01de1d9e2b58e61961e9eecdf902e55 100644 --- a/pmu/pmu.cpp +++ b/pmu/pmu.cpp @@ -277,6 +277,7 @@ int PmuOpen(enum PmuTaskType collectType, struct PmuAttr *attr) } KUNPENG_PMU::PmuList::GetInstance()->SetSymbolMode(pd, attr->symbolMode); + KUNPENG_PMU::PmuList::GetInstance()->SetMangleMode(pd, attr->symMangleMode); err = KUNPENG_PMU::PmuList::GetInstance()->Register(pd, taskAttr.get()); if (err != SUCCESS) { PmuList::GetInstance()->Close(pd); diff --git a/pmu/pmu_list.cpp b/pmu/pmu_list.cpp index f81686c2b427537e3571886d86429a7555ec5b0d..470b48aeb3d12771deb26b8510c3ca3d3fd21995 100644 --- a/pmu/pmu_list.cpp +++ b/pmu/pmu_list.cpp @@ -369,6 +369,9 @@ namespace KUNPENG_PMU { continue; } if (pmuData.stack == nullptr) { + SymVariables symVariables; + symVariables.mangleMode = symMangleList[eventData.pd]; + AdaptVariables(symVariables); pmuData.stack = StackToHash(pmuData.pid, ipsData.ips.data(), ipsData.ips.size()); } } @@ -659,9 +662,21 @@ namespace KUNPENG_PMU { symModeList[pd] = mode; } + void PmuList::SetMangleMode(const int pd, const SymMangleMode &mode) + { + lock_guard lg(dataListMtx); + symMangleList[pd] = mode; + } + SymbolMode PmuList::GetSymbolMode(const unsigned pd) { lock_guard lg(dataListMtx); return symModeList[pd]; } + + SymMangleMode PmuList::GetMangleMode(const unsigned pd) + { + lock_guard lg(dataListMtx); + return symMangleList[pd]; + } } \ No newline at end of file diff --git a/pmu/pmu_list.h b/pmu/pmu_list.h index 699261aca0145f6f1d11097bcd260d7b1c5a01a1..013a04b49b2c11f7e88692c441ec44f6588af0f2 100644 --- a/pmu/pmu_list.h +++ b/pmu/pmu_list.h @@ -63,6 +63,7 @@ public: void FreeData(PmuData* pmuData); int GetTaskType(const int pd) const; void SetSymbolMode(const int pd, const SymbolMode &mode); + void SetMangleMode(const int pd, const SymMangleMode &mode); int NewPd(); @@ -116,6 +117,8 @@ private: void AggregateUncoreData(const unsigned pd, const std::vector &evData, std::vector &newEvData); std::vector& GetPreviousData(const unsigned pd); SymbolMode GetSymbolMode(const unsigned pd); + SymMangleMode GetMangleMode(const unsigned pd); + static std::mutex pmuListMtx; static std::mutex dataListMtx; @@ -151,6 +154,7 @@ private: unsigned maxPd = 0; std::unordered_map symModeList; + std::unordered_map symMangleList; }; } // namespace KUNPENG_PMU #endif diff --git a/symbol/symbol.cpp b/symbol/symbol.cpp index 699dca8ae437bbf0f0353fb52bdf6fc6a6968edb..7f35bedfe2fe17f0cb3931edb580352b4952bb8c 100644 --- a/symbol/symbol.cpp +++ b/symbol/symbol.cpp @@ -153,3 +153,7 @@ void FreeAsmStack(struct StackAsm* stackAsm) { SymbolUtils::FreeStackAsm(&stackAsm); } + +void AdaptVariables(struct SymVariables var) { + SymbolResolve::GetInstance()->SetVariables(var); +} diff --git a/symbol/symbol.h b/symbol/symbol.h index aadd51d41e9d4d2ca8db89c2f0be2541ab7a5102..48f7820252394d4d3da1721dd9b7b5adca7e7492 100644 --- a/symbol/symbol.h +++ b/symbol/symbol.h @@ -54,6 +54,10 @@ struct AsmCode { unsigned int lineNum; // the real line of this addr }; +struct SymVariables { + int mangleMode; // default mangle mode,will give demangle symbol. +}; + void SymResolverInit(); int SymResolverRecordKernel(); @@ -119,6 +123,12 @@ void FreeModuleData(int pid); */ void FreeAsmStack(struct StackAsm* stackAsm); +/** + * change the variables, influence some output data. + * mangleMode, if the mode is 1, the symbol will demangle. + */ +void AdaptVariables(struct SymVariables var); + struct ProcTopology { int pid; int tid; diff --git a/symbol/symbol_resolve.cpp b/symbol/symbol_resolve.cpp index e22d0e36572a02bc97df571ee3364714960a03c1..1c35af9c3d7167d3396a3855dda4acc62548ec5a 100644 --- a/symbol/symbol_resolve.cpp +++ b/symbol/symbol_resolve.cpp @@ -754,12 +754,14 @@ void SymbolResolve::SearchElfInfo(MyElf& myElf, unsigned long addr, struct Symbo symbol->codeMapEndAddr = elfSym->get_data().value + elfSym->get_data().size; *offset = addr - elfSym->get_data().value; std::string symName = elfSym->get_name(); - char *name = CppNamedDemangle(symName.c_str()); - if (name) { - SymbolUtils::StrCpy(symbol->symbolName, MAX_LINUX_SYMBOL_LEN, name); - free(name); - name = nullptr; - return; + if (demangleLocal.Get()) { + char *name = CppNamedDemangle(symName.c_str()); + if (name) { + SymbolUtils::StrCpy(symbol->symbolName, MAX_LINUX_SYMBOL_LEN, name); + free(name); + name = nullptr; + return; + } } SymbolUtils::StrCpy(symbol->symbolName, MAX_LINUX_SYMBOL_LEN, symName.c_str()); return; @@ -1166,6 +1168,10 @@ std::vector> SymbolResolve::FindDiffMaps( return diffMaps; } +void SymbolResolve::SetVariables(struct SymVariables symVariables) { + this->demangleLocal.Set(symVariables.mangleMode); +} + SymbolResolve* SymbolResolve::instance = nullptr; std::mutex SymbolResolve::mutex; std::mutex SymbolResolve::kernelMutex; diff --git a/symbol/symbol_resolve.h b/symbol/symbol_resolve.h index 134bbdf537e607e4ef8221e92ccacbb6239ec971..2e490cb0887a028f2ff9011187d3b185627cab0f 100644 --- a/symbol/symbol_resolve.h +++ b/symbol/symbol_resolve.h @@ -26,6 +26,7 @@ #include #include #include +#include "thread_local.h" #include "safe_handler.h" #include "linked_list.h" #include "symbol.h" @@ -171,6 +172,7 @@ namespace KUNPENG_SYM { struct Symbol* MapAddr(int pid, unsigned long addr); struct StackAsm* MapAsmCode(const char* moduleName, unsigned long startAddr, unsigned long endAddr); struct Symbol* MapCodeAddr(const char* moduleName, unsigned long startAddr); + void SetVariables(struct SymVariables symVariables); private: void SearchElfInfo(MyElf &myElf, unsigned long addr, struct Symbol *symbol, unsigned long *offset); @@ -203,6 +205,7 @@ namespace KUNPENG_SYM { SafeHandler elfSafeHandler; SafeHandler symSafeHandler; SafeHandler dwarfLoadHandler; + ThreadLocal demangleLocal = {1}; static std::mutex kernelMutex; static SymbolResolve* instance; static std::mutex mutex; diff --git a/test/test_symbol/test_libsym.cpp b/test/test_symbol/test_libsym.cpp index 015ba34210fbc56f320562e9540f6ee9f94f83bf..fba2505b3cd54827fce16d0eeaa53cb97e0d7e0c 100644 --- a/test/test_symbol/test_libsym.cpp +++ b/test/test_symbol/test_libsym.cpp @@ -14,15 +14,11 @@ ******************************************************************************/ #include #include -#include #include -#include -#include #include #include #include "pcerrc.h" #include "symbol_resolve.h" -#include "linked_list.h" #include "symbol.h" /******************************************* * @brief DT testcases for libsym.so APIs * @@ -589,7 +585,6 @@ void InsertSafeDataAndDoInsert2(std::unordered_map& map, SafeHandler lock; std::unordered_map map; @@ -601,4 +596,22 @@ TEST(symbol, test_safe_handler){ b.join(); c.join(); d.join(); +} + +void SetData(const std::string &str, ThreadLocal &local) { + local.Set(str); + std::string get = local.Get(); + ASSERT_EQ(local.Get(), str); +} + +TEST(symbol, test_local_thread) { + ThreadLocal local(""); + local.Set("c"); + std::thread a(SetData, "a", std::ref(local)); + std::thread b(SetData, "b", std::ref(local)); + a.join(); + b.join(); + ASSERT_EQ(local.Get(), "c"); + local.Set("d"); + ASSERT_EQ(local.Get(), "d"); } \ No newline at end of file diff --git a/util/thread_local.h b/util/thread_local.h new file mode 100644 index 0000000000000000000000000000000000000000..4ffeaa02b7a9700c983c89eed405ea0e206a9a5d --- /dev/null +++ b/util/thread_local.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * libkperf licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: Mr.Li + * Create: 2024-07-09 + * Description: used for save the local thread data. + ******************************************************************************/ + +#ifndef LIBKPROF_THREAD_LOCAL_H +#define LIBKPROF_THREAD_LOCAL_H + +#include +#include +#include +#include + +template +class ThreadLocal { +public: + ThreadLocal() = delete; + + ThreadLocal(T t) : defaultData(t) {}; + + void Set(T t) { + safeHelp.tryLock(0); + threadLocalMap[std::this_thread::get_id()] = t; + safeHelp.releaseLock(0); + } + + void Remove(T t) { + safeHelp.tryLock(0); + threadLocalMap.erase(std::this_thread::get_id()); + safeHelp.releaseLock(0); + } + + T Get() { + safeHelp.tryLock(0); + std::thread::id id = std::this_thread::get_id(); + if (threadLocalMap.find(id) == threadLocalMap.end()) { ; + safeHelp.releaseLock(0); + return defaultData; + } + safeHelp.releaseLock(0); + return threadLocalMap.at(id); + } + +private: + T defaultData; + std::map threadLocalMap; + SafeHandler safeHelp; +}; + + +#endif //LIBKPROF_THREAD_LOCAL_H