[Lldb-commits] [lldb] [lldb] Add Populate Methods for ELFLinuxPrPsInfo and ELFLinuxPrStatus (PR #104109)

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Wed Aug 14 13:17:58 PDT 2024


================
@@ -394,6 +420,114 @@ Status ELFLinuxPrPsInfo::Parse(const DataExtractor &data,
   return error;
 }
 
+std::optional<ELFLinuxPrPsInfo>
+ELFLinuxPrPsInfo::Populate(const lldb::ProcessSP &process_sp) {
+  ELFLinuxPrPsInfo prpsinfo{};
+  prpsinfo.pr_pid = process_sp->GetID();
+  ProcessInstanceInfo info;
+  if (!process_sp->GetProcessInfo(info)) {
+    return std::nullopt;
+  }
+  prpsinfo.pr_nice = info.GetPriorityValue().value_or(0);
+  prpsinfo.pr_zomb = 0;
+  if (auto zombie_opt = info.IsZombie(); zombie_opt.value_or(false)) {
+    prpsinfo.pr_zomb = 1;
+  }
+  /**
+   * In the linux kernel this comes from:
+   * state = READ_ONCE(p->__state);
+   * i = state ? ffz(~state) + 1 : 0;
+   * psinfo->pr_sname = (i > 5) ? '.' : "RSDTZW"[i];
+   *
+   * So we replicate that here. From proc_pid_stats(5)
+   * R = Running
+   * S = Sleeping on uninterrutible wait
+   * D = Waiting on uninterruptable disk sleep
+   * T = Tracing stop
+   * Z = Zombie
+   * W = Paging
+   */
+  lldb::StateType process_state = process_sp->GetState();
+  switch (process_state) {
+  case lldb::StateType::eStateSuspended:
+    prpsinfo.pr_sname = 'S';
+    prpsinfo.pr_state = 1;
+    break;
+  case lldb::StateType::eStateStopped:
+    [[fallthrough]];
+  case lldb::StateType::eStateStepping:
+    prpsinfo.pr_sname = 'T';
+    prpsinfo.pr_state = 3;
+    break;
+  case lldb::StateType::eStateUnloaded:
+    [[fallthrough]];
+  case lldb::StateType::eStateRunning:
+    prpsinfo.pr_sname = 'R';
+    prpsinfo.pr_state = 0;
+    break;
+  default:
+    break;
+  }
+
+  /**
+   * pr_flags is left as 0. The values (in linux) are specific
+   * to the kernel. We recover them from the proc filesystem
+   * but don't put them in ProcessInfo because it would really
+   * become very linux specific and the utility here seems pretty
+   * dubious
+   */
+
+  if (info.EffectiveUserIDIsValid()) {
+    prpsinfo.pr_uid = info.GetUserID();
+  }
+  if (info.EffectiveGroupIDIsValid()) {
+    prpsinfo.pr_gid = info.GetGroupID();
+  }
+
+  if (info.ParentProcessIDIsValid()) {
+    prpsinfo.pr_ppid = info.GetParentProcessID();
+  }
+
+  if (info.ProcessGroupIDIsValid()) {
+    prpsinfo.pr_pgrp = info.GetProcessGroupID();
+  }
+
+  if (info.ProcessSessionIDIsValid()) {
+    prpsinfo.pr_sid = info.GetProcessSessionID();
+  }
+  constexpr size_t fname_len = std::extent_v<decltype(prpsinfo.pr_fname)>;
+  static_assert(fname_len > 0, "This should always be non zero");
+  const llvm::StringRef fname = info.GetNameAsStringRef();
+  auto fname_begin = fname.begin();
+  std::copy(fname_begin,
+            std::next(fname_begin, std::min(fname_len, fname.size())),
+            prpsinfo.pr_fname);
+  prpsinfo.pr_fname[fname_len - 1] = '\0';
+  auto args = info.GetArguments();
+  if (!args.empty()) {
+    constexpr size_t psargs_len = std::extent_v<decltype(prpsinfo.pr_psargs)>;
+    static_assert(psargs_len > 0, "This should always be non zero");
+    size_t i = psargs_len;
+    auto argentry_iterator = std::begin(args);
+    char *psargs = prpsinfo.pr_psargs;
+    while (i > 0 && argentry_iterator != args.end()) {
+      llvm::StringRef argentry = argentry_iterator->ref();
+      size_t len = std::min(i, argentry.size());
+      auto arg_iterator = std::begin(argentry);
+      std::copy(arg_iterator, std::next(arg_iterator, len), psargs);
+      i -= len;
+      psargs += len;
+      if (i > 0) {
+        *(psargs++) = ' ';
+        --i;
+      }
+      ++argentry_iterator;
+    }
----------------
labath wrote:

```suggestion
    auto argentry_iterator = std::begin(args);
    char *psargs = prpsinfo.pr_psargs;
    char *psargs_end = std::end(prpsinfo.pr_psargs);
    while (psargs < psargs_end && argentry_iterator != args.end()) {
      llvm::StringRef argentry = argentry_iterator->ref();
      size_t len = std::min(std::distance(psargs, psargs_end), argentry.size());
      auto arg_iterator = std::begin(argentry);
      psargs = std::copy_n(arg_iterator, len, psargs);
      if (psargs != psargs_end)
        *(psargs++) = ' ';
      ++argentry_iterator;
    }
```

I noticed you like iterators, so I've put in more of them. :)

https://github.com/llvm/llvm-project/pull/104109


More information about the lldb-commits mailing list