|
36 | 36 | #include "JavaScriptCore/JSGlobalObjectDebuggable.h" |
37 | 37 | #include <JavaScriptCore/StackFrame.h> |
38 | 38 | #include <sys/stat.h> |
| 39 | +#include <unordered_set> |
| 40 | +#if OS(DARWIN) |
| 41 | +#include <mach-o/dyld.h> |
| 42 | +#endif |
39 | 43 | #include "ConsoleObject.h" |
40 | 44 | #include <JavaScriptCore/GetterSetter.h> |
41 | 45 | #include <JavaScriptCore/JSSet.h> |
@@ -2394,9 +2398,91 @@ static JSValue constructReportObjectComplete(VM& vm, Zig::GlobalObject* globalOb |
2394 | 2398 | #endif |
2395 | 2399 | #endif |
2396 | 2400 |
|
2397 | | - header->putDirect(vm, Identifier::fromString(vm, "cpus"_s), JSC::constructEmptyArray(globalObject, nullptr), 0); |
2398 | | - RETURN_IF_EXCEPTION(scope, {}); |
2399 | | - header->putDirect(vm, Identifier::fromString(vm, "networkInterfaces"_s), JSC::constructEmptyArray(globalObject, nullptr), 0); |
| 2401 | + // Use libuv to get CPU info |
| 2402 | + { |
| 2403 | + uv_cpu_info_t* cpu_infos; |
| 2404 | + int count; |
| 2405 | + if (uv_cpu_info(&cpu_infos, &count) == 0) { |
| 2406 | + JSC::JSArray* cpuArray = JSC::constructEmptyArray(globalObject, nullptr, count); |
| 2407 | + RETURN_IF_EXCEPTION(scope, {}); |
| 2408 | + |
| 2409 | + for (int i = 0; i < count; i++) { |
| 2410 | + JSC::JSObject* cpu = JSC::constructEmptyObject(globalObject); |
| 2411 | + cpu->putDirect(vm, JSC::Identifier::fromString(vm, "model"_s), JSC::jsString(vm, String::fromUTF8(cpu_infos[i].model)), 0); |
| 2412 | + cpu->putDirect(vm, JSC::Identifier::fromString(vm, "speed"_s), JSC::jsNumber(cpu_infos[i].speed), 0); |
| 2413 | + |
| 2414 | + JSC::JSObject* times = JSC::constructEmptyObject(globalObject); |
| 2415 | + times->putDirect(vm, JSC::Identifier::fromString(vm, "user"_s), JSC::jsNumber(cpu_infos[i].cpu_times.user), 0); |
| 2416 | + times->putDirect(vm, JSC::Identifier::fromString(vm, "nice"_s), JSC::jsNumber(cpu_infos[i].cpu_times.nice), 0); |
| 2417 | + times->putDirect(vm, JSC::Identifier::fromString(vm, "sys"_s), JSC::jsNumber(cpu_infos[i].cpu_times.sys), 0); |
| 2418 | + times->putDirect(vm, JSC::Identifier::fromString(vm, "idle"_s), JSC::jsNumber(cpu_infos[i].cpu_times.idle), 0); |
| 2419 | + times->putDirect(vm, JSC::Identifier::fromString(vm, "irq"_s), JSC::jsNumber(cpu_infos[i].cpu_times.irq), 0); |
| 2420 | + |
| 2421 | + cpu->putDirect(vm, JSC::Identifier::fromString(vm, "times"_s), times, 0); |
| 2422 | + cpuArray->putDirectIndex(globalObject, i, cpu); |
| 2423 | + } |
| 2424 | + header->putDirect(vm, Identifier::fromString(vm, "cpus"_s), cpuArray, 0); |
| 2425 | + uv_free_cpu_info(cpu_infos, count); |
| 2426 | + } else { |
| 2427 | + header->putDirect(vm, Identifier::fromString(vm, "cpus"_s), JSC::constructEmptyArray(globalObject, nullptr), 0); |
| 2428 | + } |
| 2429 | + RETURN_IF_EXCEPTION(scope, {}); |
| 2430 | + } |
| 2431 | + |
| 2432 | + // Use libuv to get network interfaces |
| 2433 | + { |
| 2434 | + uv_interface_address_t* interfaces; |
| 2435 | + int count; |
| 2436 | + if (uv_interface_addresses(&interfaces, &count) == 0) { |
| 2437 | + JSC::JSArray* interfacesArray = JSC::constructEmptyArray(globalObject, nullptr, count); |
| 2438 | + RETURN_IF_EXCEPTION(scope, {}); |
| 2439 | + |
| 2440 | + for (int i = 0; i < count; i++) { |
| 2441 | + JSC::JSObject* iface = JSC::constructEmptyObject(globalObject); |
| 2442 | + iface->putDirect(vm, JSC::Identifier::fromString(vm, "name"_s), JSC::jsString(vm, String::fromUTF8(interfaces[i].name)), 0); |
| 2443 | + iface->putDirect(vm, JSC::Identifier::fromString(vm, "internal"_s), JSC::jsBoolean(interfaces[i].is_internal), 0); |
| 2444 | + |
| 2445 | + char addr[INET6_ADDRSTRLEN]; |
| 2446 | + if (interfaces[i].address.address4.sin_family == AF_INET) { |
| 2447 | + uv_inet_ntop(AF_INET, &interfaces[i].address.address4.sin_addr, addr, sizeof(addr)); |
| 2448 | + iface->putDirect(vm, JSC::Identifier::fromString(vm, "address"_s), JSC::jsString(vm, String::fromUTF8(addr)), 0); |
| 2449 | + |
| 2450 | + char netmask[INET_ADDRSTRLEN]; |
| 2451 | + uv_inet_ntop(AF_INET, &interfaces[i].netmask.netmask4.sin_addr, netmask, sizeof(netmask)); |
| 2452 | + iface->putDirect(vm, JSC::Identifier::fromString(vm, "netmask"_s), JSC::jsString(vm, String::fromUTF8(netmask)), 0); |
| 2453 | + |
| 2454 | + iface->putDirect(vm, JSC::Identifier::fromString(vm, "family"_s), JSC::jsString(vm, String::fromLatin1("IPv4")), 0); |
| 2455 | + } else if (interfaces[i].address.address6.sin6_family == AF_INET6) { |
| 2456 | + uv_inet_ntop(AF_INET6, &interfaces[i].address.address6.sin6_addr, addr, sizeof(addr)); |
| 2457 | + iface->putDirect(vm, JSC::Identifier::fromString(vm, "address"_s), JSC::jsString(vm, String::fromUTF8(addr)), 0); |
| 2458 | + |
| 2459 | + char netmask[INET6_ADDRSTRLEN]; |
| 2460 | + uv_inet_ntop(AF_INET6, &interfaces[i].netmask.netmask6.sin6_addr, netmask, sizeof(netmask)); |
| 2461 | + iface->putDirect(vm, JSC::Identifier::fromString(vm, "netmask"_s), JSC::jsString(vm, String::fromUTF8(netmask)), 0); |
| 2462 | + |
| 2463 | + iface->putDirect(vm, JSC::Identifier::fromString(vm, "family"_s), JSC::jsString(vm, String::fromLatin1("IPv6")), 0); |
| 2464 | + iface->putDirect(vm, JSC::Identifier::fromString(vm, "scopeid"_s), JSC::jsNumber(interfaces[i].address.address6.sin6_scope_id), 0); |
| 2465 | + } |
| 2466 | + |
| 2467 | + // MAC address |
| 2468 | + char mac[18]; |
| 2469 | + snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x", |
| 2470 | + static_cast<unsigned char>(interfaces[i].phys_addr[0]), |
| 2471 | + static_cast<unsigned char>(interfaces[i].phys_addr[1]), |
| 2472 | + static_cast<unsigned char>(interfaces[i].phys_addr[2]), |
| 2473 | + static_cast<unsigned char>(interfaces[i].phys_addr[3]), |
| 2474 | + static_cast<unsigned char>(interfaces[i].phys_addr[4]), |
| 2475 | + static_cast<unsigned char>(interfaces[i].phys_addr[5])); |
| 2476 | + iface->putDirect(vm, JSC::Identifier::fromString(vm, "mac"_s), JSC::jsString(vm, String::fromUTF8(mac)), 0); |
| 2477 | + |
| 2478 | + interfacesArray->putDirectIndex(globalObject, i, iface); |
| 2479 | + } |
| 2480 | + header->putDirect(vm, Identifier::fromString(vm, "networkInterfaces"_s), interfacesArray, 0); |
| 2481 | + uv_free_interface_addresses(interfaces, count); |
| 2482 | + } else { |
| 2483 | + header->putDirect(vm, Identifier::fromString(vm, "networkInterfaces"_s), JSC::constructEmptyArray(globalObject, nullptr), 0); |
| 2484 | + } |
| 2485 | + } |
2400 | 2486 | RETURN_IF_EXCEPTION(scope, {}); |
2401 | 2487 |
|
2402 | 2488 | return header; |
@@ -2425,6 +2511,10 @@ static JSValue constructReportObjectComplete(VM& vm, Zig::GlobalObject* globalOb |
2425 | 2511 | RETURN_IF_EXCEPTION(scope, {}); |
2426 | 2512 | heapSpaces->putDirect(vm, JSC::Identifier::fromString(vm, "shared_large_object_space"_s), JSC::constructEmptyObject(globalObject), 0); |
2427 | 2513 | RETURN_IF_EXCEPTION(scope, {}); |
| 2514 | + heapSpaces->putDirect(vm, JSC::Identifier::fromString(vm, "trusted_space"_s), JSC::constructEmptyObject(globalObject), 0); |
| 2515 | + RETURN_IF_EXCEPTION(scope, {}); |
| 2516 | + heapSpaces->putDirect(vm, JSC::Identifier::fromString(vm, "trusted_large_object_space"_s), JSC::constructEmptyObject(globalObject), 0); |
| 2517 | + RETURN_IF_EXCEPTION(scope, {}); |
2428 | 2518 |
|
2429 | 2519 | heap->putDirect(vm, JSC::Identifier::fromString(vm, "totalMemory"_s), JSC::jsNumber(WTF::ramSize()), 0); |
2430 | 2520 | heap->putDirect(vm, JSC::Identifier::fromString(vm, "executableMemory"_s), jsNumber(0), 0); |
@@ -2466,10 +2556,48 @@ static JSValue constructReportObjectComplete(VM& vm, Zig::GlobalObject* globalOb |
2466 | 2556 | }; |
2467 | 2557 |
|
2468 | 2558 | auto constructSharedObjects = [&]() -> JSC::JSValue { |
2469 | | - JSC::JSObject* sharedObjects = JSC::constructEmptyArray(globalObject, nullptr); |
| 2559 | + JSC::JSArray* sharedObjects = JSC::constructEmptyArray(globalObject, nullptr); |
2470 | 2560 | RETURN_IF_EXCEPTION(scope, {}); |
2471 | 2561 |
|
2472 | | - // TODO: |
| 2562 | +#if OS(LINUX) |
| 2563 | + // Read /proc/self/maps to find loaded shared objects |
| 2564 | + FILE* maps = fopen("/proc/self/maps", "r"); |
| 2565 | + if (maps) { |
| 2566 | + char line[1024]; |
| 2567 | + std::unordered_set<std::string> libraries; |
| 2568 | + while (fgets(line, sizeof(line), maps)) { |
| 2569 | + char path[512]; |
| 2570 | + if (sscanf(line, "%*s %*s %*s %*s %*s %511s", path) == 1) { |
| 2571 | + if (strstr(path, ".so") != nullptr && path[0] == '/') { |
| 2572 | + libraries.insert(path); |
| 2573 | + } |
| 2574 | + } |
| 2575 | + } |
| 2576 | + fclose(maps); |
| 2577 | + |
| 2578 | + int index = 0; |
| 2579 | + for (const auto& lib : libraries) { |
| 2580 | + sharedObjects->putDirectIndex(globalObject, index++, JSC::jsString(vm, String::fromUTF8(lib.c_str()))); |
| 2581 | + } |
| 2582 | + } |
| 2583 | +#elif OS(DARWIN) |
| 2584 | + // Use dyld to enumerate loaded images |
| 2585 | + uint32_t count = _dyld_image_count(); |
| 2586 | + for (uint32_t i = 0; i < count; i++) { |
| 2587 | + const char* name = _dyld_get_image_name(i); |
| 2588 | + if (name) { |
| 2589 | + sharedObjects->putDirectIndex(globalObject, i, JSC::jsString(vm, String::fromUTF8(name))); |
| 2590 | + } |
| 2591 | + } |
| 2592 | +#else |
| 2593 | + // For other platforms, at least add the main executable |
| 2594 | + char path[PATH_MAX]; |
| 2595 | + ssize_t len = readlink("/proc/self/exe", path, sizeof(path) - 1); |
| 2596 | + if (len != -1) { |
| 2597 | + path[len] = '\0'; |
| 2598 | + sharedObjects->putDirectIndex(globalObject, 0, JSC::jsString(vm, String::fromUTF8(path))); |
| 2599 | + } |
| 2600 | +#endif |
2473 | 2601 |
|
2474 | 2602 | return sharedObjects; |
2475 | 2603 | }; |
|
0 commit comments