[compiler-rt] 74f6672 - [sanitizer_common] Several Solaris procmaps fixes

Rainer Orth via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 15 21:59:28 PDT 2022


Author: Rainer Orth
Date: 2022-07-16T06:59:00+02:00
New Revision: 74f6672e59d2cc9fdc95abfd28f527f00c808c07

URL: https://github.com/llvm/llvm-project/commit/74f6672e59d2cc9fdc95abfd28f527f00c808c07
DIFF: https://github.com/llvm/llvm-project/commit/74f6672e59d2cc9fdc95abfd28f527f00c808c07.diff

LOG: [sanitizer_common] Several Solaris procmaps fixes

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`.

Differential Revision: https://reviews.llvm.org/D129837

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_solaris.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_solaris.cpp
index e16c4e938cb23..6f43817aedb15 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_solaris.cpp
+++ b/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 @@ bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
     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);
-
-    // If readlink failed, the map is anonymous.
-    if (sz == -1) {
+    // Avoid unnecessary readlink on unnamed entires.
+    if (xmapentry->pr_mapname[0] == '\0')
       segment->filename[0] = '\0';
-    } else if ((size_t)sz < segment->filename_size)
-      // readlink doesn't NUL-terminate.
-      segment->filename[sz] = '\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';
+    }
   }
 
   data_.current += sizeof(prxmap_t);


        


More information about the llvm-commits mailing list