MappedFile.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 #include "common/h/MappedFile.h"
00031 #include "common/h/pathName.h"
00032 #include <iostream>
00033 using namespace std;
00034 
00035 dyn_hash_map<std::string, MappedFile *> MappedFile::mapped_files;
00036 
00037 MappedFile *MappedFile::createMappedFile(std::string fullpath_)
00038 {
00039    //fprintf(stderr, "%s[%d]:  createMappedFile %s\n", FILE__, __LINE__, fullpath_.c_str());
00040    if (mapped_files.find(fullpath_) != mapped_files.end()) {
00041       //fprintf(stderr, "%s[%d]:  mapped file exists for %s\n", FILE__, __LINE__, fullpath_.c_str());
00042       MappedFile  *ret = mapped_files[fullpath_];
00043       if (ret->can_share) {
00044          ret->refCount++;
00045          return ret;
00046       }
00047    }
00048 
00049    bool ok = false;
00050    MappedFile *mf = new MappedFile(fullpath_, ok);
00051    if (!mf) {
00052        return NULL;
00053    }
00054 
00055    if (!ok) {
00056 
00057 #if defined(os_vxworks)
00058       // vxWorks may request to open files that exist only on the remote
00059       // target.  Return a placeholder mapped file to hold filename only.
00060       mf->remote_file = true;
00061       mf->can_share = true;
00062       mf->map_addr = 0x0;
00063       mf->fd = -1;
00064 
00065       ok = true;
00066 #elif defined(os_windows)
00067       if (std::string::npos != fullpath_.find(".dll") &&
00068           std::string::npos == fullpath_.find("\\"))
00069       {
00070           size_t envLen = 64;
00071           char *buf = (char*) malloc(envLen);
00072           bool repeat = false;
00073           do {
00074               repeat = false;
00075               if (getenv_s(&envLen, buf, envLen, "windir")) {
00076                   if (envLen > 64) { // error due to size problem
00077                       repeat = true;
00078                       free(buf);
00079                       buf = (char*) malloc(envLen);
00080                   }
00081               }
00082           } while(repeat); // repeat once if needed
00083           fullpath_ = buf + ("\\system32\\" + fullpath_);
00084           free(buf);
00085           return MappedFile::createMappedFile(fullpath_);
00086       }
00087       else {
00088           delete mf;
00089           return NULL;
00090       }
00091 #else
00092       delete mf;
00093       return NULL;
00094 #endif
00095    }
00096 
00097    mapped_files[fullpath_] = mf;
00098 
00099    //fprintf(stderr, "%s[%d]:  MMAPFILE %s: mapped_files.size() =  %d\n", FILE__, __LINE__, fullpath_.c_str(), mapped_files.size());
00100    return mf;
00101 }
00102 
00103 MappedFile::MappedFile(std::string fullpath_, bool &ok) :
00104    fullpath(fullpath_),
00105        map_addr(NULL),
00106 #if defined(os_windows)
00107        hMap(NULL),
00108        hFile(NULL),
00109 #endif
00110    remote_file(false),
00111    did_mmap(false),
00112    did_open(false),
00113    can_share(true),
00114    refCount(1)
00115 {
00116   ok = check_path(fullpath);
00117   if (!ok) {
00118       return;
00119   }
00120   ok = open_file();
00121   if (!ok) return;
00122   ok = map_file();
00123 
00124   //  I think on unixes we can close the fd after mapping the file, 
00125   //  but is this really somehow better?
00126 }
00127 
00128 MappedFile *MappedFile::createMappedFile(void *loc, unsigned long size_, const std::string &name)
00129 {
00130    bool ok = false;
00131    MappedFile *mf = new MappedFile(loc, size_, name, ok);
00132    if (!mf || !ok) {
00133       if (mf)
00134          delete mf;
00135       return NULL;
00136   }
00137 
00138   return mf;
00139 }
00140 
00141 MappedFile::MappedFile(void *loc, unsigned long size_, const std::string &name, bool &ok) :
00142    fullpath(name),
00143     map_addr(NULL),
00144 #if defined(os_windows)
00145     hMap(NULL),
00146     hFile(NULL),
00147 #endif
00148        remote_file(false),
00149    did_mmap(false),
00150    did_open(false),
00151    can_share(true),
00152    refCount(1)
00153 {
00154   ok = open_file(loc, size_);
00155 #if defined(os_windows)  
00156   if (!ok) {
00157       return;
00158   }
00159   //ok = map_file();
00160   map_addr = loc;
00161   this->file_size = size_;
00162 #endif
00163 }
00164 
00165 void MappedFile::closeMappedFile(MappedFile *&mf)
00166 {
00167    if (!mf) 
00168    {
00169       fprintf(stderr, "%s[%d]:  BAD NEWS:  called closeMappedFile(NULL)\n", FILE__, __LINE__);
00170       return;
00171    }
00172 
00173   //fprintf(stderr, "%s[%d]:  welcome to closeMappedFile() refCount = %d\n", FILE__, __LINE__, mf->refCount);
00174    mf->refCount--;
00175 
00176    if (mf->refCount <= 0) 
00177    {
00178       dyn_hash_map<std::string, MappedFile *>::iterator iter;
00179       iter = mapped_files.find(mf->pathname());
00180 
00181       if (iter != mapped_files.end()) 
00182       {
00183          mapped_files.erase(iter);
00184       }
00185 
00186       //fprintf(stderr, "%s[%d]:  DELETING mapped file\n", FILE__, __LINE__);
00187       //  dtor handles unmap and close
00188 
00189       delete mf;
00190       mf = NULL;
00191    }
00192 }
00193 
00194 bool MappedFile::clean_up()
00195 {
00196    if (did_mmap) {
00197       if (!unmap_file()) goto err;
00198    }
00199    if (did_open) {
00200       if (!close_file()) goto err;
00201    }
00202    return true;
00203 
00204 err:
00205    fprintf(stderr, "%s[%d]:  error unmapping file %s\n", 
00206          FILE__, __LINE__, fullpath.c_str() );
00207    return false;
00208 }
00209 
00210 MappedFile::~MappedFile()
00211 {
00212   //  warning, destructor should not allowed to throw exceptions
00213    if (did_mmap)  {
00214       //fprintf(stderr, "%s[%d]: unmapping %s\n", FILE__, __LINE__, fullpath.c_str());
00215       unmap_file();
00216    }
00217    if (did_open) 
00218       close_file();
00219 }
00220 
00221 bool MappedFile::check_path(std::string &filename)
00222 {
00223    struct stat statbuf;
00224    if (0 != stat(filename.c_str(), &statbuf)) {
00225       char ebuf[1024];
00226 #if defined(os_windows)
00227       LPVOID lpMsgBuf;
00228       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
00229             |     FORMAT_MESSAGE_IGNORE_INSERTS,    NULL,
00230             GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)
00231             &lpMsgBuf,    0,    NULL );
00232 
00233       sprintf(ebuf, "stat: %s", (char *) lpMsgBuf);
00234       LocalFree(lpMsgBuf);
00235 #else
00236       sprintf(ebuf, "stat: %s", strerror(errno));
00237 #endif
00238       goto err;
00239    }
00240 
00241    file_size = statbuf.st_size;
00242 
00243    return true;
00244 
00245 err:
00246    return false;
00247 }
00248 
00249 bool MappedFile::open_file(void *loc, unsigned long size_)
00250 {
00251 #if defined(os_windows)
00252    hFile = LocalHandle( loc );  //For a mem image
00253    if (!hFile) {
00254       LPVOID lpMsgBuf;
00255       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
00256                     FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
00257                     GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
00258                     (LPTSTR) &lpMsgBuf, 0, NULL);
00259 
00260       char ebuf[1024];
00261       sprintf(ebuf, "CreateFileMapping failed: %s", (char *) lpMsgBuf);
00262       LocalFree(lpMsgBuf);
00263       goto err;
00264    }
00265    did_open = true;
00266 
00267    return true;
00268 err:
00269    fprintf(stderr, "%s[%d]: failed to open file\n", FILE__, __LINE__);
00270    return false;
00271 #else
00272    map_addr = loc;
00273    file_size = size_;
00274    did_open = false;
00275    fd = -1;
00276    return true;
00277 #endif
00278 }
00279 
00280 bool MappedFile::open_file()
00281 {
00282 #if defined(os_windows)
00283    hFile = CreateFile(fullpath.c_str(), GENERIC_READ, FILE_SHARE_READ,
00284          NULL,OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
00285    if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
00286       LPVOID lpMsgBuf;
00287       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
00288             |     FORMAT_MESSAGE_IGNORE_INSERTS,    NULL,
00289             GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)
00290             &lpMsgBuf,    0,    NULL );
00291 
00292       char ebuf[1024];
00293       sprintf(ebuf, "CreateFileMapping failed: %s", (char *) lpMsgBuf);
00294       LocalFree(lpMsgBuf);
00295       goto err;
00296    }
00297 #else
00298    fd = open(fullpath.c_str(), O_RDONLY);
00299    if (-1 == fd) {
00300       char ebuf[1024];
00301       sprintf(ebuf, "open(%s) failed: %s", fullpath.c_str(), strerror(errno));
00302       goto err;
00303    }
00304 #endif
00305 
00306    did_open = true;
00307    return true;
00308 err:
00309    fprintf(stderr, "%s[%d]: failed to open file\n", FILE__, __LINE__);
00310    return false;
00311 }
00312 
00313 bool MappedFile::map_file()
00314 {
00315    char ebuf[1024];
00316 #if defined(os_windows)
00317 
00318    // map the file to our address space
00319    // first, create a file mapping object
00320    
00321    hMap = CreateFileMapping( hFile,
00322          NULL,           // security attrs
00323          PAGE_READONLY,  // protection flags
00324          0,              // max size - high DWORD
00325          0,              // max size - low DWORD
00326          NULL );         // mapping name - not used
00327 
00328    if (!hMap) {
00329        LPVOID lpMsgBuf;
00330       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
00331             |     FORMAT_MESSAGE_IGNORE_INSERTS,    NULL,
00332             GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)
00333             &lpMsgBuf,    0,    NULL );
00334 
00335       sprintf(ebuf, "CreateFileMapping failed: %s", (char *) lpMsgBuf);
00336       LocalFree(lpMsgBuf);
00337       goto err;
00338    }
00339 
00340    // next, map the file to our address space
00341 
00342    map_addr = MapViewOfFileEx( hMap,             // mapping object
00343          FILE_MAP_COPY,  // desired access
00344          0,              // loc to map - hi DWORD
00345          0,              // loc to map - lo DWORD
00346          0,              // #bytes to map - 0=all
00347          NULL );         // suggested map addr
00348    if (!map_addr) {
00349         LPVOID lpMsgBuf;
00350       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
00351             |     FORMAT_MESSAGE_IGNORE_INSERTS,    NULL,
00352             GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)
00353             &lpMsgBuf,    0,    NULL );
00354 
00355       sprintf(ebuf, "MapViewOfFileEx failed: %s", (char *) lpMsgBuf);
00356       LocalFree(lpMsgBuf);
00357       goto err;
00358    }
00359 
00360 #else
00361 
00362    int mmap_prot  = PROT_READ;
00363    int mmap_flags = MAP_SHARED;
00364 
00365 #if defined(os_vxworks)   
00366    // VxWorks kernel modules have relocations which need to be
00367    // overwritten in memory.
00368    //
00369    // XXX - We don't overwrite our memory image with relocations from the
00370    // target memory space yet due to performance concerns.  If we decide
00371    // to go this route, it would simplify a lot of the Dyninst internals.
00372    mmap_prot  = PROT_READ | PROT_WRITE;
00373    mmap_flags = MAP_PRIVATE;
00374 #endif
00375 
00376    map_addr = mmap(0, file_size, mmap_prot, mmap_flags, fd, 0);
00377    if (MAP_FAILED == map_addr) {
00378       sprintf(ebuf, "mmap(0, %lu, prot=0x%x, flags=0x%x, %d, 0): %s", 
00379             file_size, mmap_prot, mmap_flags, fd, strerror(errno));
00380       goto err;
00381    }
00382 
00383 #endif
00384 
00385    did_mmap = true;
00386    return true;
00387 err:
00388    return false;
00389 }
00390 
00391 bool MappedFile::unmap_file()
00392 {
00393    if (remote_file) {
00394       return true;
00395    }
00396 
00397 #if defined(os_windows)
00398 
00399    UnmapViewOfFile(map_addr);
00400    CloseHandle(hMap);
00401 
00402 #else
00403 
00404    if ( 0 != munmap(map_addr, file_size))  {
00405       fprintf(stderr, "%s[%d]: failed to unmap file\n", FILE__, __LINE__);
00406       return false;
00407    }
00408    
00409    map_addr = NULL;
00410 #endif
00411    return true;
00412 }
00413 
00414 bool MappedFile::close_file()
00415 {
00416    if (remote_file) {
00417       return true;
00418    }
00419 
00420 #if defined (os_windows)
00421 
00422    CloseHandle(hFile);
00423 
00424 #else
00425 
00426    if (-1 == close(fd)) {
00427       fprintf(stderr, "%s[%d]: failed to close file\n", FILE__, __LINE__);
00428       return false;
00429    }
00430 
00431 #endif
00432    return true;
00433 }
00434 
00435 std::string MappedFile::pathname() 
00436 {
00437     return fullpath;
00438 }
00439 
00440 std::string MappedFile::filename() 
00441 {
00442     return extract_pathname_tail(fullpath);
00443 }
00444 
00445 void MappedFile::setSharing(bool s)
00446 {
00447    can_share = s;
00448 }
00449 
00450 bool MappedFile::canBeShared()
00451 {
00452    return can_share;
00453 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1