00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
00058 return NULL;
00059 }
00060 if (status == -2) {
00061
00062 return NULL;
00063 }
00064 assert(status == 0);
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
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
00085
00086
00087
00088
00089
00090
00091
00092
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
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;
00164 retMaps[i].dev_minor = 0;
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
00236 if( numEntries == 1 ) {
00237 lwpid_t ret = procInfo->ki_tid;
00238 free(procInfo);
00239 return ret;
00240 }
00241
00242
00243
00244
00245
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
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 }