|
30 | 30 |
|
31 | 31 | #endif // __POSIX__
|
32 | 32 |
|
| 33 | +#if defined(__linux__) || defined(__sun) |
| 34 | +#include <link.h> |
| 35 | +#endif // (__linux__) || defined(__sun) |
| 36 | + |
| 37 | +#ifdef __APPLE__ |
| 38 | +#include <mach-o/dyld.h> // _dyld_get_image_name() |
| 39 | +#endif // __APPLE__ |
| 40 | + |
| 41 | +#ifdef _AIX |
| 42 | +#include <sys/ldr.h> // ld_info structure |
| 43 | +#endif // _AIX |
| 44 | + |
| 45 | +#ifdef _WIN32 |
| 46 | +#include <Lm.h> |
| 47 | +#include <Windows.h> |
| 48 | +#include <dbghelp.h> |
| 49 | +#include <process.h> |
| 50 | +#include <psapi.h> |
| 51 | +#include <tchar.h> |
| 52 | +#endif // _WIN32 |
| 53 | + |
33 | 54 | namespace node {
|
34 | 55 |
|
35 | 56 | #ifdef __POSIX__
|
@@ -299,6 +320,108 @@ void CheckedUvLoopClose(uv_loop_t* loop) {
|
299 | 320 | CHECK(0 && "uv_loop_close() while having open handles");
|
300 | 321 | }
|
301 | 322 |
|
| 323 | +std::vector<std::string> NativeSymbolDebuggingContext::GetLoadedLibraries() { |
| 324 | + std::vector<std::string> list; |
| 325 | +#ifdef __linux__ |
| 326 | + dl_iterate_phdr( |
| 327 | + [](struct dl_phdr_info* info, size_t size, void* data) { |
| 328 | + auto list = static_cast<std::vector<std::string>*>(data); |
| 329 | + if (*info->dlpi_name != '\0') { |
| 330 | + list->push_back(info->dlpi_name); |
| 331 | + } |
| 332 | + return 0; |
| 333 | + }, |
| 334 | + &list); |
| 335 | +#elif __APPLE__ |
| 336 | + uint32_t i = 0; |
| 337 | + for (const char* name = _dyld_get_image_name(i); name != nullptr; |
| 338 | + name = _dyld_get_image_name(++i)) { |
| 339 | + list.push_back(name); |
| 340 | + } |
| 341 | + |
| 342 | +#elif _AIX |
| 343 | + // We can't tell in advance how large the buffer needs to be. |
| 344 | + // Retry until we reach too large a size (1Mb). |
| 345 | + const unsigned int kBufferGrowStep = 4096; |
| 346 | + MallocedBuffer<char> buffer(kBufferGrowStep); |
| 347 | + int rc = -1; |
| 348 | + do { |
| 349 | + rc = loadquery(L_GETINFO, buffer.data, buffer.size); |
| 350 | + if (rc == 0) break; |
| 351 | + buffer = MallocedBuffer<char>(buffer.size + kBufferGrowStep); |
| 352 | + } while (buffer.size < 1024 * 1024); |
| 353 | + |
| 354 | + if (rc == 0) { |
| 355 | + char* buf = buffer.data; |
| 356 | + ld_info* cur_info = nullptr; |
| 357 | + do { |
| 358 | + std::ostringstream str; |
| 359 | + cur_info = reinterpret_cast<ld_info*>(buf); |
| 360 | + char* member_name = cur_info->ldinfo_filename + |
| 361 | + strlen(cur_info->ldinfo_filename) + 1; |
| 362 | + if (*member_name != '\0') { |
| 363 | + str << cur_info->ldinfo_filename << "(" << member_name << ")"; |
| 364 | + list.push_back(str.str()); |
| 365 | + str.str(""); |
| 366 | + } else { |
| 367 | + list.push_back(cur_info->ldinfo_filename); |
| 368 | + } |
| 369 | + buf += cur_info->ldinfo_next; |
| 370 | + } while (cur_info->ldinfo_next != 0); |
| 371 | + } |
| 372 | +#elif __sun |
| 373 | + Link_map* p; |
| 374 | + |
| 375 | + if (dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &p) != -1) { |
| 376 | + for (Link_map* l = p; l != nullptr; l = l->l_next) { |
| 377 | + list.push_back(l->l_name); |
| 378 | + } |
| 379 | + } |
| 380 | + |
| 381 | +#elif _WIN32 |
| 382 | + // Windows implementation - get a handle to the process. |
| 383 | + HANDLE process_handle = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, |
| 384 | + FALSE, GetCurrentProcessId()); |
| 385 | + if (process_handle == nullptr) { |
| 386 | + // Cannot proceed, return an empty list. |
| 387 | + return list; |
| 388 | + } |
| 389 | + // Get a list of all the modules in this process |
| 390 | + DWORD size_1 = 0; |
| 391 | + DWORD size_2 = 0; |
| 392 | + // First call to get the size of module array needed |
| 393 | + if (EnumProcessModules(process_handle, nullptr, 0, &size_1)) { |
| 394 | + MallocedBuffer<HMODULE> modules(size_1); |
| 395 | + |
| 396 | + // Second call to populate the module array |
| 397 | + if (EnumProcessModules(process_handle, modules.data, size_1, &size_2)) { |
| 398 | + for (DWORD i = 0; |
| 399 | + i < (size_1 / sizeof(HMODULE)) && i < (size_2 / sizeof(HMODULE)); |
| 400 | + i++) { |
| 401 | + WCHAR module_name[MAX_PATH]; |
| 402 | + // Obtain and report the full pathname for each module |
| 403 | + if (GetModuleFileNameExW(process_handle, |
| 404 | + modules.data[i], |
| 405 | + module_name, |
| 406 | + arraysize(module_name) / sizeof(WCHAR))) { |
| 407 | + DWORD size = WideCharToMultiByte( |
| 408 | + CP_UTF8, 0, module_name, -1, nullptr, 0, nullptr, nullptr); |
| 409 | + char* str = new char[size]; |
| 410 | + WideCharToMultiByte( |
| 411 | + CP_UTF8, 0, module_name, -1, str, size, nullptr, nullptr); |
| 412 | + list.push_back(str); |
| 413 | + } |
| 414 | + } |
| 415 | + } |
| 416 | + } |
| 417 | + |
| 418 | + // Release the handle to the process. |
| 419 | + CloseHandle(process_handle); |
| 420 | +#endif |
| 421 | + return list; |
| 422 | +} |
| 423 | + |
| 424 | + |
302 | 425 | } // namespace node
|
303 | 426 |
|
304 | 427 | extern "C" void __DumpBacktrace(FILE* fp) {
|
|
0 commit comments