| // Copyright 2022 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "src/developer/process_explorer/process_data.h" | |
| #include <unordered_map> | |
| #include "third_party/rapidjson/include/rapidjson/document.h" | |
| #include "third_party/rapidjson/include/rapidjson/rapidjson.h" | |
| #include "third_party/rapidjson/include/rapidjson/stringbuffer.h" | |
| #include "third_party/rapidjson/include/rapidjson/writer.h" | |
| namespace process_explorer { | |
| std::string WriteProcessesDataAsJson(std::vector<Process> processes_data) { | |
| rapidjson::Document json_document; | |
| json_document.SetObject(); | |
| auto& allocator = json_document.GetAllocator(); | |
| rapidjson::Value processes_json(rapidjson::kArrayType); | |
| processes_json.Reserve((unsigned int)processes_data.size(), allocator); | |
| for (const auto& process : processes_data) { | |
| rapidjson::Value process_objects_json(rapidjson::kArrayType); | |
| process_objects_json.Reserve((unsigned int)process.objects.size(), allocator); | |
| for (const auto& object : process.objects) { | |
| rapidjson::Value object_json(rapidjson::kObjectType); | |
| object_json.AddMember("object_type", object.object_type, allocator) | |
| .AddMember("koid", object.koid, allocator) | |
| .AddMember("related_koid", object.related_koid, allocator) | |
| .AddMember("peer_owner_koid", object.peer_owner_koid, allocator); | |
| process_objects_json.PushBack(object_json, allocator); | |
| } | |
| rapidjson::Value process_name(rapidjson::kObjectType); | |
| const std::string s(process.name); | |
| process_name.SetString(s.c_str(), static_cast<rapidjson::SizeType>(s.length()), allocator); | |
| rapidjson::Value process_json(rapidjson::kObjectType); | |
| process_json.AddMember("koid", process.koid, allocator) | |
| .AddMember("name", process_name, allocator) | |
| .AddMember("objects", process_objects_json, allocator); | |
| processes_json.PushBack(process_json, allocator); | |
| } | |
| json_document.AddMember("Processes", processes_json, allocator); | |
| rapidjson::StringBuffer buffer; | |
| buffer.Clear(); | |
| rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); | |
| json_document.Accept(writer); | |
| return std::string(buffer.GetString(), buffer.GetSize()); | |
| } | |
| zx_status_t GetHandles(zx::unowned_process process, std::vector<zx_info_handle_extended_t>* out) { | |
| size_t avail = 8; | |
| while (true) { | |
| out->resize(avail); | |
| auto size = avail * sizeof(zx_info_handle_extended_t); | |
| size_t actual = 0; | |
| if (auto status = process->get_info(ZX_INFO_HANDLE_TABLE, out->data(), size, &actual, &avail); | |
| status != ZX_OK) { | |
| return status; | |
| } | |
| if (actual < avail) { | |
| avail *= 2u; | |
| continue; | |
| } | |
| out->resize(actual); | |
| return ZX_OK; | |
| } | |
| } | |
| void FillPeerOwnerKoid(std::vector<Process>& processes_data) { | |
| std::unordered_map<zx_koid_t, zx_koid_t> object_to_process; | |
| for (const Process& process : processes_data) { | |
| for (const KernelObject& object : process.objects) { | |
| if (object.related_koid != 0) { | |
| object_to_process[object.related_koid] = process.koid; | |
| } | |
| } | |
| } | |
| for (Process& process : processes_data) { | |
| for (KernelObject& object : process.objects) { | |
| if (object.related_koid != 0) { | |
| if (object_to_process.find(object.koid) == object_to_process.end()) | |
| continue; | |
| object.peer_owner_koid = object_to_process[object.koid]; | |
| } | |
| } | |
| } | |
| } | |
| } // namespace process_explorer |