blob: 6b259fd8b9212594ee2165d0165482aaa6c47caf [file] [log] [blame]
//===-- 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;
}