Archive.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 "symtabAPI/h/Symtab.h"
00032 #include "symtabAPI/h/Archive.h"
00033 #include "symtabAPI/src/Object.h"
00034 
00035 #include <iostream>
00036 
00037 using namespace Dyninst;
00038 using namespace Dyninst::SymtabAPI;
00039 
00040 /*
00041  * A generic interface for handling archives (aka .a files)
00042  *
00043  * Specifics of the format for the .a files are handled per platform.
00044  * See Archive-<platform> files for more info. 
00045  */
00046 
00047 std::vector<Archive *> Archive::allArchives;
00048 std::string Archive::errMsg;
00049 SymtabError Archive::serr;
00050 
00051 // Error messages used by printError
00052 static const std::string PARSE_FAILURE = "Failed to parse the archive: ";
00053 static const std::string NO_MEMBER = "Member not found: ";
00054 static const std::string NOT_ARCHIVE = "File is not an archive";
00055 static const std::string DUPLICATE_SYM = "Duplicate symbol found: ";
00056 static const std::string UNKNOWN_ERR = "Unknown Error";
00057 
00058 // Specific error cases
00059 static const std::string MEMBER_DNE = "member does not exist";
00060 
00061 SymtabError Archive::getLastError()
00062 {
00063     return serr;
00064 }
00065 
00066 std::string Archive::printError(SymtabError err)
00067 {
00068    switch (err) {
00069       case Obj_Parsing:
00070          return PARSE_FAILURE + errMsg;
00071       case No_Such_Member:
00072          return NO_MEMBER + errMsg;
00073       case Not_A_File:
00074          return errMsg;
00075       case Not_An_Archive:
00076          return NOT_ARCHIVE;
00077       case Duplicate_Symbol:
00078          return DUPLICATE_SYM + errMsg;
00079       default:
00080          return UNKNOWN_ERR;
00081    }
00082 }
00083 
00084 std::string Archive::name() {
00085     return mf->filename();
00086 }
00087 
00088 bool Archive::openArchive(Archive * &img, std::string filename)
00089 {
00090     bool err = false;
00091 
00092     // Has the archive already been opened?
00093     std::vector<Archive *>::iterator ar_it;
00094     for (ar_it = allArchives.begin(); ar_it != allArchives.end(); ++ar_it) {
00095         assert( *ar_it != NULL );
00096 
00097         if( (*ar_it)->mf->pathname() == filename ) {
00098             img = *ar_it;
00099             return true;
00100         }
00101     }
00102 
00103     img = new Archive(filename, err);
00104     if (err) {          
00105     allArchives.push_back(img);
00106     } else {
00107     if (img) {
00108             delete img;
00109             img = NULL;
00110         }
00111     }
00112 
00113     return err;
00114 }
00115 
00116 bool Archive::openArchive(Archive * &img, char *mem_image, size_t size)
00117 {
00118     bool err;
00119     // Has the archive already been opened?
00120     std::vector<Archive *>::iterator ar_it;
00121     for (ar_it = allArchives.begin(); ar_it != allArchives.end(); ++ar_it) {
00122         assert( *ar_it != NULL );
00123 
00124         if( (*ar_it)->mf->base_addr() == (void *)mem_image ) {
00125             img = *ar_it;
00126             return true;
00127         }
00128     }
00129 
00130     img = new Archive(mem_image, size, err);
00131     if (err) {
00132         allArchives.push_back(img);
00133     } else {
00134         if (img) {
00135             delete img;
00136             img = NULL;
00137         }
00138     }
00139 
00140     return err;
00141 }
00142 
00143 bool Archive::getMember(Symtab *&img, string& member_name) 
00144 {
00145     dyn_hash_map<string, ArchiveMember *>::iterator mem_it;
00146     mem_it = membersByName.find(member_name);
00147     if ( mem_it == membersByName.end() ) {
00148         serr = No_Such_Member;
00149         errMsg = MEMBER_DNE;
00150         return false;
00151     }
00152 
00153     img = mem_it->second->getSymtab();
00154     if( img == NULL ) {
00155         if( !parseMember(img, mem_it->second) ) {
00156             return false;
00157         }
00158     }
00159 
00160     return true;
00161 }
00162 
00163 bool Archive::getMemberByOffset(Symtab *&img, Offset memberOffset) 
00164 {
00165     dyn_hash_map<Offset, ArchiveMember *>::iterator off_it;
00166     off_it = membersByOffset.find(memberOffset);
00167     if( off_it == membersByOffset.end() ) {
00168         serr = No_Such_Member;
00169         errMsg = MEMBER_DNE;
00170         return false;
00171     }
00172 
00173     img = off_it->second->getSymtab();
00174     if( img == NULL ) {
00175         if( !parseMember(img, off_it->second) ) {
00176             return false;
00177         }
00178     }
00179 
00180     return true;
00181 }
00182 
00183 bool Archive::getMemberByGlobalSymbol(Symtab *&img, string& symbol_name) 
00184 {
00185     if( !symbolTableParsed ) {
00186        if( !parseSymbolTable() ) {
00187             return false;
00188        }
00189     }
00190 
00191     std::pair<std::multimap<string, ArchiveMember *>::iterator,
00192               std::multimap<string, ArchiveMember *>::iterator> range_it;
00193     range_it = membersBySymbol.equal_range(symbol_name);
00194 
00195     // Symbol not found in symbol table
00196     if( range_it.first == range_it.second ) {
00197         serr = No_Such_Member;
00198         errMsg = MEMBER_DNE;
00199         return false;
00200     }
00201     ArchiveMember *foundMember = range_it.first->second;
00202 
00203     // Duplicate symbol found in symbol table
00204     ++(range_it.first);
00205     if( range_it.first != range_it.second ) {
00206         serr = Duplicate_Symbol;
00207         errMsg = symbol_name;
00208         return false;
00209     }
00210 
00211     img = foundMember->getSymtab();
00212     if( img == NULL ) {
00213         if( !parseMember(img, foundMember) ) {
00214             return false;
00215         }
00216     }
00217 
00218     return true;
00219 }
00220 
00221 bool Archive::getMembersBySymbol(std::string name,
00222                                  std::vector<Symtab *> &matches) {
00223    if (!symbolTableParsed && !parseSymbolTable())
00224       return false;
00225    
00226    std::pair<std::multimap<string, ArchiveMember *>::iterator,
00227       std::multimap<string, ArchiveMember *>::iterator> range_it;
00228    
00229    range_it = membersBySymbol.equal_range(name);
00230    auto begin = range_it.first;
00231    auto end = range_it.second;
00232 
00233    for (; begin != end; ++begin) {
00234       ArchiveMember *member = begin->second;
00235       Symtab *img = member->getSymtab();
00236       if (!img && !parseMember(img, member)) return false;
00237       matches.push_back(img);
00238    }
00239          
00240    return true;
00241 }
00242 
00243 bool Archive::getAllMembers(vector<Symtab *> &members) 
00244 {
00245     dyn_hash_map<string, ArchiveMember *>::iterator mem_it;
00246     for(mem_it = membersByName.begin(); mem_it != membersByName.end(); ++mem_it) {
00247         Symtab *img = mem_it->second->getSymtab();
00248         if( img == NULL) {
00249             if( !parseMember(img, mem_it->second) ) {
00250                 return false;
00251             }
00252         }
00253         members.push_back(mem_it->second->getSymtab());
00254     }
00255     return true;
00256 }
00257 
00258 bool Archive::isMemberInArchive(std::string& member_name) 
00259 {
00260     if (membersByName.count(member_name)) return true;
00261     return false;
00262 }
00263 
00264 /**
00265  * This method differs from getMemberByGlobalSymbol in that it searches the
00266  * underlying Symtab objects in the archive for the symbol while
00267  * getMemberByGlobalSymbol searches the Archive's symbol table.
00268  *
00269  * The reasoning behind this is that searching the Archive's symbol table will
00270  * be faster than using the Symtab interface because the underlying Symtab
00271  * object is only created when the symbol is found in the Archive's symbol table.
00272  * Contrary to this, findMemberWithDefinition requires creating Symtab objects
00273  * for every member in an Archive and then searching each of these Symtab objects
00274  * for the symbol.
00275  */
00276 bool Archive::findMemberWithDefinition(Symtab * &obj, std::string& name)
00277 {
00278     std::vector<Symtab *> members;
00279     if( !getAllMembers(members) ) {
00280         return false;
00281     }
00282 
00283     std::vector<Symtab *>::iterator obj_it;
00284     for (obj_it = members.begin(); obj_it != members.end(); ++obj_it) {
00285         std::vector<Symbol *> syms;
00286     if ((*obj_it)->findSymbol(syms, name, Symbol::ST_UNKNOWN)) {
00287             obj = *obj_it;
00288             return true;
00289     }
00290     }
00291 
00292     serr = No_Such_Member;
00293     errMsg = MEMBER_DNE;
00294     return false;
00295 }
00296 
00297 Archive::~Archive()
00298 {
00299     dyn_hash_map<string, ArchiveMember *>::iterator it;
00300     for (it = membersByName.begin(); it != membersByName.end(); ++it) {
00301         if (it->second) delete it->second;
00302     }
00303 
00304     for (unsigned i = 0; i < allArchives.size(); i++) {
00305         if (allArchives[i] == this)
00306             allArchives.erase(allArchives.begin()+i);
00307     }
00308 
00309     if (mf) {
00310       MappedFile::closeMappedFile(mf);
00311     }
00312     // who allocated basePtr? they should delete it...
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