[PATCH] D129837: [sanitizer_common] Several Solaris procmaps fixes

Rainer Orth via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 14 23:36:47 PDT 2022


ro created this revision.
ro added a reviewer: vitalybuka.
ro added a project: Sanitizers.
Herald added subscribers: Enna1, fedor.sergeev, jyknight.
Herald added a project: All.
ro requested review of this revision.
Herald added a subscriber: Sanitizers.

Since the introduction of GoogleTest sharding in D122251 <https://reviews.llvm.org/D122251>, some of the Solaris sanitizer tests have been running extremly long (up to an hour) while they took mere seconds before.  Initial investigation suggests that massive lock contention in Solaris procfs is involved here.

However, there's an easy way to somewhat reduce the impact: while the current `ReadProcMaps` uses `ReadFileToBuffer` to read `/proc/self/xmap`, that function primarily caters to Linux procfs reporting file sizes of 0 while the size on Solaris is accurate.  This patch makes use of that, reducing the number of syscalls involved and reducing the runtime of affected tests by a factor of 4.

Besides, it handles shared mappings and doesn't call `readlink` for unnamed map entries.

Tested on `sparcv9-sun-solaris2.11` and `amd64-pc-solaris2.11`.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D129837

Files:
  compiler-rt/lib/sanitizer_common/sanitizer_procmaps_solaris.cpp


Index: compiler-rt/lib/sanitizer_common/sanitizer_procmaps_solaris.cpp
===================================================================
--- compiler-rt/lib/sanitizer_common/sanitizer_procmaps_solaris.cpp
+++ compiler-rt/lib/sanitizer_common/sanitizer_procmaps_solaris.cpp
@@ -9,25 +9,32 @@
 // Information about the process mappings (Solaris-specific parts).
 //===----------------------------------------------------------------------===//
 
-// Before Solaris 11.4, <procfs.h> doesn't work in a largefile environment.
-#undef _FILE_OFFSET_BITS
 #include "sanitizer_platform.h"
 #if SANITIZER_SOLARIS
-#include "sanitizer_common.h"
-#include "sanitizer_procmaps.h"
+#  include <fcntl.h>
+#  include <limits.h>
+#  include <procfs.h>
 
-#include <procfs.h>
-#include <limits.h>
+#  include "sanitizer_common.h"
+#  include "sanitizer_procmaps.h"
 
 namespace __sanitizer {
 
 void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
-  if (!ReadFileToBuffer("/proc/self/xmap", &proc_maps->data,
-                        &proc_maps->mmaped_size, &proc_maps->len)) {
-    proc_maps->data = nullptr;
-    proc_maps->mmaped_size = 0;
-    proc_maps->len = 0;
-  }
+  uptr fd = internal_open("/proc/self/xmap", O_RDONLY);
+  CHECK_NE(fd, -1);
+  uptr Size = internal_filesize(fd);
+  CHECK_GT(Size, 0);
+
+  // Allow for additional entries by following mmap.
+  size_t MmapedSize = Size * 4 / 3;
+  void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()");
+  Size = internal_read(fd, VmMap, MmapedSize);
+  CHECK_NE(Size, -1);
+  internal_close(fd);
+  proc_maps->data = (char *)VmMap;
+  proc_maps->mmaped_size = MmapedSize;
+  proc_maps->len = Size;
 }
 
 bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
@@ -49,21 +56,28 @@
     segment->protection |= kProtectionWrite;
   if ((xmapentry->pr_mflags & MA_EXEC) != 0)
     segment->protection |= kProtectionExecute;
+  if ((xmapentry->pr_mflags & MA_SHARED) != 0)
+    segment->protection |= kProtectionShared;
 
   if (segment->filename != NULL && segment->filename_size > 0) {
     char proc_path[PATH_MAX + 1];
 
-    internal_snprintf(proc_path, sizeof(proc_path), "/proc/self/path/%s",
-                      xmapentry->pr_mapname);
-    ssize_t sz = internal_readlink(proc_path, segment->filename,
-                                   segment->filename_size - 1);
+    // Avoid unnecessary readlink on unnamed entires.
+    if (xmapentry->pr_mapname[0] == '\0')
+      segment->filename[0] = '\0';
+    else {
+      internal_snprintf(proc_path, sizeof(proc_path), "/proc/self/path/%s",
+                        xmapentry->pr_mapname);
+      ssize_t sz = internal_readlink(proc_path, segment->filename,
+                                     segment->filename_size - 1);
 
-    // If readlink failed, the map is anonymous.
-    if (sz == -1) {
-      segment->filename[0] = '\0';
-    } else if ((size_t)sz < segment->filename_size)
-      // readlink doesn't NUL-terminate.
-      segment->filename[sz] = '\0';
+      // If readlink failed, the map is anonymous.
+      if (sz == -1)
+        segment->filename[0] = '\0';
+      else if ((size_t)sz < segment->filename_size)
+        // readlink doesn't NUL-terminate.
+        segment->filename[sz] = '\0';
+    }
   }
 
   data_.current += sizeof(prxmap_t);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D129837.444887.patch
Type: text/x-patch
Size: 3269 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220715/debd05e4/attachment.bin>


More information about the llvm-commits mailing list