blob: a1bb7a6e09d556db956482fea837d4a3fd36fd26 [file] [log] [blame]
Todd Fiala3dc2fb22014-06-30 04:14:13 +00001//===-- ProcFileReader.cpp --------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "Plugins/Process/Linux/ProcFileReader.h"
11
12// C Headers
13#include <fcntl.h>
14#include <inttypes.h>
15#include <limits.h>
16#include <stdio.h>
17#include <sys/stat.h>
18
19// C++ Headers
20#include <fstream>
21
22// LLDB Headers
23#include "lldb/Core/DataBufferHeap.h"
24#include "lldb/Core/Error.h"
25
Tamas Berghammerdb264a62015-03-31 09:52:22 +000026using namespace lldb_private;
27using namespace lldb_private::process_linux;
28
Kate Stoneb9c1b512016-09-06 20:57:50 +000029lldb::DataBufferSP ProcFileReader::ReadIntoDataBuffer(lldb::pid_t pid,
30 const char *name) {
31 int fd;
32 char path[PATH_MAX];
Todd Fiala3dc2fb22014-06-30 04:14:13 +000033
Kate Stoneb9c1b512016-09-06 20:57:50 +000034 // Make sure we've got a nil terminated buffer for all the folks calling
35 // GetBytes() directly off our returned DataBufferSP if we hit an error.
36 lldb::DataBufferSP buf_sp(new DataBufferHeap(1, 0));
Todd Fiala3dc2fb22014-06-30 04:14:13 +000037
Kate Stoneb9c1b512016-09-06 20:57:50 +000038 // Ideally, we would simply create a FileSpec and call ReadFileContents.
39 // However, files in procfs have zero size (since they are, in general,
40 // dynamically generated by the kernel) which is incompatible with the
41 // current ReadFileContents implementation. Therefore we simply stream the
42 // data into a DataBuffer ourselves.
43 if (snprintf(path, PATH_MAX, "/proc/%" PRIu64 "/%s", pid, name) > 0) {
44 if ((fd = open(path, O_RDONLY, 0)) >= 0) {
45 size_t bytes_read = 0;
46 std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
Todd Fiala3dc2fb22014-06-30 04:14:13 +000047
Kate Stoneb9c1b512016-09-06 20:57:50 +000048 for (;;) {
49 size_t avail = buf_ap->GetByteSize() - bytes_read;
50 ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail);
Todd Fiala3dc2fb22014-06-30 04:14:13 +000051
Kate Stoneb9c1b512016-09-06 20:57:50 +000052 if (status < 0)
53 break;
Todd Fiala3dc2fb22014-06-30 04:14:13 +000054
Kate Stoneb9c1b512016-09-06 20:57:50 +000055 if (status == 0) {
56 buf_ap->SetByteSize(bytes_read);
57 buf_sp.reset(buf_ap.release());
58 break;
Todd Fiala3dc2fb22014-06-30 04:14:13 +000059 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000060
61 bytes_read += status;
62
63 if (avail - status == 0)
64 buf_ap->SetByteSize(2 * buf_ap->GetByteSize());
65 }
66
67 close(fd);
Todd Fiala3dc2fb22014-06-30 04:14:13 +000068 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000069 }
70
71 return buf_sp;
Todd Fiala3dc2fb22014-06-30 04:14:13 +000072}
73
Kate Stoneb9c1b512016-09-06 20:57:50 +000074Error ProcFileReader::ProcessLineByLine(
75 lldb::pid_t pid, const char *name,
76 std::function<bool(const std::string &line)> line_parser) {
77 Error error;
Todd Fiala3dc2fb22014-06-30 04:14:13 +000078
Kate Stoneb9c1b512016-09-06 20:57:50 +000079 // Try to open the /proc/{pid}/maps entry.
80 char filename[PATH_MAX];
81 snprintf(filename, sizeof(filename), "/proc/%" PRIu64 "/%s", pid, name);
82 filename[sizeof(filename) - 1] = '\0';
Todd Fiala3dc2fb22014-06-30 04:14:13 +000083
Kate Stoneb9c1b512016-09-06 20:57:50 +000084 std::ifstream proc_file(filename);
85 if (proc_file.fail()) {
86 error.SetErrorStringWithFormat("failed to open file '%s'", filename);
Todd Fiala3dc2fb22014-06-30 04:14:13 +000087 return error;
Kate Stoneb9c1b512016-09-06 20:57:50 +000088 }
89
90 // Read the file line by line, processing until either end of file or when the
91 // line_parser returns false.
92 std::string line;
93 bool should_continue = true;
94
95 while (should_continue && std::getline(proc_file, line)) {
96 // Pass the line over to the line_parser for processing. If the line_parser
97 // returns false, we
98 // stop processing.
99 should_continue = line_parser(line);
100 }
101
102 return error;
Todd Fiala3dc2fb22014-06-30 04:14:13 +0000103}