Function.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 // $Id: Object.C,v 1.31 2008/11/03 15:19:25 jaw Exp $
00032 
00033 #include "Annotatable.h"
00034 #include "common/h/serialize.h"
00035 
00036 #include "Symtab.h"
00037 #include "symutil.h"
00038 #include "Module.h"
00039 #include "Collections.h"
00040 #include "Function.h"
00041 #include "dynutil/h/VariableLocation.h"
00042 #include "symtabAPI/src/Object.h"
00043 
00044 #if !defined(os_windows)
00045 #include "dwarf/h/dwarfFrameParser.h"
00046 #endif
00047 
00048 #include "annotations.h"
00049 #include <iterator>
00050 #include <algorithm>
00051 
00052 #include <iostream>
00053 
00054 using namespace std;
00055 using namespace Dyninst;
00056 using namespace Dyninst::SymtabAPI;
00057 
00058 Function::Function(Symbol *sym)
00059     : Aggregate(sym),
00060       retType_(NULL), 
00061       framePtrRegNum_(-1),
00062       frameBaseExpanded_(false),
00063       functionSize_(0)
00064 {}
00065 
00066 Function::Function()
00067     : Aggregate(),
00068       retType_(NULL), 
00069       framePtrRegNum_(-1),
00070       frameBaseExpanded_(false),
00071       functionSize_(0)
00072 {}
00073 
00074 Type * Function::getReturnType() const
00075 {
00076     return retType_;
00077 }
00078 
00079 bool Function::setReturnType(Type *newType)
00080 {
00081     retType_ = newType;
00082     return true;
00083 }
00084 
00085 int Function::getFramePtrRegnum() const
00086 {
00087     return framePtrRegNum_;
00088 }
00089 
00090 bool Function::setFramePtrRegnum(int regnum)
00091 {
00092     framePtrRegNum_ = regnum;
00093     return true;
00094 }
00095 
00096 Offset Function::getPtrOffset() const
00097 {
00098     Offset retval = 0;
00099     for (unsigned i = 0; i < symbols_.size(); ++i) {
00100         Offset tmp_off = symbols_[i]->getPtrOffset();
00101         if (tmp_off) {
00102            if (retval == 0) retval = tmp_off;
00103            assert(retval == tmp_off);
00104         }
00105     }
00106     return retval;
00107 }
00108 
00109 Offset Function::getTOCOffset() const
00110 {
00111     Offset retval = 0;
00112     for (unsigned i = 0; i < symbols_.size(); ++i) {
00113         Offset tmp_toc = symbols_[i]->getLocalTOC();
00114         if (tmp_toc) {
00115             if (retval == 0) retval = tmp_toc;
00116             assert(retval == tmp_toc);
00117         }
00118     }
00119     return retval;
00120 }
00121 
00122 std::vector<Dyninst::VariableLocation> &Function::getFramePtrRefForInit() {
00123    return frameBase_;
00124 }
00125 
00126 std::vector<Dyninst::VariableLocation> &Function::getFramePtr() 
00127 {
00128    if (frameBaseExpanded_)
00129       return frameBase_;
00130 
00131    frameBaseExpanded_ = true;
00132 
00133    std::vector<VariableLocation> orig;
00134    orig.swap(frameBase_);
00135 
00136    for (unsigned i = 0; i < orig.size(); ++i) {
00137       expandLocation(orig[i], frameBase_);
00138    }
00139 
00140    return frameBase_;
00141 }
00142 
00143 bool Function::setFramePtr(vector<VariableLocation> *locs) 
00144 {
00145    frameBase_.clear();
00146    std::copy(locs->begin(), locs->end(), std::back_inserter(frameBase_));
00147    return true;
00148 }
00149 
00150 void Function::expandLocation(const VariableLocation &loc,
00151                               std::vector<VariableLocation> &ret) {
00152    // We are the frame base, so... WTF? 
00153 
00154    assert(loc.mr_reg != Dyninst::FrameBase);
00155 
00156 #if defined(os_windows) 
00157    ret.push_back(loc);
00158    return;
00159 #else
00160    if (loc.mr_reg != Dyninst::CFA) {
00161       ret.push_back(loc);
00162       return;
00163    }
00164 
00165    Dyninst::Dwarf::DwarfFrameParser::Ptr frameParser =
00166       Dyninst::Dwarf::DwarfFrameParser::create(*module_->exec()->getObject()->dwarf->frame_dbg(),
00167                                                module_->exec()->getObject()->getArch());
00168    
00169    std::vector<VariableLocation> FDEs;
00170    Dyninst::Dwarf::FrameErrors_t err;
00171    frameParser->getRegsForFunction(getOffset(),
00172                                    Dyninst::CFA,
00173                                    FDEs,
00174                                    err);
00175 
00176 
00177    if (FDEs.empty()) {
00178       // Odd, but happens
00179       return;
00180    }
00181 
00182    // This looks surprisingly similar to localVar's version...
00183    // Perhaps we should unify. 
00184 
00185    std::vector<VariableLocation>::iterator i;
00186    for (i = FDEs.begin(); i != FDEs.end(); i++) 
00187    {
00188       Offset fdelowPC = i->lowPC;
00189       Offset fdehiPC = i->hiPC;
00190 
00191       Offset frame_lowPC = loc.lowPC;
00192       Offset frame_hiPC = loc.hiPC;
00193 
00194       if (frame_hiPC < fdehiPC) {
00195          // We're done since the variable proceeds the frame
00196          // base
00197          break;
00198       }
00199 
00200       // low is MAX(frame_lowPC, fdelowPC)
00201       Offset low = (frame_lowPC < fdelowPC) ? fdelowPC : frame_lowPC;
00202 
00203       // high is MIN(frame_hiPC, fdehiPC)
00204       Offset high = (frame_hiPC < fdehiPC) ? frame_hiPC : fdehiPC;
00205 
00206       VariableLocation newloc;
00207 
00208       newloc.stClass = loc.stClass;
00209       newloc.refClass = loc.refClass;
00210       newloc.mr_reg = i->mr_reg;
00211       newloc.frameOffset = loc.frameOffset + i->frameOffset;
00212       newloc.lowPC = low;
00213       newloc.hiPC = high;
00214 
00215 /*
00216       cerr << "Created frame pointer ["
00217            << hex << newloc.lowPC << ".." << newloc.hiPC
00218            << "], reg " << newloc.mr_reg.name()
00219            << " /w/ offset " << newloc.frameOffset
00220            << " = (" << loc.frameOffset 
00221            << "+" << i->frameOffset << ")" 
00222            << ", " 
00223            << storageClass2Str(newloc.stClass)
00224            << ", " 
00225            << storageRefClass2Str(newloc.refClass) << endl;
00226 */
00227 
00228 
00229       ret.push_back(newloc);
00230    }
00231    return;
00232 #endif
00233 }
00234 
00235 bool Function::findLocalVariable(std::vector<localVar *> &vars, std::string name)
00236 {
00237    module_->exec()->parseTypesNow();    
00238 
00239    localVarCollection *lvs = NULL, *lps = NULL;
00240    bool res1 = false, res2 = false;
00241    res1 = getAnnotation(lvs, FunctionLocalVariablesAnno);
00242    res2 = getAnnotation(lps, FunctionParametersAnno);
00243 
00244    if (!res1 && !res2)
00245       return false;
00246 
00247    unsigned origSize = vars.size(); 
00248 
00249    if (lvs)
00250    {
00251       localVar *var = lvs->findLocalVar(name);
00252       if (var) 
00253          vars.push_back(var);
00254    }
00255 
00256    if (lps)
00257    {
00258       localVar *var = lps->findLocalVar(name);
00259       if (var) 
00260          vars.push_back(var);
00261    }
00262 
00263    if (vars.size() > origSize)
00264       return true;
00265 
00266    return false;
00267 }
00268 
00269 bool Function::getLocalVariables(std::vector<localVar *> &vars)
00270 {
00271    module_->exec()->parseTypesNow();    
00272 
00273    localVarCollection *lvs = NULL;
00274    if (!getAnnotation(lvs, FunctionLocalVariablesAnno))
00275    {
00276       return false;
00277    }
00278    if (!lvs)
00279    {
00280       return false;
00281    }
00282 
00283    std::vector<localVar *> &p = *lvs->getAllVars();
00284    std::copy(p.begin(), p.end(), back_inserter(vars));
00285    
00286    if (p.empty())
00287       return false;
00288    return true;
00289 }
00290 
00291 bool Function::getParams(std::vector<localVar *> &params)
00292 {
00293    module_->exec()->parseTypesNow();
00294 
00295    localVarCollection *lvs = NULL;
00296    if (!getAnnotation(lvs, FunctionParametersAnno))
00297    {
00298       if (!setupParams())
00299       {
00300          return false;
00301       }
00302 
00303       if (!getAnnotation(lvs, FunctionParametersAnno))
00304       {
00305          return false;
00306       }
00307    }
00308 
00309    if (!lvs)
00310       return false;
00311 
00312    std::vector<localVar *> &p = *lvs->getAllVars();
00313    std::copy(p.begin(), p.end(), back_inserter(params));
00314 
00315    if (p.empty())
00316       return false;
00317    return true;
00318 }
00319 
00320 bool Function::addLocalVar(localVar *locVar)
00321 {
00322    localVarCollection *lvs = NULL;
00323 
00324    if (!getAnnotation(lvs, FunctionLocalVariablesAnno))
00325    {
00326       lvs = new localVarCollection();
00327 
00328       if (!addAnnotation(lvs, FunctionLocalVariablesAnno))
00329       {
00330          return false;
00331       }
00332    }
00333    if (!lvs)
00334       return false;
00335 
00336    lvs->addLocalVar(locVar);
00337    return true;
00338 }
00339 
00340 bool Function::addParam(localVar *param)
00341 {
00342     localVarCollection *ps = NULL;
00343    if (!setupParams())
00344    {
00345       return false;
00346    }
00347 
00348     if (!getAnnotation(ps, FunctionParametersAnno))
00349     {
00350       return false;
00351     }
00352    
00353     ps->addLocalVar(param);
00354 
00355     return true;
00356 }
00357 
00358 bool Function::setupParams()
00359 {
00360     localVarCollection *ps = NULL;
00361 
00362     if (!getAnnotation(ps, FunctionParametersAnno))
00363     {
00364         ps = new localVarCollection();
00365 
00366         if (!addAnnotation(ps, FunctionParametersAnno))
00367         {
00368             fprintf(stderr, "%s[%d]:  failed to add local var collecton anno\n", 
00369                     FILE__, __LINE__);
00370             return false;
00371         }
00372     }
00373         
00374    return true;
00375 }
00376 
00377 Function::~Function()
00378 {
00379    localVarCollection *lvs = NULL;
00380    if (getAnnotation(lvs, FunctionLocalVariablesAnno) && (NULL != lvs))
00381    {
00382        if (!removeAnnotation(FunctionLocalVariablesAnno))
00383        {
00384            fprintf(stderr, "%s[%d]:  ERROR removing local vars\n", FILE__, __LINE__);
00385        }
00386        delete lvs;
00387    }
00388 
00389    localVarCollection *lps = NULL;
00390    if (getAnnotation(lps, FunctionParametersAnno) && (NULL != lps))
00391    {
00392        if (!removeAnnotation(FunctionParametersAnno))
00393        {
00394            fprintf(stderr, "%s[%d]:  ERROR removing params\n", FILE__, __LINE__);
00395        }
00396        delete lps;
00397    }
00398 
00399 }
00400 
00401 #if !defined(SERIALIZATION_DISABLED)
00402 Serializable *Function::serialize_impl(SerializerBase *sb, const char *tag) THROW_SPEC (SerializerError)
00403 {
00404     if (!sb) SER_ERR("bad paramater sb");
00405 
00406 
00407 
00408     //  Use typeID as unique identifier
00409     unsigned int t_id = retType_ ? retType_->getID() : (unsigned int) 0xdeadbeef;
00410 
00411         ifxml_start_element(sb, tag);
00412         gtranslate(sb, t_id, "typeID");
00413         gtranslate(sb, framePtrRegNum_, "framePointerRegister");
00414 #if 0
00415         gtranslate(sb, frameBase_, "framePointerLocationList");
00416 #endif
00417         Aggregate::serialize_aggregate(sb);
00418         ifxml_end_element(sb, tag);
00419         if (sb->isInput())
00420         {
00421             if (t_id == 0xdeadbeef)
00422                 retType_ = NULL;
00423             else
00424                 restore_type_by_id(sb, retType_, t_id);
00425 #if 0
00426             for (unsigned long i = 0; i < symbols_.size(); ++i)
00427             {
00428                 symbols_[i]->setFunction(this);
00429                 assert(symbols_[i]->isFunction());
00430             }
00431 #endif
00432         }
00433 
00434     serialize_printf("%s[%d]:  Function(%p--%s)::%s\n", FILE__, __LINE__, this,
00435             getAllPrettyNames().size() ? getAllPrettyNames()[0].c_str() : "UNNAMED_FUNCTION",
00436             sb->isInput() ? "deserialize" : "serialize");
00437     return NULL;
00438 }
00439 #else
00440 Serializable *Function::serialize_impl(SerializerBase *, const char *) THROW_SPEC (SerializerError)
00441 {
00442    return NULL;
00443 }
00444 #endif
00445 
00446 bool Function::removeSymbol(Symbol *sym) 
00447 {
00448     removeSymbolInt(sym);
00449     if (symbols_.empty()) {
00450         module_->exec()->deleteFunction(this);
00451     }
00452     return true;
00453 }
00454 
00455 std::ostream &operator<<(std::ostream &os, const Dyninst::VariableLocation &l)
00456 {
00457     const char *stc = storageClass2Str(l.stClass);
00458     const char *strc = storageRefClass2Str(l.refClass);
00459     os << "{"
00460            << "storageClass=" << stc
00461            << " storageRefClass=" << strc
00462            << " reg=" << l.mr_reg.name() 
00463            << " frameOffset=" << l.frameOffset
00464            << " lowPC=" << l.lowPC
00465            << " hiPC=" << l.hiPC
00466            << "}";
00467     return os;
00468 }
00469 
00470 std::ostream &operator<<(std::ostream &os, const Dyninst::SymtabAPI::Function &f)
00471 {
00472     Type *retType = (const_cast<Function &>(f)).getReturnType();
00473 
00474     std::string tname(retType ? retType->getName() : "no_type");
00475     const Aggregate *ag = dynamic_cast<const Aggregate *>(&f);
00476     assert(ag);
00477 
00478     os  << "Function{"
00479         << " type=" << tname
00480             << " framePtrRegNum_=" << f.getFramePtrRegnum()
00481         << " FramePtrLocationList=[";
00482 #if 0
00483     for (unsigned int i = 0; i < f.frameBase_.size(); ++i)
00484     {
00485         os << f.frameBase_[i]; 
00486         if ( (i + 1) < f.frameBase_.size())
00487             os << ", ";
00488     }
00489 #endif
00490     os  << "] ";
00491     os  <<  *ag;
00492     os  <<  "}";
00493     return os;
00494 
00495 }
00496 
00497 bool Function::operator==(const Function &f)
00498 {
00499     if (retType_ && !f.retType_)
00500         return false;
00501     if (!retType_ && f.retType_)
00502         return false;
00503     if (retType_)
00504         if (retType_->getID() != f.retType_->getID())
00505         {
00506             return false;
00507         }
00508 
00509     if (framePtrRegNum_ != f.framePtrRegNum_)
00510         return false;
00511 
00512 #if 0
00513     if (frameBase_.size() != f.frameBase_.size())
00514         return false;
00515 
00516     for (unsigned int i = 0; i < frameBase_.size(); ++i)
00517     {
00518         if (frameBase_[i] == frameBase_[i])
00519             return false;
00520     }
00521 #endif
00522 
00523     return ((Aggregate &)(*this)) == ((Aggregate &)f);
00524 }
00525 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1