00001 // Copyright (c) 2006, Google Inc. 00002 // All rights reserved. 00003 // 00004 // Redistribution and use in source and binary forms, with or without 00005 // modification, are permitted provided that the following conditions are 00006 // met: 00007 // 00008 // * Redistributions of source code must retain the above copyright 00009 // notice, this list of conditions and the following disclaimer. 00010 // * Redistributions in binary form must reproduce the above 00011 // copyright notice, this list of conditions and the following disclaimer 00012 // in the documentation and/or other materials provided with the 00013 // distribution. 00014 // * Neither the name of Google Inc. nor the names of its 00015 // contributors may be used to endorse or promote products derived from 00016 // this software without specific prior written permission. 00017 // 00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00019 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00020 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00021 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00022 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00023 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00024 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00025 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00026 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00027 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00028 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 // 00030 // --- 00031 // Author: Mike Burrows 00032 00033 #ifndef _SYSINFO_H_ 00034 #define _SYSINFO_H_ 00035 00036 #include "config.h" 00037 00038 #include <time.h> 00039 #ifdef WIN32 00040 #include <windows.h> // for DWORD 00041 #include <TlHelp32.h> // for CreateToolhelp32Snapshot 00042 #endif 00043 #ifdef HAVE_UNISTD_H 00044 #include <unistd.h> // for pid_t 00045 #endif 00046 #include <stddef.h> // for size_t 00047 #include <limits.h> // for PATH_MAX 00048 #include "base/basictypes.h" 00049 00050 // This getenv prefers using /proc/self/environ to calling getenv(). 00051 // It's intended to be used in routines that run before main(), when 00052 // the state required for getenv() may not be set up yet. In particular, 00053 // errno isn't set up until relatively late (after the pthreads library 00054 // has a chance to make it threadsafe), and getenv() doesn't work until then. 00055 // Note that /proc only has the environment at the time the application was 00056 // started, so this routine ignores setenv() calls/etc. Also note it only 00057 // reads the first 16K of the environment. 00058 const char* GetenvBeforeMain(const char* name); 00059 00060 00061 // A ProcMapsIterator abstracts access to /proc/maps for a given 00062 // process. Needs to be stack-allocatable and avoid using stdio/malloc 00063 // so it can be used in the google stack dumper, heap-profiler, etc. 00064 // 00065 // On Windows and Mac OS X, this iterator iterates *only* over DLLs 00066 // mapped into this process space. For Linux, FreeBSD, and Solaris, 00067 // it iterates over *all* mapped memory regions, including anonymous 00068 // mmaps. For other O/Ss, it is unlikely to work at all, and Valid() 00069 // will always return false. Also note: this routine only works on 00070 // FreeBSD if procfs is mounted: make sure this is in your /etc/fstab: 00071 // proc /proc procfs rw 0 0 00072 class ProcMapsIterator { 00073 public: 00074 struct Buffer { 00075 #ifdef __FreeBSD__ 00076 // FreeBSD requires us to read all of the maps file at once, so 00077 // we have to make a buffer that's "always" big enough 00078 static const size_t kBufSize = 102400; 00079 #else // a one-line buffer is good enough 00080 static const size_t kBufSize = PATH_MAX + 1024; 00081 #endif 00082 char buf_[kBufSize]; 00083 }; 00084 00085 00086 // Create a new iterator for the specified pid. pid can be 0 for "self". 00087 explicit ProcMapsIterator(pid_t pid); 00088 00089 // Create an iterator with specified storage (for use in signal 00090 // handler). "buffer" should point to a ProcMapsIterator::Buffer 00091 // buffer can be NULL in which case a bufer will be allocated. 00092 ProcMapsIterator(pid_t pid, Buffer *buffer); 00093 00094 // Iterate through maps_backing instead of maps if use_maps_backing 00095 // is true. Otherwise the same as above. buffer can be NULL and 00096 // it will allocate a buffer itself. 00097 ProcMapsIterator(pid_t pid, Buffer *buffer, 00098 bool use_maps_backing); 00099 00100 // Returns true if the iterator successfully initialized; 00101 bool Valid() const; 00102 00103 // Returns a pointer to the most recently parsed line. Only valid 00104 // after Next() returns true, and until the iterator is destroyed or 00105 // Next() is called again. This may give strange results on non-Linux 00106 // systems. Prefer FormatLine() if that may be a concern. 00107 const char *CurrentLine() const { return stext_; } 00108 00109 // Writes the "canonical" form of the /proc/xxx/maps info for a single 00110 // line to the passed-in buffer. Returns the number of bytes written, 00111 // or 0 if it was not able to write the complete line. (To guarantee 00112 // success, buffer should have size at least Buffer::kBufSize.) 00113 // Takes as arguments values set via a call to Next(). The 00114 // "canonical" form of the line (taken from linux's /proc/xxx/maps): 00115 // <start_addr(hex)>-<end_addr(hex)> <perms(rwxp)> <offset(hex)> + 00116 // <major_dev(hex)>:<minor_dev(hex)> <inode> <filename> Note: the 00117 // eg 00118 // 08048000-0804c000 r-xp 00000000 03:01 3793678 /bin/cat 00119 // If you don't have the dev_t (dev), feel free to pass in 0. 00120 // (Next() doesn't return a dev_t, though NextExt does.) 00121 // 00122 // Note: if filename and flags were obtained via a call to Next(), 00123 // then the output of this function is only valid if Next() returned 00124 // true, and only until the iterator is destroyed or Next() is 00125 // called again. (Since filename, at least, points into CurrentLine.) 00126 static int FormatLine(char* buffer, int bufsize, 00127 uint64 start, uint64 end, const char *flags, 00128 uint64 offset, int64 inode, const char *filename, 00129 dev_t dev); 00130 00131 // Find the next entry in /proc/maps; return true if found or false 00132 // if at the end of the file. 00133 // 00134 // Any of the result pointers can be NULL if you're not interested 00135 // in those values. 00136 // 00137 // If "flags" and "filename" are passed, they end up pointing to 00138 // storage within the ProcMapsIterator that is valid only until the 00139 // iterator is destroyed or Next() is called again. The caller may 00140 // modify the contents of these strings (up as far as the first NUL, 00141 // and only until the subsequent call to Next()) if desired. 00142 00143 // The offsets are all uint64 in order to handle the case of a 00144 // 32-bit process running on a 64-bit kernel 00145 // 00146 // IMPORTANT NOTE: see top-of-class notes for details about what 00147 // mapped regions Next() iterates over, depending on O/S. 00148 // TODO(csilvers): make flags and filename const. 00149 bool Next(uint64 *start, uint64 *end, char **flags, 00150 uint64 *offset, int64 *inode, char **filename); 00151 00152 bool NextExt(uint64 *start, uint64 *end, char **flags, 00153 uint64 *offset, int64 *inode, char **filename, 00154 uint64 *file_mapping, uint64 *file_pages, 00155 uint64 *anon_mapping, uint64 *anon_pages, 00156 dev_t *dev); 00157 00158 ~ProcMapsIterator(); 00159 00160 private: 00161 void Init(pid_t pid, Buffer *buffer, bool use_maps_backing); 00162 00163 char *ibuf_; // input buffer 00164 char *stext_; // start of text 00165 char *etext_; // end of text 00166 char *nextline_; // start of next line 00167 char *ebuf_; // end of buffer (1 char for a nul) 00168 #if defined(WIN32) 00169 HANDLE snapshot_; // filehandle on dll info 00170 // In a change from the usual W-A pattern, there is no A variant of 00171 // MODULEENTRY32. Tlhelp32.h #defines the W variant, but not the A. 00172 // We want the original A variants, and this #undef is the only 00173 // way I see to get them. Redefining it when we're done prevents us 00174 // from affecting other .cc files. 00175 # ifdef MODULEENTRY32 // Alias of W 00176 # undef MODULEENTRY32 00177 MODULEENTRY32 module_; // info about current dll (and dll iterator) 00178 # define MODULEENTRY32 MODULEENTRY32W 00179 # else // It's the ascii, the one we want. 00180 MODULEENTRY32 module_; // info about current dll (and dll iterator) 00181 # endif 00182 #elif defined(__MACH__) 00183 int current_image_; // dll's are called "images" in macos parlance 00184 int current_load_cmd_; // the segment of this dll we're examining 00185 #else 00186 int fd_; // filehandle on /proc/*/maps 00187 #endif 00188 char flags_[10]; 00189 Buffer* dynamic_buffer_; // dynamically-allocated Buffer 00190 bool using_maps_backing_; // true if we are looking at maps_backing instead of maps. 00191 }; 00192 00193 #endif /* #ifndef _SYSINFO_H_ */