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; +}  | 
