ports/devel/electron13/files/patch-base_debug_proc__maps__linux.cc

141 lines
4.5 KiB
C++

--- base/debug/proc_maps_linux.cc.orig 2021-04-14 01:08:36 UTC
+++ base/debug/proc_maps_linux.cc
@@ -13,13 +13,18 @@
#include "base/strings/string_split.h"
#include "build/build_config.h"
-#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || defined(OS_BSD)
#include <inttypes.h>
#endif
namespace base {
namespace debug {
+#if defined(OS_BSD)
+const char kProcSelfMapsPath[] = "/proc/curproc/map";
+#else
+const char kProcSelfMapsPath[] = "/proc/self/maps";
+
// Scans |proc_maps| starting from |pos| returning true if the gate VMA was
// found, otherwise returns false.
static bool ContainsGateVMA(std::string* proc_maps, size_t pos) {
@@ -35,15 +40,16 @@ static bool ContainsGateVMA(std::string* proc_maps, si
return false;
#endif
}
+#endif
bool ReadProcMaps(std::string* proc_maps) {
// seq_file only writes out a page-sized amount on each call. Refer to header
// file for details.
const long kReadSize = sysconf(_SC_PAGESIZE);
- base::ScopedFD fd(HANDLE_EINTR(open("/proc/self/maps", O_RDONLY)));
+ base::ScopedFD fd(HANDLE_EINTR(open(kProcSelfMapsPath, O_RDONLY)));
if (!fd.is_valid()) {
- DPLOG(ERROR) << "Couldn't open /proc/self/maps";
+ DPLOG(ERROR) << "Couldn't open " << kProcSelfMapsPath;
return false;
}
proc_maps->clear();
@@ -57,7 +63,7 @@ bool ReadProcMaps(std::string* proc_maps) {
ssize_t bytes_read = HANDLE_EINTR(read(fd.get(), buffer, kReadSize));
if (bytes_read < 0) {
- DPLOG(ERROR) << "Couldn't read /proc/self/maps";
+ DPLOG(ERROR) << "Couldn't read " << kProcSelfMapsPath;
proc_maps->clear();
return false;
}
@@ -68,6 +74,7 @@ bool ReadProcMaps(std::string* proc_maps) {
if (bytes_read == 0)
break;
+#if !defined(OS_BSD)
// The gate VMA is handled as a special case after seq_file has finished
// iterating through all entries in the virtual memory table.
//
@@ -78,6 +85,7 @@ bool ReadProcMaps(std::string* proc_maps) {
// Avoid this by searching for the gate VMA and breaking early.
if (ContainsGateVMA(proc_maps, pos))
break;
+#endif
}
return true;
@@ -105,11 +113,32 @@ bool ParseProcMaps(const std::string& input,
MappedMemoryRegion region;
const char* line = lines[i].c_str();
- char permissions[5] = {'\0'}; // Ensure NUL-terminated string.
+ char permissions[6] = {'\0'}; // Ensure NUL-terminated string.
+ int path_index = 0;
+
+#if defined(OS_BSD)
+ if (lines[i].empty())
+ continue;
+
+ char cow;
+
+ // Format:
+ //
+ // start end resident private_resident obj perms ref_count shadow_count flags cow needs_copy type fullpath cred ruid
+ // 0x200000 0x202000 2 6 0xfffff80005be9000 r-- 3 1 0x1000 COW NC vnode /bin/cat NCH -1
+ //
+ if (sscanf(line, "%" SCNxPTR " %" SCNxPTR " %*ld %*ld %*[^ ] %5[^ ] %*d %*d %*x %c%*s %*s %*s %n",
+ &region.start, &region.end, permissions, &cow, &path_index) < 4) {
+ DPLOG(WARNING) << "sscanf failed for line: " << line;
+ return false;
+ }
+
+ const char* fullpath = line + path_index;
+ const char* cred = strchr(fullpath, ' ');
+#else
uint8_t dev_major = 0;
uint8_t dev_minor = 0;
long inode = 0;
- int path_index = 0;
// Sample format from man 5 proc:
//
@@ -125,6 +154,7 @@ bool ParseProcMaps(const std::string& input,
DPLOG(WARNING) << "sscanf failed for line: " << line;
return false;
}
+#endif
region.permissions = 0;
@@ -143,14 +173,31 @@ bool ParseProcMaps(const std::string& input,
else if (permissions[2] != '-')
return false;
+#if defined(OS_BSD)
+ if (cow == 'C') {
+ region.permissions |= MappedMemoryRegion::PRIVATE;
+ } else if (cow != 'N') {
+ DPLOG(WARNING) << "unknown value for COW in line " << line << ": " << cow;
+ return false;
+ }
+#else
if (permissions[3] == 'p')
region.permissions |= MappedMemoryRegion::PRIVATE;
else if (permissions[3] != 's' && permissions[3] != 'S') // Shared memory.
return false;
+#endif
// Pushing then assigning saves us a string copy.
regions.push_back(region);
+#if defined(OS_BSD)
+ if (cred != nullptr) {
+ regions.back().path.assign(line + path_index, cred - fullpath);
+ } else {
+ regions.back().path.assign(line + path_index);
+ }
+#else
regions.back().path.assign(line + path_index);
+#endif
}
regions_out->swap(regions);