Merge branch 'jistone/coverity'
[dyninst.git] / dyninstAPI / src / unix.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 // $Id: unix.C,v 1.243 2008/06/30 17:33:31 legendre Exp $
32
33 #include "os.h"
34 #include "debug.h"
35 #include "mapped_object.h"
36 #include "mapped_module.h"
37 #include "dynProcess.h"
38 #include "dynThread.h"
39 #include "function.h"
40
41 #include "common/src/pathName.h"
42
43 #include <sstream>
44
45 extern char **environ;
46
47 using namespace Dyninst::ProcControlAPI;
48
49 // Functions for all Unices //
50
51 bool PCProcess::hideDebugger()
52 {
53     return false;
54 }
55
56 bool OS::executableExists(const std::string &file) 
57 {
58    struct stat file_stat;
59    int stat_result;
60
61    const char *fn = file.c_str();
62    stat_result = stat(fn, &file_stat);
63    return (stat_result != -1);
64 }
65
66 void OS::get_sigaction_names(std::vector<std::string> &names)
67 {
68    names.push_back(string("sigaction"));
69    names.push_back(string("signal"));
70 }
71
72
73
74 std::string PCProcess::createExecPath(const std::string &file, const std::string &dir) {
75     std::string ret = file;
76     if (dir.length() > 0) {
77         if (!(file[0] == ('/'))) {
78             // file does not start  with a '/', so it is a relative pathname
79             // we modify it to prepend the given directory
80             if (dir[dir.length()-1 ] == ('/') ) {
81                 // the dir already has a trailing '/', so we can
82                 // just concatenate them to get an absolute path
83                 ret =  dir + file;
84             } else {
85                 // the dir does not have a trailing '/', so we must
86                 // add a '/' to get the absolute path
87                 ret =  dir + "/" + file;
88             }
89         } else {
90             // file starts with a '/', so it is an absolute pathname
91             // DO NOT prepend the directory, regardless of what the
92             // directory variable holds.
93             // nothing to do in this case
94         }
95
96     }
97     return ret;
98 }
99
100 // If true is passed for ignore_if_mt_not_set, then an error won't be
101 // initiated if we're unable to determine if the program is multi-threaded.
102 // We are unable to determine this if the daemon hasn't yet figured out what
103 // libraries are linked against the application.  Currently, we identify an
104 // application as being multi-threaded if it is linked against a thread
105 // library (eg. libpthreads.a on AIX).  There are cases where we are querying
106 // whether the app is multi-threaded, but it can't be determined yet but it
107 // also isn't necessary to know.
108 bool PCProcess::multithread_capable(bool ignoreIfMtNotSet) {
109     if( mt_cache_result_ != not_cached ) {
110         if( mt_cache_result_ == cached_mt_true) return true;
111         else return false;
112     }
113
114     if( mapped_objects.size() <= 1 ) {
115         assert( ignoreIfMtNotSet && "Can't query MT state" );
116         return false;
117     }
118
119     if(    findObject("libthread.so*", true) // Solaris
120         || findObject("libpthreads.*", true) // AIX
121         || findObject("libpthread.so*", true) // Linux
122         || findObject("libpthread-*.so", true) // Linux
123         || findObject("libthr.*", true) ) // FreeBSD
124     {
125         mt_cache_result_ = cached_mt_true;
126         return true;
127     }
128
129     mt_cache_result_ = cached_mt_false;
130     return false;
131 }
132
133 /**
134  * Searches for function in order, with preference given first
135  * to libpthread, then to libc, then to the process.
136  **/
137 static void findThreadFuncs(PCProcess *p, std::string func,
138                             pdvector<func_instance *> &result) {
139     bool found = false;
140     mapped_module *lpthread = p->findModule("libpthread*", true);
141     if (lpthread)
142         found = lpthread->findFuncVectorByPretty(func, result);
143     if (found)
144         return;
145
146     mapped_module *lc = p->findModule("libc.so*", true);
147     if (lc)
148         found = lc->findFuncVectorByPretty(func, result);
149     if (found)
150         return;
151
152     p->findFuncsByPretty(func, result);
153 }
154
155 bool PCProcess::instrumentMTFuncs() {
156     bool res;
157
158     /**
159      * Have dyn_pthread_self call the actual pthread_self
160      **/
161     //Find dyn_pthread_self
162     pdvector<int_variable *> ptself_syms;
163     res = findVarsByAll("DYNINST_pthread_self", ptself_syms);
164     if (!res) {
165         fprintf(stderr, "[%s:%d] - Couldn't find any dyn_pthread_self, expected 1\n",
166                 __FILE__, __LINE__);
167     }
168     assert(ptself_syms.size() == 1);
169     Address dyn_pthread_self = ptself_syms[0]->getAddress();
170     //Find pthread_self
171     pdvector<func_instance *> pthread_self_funcs;
172     findThreadFuncs(this, "pthread_self", pthread_self_funcs);
173     if (pthread_self_funcs.size() != 1) {
174         fprintf(stderr, "[%s:%d] - Found %ld pthread_self functions, expected 1\n",
175                 __FILE__, __LINE__, (long) pthread_self_funcs.size());
176         for (unsigned j=0; j<pthread_self_funcs.size(); j++) {
177             func_instance *ps = pthread_self_funcs[j];
178             fprintf(stderr, "[%s:%u] - %s in module %s at %lx\n", __FILE__, __LINE__,
179                     ps->prettyName().c_str(), ps->mod()->fullName().c_str(),
180                     ps->addr());
181         }
182         return false;
183     }
184     //Replace
185     res = writeFunctionPtr(this, dyn_pthread_self, pthread_self_funcs[0]);
186     if (!res) {
187         fprintf(stderr, "[%s:%d] - Couldn't update dyn_pthread_self\n",
188                 __FILE__, __LINE__);
189         return false;
190     }
191
192     return true;
193 }
194
195 bool PCEventHandler::shouldStopForSignal(int signal) {
196     if( signal == SIGSTOP ) return true;
197     return false;
198 }
199
200 bool PCEventHandler::isCrashSignal(int signal) {
201     switch(signal) {
202         case SIGBUS:
203         case SIGSEGV:
204         case SIGABRT:
205         case SIGILL:
206         case SIGFPE:
207         case SIGTRAP:
208             return true;
209         default:
210             return false;
211     }
212 }
213
214 bool PCEventHandler::isKillSignal(int signal) {
215     switch(signal) {
216         case SIGKILL:
217         case SIGTERM:
218             return true;
219         default:
220             return false;
221     }
222 }
223
224 bool PCEventHandler::isValidRTSignal(int signal, RTBreakpointVal breakpointVal, 
225         Address arg1, int status)
226 {
227     /* Okay... we use both DYNINST_BREAKPOINT_SIGNUM and sigstop,
228      * depending on what we're trying to stop. So we have to check the
229      *flags against the signal
230      */
231     if( signal == SIGSTOP ) {
232         if( breakpointVal == SoftRTBreakpoint ) {
233             if( status == DSE_forkExit ) {
234                 if( arg1 == 0 ) return true;
235
236                 proccontrol_printf("%s[%d]: parent process received SIGSTOP\n",
237                         FILE__, __LINE__);
238             }else{
239                 proccontrol_printf("%s[%d]: SIGSTOP wasn't due to fork exit\n",
240                         FILE__, __LINE__);
241             }
242         }else{
243             proccontrol_printf("%s[%d]: mismatch in signal for breakpoint type\n",
244                     FILE__, __LINE__);
245         }
246     }else if( signal == DYNINST_BREAKPOINT_SIGNUM ) {
247         if( breakpointVal == NormalRTBreakpoint ) {
248             if( (status != DSE_forkExit) || (arg1 != 0) ) return true;
249
250             proccontrol_printf("%s[%d]: child received signal %d\n",
251                     FILE__, __LINE__, DYNINST_BREAKPOINT_SIGNUM);
252         }else{
253             proccontrol_printf("%s[%d]: mismatch in signal for breakpoint type\n",
254                     FILE__, __LINE__);
255         }
256     }else{
257         proccontrol_printf("%s[%d]: signal wasn't sent by RT library\n",
258                 FILE__, __LINE__);
259     }
260
261     return false;
262 }
263
264 mapped_object *PCProcess::createObjectNoFile(Address) {
265     assert(0); // not implemented on UNIX
266     return NULL;
267 }
268
269 void PCProcess::changeMemoryProtections(Address addr, size_t size,
270                                         PCMemPerm rights, bool setShadow) {
271     (void)addr;
272     (void)size;
273     (void)rights;
274     (void)setShadow;
275     assert(!"Not implemented yet");
276 }
277
278 bool PCProcess::setMemoryAccessRights(Address start, size_t size,
279                                       PCMemPerm rights) {
280     mal_printf("setMemoryAccessRights to %s [%lx %lx]\n",
281                rights.getPermName().c_str(), start, start+size);
282     assert(!"Not implemented yet");
283     return false;
284 }
285
286 bool PCProcess::getMemoryAccessRights(Address start, PCMemPerm& rights) {
287     mal_printf("getMemoryAccessRights at %lx\n", start);
288     assert(!"Not implemented yet");
289     (void)rights; // unused parameter
290     return false;
291 }
292
293 void PCProcess::redirectFds(int stdin_fd, int stdout_fd, int stderr_fd,
294         std::map<int, int> &fds)
295 {
296     if( stdin_fd != 0 ) fds.insert(std::make_pair(stdin_fd, 0));
297     if( stdout_fd != 1 ) fds.insert(std::make_pair(stdout_fd, 1));
298     if( stderr_fd != 2 ) fds.insert(std::make_pair(stderr_fd, 2));
299 }
300
301 bool PCProcess::setEnvPreload(std::vector<std::string> &envp, std::string fileName) {
302     const unsigned int ERROR_CODE = 101;
303     bool use_abi_rt = false;
304     (void)fileName; // unused
305
306 #if defined(arch_64bit)
307     SymtabAPI::Symtab *symt_obj;
308     bool result = SymtabAPI::Symtab::openFile(symt_obj, fileName);
309     if( !result ) return false;
310
311     use_abi_rt = (symt_obj->getAddressWidth() == 4);
312 #endif
313
314     const char *rt_lib_name = getenv("DYNINSTAPI_RT_LIB");
315     if( rt_lib_name == NULL ) {
316         showErrorCallback(ERROR_CODE, std::string("setEnvPreload: DYNINSTAPI_RT_LIB is undefined"));
317         proccontrol_printf("%s[%d]: DYNINSTAPI_RT_LIB is undefined\n");
318         return false;
319     }
320
321     std::string full_name;
322     if (use_abi_rt) {
323         const char *slash = P_strrchr(rt_lib_name, '/');
324         if (!slash)
325             slash = P_strrchr(rt_lib_name, '\\');
326         if (!slash)
327             return false;
328         const char *dot = P_strchr(slash, '.');
329         if (!dot)
330             return false;
331         full_name = std::string(rt_lib_name, dot - rt_lib_name) +
332                     std::string("_m32") +
333                     std::string(dot);
334         rt_lib_name = full_name.c_str();
335     }
336
337     // Check to see if the library given exists.
338     if (access(rt_lib_name, R_OK)) {
339         std::string msg = std::string("Runtime library ") + std::string(rt_lib_name) +
340                           std::string(" does not exist or cannot be accessed!");
341         cerr << msg << endl;
342         showErrorCallback(ERROR_CODE, msg);
343         return false;
344     }
345
346     const char *var_name = "LD_PRELOAD";
347     if (envp.size()) {
348         // Check if some LD_PRELOAD is already part of the environment.
349         std::vector<std::string>::iterator ldPreloadVal =  envp.end();
350         for(std::vector<std::string>::iterator i = envp.begin();
351                 i != envp.end(); ++i)
352         {
353             if( (*i) == var_name ) {
354                 ldPreloadVal = i;
355                 break;
356             }
357         }
358
359         if (ldPreloadVal == envp.end()) {
360             // Not found, append an entry
361             std::string ld_preload = std::string(var_name) + std::string("=") +
362                                      std::string(rt_lib_name);
363             startup_printf("LD_PRELOAD=%s\n", ld_preload.c_str());
364             envp.push_back(ld_preload);
365         } else {
366             // Found, modify envs in-place
367             std::string ld_preload = *ldPreloadVal + std::string(":") +
368                                      std::string(rt_lib_name);
369             startup_printf("LD_PRELOAD=%s\n", ld_preload.c_str());
370             *ldPreloadVal = ld_preload;
371         }
372     } else {
373         // Environment inherited from this process, copy the current
374         // environment to envp, modifying/adding LD_PRELOAD
375         char *ld_preload_orig = NULL;
376         int i = 0;
377         while( environ[i] != NULL ) {
378             std::string envVar(environ[i]);
379             if( envVar.find("LD_PRELOAD=") == 0 ) {
380                 ld_preload_orig = environ[i];
381             }else{
382                 envp.push_back(envVar);
383             }
384             i++;
385         }
386
387         std::string ld_preload;
388         if (ld_preload_orig) {
389             // Append to existing var
390             ld_preload = std::string(var_name) + std::string("=") +
391                          std::string(ld_preload_orig) + std::string(":") +
392                          std::string(rt_lib_name);
393         } else {
394             // Define a new var
395             ld_preload = std::string(var_name) + std::string("=") +
396                          std::string(rt_lib_name);
397         }
398         envp.push_back(ld_preload);
399     }
400
401     return true;
402 }
403
404
405 bool PCProcess::getExecFileDescriptor(string filename,
406         bool, fileDescriptor &desc)
407 {
408    Address base = 0;
409
410     desc = fileDescriptor(filename.c_str(),
411                           base, // code
412                           base, // data
413                           false); // a.out
414     return true;
415 }
416
417 /**
418  * Strategy:  The program entry point is in /lib/ld-2.x.x at the 
419  * _start function.  Get the current PC, parse /lib/ld-2.x.x, and 
420  * compare the two points.
421  **/
422 bool PCProcess::hasPassedMain() 
423 {
424    using namespace SymtabAPI;
425    Symtab *ld_file = NULL;
426    Address entry_addr, ldso_start_addr = 0;
427
428    //Get current PC
429    Frame active_frame = initialThread_->getActiveFrame();
430    Address current_pc = active_frame.getPC();
431
432    // Get the interpreter name from SymtabAPI
433    const char *path = getAOut()->parse_img()->getObject()->getInterpreterName();
434
435    if (!path) {
436       //Strange... This shouldn't happen on a normal linux system
437       startup_printf("[%s:%u] - Couldn't find /lib/ld-x.x.x in hasPassedMain\n",
438                      FILE__, __LINE__);
439       return true;
440    }
441
442    std::string derefPath = resolve_file_path(path);
443
444    // Search for the dynamic linker in the loaded libraries
445    const LibraryPool &libraries = pcProc_->libraries();
446    bool foundDynLinker = false;
447    for(LibraryPool::const_iterator i = libraries.begin(); i != libraries.end();
448            ++i)
449    {
450        if( (*i)->getAbsoluteName() == derefPath ) {
451            foundDynLinker = true;
452            ldso_start_addr = (*i)->getLoadAddress();
453        }
454    }
455
456    if( !foundDynLinker ) {
457        // This means that libraries haven't been loaded yet which implies
458        // that main hasn't been reached yet
459        return false;
460    }
461
462    //Open /lib/ld-x.x.x and find the entry point
463    if (!Symtab::openFile(ld_file, derefPath)) {
464       startup_printf("[%s:%u] - Unable to open %s in hasPassedMain\n", 
465                      FILE__, __LINE__, path);
466       return true;
467    }
468
469    entry_addr = ld_file->getEntryOffset();
470    if (!entry_addr) {
471       startup_printf("[%s:%u] - No entry addr for %s\n", 
472                      FILE__, __LINE__, path);
473       return true;
474    }
475
476    entry_addr += ldso_start_addr;
477
478    if( !getOPDFunctionAddr(entry_addr) ) {
479        startup_printf("[%s:%u] - failed to read entry addr function pointer\n",
480                FILE__, __LINE__);
481        return false;
482    }
483
484    if( entry_addr < ldso_start_addr ) {
485        entry_addr += ldso_start_addr;
486    }
487    
488    bool result = (entry_addr != current_pc);
489    startup_printf("[%s:%u] - hasPassedMain returning %d (%lx %lx)\n",
490                   FILE__, __LINE__, (int) result, entry_addr, current_pc);
491
492    return result;
493 }
494
495 bool PCProcess::startDebugger() {
496     std::stringstream pidStr;
497     pidStr << getPid();
498
499     const char *args[4];
500     args[0] = dyn_debug_crash_debugger;
501     args[1] = file_.c_str();
502     args[2] = pidStr.str().c_str();
503     args[3] = NULL;
504
505     proccontrol_printf("%s[%d]: Launching %s %s %s\n", FILE__, __LINE__,
506             args[0], args[1], args[2]);
507     if( execv(args[0], const_cast<char **>(args)) == -1 ) {
508         perror("execv");
509         return false;
510     }
511
512     return true;
513 }
514
515 // The following functions are only implemented on some Unices //
516
517 #if defined(os_linux) || defined(os_freebsd)
518
519 #include "dyninstAPI/src/binaryEdit.h"
520 #include "symtabAPI/h/Archive.h"
521
522 using namespace Dyninst::SymtabAPI;
523
524
525 mapped_object *BinaryEdit::openResolvedLibraryName(std::string filename,
526                                                    std::map<std::string, BinaryEdit*> &retMap) {
527     std::vector<std::string> paths;
528     std::vector<std::string>::iterator pathIter;
529     // First, find the specified library file
530     bool resolved = getResolvedLibraryPath(filename, paths);
531
532     // Second, create a set of BinaryEdits for the found library
533     if ( resolved ) {
534         startup_printf("[%s:%u] - Opening dependent file %s\n",
535                        FILE__, __LINE__, filename.c_str());
536
537         Symtab *origSymtab = getMappedObject()->parse_img()->getObject();
538         assert(mgr());
539         // Dynamic case
540         if ( !origSymtab->isStaticBinary() ) {
541             for(pathIter = paths.begin(); pathIter != paths.end(); ++pathIter) {
542                BinaryEdit *temp = BinaryEdit::openFile(*pathIter, mgr(), patcher());
543
544                 if (temp && temp->getAddressWidth() == getAddressWidth()) {
545                     retMap.insert(std::make_pair(*pathIter, temp));
546                     return temp->getMappedObject();
547                 }
548                 delete temp;
549             }
550         } else {
551             // Static executable case
552
553             /* 
554              * Alright, this is a kludge, but even though the Archive is opened
555              * twice (once here and once by the image class later on), it is
556              * only parsed once because the Archive class keeps track of all
557              * open Archives.
558              *
559              * This is partly due to the fact that Archives are collections of
560              * Symtab objects and their is one Symtab for each BinaryEdit. In
561              * some sense, an Archive is a collection of BinaryEdits.
562              */
563             for(pathIter = paths.begin(); pathIter != paths.end(); ++pathIter) {
564                 Archive *library;
565                 Symtab *singleObject;
566                 if (Archive::openArchive(library, *pathIter)) {
567                     std::vector<Symtab *> members;
568                     if (library->getAllMembers(members)) {
569                         std::vector <Symtab *>::iterator member_it;
570                         for (member_it = members.begin(); member_it != members.end();
571                              ++member_it) 
572                         {
573                            BinaryEdit *temp = BinaryEdit::openFile(*pathIter, 
574                                                                    mgr(), patcher(), (*member_it)->memberName());
575
576                             if (temp && temp->getAddressWidth() == getAddressWidth()) {
577                                 std::string mapName = *pathIter + string(":") +
578                                     (*member_it)->memberName();
579                                 retMap.insert(std::make_pair(mapName, temp));
580                             }else{
581                                 if(temp) delete temp;
582                                 retMap.clear();
583                                 break;
584                             }
585                         }
586
587                         if (retMap.size() > 0) {
588                             origSymtab->addLinkingResource(library);
589                             // So we tried loading "libc.a", and got back a swarm of individual members. 
590                             // Lovely. 
591                             // Just return the first thing...
592                             return retMap.begin()->second->getMappedObject();
593                         }
594                         //if( library ) delete library;
595                     }
596                 } else if (Symtab::openFile(singleObject, *pathIter)) {
597                    BinaryEdit *temp = BinaryEdit::openFile(*pathIter, mgr(), patcher());
598
599
600                     if (temp && temp->getAddressWidth() == getAddressWidth()) {
601                         if( singleObject->getObjectType() == obj_SharedLib ||
602                             singleObject->getObjectType() == obj_Executable ) 
603                         {
604                           startup_printf("%s[%d]: cannot load dynamic object(%s) when rewriting a static binary\n", 
605                                   FILE__, __LINE__, pathIter->c_str());
606                           std::string msg = std::string("Cannot load a dynamic object when rewriting a static binary");
607                           showErrorCallback(71, msg.c_str());
608
609                           delete singleObject;
610                         }else{
611                             retMap.insert(std::make_pair(*pathIter, temp));
612                             return temp->getMappedObject();
613                         }
614                     }
615                     if(temp) delete temp;
616                 }
617             }
618         }
619     }
620
621     startup_printf("[%s:%u] - Creation error opening %s\n",
622                    FILE__, __LINE__, filename.c_str());
623     // If the only thing we could find was a dynamic lib for a static executable, we can reach here; caller should handle this.
624     return NULL;
625 }
626
627 #endif
628
629 #if defined(os_linux) || defined(os_freebsd)
630
631 #include "dyninstAPI/src/instPoint.h"
632 #include "dyninstAPI/src/parse-cfg.h"
633 #include "dyninstAPI/src/function.h"
634 #include "dyninstAPI/src/addressSpace.h"
635 #include "symtabAPI/h/Symtab.h"
636 #include "dyninstAPI/src/mapped_object.h"
637 #include "dyninstAPI/src/binaryEdit.h"
638 #include "dyninstAPI/src/debug.h"
639 #include "boost/tuple/tuple.hpp"
640 #include <elf.h>
641
642 #if defined(os_linux)
643 #include "dyninstAPI/src/linux.h"
644 #else
645 #include "dyninstAPI/src/freebsd.h"
646 #endif
647
648 // The following functions were factored from linux.C to be used
649 // on both Linux and FreeBSD
650
651 // findCallee: finds the function called by the instruction corresponding
652 // to the instPoint "instr". If the function call has been bound to an
653 // address, then the callee function is returned in "target" and the 
654 // instPoint "callee" data member is set to pt to callee's func_instance.  
655 // If the function has not yet been bound, then "target" is set to the 
656 // func_instance associated with the name of the target function (this is 
657 // obtained by the PLT and relocation entries in the image), and the instPoint
658 // callee is not set.  If the callee function cannot be found, (ex. function
659 // pointers, or other indirect calls), it returns false.
660 // Returns false on error (ex. process doesn't contain this instPoint).
661 //
662 // HACK: made an func_instance method to remove from instPoint class...
663 // FURTHER HACK: made a block_instance method so we can share blocks
664 func_instance *block_instance::callee() {
665    // Check 1: pre-computed callee via PLT
666    func_instance *ret = obj()->getCallee(this);
667    if (ret) return ret;
668
669    // See if we've already done this
670    edge_instance *tEdge = getTarget();
671    if (!tEdge) {
672       return NULL;
673    }
674
675    if (!tEdge->sinkEdge()) {
676       func_instance *tmp = obj()->findFuncByEntry(tEdge->trg());
677       if (tmp && !(tmp->ifunc()->isPLTFunction())) {
678          return tmp;
679       }
680    }
681
682    
683
684    // Do this the hard way - an inter-module jump
685    // get the target address of this function
686    Address target_addr; bool success;
687    boost::tie(success, target_addr) = llb()->callTarget();
688    if(!success) {
689       // this is either not a call instruction or an indirect call instr
690       // that we can't get the target address
691       //fprintf(stderr, "%s[%d]:  returning NULL\n", FILE__, __LINE__);
692       return NULL;
693    }
694    
695    // get the relocation information for this image
696    Symtab *sym = obj()->parse_img()->getObject();
697    pdvector<relocationEntry> fbt;
698    vector <relocationEntry> fbtvector;
699    if (!sym->getFuncBindingTable(fbtvector)) {
700       //fprintf(stderr, "%s[%d]:  returning NULL\n", FILE__, __LINE__);
701       return NULL;
702    }
703
704
705    /**
706     * Object files and static binaries will not have a function binding table
707     * because the function binding table holds relocations used by the dynamic
708     * linker
709     */
710    if (!fbtvector.size() && !sym->isStaticBinary() && 
711            sym->getObjectType() != obj_RelocatableFile ) 
712    {
713       fprintf(stderr, "%s[%d]:  WARN:  zero func bindings\n", FILE__, __LINE__);
714    }
715
716    for (unsigned index=0; index< fbtvector.size();index++)
717       fbt.push_back(fbtvector[index]);
718    
719    Address base_addr = obj()->codeBase();
720    
721    std::map<Address, std::string> pltFuncs;
722    obj()->parse_img()->getPltFuncs(pltFuncs);
723
724    // find the target address in the list of relocationEntries
725    if (pltFuncs.find(target_addr) != pltFuncs.end()) {
726       for (u_int i=0; i < fbt.size(); i++) {
727          if (fbt[i].target_addr() == target_addr) 
728          {
729             // check to see if this function has been bound yet...if the
730             // PLT entry for this function has been modified by the runtime
731             // linker
732             func_instance *target_pdf = 0;
733             if (proc()->hasBeenBound(fbt[i], target_pdf, base_addr)) {
734                updateCallTarget(target_pdf);
735                obj()->setCalleeName(this, target_pdf->symTabName());
736                obj()->setCallee(this, target_pdf);
737                return target_pdf;
738             }
739          }
740       }
741       const char *target_name = pltFuncs[target_addr].c_str();
742       PCProcess *dproc = dynamic_cast<PCProcess *>(proc());
743
744       BinaryEdit *bedit = dynamic_cast<BinaryEdit *>(proc());
745       obj()->setCalleeName(this, std::string(target_name));
746       pdvector<func_instance *> pdfv;
747
748       // See if we can name lookup
749       if (dproc) {
750          if (proc()->findFuncsByMangled(target_name, pdfv)) {
751             obj()->setCallee(this, pdfv[0]);
752             updateCallTarget(pdfv[0]);
753             return pdfv[0];
754          }
755       }
756       else if (bedit) {
757          std::vector<BinaryEdit *>::iterator i;
758          for (i = bedit->getSiblings().begin(); i != bedit->getSiblings().end(); i++)
759          {
760             if ((*i)->findFuncsByMangled(target_name, pdfv)) {
761                obj()->setCallee(this, pdfv[0]);
762                updateCallTarget(pdfv[0]);
763                return pdfv[0];
764             }
765          }
766       }
767       else 
768          assert(0);
769    }
770    
771    //fprintf(stderr, "%s[%d]:  returning NULL: target addr = %p\n", FILE__, __LINE__, (void *)target_addr);
772    return NULL;
773 }
774
775 void BinaryEdit::makeInitAndFiniIfNeeded()
776 {
777     using namespace Dyninst::SymtabAPI;
778
779     Symtab* linkedFile = getAOut()->parse_img()->getObject();
780
781     // Disable this for .o's and static binaries
782     if( linkedFile->isStaticBinary() || 
783         linkedFile->getObjectType() == obj_RelocatableFile ) 
784     {
785         return;
786     }
787
788     bool foundInit = false;
789     bool foundFini = false;
790     vector <Function *> funcs;
791     if (linkedFile->findFunctionsByName(funcs, "_init")) {
792         foundInit = true;
793     }
794     if (linkedFile->findFunctionsByName(funcs, "_fini")) {
795         foundFini = true;
796     }
797     if( !foundInit )
798     {
799         Offset initOffset = linkedFile->getInitOffset();
800         Region *initsec = linkedFile->findEnclosingRegion(initOffset);
801         if(!initOffset || !initsec)
802         {
803             unsigned char* emptyFunction = NULL;
804             int emptyFuncSize = 0;
805 #if defined(arch_x86) || defined(arch_x86_64)
806             static unsigned char empty_32[] = { 0x55, 0x89, 0xe5, 0xc9, 0xc3 };
807             static unsigned char empty_64[] = { 0x55, 0x48, 0x89, 0xe5, 0xc9, 0xc3 };
808             if(linkedFile->getAddressWidth() == 8)
809             {
810                 emptyFunction = empty_64;
811                 emptyFuncSize = 6;
812             }
813             else
814             {
815                 emptyFunction = empty_32;
816                 emptyFuncSize = 5;
817             }
818 #elif defined (arch_power)
819             static unsigned char empty[] = { 0x4e, 0x80, 0x00, 0x20};
820              emptyFunction = empty;
821              emptyFuncSize = 4;
822 #endif //defined(arch_x86) || defined(arch_x86_64)
823             linkedFile->addRegion(highWaterMark_, (void*)(emptyFunction), emptyFuncSize, ".init.dyninst",
824                                   Dyninst::SymtabAPI::Region::RT_TEXT, true);
825             highWaterMark_ += emptyFuncSize;
826             lowWaterMark_ += emptyFuncSize;
827             linkedFile->findRegion(initsec, ".init.dyninst");
828             assert(initsec);
829             linkedFile->addSysVDynamic(DT_INIT, initsec->getMemOffset());
830             startup_printf("%s[%d]: creating .init.dyninst region, region addr 0x%lx\n",
831                            FILE__, __LINE__, initsec->getMemOffset());
832         }
833         startup_printf("%s[%d]: ADDING _init at 0x%lx\n", FILE__, __LINE__, initsec->getMemOffset());
834         Symbol *initSym = new Symbol( "_init",
835                                       Symbol::ST_FUNCTION,
836                                       Symbol::SL_GLOBAL,
837                                       Symbol::SV_DEFAULT,
838                                       initsec->getMemOffset(),
839                                       linkedFile->getDefaultModule(),
840                                       initsec,
841                                       UINT_MAX );
842         linkedFile->addSymbol(initSym);
843     }
844     if( !foundFini )
845     {
846         Offset finiOffset = linkedFile->getFiniOffset();
847         Region *finisec = linkedFile->findEnclosingRegion(finiOffset);
848         if(!finiOffset || !finisec)
849         {
850             unsigned char* emptyFunction = NULL;
851             int emptyFuncSize = 0;
852 #if defined(arch_x86) || defined(arch_x86_64)
853             static unsigned char empty_32[] = { 0x55, 0x89, 0xe5, 0xc9, 0xc3 };
854             static unsigned char empty_64[] = { 0x55, 0x48, 0x89, 0xe5, 0xc9, 0xc3 };
855             if(linkedFile->getAddressWidth() == 8)
856             {
857                 emptyFunction = empty_64;
858                 emptyFuncSize = 6;
859             }
860             else
861             {
862                 emptyFunction = empty_32;
863                 emptyFuncSize = 5;
864             }
865
866 #elif defined (arch_power)
867             static unsigned char empty[] = { 0x4e, 0x80, 0x00, 0x20};
868              emptyFunction = empty;
869              emptyFuncSize = 4;
870 #endif //defined(arch_x86) || defined(arch_x86_64)
871             linkedFile->addRegion(highWaterMark_, (void*)(emptyFunction), emptyFuncSize, ".fini.dyninst",
872                                   Dyninst::SymtabAPI::Region::RT_TEXT, true);
873             highWaterMark_ += emptyFuncSize;
874             lowWaterMark_ += emptyFuncSize;
875             linkedFile->findRegion(finisec, ".fini.dyninst");
876             assert(finisec);
877             linkedFile->addSysVDynamic(DT_FINI, finisec->getMemOffset());
878             startup_printf("%s[%d]: creating .fini.dyninst region, region addr 0x%lx\n",
879                            FILE__, __LINE__, finisec->getMemOffset());
880
881         }
882         startup_printf("%s[%d]: ADDING _fini at 0x%lx\n", FILE__, __LINE__, finisec->getMemOffset());
883         Symbol *finiSym = new Symbol( "_fini",
884                                       Symbol::ST_FUNCTION,
885                                       Symbol::SL_GLOBAL,
886                                       Symbol::SV_DEFAULT,
887                                       finisec->getMemOffset(),
888                                       linkedFile->getDefaultModule(),
889                                       finisec,
890                                       UINT_MAX );
891         linkedFile->addSymbol(finiSym);
892     }
893 }
894
895 Address PCProcess::setAOutLoadAddress(fileDescriptor &desc) {
896    //The load address of the a.out isn't correct.  We can't read a
897    // correct one out of ld-x.x.x.so because it may not be initialized yet,
898    // and it won't be initialized until we reach main.  But we need the load
899    // address to find main.  Darn.
900    //
901    //Instead we'll read the entry out of /proc/pid/maps, and try to make a good
902    // effort to correctly match the fileDescriptor to an entry.  Unfortunately,
903    // symlinks can complicate this, so we'll stat the files and compare inodes
904
905    struct stat aout, maps_entry;
906    map_entries *maps = NULL;
907    unsigned maps_size = 0, i;
908    char proc_path[128];
909    int result;
910    Address loadAddr = 0;
911
912    //Get the inode for the a.out
913    startup_printf("[%s:%u] - a.out is a shared library, computing load addr\n",
914                   FILE__, __LINE__);
915    memset(&aout, 0, sizeof(aout));
916    result = stat(pcProc_->libraries().getExecutable()->getAbsoluteName().c_str(), &aout);
917    if (result == -1) {
918       startup_printf("[%s:%u] - setAOutLoadAddress couldn't stat %s: %s\n",
919                      FILE__, __LINE__, proc_path, strerror(errno));
920       goto done;
921    }
922                     
923    //Get the maps
924    maps = getVMMaps(getPid(), maps_size);
925    if (!maps) {
926       startup_printf("[%s:%u] - setAOutLoadAddress, getVMMaps return NULL\n",
927                      FILE__, __LINE__);
928       goto done;
929    }
930    
931    //Compare the inode of each map entry to the a.out's
932    for (i=0; i<maps_size; i++) {
933       memset(&maps_entry, 0, sizeof(maps_entry));
934       result = stat(maps[i].path, &maps_entry);
935       if (result == -1) {
936          startup_printf("[%s:%u] - setAOutLoadAddress couldn't stat %s: %s\n",
937                         FILE__, __LINE__, maps[i].path, strerror(errno));
938          continue;
939       }
940       if (maps_entry.st_dev == aout.st_dev && maps_entry.st_ino == aout.st_ino)
941       {
942          //We have a match
943          
944          desc.setLoadAddr(maps[i].start);
945          loadAddr = maps[i].start;
946       }
947    }
948         
949  done:
950    if (maps)
951       free(maps);
952
953    return loadAddr;
954 }
955
956 #endif
957