| //===-- 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; |
| } |