+ DWORD64 dwAddr = (DWORD64)(uintptr_t)addr;
+ HANDLE hProcess = GetCurrentProcess();
+
+ /* General purpose buffer, to back pSymbol and other temporary stuff.
+ * Must not be too memory hungry here to avoid stack overflows.
+ */
+ CHAR buffer[512];
+
+ PSYMBOL_INFO pSymbol = (PSYMBOL_INFO) buffer;
+ DWORD64 dwDisplacement = 0; /* Displacement of the input address, relative to the start of the symbol */
+ DWORD dwLineDisplacement = 0;
+ IMAGEHLP_LINE64 Line;
+
+ memset(pSymbol, 0, sizeof *pSymbol);
+ pSymbol->SizeOfStruct = sizeof buffer;
+ pSymbol->MaxNameLen = sizeof buffer - offsetof(SYMBOL_INFO, Name);
+
+ if (!g_bSymInitialized) {
+ j_SymSetOptions(/* SYMOPT_UNDNAME | */ SYMOPT_LOAD_LINES);
+ if (j_SymInitialize(hProcess, NULL, TRUE)) {
+ g_bSymInitialized = TRUE;
+ }
+ }
+
+ /* Lookup symbol name */
+ if (!g_bSymInitialized ||
+ !j_SymFromAddr(hProcess, dwAddr, &dwDisplacement, pSymbol)) {
+ /*
+ * We couldn't obtain symbol information. At least tell which module the address belongs.
+ */
+
+ HMODULE hModule = NULL;
+
+ if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ (LPCTSTR)addr,
+ &hModule)) {
+ return FALSE;
+ }
+
+ if (GetModuleFileNameA(hModule, buffer, sizeof buffer) == sizeof buffer) {
+ return FALSE;
+ }
+ util_snprintf(buf, size, "%p at %s+0x%lx",
+ addr, buffer,
+ (unsigned long)((uintptr_t)addr - (uintptr_t)hModule));
+
+ return TRUE;
+ }
+
+ /*
+ * Try to get filename and line number.
+ */
+ memset(&Line, 0, sizeof Line);
+ Line.SizeOfStruct = sizeof Line;
+ if (!j_SymGetLineFromAddr64(hProcess, dwAddr, &dwLineDisplacement, &Line)) {
+ Line.FileName = NULL;
+ }
+
+ if (Line.FileName) {
+ util_snprintf(buf, size, "%s at %s:%lu", pSymbol->Name, Line.FileName, Line.LineNumber);
+ } else {
+ util_snprintf(buf, size, "%s", pSymbol->Name);
+ }
+
+ return TRUE;