[Lldb-commits] [lldb] r212015 - Factored out Linux proc file reading into separate class.

Todd Fiala todd.fiala at gmail.com
Sun Jun 29 21:14:13 PDT 2014


Author: tfiala
Date: Sun Jun 29 23:14:13 2014
New Revision: 212015

URL: http://llvm.org/viewvc/llvm-project?rev=212015&view=rev
Log:
Factored out Linux proc file reading into separate class.

Both NativeProcessLinux (in llgs branch) and Linux Host.cpp had similar code to handle /proc 
file reading.  I factored that out into a new Linux-specific ProcFileReader class and added a method
that the llgs branch will use for line-by-line parsing.

This change also adds numerous Linux-specific files to Xcode that were missing from the Xcode
project files.

Related to https://github.com/tfiala/lldb/issues/27

Added:
    lldb/trunk/source/Plugins/Process/Linux/ProcFileReader.cpp
    lldb/trunk/source/Plugins/Process/Linux/ProcFileReader.h
Modified:
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/Host/linux/Host.cpp
    lldb/trunk/source/Plugins/Process/Linux/CMakeLists.txt

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=212015&r1=212014&r2=212015&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Sun Jun 29 23:14:13 2014
@@ -55,6 +55,14 @@
 		23059A121958B3B2007B8189 /* SBUnixSignals.h in Headers */ = {isa = PBXBuildFile; fileRef = 23059A111958B37B007B8189 /* SBUnixSignals.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		233B007D1960C9F90090E598 /* ProcessInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B007B1960C9E60090E598 /* ProcessInfo.cpp */; };
 		233B007F1960CB280090E598 /* ProcessLaunchInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B007E1960CB280090E598 /* ProcessLaunchInfo.cpp */; };
+		233B009419610B1F0090E598 /* LinuxSignals.cpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B008C19610B1F0090E598 /* LinuxSignals.cpp */; };
+		233B009519610B1F0090E598 /* LinuxSignals.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B008D19610B1F0090E598 /* LinuxSignals.h */; };
+		233B009619610B1F0090E598 /* LinuxThread.cpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B008E19610B1F0090E598 /* LinuxThread.cpp */; };
+		233B009719610B1F0090E598 /* LinuxThread.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B008F19610B1F0090E598 /* LinuxThread.h */; };
+		233B009819610B1F0090E598 /* ProcessLinux.cpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B009019610B1F0090E598 /* ProcessLinux.cpp */; };
+		233B009919610B1F0090E598 /* ProcessLinux.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B009119610B1F0090E598 /* ProcessLinux.h */; };
+		233B009A19610B1F0090E598 /* ProcessMonitor.cpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B009219610B1F0090E598 /* ProcessMonitor.cpp */; };
+		233B009B19610B1F0090E598 /* ProcessMonitor.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B009319610B1F0090E598 /* ProcessMonitor.h */; };
 		23EFE389193D1ABC00E54E54 /* SBTypeEnumMember.h in Headers */ = {isa = PBXBuildFile; fileRef = 23EFE388193D1ABC00E54E54 /* SBTypeEnumMember.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		23EFE38B193D1AEC00E54E54 /* SBTypeEnumMember.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23EFE38A193D1AEC00E54E54 /* SBTypeEnumMember.cpp */; };
 		260157C61885F51C00F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; };
@@ -853,6 +861,14 @@
 			dstPath = "$(DEVELOPER_DIR)/usr/share/man/man1/";
 			dstSubfolderSpec = 0;
 			files = (
+				233B009819610B1F0090E598 /* ProcessLinux.cpp in CopyFiles */,
+				233B009619610B1F0090E598 /* LinuxThread.cpp in CopyFiles */,
+				233B009A19610B1F0090E598 /* ProcessMonitor.cpp in CopyFiles */,
+				233B009719610B1F0090E598 /* LinuxThread.h in CopyFiles */,
+				233B009919610B1F0090E598 /* ProcessLinux.h in CopyFiles */,
+				233B009B19610B1F0090E598 /* ProcessMonitor.h in CopyFiles */,
+				233B009419610B1F0090E598 /* LinuxSignals.cpp in CopyFiles */,
+				233B009519610B1F0090E598 /* LinuxSignals.h in CopyFiles */,
 				AF90106515AB7D3600FF120D /* lldb.1 in CopyFiles */,
 			);
 			runOnlyForDeploymentPostprocessing = 1;
@@ -881,6 +897,17 @@
 		233B007A1960A0440090E598 /* ProcessInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ProcessInfo.h; path = include/lldb/Target/ProcessInfo.h; sourceTree = "<group>"; };
 		233B007B1960C9E60090E598 /* ProcessInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProcessInfo.cpp; path = source/Target/ProcessInfo.cpp; sourceTree = "<group>"; };
 		233B007E1960CB280090E598 /* ProcessLaunchInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProcessLaunchInfo.cpp; path = source/Target/ProcessLaunchInfo.cpp; sourceTree = "<group>"; };
+		233B008C19610B1F0090E598 /* LinuxSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinuxSignals.cpp; sourceTree = "<group>"; };
+		233B008D19610B1F0090E598 /* LinuxSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinuxSignals.h; sourceTree = "<group>"; };
+		233B008E19610B1F0090E598 /* LinuxThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinuxThread.cpp; sourceTree = "<group>"; };
+		233B008F19610B1F0090E598 /* LinuxThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinuxThread.h; sourceTree = "<group>"; };
+		233B009019610B1F0090E598 /* ProcessLinux.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessLinux.cpp; sourceTree = "<group>"; };
+		233B009119610B1F0090E598 /* ProcessLinux.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessLinux.h; sourceTree = "<group>"; };
+		233B009219610B1F0090E598 /* ProcessMonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessMonitor.cpp; sourceTree = "<group>"; };
+		233B009319610B1F0090E598 /* ProcessMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessMonitor.h; sourceTree = "<group>"; };
+		233B009D19610D6B0090E598 /* Host.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Host.cpp; sourceTree = "<group>"; };
+		233B00A1196113730090E598 /* ProcFileReader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ProcFileReader.cpp; sourceTree = "<group>"; };
+		233B00A2196113730090E598 /* ProcFileReader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProcFileReader.h; sourceTree = "<group>"; };
 		2360092C193FB21500189DB1 /* MemoryRegionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MemoryRegionInfo.h; path = include/lldb/Target/MemoryRegionInfo.h; sourceTree = "<group>"; };
 		23EDE3371926AAD500F6A132 /* RegisterInfoInterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RegisterInfoInterface.h; path = Utility/RegisterInfoInterface.h; sourceTree = "<group>"; };
 		23EFE388193D1ABC00E54E54 /* SBTypeEnumMember.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBTypeEnumMember.h; path = include/lldb/API/SBTypeEnumMember.h; sourceTree = "<group>"; };
@@ -2156,6 +2183,32 @@
 			sourceTree = "<group>";
 			usesTabs = 0;
 		};
+		233B008B196106E90090E598 /* Linux */ = {
+			isa = PBXGroup;
+			children = (
+				233B008C19610B1F0090E598 /* LinuxSignals.cpp */,
+				233B008D19610B1F0090E598 /* LinuxSignals.h */,
+				233B008E19610B1F0090E598 /* LinuxThread.cpp */,
+				233B008F19610B1F0090E598 /* LinuxThread.h */,
+				233B009019610B1F0090E598 /* ProcessLinux.cpp */,
+				233B009119610B1F0090E598 /* ProcessLinux.h */,
+				233B009219610B1F0090E598 /* ProcessMonitor.cpp */,
+				233B009319610B1F0090E598 /* ProcessMonitor.h */,
+				233B00A2196113730090E598 /* ProcFileReader.h */,
+				233B00A1196113730090E598 /* ProcFileReader.cpp */,
+			);
+			path = Linux;
+			sourceTree = "<group>";
+		};
+		233B009C19610D130090E598 /* linux */ = {
+			isa = PBXGroup;
+			children = (
+				233B009D19610D6B0090E598 /* Host.cpp */,
+			);
+			name = linux;
+			path = source/Host/linux;
+			sourceTree = "<group>";
+		};
 		260C897110F57C5600BB2B04 /* Plugins */ = {
 			isa = PBXGroup;
 			children = (
@@ -2270,6 +2323,7 @@
 			children = (
 				26BC179F18C7F4CB00D2196D /* elf-core */,
 				4CEE62F71145F1C70064CF93 /* GDB Remote */,
+				233B008B196106E90090E598 /* Linux */,
 				2642FBA713D003B400ED6808 /* MacOSX-Kernel */,
 				26A527BC14E24F5F00F3A14A /* mach-core */,
 				26BC17B318C7F4FA00D2196D /* POSIX */,
@@ -3311,6 +3365,7 @@
 			isa = PBXGroup;
 			children = (
 				69A01E1A1236C5D400C660B5 /* common */,
+				233B009C19610D130090E598 /* linux */,
 				26BC7EE510F1B88100F91463 /* MacOSX */,
 				26BC7DD210F1B7D500F91463 /* Condition.h */,
 				266F5CBB12FC846200DFCE33 /* Config.h */,

Modified: lldb/trunk/source/Host/linux/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/linux/Host.cpp?rev=212015&r1=212014&r2=212015&view=diff
==============================================================================
--- lldb/trunk/source/Host/linux/Host.cpp (original)
+++ lldb/trunk/source/Host/linux/Host.cpp Sun Jun 29 23:14:13 2014
@@ -29,6 +29,7 @@
 
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Symbol/ObjectFile.h"
+#include "Plugins/Process/Linux/ProcFileReader.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -52,67 +53,11 @@ typedef struct ProcessStatInfo
 // Get the process info with additional information from /proc/$PID/stat (like process state, and tracer pid).
 static bool GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid);
 
-
-namespace
-{
-
-lldb::DataBufferSP
-ReadProcPseudoFile (lldb::pid_t pid, const char *name)
-{
-    int fd;
-    char path[PATH_MAX];
-
-    // Make sure we've got a nil terminated buffer for all the folks calling
-    // GetBytes() directly off our returned DataBufferSP if we hit an error.
-    lldb::DataBufferSP buf_sp (new DataBufferHeap(1, 0));
-
-    // Ideally, we would simply create a FileSpec and call ReadFileContents.
-    // However, files in procfs have zero size (since they are, in general,
-    // dynamically generated by the kernel) which is incompatible with the
-    // current ReadFileContents implementation. Therefore we simply stream the
-    // data into a DataBuffer ourselves.
-    if (snprintf (path, PATH_MAX, "/proc/%" PRIu64 "/%s", pid, name) > 0)
-    {
-        if ((fd = open (path, O_RDONLY, 0)) >= 0)
-        {
-            size_t bytes_read = 0;
-            std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
-
-            for (;;) 
-            {
-                size_t avail = buf_ap->GetByteSize() - bytes_read;
-                ssize_t status = read (fd, buf_ap->GetBytes() + bytes_read, avail);
-
-                if (status < 0) 
-                    break;
-
-                if (status == 0) 
-                {
-                    buf_ap->SetByteSize (bytes_read);
-                    buf_sp.reset (buf_ap.release());
-                    break;
-                }
-
-                bytes_read += status;
-
-                if (avail - status == 0)
-                    buf_ap->SetByteSize (2 * buf_ap->GetByteSize());
-            }
-
-            close (fd);
-        }
-    }
-
-    return buf_sp;
-}
-
-} // anonymous namespace
-
 static bool
 ReadProcPseudoFileStat (lldb::pid_t pid, ProcessStatInfo& stat_info)
 {
     // Read the /proc/$PID/stat file.
-    lldb::DataBufferSP buf_sp = ReadProcPseudoFile (pid, "stat");
+    lldb::DataBufferSP buf_sp = ProcFileReader::ReadIntoDataBuffer (pid, "stat");
 
     // The filename of the executable is stored in parenthesis right after the pid. We look for the closing
     // parenthesis for the filename and work from there in case the name has something funky like ')' in it.
@@ -165,7 +110,7 @@ GetLinuxProcessUserAndGroup (lldb::pid_t
     uint32_t eGid = UINT32_MAX;     // Effective Group ID
 
     // Read the /proc/$PID/status file and parse the Uid:, Gid:, and TracerPid: fields.
-    lldb::DataBufferSP buf_sp = ReadProcPseudoFile (pid, "status");
+    lldb::DataBufferSP buf_sp = ProcFileReader::ReadIntoDataBuffer (pid, "status");
 
     static const char uid_token[] = "Uid:";
     char *buf_uid = strstr ((char *)buf_sp->GetBytes(), uid_token);
@@ -227,7 +172,7 @@ Host::GetOSVersion(uint32_t &major,
 lldb::DataBufferSP
 Host::GetAuxvData(lldb_private::Process *process)
 {
-    return ReadProcPseudoFile(process->GetID(), "auxv");
+    return ProcFileReader::ReadIntoDataBuffer (process->GetID(), "auxv");
 }
 
 static bool
@@ -391,7 +336,7 @@ GetProcessAndStatInfo (lldb::pid_t pid,
     lldb::DataBufferSP buf_sp;
 
     // Get the process environment.
-    buf_sp = ReadProcPseudoFile(pid, "environ");
+    buf_sp = ProcFileReader::ReadIntoDataBuffer(pid, "environ");
     Args &info_env = process_info.GetEnvironmentEntries();
     char *next_var = (char *)buf_sp->GetBytes();
     char *end_buf = next_var + buf_sp->GetByteSize();
@@ -402,7 +347,7 @@ GetProcessAndStatInfo (lldb::pid_t pid,
     }
 
     // Get the commond line used to start the process.
-    buf_sp = ReadProcPseudoFile(pid, "cmdline");
+    buf_sp = ProcFileReader::ReadIntoDataBuffer(pid, "cmdline");
 
     // Grab Arg0 first, if there is one.
     char *cmd = (char *)buf_sp->GetBytes();
@@ -458,7 +403,7 @@ Host::GetThreadName (lldb::pid_t pid, ll
     assert(tid != LLDB_INVALID_THREAD_ID);
 
     // Read /proc/$TID/comm file.
-    lldb::DataBufferSP buf_sp = ReadProcPseudoFile (tid, "comm");
+    lldb::DataBufferSP buf_sp = ProcFileReader::ReadIntoDataBuffer (tid, "comm");
     const char *comm_str = (const char *)buf_sp->GetBytes();
     const char *cr_str = ::strchr(comm_str, '\n');
     size_t length = cr_str ? (cr_str - comm_str) : strlen(comm_str);

Modified: lldb/trunk/source/Plugins/Process/Linux/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/CMakeLists.txt?rev=212015&r1=212014&r2=212015&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Process/Linux/CMakeLists.txt Sun Jun 29 23:14:13 2014
@@ -7,6 +7,7 @@ include_directories(../Utility)
 add_lldb_library(lldbPluginProcessLinux
   ProcessLinux.cpp
   ProcessMonitor.cpp
+  ProcFileReader.cpp
   LinuxSignals.cpp
   LinuxThread.cpp
   )

Added: lldb/trunk/source/Plugins/Process/Linux/ProcFileReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcFileReader.cpp?rev=212015&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcFileReader.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcFileReader.cpp Sun Jun 29 23:14:13 2014
@@ -0,0 +1,105 @@
+//===-- ProcFileReader.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/Process/Linux/ProcFileReader.h"
+
+// C Headers
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <sys/stat.h>
+
+// C++ Headers
+#include <fstream>
+
+// LLDB Headers
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+
+lldb::DataBufferSP
+lldb_private::ProcFileReader::ReadIntoDataBuffer (lldb::pid_t pid, const char *name)
+{
+    int fd;
+    char path[PATH_MAX];
+
+    // Make sure we've got a nil terminated buffer for all the folks calling
+    // GetBytes() directly off our returned DataBufferSP if we hit an error.
+    lldb::DataBufferSP buf_sp (new DataBufferHeap(1, 0));
+
+    // Ideally, we would simply create a FileSpec and call ReadFileContents.
+    // However, files in procfs have zero size (since they are, in general,
+    // dynamically generated by the kernel) which is incompatible with the
+    // current ReadFileContents implementation. Therefore we simply stream the
+    // data into a DataBuffer ourselves.
+    if (snprintf (path, PATH_MAX, "/proc/%" PRIu64 "/%s", pid, name) > 0)
+    {
+        if ((fd = open (path, O_RDONLY, 0)) >= 0)
+        {
+            size_t bytes_read = 0;
+            std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
+
+            for (;;)
+            {
+                size_t avail = buf_ap->GetByteSize() - bytes_read;
+                ssize_t status = read (fd, buf_ap->GetBytes() + bytes_read, avail);
+
+                if (status < 0)
+                    break;
+
+                if (status == 0)
+                {
+                    buf_ap->SetByteSize (bytes_read);
+                    buf_sp.reset (buf_ap.release());
+                    break;
+                }
+
+                bytes_read += status;
+
+                if (avail - status == 0)
+                    buf_ap->SetByteSize (2 * buf_ap->GetByteSize());
+            }
+            
+            close (fd);
+        }
+    }
+    
+    return buf_sp;
+}
+
+lldb_private::Error
+lldb_private::ProcFileReader::ProcessLineByLine (lldb::pid_t pid, const char *name, std::function<bool (const std::string &line)> line_parser)
+{
+    lldb_private::Error error;
+
+    // Try to open the /proc/{pid}/maps entry.
+    char filename [PATH_MAX];
+    snprintf (filename, sizeof(filename), "/proc/%" PRIu64 "/%s", pid, name);
+    filename[sizeof (filename) - 1] = '\0';
+
+    std::ifstream proc_file (filename);
+    if (proc_file.fail ())
+    {
+        error.SetErrorStringWithFormat ("failed to open file '%s'", filename);
+        return error;
+    }
+
+    // Read the file line by line, processing until either end of file or when the line_parser returns false.
+    std::string line;
+    bool should_continue = true;
+
+    while (should_continue && std::getline (proc_file, line))
+    {
+        // Pass the line over to the line_parser for processing.  If the line_parser returns false, we
+        // stop processing.
+        should_continue = line_parser (line);
+    }
+
+    return error;
+}

Added: lldb/trunk/source/Plugins/Process/Linux/ProcFileReader.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcFileReader.h?rev=212015&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcFileReader.h (added)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcFileReader.h Sun Jun 29 23:14:13 2014
@@ -0,0 +1,34 @@
+//===-- ProcFileReader.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcFileReader_h_
+#define liblldb_ProcFileReader_h_
+
+#include <functional>
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
+
+namespace lldb_private
+{
+    class ProcFileReader
+    {
+    public:
+
+        static lldb::DataBufferSP
+        ReadIntoDataBuffer (lldb::pid_t pid, const char *name);
+
+        /// Parse the /proc/{@a pid}/{@a name} file line by line, passing each line to line_parser, until
+        /// either end of file or until line_parser returns false.
+        static lldb_private::Error
+        ProcessLineByLine (lldb::pid_t pid, const char *name, std::function<bool (const std::string &line)> line_parser);
+    };
+}
+
+#endif // #ifndef liblldb_ProcFileReader_h_





More information about the lldb-commits mailing list