forked from OSchip/llvm-project
104 lines
3.0 KiB
C++
104 lines
3.0 KiB
C++
//===-- 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;
|
|
}
|