Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / linuxDL.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 #include "dyninstAPI/src/mapped_object.h"
33 #include "dyninstAPI/src/dynamiclinking.h"
34 #include "dyninstAPI/src/process.h"
35 #include "dyninstAPI/src/dyn_lwp.h"
36 #include "dyninstAPI/src/symtab.h"
37 #include "common/h/debugOstream.h"
38 #include "dyninstAPI/src/dyn_thread.h"
39
40 #include <link.h>
41 #include <libelf.h>
42 #include <sys/types.h>
43 #include <sys/procfs.h>
44 #include <sys/ioctl.h>
45 #include <dirent.h>
46 #include <sys/stat.h>
47
48
49 // ---------------------------------------------------------------
50 // The link_map and r_debug structures from <link.h> decide their
51 // size at runtime.  This makes it impossible for a 64-bit mutator
52 // to use these structures for a 32-bit mutatee.
53 // 
54 // So we must provide our own 32-bit equivalent.  If the link_map
55 // or r_debug from <link.h> ever change, so must our structures
56 // below.
57 // 
58 // struct link_map and r_debug: provided by <link.h>
59 // struct link_map_dyn32 and r_debug_dyn32: Forced 32-bit versions
60 // class  link_map_x and r_debug_x: Size independant class.
61 //
62 // These definitions should probably be moved to an h file.
63
64 struct link_map_dyn32
65 {
66    /* These first few members are part of the protocol with the debugger.
67       This is the same format used in SVR4.  */
68
69    Elf32_Addr l_addr;          /* Base address shared object is loaded at.  */
70
71    //char *l_name;               /* Absolute file name object was found in.  */
72    uint32_t l_name;
73
74    //Elf32_Dyn *l_ld;            /* Dynamic section of the shared object.  */
75    uint32_t l_ld;
76
77    //struct link_map_32 *l_next, *l_prev; /* Chain of loaded objects.  */
78    uint32_t l_next, l_prev;
79 };
80
81 class link_map_x {
82 public:
83    link_map_x(process *proc_) : proc(proc_), loaded_name(false) {}
84    virtual ~link_map_x() {}
85    virtual size_t size() = 0;
86    virtual uint64_t l_addr() = 0;
87    virtual char *l_name() = 0;
88    virtual uint64_t l_ld() = 0;
89    virtual bool is_last() = 0;
90    virtual bool load_next() = 0;
91
92    bool is_valid() { return valid; }
93
94 protected:
95    process *proc;
96    char link_name[256];
97    bool loaded_name;
98    bool valid;
99 };
100
101 class link_map_32 : public link_map_x {
102 public:
103    link_map_32(process *proc_, void *addr_)
104       : link_map_x(proc_) { 
105       valid = load_link(addr_); 
106    }
107
108    size_t size() { 
109       return sizeof(link_elm); 
110    }
111
112    uint64_t l_addr() { 
113       return link_elm.l_addr; 
114    }
115    
116    char *l_name() {
117       if (loaded_name) return link_name;
118       
119       for (unsigned int i = 0; i < sizeof(link_name); ++i) {
120          if (!proc->readDataSpace((caddr_t)((Address)link_elm.l_name + i),
121                                   sizeof(char), (caddr_t)(link_name + i), true)) {
122             valid = false;
123             link_name[0] = '\0';
124             assert(0);
125             return link_name;
126          }
127          if (link_name[i] == '\0') break;
128       }
129       link_name[sizeof(link_name) - 1] = '\0';
130       loaded_name = true;
131
132       return link_name;
133    }
134
135    uint64_t l_ld() { 
136       return static_cast<uint64_t>(link_elm.l_ld); 
137    }
138
139    bool is_last() {
140       return (link_elm.l_next == 0); 
141    }
142
143    bool load_next() {
144       if (is_last()) {
145          return false;
146       }
147       if (load_link(reinterpret_cast<void *>(link_elm.l_next))) {
148          loaded_name = false;
149          return true;
150       }
151       return false;
152    }
153
154 private:
155    bool load_link(void *addr) {
156       bool ret =  proc->readDataSpace((caddr_t)addr, sizeof(link_elm),
157                                       (caddr_t)&link_elm, true);
158       loaded_name = false;
159       return ret;
160    }
161    link_map_dyn32 link_elm;
162 };
163
164 class link_map_64 : public link_map_x {
165 public:
166    link_map_64(process *proc_, void *addr_)
167       : link_map_x(proc_) { valid = load_link(addr_); }
168
169    size_t size() { 
170       return sizeof(link_elm); 
171    }
172
173    uint64_t l_addr() { 
174       return link_elm.l_addr; 
175    }
176
177    char *l_name() {
178       if (loaded_name) return link_name;
179
180       for (unsigned int i = 0; i < sizeof(link_name); ++i) {
181          if (!proc->readDataSpace((caddr_t)((Address)link_elm.l_name + i),
182                                   sizeof(char), ((caddr_t)link_name + i), true)) {
183             valid = false;
184             link_name[0] = '\0';
185             return link_name;
186          }
187          if (link_name[i] == '\0') break;
188       }
189       link_name[sizeof(link_name) - 1] = '\0';
190       loaded_name = true;
191
192       return link_name;
193    }
194
195    uint64_t l_ld() { 
196       return reinterpret_cast<uint64_t>(link_elm.l_ld); 
197    }
198
199    bool is_last() { 
200       return (link_elm.l_next == 0); 
201    }
202
203    bool load_next() {
204       if (is_last()) return false;
205
206       if (load_link(link_elm.l_next)) {
207          loaded_name = false;
208          return true;
209       }
210       return false;
211    }
212
213 private:
214    bool load_link(void *addr) {
215       return proc->readDataSpace((caddr_t)addr, sizeof(link_elm),
216                                  (caddr_t)&link_elm, true);
217    }
218    link_map link_elm;
219 };
220
221 struct r_debug_dyn32
222 {
223    int r_version;              /* Version number for this protocol.  */
224
225    //struct link_map_32 *r_map;     /* Head of the chain of loaded objects.  */
226    uint32_t r_map;
227
228    /* This is the address of a function internal to the run-time linker,
229       that will always be called when the linker begins to map in a
230       library or unmap it, and again when the mapping change is complete.
231       The debugger can set a breakpoint at this address if it wants to
232       notice shared object mapping changes.  */
233    Elf32_Addr r_brk;
234    enum
235    {
236       /* This state value describes the mapping change taking place when
237          the `r_brk' address is called.  */
238       RT_CONSISTENT,          /* Mapping change is complete.  */
239       RT_ADD,                 /* Beginning to add a new object.  */
240       RT_DELETE               /* Beginning to remove an object mapping.  */
241    } r_state;
242
243    Elf32_Addr r_ldbase;        /* Base address the linker is loaded at.  */
244 };
245
246 class r_debug_x {
247 public:
248    r_debug_x(process *proc_) : proc(proc_) {}
249    virtual ~r_debug_x() {}
250    virtual link_map_x *r_map() = 0;
251    virtual void *r_brk() = 0;
252    virtual int r_state() = 0;
253
254    bool is_valid() { return valid; }
255
256 protected:
257    process *proc;
258    bool valid;
259 };
260
261 class r_debug_32 : public r_debug_x {
262 public:
263    r_debug_32(process *proc_, Address addr) :
264       r_debug_x(proc_) 
265    {
266       valid = proc->readDataSpace((caddr_t)addr, sizeof(debug_elm),
267                                   (caddr_t)&debug_elm, true);
268    }
269
270    link_map_x *r_map() {
271       return new link_map_32(proc, reinterpret_cast<void *>(debug_elm.r_map));
272    }
273
274    void *r_brk() { 
275       return reinterpret_cast<void *>(debug_elm.r_brk);
276    }
277
278    int r_state() {
279       return (int)debug_elm.r_state; 
280    }
281
282 private:
283    r_debug_dyn32 debug_elm;
284 };
285
286 class r_debug_64 : public r_debug_x {
287 public:
288    r_debug_64(process *proc_, Address addr) : 
289       r_debug_x(proc_) 
290    {
291       valid = proc->readDataSpace((caddr_t)addr, sizeof(debug_elm),
292                                   (caddr_t)&debug_elm, true);
293    }
294
295    link_map_x *r_map() {
296       return new link_map_64(proc, reinterpret_cast<void *>(debug_elm.r_map));
297    }
298
299    void *r_brk() { 
300       return reinterpret_cast<void *>(debug_elm.r_brk);
301    }
302
303    int r_state() {
304       return (int)debug_elm.r_state; 
305    }
306
307 private:
308    r_debug debug_elm;
309 };
310
311 //
312 // End 32/64-bit helper structures.
313 // ---------------------------------------------------------------
314
315 /* 16 is a good choice for testing long_fgets. */
316 #define LONG_FGETS_GRANULARITY 256
317
318 /* Utility function; functions as fgets, except it returns a malloc()d string
319    of sufficient length to hold the whole line.  Returns NULL when fgets() does. */
320 char * long_fgets( FILE * file ) {
321         char initialBuffer[ LONG_FGETS_GRANULARITY ];
322         char * status = fgets( initialBuffer, LONG_FGETS_GRANULARITY, file );
323         if( status == NULL ) { return NULL; }
324         if( initialBuffer[ strlen( initialBuffer ) - 2 ] == '\n' ) {
325                 return strdup( initialBuffer );
326                 }
327         
328         char * longline = NULL;
329         char * oldline = strdup( initialBuffer );
330         assert( oldline != NULL );
331         for( int i = 2; oldline[ strlen( oldline ) - 1 ] != '\n'; ++i ) {
332                 longline = (char *)malloc( sizeof( char ) * LONG_FGETS_GRANULARITY * i );
333                 assert( longline != NULL );
334                 strcpy( longline, oldline );
335                 char * nextline = &( longline[ (LONG_FGETS_GRANULARITY - 1) * (i - 1) ] );
336                 free( oldline );
337                 
338                 status = fgets( nextline, LONG_FGETS_GRANULARITY, file );
339                 if( status == NULL ) { return NULL; }
340                 
341                 oldline = longline;
342                 }
343         
344         return oldline;
345         } /* end long_fgets() */
346
347 static bool isValidMemory(Address addr, int pid) {
348    bool result = false;
349    unsigned maps_size = 0;
350    map_entries *maps = NULL;
351
352    maps = getLinuxMaps(pid, maps_size);
353    if (!maps)
354       goto done;
355    for (unsigned i=0; i<maps_size; i++) {
356       if (maps[i].start <= addr && maps[i].end > addr) {
357          result = true;
358          goto done;
359       }
360    }
361
362  done:
363    if (maps)
364       free(maps);
365    return result;
366 }
367
368 /* get_ld_info() returns true if it filled in the base address of the
369    ld.so library and its path, and false if it could not. */
370 bool dynamic_linking::get_ld_info( Address & addr, unsigned &size, char ** path)
371 {
372    map_entries *maps = NULL;
373    unsigned maps_size = 0;
374    bool result = false;
375    Address first = 0x0, last = 0x0;
376    *path = NULL;
377
378    addr = 0x0;
379    maps = getLinuxMaps(proc->getPid(), maps_size);
380    if (!maps)
381       goto done;
382
383    for (unsigned i=0; i<maps_size; i++) {
384       //Check inode
385       bool has_inode = (maps[i].inode != 0);
386
387
388       //Get the file part of the filename. eg /lib/ld-2.3.4.so -> ld-2.3.4.so
389       char *filename = NULL;
390       bool matches_name = false;
391       if (has_inode) {
392          filename = strrchr(maps[i].path, '/');
393          if (!filename)
394             filename = maps[i].path;
395          else
396             filename++; 
397
398          //Check for format match of ld*.so* (don't get /etc/ld.so.cache)
399          matches_name = (strncmp("ld", filename, 2)==0 && 
400                          strstr(filename, ".so") && 
401                          !strstr(filename, ".cache"));
402      }
403
404       if (!matches_name) {
405          continue;
406       }
407
408       if (!*path)
409          *path = strdup(maps[i].path);      
410       if (!first)
411          first = maps[i].start;
412       last = maps[i].end;
413    }
414
415    if (!first) {
416       result = false;
417       goto done;
418    }
419
420    assert(*path);
421    assert(last);
422    addr = first;
423    size = last - first;
424    result = true;
425    
426  done:
427    if (maps)
428       free(maps);
429
430    return result;
431 } /* end get_ld_info() */
432
433
434 #if defined(arch_ia64)
435
436 ////////////// IA-64 breakpoint routines
437
438 sharedLibHook::sharedLibHook(process *p, sharedLibHookType t, Address b) 
439         : proc_(p), type_(t), breakAddr_(b), loadinst_(NULL) {
440
441         InsnAddr iAddr = InsnAddr::generateFromAlignedDataAddress( breakAddr_, proc_ );
442         /* Save the original instructions. */
443         iAddr.saveMyBundleTo( (uint8_t *)saved_ );
444
445         IA64_bundle trapBundle = generateTrapBundle();
446         iAddr.replaceBundleWith( trapBundle );
447 }
448
449
450 sharedLibHook::~sharedLibHook() {
451     if (!proc_->isAttached() || proc_->execing())
452         return;
453
454     InsnAddr iAddr = InsnAddr::generateFromAlignedDataAddress( breakAddr_, proc_ );
455     iAddr.writeMyBundleFrom((uint8_t *)saved_);
456 }
457
458
459 #else
460
461 /////////////// x86-linux breakpoint insertion routines
462 sharedLibHook::sharedLibHook(process *p, sharedLibHookType t, Address b) 
463         : proc_(p), type_(t), breakAddr_(b), loadinst_(NULL) {
464
465     // Before putting in the breakpoint, save what is currently at the
466     // location that will be overwritten.
467     if (!proc_->readDataSpace((void *)breakAddr_, SLH_SAVE_BUFFER_SIZE,
468                          (void *)saved_, true))
469                 fprintf(stderr, "%s[%d]:  readDataSpace\n", __FILE__, __LINE__);
470 #if defined(arch_power)
471     codeGen gen(instruction::size());
472 #else
473     // Need a "trap size" method...
474     codeGen gen(1);
475 #endif
476     instruction::generateTrap(gen);
477     proc_->writeDataSpace((void*)breakAddr_, gen.used(), gen.start_ptr());
478     
479 }
480
481 sharedLibHook::~sharedLibHook() 
482 {
483     if (!proc_->isAttached() || proc_->execing())
484         return;
485
486     if (!proc_->writeDataSpace((void *)breakAddr_, SLH_SAVE_BUFFER_SIZE, saved_)) {
487         //  This wds fails, and has so for a long time...
488         // Yeah, because the process may be, you know, GONE... -- bernat
489         
490         //fprintf(stderr, "%s[%d]:  WDS failed: %d bytes at %p\n", FILE__, __LINE__, SLH_SAVE_BUFFER_SIZE, breakAddr_);
491     }
492 }
493 #endif
494
495 // processLinkMaps: This routine is called by getSharedObjects to  
496 // process all shared objects that have been mapped into the process's
497 // address space.  This routine reads the link maps from the application 
498 // process to find the shared object file base mappings. It returns 0 on error.
499 bool dynamic_linking::processLinkMaps(pdvector<fileDescriptor> &descs) {
500    // Use proc maps file instead of r_debug.  It's more detailed, and some
501    // kernels don't report correct info in r_debug
502
503    // Apparently the r_debug stuff keeps things in some wacked out
504    // order that we need (i.e. the order in which the libs are loaded)
505    // Use proc/maps to augment r_debug instead
506
507    unsigned maps_size = 0;
508    map_entries *maps= getLinuxMaps(proc->getPid(), maps_size);
509    //   std::string aout = process::tryToFindExecutable("", proc->getPid());
510
511    assert(r_debug_addr); // needs to be set before we're called
512
513    r_debug_x *debug_elm;
514    if (proc->getAddressWidth() == 4)
515       debug_elm = new r_debug_32(proc, r_debug_addr);
516    else
517       debug_elm = new r_debug_64(proc, r_debug_addr);
518     
519    if (!debug_elm->is_valid()) {
520       startup_printf("debug element invalid!\n");
521       delete debug_elm;
522       return false;
523    }
524
525    // get each link_map object
526    link_map_x *link_elm = debug_elm->r_map();
527    if (!link_elm->is_valid()) {
528       delete link_elm;
529       delete debug_elm;
530       startup_printf("Link element invalid!\n");
531       return false;
532    }
533
534    startup_printf("%s[%d]: dumping maps info\n",
535                   FILE__, __LINE__);
536    for (unsigned i = 0; i < maps_size; i++) {
537        startup_printf("\t Entry %d, name %s, addr 0x%lx\n",
538                       i, maps[i].path, maps[i].start);
539    }
540
541    do {
542       string obj_name = link_elm->l_name();
543       Address text = static_cast<Address>(link_elm->l_addr());
544       startup_printf("%s[%d]: processing element, name %s, text addr 0x%lx\n",
545                      FILE__, __LINE__, obj_name.c_str(), text);
546       if (obj_name == "") {
547          continue;
548       }
549
550       if (obj_name == "") { // Augment using maps
551          for (unsigned i = 0; i < maps_size; i++) {
552             if (text == maps[i].start) {
553                 startup_printf("%s[%d]: augmenting empty name with maps name %s\n",
554                                FILE__, __LINE__, maps[i].path);
555                 obj_name = maps[i].path;
556                 break;
557             }
558          }
559       }
560       if (obj_name[0] == '[')
561          continue;
562       if (obj_name == "") {
563           // Should we try to parse this out of memory?
564           continue;
565       }
566       if (!link_elm->is_valid()) {
567          delete link_elm;
568          delete debug_elm;
569          startup_printf("Link element invalid! (2)\n");
570          return 0;
571       }
572       startup_printf("%s[%d]: creating new file descriptor %s/0x%lx/0x%lx, ld is %lx\n",
573                      FILE__, __LINE__, obj_name.c_str(), text, text, link_elm->l_ld());
574       descs.push_back(fileDescriptor(obj_name, 
575                                      text, text,
576                                      true, 
577                                      static_cast<Address>(link_elm->l_ld())));
578    } while (link_elm->load_next());
579     
580    delete link_elm;
581    delete debug_elm;
582    return true;
583 }
584
585 // getLinkMapAddrs: returns a vector of addresses corresponding to all 
586 // base addresses in the link maps.  Returns 0 on error.
587 pdvector<Address> *dynamic_linking::getLinkMapAddrs() {
588
589     r_debug_x *debug_elm;
590     if (proc->getAddressWidth() == 4)
591         debug_elm = new r_debug_32(proc, r_debug_addr);
592     else
593         debug_elm = new r_debug_64(proc, r_debug_addr);
594
595     if (!debug_elm->is_valid()) {
596         delete debug_elm;
597         return 0;
598     }
599
600     bool first_time = true;
601     link_map_x *link_elm = debug_elm->r_map();
602     if (!link_elm->is_valid()) {
603         delete link_elm;
604         delete debug_elm;
605         return 0;
606     }
607
608     pdvector<Address> *link_addresses = new pdvector<Address>;
609     do {
610         // kludge: ignore the first entry
611         if (!first_time)
612       (*link_addresses).push_back(static_cast<Address>(link_elm->l_addr()));
613
614         first_time = false;
615     } while (link_elm->load_next());
616
617     delete link_elm;
618     delete debug_elm;
619     return link_addresses;
620 }
621 // initialize: perform initialization tasks on a platform-specific level
622 bool dynamic_linking::initialize() {
623     r_debug_addr = 0;
624     r_brk_target_addr = 0;
625
626     // Set an initial value for use in
627     // handleIfDueToSharedObjectMapping.  The value should be
628     // RT_CONSISTENT if we ld-preloaded our RT lib and RT_ADD if we
629     // are force-loading RT lib (the hook is not placed
630     // yet). Fortunately, the code recognizes that the RT lib is added
631     // even if previous_r_state was set to RT_CONSISTENT.
632     previous_r_state = r_debug::RT_CONSISTENT;
633     
634     /* Is this a dynamic executable? */
635     std::string dyn_str = std::string("DYNAMIC");
636     int_symbol dyn_sym;
637     if( ! proc->getSymbolInfo( dyn_str, dyn_sym ) ) { 
638         startup_printf("[%s][%d]Failed to find DYNAMIC symbol in dyn::init, "
639                        "this may not be a dynamic executable\n",__FILE__,__LINE__);
640         //return false; 
641     }
642
643     /* Find the base address of ld.so.1, since the entries we get
644        from its Object won't be right, otherwise. */
645     
646     Address ld_base, ld_base_backup = 0x0;
647     unsigned ld_size;
648     char *ld_path_backup = NULL;
649
650     const char *ld_path = proc->getInterpreterName();
651     ld_base = proc->getInterpreterBase();
652
653     if( ! get_ld_info( ld_base_backup, ld_size, &ld_path_backup) ) { 
654        startup_printf("Failed to get ld info, ret false from dyn::init\n");
655        return false; 
656     }
657     if (!ld_path && ld_path_backup) {
658        ld_path = ld_path_backup;
659        proc->setInterpreterName(ld_path);
660     }
661     if (!ld_path) {
662         startup_printf("[%s][%d]Secondary attempt to find the dynamic linker using /proc failed\n",__FILE__,__LINE__);
663         return false;
664     }
665     /* Generate its Object and set r_debug_addr ("_r_debug"/STT_OBJECT) */
666     // We haven't parsed libraries at this point, so do it by hand.
667     Symtab *ldsoOne = new Symtab();
668     string fileName = ld_path;
669     ldsoOne->Symtab::openFile(ldsoOne, fileName);
670
671     vector<Variable *> vars;
672
673     if (!ldsoOne->findVariablesByName(vars, "_r_debug")) {
674         startup_printf("Failed to find _r_debug, ret false from dyn::init\n");
675         return false;
676     }
677     if (vars.size() != 1) {
678         startup_printf("Found %d symbols for _r_debug, expecting 1, ret false from dyn::init\n", vars.size());
679         return false; 
680     }        
681
682     r_debug_addr = vars[0]->getOffset();
683
684     if (!isValidMemory(r_debug_addr + ld_base, proc->getPid())) {
685        ld_base = ld_base_backup;
686     }
687     if (!isValidMemory(r_debug_addr + ld_base, proc->getPid())) {
688        ld_base = ldsoOne->getLoadOffset();
689     }
690     r_debug_addr += ld_base;
691
692     assert( r_debug_addr );
693
694     dynlinked = true;
695
696     return true;
697 }
698
699 /* Return true if the exception was caused by the hook in the linker
700  * code, we'll worry about whether or not any libraries were
701  * added/removed later on when we handle the exception
702  */
703 bool dynamic_linking::decodeIfDueToSharedObjectMapping(EventRecord &ev,
704                                                        unsigned int & /*change_type*/)
705 {
706     sharedLibHook *hook;
707     assert(ev.lwp);
708     Frame lwp_frame = ev.lwp->getActiveFrame();
709     hook = reachedLibHook(lwp_frame.getPC());
710     return (bool)hook;
711 }
712
713 bool dynamic_linking::getChangedObjects(EventRecord & /* ev */, pdvector<mapped_object*> & /* changed_objects */)
714 {
715   return false;
716 }
717
718 // handleIfDueToSharedObjectMapping: returns true if the trap was caused
719 // by a change to the link maps,  If it is, and if the linkmaps state is
720 // safe, it processes the linkmaps to find out what has changed...if it
721 // is not safe it sets the type of change currently going on (specified by
722 // the value of r_debug.r_state in link.h
723 // The added or removed shared objects are returned in changed_objects
724 // the change_type value is set to indicate if the objects have been added 
725 // or removed
726 bool dynamic_linking::handleIfDueToSharedObjectMapping(EventRecord &ev,
727                                  pdvector<mapped_object*> &changed_objects,
728                                  pdvector<bool> &is_new_object)
729
730    //  pdvector<dyn_thread *>::iterator iter = proc->threads.begin();
731   
732   dyn_lwp *brk_lwp = ev.lwp;
733   sharedLibHook *hook = NULL;
734
735   if (brk_lwp) {
736     Frame lwp_frame = brk_lwp->getActiveFrame();
737     hook = reachedLibHook(lwp_frame.getPC());
738   }
739
740   // is the trap instr at at the breakpoint?
741   if (force_library_load || hook != NULL) {
742     // We can force this manually, even if we aren't at
743     // the correct address.
744     // dlclose_brk_addr would be the same if it was set, so we need to 
745     // compare link maps to find what has changed
746     // find out what has changed in the link map
747     // and process it
748     r_debug_x *debug_elm;
749     if (proc->getAddressWidth() == 4)
750       debug_elm = new r_debug_32(proc, r_debug_addr);
751     else
752       debug_elm = new r_debug_64(proc, r_debug_addr);
753     
754     if (!debug_elm->is_valid()) {
755         bperr("read failed r_debug_addr = 0x%x\n",r_debug_addr);
756         delete debug_elm;
757         return false;
758     }
759     
760     // if the state of the link maps is consistent then we can read
761     // the link maps, otherwise just set the r_state value
762     
763     // The EventRecord is used for passing information in, but not
764     // back out, it's not necessary to set ev.what.
765
766     // We see two events: first a "something is changing..." then a 
767     // "now consistent". We want the library list from consistent,
768     // and the "what's new" from "changing".
769     switch(previous_r_state) {
770     case r_debug::RT_CONSISTENT:
771       ev.what = SHAREDOBJECT_NOCHANGE;
772       break;
773     case r_debug::RT_ADD:
774       ev.what = SHAREDOBJECT_ADDED;
775       break;
776     case r_debug::RT_DELETE:
777       ev.what = SHAREDOBJECT_REMOVED;
778       break;
779     default:
780       assert(0);
781       break;
782     }
783     current_r_state = debug_elm->r_state();
784     
785     delete debug_elm; 
786     // figure out how link maps have changed, and then create
787     // a list of all the changes in shared object mappings
788     bool res = findChangeToLinkMaps(changed_objects, is_new_object);
789     if (!res) {
790        return false;
791     }
792 #if defined(i386_unknown_linux2_0)                                   \
793  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
794     // SAVE THE WORLD
795     if (previous_r_state == r_debug::RT_ADD) {
796        for(unsigned int index = 0; index < changed_objects.size(); index++){
797           if (changed_objects[index]->fileName() == "libdyninstAPI_RT.so")
798              continue; // Don't want 
799           if (changed_objects[index]->fileName() == "libelf.so")
800              continue; // Don't want 
801           setlowestSObaseaddr(changed_objects[index]->getBaseAddress());
802        }        
803     }
804 #endif
805     
806     // Now to clean up.
807     
808     if (!force_library_load) {
809 #if defined(arch_x86) || defined(arch_x86_64)
810       // Return from the function.  We used to do this by setting the program
811       // counter to the end of the function, but we don't necessarily know
812       // how long it is, so now we emulate a ret instruction by changing the
813       // PC to the return value from the stack and incrementing the stack
814       // pointer.
815       dyn_saved_regs regs;
816       
817       brk_lwp->getRegisters(&regs);
818       
819       Address sp = regs.gprs.PTRACE_REG_SP;
820       
821       Address ret_addr = 0;
822       if(!proc->readDataSpace((caddr_t)sp, proc->getAddressWidth(),
823                               (caddr_t)&ret_addr, true)) {
824         // bperr("read failed sp = 0x%x\n", sp);
825         fprintf(stderr, "%s[%d]:  readDataSpace\n", __FILE__, __LINE__);
826         return false;
827       }
828       // Fix up the stack pointer
829       regs.gprs.PTRACE_REG_SP = sp + proc->getAddressWidth();
830       brk_lwp->restoreRegisters(regs);
831       
832       if (! brk_lwp->changePC(ret_addr, NULL)) {
833         return false;
834       }
835 #elif defined(arch_power)
836       // The debug function looks like so:
837
838       // 0x4000c4d0 <_dl_debug_state+0>: stwu    r1,-32(r1)
839       // 0x4000c4d4 <_dl_debug_state+4>: addi    r1,r1,32
840       // 0x4000c4d8 <_dl_debug_state+8>: blr
841
842       // For now, to avoid a dependence on the size of the stack frame
843       // (which we can't tell) I'm going to instead fake an immediate return
844       // from the function - bernat, 3JUL07
845
846       dyn_saved_regs regs;
847       if (!brk_lwp->getRegisters(&regs))
848           return false;
849
850       Address retAddr = regs.gprs.link;
851       if (!brk_lwp->changePC(retAddr, NULL))
852           return false;
853
854 #else   // ia64
855       dyn_lwp *lwp_to_use = NULL;
856       lwp_to_use = proc->getRepresentativeLWP();
857       if(lwp_to_use == NULL)
858         if(process::IndependentLwpControl() && lwp_to_use == NULL)
859           lwp_to_use = proc->getInitialThread()->get_lwp();
860       
861       /* We've inserted a return statement at r_brk_target_addr
862          for our use here. */
863       // fprintf(stderr, "Changing PC to 0x%llx\n", r_brk_target_addr);
864       assert(r_brk_target_addr);
865       lwp_to_use->changePC( r_brk_target_addr, NULL );
866 #endif  //x86
867     } // non-forced, clean up for breakpoint
868     previous_r_state = current_r_state;
869     return true;
870   } // Not a library load (!forced && pc != breakpoint)
871   return false; 
872 }
873
874 // This function performs all initialization necessary to catch shared object
875 // loads and unloads (symbol lookups and trap setting)
876 bool dynamic_linking::installTracing()
877 {
878   // Need to update for IA64 as well.
879 #if defined(arch_x86)
880   //Libc >= 2.3.3 has security features that prevent _dl_open from being
881   // called from outside libc.  We'll disable those features by finding the
882   // function that implements them and writing 'return 0' over the top of
883   // the function.
884     startup_printf("... Looking for dl_check_caller...\n");
885     pdvector<int_function *> dlchecks;
886     if (proc->findFuncsByMangled("_dl_check_caller",
887                                  dlchecks)) {
888         for (unsigned i = 0; i < dlchecks.size(); i++) {
889             startup_printf("Overwriting retval for hit %d\n", i);
890             dlchecks[i]->setReturnValue(0);
891         }
892     }
893     
894     // And find the address of do_dlopen and set the RT library symbol correctly
895     // TODO: check libc only
896     // TODO: use replaceCall to do this right...
897     pdvector<int_function *> do_dlopens;
898     startup_printf("... Looking for do_dlopen...\n");
899     if (proc->findFuncsByMangled("do_dlopen",
900                                  do_dlopens)) {
901         Address do_dlopen_addr = do_dlopens[0]->getAddress();
902         startup_printf("... Found do_dlopen at 0x%x\n", do_dlopen_addr);
903         pdvector<int_variable *> vars;
904         if (proc->findVarsByAll("DYNINST_do_dlopen", vars)) {
905             assert(vars.size() == 1);
906             Address tmp = vars[0]->getAddress();
907             startup_printf("... writing to RT var at 0x%x\n", tmp);
908             proc->writeDataSpace((void *)tmp, sizeof(Address), (void *)&do_dlopen_addr);
909         }
910     }
911 #endif
912   
913   assert(r_debug_addr);
914     
915   r_debug_x *debug_elm;
916   if (proc->getAddressWidth() == 4)
917      debug_elm = new r_debug_32(proc, r_debug_addr);
918   else
919      debug_elm = new r_debug_64(proc, r_debug_addr);
920   
921   if (!debug_elm->is_valid()) {
922      bperr( "Failed data read\n");
923      
924      delete debug_elm;
925      return true;
926   }
927     Address breakAddr = reinterpret_cast<Address>(debug_elm->r_brk());
928     delete debug_elm;
929
930 #if defined(arch_ia64)
931     /* The IA-64's function pointers don't actually point at the function,
932        because you also need to know the GP to call it.  Hence, another
933        indirection. */
934     if(! proc->readDataSpace( (void *)breakAddr, 8, (void *)&breakAddr, true ) ) {
935         bperr( "Failed to read breakAddr_.\n" );
936         return 0;
937     }
938
939     // We don't handle the trap directly, rather inserting a sequence of instructions
940     // in the runtime library that patch it up
941
942     /* Insert a return bundle for use in the handler. */
943     instruction memoryNOP( NOP_M );
944     instruction returnToBZero = generateReturnTo( 0 );
945     IA64_bundle returnBundle( MMBstop, memoryNOP, memoryNOP, returnToBZero );
946
947     int_symbol r_brk_target;
948     if (!proc->getSymbolInfo("R_BRK_TARGET", r_brk_target))
949         assert(0);
950     r_brk_target_addr = r_brk_target.getAddr(); assert( r_brk_target_addr );
951
952     InsnAddr jAddr = InsnAddr::generateFromAlignedDataAddress( r_brk_target_addr, proc );
953     jAddr.replaceBundleWith( returnBundle );
954
955 #elif defined(arch_power) && defined(arch_64bit)
956     /* 64-bit POWER architectures also use function descriptors instead of directly
957        pointing at the function code.  Find the actual address of the function.
958     */
959     Address actualAddr;
960     if (! proc->readDataSpace( (void *)breakAddr, 8, (void *)&actualAddr, true ) ) {
961         bperr( "Failed to read breakAddr_.\n" );
962         return 0;
963     }
964     breakAddr = actualAddr;
965 #endif
966
967     sharedLibHook *sharedHook = new sharedLibHook(proc, SLH_UNKNOWN, // not used
968                                                   breakAddr);
969     sharedLibHooks_.push_back(sharedHook);
970
971     return true;
972 }