Update copyright to LGPL on all files
[dyninst.git] / symtabAPI / src / addrtranslate-sysv.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 <assert.h>
33 #include <link.h>
34 #include <stdio.h>
35 #include <errno.h>
36 #include <sys/types.h>
37 #include <sys/wait.h>
38 #include <string.h>
39
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <unistd.h>
43
44 #include <vector>
45 #include <string>
46
47 #include "common/h/parseauxv.h"
48 #include "common/h/headers.h"
49
50 #include "symtabAPI/h/Symtab.h"
51 #include "symtabAPI/src/addrtranslate.h"
52 #include "symtabAPI/src/addrtranslate-sysv.h"
53 #include "debug.h"
54
55 #if defined(os_linux) || defined(os_bg)
56 #define R_DEBUG_NAME "_r_debug"
57 #else
58 #define R_DEBUG_NAME "r_debug"
59 #endif
60
61 using namespace std;
62
63 using namespace Dyninst;
64 using namespace SymtabAPI;
65
66 FileCache Dyninst::SymtabAPI::files;
67
68
69 class ProcessReaderSelf : public ProcessReader {
70 public:
71    ProcessReaderSelf();
72    bool start();
73    bool readAddressSpace(Address inTraced, unsigned amount,
74                          void *inSelf);
75    bool done();
76
77   virtual ~ProcessReaderSelf();
78 };
79
80 struct link_map_dyn32
81 {
82    Elf32_Addr l_addr;
83    uint32_t l_name;
84    uint32_t l_ld;
85    uint32_t l_next, l_prev;
86 };
87
88 struct r_debug_dyn32
89 {
90     int r_version;
91     uint32_t r_map;
92     Elf32_Addr r_brk;
93     enum
94     {
95        RT_CONSISTENT,
96        RT_ADD,
97        RT_DELETE
98     } r_state;
99     Elf32_Addr r_ldbase;
100 };
101
102 class link_map_xplat 
103 {
104 public:
105    virtual size_t size() = 0;
106    virtual uint64_t l_addr() = 0;
107    virtual char *l_name() = 0;
108    virtual void *l_ld() = 0;
109    virtual bool is_last() = 0;
110    virtual bool load_next() = 0;   
111    virtual bool is_valid() = 0;   
112    virtual bool load_link(Address addr) = 0;
113    virtual ~link_map_xplat() {};
114 };
115
116 template<class link_map_X> 
117 class link_map_dyn : public link_map_xplat 
118 {
119 public: 
120    link_map_dyn(ProcessReader *proc_, Address addr);
121    ~link_map_dyn();
122    virtual size_t size();
123    virtual uint64_t l_addr();
124    virtual char *l_name();
125    virtual void *l_ld();
126    virtual bool is_last();
127    virtual bool load_next();   
128    virtual bool is_valid();   
129    virtual bool load_link(Address addr);
130
131 protected:
132    ProcessReader *proc;
133    char link_name[256];
134    bool loaded_name;
135    bool valid;
136    link_map_X link_elm;
137 };
138
139 template<class r_debug_X> 
140 class r_debug_dyn {
141 public:
142    r_debug_dyn(ProcessReader *proc_, Address addr);
143    ~r_debug_dyn();
144    void *r_brk();
145    Address r_map();
146    int r_state();
147    bool is_valid();
148 protected:
149    ProcessReader *proc;
150    bool valid;
151    r_debug_X debug_elm;
152 };
153
154 template<class r_debug_X> 
155 r_debug_dyn<r_debug_X>::r_debug_dyn(ProcessReader *proc_, Address addr)
156    : proc(proc_) 
157 {
158    valid = proc->readAddressSpace(addr, sizeof(debug_elm), &debug_elm);
159
160    translate_printf("[%s:%u] -     Read rdebug structure.  Values were:\n", __FILE__, __LINE__);
161    translate_printf("[%s:%u] -       r_brk:    %lx\n", __FILE__, __LINE__, (unsigned long)debug_elm.r_brk);
162    translate_printf("[%s:%u] -       r_map:    %lx\n", __FILE__, __LINE__, (unsigned long)debug_elm.r_map);
163    translate_printf("[%s:%u] -       r_ldbase: %lx\n", __FILE__, __LINE__, (unsigned long)debug_elm.r_ldbase);
164 }
165
166 template<class r_debug_X> 
167 r_debug_dyn<r_debug_X>::~r_debug_dyn() 
168 {
169 }
170
171 template<class r_debug_X> 
172 bool r_debug_dyn<r_debug_X>::is_valid() {
173    if (0 == r_map()) return false;
174    else return valid;
175 }
176
177 template<class r_debug_X> 
178 Address r_debug_dyn<r_debug_X>::r_map() {
179         return (Address) debug_elm.r_map;
180 }
181
182 template<class r_debug_X> 
183 void *r_debug_dyn<r_debug_X>::r_brk() { 
184    return reinterpret_cast<void *>(debug_elm.r_brk); 
185 }
186
187 template<class r_debug_X> 
188 int r_debug_dyn<r_debug_X>::r_state() { 
189    return (int)debug_elm.r_state; 
190 }
191  
192 template<class link_map_X>
193 link_map_dyn<link_map_X>::link_map_dyn(ProcessReader *proc_, Address addr_) :
194    proc(proc_),
195    loaded_name(false)
196 {
197    valid = load_link(addr_);
198 }
199
200 template<class link_map_X>
201 link_map_dyn<link_map_X>::~link_map_dyn() {
202 }
203
204 template<class link_map_X>
205 bool link_map_dyn<link_map_X>::is_valid() {
206    return valid;
207 }
208
209 template<class link_map_X>
210 size_t link_map_dyn<link_map_X>::size()
211 {
212    return sizeof(link_elm);
213 }
214
215 template<class link_map_X>
216 uint64_t link_map_dyn<link_map_X>::l_addr() 
217 {
218    return link_elm.l_addr;
219 }
220
221 template<class link_map_X>
222 char *link_map_dyn<link_map_X>::l_name() 
223 {
224   if (loaded_name) return link_name;
225
226   for (unsigned int i = 0; i < sizeof(link_name); ++i) {
227     if (!proc->readAddressSpace((Address) (link_elm.l_name + i),
228                              sizeof(char), link_name + i))
229     {
230        valid = false;
231        return NULL;
232     }
233     if (link_name[i] == '\0') break;
234   }
235   link_name[sizeof(link_name) - 1] = '\0';
236
237   loaded_name = true;  
238   return link_name;
239 }
240
241 template<class link_map_X>
242 void *link_map_dyn<link_map_X>::l_ld() 
243
244    return reinterpret_cast<void *>(link_elm.l_ld); 
245 }
246
247 template<class link_map_X>
248 bool link_map_dyn<link_map_X>::is_last() 
249
250    return (link_elm.l_next == 0); 
251 }
252
253 template<class link_map_X>
254 bool link_map_dyn<link_map_X>::load_next() 
255 {
256         if (is_last()) {
257       return false;
258    }
259         if (load_link((Address) link_elm.l_next)) {
260       loaded_name = false;
261       return true;
262         }
263         return false;
264 }
265
266 template<class link_map_X>
267 bool link_map_dyn<link_map_X>::load_link(Address addr) 
268 {
269    return proc->readAddressSpace(addr, sizeof(link_elm), &link_elm);
270 }
271
272 static const char *deref_link(const char *path)
273 {
274    static char buffer[PATH_MAX], *p;
275    buffer[PATH_MAX-1] = '\0';
276    p = realpath(path, buffer);
277    if (!p)
278       return path;
279    return p;
280 }
281
282 ProcessReader::ProcessReader(int pid_, string exe) :
283    pid(pid_), executable(exe)
284 {
285 }
286
287 ProcessReader::ProcessReader() :
288    pid(0)
289 {
290 }
291
292 ProcessReaderSelf::ProcessReaderSelf() :
293    ProcessReader(getpid()) 
294 {
295 }
296
297 ProcessReaderSelf::~ProcessReaderSelf()
298 {
299 }
300
301 bool ProcessReaderSelf::start() {
302    return true;
303 }
304
305 bool ProcessReaderSelf::done() {
306    return true;
307 }
308
309 bool ProcessReaderSelf::readAddressSpace(Address inTraced, unsigned amount,
310                                          void *inSelf) 
311 {
312    memcpy(inSelf, (void *) inTraced, amount);
313    return true;
314 }
315
316 Symtab *LoadedLib::getSymtab()
317 {
318    if (symtable)
319       return symtable;
320
321    FCNode *fc = files.getNode(name);
322    if (!fc)
323       return NULL;
324    symtable = fc->getSymtab();
325
326    return symtable;
327 }
328
329 vector< pair<Address, unsigned long> > *LoadedLib::getMappedRegions()
330 {
331    if (mapped_regions.size())
332    {
333       return &mapped_regions;
334    }
335    
336    FCNode *fc = files.getNode(name);
337    if (!fc)
338       return false;
339
340    vector<Region *> regs;
341    fc->getRegions(regs);
342    
343    for (unsigned i=0; i<regs.size(); i++) {
344       pair<Address, unsigned long> p(load_addr + regs[i]->getRegionAddr(), regs[i]->getRegionSize());
345       mapped_regions.push_back(p);
346    }
347    
348    return &mapped_regions;
349 }
350
351 AddressTranslate *AddressTranslate::createAddressTranslator(int pid_, 
352                                                             ProcessReader *reader_,
353                                                                                                                         PROC_HANDLE)
354 {
355    translate_printf("[%s:%u] - Creating AddressTranslateSysV\n", __FILE__, __LINE__);
356    AddressTranslate *at = new AddressTranslateSysV(pid_, reader_);
357    translate_printf("[%s:%u] - Created: %lx\n", __FILE__, __LINE__, (long)at);
358    
359    if (!at) {
360       return NULL;
361    }
362    else if (at->creation_error) {
363       delete at;
364       return NULL;
365    }
366    return at;
367 }
368
369 AddressTranslate *AddressTranslate::createAddressTranslator(ProcessReader *reader_)
370 {
371    return createAddressTranslator(getpid(), reader_, INVALID_HANDLE_VALUE);
372 }
373
374 AddressTranslate *AddressTranslate::createAddressTranslator(const std::vector<LoadedLibrary> &name_addrs)
375 {
376    AddressTranslate *at = new AddressTranslateSysV();
377    
378    if (!at) {
379       return NULL;
380    }
381    else if (at->creation_error) {
382       delete at;
383       return NULL;
384    }
385    
386    for (unsigned i=0; i<name_addrs.size(); i++)
387    {
388       LoadedLib *ll = new LoadedLib(name_addrs[i].name, name_addrs[i].codeAddr);
389       at->libs.push_back(ll);
390    }
391    return at;
392 }
393
394 AddressTranslateSysV::AddressTranslateSysV() :
395    AddressTranslate(0),
396    reader(NULL),
397    interpreter_base(0),
398    set_interp_base(0),
399    address_size(0),
400    interpreter(NULL),
401    previous_r_state(0),
402    current_r_state(0),
403    r_debug_addr(0),
404    trap_addr(0)
405 {
406 }
407
408 AddressTranslateSysV::AddressTranslateSysV(int pid, ProcessReader *reader_) :
409    AddressTranslate(pid),
410    reader(reader_),
411    interpreter_base(0),
412    set_interp_base(0),
413    address_size(0),
414    interpreter(NULL),
415    previous_r_state(0),
416    current_r_state(0),
417    r_debug_addr(0),
418    trap_addr(0)
419 {
420    bool result;
421    if (!reader) {
422       if (pid == getpid())
423          reader = new ProcessReaderSelf();
424       else
425          reader = createDefaultDebugger(pid);
426    }
427
428    result = init();
429    if (!result) {
430       creation_error = true;
431       return;
432    }
433 }
434
435 bool AddressTranslateSysV::setInterpreterBase()
436 {
437    if (set_interp_base)
438      return true;
439
440    AuxvParser *parser = AuxvParser::createAuxvParser(pid, address_size);
441    if (!parser) {
442       return false;
443    }
444
445    interpreter_base = parser->getInterpreterBase();
446    set_interp_base = true;
447
448    parser->deleteAuxvParser();
449    return true;
450 }
451
452 bool AddressTranslateSysV::init()
453 {
454    bool result;
455    translate_printf("[%s:%u] - Initing AddressTranslateSysV\n", __FILE__, __LINE__);
456
457    result = setInterpreter();
458
459    if (!result) {
460      translate_printf("[%s:%u] - Failed to set interpreter.\n", __FILE__, __LINE__);
461      return false;
462    }
463
464    result = setAddressSize();
465    if (!result) {
466       translate_printf("[%s:%u] - Failed to set address size.\n", __FILE__, __LINE__);
467       return false;
468    }
469
470    result = setInterpreterBase();
471    if (!result) {
472       translate_printf("[%s:%u] - Failed to set interpreter base.\n", __FILE__, __LINE__);
473       return false;
474    }
475
476    if (interpreter) {
477       r_debug_addr = interpreter->get_r_debug() + interpreter_base;
478       trap_addr = interpreter->get_r_trap() + interpreter_base;
479    }
480    else {
481       r_debug_addr = 0;
482       trap_addr = 0;
483    }
484    
485    translate_printf("[%s:%u] - Done with AddressTranslateSysV::init()\n", __FILE__, __LINE__);
486
487    return true;
488 }
489
490 bool AddressTranslateSysV::refresh()
491 {
492    link_map_xplat *link_elm = NULL;
493    r_debug_dyn<r_debug_dyn32> *r_debug_32 = NULL;
494    r_debug_dyn<r_debug> *r_debug_native = NULL;
495    map_entries *maps = NULL;
496    bool result = false;
497    size_t loaded_lib_count = 0;
498
499    translate_printf("[%s:%u] - Refreshing Libraries\n", __FILE__, __LINE__);
500
501    if (!pid)
502       return true;
503
504    for (unsigned i=0; i<libs.size(); i++) {
505       if (libs[i])
506          delete libs[i];
507       if (libs[i] == exec)
508          exec = NULL;
509    }
510    libs.clear();
511
512    if (!exec) {
513       exec = getAOut();
514    }
515    if (exec) {
516       libs.push_back(exec);
517    }
518    
519    if (!r_debug_addr) {
520       return true; //Static library
521    }
522
523    reader->start();
524
525    translate_printf("[%s:%u] -     Starting refresh.\n", __FILE__, __LINE__);
526    translate_printf("[%s:%u] -       trap_addr:    %lx\n", __FILE__, __LINE__, trap_addr);
527    translate_printf("[%s:%u] -       r_debug_addr: %lx\n", __FILE__, __LINE__, r_debug_addr);
528
529    if (address_size == sizeof(void*)) {
530       r_debug_native = new r_debug_dyn<r_debug>(reader, r_debug_addr);
531       if (!r_debug_native)
532       {
533         result = true;
534         goto done;
535       }
536       else if (!r_debug_native->is_valid())
537       {
538          libs.push_back(new LoadedLib(interpreter->getFilename(),
539                                       interpreter_base));
540          result = true;
541          goto done;
542       }
543       link_elm = new link_map_dyn<link_map>(reader, r_debug_native->r_map());
544    }
545    else { //64-bit mutator, 32-bit mutatee
546       r_debug_32 = new r_debug_dyn<r_debug_dyn32>(reader, r_debug_addr);
547       if (!r_debug_32)
548       {
549          result = true;
550          goto done;
551       }
552       else if (!r_debug_32->is_valid())
553       {
554          libs.push_back(new LoadedLib(interpreter->getFilename(),
555                                       interpreter_base));
556          result = true;
557          goto done;
558       }
559       link_elm = new link_map_dyn<link_map_dyn32>(reader, r_debug_32->r_map());
560    }
561
562    if (!link_elm->is_valid()) {
563       result = true;
564       goto done;
565    }
566
567    do {
568       if (!link_elm->l_name())
569          continue;
570       string obj_name(link_elm->l_name());
571       Address text = (Address) link_elm->l_addr();
572       if (obj_name == "" && !text)
573          continue;
574       if (!link_elm->is_valid())
575          goto done;
576
577 #if defined(os_linux)
578       unsigned maps_size;
579       if (obj_name == "") { //Augment using maps
580          if (!maps)
581             maps = getLinuxMaps(pid, maps_size);
582          for (unsigned i=0; maps && i<maps_size; i++) {
583             if (text == maps[i].start) {
584                obj_name = maps[i].path;
585                break;
586             }
587          }
588       }
589       if (obj_name.c_str()[0] == '[')
590          continue;
591 #endif
592       
593       string s(deref_link(obj_name.c_str()));
594       LoadedLib *ll = new LoadedLib(s, text);
595       loaded_lib_count++;
596       translate_printf("[%s:%u] -     New Loaded Library: %s(%lx)\n", __FILE__, __LINE__, s.c_str(), text);
597
598       libs.push_back(ll);
599    } while (link_elm->load_next());
600
601    translate_printf("[%s:%u] - Found %d libraries.\n", __FILE__, __LINE__, loaded_lib_count);
602
603    result = true;
604  done:
605    reader->done();
606
607    if (link_elm)
608       delete link_elm;
609    if (r_debug_32)
610       delete r_debug_32;
611    if (r_debug_native)
612       delete r_debug_native;
613    if (maps)
614       free(maps);
615
616    return result;
617 }
618
619 FCNode::FCNode(string f, dev_t d, ino_t i) :
620    device(d),
621    inode(i),
622    parsed_file(false),
623    parse_error(false)
624 {
625    filename = deref_link(f.c_str());
626 }
627
628 string FCNode::getFilename() {
629    return filename;
630 }
631
632 string FCNode::getInterpreter() {
633    parsefile();
634
635    return interpreter_name;
636 }
637
638 Symtab *FCNode::getSymtab()
639 {
640    parsefile();
641
642    return symtable;
643 }
644
645 void FCNode::getRegions(vector<Region *> &regs) {
646    parsefile();
647
648    for (unsigned i=0; i<regions.size(); i++)
649       regs.push_back(regions[i]);
650 }
651
652 unsigned FCNode::getAddrSize() {
653    parsefile();
654
655    return addr_size;
656 }
657
658 Offset FCNode::get_r_debug() {
659    parsefile();
660
661    return r_debug_offset;
662 }
663
664 Offset FCNode::get_r_trap() {
665    parsefile();
666
667    return r_trap_offset;
668 }
669
670 #define NUM_DBG_BREAK_NAMES 3
671 const char *dbg_break_names[] = { "_dl_debug_state",
672                                   "r_debug_state",
673                                   "_r_debug_state" };
674 void FCNode::parsefile() {
675    bool result;
676
677    if (parsed_file || parse_error)
678       return;
679
680    translate_printf("[%s:%u] - Parsing file in FCNode: %s.\n", __FILE__, __LINE__, filename.c_str());
681
682    result = Symtab::openFile(symtable, filename);
683    if (!result) {
684       parse_error = true;
685       return;
686    }
687    
688    const char *name = symtable->getInterpreterName();
689    if (name) {
690      interpreter_name = name;
691      translate_printf("[%s:%u] - Interpreter was: %s.\n", __FILE__, __LINE__, name);
692    }
693
694    addr_size = symtable->getAddressWidth();
695    symtable->getMappedRegions(regions);
696    r_debug_offset = 0;
697    r_trap_offset = 0;
698    parsed_file = true;
699
700    vector<Symbol *> syms;
701    result = symtable->findSymbolByType(syms, 
702                                        R_DEBUG_NAME, 
703                                        Symbol::ST_OBJECT,
704                                        anyName);
705    if (result && syms.size() != 0) {
706       Symbol *rDebugSym = syms[0];   
707       r_debug_offset = rDebugSym->getAddr();
708    }
709    syms.clear();
710
711    for (unsigned i=0; i<NUM_DBG_BREAK_NAMES; i++) {
712       result = symtable->findSymbolByType(syms, dbg_break_names[i], 
713                                           Symbol::ST_FUNCTION,
714                                           anyName);
715       if (!result || !syms.size())
716          continue;
717       Symbol *rTrapSym = syms[0];
718       r_trap_offset = rTrapSym->getAddr();
719       break;
720    }
721 }
722
723 FCNode *FileCache::getNode(const string &filename)
724 {
725    struct stat buf;
726    int result = stat(filename.c_str(), &buf);
727    if (result == -1)
728       return NULL;
729    if (!filename.length())
730       return NULL;
731
732    for (unsigned i=0; i<nodes.size(); i++)
733    {
734       if (nodes[i]->inode == buf.st_ino &&
735           nodes[i]->device == buf.st_dev)
736       {
737          return nodes[i];
738       }
739    }
740
741    FCNode *fc = new FCNode(filename, buf.st_dev, buf.st_ino);
742    nodes.push_back(fc);
743
744    return fc;
745 }
746
747 FileCache::FileCache()
748 {
749 }
750
751 Address AddressTranslateSysV::getLibraryTrapAddrSysV() {
752   return trap_addr;
753 }