1
// Copyright (c) 2006, Google Inc.
2
// All rights reserved.
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are
8
// * Redistributions of source code must retain the above copyright
9
// notice, this list of conditions and the following disclaimer.
10
// * Redistributions in binary form must reproduce the above
11
// copyright notice, this list of conditions and the following disclaimer
12
// in the documentation and/or other materials provided with the
14
// * Neither the name of Google Inc. nor the names of its
15
// contributors may be used to endorse or promote products derived from
16
// this software without specific prior written permission.
18
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
// Author: Mike Burrows
33
// All functions here are thread-hostile due to file caching unless
34
// commented otherwise.
43
#include <windows.h> // for DWORD
44
#include <TlHelp32.h> // for CreateToolhelp32Snapshot
47
#include <unistd.h> // for pid_t
49
#include <stddef.h> // for size_t
50
#include <limits.h> // for PATH_MAX
52
// BEGIN Google Gears changes
53
#include "third_party/google_perftools/src/base/basictypes.h"
54
// END Google Gears changes
56
// A ProcMapsIterator abstracts access to /proc/maps for a given
57
// process. Needs to be stack-allocatable and avoid using stdio/malloc
58
// so it can be used in the google stack dumper, heap-profiler, etc.
60
// On Windows and Mac OS X, this iterator iterates *only* over DLLs
61
// mapped into this process space. For Linux, FreeBSD, and Solaris,
62
// it iterates over *all* mapped memory regions, including anonymous
63
// mmaps. For other O/Ss, it is unlikely to work at all, and Valid()
64
// will always return false. Also note: this routine only works on
65
// FreeBSD if procfs is mounted: make sure this is in your /etc/fstab:
66
// proc /proc procfs rw 0 0
67
class ProcMapsIterator {
71
// FreeBSD requires us to read all of the maps file at once, so
72
// we have to make a buffer that's "always" big enough
73
static const size_t kBufSize = 102400;
74
#else // a one-line buffer is good enough
75
static const size_t kBufSize = PATH_MAX + 1024;
81
// Create a new iterator for the specified pid. pid can be 0 for "self".
82
explicit ProcMapsIterator(pid_t pid);
84
// Create an iterator with specified storage (for use in signal
85
// handler). "buffer" should point to a ProcMapsIterator::Buffer
86
// buffer can be NULL in which case a bufer will be allocated.
87
ProcMapsIterator(pid_t pid, Buffer *buffer);
89
// Iterate through maps_backing instead of maps if use_maps_backing
90
// is true. Otherwise the same as above. buffer can be NULL and
91
// it will allocate a buffer itself.
92
ProcMapsIterator(pid_t pid, Buffer *buffer,
93
bool use_maps_backing);
95
// Returns true if the iterator successfully initialized;
98
// Returns a pointer to the most recently parsed line. Only valid
99
// after Next() returns true, and until the iterator is destroyed or
100
// Next() is called again. This may give strange results on non-Linux
101
// systems. Prefer FormatLine() if that may be a concern.
102
const char *CurrentLine() const { return stext_; }
104
// Writes the "canonical" form of the /proc/xxx/maps info for a single
105
// line to the passed-in buffer. Returns the number of bytes written,
106
// or 0 if it was not able to write the complete line. (To guarantee
107
// success, buffer should have size at least Buffer::kBufSize.)
108
// Takes as arguments values set via a call to Next(). The
109
// "canonical" form of the line (taken from linux's /proc/xxx/maps):
110
// <start_addr(hex)>-<end_addr(hex)> <perms(rwxp)> <offset(hex)> +
111
// <major_dev(hex)>:<minor_dev(hex)> <inode> <filename> Note: the
113
// 08048000-0804c000 r-xp 00000000 03:01 3793678 /bin/cat
114
// If you don't have the dev_t (dev), feel free to pass in 0.
115
// (Next() doesn't return a dev_t, though NextExt does.)
117
// Note: if filename and flags were obtained via a call to Next(),
118
// then the output of this function is only valid if Next() returned
119
// true, and only until the iterator is destroyed or Next() is
120
// called again. (Since filename, at least, points into CurrentLine.)
121
static int FormatLine(char* buffer, int bufsize,
122
uint64 start, uint64 end, const char *flags,
123
uint64 offset, int64 inode, const char *filename,
126
// Find the next entry in /proc/maps; return true if found or false
127
// if at the end of the file.
129
// Any of the result pointers can be NULL if you're not interested
132
// If "flags" and "filename" are passed, they end up pointing to
133
// storage within the ProcMapsIterator that is valid only until the
134
// iterator is destroyed or Next() is called again. The caller may
135
// modify the contents of these strings (up as far as the first NUL,
136
// and only until the subsequent call to Next()) if desired.
138
// The offsets are all uint64 in order to handle the case of a
139
// 32-bit process running on a 64-bit kernel
141
// IMPORTANT NOTE: see top-of-class notes for details about what
142
// mapped regions Next() iterates over, depending on O/S.
143
// TODO(csilvers): make flags and filename const.
144
bool Next(uint64 *start, uint64 *end, char **flags,
145
uint64 *offset, int64 *inode, char **filename);
147
bool NextExt(uint64 *start, uint64 *end, char **flags,
148
uint64 *offset, int64 *inode, char **filename,
149
uint64 *file_mapping, uint64 *file_pages,
150
uint64 *anon_mapping, uint64 *anon_pages,
156
void Init(pid_t pid, Buffer *buffer, bool use_maps_backing);
158
char *ibuf_; // input buffer
159
char *stext_; // start of text
160
char *etext_; // end of text
161
char *nextline_; // start of next line
162
char *ebuf_; // end of buffer (1 char for a nul)
164
HANDLE snapshot_; // filehandle on dll info
165
// In a change from the usual W-A pattern, there is no A variant of
166
// MODULEENTRY32. Tlhelp32.h #defines the W variant, but not the A.
167
// We want the original A variants, and this #undef is the only
168
// way I see to get them. Redefining it when we're done prevents us
169
// from affecting other .cc files.
170
# ifdef MODULEENTRY32 // Alias of W
171
# undef MODULEENTRY32
172
MODULEENTRY32 module_; // info about current dll (and dll iterator)
173
# define MODULEENTRY32 MODULEENTRY32W
174
# else // It's the ascii, the one we want.
175
MODULEENTRY32 module_; // info about current dll (and dll iterator)
177
#elif defined(__MACH__)
178
int current_image_; // dll's are called "images" in macos parlance
179
int current_load_cmd_; // the segment of this dll we're examining
181
int fd_; // filehandle on /proc/*/maps
184
Buffer* dynamic_buffer_; // dynamically-allocated Buffer
185
bool using_maps_backing_; // true if we are looking at maps_backing instead of maps.
188
#endif /* #ifndef _SYSINFO_H_ */