Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / solaris.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 // $Id: solaris.C,v 1.224 2008/06/19 22:13:43 jaw Exp $
33
34 #include "dyninstAPI/src/symtab.h"
35 #include "common/h/headers.h"
36 #include "dyninstAPI/src/process.h"
37 #include "dyninstAPI/src/dyn_thread.h"
38 #include "common/h/stats.h"
39 #include "common/h/Types.h"
40 #include <sys/ioctl.h>
41 #include <fcntl.h>
42 #include <sys/termios.h>
43 #include <unistd.h>
44 #include <string>
45 #include "dyninstAPI/src/debug.h"
46 #include "common/h/pathName.h" // concat_pathname_components()
47 #include "common/h/debugOstream.h"
48 #include "common/h/solarisKludges.h"
49 #include "dyninstAPI/src/registerSpace.h"
50 #include "dyninstAPI/src/editSharedLibrary.h" //ccw 11 mar 2005
51 #include "mapped_module.h"
52 #include "mapped_object.h"
53 #include "dynamiclinking.h"
54 #include "dyninstAPI/h/BPatch.h"
55
56 #include "symtabAPI/src/Object.h" //TODO: Remove this
57
58 #if defined (sparc_sun_solaris2_4)
59 #include "dyninstAPI/src/inst-sparc.h"
60 #else
61 #include "dyninstAPI/src/inst-x86.h"
62 #endif
63
64 #include "signalgenerator.h"
65
66 #include "instPoint.h"
67 #include "baseTramp.h"
68 #include "miniTramp.h"
69
70 #include <procfs.h>
71 #include <stropts.h>
72 #include <link.h>
73 #include <dlfcn.h>
74 #include <strings.h> //ccw 11 mar 2005
75
76 #include "dyn_lwp.h"
77
78 #include "ast.h"
79 #define DLOPEN_MODE (RTLD_NOW | RTLD_GLOBAL)
80
81 extern "C" {
82 extern long sysconf(int);
83 };
84
85 /*
86    Define the indices of some registers to be used with pr_reg.
87    These values are different on sparc and x86 platforms.
88    RETVAL_REG: the registers that holds the return value of calls ($o0 on sparc,
89                %eax on x86).
90    PC_REG: program counter
91    FP_REG: frame pointer (%i7 on sparc, %ebp on x86) 
92 */
93 #ifdef sparc_sun_solaris2_4
94 #define PARAM1_REG (R_O0)
95 #define RETVAL_REG (R_O0)
96 #define PC_REG (R_PC)
97 #define FP_REG (R_O6)
98 #endif
99 #ifdef i386_unknown_solaris2_5
100 #define RETVAL_REG (EAX)
101 #define SP_REG (UESP)
102 #define PC_REG (EIP)
103 #define FP_REG (EBP)
104 #endif
105
106
107 // already setup on this FD.
108 // disconnect from controlling terminal 
109 void OS::osDisconnect(void) {
110   //This is the POSIX-compliant way of disconnecting from the terminal 
111   setpgrp();
112 }
113
114 /*
115  * The set operations (set_entry_syscalls and set_exit_syscalls) are defined
116  * in sol_proc.C
117  */
118
119
120 // Compatibility for /proc
121 bool process::get_entry_syscalls(sysset_t *entry)
122 {
123     pstatus_t status;
124     if (!get_status(&status)) return false;
125     
126     memcpy(entry, &(status.pr_sysentry), sizeof(sysset_t));    
127     return true;
128 }
129
130 bool process::get_exit_syscalls(sysset_t *exit)
131 {
132     pstatus_t status;
133     if (!get_status(&status)) return false;
134
135     memcpy(exit, &(status.pr_sysexit), sizeof(sysset_t));
136     return true;
137 }    
138
139 #if defined (cap_save_the_world)
140 //TODO: This function should be converted to use process objects, not BPatch.
141 bool process::dldumpSharedLibrary(std::string originalLibNameFullPath, char* dirName){
142     BPatch_Vector<BPatch_snippet *> args;
143     char *newLibName = saveWorldFindNewSharedLibraryName(originalLibNameFullPath.c_str(),dirName);
144     
145     bool exists;
146     BPatch_process *bproc = BPatch::bpatch->getProcessByPid(getPid(), &exists);
147     
148     assert(exists);
149     BPatch_constExpr *oldNameArg= new BPatch_constExpr(originalLibNameFullPath.c_str());
150     BPatch_constExpr *newNameArg = new BPatch_constExpr(newLibName);
151     
152     args.push_back(oldNameArg);
153     args.push_back(newNameArg);
154     
155     BPatch_Vector<BPatch_function *> bpfv;
156     
157     if (((NULL == bproc->getImage()->findFunction("DYNINSTsaveRtSharedLibrary", bpfv) || !bpfv.size()))) {
158         cout << __FILE__ << ":" << __LINE__ << ": FATAL:  Cannot find Internal Function " << "DYNINSTsaveRtSharedLibrary" << endl;
159         if( newLibName){
160             delete [] newLibName;
161         }
162         return false;
163     }
164     
165     BPatch_function *dldump_func = bpfv[0]; 
166     if (dldump_func == NULL) {
167         if(newLibName){
168             delete [] newLibName;
169         }
170         return false;
171     }
172     
173     BPatch_funcCallExpr call_dldump(*dldump_func, args);
174     
175     /*fprintf(stderr,"CALLING dldump\n"); */
176     if (!bproc->oneTimeCodeInternal(call_dldump, NULL, NULL, NULL,true)) {
177         fprintf(stderr, "%s[%d]:  oneTimeCodeInternal failed\n", FILE__, __LINE__);
178         // dldump FAILED
179         // find the (global var) error string in the RT Lib and send it to the
180         // error reporting mechanism
181         BPatch_variableExpr *dlerror_str_var = bproc->getImage()->findVariable("gLoadLibraryErrorString");
182         assert(NULL != dlerror_str_var);
183         
184         char dlerror_str[256];
185         dlerror_str_var->readValue((void *)dlerror_str, 256);
186         cerr << dlerror_str << endl;
187         BPatch_reportError(BPatchWarning, 0, dlerror_str);
188         if(newLibName){
189             delete [] newLibName;
190         }
191         return false;
192     }
193     
194     editSharedLibrary editSL;
195     bool res = editSL.removeBSSfromSharedLibrary(newLibName);   
196     delete [] newLibName;
197     return res;
198 }
199 #endif
200
201 #if defined(cap_save_the_world)
202
203 char* process::dumpPatchedImage(std::string imageFileName){ //ccw 28 oct 2001
204
205         writeBackElf *newElf;
206         addLibrary *addLibraryElf;
207    char *data, *paddedData;
208         unsigned int errFlag=0;
209         char name[50];  
210         pdvector<imageUpdate*> compactedUpdates;
211         pdvector<imageUpdate*> compactedHighmemUpdates;
212         Address guardFlagAddr= trampGuardBase();
213         char *mutatedSharedObjects=0;
214         int mutatedSharedObjectsSize = 0, mutatedSharedObjectsIndex=0;
215         char *directoryName = 0;
216         mapped_object *sh_obj;
217         if(!collectSaveWorldData){
218                 BPatch_reportError(BPatchSerious,122,"dumpPatchedImage: BPatch_thread::enableDumpPatchedImage() not called.  No mutated binary saved\n");
219                 return NULL;
220         }
221
222
223         directoryName = saveWorldFindDirectory();
224
225         if(!directoryName){
226                 return NULL;
227         }
228         strcat(directoryName, "/");
229
230         unsigned int dl_debug_statePltEntry = 0x00016574;//a pretty good guess
231         unsigned int dyninst_SharedLibrariesSize = 0, mutatedSharedObjectsNumb;
232
233         newElf = new writeBackElf(mapped_objects[0]->fullName().c_str(),
234                 "/tmp/dyninstMutatee",errFlag);
235         newElf->registerProcess(this);
236         //add section that has, as its address, the original load address of
237         //libdyninstAPI_RT.so.  The RT lib will check to see that it is loaded
238         //in the correct place when the mutated binary is run.
239
240         Address rtlibAddr;
241         for(unsigned int i=0; i < mapped_objects.size() ; i++) {
242             sh_obj = mapped_objects[i];
243             if( strstr(sh_obj->fileName().c_str(),"libdyninstAPI_RT") ) {
244                 rtlibAddr = sh_obj->codeBase();
245             }
246         }
247
248         /*fprintf(stderr,"SAVING RTLIB ADDR: %x\n",rtlibAddr);*/
249         newElf->addSection(0,&rtlibAddr,sizeof(Address),"rtlib_addr",false);
250 /*
251         //save the RT lib to the new directory using dldump in the RT lib.
252         if(!dldumpSharedLibrary(dyninstRT_name, directoryName)){
253                 char *msg;
254                 msg = new char[dyninstRT_name.length() + 512];
255                 sprintf(msg,"dumpPatchedImage: libdyninstAPR_RT.so.1 not saved to %s.\nTry to use %s with the mutated binary.\n",directoryName,dyninstRT_name.c_str());
256
257                 BPatch_reportError(BPatchWarning,0,msg);
258                 delete [] msg;
259         }
260 */
261
262         // DLDUMP every shared lib marked dirty or dirtycalled to the new directory:
263         //      remove .bss section
264         //      change filesz of Datasegment in PHT
265         //      ehdr needs start of section headers updated
266         // Always save the API_RT lib
267         // Libraries: start at index 1
268         for(unsigned i=1; i < mapped_objects.size() ; i++) {
269             sh_obj = mapped_objects[i];
270             if( sh_obj->isDirty() || sh_obj->isDirtyCalled() || strstr(sh_obj->fileName().c_str(),"libdyninstAPI_RT")){
271                 /*fprintf(stderr,"\nWRITE BACK SHARED OBJ %s\n", sh_obj->getName().c_str());*/
272                 
273                 if(!dldumpSharedLibrary(sh_obj->fileName().c_str(),directoryName)){
274                     char *msg;
275                     msg = new char[sh_obj->fileName().length() + strlen(directoryName)+128];
276                     sprintf(msg,"dumpPatchedImage: %s not saved to %s.\n.\nTry to use the original shared library with the mutated binary.\n",sh_obj->fileName().c_str(),directoryName);
277                     
278                     BPatch_reportError(BPatchWarning,0,msg);
279                     delete [] msg;
280                 }
281             }
282             
283         }
284         
285         dl_debug_statePltEntry = saveWorldSaveSharedLibs(mutatedSharedObjectsSize, 
286                                                          dyninst_SharedLibrariesSize,
287                                                          directoryName, 
288                                                          mutatedSharedObjectsNumb);
289         
290         
291         
292         // for each mutated shared object
293         //      read the .text section from the new file, copy over the instrumentation code, 
294         //      this allows subtest 6 to pass)
295         //      add dyninst specific sections
296         if(mutatedSharedObjectsSize){
297
298                 //UPDATED: 24 jul 2003 to include flag.
299                 //the flag denotes whether the shared lib is Dirty (1) or only DirtyCalled (0)
300                 // This is going to be a section that looks like this:
301                 // string
302                 // addr
303                 // flag
304                 // ...
305                 // string
306                 // addr
307                 // flag
308                 
309                 mutatedSharedObjectsSize += mutatedSharedObjectsNumb * sizeof(unsigned int);
310                 mutatedSharedObjects = new char[mutatedSharedObjectsSize ];
311                 // 1: shared library start (a.out is 0)
312                 for(unsigned i=1; i<mapped_objects.size() ; i++) {
313                     sh_obj = mapped_objects[i];
314                     //i ignore the dyninst RT lib here and in process::saveWorldSaveSharedLibs
315                     if(sh_obj->isDirty() || sh_obj->isDirtyCalled()&& NULL==strstr(sh_obj->fileName().c_str(),"libdyninstAPI_RT")){ //ccw 24 jul 2003
316                         memcpy(  & ( mutatedSharedObjects[mutatedSharedObjectsIndex]),
317                                  sh_obj->fileName().c_str(),
318                                  strlen(sh_obj->fileName().c_str())+1);
319                         mutatedSharedObjectsIndex += strlen(
320                                                             sh_obj->fileName().c_str())+1;
321                         unsigned int baseAddr = sh_obj->getBaseAddress();
322                         memcpy( & (mutatedSharedObjects[mutatedSharedObjectsIndex]),
323                                 &baseAddr, sizeof(unsigned int));
324                         mutatedSharedObjectsIndex += sizeof(unsigned int);      
325                         
326                         //set flag
327                         unsigned int tmpFlag = ((sh_obj->isDirty()
328                                                  &&  NULL==strstr(sh_obj->fileName().c_str(),"libc")) ?1:0);    
329                         memcpy( &(mutatedSharedObjects[mutatedSharedObjectsIndex]), &tmpFlag, sizeof(unsigned int));
330                         mutatedSharedObjectsIndex += sizeof(unsigned int);      
331                         
332                     }
333                 }       
334         }
335         char *dyninst_SharedLibrariesData = saveWorldCreateSharedLibrariesSection(dyninst_SharedLibrariesSize);
336         
337         /*newElf = new writeBackElf(( char*) getImage()->file().c_str(),
338           "/tmp/dyninstMutatee",errFlag);
339           newElf->registerProcess(this);*/
340         
341         imageUpdates.sort(imageUpdateSort);// imageUpdate::mysort ); 
342
343         newElf->compactLoadableSections(imageUpdates,compactedUpdates);
344
345         highmemUpdates.sort(imageUpdateSort);
346
347         newElf->compactSections(highmemUpdates, compactedHighmemUpdates);
348
349         newElf->alignHighMem(compactedHighmemUpdates);
350
351         int sectionsAdded = 0;
352         unsigned int newSize, nextPage, paddedDiff;
353         unsigned int pageSize = getpagesize();
354
355
356         //This adds the LOADABLE HEAP TRAMP sections
357         //if new platforms require this it will be moved
358         //to process.C proper. Right now, only solaris uses it
359         for(unsigned int i=0;i<compactedUpdates.size();i++) {
360                 data = new char[compactedUpdates[i]->size];
361                 readDataSpace((void*) compactedUpdates[i]->address, 
362                                                   compactedUpdates[i]->size, data, true);
363
364                 //the TrampGuardFlag must be set to 1 to get the
365                 //tramps to run. it is not necessary set to 1 yet so
366                 //we set it to 1 before we save the file.
367                 if(guardFlagAddr){
368                         if(compactedUpdates[i]->address < guardFlagAddr &&
369                         guardFlagAddr < compactedUpdates[i]->address+compactedUpdates[i]->size){
370                                 data[guardFlagAddr -
371                                         compactedUpdates[i]->address ] = 0x1;
372                         }
373                 }
374
375                 sprintf(name,"dyninstAPI_%08x",sectionsAdded);
376
377                 // what i want to do is this: 
378                 // I want MMAP rather than MEMCPY as much into place 
379                 // as i can. 
380                 // My assumptions:
381                 // there can be any number of heap trampoline sections
382                 // Only the first section could have valid (non heap tramp) data on the
383                 // beginning of its first page. Any subsequent sections will begin on
384                 // a different page than the previous page ends on [by the way 
385                 // compactLoadableSections works] and the heap has been moved
386                 // beyond the last heap tramp section so the mutatee cannot
387                 // put data there.
388                 // 
389                 // for the first section, i=0, make
390                 // two sections, where the first one is everything up to the first
391                 // page break, which will be memcpy'ed to memory
392                 // the second and subsequent sections will be aligned to be
393                 // mmaped ..... which means some sections will get bigger.
394                 
395                 if( i == 0 ){
396                         /* create memcpy section */
397                         nextPage = compactedUpdates[i]->address - (compactedUpdates[i]->address%pageSize);
398                         nextPage +=pageSize;
399                         newSize = nextPage - compactedUpdates[i]->address;      
400
401                         if( newSize > compactedUpdates[i]->size ){
402                                 /* INSURE FIX CCW */
403                                 /*      changing newSize will cause us to read beyond the buffer data in addSection
404                                         we should really realloc data to be of size newSize
405                                 */
406                                 char *tmpData = new char[newSize];
407                                 memcpy(tmpData,data,compactedUpdates[i]->size);
408                                 delete [] data; //ccw 21 apr 2006 INSURE
409                                 data = tmpData;
410                                 /* end realloc */
411                         }
412                         newElf->addSection(compactedUpdates[i]->address,data ,newSize,name);
413                         sectionsAdded ++;
414
415                         if(compactedUpdates[i]->size > newSize){
416                                 /* only create this section if the size of the update
417                                         spans beyond the first memcpy section*/ 
418                                 /* create mmap section */
419                                 sprintf(name,"dyninstAPI_%08x",sectionsAdded);
420                                 newElf->addSection(nextPage, &(((char*) data)[newSize]) ,
421                                         compactedUpdates[i]->size- newSize,name);
422                                 sectionsAdded ++;
423                         }
424                 }else{
425                         /* create section padded out backwards to a page boundry */
426                         paddedDiff = (compactedUpdates[i]->address%pageSize);
427                         paddedData = new char[paddedDiff + compactedUpdates[i]->size];
428                         memset(paddedData, '\0', paddedDiff + compactedUpdates[i]->size); //necessary?
429                         memcpy(&( ((char*) paddedData)[paddedDiff]), data, compactedUpdates[i]->size);
430
431                         newElf->addSection(compactedUpdates[i]->address-paddedDiff, paddedData,
432                                 paddedDiff + compactedUpdates[i]->size, name);
433                         delete [] (char*) paddedData;
434                                 
435                 }
436                 delete [] (char*) data;
437         }
438
439         saveWorldCreateHighMemSections(compactedHighmemUpdates, highmemUpdates, (void*) newElf);
440
441         if(mutatedSharedObjectsSize){
442                 newElf->addSection(0, mutatedSharedObjects, mutatedSharedObjectsSize,
443                                                                  "dyninstAPI_mutatedSO", false);
444         }
445
446         unsigned int k;
447         
448         for( k=0;k<imageUpdates.size();k++){
449                 delete imageUpdates[k];
450         }
451
452         for( k=0;k<highmemUpdates.size();k++){
453                 delete highmemUpdates[k];
454         }
455         for(  k=0;k<compactedUpdates.size();k++){
456                 delete compactedUpdates[k];
457         }
458
459         for(  k=0;k<compactedHighmemUpdates.size();k++){
460                 delete compactedHighmemUpdates[k];
461         }
462
463         //the following is for the dlopen problem 
464         newElf->addSection(dl_debug_statePltEntry, dyninst_SharedLibrariesData, 
465         dyninst_SharedLibrariesSize, "dyninstAPI_SharedLibraries", false);
466
467         delete [] dyninst_SharedLibrariesData;
468
469
470         //the following reloads any shared libraries loaded into the
471         //mutatee using BPatch_thread::loadLibrary
472         saveWorldAddSharedLibs((void*)newElf); // ccw 14 may 2002 
473
474         saveWorldCreateDataSections((void*)newElf);
475 /*
476         //add section that has, as its address, the original load address of
477         //libdyninstAPI_RT.so.  The RT lib will check to see that it is loaded
478         //in the correct place when the mutated binary is run.
479
480         Address rtlibAddr;
481         for(int i=0;mapped_objects && i<(int)mapped_objects->size() ; i++) {
482                 sh_obj = mapped_objects[i];
483                 if( strstr(sh_obj->fileName().c_str(),"libdyninstAPI_RT") ) {
484                         rtlibAddr = sh_obj->getBaseAddress();
485                 }
486         }
487 */
488         /*fprintf(stderr,"SAVING RTLIB ADDR: %x\n",rtlibAddr);*/
489 //      newElf->addSection(0,&rtlibAddr,sizeof(Address),"rtlib_addr",false);
490
491         newElf->createElf();
492         char* fullName = new char[strlen(directoryName) + strlen ( imageFileName.c_str())+1];
493         strcpy(fullName, directoryName);
494         strcat(fullName, imageFileName.c_str());
495         
496         addLibraryElf = new addLibrary();
497         elf_update(newElf->getElf(), ELF_C_WRITE);
498         if(!addLibraryElf->driver(newElf->getElf(), fullName, "libdyninstAPI_RT.so.1")) {
499                 //ccw 27 jun 2003
500                 BPatch_reportError(BPatchSerious,122,"dumpPatchedImage: addLibraryElf() failed!  No mutated binary saved\n");
501                 delete [] directoryName;
502                 return NULL;
503
504         }
505         delete [] fullName;
506         if(mutatedSharedObjects){
507                 delete [] mutatedSharedObjects;
508         }
509         delete addLibraryElf; //INSURE CCW 
510         delete newElf; // INSURE CCW
511         return directoryName;
512 }
513 #endif
514
515 bool process::dumpImage(std::string imageFileName) 
516 {
517     int newFd;
518     string command;
519
520     string origFile = getAOut()->fileName();
521    
522     // first copy the entire image file
523     command = "cp ";
524     command += origFile;
525     command += " ";
526     command += imageFileName.c_str();
527     system(command.c_str());
528
529     // now open the copy
530     newFd = open(imageFileName.c_str(), O_RDWR, 0);
531     if (newFd < 0) {
532         // log error
533         return false;
534     }
535
536     Elf_X elf(newFd, ELF_C_READ);
537     if (!elf.isValid()) return false;
538
539     Elf_X_Shdr shstrscn = elf.get_shdr( elf.e_shstrndx() );
540     Elf_X_Data shstrdata = shstrscn.get_data();
541     const char* shnames = (const char *) shstrdata.get_string();
542
543     Address baseAddr = 0;
544     int length = 0;
545     int offset = 0;
546     for (int i = 0; i < elf.e_shnum(); ++i) {
547         Elf_X_Shdr shdr = elf.get_shdr(i);
548         const char *name = (const char *) &shnames[shdr.sh_name()];
549
550         if (!P_strcmp(name, ".text")) {
551             offset = shdr.sh_offset();
552             length = shdr.sh_size();
553             baseAddr = shdr.sh_addr();
554             break;
555         }
556     }
557
558     char *tempCode = new char[length];
559     bool ret = readTextSpace((void *) baseAddr, length, tempCode);
560     if (!ret) {
561         // log error
562
563         delete[] tempCode;
564         elf.end();
565         P_close(newFd);
566
567         return false;
568     }
569
570     lseek(newFd, offset, SEEK_SET);
571     write(newFd, tempCode, length);
572
573     // Cleanup
574     delete[] tempCode;
575     elf.end();
576     P_close(newFd);
577
578     return true;
579 }
580
581 /* Auxiliary function */
582 bool checkAllThreadsForBreakpoint(process *proc, Address break_addr)
583 {
584    pdvector<Frame> activeFrames;
585    if (!proc->getAllActiveFrames(activeFrames)) {
586       fprintf(stderr, "%s[%d]:  getAllActiveFrames failed\n", FILE__, __LINE__);
587       return false;
588    }
589    for(unsigned frame_iter = 0; frame_iter < activeFrames.size(); frame_iter++)
590    {
591       if (activeFrames[frame_iter].getPC() == break_addr) {
592          return true;
593       }
594    }
595    
596    return false;
597 }
598
599 bool process::trapAtEntryPointOfMain(dyn_lwp *, Address)
600 {
601     if (main_brk_addr == 0x0) return false;
602     return checkAllThreadsForBreakpoint(this, main_brk_addr);
603 }
604
605 bool process::handleTrapAtEntryPointOfMain(dyn_lwp *)
606 {
607     assert(main_brk_addr);
608     
609   // restore original instruction 
610     writeDataSpace((void *)main_brk_addr, sizeof(savedCodeBuffer), 
611                    (char *)savedCodeBuffer);
612     main_brk_addr = 0;
613     return true;
614 }
615
616 bool process::insertTrapAtEntryPointOfMain()
617 {
618
619     int_function *f_main = 0;
620     pdvector<int_function *> funcs;
621     
622     //first check a.out for function symbol   
623     bool res = findFuncsByPretty("main", funcs);
624     if (!res)
625     {
626         logLine( "a.out has no main function. checking for PLT entry\n" );
627         //we have not found a "main" check if we have a plt entry
628         res = findFuncsByPretty( "DYNINST_pltMain", funcs );
629  
630         if (!res) {
631             logLine( "no PLT entry for main found\n" );
632             return false;
633           }       
634     }
635     
636     if( funcs.size() > 1 ) {
637         cerr << __FILE__ << __LINE__ 
638              << ": found more than one main! using the first" << endl;
639     }
640     f_main = funcs[0];
641     assert(f_main);
642
643     Address addr = f_main->getAddress(); 
644
645     codeGen gen(instruction::size());
646     instruction::generateTrap(gen);
647
648     // save original instruction first
649     readDataSpace((void *)addr, sizeof(savedCodeBuffer), savedCodeBuffer, true);
650     
651     writeDataSpace((void *)addr, gen.used(), gen.start_ptr());
652
653     main_brk_addr = addr;
654     
655     return true;
656 }
657
658 bool process::handleTrapAtLibcStartMain(dyn_lwp *)  { assert(0); return false; }
659 bool process::instrumentLibcStartMain() { assert(0); return false; }
660 bool process::decodeStartupSysCalls(EventRecord &) { assert(0); return false; }
661 void process::setTraceSysCalls(bool) { assert(0); }
662 void process::setTraceState(traceState_t) { assert(0); }
663 bool process::getSysCallParameters(dyn_saved_regs *, long *, int) { assert(0); return false; }
664 int process::getSysCallNumber(dyn_saved_regs *) { assert(0); return 0; }
665 long process::getSysCallReturnValue(dyn_saved_regs *) { assert(0); return 0; }
666 Address process::getSysCallProgramCounter(dyn_saved_regs *) { assert(0); return 0; }
667 bool process::isMmapSysCall(int) { assert(0); return false; }
668 Offset process::getMmapLength(int, dyn_saved_regs *) { assert(0); return 0;}
669 Address process::getLibcStartMainParam(dyn_lwp *) { assert(0); return 0;}
670
671 bool AddressSpace::getDyninstRTLibName() {
672    if (dyninstRT_name.length() == 0) {
673       // Get env variable
674       if (getenv("DYNINSTAPI_RT_LIB") != NULL) {
675          dyninstRT_name = getenv("DYNINSTAPI_RT_LIB");
676       }
677       else {
678          std::string msg = std::string("Environment variable ") +
679                         std::string("DYNINSTAPI_RT_LIB") +
680                         std::string(" has not been defined.");
681          showErrorCallback(101, msg);
682          return false;
683       }
684    }
685    // Check to see if the library given exists.
686    if (access(dyninstRT_name.c_str(), R_OK)) {
687       std::string msg = std::string("Runtime library ") + dyninstRT_name +
688                      std::string(" does not exist or cannot be accessed!");
689       showErrorCallback(101, msg);
690       return false;
691    }
692    return true;
693 }
694
695 bool process::loadDYNINSTlib() {
696     // we will write the following into a buffer and copy it into the
697     // application process's address space
698     // [....LIBRARY's NAME...|code for DLOPEN]
699     
700     // write to the application at codeOffset. This won't work if we
701     // attach to a running process.
702     //Address codeBase = this->getImage()->codeOffset();
703     // ...let's try "_start" instead
704     int_function *_startfn;
705     
706     pdvector<int_function *> funcs;
707     bool res = findFuncsByPretty("_start", funcs);
708     if (!res) {
709         // we can't instrument main - naim
710         showErrorCallback(108,"_start() unfound");
711         return false;
712     }
713
714     if( funcs.size() > 1 ) {
715         cerr << __FILE__ << __LINE__ 
716              << ": found more than one _start! using the first" << endl;
717     }
718     _startfn = funcs[0];
719
720     Address codeBase = _startfn->getAddress();
721     assert(codeBase);
722     
723     // Or should this be readText... it seems like they are identical
724     // the remaining stuff is thanks to Marcelo's ideas - this is what 
725     // he does in NT. The major change here is that we use AST's to 
726     // generate code for dlopen.
727     
728     // savedCodeBuffer[BYTES_TO_SAVE] is declared in process.h
729     readDataSpace((void *)codeBase, sizeof(savedCodeBuffer), savedCodeBuffer, true);
730     
731     codeGen scratchCodeBuffer(BYTES_TO_SAVE);
732     scratchCodeBuffer.setAddrSpace(this);
733     scratchCodeBuffer.setAddr(codeBase);
734     scratchCodeBuffer.setRegisterSpace(registerSpace::savedRegSpace(this));
735
736     // First we write in the dyninst lib string. Vewy simple.
737     Address dyninstlib_addr = codeBase;
738     
739     scratchCodeBuffer.copy(dyninstRT_name.c_str(), dyninstRT_name.length()+1);
740
741     // Were we're calling into
742     Address dlopencall_addr = codeBase + scratchCodeBuffer.used();
743
744     /*
745       fprintf(stderr, "dlopen call addr at 0x%x, for codeBase of 0x%x\n",
746             dlopencall_addr, codeBase);
747     */
748
749
750     pdvector<AstNodePtr> dlopenAstArgs(2);
751     AstNodePtr dlopenAst;
752     
753     // We call directly into ld.so.1. This used to be handled in 
754     // process::findInternalSymbols, which made it very difficult
755     // to figure out what was going on.
756     Address dlopen_func_addr = dyn->get_dlopen_addr();
757     assert(dlopen_func_addr);
758
759     //fprintf(stderr, "We want to call 0x%x\n", dlopen_func_addr);
760     // See if we can get a function for it.
761
762     dlopenAstArgs[0] = AstNode::operandNode(AstNode::Constant, (void *)(dyninstlib_addr));
763     dlopenAstArgs[1] = AstNode::operandNode(AstNode::Constant, (void*)DLOPEN_MODE);
764     dlopenAst = AstNode::funcCallNode(dlopen_func_addr, dlopenAstArgs);
765
766     dlopenAst->generateCode(scratchCodeBuffer,
767                             true);
768
769     // Slap in a breakpoint
770     dyninstlib_brk_addr = codeBase + scratchCodeBuffer.used();
771     instruction::generateTrap(scratchCodeBuffer);
772     
773     writeDataSpace((void *)codeBase, scratchCodeBuffer.used(), 
774                    scratchCodeBuffer.start_ptr());
775     
776     //fprintf(stderr, "Breakpoint at 0x%x\n", dyninstlib_brk_addr);
777     
778     // save registers
779     savedRegs = new dyn_saved_regs;
780     bool status = getRepresentativeLWP()->getRegisters(savedRegs);
781     assert(status == true);
782     
783     if (!getRepresentativeLWP()->changePC(dlopencall_addr, NULL)) {
784         logLine("WARNING: changePC failed in loadDYNINSTlib\n");
785         assert(0);
786     }
787     setBootstrapState(loadingRT_bs);
788     return true;
789 }
790
791 bool process::trapDueToDyninstLib(dyn_lwp *)
792 {
793   if (dyninstlib_brk_addr == 0) return(false);
794   return checkAllThreadsForBreakpoint(this, dyninstlib_brk_addr);
795 }
796
797 bool process::loadDYNINSTlibCleanup(dyn_lwp *)
798 {
799   // rewrite original instructions in the text segment we use for 
800   // the inferiorRPC - naim
801   unsigned count = sizeof(savedCodeBuffer);
802   //Address codeBase = getImage()->codeOffset();
803
804   int_function *_startfn;
805
806     pdvector<int_function *> funcs;
807     bool res = findFuncsByPretty("_start", funcs);
808     if (!res) {
809         // we can't instrument main - naim
810         showErrorCallback(108,"_start() unfound");
811         return false;
812     }
813
814     if( funcs.size() > 1 ) {
815         cerr << __FILE__ << __LINE__ 
816              << ": found more than one main! using the first" << endl;
817     }
818     _startfn = funcs[0];
819
820     Address codeBase = _startfn->getAddress();
821     assert(codeBase);
822     if (!writeDataSpace((void *)codeBase, count, (char *)savedCodeBuffer))
823         return false;
824
825     // restore registers
826     if (!getRepresentativeLWP()->restoreRegisters(*savedRegs))
827      return false;
828     delete savedRegs;
829     savedRegs = NULL;
830     return true;
831 }
832
833 bool SignalGeneratorCommon::getExecFileDescriptor(std::string filename,
834                                     int /*pid*/,
835                                     bool /*whocares*/,
836                                     int &,
837                                     fileDescriptor &desc)
838 {
839     desc = fileDescriptor(filename.c_str(), 0, 0, false);
840     return true;
841 }
842
843 #if defined(cap_dynamic_heap)
844 static const Address lowest_addr = 0x0;
845 void process::inferiorMallocConstraints(Address near, Address &lo, Address &hi,
846                                         inferiorHeapType /* type */)
847 {
848   if (near)
849     {
850       lo = region_lo(near);
851       hi = region_hi(near);  
852     }
853 }
854 #endif
855
856 bool process::dumpCore_(const std::string coreName) 
857 {
858   char command[100];
859
860   sprintf(command, "gcore %d 2> /dev/null; mv core.%d %s", getPid(), getPid(), 
861           coreName.c_str());
862
863   detach(false);
864   system(command);
865   attach();
866
867   return false;
868 }
869
870 Frame Frame::getCallerFrame()
871 {
872   Address newPC=0;
873   Address newFP=0;
874   Address newSP=0;
875
876   //fprintf(stderr, "Frame::getCallerFrame for %p\n", this);
877
878   if (uppermost_) {
879     codeRange *range = getRange();
880     int_function *func = range->is_function();
881     if (func) {
882         struct dyn_saved_regs regs;
883         bool status;
884         if (lwp_)
885           status = lwp_->getRegisters(&regs);
886         else
887           status = getProc()->getRepresentativeLWP()->getRegisters(&regs);
888
889         assert(status == true);
890       if (func->hasNoStackFrame()) { // formerly "isLeafFunc()"
891         newPC = regs.theIntRegs[R_O7] + 8;
892         newFP = fp_; // frame pointer unchanged
893       } else {
894         newPC = regs.theIntRegs[R_O7] + 8;
895         if (!getProc()->readDataSpace((caddr_t)(fp_ + 56), sizeof(int), (caddr_t)&newFP, true))
896            return Frame();
897       }
898         return Frame(newPC, newFP, newSP, 0, this);
899     }
900   }
901   //
902   // For the sparc, register %i7 is the return address - 8 and the fp is
903   // register %i6. These registers can be located in %fp+14*5 and
904   // %fp+14*4 respectively, but to avoid two calls to readDataSpace,
905   // we bring both together (i.e. 8 bytes of memory starting at %fp+14*4
906   // or %fp+56).
907   // These values are copied to the stack when the application is paused,
908   // so we are assuming that the application is paused at this point
909   
910   struct {
911     Address fp;
912     Address rtn;
913   } addrs;
914   
915   if (getProc()->readDataSpace((caddr_t)(fp_ + 56), 2*sizeof(int),
916                                (caddr_t)&addrs, true))
917     {
918
919       newFP = addrs.fp;
920       newPC = addrs.rtn + 8;
921
922       if (isSignalFrame()) {
923          // get the value of the saved PC: this value is stored in the
924          // address specified by the value in register i2 + 44. Register i2
925          // must contain the address of some struct that contains, among
926          // other things, the saved PC value.
927          u_int reg_i2;
928          if (getProc()->readDataSpace((caddr_t)(fp_+40), sizeof(u_int),
929                               (caddr_t)&reg_i2,true)) {
930             Address saved_pc;
931             if (getProc()->readDataSpace((caddr_t) (reg_i2+44), sizeof(int),
932                                  (caddr_t) &saved_pc,true)) {
933                
934                int_function *func = getProc()->findFuncByAddr(saved_pc);
935                
936                newPC = saved_pc;
937                if (func && func->hasNoStackFrame())
938                   newFP = fp_;
939             }
940          }
941          else {
942            return Frame();
943          }
944       }
945       
946
947       if(getProc()->multithread_capable()) {
948          // MT thread adds another copy of the start function
949          // to the top of the stack... this breaks instrumentation
950          // since we think we're at a function entry.
951          if (newFP == 0) newPC = 0;
952       }
953       Frame ret = Frame(newPC, newFP, 0, 0, this);
954
955       codeRange *range = getRange();
956       // Find our way out of the minitramp, and up to the calling function
957       if (range->is_minitramp()) {
958          instPoint *p = getPoint();
959          if (p->getPointType() != functionEntry &&
960              !p->func()->hasNoStackFrame()) {
961             if (!getProc()->readDataSpace((caddr_t)(newFP + 60), sizeof(int), (caddr_t)&newPC, true))
962                return Frame();
963             if (!getProc()->readDataSpace((caddr_t)(newFP + 56), sizeof(int), (caddr_t)&newFP, true))
964                return Frame();
965             ret = Frame(newPC, newFP, 0, 0, this);
966          }
967       }
968
969       // If we're in a base tramp, skip this frame (return getCallerFrame)
970       // as we only return minitramps
971       if (range->is_multitramp()) {
972           // If we're inside instrumentation only....
973           multiTramp *multi = range->is_multitramp();
974           baseTrampInstance *bti = multi->getBaseTrampInstanceByAddr(getPC());
975           if (bti &&
976               bti->isInInstru(getPC()))
977               return ret.getCallerFrame();
978       }
979       return ret;
980     }
981    return Frame(); // zero frame
982 }
983
984 bool Frame::setPC(Address newpc) {
985   fprintf(stderr, "Implement me! Changing frame PC from %x to %x\n",
986           pc_, newpc);
987   return false;
988 }
989
990
991 void print_read_error_info(const relocationEntry entry, 
992                            int_function *&target_pdf, Address base_addr) {
993
994    sprintf(errorLine, "  entry      : target_addr 0x%lx\n",
995            entry.target_addr());
996    logLine(errorLine);
997    sprintf(errorLine, "               rel_addr 0x%lx\n", entry.rel_addr());
998    logLine(errorLine);
999    sprintf(errorLine, "               name %s\n", (entry.name()).c_str());
1000    logLine(errorLine);
1001    
1002    if (target_pdf) {
1003       sprintf(errorLine, "  target_pdf : symTabName %s\n",
1004               (target_pdf->symTabName()).c_str());
1005       logLine(errorLine);    
1006       sprintf(errorLine , "              prettyName %s\n",
1007               (target_pdf->symTabName()).c_str());
1008       logLine(errorLine);
1009       sprintf(errorLine , "              addr 0x%lx\n",
1010               target_pdf->getAddress());
1011       logLine(errorLine);
1012    }
1013
1014    sprintf(errorLine, "  base_addr  0x%lx\n", base_addr);
1015    logLine(errorLine);
1016 }
1017
1018 // hasBeenBound: returns true if the runtime linker has bound the
1019 // function symbol corresponding to the relocation entry in at the address
1020 // specified by entry and base_addr.  If it has been bound, then the callee 
1021 // function is returned in "target_pdf", else it returns false.
1022 bool process::hasBeenBound(const relocationEntry &entry, 
1023                            int_function *&target_pdf, Address base_addr) {
1024
1025 // TODO: the x86 and sparc versions should really go in seperate files 
1026 #if defined(i386_unknown_solaris2_5)
1027
1028     if (status() == exited) return false;
1029
1030     // if the relocationEntry has not been bound yet, then the value
1031     // at rel_addr is the address of the instruction immediately following
1032     // the first instruction in the PLT entry (which is at the target_addr) 
1033     // The PLT entries are never modified, instead they use an indirrect 
1034     // jump to an address stored in the _GLOBAL_OFFSET_TABLE_.  When the 
1035     // function symbol is bound by the runtime linker, it changes the address
1036     // in the _GLOBAL_OFFSET_TABLE_ corresponding to the PLT entry
1037
1038     Address got_entry = entry.rel_addr() + base_addr;
1039     Address bound_addr = 0;
1040     if(!readDataSpace((const void*)got_entry, sizeof(Address), 
1041                         &bound_addr, true)){
1042         sprintf(errorLine, "read error in process::hasBeenBound "
1043                 "addr 0x%lx, pid=%d\n (readDataSpace returns 0)",
1044                 got_entry, pid);
1045         logLine(errorLine);
1046         print_read_error_info(entry, target_pdf, base_addr);
1047         return false;
1048     }
1049
1050     if( !( bound_addr == (entry.target_addr()+6+base_addr)) ) {
1051         // the callee function has been bound by the runtime linker
1052         // find the function and return it
1053         target_pdf = findFuncByAddr(bound_addr);
1054         if(!target_pdf){
1055             return false;
1056         }
1057         return true;    
1058     }
1059     return false;
1060
1061 #else
1062     // if the relocationEntry has not been bound yet, then the second instr 
1063     // in this PLT entry branches to the fist PLT entry.  If it has been   
1064     // bound, then second two instructions of the PLT entry have been changed 
1065     // by the runtime linker to jump to the address of the function.  
1066     // Here is an example:   
1067     //     before binding                       after binding
1068     //     --------------                       -------------
1069     //     sethi  %hi(0x15000), %g1             sethi  %hi(0x15000), %g1
1070     //     b,a  <_PROCEDURE_LINKAGE_TABLE_>     sethi  %hi(0xef5eb000), %g1
1071     //     nop                                  jmp  %g1 + 0xbc ! 0xef5eb0bc
1072
1073     unsigned int insnBuf;
1074
1075     Address next_insn_addr = entry.target_addr() + base_addr + instruction::size(); 
1076     if( !(readDataSpace((caddr_t)next_insn_addr, instruction::size(), 
1077                         (char *)&insnBuf, true)) ) {
1078         sprintf(errorLine, "read error in process::hasBeenBound addr 0x%lx"
1079                 " (readDataSpace next_insn_addr returned 0)\n",
1080                 next_insn_addr);
1081         logLine(errorLine);
1082         print_read_error_info(entry, target_pdf, base_addr);
1083     }
1084     instruction next_insn(insnBuf);
1085     // if this is a b,a instruction, then the function has not been bound
1086     if(((*next_insn).branch.op == FMT2op)  && ((*next_insn).branch.op2 == BICCop2) 
1087        && ((*next_insn).branch.anneal == 1) && ((*next_insn).branch.cond == BAcond)) {
1088         return false;
1089     } 
1090
1091     // if this is a sethi instruction, then it has been bound...get target_addr
1092     Address third_addr = entry.target_addr() + base_addr + 8; 
1093     if( !(readDataSpace((caddr_t)third_addr, instruction::size(),
1094                        (char *)&insnBuf, true)) ) {
1095         sprintf(errorLine, "read error in process::hasBeenBound addr 0x%lx"
1096                 " (readDataSpace third_addr returned 0)\n",
1097                 third_addr);
1098         logLine(errorLine);
1099         print_read_error_info(entry,target_pdf, base_addr);
1100     }
1101
1102     instruction third_insn(insnBuf);
1103
1104     // get address of bound function, and return the corr. int_function
1105     if(((*next_insn).sethi.op == FMT2op) && ((*next_insn).sethi.op2 == SETHIop2)
1106         && ((*third_insn).rest.op == RESTop) && ((*third_insn).rest.i == 1)
1107         && ((*third_insn).rest.op3 == JMPLop3)) {
1108         
1109         Address new_target = ((*next_insn).sethi.imm22 << 10) & 0xfffffc00; 
1110         new_target |= (*third_insn).resti.simm13;
1111
1112         target_pdf = findFuncByAddr(new_target);
1113         if(!target_pdf){
1114             return false;
1115         }
1116         return true;
1117     }
1118     // this is a messed up entry
1119     return false;
1120 #endif
1121
1122 }
1123
1124
1125
1126 // findCallee: finds the function called by the instruction corresponding
1127 // to the instPoint "instr". If the function call has been bound to an
1128 // address, then the callee function is returned in "target" and the 
1129 // instPoint "callee" data member is set to pt to callee's int_function.  
1130 // If the function has not yet been bound, then "target" is set to the 
1131 // int_function associated with the name of the target function (this is 
1132 // obtained by the PLT and relocation entries in the image), and the instPoint
1133 // callee is not set.  If the callee function cannot be found, (ex. function
1134 // pointers, or other indirect calls), it returns false.
1135 // Returns false on error (ex. process doesn't contain this instPoint).
1136 //
1137 int_function *instPoint::findCallee() {
1138
1139    if(callee_) {
1140        return callee_;
1141    }
1142
1143        if (ipType_ != callSite) {
1144         return NULL;
1145     }
1146
1147     if (isDynamic()) { 
1148         return NULL;
1149     }
1150
1151     // Check if we parsed an intra-module static call
1152     assert(img_p_);
1153     image_func *icallee = img_p_->getCallee();
1154     if (icallee) {
1155         // Now we have to look up our specialized version
1156         // Can't do module lookup because of DEFAULT_MODULE...
1157         const pdvector<int_function *> *possibles = func()->obj()->findFuncVectorByMangled(icallee->symTabName().c_str());
1158         if (!possibles) {
1159             return NULL;
1160         }
1161         for (unsigned i = 0; i < possibles->size(); i++) {
1162           if ((*possibles)[i]->ifunc() == icallee) {
1163                 callee_ = (*possibles)[i];
1164                 return callee_;
1165             }
1166         }
1167         // No match... very odd
1168         assert(0);
1169         return NULL;
1170     }
1171
1172     
1173     // get the target address of this function
1174     Address target_addr = img_p_->callTarget();
1175     //    Address insn_addr = instr.pointAddr(); 
1176     
1177     if(!target_addr) {  
1178         // this is either not a call instruction or an indirect call instr
1179         // that we can't get the target address
1180         return NULL;
1181     }
1182     
1183     
1184     // else, get the relocation information for this image
1185     Symtab *obj = func()->obj()->parse_img()->getObject();
1186     vector<relocationEntry> fbtvector;
1187     if(!obj->getFuncBindingTable(fbtvector))
1188         return false;   // target cannot be found...it is an indirect call.
1189     pdvector<relocationEntry> *fbt = new pdvector<relocationEntry>;
1190     for(unsigned index=0;index<fbtvector.size();index++)
1191         fbt->push_back(fbtvector[index]);
1192     
1193     // find the target address in the list of relocationEntries
1194     Address base_addr = func()->obj()->codeBase();
1195     for(u_int i=0; i < fbt->size(); i++) {
1196         if((*fbt)[i].target_addr() == target_addr) {
1197             // check to see if this function has been bound yet...if the
1198             // PLT entry for this function has been modified by the runtime
1199             // linker
1200             int_function *target_pdf = 0;
1201             if(proc()->hasBeenBound((*fbt)[i], target_pdf, base_addr)) {
1202                 callee_ = target_pdf;
1203                 return callee_;
1204             } 
1205             else {
1206                 // just try to find a function with the same name as entry 
1207                 pdvector<int_function *> pdfv;
1208                 bool found = proc()->findFuncsByMangled((*fbt)[i].name().c_str(), pdfv);
1209                 if(found) {
1210                     assert(pdfv.size());
1211                     if(pdfv.size() > 1)
1212                         cerr << __FILE__ << ":" << __LINE__ 
1213                              << ": WARNING:  findAllFuncsByName found " 
1214                              << pdfv.size() << " references to function " 
1215                              << (*fbt)[i].name() << ".  Using the first.\n";
1216                     callee_ = pdfv[0];
1217                     return callee_;
1218                 }
1219             }
1220             return NULL;
1221         }
1222     }
1223     return NULL;
1224 }
1225
1226 // vim:ts=5:
1227
1228 /**
1229  * Searches for function in order, with preference given first 
1230  * to libpthread, then to libc, then to the process.
1231  **/
1232 static void findThreadFuncs(process *p, std::string func, 
1233                             pdvector<int_function *> &result)
1234 {
1235    bool found = false;
1236    mapped_module *lpthread = p->findModule("libthread*", true);
1237    if (lpthread)
1238       found = lpthread->findFuncVectorByPretty(func, result);
1239    if (found) {
1240       return;
1241    }
1242    /*
1243     * Do not look in libc... there are matches, but they're singlethread versions
1244
1245     mapped_module *lc = p->findModule("libc.so*", true);
1246     if (lc)
1247     found = lc->findFuncVectorByPretty(func, result);
1248     if (found) {
1249     fprintf(stderr, "found in libc.so\n");
1250     return;
1251     }
1252    */
1253
1254    p->findFuncsByPretty(func, result);
1255 }
1256
1257 bool process::initMT()
1258 {
1259     unsigned i;
1260     bool res;
1261     
1262 #if !defined(cap_threads)
1263     return true;
1264 #endif
1265
1266     /**
1267      * Instrument thread_create with calls to DYNINST_dummy_create
1268      **/
1269     pdvector<int_function *> thread_init_funcs;
1270     findThreadFuncs(this, "init_func", thread_init_funcs);
1271     if (thread_init_funcs.size() < 1) {
1272         //findThreadFuncs(this, "_lwp_start", thread_init_funcs);
1273         findThreadFuncs(this, "_thr_setup", thread_init_funcs);
1274         if (thread_init_funcs.size() < 1) {
1275           findThreadFuncs(this, "_thread_start", thread_init_funcs);
1276           if (thread_init_funcs.size() < 1) {
1277             fprintf(stderr, "%s[%d]: no copies of thread start function, expected 1\n",
1278                     FILE__, __LINE__);
1279
1280             return false;
1281           }
1282         }
1283     }
1284
1285     //Find DYNINST_dummy_create
1286    int_function *dummy_create = findOnlyOneFunction("DYNINST_dummy_create");
1287    if (!dummy_create) {
1288        fprintf(stderr, "[%s:%d] - Couldn't find DYNINST_dummy_create",
1289                __FILE__, __LINE__);
1290        return false;
1291    }
1292    //Instrument
1293    for (i=0; i<thread_init_funcs.size(); i++)
1294    {
1295       pdvector<AstNodePtr> args;
1296       AstNodePtr call_dummy_create = AstNode::funcCallNode(dummy_create, args);
1297       const pdvector<instPoint *> &ips = thread_init_funcs[i]->funcEntries();
1298       for (unsigned j=0; j<ips.size(); j++)
1299       {
1300          miniTramp *mt;
1301          mt = ips[j]->instrument(call_dummy_create, callPreInsn, orderFirstAtPoint, false, 
1302                                  false);
1303          if (!mt)
1304          {
1305             fprintf(stderr, "[%s:%d] - Couldn't instrument thread_create\n",
1306                     __FILE__, __LINE__);
1307          }
1308          //TODO: Save the mt objects for detach
1309       }
1310    }
1311    
1312    /**
1313     * Have dyn_pthread_self call the actual pthread_self
1314     **/
1315    //Find dyn_pthread_self
1316    pdvector<int_variable *> ptself_syms;
1317    res = findVarsByAll("DYNINST_pthread_self", ptself_syms);
1318    if (!res) {
1319        fprintf(stderr, "[%s:%d] - Couldn't find any dyn_pthread_self, expected 1\n",
1320                __FILE__, __LINE__);
1321    }
1322    assert(ptself_syms.size() == 1);
1323    Address dyn_pthread_self = ptself_syms[0]->getAddress();
1324
1325
1326    //Find pthread_self
1327    pdvector<int_function *> pthread_self_funcs;
1328    findThreadFuncs(this, "thr_self", pthread_self_funcs);   
1329    if (pthread_self_funcs.size() != 1) {
1330        fprintf(stderr, "[%s:%d] - Found %d pthread_self functions, expected 1\n",
1331                __FILE__, __LINE__, pthread_self_funcs.size());
1332        for (unsigned j=0; j<pthread_self_funcs.size(); j++) {
1333            int_function *ps = pthread_self_funcs[j];
1334            fprintf(stderr, "[%s:%u] - %s in module %s at %lx\n", __FILE__, __LINE__,
1335                    ps->prettyName().c_str(), ps->mod()->fullName().c_str(), 
1336                    ps->getAddress());
1337        }
1338        return false;
1339    }   
1340    //Replace
1341    res = writeFunctionPtr(this, dyn_pthread_self, pthread_self_funcs[0]);
1342    if (!res) {
1343        fprintf(stderr, "[%s:%d] - Couldn't update dyn_pthread_self\n",
1344                __FILE__, __LINE__);
1345        return false;
1346    }
1347    return true;
1348 }
1349
1350 #include <sched.h>
1351 void dyninst_yield()
1352 {
1353    sched_yield();
1354 }
1355
1356 bool SignalHandler::handleProcessExitPlat(EventRecord & /*ev*/, bool &) 
1357 {
1358     return true;
1359 }
1360
1361 bool process::hasPassedMain() 
1362 {
1363    return true;
1364 }