| // 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/utils.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 |