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/linux/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
17using namespace lldb;
18using namespace lldb_private;
19using namespace process_linux;
20using namespace llvm;
21
22Expected<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
33Expected<std::vector<cpu_id_t>>
34lldb_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
55llvm::Expected<llvm::ArrayRef<cpu_id_t>>
56lldb_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
74llvm::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

source code of lldb/source/Plugins/Process/Linux/Procfs.cpp