Files
handleaiuinew/env/LMI/include/kApi/Utils/kSymbolInfo.cpp
T
2024-05-18 23:53:26 +08:00

325 lines
7.8 KiB
C++

/**
* @file kSymbolInfo.cpp
*
* @internal
* Copyright (C) 2014-2021 by LMI Technologies Inc.
* Licensed under the MIT License.
* Redistributed files must retain the above copyright notice.
*/
#define K_PLATFORM
#include <kApi/Utils/kSymbolInfo.h>
#include <kApi/Data/kMap.h>
#include <kApi/Data/kString.h>
#include <kApi/Threads/kLock.h>
kBeginStaticClassEx(k, kSymbolInfo)
kEndStaticClassEx()
kFx(void) xkSymbolInfo_Lock()
{
kStaticObj(kSymbolInfo);
kApiLockFx handler = kApiLib_SymbolLockHandler();
kPointer provider= kApiLib_SymbolLockProvider();
if (!kIsNull(handler))
{
handler(provider);
}
else if (!kIsNull(sobj->lock))
{
kLock_Enter(sobj->lock);
}
}
kFx(void) xkSymbolInfo_Unlock()
{
kStaticObj(kSymbolInfo);
kApiUnlockFx handler = kApiLib_SymbolUnlockHandler();
kPointer provider= kApiLib_SymbolLockProvider();
if (!kIsNull(handler))
{
handler(provider);
}
else if (!kIsNull(sobj->lock))
{
kLock_Exit(sobj->lock);
}
}
kFx(kStatus) xkSymbolInfo_FormatUnknown(kPointer function, kString description)
{
#if (K_POINTER_SIZE == 8)
return kString_Setf(description, "[0x%016llX]", (k64u)function);
#else
return kString_Setf(description, "[0x%08X]", (k32u)function);
#endif
}
#if defined(K_DEBUG) && defined(K_WINDOWS) && _MSC_VER >= 1500
#include <DbgHelp.h>
kFx(kStatus) xkSymbolInfo_InitStatic()
{
kStaticObj(kSymbolInfo);
kPointer symbolService = GetCurrentProcess();
const kSize NAME_CAPACITY = 256;
kSize symbolInfoLength = sizeof(SYMBOL_INFO) + (NAME_CAPACITY - 1)*sizeof(WCHAR);
SYMBOL_INFOW* symbolInfo = kNULL;
IMAGEHLP_LINEW64* lineInfo = kNULL;
kStatus status;
sobj->alloc = kAlloc_System();
kTry
{
if (kApiLib_SymbolInitializationEnabled())
{
if (!SymInitializeW(symbolService, kNULL, kTRUE))
{
kLogf("kSymbolInfo: SymInitialize failed.");
}
else
{
sobj->service = symbolService;
}
}
else
{
sobj->service = symbolService;
}
kTest(kLock_ConstructEx(&sobj->lock, xkLOCK_OPTION_PRIORITY_INHERITANCE, sobj->alloc));
kTest(kMap_Construct(&sobj->cache, kTypeOf(kPointer), kTypeOf(kString), 0, sobj->alloc));
kTest(kAlloc_Get(sobj->alloc, symbolInfoLength, &symbolInfo));
symbolInfo->MaxNameLen = (ULONG)NAME_CAPACITY;
symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
sobj->symbolInfo = symbolInfo;
kTest(kAlloc_Get(sobj->alloc, sizeof(IMAGEHLP_LINEW64), &lineInfo));
lineInfo->SizeOfStruct = sizeof(IMAGEHLP_LINEW64);
sobj->lineInfo = lineInfo;
kTest(kAssembly_AddLoadHandler(xkSymbolInfo_OnAssemblyLoad, kNULL));
}
kCatch(&status)
{
xkSymbolInfo_ReleaseStatic();
kEndCatch(status);
}
return kOK;
}
kFx(kStatus) xkSymbolInfo_ReleaseStatic()
{
kStaticObj(kSymbolInfo);
kAssembly_RemoveLoadHandler(xkSymbolInfo_OnAssemblyLoad, kNULL);
if (kApiLib_SymbolInitializationEnabled() && !kIsNull(sobj->service))
{
SymCleanup(sobj->service);
}
kCheck(kAlloc_Free(sobj->alloc, sobj->lineInfo));
kCheck(kAlloc_Free(sobj->alloc, sobj->symbolInfo));
kCheck(kObject_Dispose(sobj->cache));
kCheck(kObject_Destroy(sobj->lock));
return kOK;
}
kFx(kStatus) xkSymbolInfo_OnAssemblyLoad(kSymbolInfo trace, kAssembly assembly, kPointer unused)
{
kStaticObj(kSymbolInfo);
xkSymbolInfo_Lock();
{
if (kApiLib_SymbolInitializationEnabled() && !kIsNull(sobj->service))
{
SymRefreshModuleList(sobj->service);
}
}
xkSymbolInfo_Unlock();
return kOK;
}
kFx(kStatus) kSymbolInfo_DescribeFunction(kPointer function, kString* description)
{
kStaticObj(kSymbolInfo);
kString line = kNULL;
kStatus status;
kCheckTrue(!kIsNull(sobj->service) && !kIsNull(sobj->cache), kERROR_UNIMPLEMENTED);
xkSymbolInfo_Lock();
kTry
{
if (!kSuccess(kMap_FindT(sobj->cache, &function, &line)))
{
DWORD64 functionAddress = (DWORD64)(kSize)(function);
SYMBOL_INFOW* symbolInfo = (SYMBOL_INFOW*) sobj->symbolInfo;
IMAGEHLP_LINEW64* lineInfo = (IMAGEHLP_LINEW64*) sobj->lineInfo;
DWORD displacement;
BOOL symStatus;
kTest(kString_Construct(&line, kNULL, sobj->alloc));
symStatus = SymFromAddrW(sobj->service, functionAddress, NULL, symbolInfo);
if (symStatus)
{
if (WideCharToMultiByte(CP_UTF8, 0, symbolInfo->Name, -1, sobj->tempPath1, (int)kCountOf(sobj->tempPath1), kNULL, kNULL) != 0)
{
kTest(kString_Setf(line, "%s", sobj->tempPath1));
symStatus = SymGetLineFromAddrW64(sobj->service, functionAddress, &displacement, lineInfo);
if (symStatus)
{
kTest(xkPath_NativeWideToNormalizedWin(lineInfo->FileName, sobj->tempPath1, kCountOf(sobj->tempPath1)));
kTest(kPath_FileName(sobj->tempPath1, sobj->tempPath2, kCountOf(sobj->tempPath2)));
kTest(kString_Addf(line, " [%s, line %u]", sobj->tempPath2, lineInfo->LineNumber));
}
}
}
if (kString_Length(line) == 0)
{
xkSymbolInfo_FormatUnknown(function, line);
}
kTest(kMap_AddT(sobj->cache, &function, &line));
}
kShareRef(description, line);
}
kCatchEx(&status)
{
kObject_Destroy(line);
kEndCatchEx(status);
}
kFinallyEx
{
xkSymbolInfo_Unlock();
kEndFinallyEx();
}
return kOK;
}
#elif defined(K_DEBUG) && defined(K_GCC) && defined(K_POSIX)
#include <execinfo.h>
kFx(kStatus) xkSymbolInfo_InitStatic()
{
kStaticObj(kSymbolInfo);
kStatus status;
sobj->alloc = kAlloc_System();
kTry
{
kTest(kLock_ConstructEx(&sobj->lock, xkLOCK_OPTION_PRIORITY_INHERITANCE, sobj->alloc));
kTest(kMap_Construct(&sobj->cache, kTypeOf(kPointer), kTypeOf(kString), 0, sobj->alloc));
}
kCatch(&status)
{
xkSymbolInfo_ReleaseStatic();
kEndCatch(status);
}
return kOK;
}
kFx(kStatus) xkSymbolInfo_ReleaseStatic()
{
kStaticObj(kSymbolInfo);
kCheck(kObject_Dispose(sobj->cache));
kCheck(kObject_Destroy(sobj->lock));
return kOK;
}
kFx(kStatus) kSymbolInfo_DescribeFunction(kPointer function, kString* description)
{
kStaticObj(kSymbolInfo);
kChar** symbolInfo = kNULL;
kString line = kNULL;
kStatus status;
kCheckTrue(!kIsNull(sobj->cache), kERROR_UNIMPLEMENTED);
xkSymbolInfo_Lock();
kTry
{
if (!kSuccess(kMap_FindT(sobj->cache, &function, &line)))
{
kTest(kString_Construct(&line, kNULL, sobj->alloc));
if (!kIsNull(symbolInfo = backtrace_symbols(&function, 1)))
{
kTest(kString_Set(line, symbolInfo[0]));
}
if (kString_Length(line) == 0)
{
xkSymbolInfo_FormatUnknown(function, line);
}
kTest(kMap_AddT(sobj->cache, &function, &line));
}
kShareRef(description, line);
}
kCatchEx(&status)
{
kObject_Destroy(line);
kEndCatchEx(status);
}
kFinallyEx
{
free(symbolInfo);
xkSymbolInfo_Unlock();
kEndFinallyEx();
}
return kOK;
}
#else
kFx(kStatus) xkSymbolInfo_InitStatic()
{
return kOK;
}
kFx(kStatus) xkSymbolInfo_ReleaseStatic()
{
return kOK;
}
kFx(kStatus) kSymbolInfo_DescribeFunction(kPointer function, kString* description)
{
return kERROR_UNIMPLEMENTED;
}
#endif