Ejemplo n.º 1
0
bool shgPhases::defineNewSearch(int phaseId, const pdstring &phaseName) {
   assert(!existsById(phaseId));

   shgStruct theStruct(phaseId, phaseName,
		       interp, theTkWindow,
		       horizSBName, vertSBName,
		       currItemLabelName,
		       showTrueNodes, showFalseNodes, showUnknownNodes,
		       showNeverSeenNodes, showActiveNodes, showInactiveNodes,
		       showShadowNodes);

   bool result = false; // so far, nothing has changed

   // possibly pull off the last phase...
   if (theShgPhases.size() > 1) // never touch the "Global Search"
      if (!theShgPhases[theShgPhases.size()-1].everSearched) {
         shgStruct &victimStruct = theShgPhases[theShgPhases.size()-1];
         
//         cout << "shgPhases: throwing out never-searched phase id " << victimStruct.getPhaseId() << " " << victimStruct.phaseName << endl;
         pdstring commandStr = menuName + " delete " + pdstring(theShgPhases.size());
         myTclEval(interp, commandStr);

         victimStruct.fryDag();

         theShgPhases.resize(theShgPhases.size()-1);
            // destructor for shgStruct will fry the shg

         if (currShgPhaseIndex == theShgPhases.size()) {
            // uh oh.  We fried the current search.  We need to make
            // someone else the current search.  But who?  We'll just
            // make it the previous search index.  One will always exist,
            // since we'll never fry the global phase search.
            assert(theShgPhases.size() > 0);
            changeLL(theShgPhases.size()-1);
	    result = true;
	 }
      }

   theShgPhases += theStruct;

   pdstring commandStr = menuName + " add radiobutton -label " +
                       "\"" + phaseName + "\"" +
                       " -command " + "\"" + "shgChangePhase " +
                       pdstring(phaseId) + "\"" +
                       " -variable currShgPhase -value " +
                       pdstring(phaseId);
   myTclEval(interp, commandStr);

   const bool changeTo = (theShgPhases.size()==1);
   if (changeTo)
      if (change(phaseName))
         result = true; // indicates a redraw is called for

   return result;
}
Ejemplo n.º 2
0
void shgPhases::addToStatusDisplay(int phaseId, const pdstring &iMsg) {
   // currently, we do _not_ add a \n to the message for you.
   if (!existsCurrent()) {
      cerr << "addToStatusDisplay: no current phase to display msg:" << endl;
      cerr << iMsg << endl;
      return;
   }

   if (!existsById(phaseId)) {
      //cerr << "addToStatusDisplay: no phase id " << phaseId << " exists to display msg:" << endl;
      //cerr << "\"" << iMsg << "\"" << endl;
      return;
   }

   const bool isCurrShg = (getCurrentId() == phaseId);
   shgStruct &theShgStruct = getByIDLL(phaseId);

   pdstring Msg;
   // auto-prepend "\n" for all but first message
   if (theShgStruct.msgText.length() > 1) Msg = pdstring("\n") + iMsg;
   else Msg=iMsg;

   theShgStruct.msgText += Msg;

   if (isCurrShg) {
      pdstring commandStr = msgTextWindowName + " insert end {" + Msg + "}";
      myTclEval(interp, commandStr);

      commandStr = msgTextWindowName + " yview -pickplace end";
      myTclEval(interp, commandStr);
   }
}
Ejemplo n.º 3
0
//
// This procedure is used when paradyn create a process after 
// reading a configuration file (using option -f).
//
void
ParadynTkGUI::ProcessCmd(pdstring *args)
{

  pdstring command;
  command = pdstring("paradyn process ") + (*args);

  if (Tcl_VarEval(interp,command.c_str(),0)==TCL_ERROR) {
    pdstring msg = pdstring("Tcl interpreter failed in routine ProcessCmd: ");
    msg += pdstring(Tcl_GetStringResult(interp));
    msg += pdstring("Was processing: ");
    msg += command;
    uiMgr->showError(83, P_strdup(msg.c_str()));
  }  
  delete args;
}
Ejemplo n.º 4
0
bool function_is_excluded(BPatch_function *f, pdstring module_name)
{
  char fnamebuf[2048];
  f->getName(fnamebuf, 2048);
  pdstring full_name = module_name + pdstring("/") + pdstring(fnamebuf);

  if (!func_constraint_hash_loaded) {
      if (!cache_func_constraint_hash()) {
          return FALSE;
      }
  }

  if (func_constraint_hash.defines(full_name)) {
      return TRUE;
  }
  return FALSE;
}
Ejemplo n.º 5
0
//
// findVariable
//	scp	- a BPatch_point that defines the scope of the current search
//	name	- name of the variable to find.
//
BPatch_variableExpr *BPatch_image::findVariableInScope(BPatch_point &scp,
        const char *name)
{
    // Get the function to search for it's local variables.
    // XXX - should really use more detailed scoping info here - jkh 6/30/99
    BPatch_function *func = const_cast<BPatch_function *> (scp.getFunction());
    if (!func) {
        pdstring msg = pdstring("point passed to findVariable lacks a function\n address point type passed?");
        showErrorCallback(100, msg);
        return NULL;
    }
    BPatch_localVar *lv = func->findLocalVar(name);

    if (!lv) {
        // look for it in the parameter scope now
        lv = func->findLocalParam(name);
    }
    if (lv) {
        // create a local expr with the correct frame offset or absolute
        //   address if that is what is needed
        return new BPatch_variableExpr(proc, (void *) lv->getFrameOffset(),
                                       lv->getRegister(), lv->getType(), lv->getStorageClass(), &scp);
    }

    // finally check the global scope.
    // return findVariable(name);

    /* If we have something else to try, don't report errors on this failure. */
    bool reportErrors = true;
    char mangledName[100];
    func->getName( mangledName, 100 );
    char * lastScoping = NULL;
    if( strrchr( mangledName, ':' ) != NULL ) {
        reportErrors = false;
    }
    BPatch_variableExpr * gsVar = findVariable( name, reportErrors );

    if( gsVar == NULL ) {
        /* Try finding it with the function's scope prefixed. */

        if( (lastScoping = strrchr( mangledName, ':' )) != NULL ) {
            * (lastScoping + sizeof(char)) = '\0';
            char scopedName[200];
            memmove( scopedName, mangledName, strlen( mangledName ) );
            memmove( scopedName + strlen( mangledName ), name, strlen( name ) );
            scopedName[ strlen( mangledName ) + strlen( name ) ] = '\0';
            bperr( "Searching for scoped name '%s'\n", scopedName );
            gsVar = findVariable( scopedName );
        }
    }
    return gsVar;
}
Ejemplo n.º 6
0
pd_image::pd_image(BPatch_image *d_image, pd_process *p_proc) :
   appImage(d_image), parent_proc(p_proc)
{
   all_pd_images.push_back(this);

   BPatch_Vector<BPatch_module *> *mods = parent_proc->getAllModules();

   for (unsigned int m = 0; m < mods->size(); m++)  {
       BPatch_module *curr = (BPatch_module *) (*mods)[m];
       addModule(curr);
   }

   char namebuf[NAME_LEN];
   d_image->getProgramName(namebuf, NAME_LEN);
   _name = pdstring(namebuf);
   d_image->getProgramFileName(namebuf, NAME_LEN);

   _fname = pdstring(namebuf);

   //fprintf(stderr, "%s[%d]:  new pd_image: '%s'/'%s'\n", 
   //        __FILE__, __LINE__, _name.c_str(), _fname.c_str());
}
Ejemplo n.º 7
0
bool process::getDyninstRTLibName() {
  if (dyninstRT_name.length() == 0) {
    // Get env variable
    if (getenv("DYNINSTAPI_RT_LIB") != NULL) {
      dyninstRT_name = getenv("DYNINSTAPI_RT_LIB");
    }
    else {
      pdstring msg = pdstring( "Environment variable " + pdstring( "DYNINSTAPI_RT_LIB" )
			       + " has not been defined for process " ) + pdstring( getPid() );
      showErrorCallback(101, msg);
      return false;
    }
  }
  // Check to see if the library given exists.
  if (access(dyninstRT_name.c_str(), R_OK)) {
    pdstring msg = pdstring("Runtime library ") + dyninstRT_name
      + pdstring(" does not exist or cannot be accessed!");
    showErrorCallback(101, msg);
    return false;
  }
  return true;
}
Ejemplo n.º 8
0
// initialize: perform initialization tasks on a platform-specific level
bool dynamic_linking::initialize() {
    // First, initialize all platform-specific stuff
    r_debug_addr = 0;
    r_state = 0;
    // First, find if we're a dynamic executable
    pdstring dyn_str = pdstring("DYNAMIC");
    Symbol dyn_sym;
    if( ! proc->getSymbolInfo(dyn_str, dyn_sym)) {
        bperr( "Failed to find string DYNAMIC\n");
        return false; 
    }

    // step 2: find the base address and file descriptor of ld.so.1
    // Three-step process.
    // 1) Examine aux vector for address of the loader
    Address ld_base = 0;
    dyn_lwp *replwp = proc->getRepresentativeLWP();
    if(!(this->get_ld_base_addr(ld_base, replwp->auxv_fd()))) {
        return false;
    }
    
    // 2) Examine virtual address map for the name of the object (inode style)
    char ld_name[128+PRMAPSZ];
    if(!(this->get_ld_name(ld_name, ld_base, replwp->map_fd(),
                           proc->getPid()))) { 
        return false;
    }
    
    // 3) Open that file
    int ld_fd = -1;    
    ld_fd = open(ld_name, O_RDONLY, 0);
    if(ld_fd == -1) {
        perror("LD.SO");
        return false;
    } 

    // step 3: get its symbol table and find r_debug
    if (!(this->find_r_debug(ld_fd,ld_base))) { 
        return false;
    }

    if (!(this->find_dlopen(ld_fd,ld_base))) {
        bperr( "WARNING: we didn't find dlopen in ld.so.1\n");
    }

    P_close(ld_fd);

   dynlinked = true;

    return true;
}
Ejemplo n.º 9
0
void callGraphDisplay::resizeScrollbars() {
   pdstring commandStr = pdstring("resize1Scrollbar ") + horizSBName + " " +
                       pdstring(rootPtr->entire_width(consts)) + " " +
		       pdstring(Tk_Width(consts.theTkWindow));
   myTclEval(interp, commandStr);

   commandStr = pdstring("resize1Scrollbar ") + vertSBName + " " +
                pdstring(rootPtr->entire_height(consts)) + " " +
		pdstring(Tk_Height(consts.theTkWindow));
   myTclEval(interp, commandStr);
}
Ejemplo n.º 10
0
/*
 * BPatch_image::findModule
 *
 * Returns module with <name>, NULL if not found
 */
BPatch_module *BPatch_image::findModuleInt(const char *name, bool substring_match)
{
    if (!name) {
        bperr("%s[%d]:  findModule:  no module name provided\n",
              __FILE__, __LINE__);
        return NULL;
    }

    BPatch_module *target = NULL;

    char buf[512];
    for (unsigned int i = 0; i < modlist.size(); ++i) {
        BPatch_module *mod = modlist[i];
        assert(mod);
        mod->getName(buf, 512);
        if (substring_match)
            if (strstr(buf, name)) {
                target = mod;
                break;
            }
            else  //exact match required
                if (!strcmp(name, buf)) {
                    target = mod;
                    break;
                }
    }

    if (target)
        return target;

    // process::findModule does a wildcard match, not a substring match

    char *tmp = (char *) malloc(strlen(name) + 2);
    if(substring_match)
        sprintf(tmp, "*%s*", name);
    else
        sprintf(tmp, "%s", name);
    mapped_module *mod = proc->llproc->findModule(pdstring(tmp),substring_match);
    free(tmp);
    if (!mod) return false;

    target = findOrCreateModule(mod);

    return target;
}
Ejemplo n.º 11
0
bool dynamic_linking::initialize() {

    // step 1: figure out if this is a dynamic executable. 

    // Use the symbol _call_add_pc_range_table as the test for a 
  // dynamically linked obj
  pdstring dyn_str = pdstring("__INIT_00_add_pc_range_table");
  Symbol dyn_sym;
  if (!proc->getSymbolInfo(dyn_str, dyn_sym)) {
    // static, nothing to do.
    bpinfo("program is statically linked\n");
    return false;
  }
  
  dynlinked = true;
  
  return true;
}
Ejemplo n.º 12
0
instrCodeNode *instrCodeNode::newInstrCodeNode(pdstring name_, const Focus &f,
                                               pd_process *proc, bool arg_dontInsertData, 
                                               pdstring hw_cntr_str)
{
  instrCodeNode_Val *nodeVal;
  // it's fine to use a code node with data inserted for a code node
  // that doesn't need data to be inserted
  pdstring key_name = instrCodeNode_Val::construct_key_name(name_, f.getName());
  bool foundIt = allInstrCodeNodeVals.find(key_name, nodeVal);

  if(! foundIt) {
    HwEvent* hw = NULL;
    /* if PAPI isn't available, hw_cntr_str should always be "" */
    if (hw_cntr_str != "") {
#ifdef PAPI
      papiMgr* papi;
      papi = proc->getPapiMgr();
      assert(papi);
      hw = papi->createHwEvent(hw_cntr_str);

      if (hw == NULL) {
	string msg = pdstring("unable to add PAPI hardware event: ") 
	             + hw_cntr_str;
        showErrorCallback(125, msg.c_str());
        return NULL;
      }
#endif
    }

    nodeVal = new instrCodeNode_Val(name_, f, proc, arg_dontInsertData, hw);
    registerCodeNodeVal(nodeVal);
  }

  nodeVal->incrementRefCount();
  instrCodeNode *retNode = new instrCodeNode(nodeVal);
  return retNode;
}
Ejemplo n.º 13
0
void 
ParadynTkGUI::chooseMetricsandResources(chooseMandRCBFunc cb,
			       pdvector<metric_focus_pair> * /* pairList */ )
{
      // store record with unique id and callback function
  UIMMsgTokenID++;
  int newptr;
  Tcl_HashEntry *entryPtr = Tcl_CreateHashEntry (&UIMMsgReplyTbl,
						 (char *)UIMMsgTokenID, 
						 &newptr);
  if (newptr == 0) {
    showError(21, "");
    thr_exit(0);
  }

  unsigned requestingThread = getRequestingThread();
     // in theory, we can check here whether this (VISI-) thread already
     // has an outstanding metric request.  But for now, we let code in mets.tcl do this...
//  pdstring commandStr = pdstring("winfo exists .metmenunew") + pdstring(requestingThread);
//  myTclEval(interp, commandStr);
//  int result;
//  assert(TCL_OK == Tcl_GetBoolean(interp, Tcl_GetStringResult(interp), &result));
//  if (result)
//     return; // the window is already up for this thread!

  UIMReplyRec *reply = new UIMReplyRec;
  reply->tid = requestingThread;
  reply->cb = (void *) cb;
  Tcl_SetHashValue (entryPtr, reply);

  if (!all_metrics_set_yet) {
      pdvector<met_name_id> *all_mets = dataMgr->getAvailableMetInfo(true);
      
      for (unsigned metlcv=0; metlcv < all_mets->size(); metlcv++) {
	 unsigned id  = (*all_mets)[metlcv].id;
	 pdstring &name = (*all_mets)[metlcv].name;

	 all_metric_names[id] = name;

	 pdstring idString(id);
	 bool aflag;
	 aflag=(Tcl_SetVar2(interp, "metricNamesById", 
			    const_cast<char*>(idString.c_str()),
			    const_cast<char*>(name.c_str()), 
			    TCL_GLOBAL_ONLY) != NULL);
         assert(aflag);
      }
      
      delete all_mets;
      all_metrics_set_yet = true;
  }

  // Set metIndexes2Id via "temp"
  (void)Tcl_UnsetVar(interp, "temp", 0);
     // ignore result; temp may not have existed
  pdvector<met_name_id> *curr_avail_mets_ptr = dataMgr->getAvailableMetInfo(false);
  pdvector<met_name_id> &curr_avail_mets = *curr_avail_mets_ptr;
  unsigned numAvailMets = curr_avail_mets.size();
  assert( numAvailMets > 0 );
  for (unsigned metlcv=0; metlcv < numAvailMets; metlcv++) {
     pdstring metricIdStr = pdstring(curr_avail_mets[metlcv].id);
     
     bool aflag;
     aflag = (Tcl_SetVar(interp, "temp", 
			 const_cast<char*>(metricIdStr.c_str()),
			 TCL_APPEND_VALUE | TCL_LIST_ELEMENT) != NULL);
     assert(aflag);
  }
  delete curr_avail_mets_ptr;
  

  pdstring tcommand("getMetsAndRes ");
  tcommand += pdstring(UIMMsgTokenID);
  tcommand += pdstring(" ") + pdstring(requestingThread);
  tcommand += pdstring(" ") + pdstring(numAvailMets);
  tcommand += pdstring(" $temp");

  int retVal = Tcl_VarEval (interp, tcommand.c_str(), 0);
  if (retVal == TCL_ERROR)  {
    uiMgr->showError (22, "");
    cerr << Tcl_GetStringResult(interp) << endl;
    thr_exit(0);  
  } 
}
Ejemplo n.º 14
0
bool SignalHandler::handleEvent(EventRecord &ev)
{
    signal_printf("%s[%d]:  got event: %s\n", FILE__, __LINE__, eventType2str(ev.type));
    
    if (ev.type == evtShutDown) {
        stop_request = true;
        return true;
    }

    process *proc = ev.proc;
    // Do we run the process or not? Well, that's a tricky question...
    // user control can override anything we do here (frex, a "run when
    // done" iRPC conflicting with a user "pause"). So we have the lowlevel
    // code suggest whether to continue or not, and we have logic here
    // to see if we do it or not.
    
    bool continueHint = false;
    bool ret = false;
    Frame activeFrame;
    assert(proc);
    
    // One big switch statement
    switch(ev.type) {
        // First the platform-independent stuff
        // (/proc and waitpid)
    case evtProcessExit:
        ret = handleProcessExit(ev, continueHint);
        break;
    case evtProcessCreate:
        ret = handleProcessCreate(ev, continueHint);
        break;
    case evtThreadCreate:
        ret = handleThreadCreate(ev, continueHint);
        break;
    case evtThreadExit:
        ret = handleLwpExit(ev, continueHint);
        break;
     case evtLwpAttach:
        ret = handleLwpAttach(ev, continueHint);
        break;
    case evtProcessAttach:
        ret = handleProcessAttach(ev, continueHint);
        break;
     case evtProcessInit:
        proc->handleTrapAtEntryPointOfMain(ev.lwp);
        proc->setBootstrapState(initialized_bs);
        // If we were execing, we now know we finished
        if (proc->execing()) {
           proc->finishExec();
        }
        continueHint = false;
        ret = true;
        break;
     case evtProcessLoadedRT:
     {
        pdstring buffer = pdstring("PID=") + pdstring(proc->getPid());
        buffer += pdstring(", loaded dyninst library");
        statusLine(buffer.c_str());
        startup_printf("%s[%]:  trapDueToDyninstLib returned tru, trying to handle\n", 
                       FILE__, __LINE__);
        startup_cerr << "trapDueToDyninstLib returned true, trying to handle\n";
        proc->loadDYNINSTlibCleanup(ev.lwp);
        proc->setBootstrapState(loadedRT_bs);
        ret = true;
        continueHint = false;
        break;
     }
     case evtInstPointTrap: {
         // Linux inst via traps
         // First, we scream... this is undesired behavior.
         signal_printf("%s[%d]: WARNING: inst point trap detected at 0x%lx, trap to 0x%lx\n",
                       FILE__, __LINE__, ev.address, proc->trampTrapMapping[ev.address]);
         ev.lwp->changePC(proc->trampTrapMapping[ev.address], NULL);
         continueHint = true;
         ret = true;
         break;
     }
     case evtLoadLibrary:
     case evtUnloadLibrary:
       ret = handleLoadLibrary(ev, continueHint);
       continueHint = true;
       break;
     case evtPreFork:
         // If we ever want to callback this guy, put it here.
        ret = true;
        continueHint = true;
        break;
     case evtSignalled:
     {
        ret = forwardSigToProcess(ev, continueHint);
        break;
     }
    case evtProcessStop:
       ret = handleProcessStop(ev, continueHint);
       if (!ret) {
           fprintf(stderr, "%s[%d]:  handleProcessStop failed\n", FILE__, __LINE__);
       }
       break;
     // Now the /proc only
     // AIX clones some of these (because of fork/exec/load notification)
     case evtRPCSignal:
         ret = proc->getRpcMgr()->handleRPCEvent(ev, continueHint);
         signal_printf("%s[%d]: handled RPC event, continueHint %d\n",
                       FILE__, __LINE__, continueHint);
         break;
     case evtSyscallEntry:
         ret = handleSyscallEntry(ev, continueHint);
         if (!ret)
             cerr << "handleSyscallEntry failed!" << endl;
         break;
     case evtSyscallExit:
         ret = handleSyscallExit(ev, continueHint);
         if (!ret)
            fprintf(stderr, "%s[%d]: handlesyscallExit failed! ", __FILE__, __LINE__); ;
         break;
     case evtSuspended:
         continueHint = true;
         ret = true;
         flagBPatchStatusChange();
         break;
     case evtDebugStep:
         handleSingleStep(ev, continueHint);
         ret = 1;
         break;
     case evtUndefined:
        // Do nothing
        cerr << "Undefined event!" << endl;
        continueHint = true;
        break;
     case evtCritical:
       ret = handleCritical(ev, continueHint);
         break;
     case evtRequestedStop:
         // /proc-age. We asked for a stop and the process did, and the signalGenerator
         // saw it.
         continueHint = false;
         ret = true;
         break;
     case evtTimeout:
     case evtThreadDetect:
         continueHint = true;
         ret = true;
         break;
     case evtNullEvent:
         ret = true;
         continueHint = true;
         break;
     default:
        fprintf(stderr, "%s[%d]:  cannot handle signal %s\n", FILE__, __LINE__, eventType2str(ev.type));
        assert(0 && "Undefined");
   }

  if (stop_request) {
    // Someone deleted us in place. 
    return true;
  }

   if (ret == false) {
      //  if ret is false, complain, but return true anyways, since the handler threads
      //  should be shut down by the SignalGenerator.
      char buf[128];
      fprintf(stderr, "%s[%d]:  failed to handle event %s\n", FILE__, __LINE__,
              ev.sprint_event(buf));
      ret = true;
   }

   // Process continue hint...
   if (continueHint) {
       signal_printf("%s[%d]: requesting continue\n",
                     FILE__, __LINE__);
       wait_flag = true;
       sg->continueProcessAsync(-1, // No signal...
                                ev.lwp); // But give the LWP
       wait_flag = false;
   }

   // Should always be the last thing we do...
   sg->signalEvent(ev);

   return ret;
}
Ejemplo n.º 15
0
tvFocus::tvFocus(unsigned iVisiLibId,
		 const pdstring &iLongName, Tk_Font nameFont) :
                                                   longName(iLongName) {
   visiLibId = iVisiLibId;

   longNamePixWidth = Tk_TextWidth(nameFont, longName.c_str(),
				 longName.length());
   
   // Calculate the short name as follows:
   // Split the name up into its components.  Assuming there are 4 resource
   // hierarchies, there will be 4 components.
   // For each component, strip off everything upto and including the last '/'
   // Then re-concatenate the components back together (with comma delimiters)
   // to obtain the short name
   
   // Step 0: make an exception for "Whole Program"
   if (0==strcmp(longName.c_str(), "Whole Program")) {
      shortName = longName;
   }
   else {
      // Step 1: split up into components; 1 per resource hierarchy
      pdvector<pdstring> components;
		unsigned componentlcv;

      const char *ptr = longName.c_str();
      while (*ptr != '\0') {
         // begin a new component; collect upto & including the first seen comma
         char buffer[200];
         char *bufferPtr = &buffer[0];
         do {
            *bufferPtr++ = *ptr++;
         } while (*ptr != ',' && *ptr != '\0');

         if (*ptr == ',')
            *bufferPtr++ = *ptr++;

         *bufferPtr = '\0';

         components += pdstring(buffer);
      }

      // Step 2: for each component, strip off all upto and including
      //         the last '/'
      for (componentlcv=0; componentlcv < components.size(); componentlcv++) {
         const pdstring &oldComponentString = components[componentlcv];

         char *ptr = strrchr(oldComponentString.c_str(), '/');
         if (ptr == NULL)
            cerr << "tableVisi: could not find / in component " << oldComponentString << endl;
         else if (ptr+1 == '\0')
            cerr << "tableVisi: there was nothing after / in component " << oldComponentString << endl;
         else
            components[componentlcv] = pdstring(ptr+1);
      }

      // Step 3: combine the components
      pdstring theShortName;
      for (componentlcv=0; componentlcv < components.size(); componentlcv++)
         theShortName += components[componentlcv];

      // Step 4: pull it all together:
      this->shortName = theShortName;
   }
   
   shortNamePixWidth = Tk_TextWidth(nameFont, shortName.c_str(),
				  shortName.length());
}
Ejemplo n.º 16
0
BPatch_Vector<BPatch_function*> *BPatch_image::findFunctionInt(const char *name,
        BPatch_Vector<BPatch_function*> &funcs,
        bool showError,
        bool regex_case_sensitive,
        bool incUninstrumentable)
{
    process *llproc = proc->llproc;
    if (NULL == strpbrk(name, REGEX_CHARSET)) {
        //  usual case, no regex
        pdvector<int_function *> foundIntFuncs;
        if (!llproc->findFuncsByAll(pdstring(name),
                                    foundIntFuncs)) {
            // Error callback...
            if (showError) {
                pdstring msg = pdstring("Image: Unable to find function: ") +
                               pdstring(name);
                BPatch_reportError(BPatchSerious, 100, msg.c_str());
            }
            return NULL;
        }
        // We have a list; if we don't want to include uninstrumentable,
        // scan and check
        for (unsigned int fi = 0; fi < foundIntFuncs.size(); fi++) {
            if (foundIntFuncs[fi]->isInstrumentable() || incUninstrumentable) {
                BPatch_function *foo = proc->findOrCreateBPFunc(foundIntFuncs[fi], NULL);
                funcs.push_back(foo);
            }
        }

        if (funcs.size() > 0) {
            return &funcs;
        } else {

            if (showError) {
                pdstring msg = pdstring("Image: Unable to find function: ") +
                               pdstring(name);
                BPatch_reportError(BPatchSerious, 100, msg.c_str());
            }
            return NULL;
        }
    }

#if !defined(i386_unknown_nt4_0) && !defined(mips_unknown_ce2_11) // no regex for M$
    // REGEX falls through:
    regex_t comp_pat;
    int err, cflags = REG_NOSUB | REG_EXTENDED;

    if( !regex_case_sensitive )
        cflags |= REG_ICASE;

    //cerr << "compiling regex: " <<name<<endl;

    if (0 != (err = regcomp( &comp_pat, name, cflags ))) {
        char errbuf[80];
        regerror( err, &comp_pat, errbuf, 80 );
        if (showError) {
            cerr << __FILE__ << ":" << __LINE__ << ":  REGEXEC ERROR: "<< errbuf << endl;
            pdstring msg = pdstring("Image: Unable to find function pattern: ")
                           + pdstring(name) + ": regex error --" + pdstring(errbuf);
            BPatch_reportError(BPatchSerious, 100, msg.c_str());
        }
        // remove this line
        cerr << __FILE__ << ":" << __LINE__ << ":  REGEXEC ERROR: "<< errbuf << endl;
        return NULL;
    }

    // Regular expression search. This used to be handled at the image
    // class level, but was moved up here to simplify semantics. We
    // have to iterate over every function known to the process at some
    // point, so it might as well be top-level. This is also an
    // excellent candidate for a "value-added" library.

    pdvector<int_function *> all_funcs;
    llproc->getAllFunctions(all_funcs);

    for (unsigned ai = 0; ai < all_funcs.size(); ai++) {
        int_function *func = all_funcs[ai];
        // If it matches, push onto the vector
        // Check all pretty names (and then all mangled names if there is no match)
        bool found_match = false;
        for (unsigned piter = 0; piter < func->prettyNameVector().size(); piter++) {
            const pdstring &pName = func->prettyNameVector()[piter];
            int err;

            if (0 == (err = regexec(&comp_pat, pName.c_str(), 1, NULL, 0 ))) {
                if (func->isInstrumentable() || incUninstrumentable) {
                    BPatch_function *foo = proc->findOrCreateBPFunc(func, NULL);
                    funcs.push_back(foo);
                }
                found_match = true;
                break;
            }
        }
        if (found_match) continue; // Don't check mangled names

        for (unsigned miter = 0; miter < func->symTabNameVector().size(); miter++) {
            const pdstring &mName = func->symTabNameVector()[miter];
            int err;

            if (0 == (err = regexec(&comp_pat, mName.c_str(), 1, NULL, 0 ))) {
                if (func->isInstrumentable() || incUninstrumentable) {
                    BPatch_function *foo = proc->findOrCreateBPFunc(func, NULL);
                    funcs.push_back(foo);
                }
                found_match = true;
                break;
            }
        }
    }

    regfree(&comp_pat);

    if (funcs.size() > 0) {
        return &funcs;
    }

    if (showError) {
        pdstring msg = pdstring("Unable to find pattern: ") + pdstring(name);
        BPatch_reportError(BPatchSerious, 100, msg.c_str());
    }
#endif
    return NULL;
}
Ejemplo n.º 17
0
// parseStabTypes:  parses type and variable info, does some init
// does NOT parse file-line info anymore, this is done later, upon request.
void BPatch_module::parseStabTypes() 
{
  stab_entry *stabptr;
  const char *next_stabstr;

  unsigned i;
  char *modName;
  pdstring temp;
  image * imgPtr=NULL;
  char *ptr, *ptr2, *ptr3;
  bool parseActive = false;

  pdstring* currentFunctionName = NULL;
  Address currentFunctionBase = 0;
  BPatch_variableExpr *commonBlockVar = NULL;
 char *commonBlockName;
  BPatch_typeCommon *commonBlock = NULL;
 int mostRecentLinenum = 0;

#if defined(TIMED_PARSE)
  struct timeval starttime;
  gettimeofday(&starttime, NULL);
  unsigned int pss_count = 0;
  double pss_dur = 0;
  unsigned int src_count = 0;
  double src_dur = 0;
  unsigned int fun_count = 0;
  double fun_dur = 0;
  struct timeval t1, t2;
#endif

  imgPtr = mod->obj()->parse_img();
  imgPtr->analyzeIfNeeded();
  const Object &objPtr = imgPtr->getObject();

  //Using the Object to get the pointers to the .stab and .stabstr
  // XXX - Elf32 specific needs to be in seperate file -- jkh 3/18/99
  stabptr = objPtr.get_stab_info();
  next_stabstr = stabptr->getStringBase();

  for (i=0; i<stabptr->count(); i++) {
    switch(stabptr->type(i)){
    case N_UNDF: /* start of object file */
      /* value contains offset of the next string table for next module */
      // assert(stabptr->nameIdx(i) == 1);
      stabptr->setStringBase(next_stabstr);
      next_stabstr = stabptr->getStringBase() + stabptr->val(i);

      //N_UNDF is the start of object file. It is time to 
      //clean source file name at this moment.
      /*
      if(currentSourceFile){
	delete currentSourceFile;
	currentSourceFile = NULL;
	delete absoluteDirectory;
	absoluteDirectory = NULL;
	delete currentFunctionName;
	currentFunctionName = NULL;
	currentFileInfo = NULL;
	currentFuncInfo = NULL;
      }
      */
      break;
      
    case N_ENDM: /* end of object file */
      break;

    case N_SO: /* compilation source or file name */
      /* bperr("Resetting CURRENT FUNCTION NAME FOR NEXT OBJECT FILE\n");*/
#ifdef TIMED_PARSE
      src_count++;
      gettimeofday(&t1, NULL);
#endif
      current_func_name = ""; // reset for next object file
      current_mangled_func_name = ""; // reset for next object file
      current_func = NULL;

      modName = const_cast<char*>(stabptr->name(i));
      // cerr << "checkpoint B" << endl;
      ptr = strrchr(modName, '/');
      //  cerr << "checkpoint C" << endl;
      if (ptr) {
	ptr++;
	modName = ptr;
      }

      if (!strcmp(modName, mod->fileName().c_str())) {
	parseActive = true;
        moduleTypes->clearNumberedTypes();
	BPatch_language lang;
	// language should be set in the constructor, this is probably redundant
	switch (stabptr->desc(i)) {
	case N_SO_FORTRAN:
	  lang = BPatch_fortran;
	  break;
	  
	case N_SO_F90:
	  lang = BPatch_fortran90;
	  break;
	  
	case N_SO_AS:
	  lang = BPatch_assembly;
	  break;
	  
	case N_SO_ANSI_C:
	case N_SO_C:
	  lang = BPatch_c;
	  break;
	  
	case N_SO_CC:
	  lang = BPatch_cPlusPlus;
	  break;
	  
	default:
	  lang = BPatch_unknownLanguage;
	  break;
	}
	if (BPatch_f90_demangled_stabstr != getLanguage())
	  setLanguage(lang);
      } else {
	parseActive = false;
      }

#ifdef TIMED_PARSE
	    gettimeofday(&t2, NULL);
	    src_dur += (t2.tv_sec - t1.tv_sec)*1000.0 + (t2.tv_usec - t1.tv_usec)/1000.0;
	    //src_dur += (t2.tv_sec/1000 + t2.tv_usec*1000) - (t1.tv_sec/1000 + t1.tv_usec*1000) ;
#endif
	    break;
    case N_SLINE:
      mostRecentLinenum = stabptr->desc(i);
      break;
    default:
      break;
    }


    if(parseActive || mod->obj()->isSharedLib()) {
      BPatch_Vector<BPatch_function *> bpfv;
      switch(stabptr->type(i)){
      case N_FUN:
#ifdef TIMED_PARSE
	fun_count++;
	gettimeofday(&t1, NULL);
#endif
	//all we have to do with function stabs at this point is to assure that we have
	//properly set the var currentFunctionName for the later case of (parseActive)
        current_func = NULL;
        int currentEntry = i;
        int funlen = strlen(stabptr->name(currentEntry));
        ptr = new char[funlen+1];
        strcpy(ptr, stabptr->name(currentEntry));
        while(strlen(ptr) != 0 && ptr[strlen(ptr)-1] == '\\'){
            ptr[strlen(ptr)-1] = '\0';
            currentEntry++;
            strcat(ptr,stabptr->name(currentEntry));
        }
        
        char* colonPtr = NULL;
        if(currentFunctionName) delete currentFunctionName;
        if(!ptr || !(colonPtr = strchr(ptr,':')))
            currentFunctionName = NULL;
        else {
            char* tmp = new char[colonPtr-ptr+1];
            strncpy(tmp,ptr,colonPtr-ptr);
            tmp[colonPtr-ptr] = '\0';
            currentFunctionName = new pdstring(tmp);
            
            currentFunctionBase = 0;
            Symbol info;
            // Shouldn't this be a function name lookup?
            if (!proc->llproc->getSymbolInfo(*currentFunctionName,
                                             info))
                {
                    pdstring fortranName = *currentFunctionName + pdstring("_");
                    if (proc->llproc->getSymbolInfo(fortranName,info))
                        {
                            delete currentFunctionName;
                            currentFunctionName = new pdstring(fortranName);
                        }
                }
            
            currentFunctionBase = info.addr();

            delete[] tmp;
      		
	//	if(currentSourceFile && (currentFunctionBase > 0)){
	//	lineInformation->insertSourceFileName(
	//			*currentFunctionName,
	//			*currentSourceFile,
	//			&currentFileInfo,&currentFuncInfo);
	//}
      }
      //  used to be a symbol lookup here to find currentFunctionBase, do we need it?
      delete[] ptr;
#ifdef TIMED_PARSE
      gettimeofday(&t2, NULL);
      fun_dur += (t2.tv_sec - t1.tv_sec)*1000.0 + (t2.tv_usec - t1.tv_usec)/1000.0;
      //fun_dur += (t2.tv_sec/1000 + t2.tv_usec*1000) - (t1.tv_sec/1000 + t1.tv_usec*1000);
#endif
      break;
      }
    if (!parseActive) continue;

    switch(stabptr->type(i)){
      case N_BCOMM:	{
	// begin Fortran named common block 
	commonBlockName = const_cast<char*>(stabptr->name(i));

	// find the variable for the common block
	BPatch_image *progam = (BPatch_image *) getObjParent();
	commonBlockVar = progam->findVariable(commonBlockName);
	if (!commonBlockVar) {
	  bperr("unable to find variable %s\n", commonBlockName);
	} else {
	  commonBlock = dynamic_cast<BPatch_typeCommon *>(const_cast<BPatch_type *> (commonBlockVar->getType()));
	  if (commonBlock == NULL) {
	    // its still the null type, create a new one for it
	    commonBlock = new BPatch_typeCommon(commonBlockName);
	    commonBlockVar->setType(commonBlock);
	    moduleTypes->addGlobalVariable(commonBlockName, commonBlock);
	  }
	  // reset field list
	  commonBlock->beginCommonBlock();
	}
	break;
      }
      
      case N_ECOMM: {
	// copy this set of fields
	
	assert(currentFunctionName);
	if (NULL == findFunction(currentFunctionName->c_str(), bpfv) || !bpfv.size()) {
	  bperr("unable to locate current function %s\n", currentFunctionName->c_str());
	} else {
	  if (bpfv.size() > 1) {
	    // warn if we find more than one function with this name
	    bperr("%s[%d]:  WARNING: found %d funcs matching name %s, using the first\n",
		   __FILE__, __LINE__, bpfv.size(), currentFunctionName->c_str());
	  }
	  
	  BPatch_function *func = bpfv[0];
	  commonBlock->endCommonBlock(func, commonBlockVar->getBaseAddr());
	}
	
	// update size if needed
	if (commonBlockVar)
	  commonBlockVar->setSize(commonBlock->getSize());
	commonBlockVar = NULL;
	commonBlock = NULL;
	break;
      }
      
      // case C_BINCL: -- what is the elf version of this jkh 8/21/01
      // case C_EINCL: -- what is the elf version of this jkh 8/21/01
      case 32:    // Global symbols -- N_GYSM 
      case 38:    // Global Static -- N_STSYM
      case N_FUN:
      case 128:   // typedefs and variables -- N_LSYM
      case 160:   // parameter variable -- N_PSYM 
    case 0xc6:  // position-independant local typedefs -- N_ISYM
    case 0xc8: // position-independant external typedefs -- N_ESYM
#ifdef TIMED_PARSE
	pss_count++;
	gettimeofday(&t1, NULL);
#endif
        if (stabptr->type(i) == N_FUN) current_func = NULL;
	ptr = const_cast<char *>(stabptr->name(i));
	while (ptr[strlen(ptr)-1] == '\\') {
	  //ptr[strlen(ptr)-1] = '\0';
	  ptr2 =  const_cast<char *>(stabptr->name(i+1));
	  ptr3 = (char *) malloc(strlen(ptr) + strlen(ptr2));
	  strcpy(ptr3, ptr);
	  ptr3[strlen(ptr)-1] = '\0';
	  strcat(ptr3, ptr2);
	  
	  ptr = ptr3;
	  i++;
	  // XXX - memory leak on multiple cont. lines
	}
	
	// bperr("stab #%d = %s\n", i, ptr);
	// may be nothing to parse - XXX  jdd 5/13/99
	if (nativeCompiler)
	  temp = parseStabString(this, mostRecentLinenum, (char *)ptr, stabptr->val(i), commonBlock);
	else
	  temp = parseStabString(this, stabptr->desc(i), (char *)ptr, stabptr->val(i), commonBlock);
	if (temp.length()) {
	  //Error parsing the stabstr, return should be \0
	  bperr( "Stab string parsing ERROR!! More to parse: %s\n",
		  temp.c_str());
	  bperr( "  symbol: %s\n", ptr);
	}
	
#ifdef TIMED_PARSE
	gettimeofday(&t2, NULL);
	pss_dur += (t2.tv_sec - t1.tv_sec)*1000.0 + (t2.tv_usec - t1.tv_usec)/1000.0;
	//      pss_dur += (t2.tv_sec/1000 + t2.tv_usec*1000) - (t1.tv_sec/1000 + t1.tv_usec*1000);
#endif
	break;
      default:
	break;
      }
    }       		    
  }

#if defined(TIMED_PARSE)
  struct timeval endtime;
  gettimeofday(&endtime, NULL);
  unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
  unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
  unsigned long difftime = lendtime - lstarttime;
  double dursecs = difftime/(1000 );
  cout << __FILE__ << ":" << __LINE__ <<": parseTypes("<< mod->fileName()
       <<") took "<<dursecs <<" msecs" << endl;
  cout << "Breakdown:" << endl;
  cout << "     Functions: " << fun_count << " took " << fun_dur << "msec" << endl;
  cout << "     Sources: " << src_count << " took " << src_dur << "msec" << endl;
  cout << "     parseStabString: " << pss_count << " took " << pss_dur << "msec" << endl;
  cout << "     Total: " << pss_dur + fun_dur + src_dur 
       << " msec" << endl;
#endif
}
Ejemplo n.º 18
0
bool dynamic_linking::installTracing() {
    // We capture dlopen/dlclose by overwriting the return address
    // of their worker functions (load1 for dlopen, dlclose is TODO).
    // We get this from the (already-parsed) listing of libc.

  // Should check only libc.a...

  AstNode *retval = new AstNode(AstNode::ReturnVal, (void *)0);
  instMapping *loadInst = new instMapping("load1", "DYNINST_instLoadLibrary",
					  FUNC_EXIT | FUNC_ARG,
					  retval);
  instMapping *unloadInst = new instMapping("unload", "DYNINST_instLoadLibrary",
                                            FUNC_EXIT | FUNC_ARG,
                                            retval);
  
  loadInst->dontUseTrampGuard();
  unloadInst->dontUseTrampGuard();

  removeAst(retval);
  pdvector<instMapping *>instReqs;
  instReqs.push_back(loadInst);
  instReqs.push_back(unloadInst);
  proc->installInstrRequests(instReqs);
  if (loadInst->miniTramps.size()) {
      sharedLibHook *sharedHook = new sharedLibHook(proc, SLH_UNKNOWN,
                                                    loadInst);
      sharedLibHooks_.push_back(sharedHook);
      instru_based = true;
  }
  if (unloadInst->miniTramps.size()) {
      sharedLibHook *sharedHook = new sharedLibHook(proc, SLH_UNKNOWN,
                                                    unloadInst);
      sharedLibHooks_.push_back(sharedHook);
      instru_based = true;
  }

  if (sharedLibHooks_.size())
      return true;
  else
      return false;


#if 0
      // Seriously deprecated
      const pdvector<mapped_object *> &objs = proc->mappedObjects();
      
      // Get libc
      mapped_object *libc = NULL;
      for (unsigned i = 0; i < objs.size(); i++) {
          const fileDescriptor &desc = objs[i]->getFileDesc();
          if ((objs[i]->fileName().suffixed_by("libc.a")) &&
              (desc.member() == "shr.o")) {
              libc = (objs[i]);
          }
      }
      assert(libc);
    
      // Now, libc may have been parsed... in which case we pull the function vector
      // from it. If not, we parse it manually.
      
      const pdvector<int_function *> *loadFuncs = libc->findFuncVectorByPretty(pdstring("load1"));
      assert(loadFuncs);
      assert(loadFuncs->size() > 0);
      
      int_function *loadFunc = (*loadFuncs)[0];
      assert(loadFunc);
      
    // There is no explicit place to put a trap, so we'll replace
    // the final instruction (brl) with a trap, and emulate the branch
    // mutator-side
    //
    //  JAW-- Alas this only works on AIX < 5.2.  The AIX 5.2 version of 
    //  load1 has 2 'blr' exit points, and we really want the first one.
    //  the last one is (apparently) the return that is used when there is
    //  is a failure.
    //
    // We used to find multiple exit points in findInstPoints. Now that
    // Laune's got a new version, we don't hack that any more. Instead, we
    // read in the function image, find the blr instructions, and overwrite
    // them by hand. This should be replaced with either a) instrumentation
    // or b) a better hook (aka r_debug in Linux/Solaris)

    InstrucIter funcIter(loadFunc);

    while (*funcIter) {
        instruction insn = funcIter.getInstruction();

        if (insn.raw() == BRraw) {
            sharedLibHook *sharedHook = new sharedLibHook(proc, SLH_UNKNOWN, 
                                                          *funcIter);
            sharedLibHooks_.push_back(sharedHook);
        }
        funcIter++;
    }
  }
Ejemplo n.º 19
0
BPatch_Vector<BPatch_function *> *
BPatch_module::findFunctionInt(const char *name, 
        BPatch_Vector<BPatch_function *> & funcs,
        bool notify_on_failure, bool regex_case_sensitive,
        bool incUninstrumentable, bool dont_use_regex)
{
    if (hasBeenRemoved_) return NULL;

  unsigned size = funcs.size();

  if (!name) {
    char msg[512];
    sprintf(msg, "%s[%d]:  Module %s: findFunction(NULL)...  failing",
           __FILE__, __LINE__, mod->fileName().c_str());
    BPatch_reportError(BPatchSerious, 100, msg);
    return NULL;
  }

  // Do we want regex?
  if (dont_use_regex ||
      (NULL == strpbrk(name, REGEX_CHARSET))) {
      pdvector<int_function *> int_funcs;
      if (mod->findFuncVectorByPretty(name,
                                      int_funcs)) {
          for (unsigned piter = 0; piter < int_funcs.size(); piter++) {
              if (incUninstrumentable || int_funcs[piter]->isInstrumentable()) 
                  {
                      BPatch_function * bpfunc = proc->findOrCreateBPFunc(int_funcs[piter], this);
                      funcs.push_back(bpfunc);
                  }
          }
      }
      else {
          if (mod->findFuncVectorByMangled(name,
                                           int_funcs)) {
              for (unsigned miter = 0; miter < int_funcs.size(); miter++) {
                  if (incUninstrumentable || int_funcs[miter]->isInstrumentable()) 
                      {
                          BPatch_function * bpfunc = proc->findOrCreateBPFunc(int_funcs[miter], this);
                          funcs.push_back(bpfunc);
                      }
              }
          }
      }
      if (size != funcs.size())
          return &funcs;
  }
  else {
    // Regular expression search. As with BPatch_image, we handle it here

#if !defined(i386_unknown_nt4_0) && !defined(mips_unknown_ce2_11) // no regex for M$
   // REGEX falls through:
   regex_t comp_pat;
   int err, cflags = REG_NOSUB | REG_EXTENDED;
   
   if( !regex_case_sensitive )
     cflags |= REG_ICASE;
   
   //cerr << "compiling regex: " <<name<<endl;
   
   if (0 != (err = regcomp( &comp_pat, name, cflags ))) {
     char errbuf[80];
     regerror( err, &comp_pat, errbuf, 80 );
     if (notify_on_failure) {
       cerr << __FILE__ << ":" << __LINE__ << ":  REGEXEC ERROR: "<< errbuf << endl;
       pdstring msg = pdstring("Image: Unable to find function pattern: ") 
	 + pdstring(name) + ": regex error --" + pdstring(errbuf);
       BPatch_reportError(BPatchSerious, 100, msg.c_str());
     }
     // remove this line
     //cerr << __FILE__ << ":" << __LINE__ << ":  REGEXEC ERROR: "<< errbuf << endl;
     return NULL;
   }
   
   // Regular expression search. This used to be handled at the image
   // class level, but was moved up here to simplify semantics. We
   // have to iterate over every function known to the process at some
   // point, so it might as well be top-level. This is also an
   // excellent candidate for a "value-added" library.
   
   const pdvector<int_function *> &int_funcs = mod->getAllFunctions();
   
   for (unsigned ai = 0; ai < int_funcs.size(); ai++) {
     int_function *func = int_funcs[ai];
     // If it matches, push onto the vector
     // Check all pretty names (and then all mangled names if there is no match)
     bool found_match = false;
     for (unsigned piter = 0; piter < func->prettyNameVector().size(); piter++) {
       const pdstring &pName = func->prettyNameVector()[piter];
       int err;     
       if (0 == (err = regexec(&comp_pat, pName.c_str(), 1, NULL, 0 ))){
	 if (func->isInstrumentable() || incUninstrumentable) {
	   BPatch_function *foo = proc->findOrCreateBPFunc(func, NULL);
	   funcs.push_back(foo);
	 }
	 found_match = true;
	 break;
       }
     }
     if (found_match) continue; // Don't check mangled names

     for (unsigned miter = 0; miter < func->symTabNameVector().size(); miter++) {
       const pdstring &mName = func->symTabNameVector()[miter];
       int err;
     
       if (0 == (err = regexec(&comp_pat, mName.c_str(), 1, NULL, 0 ))){
	 if (func->isInstrumentable() || incUninstrumentable) {
	   BPatch_function *foo = proc->findOrCreateBPFunc(func, NULL);
	   funcs.push_back(foo);
	 }
	 found_match = true;
	 break;
       }
     }
   }

   regfree(&comp_pat);
   
   if (funcs.size() != size) {
      return &funcs;
   } 
   
   if (notify_on_failure) {
     pdstring msg = pdstring("Unable to find pattern: ") + pdstring(name);
     BPatch_reportError(BPatchSerious, 100, msg.c_str());
   }
#endif
  }

  if(notify_on_failure) {
    char msg[1024];
    sprintf(msg, "%s[%d]:  Module %s: unable to find function %s",
	    __FILE__, __LINE__, mod->fileName().c_str(), name);
    BPatch_reportError(BPatchSerious, 100, msg);
    
  }
  return &funcs;
}
Ejemplo n.º 20
0
// Gets the stab and stabstring section and parses it for types
// and variables
void BPatch_module::parseTypes()
{
    int i, j;
    int nlines;
    int nstabs;
    char* lines;
    SYMENT *syms;
    SYMENT *tsym;
    char *stringPool;
    char tempName[9];
    char *stabstr=NULL;
    union auxent *aux;
    image * imgPtr=NULL;
    pdstring funcName;
    Address staticBlockBaseAddr = 0;
    unsigned long linesfdptr;
    BPatch_typeCommon *commonBlock = NULL;
    BPatch_variableExpr *commonBlockVar = NULL;
    pdstring currentSourceFile;
    bool inCommonBlock = false;

#if defined(TIMED_PARSE)
  struct timeval starttime;
  gettimeofday(&starttime, NULL);
#endif

  imgPtr = mod->obj()->parse_img();
  
  const Object &objPtr = imgPtr->getObject();

  //Using the Object to get the pointers to the .stab and .stabstr
  objPtr.get_stab_info(stabstr, nstabs, syms, stringPool); 

    objPtr.get_line_info(nlines,lines,linesfdptr); 

    bool parseActive = true;
    //fprintf(stderr, "%s[%d]:  parseTypes for module %s: nstabs = %d\n", FILE__, __LINE__,mod->fileName().c_str(),nstabs);
    //int num_active = 0;

    for (i=0; i < nstabs; i++) {
      /* do the pointer addition by hand since sizeof(struct syment)
       *   seems to be 20 not 18 as it should be */
      SYMENT *sym = (SYMENT *) (((unsigned) syms) + i * SYMESZ);
      // SYMENT *sym = (SYMENT *) (((unsigned) syms) + i * sizeof(struct syment));


      if (sym->n_sclass == C_FILE) {
	 char *moduleName;
	 if (!sym->n_zeroes) {
	    moduleName = &stringPool[sym->n_offset];
	 } else {
	    memset(tempName, 0, 9);
	    strncpy(tempName, sym->n_name, 8);
	    moduleName = tempName;
	 }
	 /* look in aux records */
	 for (j=1; j <= sym->n_numaux; j++) {
	    aux = (union auxent *) ((char *) sym + j * SYMESZ);
	    if (aux->x_file._x.x_ftype == XFT_FN) {
		if (!aux->x_file._x.x_zeroes) {
                     moduleName = &stringPool[aux->x_file._x.x_offset];
                } else {
                     // x_fname is 14 bytes
                     memset(moduleName, 0, 15);
                     strncpy(moduleName, aux->x_file.x_fname, 14);
                }
	    }
	 }

	 currentSourceFile = pdstring(moduleName);
	 currentSourceFile = mod->processDirectories(currentSourceFile);

	 if (strrchr(moduleName, '/')) {
	     moduleName = strrchr(moduleName, '/');
	     moduleName++;
	 }

	 if (!strcmp(moduleName, mod->fileName().c_str())) {
		parseActive = true;
                // Clear out old types
                moduleTypes->clearNumberedTypes();
	 } else {
              parseActive = false;
	 }
      }

      if (!parseActive) continue;

      //num_active++;

      char *nmPtr;
      if (!sym->n_zeroes && ((sym->n_sclass & DBXMASK) ||
			     (sym->n_sclass == C_BINCL) ||
			     (sym->n_sclass == C_EINCL))) {
	  if (sym->n_offset < 3) {
	      if (sym->n_offset == 2 && stabstr[0]) {
		  nmPtr = &stabstr[0];
	      } else {
		  nmPtr = &stabstr[sym->n_offset];
	      }
	  } else if (!stabstr[sym->n_offset-3]) {
	      nmPtr = &stabstr[sym->n_offset];
	  } else {
	      /* has off by two error */
	      nmPtr = &stabstr[sym->n_offset-2];
	  }
#ifdef notdef
	  bperr("using nmPtr = %s\n", nmPtr);
	  bperr("got n_offset = (%d) %s\n", sym->n_offset, &stabstr[sym->n_offset]);
	  if (sym->n_offset>=2) 
	      bperr("got n_offset-2 = %s\n", &stabstr[sym->n_offset-2]);
	  if (sym->n_offset>=3) 
	      bperr("got n_offset-3 = %x\n", stabstr[sym->n_offset-3]);
	  if (sym->n_offset>=4) 
	      bperr("got n_offset-4 = %x\n", stabstr[sym->n_offset-4]);
#endif
      } else {
	  // names 8 or less chars on inline, not in stabstr
	  memset(tempName, 0, 9);
	  strncpy(tempName, sym->n_name, 8);
	  nmPtr = tempName;
      }

      if ((sym->n_sclass == C_BINCL) ||
	  (sym->n_sclass == C_EINCL) ||
	  (sym->n_sclass == C_FUN)) {
		funcName = nmPtr;
		/* The call to parseLineInformation(), below, used to modify the symbols passed to it. */
                if (funcName.find(":") < funcName.length())
                   funcName = funcName.substr(0,funcName.find(":"));

//		I'm not sure why we bother with this here, since we fetch line numbers in symtab.C anyway.
//		mod->parseLineInformation(proc->llproc, currentSourceFile, 
//					  funcName, sym,
//					  linesfdptr, lines, nlines);
      }

      if (sym->n_sclass & DBXMASK) {
	  if (sym->n_sclass == C_BCOMM) {
	      char *commonBlockName;

              inCommonBlock = true;
	      commonBlockName = nmPtr;

	      // find the variable for the common block
	      BPatch_image *progam = (BPatch_image *) getObjParent();
	      
	      commonBlockVar = progam->findVariable(commonBlockName);
	      if (!commonBlockVar) {
		  bperr("unable to find variable %s\n", commonBlockName);
	      } else {
		  commonBlock = 
		      dynamic_cast<BPatch_typeCommon *>(const_cast<BPatch_type *> (commonBlockVar->getType()));
		  if (commonBlock == NULL) {
		      // its still the null type, create a new one for it
		      commonBlock = new BPatch_typeCommon(commonBlockName);
		      commonBlockVar->setType(commonBlock);
		      moduleTypes->addGlobalVariable(commonBlockName, commonBlock);
		  }
		  // reset field list
		  commonBlock->beginCommonBlock();
	      }
	  } else if (sym->n_sclass == C_ECOMM) {
             inCommonBlock = false;
             if (commonBlock == NULL)
                continue;

	      // copy this set of fields
	    BPatch_Vector<BPatch_function *> bpmv;
   	    if (NULL == findFunction(funcName.c_str(), bpmv) || !bpmv.size()) {
	      bperr("unable to locate current function %s\n", funcName.c_str());
	      } else {
		BPatch_function *func = bpmv[0];
		commonBlock->endCommonBlock(func, commonBlockVar->getBaseAddr());
	      }

	      // update size if needed
	      if (commonBlockVar)
		  commonBlockVar->setSize(commonBlock->getSize());
	      commonBlockVar = NULL;
	      commonBlock = NULL;
	  } else if (sym->n_sclass == C_BSTAT) {
	      // begin static block
	      // find the variable for the common block
	      tsym = (SYMENT *) (((unsigned) syms) + sym->n_value * SYMESZ);

	      // We can't lookup the value by name, because the name might have been
	      // redefined later on (our lookup would then pick the last one)

	      // Since this whole function is AIX only, we're ok to get this info

	      staticBlockBaseAddr = tsym->n_value;

	      /*
	      char *staticName, tempName[9];
	      if (!tsym->n_zeroes) {
		  staticName = &stringPool[tsym->n_offset];
	      } else {
		  memset(tempName, 0, 9);
		  strncpy(tempName, tsym->n_name, 8);
		  staticName = tempName;
	      }
	      BPatch_image *progam = (BPatch_image *) getObjParent();

	      BPatch_variableExpr *staticBlockVar = progam->findVariable(staticName);
	      if (!staticBlockVar) {
		  bperr("unable to find static block %s\n", staticName);
		  staticBlockBaseAddr = 0;
	      } else {
		  staticBlockBaseAddr = (Address) staticBlockVar->getBaseAddr();
	      }
	      */

	  } else if (sym->n_sclass == C_ESTAT) {
	      staticBlockBaseAddr = 0;
	  }

          // There's a possibility that we were parsing a common block that
          // was never instantiated (meaning there's type info, but no
          // variable info

          if (inCommonBlock && commonBlock == NULL)
             continue;

	  if (staticBlockBaseAddr && (sym->n_sclass == C_STSYM)) {
              parseStabString(this, 0, nmPtr, 
		  sym->n_value+staticBlockBaseAddr, commonBlock);
	  } else {
              parseStabString(this, 0, nmPtr, sym->n_value, commonBlock);
	  }
      }
    }
#if defined(TIMED_PARSE)
  struct timeval endtime;
  gettimeofday(&endtime, NULL);
  unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
  unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
  unsigned long difftime = lendtime - lstarttime;
  double dursecs = difftime/(1000 );
  cout << __FILE__ << ":" << __LINE__ <<": parseTypes("<< mod->fileName()
       <<") took "<<dursecs <<" msecs" << endl;
#endif

//  fprintf(stderr, "%s[%d]:  parseTypes for %s, num_active = %d\n", FILE__, __LINE__, mod->fileName().c_str(), num_active);
}
Ejemplo n.º 21
0
// 
// write out all data for a single histogram to specified file
// this routine assumes that fptr points to a valid file open for writing!  
//
bool metricInstance::saveAllData(std::ofstream& iptr, int &findex,
                                 const char *dirname, SaveRequestType oFlag)
{
   Histogram *hdata = NULL;
   int phaseid = 0;

   if ((oFlag == Phase) || (oFlag == All)) {
      // save all phase data
      
      // export archived (previous) phases, if any
      for (unsigned i = 0; i < old_data.size(); i++) {
         hdata = (old_data[i])->data;
         if ( hdata ) {
            
            pdstring fileSuffix = pdstring("hist_") + pdstring(findex);
            pdstring miFileName = pdstring(dirname) + fileSuffix;
            
            std::ofstream fptr (miFileName.c_str(), std::ios::out);
            if (!fptr) {
               return false;
            }
            phaseid = old_data[i]->phaseId;
            saveOneMI_Histo (fptr, hdata, phaseid);
            fptr.close();
            // update index file
            iptr << fileSuffix.c_str() << " " <<  getMetricName() << " " 
                 << getFocusName() << " " << phaseid << endl;
            findex++;  // increment fileid
         }
      }
      
      // export current phase
      hdata = data;
      phaseid =  phaseInfo::CurrentPhaseHandle();
      if (hdata != NULL) {
         // check for histogram not created yet for this MI
         
         pdstring fileSuffix = pdstring("hist_") + pdstring(findex);
         pdstring miFileName = pdstring(dirname) + fileSuffix;
         
         std::ofstream fptr (miFileName.c_str(), std::ios::out);
         if (!fptr) {
            return false;
         }
         saveOneMI_Histo (fptr, hdata, phaseid);
         fptr.close();
         // update index file
         iptr << fileSuffix.c_str() << " " <<  
            getMetricName() << " " << getFocusName() << " " << phaseid << endl;
         findex++;  // increment fileid
      }
   }

  if ((oFlag == Global)  || (oFlag == All)) {
    hdata = global_data;
    if (hdata != NULL) {
      // check for histogram not created yet for this MI
      //  (I think actually this is an error for the global phase - klk)
      pdstring fileSuffix = pdstring("hist_") + pdstring(findex);
      pdstring miFileName = pdstring(dirname) + fileSuffix;
      
      std::ofstream fptr (miFileName.c_str(), std::ios::out);
      if (!fptr) {
         return false;
      }
      phaseid = -1;  // global phase id is set
      saveOneMI_Histo (fptr, hdata, phaseid);
      fptr.close();
      // update index file
      iptr << fileSuffix.c_str() << " " <<  
	getMetricName() << " " << getFocusName() << " -1" //global phaseid
	   << endl;
      findex++;  // increment fileid
    }
  }
  return true;
}
Ejemplo n.º 22
0
/*
 * BPatch_image::findVariable
 *
 * Returns a BPatch_variableExpr* representing the given variable in the
 * application image.  If no such variable exists, returns NULL.
 *
 * name		The name of the variable to look up.
 *
 * First look for the name with an `_' prepended to it, and if that is not
 *   found try the original name.
 */
BPatch_variableExpr *BPatch_image::findVariableInt(const char *name, bool showError)
{
    pdvector<int_variable *> vars;
    process *llproc = proc->llproc;

    if (!llproc->findVarsByAll(name, vars)) {
        // _name?
        pdstring under_name = pdstring("_") + pdstring(name);
        if (!llproc->findVarsByAll(under_name, vars)) {
            // "default Namespace prefix?
            if (defaultNamespacePrefix) {
                pdstring prefix_name = pdstring(defaultNamespacePrefix) + pdstring(".") + pdstring(name);
                if (!llproc->findVarsByAll(prefix_name, vars)) {
                    if (showError) {
                        pdstring msg = pdstring("Unable to find variable: ") + pdstring(prefix_name);
                        showErrorCallback(100, msg);
                    }
                    return NULL;
                }
            } else {
                if (showError) {
                    pdstring msg = pdstring("Unable to find variable: ") + pdstring(name);
                    showErrorCallback(100, msg);
                }
                return NULL;
            }
        }
    }
    assert(vars.size());

    if (vars.size() > 1) {
        cerr << "Warning: found multiple matches for var " << name << endl;
    }

    int_variable *var = vars[0];

    BPatch_variableExpr *bpvar = AddrToVarExpr->hash[var->getAddress()];
    if (bpvar) {
        return bpvar;
    }
    // XXX - should this stuff really be by image ??? jkh 3/19/99
    BPatch_Vector<BPatch_module *> *mods = getModules();
    BPatch_type *type = NULL;

    // XXX look up the type off of the int_variable's module
    BPatch_module *module = NULL;
    for (unsigned int m = 0; m < mods->size(); m++) {
        if( (*mods)[m]->lowlevel_mod() == var->mod() ) {
            module = (*mods)[m];
            break;
        }
    }
    if(module) {
        type = module->getModuleTypes()->findVariableType(name);
    }
    else {
        bperr("findVariable: failed look up module %s\n",
              var->mod()->fileName().c_str());
    }
    if(!type) {
        //  if we can't find the type in the module, check the other modules
        //  (fixes prob on alpha) --  actually seems like most missing types
        //  end up in DEFAULT_MODULE
        for (unsigned int m = 0; m < mods->size(); m++) {
            BPatch_module *tm = (*mods)[m];
            type = tm->getModuleTypes()->findVariableType(name);
            if (type) {
#if 0
                char buf1[1024], buf2[1024];
                tm->getName(buf1, 1024);
                module->getName(buf2, 1024);
                fprintf(stderr, "%s[%d]:  found type for %s in module %s, not %s\n", FILE__, __LINE__, name, buf2, buf1);
#endif
                break;
            }

        }

        if (!type) {
            char buf[128];
            sprintf(buf, "%s[%d]:  cannot find type for var %s\n", FILE__, __LINE__, name);
            BPatch_reportError(BPatchWarning, 0, buf);
            type = BPatch::bpatch->type_Untyped;
        }
    }

    char *nameCopy = strdup(name);
    assert(nameCopy);
    BPatch_variableExpr *ret = new BPatch_variableExpr((char *) nameCopy,
            proc, (void *)var->getAddress(),
            type);
    AddrToVarExpr->hash[var->getAddress()] = ret;
    return ret;
}
Ejemplo n.º 23
0
bool shgPhases::changeLL(unsigned newIndex) {
   // returns true iff any changes, in which case you should redraw
   // NOTE: Like currShgPhaseIndex, the param newIndex is an index into
   //       the low-level array theShgPhases; it is not a dagid/phaseid!
   if (newIndex == currShgPhaseIndex)
      return false;

   if (existsCurrent()) {
      // Save current scrollbar values
      shgStruct &theShgStruct=theShgPhases[currShgPhaseIndex];

      pdstring commandStr = horizSBName + " get";
      myTclEval(interp, commandStr);
      bool aflag;
      aflag=(2==sscanf(Tcl_GetStringResult(interp),
          "%f %f", &theShgStruct.horizSBfirst,
		       &theShgStruct.horizSBlast));
      assert(aflag);

      commandStr = vertSBName + " get";
      myTclEval(interp, commandStr);
      aflag=(2==sscanf(Tcl_GetStringResult(interp),
          "%f %f", &theShgStruct.vertSBfirst,
		       &theShgStruct.vertSBlast));
      assert(aflag);
   }

   // Set new scrollbar values:
   shgStruct &theNewShgStruct=theShgPhases[currShgPhaseIndex = newIndex];

   pdstring commandStr = horizSBName + " set " +
                       pdstring(theNewShgStruct.horizSBfirst) + " " +
                       pdstring(theNewShgStruct.horizSBlast);
   myTclEval(interp, commandStr);

   commandStr = vertSBName + " set " + pdstring(theNewShgStruct.vertSBfirst) + " " +
                pdstring(theNewShgStruct.vertSBlast);
   myTclEval(interp, commandStr);

   // Set the Search(Resume) and Pause buttons:
   if (!theNewShgStruct.everSearched) {
      commandStr = searchButtonName + " config -text \"Search\" -state normal";
      myTclEval(interp, commandStr);

      commandStr = pauseButtonName + " config -state disabled";
      myTclEval(interp, commandStr);
   }
   else if (theNewShgStruct.currSearching) {
      commandStr = searchButtonName + " config -text \"Resume\" -state disabled";
      myTclEval(interp, commandStr);

      commandStr = pauseButtonName + " config -state normal";
      myTclEval(interp, commandStr);
   }
   else {
      // we are currently paused
      commandStr = searchButtonName + " config -text \"Resume\" -state normal";
      myTclEval(interp, commandStr);

      commandStr = pauseButtonName + " config -state disabled";
      myTclEval(interp, commandStr);
   }

   // This should update the menu:
   Tcl_SetVar(interp, "currShgPhase",
              (char*)pdstring(theNewShgStruct.getPhaseId()).c_str(),
              TCL_GLOBAL_ONLY);

   // Update the label containing the current phase name:
   commandStr = currPhaseLabelName + " config -text \"" +
                theNewShgStruct.phaseName + "\"";
   myTclEval(interp, commandStr);

   // Update the message text:
   commandStr = msgTextWindowName + " delete 1.0 end";
      // this says 'delete from char 0 of line 1' (tk decrees that line 1 is the first line)
   myTclEval(interp, commandStr);

   commandStr = msgTextWindowName + " insert end \"" + theNewShgStruct.msgText + "\"";
   myTclEval(interp, commandStr);

   commandStr = msgTextWindowName + " yview -pickplace end";
   myTclEval(interp, commandStr);

   // We must resize, since newly displayed shg had been set aside (is this right?)
   theNewShgStruct.theShg->resize(true);
   
   return true;
}
Ejemplo n.º 24
0
// processLinkMaps: This routine is called by getSharedObjects to  
// process all shared objects that have been mapped into the process's
// address space.  This routine reads the link maps from the application 
// process to find the shared object file base mappings. It returns 0 on error.
bool dynamic_linking::processLinkMaps(pdvector<fileDescriptor> &descs) {
   r_debug debug_elm;
   if(!proc->readDataSpace((caddr_t)(r_debug_addr),
                        sizeof(r_debug),(caddr_t)&(debug_elm),true)) {
      // bperr("read d_ptr_addr failed r_debug_addr = 0x%lx\n",r_debug_addr);
      return 0;
   }

   // get each link_map object
   Link_map *next_link_map = debug_elm.r_map;
   Address next_addr = (Address)next_link_map; 
   
   while(next_addr != 0){
       Link_map link_elm;

       if(!proc->readDataSpace((caddr_t)(next_addr),
                               sizeof(Link_map),(caddr_t)&(link_elm),true)) {
           logLine("read next_link_map failed\n");
           return 0;
       }
       // get file name
       char f_name[256]; // assume no file names greater than 256 chars
       // check to see if reading 256 chars will go out of bounds
       // of data segment
       u_int f_amount = 256;
       bool done = false;
       for(u_int i=0; (i<256) && (!done); i++){
           if(!proc->readDataSpace((caddr_t)((u_int)(link_elm.l_name)+i),
                                   sizeof(char),(caddr_t)(&(f_name[i])),true)){
           }
           if(f_name[i] == '\0'){
               done = true;
               f_amount = i+1;
           }
       }
       f_name[f_amount-1] = '\0';
       pdstring obj_name = pdstring(f_name);

      parsing_cerr << 
         "dynamicLinking::processLinkMaps(): file name of next shared obj="
                     << obj_name << endl;

      // create a mapped_object and add it to the list
      // kludge: ignore the entry if it has the same name as the
      // executable file...this seems to be the first link-map entry
      // VG(09/25/01): also ignore if address is 65536 or name is (unknown)
      if(obj_name != proc->getAOut()->fileName() && 
         obj_name != proc->getAOut()->fullName() &&
         link_elm.l_addr != 65536 &&
         obj_name != "(unknown)"
         //strncmp(obj_name.c_str(), "(unknown)", 10)
         ) {
          
          fileDescriptor desc = fileDescriptor(obj_name, link_elm.l_addr,
                                               link_elm.l_addr,
                                               true);
          descs.push_back(desc);          
      }
      
      next_addr = (Address)link_elm.l_next;
   }

   return true;
}
Ejemplo n.º 25
0
// processLinkMaps: get a list of all loaded objects in fileDescriptor form.
bool dynamic_linking::processLinkMaps(pdvector<fileDescriptor> &descs) {
    
    int proc_fd = proc->getRepresentativeLWP()->get_fd();
    if(!proc_fd){ return false;}

    // step 2: get the runtime loader table from the process
    Address ldr_base_addr;
    ldr_context first;
    ldr_module module;

    assert(proc->readDataSpace((const void*)LDR_BASE_ADDR,sizeof(Address), &ldr_base_addr, true));
    assert(proc->readDataSpace((const void*)ldr_base_addr,sizeof(ldr_context), &first, true));
    assert(proc->readDataSpace((const void *) first.head,sizeof(ldr_module), &module, true));
    
    while (module.next != first.head) {
      if (module.nregions == 0)
	{ 
	  assert(proc->readDataSpace((const void *) module.next,sizeof(ldr_module), &module,true));
	  continue;
        }
      pdstring obj_name = pdstring(readDataString(proc, module.name));
      ldr_region *regions;
      
      regions = (ldr_region *) malloc(module.nregions * sizeof(ldr_region));
      assert(proc->readDataSpace((const void *) module.regions, 
				 sizeof(ldr_region)*module.nregions, regions, true));
      
      long offset = regions[0].mapaddr - regions[0].vaddr;
#ifdef notdef
      if (offset) {
	bperr("*** shared lib at non-default offset **: ");
	bperr("    %s\n", obj_name.c_str());
	bperr("    offset = %ld\n", offset);
      } else {
	bperr("*** shared lib **: ");
	bperr("    %s\n", obj_name.c_str());
	bperr("    at = %ld\n", regions[0].mapaddr);
      }
#endif
      
      for (int i=0; i < module.nregions; i++) {
	long newoffset = regions[i].mapaddr - regions[i].vaddr;
	if (newoffset != offset) {
	  bperr( "shared lib regions have different offsets\n");
	}
	regions[i].name = (long unsigned) readDataString(proc,
							 (void *) regions[i].name);
	// bperr("  region %d (%s) ", i, regions[i].name);
	// bperr("addr = %lx, ", regions[i].vaddr);
	// bperr("mapped at = %lx, ", regions[i].mapaddr);
	// bperr("size = %x\n", regions[i].size);
      }
      descs.push_back(fileDescriptor(obj_name, 
				     offset,
				     offset,
				     true));

      free(regions);
      assert(proc->readDataSpace((const void *) module.next,sizeof(ldr_module), &module,true));
    }
    return true;
}
Ejemplo n.º 26
0
bool process::loadDYNINSTlib() {
  /* Look for a function we can hijack to forcibly load dyninstapi_rt. 
     This is effectively an inferior RPC with the caveat that we're
     overwriting code instead of allocating memory from the RT heap. 
     (So 'hijack' doesn't mean quite what you might think.) */
  Address codeBase = findFunctionToHijack(this);	

  if( !codeBase ) { return false; }
  
  /* glibc 2.3.4 and higher adds a fourth parameter to _dl_open().
     While we could probably get away with treating the three and four
     -argument functions the same, check the version anyway, since
     we'll probably need to later. */
  bool useFourArguments = true;
  Symbol libcVersionSymbol;
  if( getSymbolInfo( "__libc_version", libcVersionSymbol ) ) {
    char libcVersion[ sizeof( int ) * libcVersionSymbol.size() + 1 ];
	libcVersion[ sizeof( int ) * libcVersionSymbol.size() ] = '\0';
    if( ! readDataSpace( (void *) libcVersionSymbol.addr(), libcVersionSymbol.size(), libcVersion, true ) ) {
      fprintf( stderr, "%s[%d]: warning, failed to read libc version, assuming 2.3.4+\n", __FILE__, __LINE__ );
      }
    else {
      startup_printf( "%s[%d]: libcVersion: %s\n", __FILE__, __LINE__, libcVersion );

      /* We could potentially add a sanity check here to make sure we're looking at 2.3.x. */
      int microVersion = ((int)libcVersion[4]) - ((int)'0');
      if( microVersion <= 3 ) {
	    useFourArguments = false;
        }
      } /* end if we read the version symbol */
    } /* end if we found the version symbol */

  if( useFourArguments ) { startup_printf( "%s[%d]: using four arguments.\n", __FILE__, __LINE__ ); }

  /* Fetch the name of the run-time library. */
  const char DyninstEnvVar[]="DYNINSTAPI_RT_LIB";
        
  if( ! dyninstRT_name.length() ) { // we didn't get anything on the command line
    if (getenv(DyninstEnvVar) != NULL) {
      dyninstRT_name = getenv(DyninstEnvVar);
    } else {
      pdstring msg = pdstring( "Environment variable " + pdstring( DyninstEnvVar )
			       + " has not been defined for process " ) + pdstring( getPid() );
      showErrorCallback(101, msg);
      return false;
    } /* end if enviromental variable not found */
  } /* end enviromental variable extraction */
        
  /* Save the (main thread's) current PC.*/
  savedPC = getRepresentativeLWP()->getActiveFrame().getPC();	
        
  /* _dl_open() takes three arguments: a pointer to the library name,
     the DLOPEN_MODE, and the return address of the current frame
     (that is, the location of the SIGILL-generating bundle we'll use
     to handleIfDueToDyninstLib()).  We construct the first here. */
        
  /* Write the string to entry, and then move the PC to the next bundle. */
  codeGen gen(BYTES_TO_SAVE);
        
  Address dyninstlib_addr = gen.used() + codeBase;
  gen.copy(dyninstRT_name.c_str(), dyninstRT_name.length()+1);
        
  Address dlopencall_addr = gen.used() + codeBase;
	
  /* At this point, we use the generic iRPC headers and trailers
     around the call to _dl_open.  (Note that pre-1.35 versions
     of this file had a simpler mechanism well-suited to boot-
     strapping a new port.  The current complexity is to handle
     the attach() case, where we don't know if execution was stopped
     at the entry the entry point to a function. */

  bool ok = theRpcMgr->emitInferiorRPCheader(gen);
  if( ! ok ) { return false; }
	
  /* Generate the call to _dl_open with a large dummy constant as the
     the third argument to make sure we generate the same size code the second
     time around, with the correct "return address." (dyninstlib_brk_addr) */
  // As a quick note, we want to "return" to the beginning of the restore
  // segment, not dyninstlib_brk_addr (or we skip all the restores).
  // Of course, we're not sure what this addr represents....

  pdvector< AstNode * > dlOpenArguments( 4 );
  AstNode * dlOpenCall;
	
  dlOpenArguments[ 0 ] = new AstNode( AstNode::Constant, (void *)dyninstlib_addr );
  dlOpenArguments[ 1 ] = new AstNode( AstNode::Constant, (void *)DLOPEN_MODE );
  dlOpenArguments[ 2 ] = new AstNode( AstNode::Constant, (void *)0xFFFFFFFFFFFFFFFF );
  if( useFourArguments ) { 
  	/* I derived the -2 as follows: from dlfcn/dlopen.c in the glibc sources, line 59,
  	   we find the call to _dl_open(), whose last argument is 'args->file == NULL ? LM_ID_BASE : NS'.
  	   Since the filename we pass in is non-null, this means we (would) pass in NS, which
  	   is defined to be __LM_ID_CALLER in the same file, line 48.  (Since glibc must be shared
  	   for us to be calling _dl_open(), we fall into the second case of the #ifdef.)  __LM_ID_CALLER
  	   is defined in include/dlfcn.h, where it has the value -2. */
    dlOpenArguments[ 3 ] = new AstNode( AstNode::Constant, (void *)(long unsigned int)-2 );
    }
  dlOpenCall = new AstNode( "_dl_open", dlOpenArguments );
	
  /* Remember where we originally generated the call. */
  codeBufIndex_t index = gen.getIndex();
	
  /* emitInferiorRPCheader() configures (the global) registerSpace for us. */
  dlOpenCall->generateCode( this, regSpace, gen, true, true );

  // Okay, we're done with the generation, and we know where we'll be.
  // Go back and regenerate it
  Address dlopenRet = codeBase + gen.used();
  gen.setIndex(index);

  /* Clean up the reference counts before regenerating. */
  removeAst( dlOpenCall );
  removeAst( dlOpenArguments[ 2 ] );
	
  dlOpenArguments[ 2 ] = new AstNode( AstNode::Constant, (void *)dlopenRet );
  dlOpenCall = new AstNode( "_dl_open", dlOpenArguments );
	
  /* Regenerate the call at the same original location with the correct constants. */
  dlOpenCall->generateCode( this, regSpace, gen, true, true );

  /* Clean up the reference counting. */
  removeAst( dlOpenCall );
  removeAst( dlOpenArguments[ 0 ] );
  removeAst( dlOpenArguments[ 1 ] );
  removeAst( dlOpenArguments[ 2 ] );
  if( useFourArguments ) { removeAst( dlOpenArguments[ 3 ] ); }

  // Okay, that was fun. Now restore. And trap. And stuff.
        
	
  unsigned breakOffset, resultOffset, justAfterResultOffset;
  ok = theRpcMgr->emitInferiorRPCtrailer(gen, breakOffset, false, 
					 resultOffset, justAfterResultOffset );
  if( ! ok ) { return false; }					 

  /* Let everyone else know that we're expecting a SIGILL. */
  dyninstlib_brk_addr = codeBase + breakOffset;

  assert(gen.used() < BYTES_TO_SAVE);

  /* Save the function we're going to hijack. */
  InsnAddr iAddr = InsnAddr::generateFromAlignedDataAddress( codeBase, this );
  /* We need to save the whole buffer, because we don't know how big gen is
     when we do the restore.  This could be made more efficient by storing
     gen.used() somewhere. */
  iAddr.saveBundlesTo( savedCodeBuffer, sizeof( savedCodeBuffer ) / 16 );

  /* Write the call into the mutatee. */
  InsnAddr jAddr = InsnAddr::generateFromAlignedDataAddress( codeBase, this );
  jAddr.writeBundlesFrom( (unsigned char *)gen.start_ptr(), gen.used() / 16 );

  /* Now that we know where the code will start, move the (main thread's) PC there. */
  getRepresentativeLWP()->changePC( dlopencall_addr, NULL );

  /* Let them know we're working on it. */
  setBootstrapState( loadingRT_bs );
  return true;
} /* end dlopenDYNINSTlib() */
Ejemplo n.º 27
0
// findFunctionIn_ld_so_1: this routine finds the symbol table for ld.so.1 and 
// parses it to find the address of symbol r_debug
// it returns false on error
bool dynamic_linking::findFunctionIn_ld_so_1(pdstring f_name, int ld_fd, 
					     Address ld_base_addr, 
					     Address *f_addr, int st_type)
{
    bool result = false;
    Elf_X elf;
    Elf_X_Shdr shstrscn;
    Elf_X_Data shstrdata;
    Elf_X_Shdr symscn;
    Elf_X_Shdr strscn;
    Elf_X_Data symdata;
    Elf_X_Data strdata;

    const char *shnames = NULL;

    lseek(ld_fd, 0, SEEK_SET);
    elf = Elf_X(ld_fd, ELF_C_READ);
    if (elf.isValid()) shstrscn = elf.get_shdr( elf.e_shstrndx() );
    if (shstrscn.isValid()) shstrdata = shstrscn.get_data();
    if (shstrdata.isValid()) shnames = shstrdata.get_string();

    if (elf.isValid() && shstrscn.isValid() && shstrdata.isValid()) {
	for (int i = 0; i < elf.e_shnum(); ++i) {
	    Elf_X_Shdr shdr = elf.get_shdr(i);
	    if (!shdr.isValid()) return false;
	    const char* name = (const char *) &shnames[shdr.sh_name()];

	    if (P_strcmp(name, ".symtab") == 0) {
		symscn = shdr;

	    } else if (P_strcmp(name, ".strtab") == 0) {
		strscn = shdr;
	    }
	}

	if (strscn.isValid()) symdata = symscn.get_data();
	if (symscn.isValid()) strdata = strscn.get_data();
	if (symdata.isValid() && strdata.isValid()) {
	    Elf_X_Sym syms = symdata.get_sym();
	    const char* strs = strdata.get_string();

	    if (f_addr != NULL) *f_addr = 0;

	    for (u_int i = 0; i < syms.count(); ++i) {
		if (syms.st_shndx(i) != SHN_UNDEF) {
		    if (syms.ST_TYPE(i) == st_type) {
			pdstring name = pdstring(&strs[ syms.st_name(i) ]);
			if (name == f_name) {
			    if (f_addr != NULL) {
				*f_addr = syms.st_value(i) + ld_base_addr;
			    }
			    result = true;
			    break;
			}
		    }
		}
	    }
	}
    }
    elf.end();

    return result;
}