freebsdKludges.C

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 #include "common/h/headers.h"
00032 #include <sys/sysctl.h>
00033 #include <sys/types.h>
00034 #include <sys/user.h>
00035 #include <sys/ptrace.h>
00036 #include <sys/proc.h>
00037 #include <libutil.h>
00038 
00039 #include <map>
00040 using std::map;
00041 
00042 #if defined(cap_gnu_demangler)
00043 #include <cxxabi.h>
00044 using namespace __cxxabiv1;
00045 #endif
00046 
00047 char * P_cplus_demangle( const char * symbol, bool,
00048                 bool includeTypes ) 
00049 {
00050    int opts = 0;
00051    opts |= includeTypes ? DMGL_PARAMS | DMGL_ANSI : 0;
00052 
00053 #if defined(cap_gnu_demangler)
00054    int status;
00055    char *demangled = __cxa_demangle(symbol, NULL, NULL, &status);
00056    if (status == -1) {
00057       //Memory allocation failure.
00058       return NULL;
00059    }
00060    if (status == -2) {
00061       //Not a C++ name
00062       return NULL;
00063    }
00064    assert(status == 0); //Success
00065 #else
00066    char * demangled = cplus_demangle( const_cast< char *>(symbol), opts);
00067 #endif
00068    if( demangled == NULL ) { return NULL; }
00069 
00070    if( ! includeTypes ) {
00071         /* de-demangling never increases the length */   
00072         char * dedemangled = strdup( demangled );   
00073         assert( dedemangled != NULL );
00074         dedemangle( demangled, dedemangled );
00075         assert( dedemangled != NULL );
00076 
00077         free( demangled );
00078         return dedemangled;
00079    }
00080 
00081    return demangled;
00082 }
00083 
00084 // Process Information Queries //
00085 // No procfs mounted by default -- need to rely on sysctl //
00086 
00087 /*
00088  * Gets the full path of the executable for the specified process
00089  *
00090  * pid  The pid for the process
00091  *
00092  * Returns the full path (caller is responsible for free'ing)
00093  */
00094 char *sysctl_getExecPathname(pid_t pid) {
00095     int mib[4];
00096     mib[0] = CTL_KERN;
00097     mib[1] = KERN_PROC;
00098     mib[2] = KERN_PROC_PATHNAME;
00099     mib[3] = pid;
00100 
00101     size_t length;
00102     if( sysctl(mib, 4, NULL, &length, NULL, 0) ) {
00103         return NULL;
00104     }
00105 
00106     char *pathname = (char *)calloc(length, sizeof(char));
00107 
00108     if( !pathname ) return NULL;
00109 
00110     if( sysctl(mib, 4, pathname, &length, NULL, 0) ) {
00111         free(pathname);
00112         return NULL;
00113     }
00114 
00115     return pathname;
00116 }
00117 
00118 static struct kinfo_proc *getProcInfo(pid_t pid, size_t &length, bool getThreads) {
00119     int mib[4];
00120     mib[0] = CTL_KERN;
00121     mib[1] = KERN_PROC;
00122     mib[2] = KERN_PROC_PID | ( getThreads ? KERN_PROC_INC_THREAD : 0 );
00123     mib[3] = pid;
00124 
00125     if( sysctl(mib, 4, NULL, &length, NULL, 0) ) {
00126         return NULL;
00127     }
00128 
00129     struct kinfo_proc *procInfo = (struct kinfo_proc *)malloc(length);
00130     if( !procInfo ) return NULL;
00131 
00132     if( sysctl(mib, 4, procInfo, &length, NULL, 0) ) {
00133         free(procInfo);
00134         return NULL;
00135     }
00136 
00137     assert( length > 0 && "process information not parsed correctly" );
00138 
00139     return procInfo;
00140 }
00141 
00142 map_entries *getVMMaps(int pid, unsigned &maps_size) {
00143     const int VM_PATH_MAX = 512;
00144     struct kinfo_vmentry *maps;
00145     map_entries *retMaps;
00146 
00147     maps = kinfo_getvmmap(pid, (int *)&maps_size);
00148     if( !maps ) {
00149         return NULL;
00150     }
00151 
00152     retMaps = (map_entries *)calloc(maps_size, sizeof(map_entries));
00153     if( !retMaps ) {
00154         free(maps);
00155         return NULL;
00156     }
00157 
00158     // Translate from one structure to another
00159     for(unsigned i = 0; i < maps_size; ++i) {
00160         retMaps[i].start = maps[i].kve_start;
00161         retMaps[i].end = maps[i].kve_end;
00162         retMaps[i].offset = maps[i].kve_offset; 
00163         retMaps[i].dev_major = 0; // N/A
00164         retMaps[i].dev_minor = 0; // N/A
00165         retMaps[i].inode = maps[i].kve_vn_fileid;
00166 
00167         retMaps[i].prems = 0;
00168         if( KVME_PROT_READ & maps[i].kve_protection ) {
00169             retMaps[i].prems |= PREMS_READ;
00170         }
00171 
00172         if( KVME_PROT_WRITE & maps[i].kve_protection ) {
00173             retMaps[i].prems |= PREMS_WRITE;
00174         }
00175 
00176         if( KVME_PROT_EXEC & maps[i].kve_protection ) {
00177             retMaps[i].prems |= PREMS_EXEC;
00178         }
00179 
00180         strncpy(retMaps[i].path, maps[i].kve_path, VM_PATH_MAX-1);
00181         retMaps[i].path[VM_PATH_MAX-1] = '\0';
00182     }
00183 
00184     free(maps);
00185     return retMaps;
00186 }
00187 
00188 int sysctl_computeAddrWidth(pid_t pid) {
00189     int retSize = sizeof(void *);
00190 
00191 #if defined(arch_64bit)
00192     const int X86_ADDR_WIDTH = 4;
00193 
00194     size_t length;
00195     struct kinfo_proc *procInfo = getProcInfo(pid, length, false);
00196     if( NULL == procInfo ) {
00197         return -1;
00198     }
00199 
00200     if( std::string(procInfo->ki_emul).find("ELF32") != std::string::npos ) {
00201         retSize = X86_ADDR_WIDTH;
00202     }
00203     free(procInfo);
00204 #endif
00205 
00206     return retSize;
00207 }
00208 
00209 bool sysctl_findProcLWPs(pid_t pid, std::vector<pid_t> &lwps) {
00210     size_t length;
00211     struct kinfo_proc *procInfo = getProcInfo(pid, length, true);
00212     if( NULL == procInfo ) {
00213         return false;
00214     }
00215 
00216     int numEntries = length / procInfo->ki_structsize;
00217     for(int i = 0; i < numEntries; ++i) {
00218         lwps.push_back(procInfo[i].ki_tid);
00219     }
00220     free(procInfo);
00221 
00222     return true;
00223 }
00224 
00225 lwpid_t sysctl_getInitialLWP(pid_t pid) {
00226     size_t length;
00227     struct kinfo_proc *procInfo = getProcInfo(pid, length, true);
00228     if( NULL == procInfo ) {
00229       fprintf(stderr, "no proc info\n");
00230         return -1;
00231     }
00232 
00233 
00234     int numEntries = length / procInfo->ki_structsize;
00235     // The string won't be set until there are multiple LWPs
00236     if( numEntries == 1 ) {
00237         lwpid_t ret = procInfo->ki_tid;
00238         free(procInfo);
00239         return ret;
00240     }
00241 
00242     // By experimentation, we appear to want the last
00243     // entry. 
00244     //
00245     // "BSD, what the hell" - bill, 24SEP2012, personal communication
00246 
00247     lwpid_t ret = procInfo[numEntries-1].ki_tid;
00248     free(procInfo);
00249     return ret;
00250 #if 0
00251     
00252     for(int i = 0; i < numEntries; ++i) {
00253       fprintf(stderr, "%d: %s\n", i+1, procInfo[i].ki_ocomm);
00254         if( std::string(procInfo[i].ki_ocomm).find("initial") != std::string::npos ) {
00255             lwpid_t ret = procInfo[i].ki_tid;
00256             free(procInfo);
00257             return ret;
00258         }
00259     }
00260 
00261     free(procInfo);
00262     fprintf(stderr, "Failed to find initial thread\n");
00263     return -1;
00264 #endif
00265 }
00266 
00267 // returns true if the process is running
00268 bool sysctl_getRunningStates(pid_t pid, map<Dyninst::LWP, bool> &runningStates) {
00269     size_t length;
00270     struct kinfo_proc *procInfo = getProcInfo(pid, length, true);
00271     if( NULL == procInfo ) {
00272         return false;
00273     }
00274 
00275     int numEntries = length / procInfo->ki_structsize;
00276 
00277     for(int i = 0; i < numEntries; ++i) {
00278         runningStates.insert(std::make_pair(procInfo[i].ki_tid,
00279                 (procInfo[i].ki_flag & P_STOPPED) == 0));
00280     }
00281 
00282     return true;
00283 }
00284 
00285 static bool PtraceBulkAccess(Dyninst::Address inTraced, unsigned size, void *inSelf, int pid, bool read) {
00286     struct ptrace_io_desc io;
00287 
00288     io.piod_op = (read ? PIOD_READ_D : PIOD_WRITE_D);
00289     io.piod_addr = inSelf;
00290     io.piod_offs = (void *)inTraced;
00291     io.piod_len = size;
00292 
00293     unsigned amountRead = 0;
00294 
00295     while( amountRead < size ) {
00296         io.piod_len -= amountRead;
00297         io.piod_addr = ((unsigned char *)io.piod_addr) + amountRead;
00298         io.piod_offs = ((unsigned char *)io.piod_offs) + amountRead;
00299 
00300         if( 0 != ptrace(PT_IO, pid, (caddr_t)&io, 0) ) return false;
00301         amountRead += io.piod_len;
00302     }
00303 
00304     return true;
00305 }
00306 
00307 bool PtraceBulkRead(Dyninst::Address inTraced, unsigned size, void *inSelf, int pid) {
00308     return PtraceBulkAccess(inTraced, size, inSelf, pid, true);
00309 }
00310 
00311 bool PtraceBulkWrite(Dyninst::Address inTraced, unsigned size, const void *inSelf, int pid) {
00312     return PtraceBulkAccess(inTraced, size, (void *)inSelf, pid, false);
00313 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1