| 1 | //===-- Procfs.cpp --------------------------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "Procfs.h" |
| 10 | #include "lldb/Host/posix/Support.h" |
| 11 | #include "llvm/ADT/StringExtras.h" |
| 12 | #include "llvm/Support/Error.h" |
| 13 | #include "llvm/Support/MemoryBuffer.h" |
| 14 | #include "llvm/Support/Threading.h" |
| 15 | #include <optional> |
| 16 | |
| 17 | using namespace lldb; |
| 18 | using namespace lldb_private; |
| 19 | using namespace process_linux; |
| 20 | using namespace llvm; |
| 21 | |
| 22 | Expected<ArrayRef<uint8_t>> lldb_private::process_linux::GetProcfsCpuInfo() { |
| 23 | static ErrorOr<std::unique_ptr<MemoryBuffer>> cpu_info_or_err = |
| 24 | getProcFile(file: "cpuinfo" ); |
| 25 | |
| 26 | if (!*cpu_info_or_err) |
| 27 | cpu_info_or_err.getError(); |
| 28 | |
| 29 | MemoryBuffer &buffer = **cpu_info_or_err; |
| 30 | return arrayRefFromStringRef(Input: buffer.getBuffer()); |
| 31 | } |
| 32 | |
| 33 | Expected<std::vector<cpu_id_t>> |
| 34 | lldb_private::process_linux::GetAvailableLogicalCoreIDs(StringRef cpuinfo) { |
| 35 | SmallVector<StringRef, 8> lines; |
| 36 | cpuinfo.split(A&: lines, Separator: "\n" , /*MaxSplit=*/-1, /*KeepEmpty=*/false); |
| 37 | std::vector<cpu_id_t> logical_cores; |
| 38 | |
| 39 | for (StringRef line : lines) { |
| 40 | std::pair<StringRef, StringRef> key_value = line.split(Separator: ':'); |
| 41 | auto key = key_value.first.trim(); |
| 42 | auto val = key_value.second.trim(); |
| 43 | if (key == "processor" ) { |
| 44 | cpu_id_t processor; |
| 45 | if (val.getAsInteger(Radix: 10, Result&: processor)) |
| 46 | return createStringError( |
| 47 | EC: inconvertibleErrorCode(), |
| 48 | Fmt: "Failed parsing the /proc/cpuinfo line entry: %s" , Vals: line.data()); |
| 49 | logical_cores.push_back(x: processor); |
| 50 | } |
| 51 | } |
| 52 | return logical_cores; |
| 53 | } |
| 54 | |
| 55 | llvm::Expected<llvm::ArrayRef<cpu_id_t>> |
| 56 | lldb_private::process_linux::GetAvailableLogicalCoreIDs() { |
| 57 | static std::optional<std::vector<cpu_id_t>> logical_cores_ids; |
| 58 | if (!logical_cores_ids) { |
| 59 | // We find the actual list of core ids by parsing /proc/cpuinfo |
| 60 | Expected<ArrayRef<uint8_t>> cpuinfo = GetProcfsCpuInfo(); |
| 61 | if (!cpuinfo) |
| 62 | return cpuinfo.takeError(); |
| 63 | |
| 64 | Expected<std::vector<cpu_id_t>> cpu_ids = GetAvailableLogicalCoreIDs( |
| 65 | cpuinfo: StringRef(reinterpret_cast<const char *>(cpuinfo->data()))); |
| 66 | if (!cpu_ids) |
| 67 | return cpu_ids.takeError(); |
| 68 | |
| 69 | logical_cores_ids.emplace(args: std::move(*cpu_ids)); |
| 70 | } |
| 71 | return *logical_cores_ids; |
| 72 | } |
| 73 | |
| 74 | llvm::Expected<int> lldb_private::process_linux::GetPtraceScope() { |
| 75 | ErrorOr<std::unique_ptr<MemoryBuffer>> ptrace_scope_file = |
| 76 | getProcFile(file: "sys/kernel/yama/ptrace_scope" ); |
| 77 | if (!ptrace_scope_file) |
| 78 | return errorCodeToError(EC: ptrace_scope_file.getError()); |
| 79 | // The contents should be something like "1\n". Trim it so we get "1". |
| 80 | StringRef buffer = (*ptrace_scope_file)->getBuffer().trim(); |
| 81 | int ptrace_scope_value; |
| 82 | if (buffer.getAsInteger(Radix: 10, Result&: ptrace_scope_value)) { |
| 83 | return createStringError(EC: inconvertibleErrorCode(), |
| 84 | Fmt: "Invalid ptrace_scope value: '%s'" , Vals: buffer.data()); |
| 85 | } |
| 86 | return ptrace_scope_value; |
| 87 | } |
| 88 | |