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 /lldb/source | |
| 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
Diffstat (limited to 'lldb/source')
| -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 |
4 files changed, 147 insertions, 62 deletions
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_ |

