This is Unofficial EPICS BASE Doxygen Site
osdFindAddr.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (C) 2017 Freddie Akeroyd
3 * EPICS BASE is distributed subject to a Software License Agreement found
4 * in file LICENSE that is included with this distribution.
5 \*************************************************************************/
6 
7 #include <windows.h>
8 #include <dbghelp.h>
9 #include "epicsStackTracePvt.h"
10 #include "epicsStackTrace.h"
11 #include "epicsString.h"
12 #include "epicsStdio.h"
13 #include "gpHash.h"
14 
15 #define MAX_SYM_SIZE 255
16 
17 /*
18  * we cache a list of previously located symbols, currently just to
19  * avoid a memory leak in allocating sym_p->s_nam and not
20  * to save on a SymFromAddr() call. This was done in case libraries
21  * were dynamically unloaded/reloaded and the cached answer might not
22  * then be correct, but this may be over cautious.
23  */
24 static struct gphPvt* symbol_table;
25 
26 typedef struct
27 {
28  char* name;
29  void* value;
30  char* file;
31  char* fileAndLine;
32  size_t line;
33 } SymbolData;
34 
35 int epicsFindAddr(void *addr, epicsSymbol *sym_p)
36 {
37  static int first_call = 1;
38  static HANDLE process = NULL;
39  DWORD64 displacement64 = 0;
40  DWORD displacement = 0;
41  SYMBOL_INFO *symbol;
42  IMAGEHLP_LINE64 line;
43  GPHENTRY* symbol_entry;
44  SymbolData* symbol_data;
45  size_t len;
46  if (first_call)
47  {
48  SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS);
49  process = GetCurrentProcess();
50  SymInitialize(process, NULL, TRUE);
51  gphInitPvt(&symbol_table, 256); /* table size must be a power of 2 in range 256 to 65536 */
52  first_call = 0;
53  }
54  symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + (MAX_SYM_SIZE + 1) * sizeof(char), 1);
55  symbol->MaxNameLen = MAX_SYM_SIZE;
56  symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
57  if (!SymFromAddr(process, (DWORD64)addr, &displacement64, symbol))
58  {
59  sym_p->s_nam = 0;
60  sym_p->s_val = 0;
61  sym_p->f_nam = 0;
62  free(symbol);
63  return -1;
64  }
65  if ( (symbol_entry = gphFind(symbol_table, symbol->Name, addr)) != NULL )
66  {
67  symbol_data = (SymbolData*)symbol_entry->userPvt;
68  }
69  else
70  {
71  symbol_entry = gphAdd(symbol_table, symbol->Name, addr);
72  symbol_data = (SymbolData*)calloc(sizeof(SymbolData), 1);
73  symbol_data->name = strdup(symbol->Name);
74  symbol_data->value = (void*)symbol->Address;
75  line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
76  if (SymGetLineFromAddr64(process, (DWORD64)addr, &displacement, &line))
77  {
78  symbol_data->file = strdup(line.FileName);
79  symbol_data->line = line.LineNumber;
80  len = strlen(line.FileName) + 32; /* add enough for [line %lu] */
81  symbol_data->fileAndLine = calloc((len + 1) * sizeof(char), 1);
82  epicsSnprintf(symbol_data->fileAndLine, len, "%s[line %lu]", line.FileName, (unsigned long)line.LineNumber);
83  }
84  symbol_entry->userPvt = symbol_data;
85  }
86  sym_p->s_nam = symbol_data->name;
87  sym_p->s_val = symbol_data->value;
88  sym_p->f_nam = symbol_data->fileAndLine;
89  free(symbol);
90  return 0;
91 }
92 
94 {
95 #if defined(_MINGW)
96 /* 64bit MINGW can lookup DLL public symbols, 32bit cannot - but we need to be a dynamic build to have a DLL to lookup */
97 # if defined(_WIN64) && defined(EPICS_CALL_DLL)
99 # else
100  return 0; /* only able to print addresses */
101 # endif /* _WIN64 && EPICS_CALL_DLL */
102 #else
106 #endif /* _MINGW */
107 }
#define MAX_SYM_SIZE
Definition: osdFindAddr.c:15
#define EPICS_STACKTRACE_LCL_SYMBOLS
int epicsFindAddrGetFeatures(void)
Definition: osdFindAddr.c:37
bucket ** symbol_table
Definition: symtab.c:18
#define EPICS_STACKTRACE_GBL_SYMBOLS
char * strdup(const char *)
char * name
Definition: osdFindAddr.c:28
#define NULL
Definition: catime.c:38
LIBCOM_API void epicsStdCall gphInitPvt(struct gphPvt **ppvt, int tableSize)
Definition: gpHashLib.c:37
void * userPvt
Definition: gpHash.h:25
LIBCOM_API GPHENTRY *epicsStdCall gphFind(struct gphPvt *pvt, const char *name, void *pvtid)
Definition: gpHashLib.c:92
const char * f_nam
#define EPICS_STACKTRACE_DYN_SYMBOLS
char * line
Definition: reader.c:25
size_t line
Definition: osdFindAddr.c:32
int epicsFindAddr(void *addr, epicsSymbol *sym_p)
Definition: osdFindAddr.c:20
const char * s_nam
void * value
Definition: osdFindAddr.c:29
#define TRUE
Definition: dbDefs.h:27
char * fileAndLine
Definition: osdFindAddr.c:31
LIBCOM_API int epicsStdCall epicsSnprintf(char *str, size_t size, const char *format,...) EPICS_PRINTF_STYLE(3
LIBCOM_API GPHENTRY *epicsStdCall gphAdd(struct gphPvt *pvt, const char *name, void *pvtid)
Definition: gpHashLib.c:97
char * file
Definition: osdFindAddr.c:30