blob: 6b259fd8b9212594ee2165d0165482aaa6c47caf [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
26lldb::DataBufferSP
27lldb_private::ProcFileReader::ReadIntoDataBuffer (lldb::pid_t pid, const char *name)
28{
29 int fd;
30 char path[PATH_MAX];
31
32 // Make sure we've got a nil terminated buffer for all the folks calling
33 // GetBytes() directly off our returned DataBufferSP if we hit an error.
34 lldb::DataBufferSP buf_sp (new DataBufferHeap(1, 0));
35
36 // Ideally, we would simply create a FileSpec and call ReadFileContents.
37 // However, files in procfs have zero size (since they are, in general,
38 // dynamically generated by the kernel) which is incompatible with the
39 // current ReadFileContents implementation. Therefore we simply stream the
40 // data into a DataBuffer ourselves.
41 if (snprintf (path, PATH_MAX, "/proc/%" PRIu64 "/%s", pid, name) > 0)
42 {
43 if ((fd = open (path, O_RDONLY, 0)) >= 0)
44 {
45 size_t bytes_read = 0;
46 std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
47
48 for (;;)
49 {
50 size_t avail = buf_ap->GetByteSize() - bytes_read;
51 ssize_t status = read (fd, buf_ap->GetBytes() + bytes_read, avail);
52
53 if (status < 0)
54 break;
55
56 if (status == 0)
57 {
58 buf_ap->SetByteSize (bytes_read);
59 buf_sp.reset (buf_ap.release());
60 break;
61 }
62
63 bytes_read += status;
64
65 if (avail - status == 0)
66 buf_ap->SetByteSize (2 * buf_ap->GetByteSize());
67 }
68
69 close (fd);
70 }
71 }
72
73 return buf_sp;
74}
75
76lldb_private::Error
77lldb_private::ProcFileReader::ProcessLineByLine (lldb::pid_t pid, const char *name, std::function<bool (const std::string &line)> line_parser)
78{
79 lldb_private::Error error;
80
81 // Try to open the /proc/{pid}/maps entry.
82 char filename [PATH_MAX];
83 snprintf (filename, sizeof(filename), "/proc/%" PRIu64 "/%s", pid, name);
84 filename[sizeof (filename) - 1] = '\0';
85
86 std::ifstream proc_file (filename);
87 if (proc_file.fail ())
88 {
89 error.SetErrorStringWithFormat ("failed to open file '%s'", filename);
90 return error;
91 }
92
93 // Read the file line by line, processing until either end of file or when the line_parser returns false.
94 std::string line;
95 bool should_continue = true;
96
97 while (should_continue && std::getline (proc_file, line))
98 {
99 // Pass the line over to the line_parser for processing. If the line_parser returns false, we
100 // stop processing.
101 should_continue = line_parser (line);
102 }
103
104 return error;
105}