xref: /llvm-project/lldb/source/Plugins/Process/Linux/Procfs.cpp (revision 5551657b310b0f5f97b26288f87bc41a8050bf93)
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 
17 using namespace lldb;
18 using namespace lldb_private;
19 using namespace process_linux;
20 using namespace llvm;
21 
GetProcfsCpuInfo()22 Expected<ArrayRef<uint8_t>> lldb_private::process_linux::GetProcfsCpuInfo() {
23   static ErrorOr<std::unique_ptr<MemoryBuffer>> cpu_info_or_err =
24       getProcFile("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(buffer.getBuffer());
31 }
32 
33 Expected<std::vector<cpu_id_t>>
GetAvailableLogicalCoreIDs(StringRef cpuinfo)34 lldb_private::process_linux::GetAvailableLogicalCoreIDs(StringRef cpuinfo) {
35   SmallVector<StringRef, 8> lines;
36   cpuinfo.split(lines, "\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(':');
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(10, processor))
46         return createStringError(
47             inconvertibleErrorCode(),
48             "Failed parsing the /proc/cpuinfo line entry: %s", line.data());
49       logical_cores.push_back(processor);
50     }
51   }
52   return logical_cores;
53 }
54 
55 llvm::Expected<llvm::ArrayRef<cpu_id_t>>
GetAvailableLogicalCoreIDs()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         StringRef(reinterpret_cast<const char *>(cpuinfo->data())));
66     if (!cpu_ids)
67       return cpu_ids.takeError();
68 
69     logical_cores_ids.emplace(std::move(*cpu_ids));
70   }
71   return *logical_cores_ids;
72 }
73 
GetPtraceScope()74 llvm::Expected<int> lldb_private::process_linux::GetPtraceScope() {
75   ErrorOr<std::unique_ptr<MemoryBuffer>> ptrace_scope_file =
76       getProcFile("sys/kernel/yama/ptrace_scope");
77   if (!*ptrace_scope_file)
78     return errorCodeToError(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(10, ptrace_scope_value)) {
83     return createStringError(inconvertibleErrorCode(),
84                              "Invalid ptrace_scope value: '%s'", buffer.data());
85   }
86   return ptrace_scope_value;
87 }
88