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