25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "prims/jvm.h" |
26 #include "prims/jvm.h" |
27 #include "runtime/arguments.hpp" |
27 #include "runtime/arguments.hpp" |
28 #include "runtime/os.hpp" |
28 #include "runtime/os.hpp" |
29 #include "decoder_windows.hpp" |
29 #include "decoder_windows.hpp" |
|
30 #include "windbghelp.hpp" |
30 |
31 |
31 WindowsDecoder::WindowsDecoder() { |
32 WindowsDecoder::WindowsDecoder() { |
32 _dbghelp_handle = NULL; |
33 _can_decode_in_vm = true; |
33 _can_decode_in_vm = false; |
|
34 _pfnSymGetSymFromAddr64 = NULL; |
|
35 _pfnUndecorateSymbolName = NULL; |
|
36 #ifdef AMD64 |
|
37 _pfnStackWalk64 = NULL; |
|
38 _pfnSymFunctionTableAccess64 = NULL; |
|
39 _pfnSymGetModuleBase64 = NULL; |
|
40 #endif |
|
41 _decoder_status = no_error; |
34 _decoder_status = no_error; |
42 initialize(); |
35 initialize(); |
43 } |
36 } |
44 |
37 |
45 void WindowsDecoder::initialize() { |
38 void WindowsDecoder::initialize() { |
46 if (!has_error() && _dbghelp_handle == NULL) { |
39 if (!has_error()) { |
47 HMODULE handle = ::LoadLibrary("dbghelp.dll"); |
|
48 if (!handle) { |
|
49 _decoder_status = helper_not_found; |
|
50 return; |
|
51 } |
|
52 |
|
53 _dbghelp_handle = handle; |
|
54 |
|
55 pfn_SymSetOptions _pfnSymSetOptions = (pfn_SymSetOptions)::GetProcAddress(handle, "SymSetOptions"); |
|
56 pfn_SymInitialize _pfnSymInitialize = (pfn_SymInitialize)::GetProcAddress(handle, "SymInitialize"); |
|
57 _pfnSymGetSymFromAddr64 = (pfn_SymGetSymFromAddr64)::GetProcAddress(handle, "SymGetSymFromAddr64"); |
|
58 _pfnUndecorateSymbolName = (pfn_UndecorateSymbolName)::GetProcAddress(handle, "UnDecorateSymbolName"); |
|
59 |
|
60 if (_pfnSymSetOptions == NULL || _pfnSymInitialize == NULL || _pfnSymGetSymFromAddr64 == NULL) { |
|
61 uninitialize(); |
|
62 _decoder_status = helper_func_error; |
|
63 return; |
|
64 } |
|
65 |
|
66 #ifdef AMD64 |
|
67 _pfnStackWalk64 = (pfn_StackWalk64)::GetProcAddress(handle, "StackWalk64"); |
|
68 _pfnSymFunctionTableAccess64 = (pfn_SymFunctionTableAccess64)::GetProcAddress(handle, "SymFunctionTableAccess64"); |
|
69 _pfnSymGetModuleBase64 = (pfn_SymGetModuleBase64)::GetProcAddress(handle, "SymGetModuleBase64"); |
|
70 if (_pfnStackWalk64 == NULL || _pfnSymFunctionTableAccess64 == NULL || _pfnSymGetModuleBase64 == NULL) { |
|
71 // We can't call StackWalk64 to walk the stack, but we are still |
|
72 // able to decode the symbols. Let's limp on. |
|
73 _pfnStackWalk64 = NULL; |
|
74 _pfnSymFunctionTableAccess64 = NULL; |
|
75 _pfnSymGetModuleBase64 = NULL; |
|
76 } |
|
77 #endif |
|
78 |
|
79 HANDLE hProcess = ::GetCurrentProcess(); |
40 HANDLE hProcess = ::GetCurrentProcess(); |
80 _pfnSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS); |
41 WindowsDbgHelp::symSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS); |
81 if (!_pfnSymInitialize(hProcess, NULL, TRUE)) { |
42 if (!WindowsDbgHelp::symInitialize(hProcess, NULL, TRUE)) { |
82 _pfnSymGetSymFromAddr64 = NULL; |
|
83 _pfnUndecorateSymbolName = NULL; |
|
84 ::FreeLibrary(handle); |
|
85 _dbghelp_handle = NULL; |
|
86 _decoder_status = helper_init_error; |
43 _decoder_status = helper_init_error; |
87 return; |
44 return; |
88 } |
45 } |
89 |
46 |
90 // set pdb search paths |
47 // set pdb search paths |
91 pfn_SymSetSearchPath _pfn_SymSetSearchPath = |
48 char paths[MAX_PATH]; |
92 (pfn_SymSetSearchPath)::GetProcAddress(handle, "SymSetSearchPath"); |
49 int len = sizeof(paths); |
93 pfn_SymGetSearchPath _pfn_SymGetSearchPath = |
50 if (!WindowsDbgHelp::symGetSearchPath(hProcess, paths, len)) { |
94 (pfn_SymGetSearchPath)::GetProcAddress(handle, "SymGetSearchPath"); |
51 paths[0] = '\0'; |
95 if (_pfn_SymSetSearchPath != NULL && _pfn_SymGetSearchPath != NULL) { |
52 } else { |
96 char paths[MAX_PATH]; |
53 // available spaces in path buffer |
97 int len = sizeof(paths); |
54 len -= (int)strlen(paths); |
98 if (!_pfn_SymGetSearchPath(hProcess, paths, len)) { |
55 } |
99 paths[0] = '\0'; |
56 |
100 } else { |
57 char tmp_path[MAX_PATH]; |
101 // available spaces in path buffer |
58 DWORD dwSize; |
102 len -= (int)strlen(paths); |
59 HMODULE hJVM = ::GetModuleHandle("jvm.dll"); |
|
60 tmp_path[0] = '\0'; |
|
61 // append the path where jvm.dll is located |
|
62 if (hJVM != NULL && (dwSize = ::GetModuleFileName(hJVM, tmp_path, sizeof(tmp_path))) > 0) { |
|
63 while (dwSize > 0 && tmp_path[dwSize] != '\\') { |
|
64 dwSize --; |
103 } |
65 } |
104 |
66 |
105 char tmp_path[MAX_PATH]; |
67 tmp_path[dwSize] = '\0'; |
106 DWORD dwSize; |
|
107 HMODULE hJVM = ::GetModuleHandle("jvm.dll"); |
|
108 tmp_path[0] = '\0'; |
|
109 // append the path where jvm.dll is located |
|
110 if (hJVM != NULL && (dwSize = ::GetModuleFileName(hJVM, tmp_path, sizeof(tmp_path))) > 0) { |
|
111 while (dwSize > 0 && tmp_path[dwSize] != '\\') { |
|
112 dwSize --; |
|
113 } |
|
114 |
68 |
115 tmp_path[dwSize] = '\0'; |
69 if (dwSize > 0 && len > (int)dwSize + 1) { |
|
70 strncat(paths, os::path_separator(), 1); |
|
71 strncat(paths, tmp_path, dwSize); |
|
72 len -= dwSize + 1; |
|
73 } |
|
74 } |
116 |
75 |
117 if (dwSize > 0 && len > (int)dwSize + 1) { |
76 // append $JRE/bin. Arguments::get_java_home actually returns $JRE |
|
77 // path |
|
78 char *p = Arguments::get_java_home(); |
|
79 assert(p != NULL, "empty java home"); |
|
80 size_t java_home_len = strlen(p); |
|
81 if (len > (int)java_home_len + 5) { |
|
82 strncat(paths, os::path_separator(), 1); |
|
83 strncat(paths, p, java_home_len); |
|
84 strncat(paths, "\\bin", 4); |
|
85 len -= (int)(java_home_len + 5); |
|
86 } |
|
87 |
|
88 // append $JDK/bin path if it exists |
|
89 assert(java_home_len < MAX_PATH, "Invalid path length"); |
|
90 // assume $JRE is under $JDK, construct $JDK/bin path and |
|
91 // see if it exists or not |
|
92 if (strncmp(&p[java_home_len - 3], "jre", 3) == 0) { |
|
93 strncpy(tmp_path, p, java_home_len - 3); |
|
94 tmp_path[java_home_len - 3] = '\0'; |
|
95 strncat(tmp_path, "bin", 3); |
|
96 |
|
97 // if the directory exists |
|
98 DWORD dwAttrib = GetFileAttributes(tmp_path); |
|
99 if (dwAttrib != INVALID_FILE_ATTRIBUTES && |
|
100 (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) { |
|
101 // tmp_path should have the same length as java_home_len, since we only |
|
102 // replaced 'jre' with 'bin' |
|
103 if (len > (int)java_home_len + 1) { |
118 strncat(paths, os::path_separator(), 1); |
104 strncat(paths, os::path_separator(), 1); |
119 strncat(paths, tmp_path, dwSize); |
105 strncat(paths, tmp_path, java_home_len); |
120 len -= dwSize + 1; |
|
121 } |
106 } |
122 } |
107 } |
123 |
|
124 // append $JRE/bin. Arguments::get_java_home actually returns $JRE |
|
125 // path |
|
126 char *p = Arguments::get_java_home(); |
|
127 assert(p != NULL, "empty java home"); |
|
128 size_t java_home_len = strlen(p); |
|
129 if (len > (int)java_home_len + 5) { |
|
130 strncat(paths, os::path_separator(), 1); |
|
131 strncat(paths, p, java_home_len); |
|
132 strncat(paths, "\\bin", 4); |
|
133 len -= (int)(java_home_len + 5); |
|
134 } |
|
135 |
|
136 // append $JDK/bin path if it exists |
|
137 assert(java_home_len < MAX_PATH, "Invalid path length"); |
|
138 // assume $JRE is under $JDK, construct $JDK/bin path and |
|
139 // see if it exists or not |
|
140 if (strncmp(&p[java_home_len - 3], "jre", 3) == 0) { |
|
141 strncpy(tmp_path, p, java_home_len - 3); |
|
142 tmp_path[java_home_len - 3] = '\0'; |
|
143 strncat(tmp_path, "bin", 3); |
|
144 |
|
145 // if the directory exists |
|
146 DWORD dwAttrib = GetFileAttributes(tmp_path); |
|
147 if (dwAttrib != INVALID_FILE_ATTRIBUTES && |
|
148 (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) { |
|
149 // tmp_path should have the same length as java_home_len, since we only |
|
150 // replaced 'jre' with 'bin' |
|
151 if (len > (int)java_home_len + 1) { |
|
152 strncat(paths, os::path_separator(), 1); |
|
153 strncat(paths, tmp_path, java_home_len); |
|
154 } |
|
155 } |
|
156 } |
|
157 |
|
158 _pfn_SymSetSearchPath(hProcess, paths); |
|
159 } |
108 } |
160 |
109 |
161 // find out if jvm.dll contains private symbols, by decoding |
110 WindowsDbgHelp::symSetSearchPath(hProcess, paths); |
162 // current function and comparing the result |
111 |
163 address addr = (address)Decoder::demangle; |
112 // find out if jvm.dll contains private symbols, by decoding |
164 char buf[MAX_PATH]; |
113 // current function and comparing the result |
165 if (decode(addr, buf, sizeof(buf), NULL, NULL, true /* demangle */)) { |
114 address addr = (address)Decoder::demangle; |
166 _can_decode_in_vm = !strcmp(buf, "Decoder::demangle"); |
115 char buf[MAX_PATH]; |
167 } |
116 if (decode(addr, buf, sizeof(buf), NULL, NULL, true /* demangle */)) { |
|
117 _can_decode_in_vm = !strcmp(buf, "Decoder::demangle"); |
|
118 } |
168 } |
119 } |
169 } |
120 } |
170 |
121 |
171 void WindowsDecoder::uninitialize() { |
122 void WindowsDecoder::uninitialize() {} |
172 _pfnSymGetSymFromAddr64 = NULL; |
|
173 _pfnUndecorateSymbolName = NULL; |
|
174 #ifdef AMD64 |
|
175 _pfnStackWalk64 = NULL; |
|
176 _pfnSymFunctionTableAccess64 = NULL; |
|
177 _pfnSymGetModuleBase64 = NULL; |
|
178 #endif |
|
179 if (_dbghelp_handle != NULL) { |
|
180 ::FreeLibrary(_dbghelp_handle); |
|
181 } |
|
182 _dbghelp_handle = NULL; |
|
183 } |
|
184 |
123 |
185 bool WindowsDecoder::can_decode_C_frame_in_vm() const { |
124 bool WindowsDecoder::can_decode_C_frame_in_vm() const { |
186 return (!has_error() && _can_decode_in_vm); |
125 return (!has_error() && _can_decode_in_vm); |
187 } |
126 } |
188 |
127 |
189 |
128 |
190 bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath, bool demangle_name) { |
129 bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath, bool demangle_name) { |
191 if (_pfnSymGetSymFromAddr64 != NULL) { |
130 if (!has_error()) { |
192 PIMAGEHLP_SYMBOL64 pSymbol; |
131 PIMAGEHLP_SYMBOL64 pSymbol; |
193 char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)]; |
132 char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)]; |
194 pSymbol = (PIMAGEHLP_SYMBOL64)symbolInfo; |
133 pSymbol = (PIMAGEHLP_SYMBOL64)symbolInfo; |
195 pSymbol->MaxNameLength = MAX_PATH; |
134 pSymbol->MaxNameLength = MAX_PATH; |
196 pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); |
135 pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); |
197 DWORD64 displacement; |
136 DWORD64 displacement; |
198 if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) { |
137 if (WindowsDbgHelp::symGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) { |
199 if (buf != NULL) { |
138 if (buf != NULL) { |
200 if (!(demangle_name && demangle(pSymbol->Name, buf, buflen))) { |
139 if (!(demangle_name && demangle(pSymbol->Name, buf, buflen))) { |
201 jio_snprintf(buf, buflen, "%s", pSymbol->Name); |
140 jio_snprintf(buf, buflen, "%s", pSymbol->Name); |
202 } |
141 } |
203 } |
142 } |