blob: 77d956ea3f8b5126c6269aaeffa80e734b6ea4c3 [file] [log] [blame]
Austin Schuh745610d2015-09-06 18:19:50 -07001// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
2// Copyright (c) 2006, Google Inc.
3// All rights reserved.
Brian Silverman20350ac2021-11-17 18:19:55 -08004//
Austin Schuh745610d2015-09-06 18:19:50 -07005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
Brian Silverman20350ac2021-11-17 18:19:55 -08008//
Austin Schuh745610d2015-09-06 18:19:50 -07009// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
Brian Silverman20350ac2021-11-17 18:19:55 -080018//
Austin Schuh745610d2015-09-06 18:19:50 -070019// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// All functions here are thread-hostile due to file caching unless
32// commented otherwise.
33
34#ifndef _SYSINFO_H_
35#define _SYSINFO_H_
36
37#include <config.h>
38
39#include <time.h>
40#if (defined(_WIN32) || defined(__MINGW32__)) && (!defined(__CYGWIN__) && !defined(__CYGWIN32__))
41#include <windows.h> // for DWORD
42#include <tlhelp32.h> // for CreateToolhelp32Snapshot
43#endif
44#ifdef HAVE_UNISTD_H
45#include <unistd.h> // for pid_t
46#endif
47#include <stddef.h> // for size_t
48#include <limits.h> // for PATH_MAX
49#include "base/basictypes.h"
50#include "base/logging.h" // for RawFD
51
52// This getenv function is safe to call before the C runtime is initialized.
53// On Windows, it utilizes GetEnvironmentVariable() and on unix it uses
54// /proc/self/environ instead calling getenv(). It's intended to be used in
55// routines that run before main(), when the state required for getenv() may
56// not be set up yet. In particular, errno isn't set up until relatively late
57// (after the pthreads library has a chance to make it threadsafe), and
Brian Silverman20350ac2021-11-17 18:19:55 -080058// getenv() doesn't work until then.
Austin Schuh745610d2015-09-06 18:19:50 -070059// On some platforms, this call will utilize the same, static buffer for
60// repeated GetenvBeforeMain() calls. Callers should not expect pointers from
61// this routine to be long lived.
62// Note that on unix, /proc only has the environment at the time the
63// application was started, so this routine ignores setenv() calls/etc. Also
64// note it only reads the first 16K of the environment.
65extern const char* GetenvBeforeMain(const char* name);
66
67// This takes as an argument an environment-variable name (like
68// CPUPROFILE) whose value is supposed to be a file-path, and sets
69// path to that path, and returns true. Non-trivial for surprising
70// reasons, as documented in sysinfo.cc. path must have space PATH_MAX.
71extern bool GetUniquePathFromEnv(const char* env_name, char* path);
72
Brian Silverman20350ac2021-11-17 18:19:55 -080073extern int GetSystemCPUsCount();
Austin Schuh745610d2015-09-06 18:19:50 -070074
75// Return true if we're running POSIX (e.g., NPTL on Linux) threads,
76// as opposed to a non-POSIX thread library. The thing that we care
77// about is whether a thread's pid is the same as the thread that
78// spawned it. If so, this function returns true.
79// Thread-safe.
80// Note: We consider false negatives to be OK.
81bool HasPosixThreads();
82
83#ifndef SWIG // SWIG doesn't like struct Buffer and variable arguments.
84
85// A ProcMapsIterator abstracts access to /proc/maps for a given
86// process. Needs to be stack-allocatable and avoid using stdio/malloc
87// so it can be used in the google stack dumper, heap-profiler, etc.
88//
89// On Windows and Mac OS X, this iterator iterates *only* over DLLs
90// mapped into this process space. For Linux, FreeBSD, and Solaris,
91// it iterates over *all* mapped memory regions, including anonymous
92// mmaps. For other O/Ss, it is unlikely to work at all, and Valid()
93// will always return false. Also note: this routine only works on
94// FreeBSD if procfs is mounted: make sure this is in your /etc/fstab:
95// proc /proc procfs rw 0 0
96class ProcMapsIterator {
97 public:
98 struct Buffer {
99#ifdef __FreeBSD__
100 // FreeBSD requires us to read all of the maps file at once, so
101 // we have to make a buffer that's "always" big enough
102 static const size_t kBufSize = 102400;
103#else // a one-line buffer is good enough
104 static const size_t kBufSize = PATH_MAX + 1024;
105#endif
106 char buf_[kBufSize];
107 };
108
109
110 // Create a new iterator for the specified pid. pid can be 0 for "self".
111 explicit ProcMapsIterator(pid_t pid);
112
113 // Create an iterator with specified storage (for use in signal
114 // handler). "buffer" should point to a ProcMapsIterator::Buffer
115 // buffer can be NULL in which case a bufer will be allocated.
116 ProcMapsIterator(pid_t pid, Buffer *buffer);
117
118 // Iterate through maps_backing instead of maps if use_maps_backing
119 // is true. Otherwise the same as above. buffer can be NULL and
120 // it will allocate a buffer itself.
121 ProcMapsIterator(pid_t pid, Buffer *buffer,
122 bool use_maps_backing);
123
124 // Returns true if the iterator successfully initialized;
125 bool Valid() const;
126
127 // Returns a pointer to the most recently parsed line. Only valid
128 // after Next() returns true, and until the iterator is destroyed or
129 // Next() is called again. This may give strange results on non-Linux
130 // systems. Prefer FormatLine() if that may be a concern.
131 const char *CurrentLine() const { return stext_; }
132
133 // Writes the "canonical" form of the /proc/xxx/maps info for a single
134 // line to the passed-in buffer. Returns the number of bytes written,
135 // or 0 if it was not able to write the complete line. (To guarantee
136 // success, buffer should have size at least Buffer::kBufSize.)
137 // Takes as arguments values set via a call to Next(). The
138 // "canonical" form of the line (taken from linux's /proc/xxx/maps):
139 // <start_addr(hex)>-<end_addr(hex)> <perms(rwxp)> <offset(hex)> +
140 // <major_dev(hex)>:<minor_dev(hex)> <inode> <filename> Note: the
141 // eg
142 // 08048000-0804c000 r-xp 00000000 03:01 3793678 /bin/cat
143 // If you don't have the dev_t (dev), feel free to pass in 0.
144 // (Next() doesn't return a dev_t, though NextExt does.)
145 //
146 // Note: if filename and flags were obtained via a call to Next(),
147 // then the output of this function is only valid if Next() returned
148 // true, and only until the iterator is destroyed or Next() is
149 // called again. (Since filename, at least, points into CurrentLine.)
150 static int FormatLine(char* buffer, int bufsize,
151 uint64 start, uint64 end, const char *flags,
152 uint64 offset, int64 inode, const char *filename,
153 dev_t dev);
154
155 // Find the next entry in /proc/maps; return true if found or false
156 // if at the end of the file.
157 //
158 // Any of the result pointers can be NULL if you're not interested
159 // in those values.
160 //
161 // If "flags" and "filename" are passed, they end up pointing to
162 // storage within the ProcMapsIterator that is valid only until the
163 // iterator is destroyed or Next() is called again. The caller may
164 // modify the contents of these strings (up as far as the first NUL,
165 // and only until the subsequent call to Next()) if desired.
166
167 // The offsets are all uint64 in order to handle the case of a
168 // 32-bit process running on a 64-bit kernel
169 //
170 // IMPORTANT NOTE: see top-of-class notes for details about what
171 // mapped regions Next() iterates over, depending on O/S.
172 // TODO(csilvers): make flags and filename const.
173 bool Next(uint64 *start, uint64 *end, char **flags,
174 uint64 *offset, int64 *inode, char **filename);
175
176 bool NextExt(uint64 *start, uint64 *end, char **flags,
177 uint64 *offset, int64 *inode, char **filename,
178 uint64 *file_mapping, uint64 *file_pages,
179 uint64 *anon_mapping, uint64 *anon_pages,
180 dev_t *dev);
181
182 ~ProcMapsIterator();
183
184 private:
185 void Init(pid_t pid, Buffer *buffer, bool use_maps_backing);
186
187 char *ibuf_; // input buffer
188 char *stext_; // start of text
189 char *etext_; // end of text
190 char *nextline_; // start of next line
191 char *ebuf_; // end of buffer (1 char for a nul)
192#if (defined(_WIN32) || defined(__MINGW32__)) && (!defined(__CYGWIN__) && !defined(__CYGWIN32__))
193 HANDLE snapshot_; // filehandle on dll info
194 // In a change from the usual W-A pattern, there is no A variant of
195 // MODULEENTRY32. Tlhelp32.h #defines the W variant, but not the A.
196 // We want the original A variants, and this #undef is the only
197 // way I see to get them. Redefining it when we're done prevents us
198 // from affecting other .cc files.
199# ifdef MODULEENTRY32 // Alias of W
200# undef MODULEENTRY32
201 MODULEENTRY32 module_; // info about current dll (and dll iterator)
202# define MODULEENTRY32 MODULEENTRY32W
203# else // It's the ascii, the one we want.
204 MODULEENTRY32 module_; // info about current dll (and dll iterator)
205# endif
206#elif defined(__MACH__)
207 int current_image_; // dll's are called "images" in macos parlance
208 int current_load_cmd_; // the segment of this dll we're examining
209#elif defined(__sun__) // Solaris
210 int fd_;
211 char current_filename_[PATH_MAX];
212#else
213 int fd_; // filehandle on /proc/*/maps
214#endif
215 pid_t pid_;
216 char flags_[10];
217 Buffer* dynamic_buffer_; // dynamically-allocated Buffer
218 bool using_maps_backing_; // true if we are looking at maps_backing instead of maps.
219};
220
221#endif /* #ifndef SWIG */
222
223// Helper routines
224
225namespace tcmalloc {
226int FillProcSelfMaps(char buf[], int size, bool* wrote_all);
227void DumpProcSelfMaps(RawFD fd);
228}
229
230#endif /* #ifndef _SYSINFO_H_ */