diff options
Diffstat (limited to 'source/Plugins/Process/Linux/ProcFileReader.cpp')
-rw-r--r-- | source/Plugins/Process/Linux/ProcFileReader.cpp | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/source/Plugins/Process/Linux/ProcFileReader.cpp b/source/Plugins/Process/Linux/ProcFileReader.cpp new file mode 100644 index 0000000000000..4d1f231f4f9be --- /dev/null +++ b/source/Plugins/Process/Linux/ProcFileReader.cpp @@ -0,0 +1,108 @@ +//===-- 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" + +using namespace lldb_private; +using namespace lldb_private::process_linux; + +lldb::DataBufferSP +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; +} + +Error +ProcFileReader::ProcessLineByLine (lldb::pid_t pid, const char *name, std::function<bool (const std::string &line)> line_parser) +{ + 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; +} |