diff options
| author | Todd Fiala <todd.fiala@gmail.com> | 2014-06-30 04:14:13 +0000 |
|---|---|---|
| committer | Todd Fiala <todd.fiala@gmail.com> | 2014-06-30 04:14:13 +0000 |
| commit | 3dc2fb2fc03b315951b8739435bbfc7f6854576b (patch) | |
| tree | 361639a73ce7cf3fe8845fc745a3345d5408a2dc | |
| parent | 8dfca43296dc311a342bf9ebf8b37cf19724c3e9 (diff) | |
| download | bcm5719-llvm-3dc2fb2fc03b315951b8739435bbfc7f6854576b.tar.gz bcm5719-llvm-3dc2fb2fc03b315951b8739435bbfc7f6854576b.zip | |
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
llvm-svn: 212015
| -rw-r--r-- | lldb/lldb.xcodeproj/project.pbxproj | 55 | ||||
| -rw-r--r-- | lldb/source/Host/linux/Host.cpp | 69 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Linux/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Linux/ProcFileReader.cpp | 105 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Linux/ProcFileReader.h | 34 |
5 files changed, 202 insertions, 62 deletions
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 2e3beeba4b0..0d4b99170bf 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -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 */, diff --git a/lldb/source/Host/linux/Host.cpp b/lldb/source/Host/linux/Host.cpp index 3c05243f92a..b30e6d5613f 100644 --- a/lldb/source/Host/linux/Host.cpp +++ b/lldb/source/Host/linux/Host.cpp @@ -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 pid, ProcessInstanceInfo &process_info, 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, ProcessInstanceInfo &process_info, Proce 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, ProcessInstanceInfo &process_info, Proce } // 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, lldb::tid_t tid) 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); diff --git a/lldb/source/Plugins/Process/Linux/CMakeLists.txt b/lldb/source/Plugins/Process/Linux/CMakeLists.txt index 1e914099bbb..46fbaa08768 100644 --- a/lldb/source/Plugins/Process/Linux/CMakeLists.txt +++ b/lldb/source/Plugins/Process/Linux/CMakeLists.txt @@ -7,6 +7,7 @@ include_directories(../Utility) add_lldb_library(lldbPluginProcessLinux ProcessLinux.cpp ProcessMonitor.cpp + ProcFileReader.cpp LinuxSignals.cpp LinuxThread.cpp ) diff --git a/lldb/source/Plugins/Process/Linux/ProcFileReader.cpp b/lldb/source/Plugins/Process/Linux/ProcFileReader.cpp new file mode 100644 index 00000000000..6b259fd8b92 --- /dev/null +++ b/lldb/source/Plugins/Process/Linux/ProcFileReader.cpp @@ -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; +} diff --git a/lldb/source/Plugins/Process/Linux/ProcFileReader.h b/lldb/source/Plugins/Process/Linux/ProcFileReader.h new file mode 100644 index 00000000000..dfd77d349e8 --- /dev/null +++ b/lldb/source/Plugins/Process/Linux/ProcFileReader.h @@ -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_ |

