First pass at thread_db integration for FreeBSD.
[dyninst.git] / common / 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 #include <fcntl.h>
44 #include <limits.h>
45
46 #include <vector>
47 #include <string>
48
49 #include "common/h/parseauxv.h"
50 #include "common/h/headers.h"
51
52 #include "common/h/addrtranslate.h"
53 #include "common/src/addrtranslate-sysv.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 using namespace Dyninst;
63
64 FileCache Dyninst::files;
65
66
67 class ProcessReaderSelf : public ProcessReader {
68 public:
69    ProcessReaderSelf();
70    bool start();
71    bool ReadMem(Address inTraced, void *inSelf, unsigned amount);
72    bool GetReg(MachRegister reg, MachRegisterVal &val);
73    bool done();
74
75   virtual ~ProcessReaderSelf();
76 };
77
78 struct link_map_dyn32
79 {
80    Elf32_Addr l_addr;
81    uint32_t l_name;
82    uint32_t l_ld;
83    uint32_t l_next, l_prev;
84 };
85
86 struct r_debug_dyn32
87 {
88     int r_version;
89     uint32_t r_map;
90     Elf32_Addr r_brk;
91     enum
92     {
93        RT_CONSISTENT,
94        RT_ADD,
95        RT_DELETE
96     } r_state;
97     Elf32_Addr r_ldbase;
98 };
99
100 class link_map_xplat 
101 {
102 public:
103    virtual size_t size() = 0;
104    virtual uint64_t l_addr() = 0;
105    virtual char *l_name() = 0;
106    virtual void *l_ld() = 0;
107    virtual bool is_last() = 0;
108    virtual bool load_next() = 0;   
109    virtual bool is_valid() = 0;   
110    virtual bool load_link(Address addr) = 0;
111    virtual ~link_map_xplat() {};
112 };
113
114 template<class link_map_X> 
115 class link_map_dyn : public link_map_xplat 
116 {
117 public: 
118    link_map_dyn(ProcessReader *proc_, Address addr);
119    ~link_map_dyn();
120    virtual size_t size();
121    virtual uint64_t l_addr();
122    virtual char *l_name();
123    virtual void *l_ld();
124    virtual bool is_last();
125    virtual bool load_next();   
126    virtual bool is_valid();   
127    virtual bool load_link(Address addr);
128
129 protected:
130    ProcessReader *proc;
131    char link_name[256];
132    bool loaded_name;
133    bool valid;
134    link_map_X link_elm;
135 };
136
137 template<class r_debug_X> 
138 class r_debug_dyn {
139 public:
140    r_debug_dyn(ProcessReader *proc_, Address addr);
141    ~r_debug_dyn();
142    void *r_brk();
143    Address r_map();
144    int r_state();
145    bool is_valid();
146 protected:
147    ProcessReader *proc;
148    bool valid;
149    r_debug_X debug_elm;
150 };
151
152 template<class r_debug_X> 
153 r_debug_dyn<r_debug_X>::r_debug_dyn(ProcessReader *proc_, Address addr)
154    : proc(proc_) 
155 {
156    valid = proc->ReadMem(addr, &debug_elm, sizeof(debug_elm));
157
158    translate_printf("[%s:%u] -     Read rdebug structure.  Values were:\n", __FILE__, __LINE__);
159    translate_printf("[%s:%u] -       r_brk:    %lx\n", __FILE__, __LINE__, (unsigned long)debug_elm.r_brk);
160    translate_printf("[%s:%u] -       r_map:    %lx\n", __FILE__, __LINE__, (unsigned long)debug_elm.r_map);
161 #if !defined(os_freebsd)
162    translate_printf("[%s:%u] -       r_ldbase: %lx\n", __FILE__, __LINE__, (unsigned long)debug_elm.r_ldbase);
163 #endif
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 (uint64_t)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->ReadMem((Address) (link_elm.l_name + i),
228                         link_name + i, sizeof(char)))
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 const_cast<void *>(reinterpret_cast<const 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->ReadMem(addr, &link_elm, sizeof(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 ProcessReaderSelf::ProcessReaderSelf() :
283    ProcessReader() 
284 {
285 }
286
287 ProcessReaderSelf::~ProcessReaderSelf()
288 {
289 }
290
291 bool ProcessReaderSelf::start() {
292    return true;
293 }
294
295 bool ProcessReaderSelf::done() {
296    return true;
297 }
298
299 bool ProcessReaderSelf::ReadMem(Address inTraced, void *inSelf, unsigned amount)
300 {
301    memcpy(inSelf, (void *) inTraced, amount);
302    return true;
303 }
304
305 bool ProcessReaderSelf::GetReg(MachRegister /*reg*/, MachRegisterVal &/*val*/)
306 {
307    assert(0);
308    return false;
309 }
310
311
312 vector< pair<Address, unsigned long> > *LoadedLib::getMappedRegions()
313 {
314    if (mapped_regions.size())
315    {
316       return &mapped_regions;
317    }
318
319    FCNode *fc = files.getNode(name, symreader_factory);
320    if (!fc)
321       return false;
322
323    vector<SymRegion> regs;
324    fc->getRegions(regs);
325    
326    for (unsigned i=0; i<regs.size(); i++) {
327       pair<Address, unsigned long> p(load_addr + regs[i].mem_addr, 
328                                      regs[i].mem_size);
329       mapped_regions.push_back(p);
330    }
331    
332    return &mapped_regions;
333 }
334
335 AddressTranslate *AddressTranslate::createAddressTranslator(int pid_, 
336                                                ProcessReader *reader_,
337                                                SymbolReaderFactory *symfactory_,
338                                                PROC_HANDLE)
339 {
340    translate_printf("[%s:%u] - Creating AddressTranslateSysV\n", __FILE__, __LINE__);
341    AddressTranslate *at = new AddressTranslateSysV(pid_, reader_, symfactory_);
342    translate_printf("[%s:%u] - Created: %lx\n", __FILE__, __LINE__, (long)at);
343    
344    if (!at) {
345       return NULL;
346    }
347    else if (at->creation_error) {
348       delete at;
349       return NULL;
350    }
351    return at;
352 }
353
354 AddressTranslate *AddressTranslate::createAddressTranslator(ProcessReader *reader_,
355                                                             SymbolReaderFactory *factory_)
356 {
357    return createAddressTranslator(getpid(), reader_, factory_, INVALID_HANDLE_VALUE);
358 }
359
360 AddressTranslateSysV::AddressTranslateSysV() :
361    AddressTranslate(NULL_PID),
362    reader(NULL),
363    interpreter_base(0),
364    set_interp_base(0),
365    address_size(0),
366    interpreter(NULL),
367    previous_r_state(0),
368    current_r_state(0),
369    r_debug_addr(0),
370    trap_addr(0)
371 {
372 }
373
374 AddressTranslateSysV::AddressTranslateSysV(int pid, ProcessReader *reader_, 
375                                            SymbolReaderFactory *reader_fact) :
376    AddressTranslate(pid),
377    reader(reader_),
378    interpreter_base(0),
379    set_interp_base(0),
380    address_size(0),
381    interpreter(NULL),
382    previous_r_state(0),
383    current_r_state(0),
384    r_debug_addr(0),
385    trap_addr(0)
386 {
387    bool result;
388    if (!reader) {
389       if (pid == getpid())
390          reader = new ProcessReaderSelf();
391       else
392          reader = createDefaultDebugger(pid);
393    }
394    symfactory = reader_fact;
395    result = init();
396    if (!result) {
397       creation_error = true;
398       return;
399    }
400 }
401
402 bool AddressTranslateSysV::parseDTDebug() {
403     //TODO this could possibly be used on other platforms
404 #if !defined(os_freebsd)
405     return false;
406 #else
407     if( !setAddressSize() ) {
408         translate_printf("[%s:%u] - Failed to set address size.\n", __FILE__, __LINE__);
409         return false;
410     }
411
412     // This information is derived from the DT_DEBUG field in the
413     // executable's program headers -- however, the value needs to
414     // be read from the loaded executable image so determine the
415     // address of the DT_DEBUG field and then read it from the
416     // process
417
418     const char *l_err = "Failed to determine trap address.";
419
420     getExecName();
421     if( exec_name.empty() ) {
422         translate_printf("[%s:%u] - %s\n", __FILE__, __LINE__, l_err);
423         return false;
424     }
425
426     SymReader *exe = symfactory->openSymbolReader(exec_name);
427     if( !exe ) {
428         translate_printf("[%s:%u] - %s\n", __FILE__, __LINE__, l_err);
429         return false;
430     }
431         
432     // Need to get the address of the DYNAMIC segment
433     Address dynAddress = 0;
434     size_t dynSize = 0;
435     unsigned numRegs = exe->numRegions();
436     for(unsigned i = 0; i < numRegs; ++i) {
437         SymRegion reg;
438         exe->getRegion(i, reg);
439
440         if( PT_DYNAMIC == reg.type ) {
441             dynAddress = reg.mem_addr;
442             dynSize = reg.mem_size;
443             break;
444         }
445     }
446     symfactory->closeSymbolReader(exe);
447
448     if( !dynAddress || !dynSize ) {
449         // This is okay for static binaries
450         return false;
451     }
452
453     if( !reader->start() ) {
454         translate_printf("[%s:%u] - %s\n", __FILE__, __LINE__, l_err);
455         return false;
456     }
457
458     // Read the DYNAMIC segment from the process
459     void *dynData = malloc(dynSize);
460     if( !dynData || !reader->ReadMem(dynAddress, dynData, dynSize) ) {
461         translate_printf("[%s:%u] - %s\n", __FILE__, __LINE__, l_err);
462         if( dynData ) free(dynData);
463         return false;
464     }
465     
466     if( address_size == 8 ) {
467         Elf64_Dyn *dynDataElf = (Elf64_Dyn *)dynData;
468         for(unsigned i = 0; i < (dynSize / sizeof(Elf64_Dyn)); ++i) {
469             if( DT_DEBUG == dynDataElf[i].d_tag ) {
470                 r_debug_addr = (Address) dynDataElf[i].d_un.d_ptr;
471                 break;
472             }
473         }
474     }else{
475         Elf32_Dyn *dynDataElf = (Elf32_Dyn *)dynData;
476         for(unsigned i = 0; i < (dynSize / sizeof(Elf32_Dyn)); ++i) {
477             if( DT_DEBUG == dynDataElf[i].d_tag ) {
478                 r_debug_addr = (Address) dynDataElf[i].d_un.d_ptr;
479                 break;
480             }
481         }
482     }
483     free(dynData);
484
485     // When a process is initializing, the DT_DEBUG value could be zero
486     // This function needs to indicate an error so the trap address can
487     // be parsed from other sources (i.e., the interpreter)
488
489     if( r_debug_addr ) {
490         trap_addr = getTrapAddrFromRdebug();
491     }
492
493     reader->done();
494     
495     return ( r_debug_addr != 0 );
496 #endif
497 }
498
499 bool AddressTranslateSysV::parseInterpreter() {
500     bool result;
501
502     result = setInterpreter();
503     if (!result) {
504         translate_printf("[%s:%u] - Failed to set interpreter.\n", __FILE__, __LINE__);
505         return false;
506     }
507
508     result = setAddressSize();
509     if (!result) {
510         translate_printf("[%s:%u] - Failed to set address size.\n", __FILE__, __LINE__);
511         return false;
512     }
513
514     result = setInterpreterBase();
515     if (!result) {
516         translate_printf("[%s:%u] - Failed to set interpreter base.\n", __FILE__, __LINE__);
517         return false;
518     }
519
520     if (interpreter) {
521         if( interpreter->get_r_debug() ) {
522             r_debug_addr = interpreter->get_r_debug() + interpreter_base;
523             trap_addr = getTrapAddrFromRdebug();
524         }else{
525             r_debug_addr = 0;
526             trap_addr = interpreter->get_r_trap() + interpreter_base;
527         }
528     } else {
529         r_debug_addr = 0;
530         trap_addr = 0;
531     }
532
533     return true;
534 }
535
536 bool AddressTranslateSysV::init() {
537    translate_printf("[%s:%u] - Initing AddressTranslateSysV\n", __FILE__, __LINE__);
538
539    // Try to use DT_DEBUG first, falling back to parsing the interpreter binary if possible
540    if( !parseDTDebug() ) {
541        if( !parseInterpreter() ) {
542            translate_printf("[%s:%u] - Failed to determine r_debug address\n", 
543                    __FILE__, __LINE__);
544            return false;
545        }
546    }
547
548    translate_printf("[%s:%u] - trap_addr = 0x%x, r_debug_addr = 0x%x\n", __FILE__, __LINE__, trap_addr, r_debug_addr);
549    translate_printf("[%s:%u] - Done with AddressTranslateSysV::init()\n", __FILE__, __LINE__);
550
551    return true;
552 }
553
554 LoadedLib *AddressTranslateSysV::getLoadedLibByNameAddr(Address addr, std::string name)
555 {
556    std::pair<Address, std::string> p(addr, name);
557    sorted_libs_t::iterator i = sorted_libs.find(p);
558    LoadedLib *ll = NULL;
559    if (i != sorted_libs.end()) {
560       ll = i->second;
561    }
562    else {
563       ll = new LoadedLib(name, addr);
564       ll->setFactory(symfactory);
565       assert(ll);
566       sorted_libs[p] = ll;
567    }
568    ll->setShouldClean(false);
569    return ll;
570 }
571
572 Address AddressTranslateSysV::getTrapAddrFromRdebug() {
573     Address retVal = 0;
574     assert( r_debug_addr && address_size );
575
576     if( address_size == sizeof(void *) ) {
577         r_debug_dyn<r_debug> *r_debug_native = new r_debug_dyn<r_debug>(reader, r_debug_addr);
578         if( !r_debug_native ) {
579             translate_printf("[%s:%u] - Failed to parse r_debug struct.\n", __FILE__, __LINE__);
580             return 0;
581         }
582         retVal = (Address) r_debug_native->r_brk();
583         delete r_debug_native;
584     }else{
585         r_debug_dyn<r_debug_dyn32> *r_debug_32 = new r_debug_dyn<r_debug_dyn32>(reader, r_debug_addr);
586         if( !r_debug_32 ) {
587             translate_printf("[%s:%u] - Failed to parse r_debug struct.\n", __FILE__, __LINE__);
588             return 0;
589         }
590         retVal = (Address) r_debug_32->r_brk();
591         delete r_debug_32;
592     }
593
594     return retVal;
595 }
596
597 bool AddressTranslateSysV::refresh()
598 {
599    link_map_xplat *link_elm = NULL;
600    r_debug_dyn<r_debug_dyn32> *r_debug_32 = NULL;
601    r_debug_dyn<r_debug> *r_debug_native = NULL;
602    map_entries *maps = NULL;
603    bool result = false;
604    size_t loaded_lib_count = 0;
605
606    translate_printf("[%s:%u] - Refreshing Libraries\n", __FILE__, __LINE__);
607    if (pid == NULL_PID)
608       return true;
609
610    if (!r_debug_addr) {
611        // On systems that use DT_DEBUG to determine r_debug_addr, DT_DEBUG might
612        // not be set right away -- read DT_DEBUG now and see if it is set
613        if( !parseDTDebug() && !interpreter ) {
614           translate_printf("[%s:%u] - Working with static binary, no libraries to refresh\n",
615                   __FILE__, __LINE__);
616           libs.clear();
617           if (!exec) {
618              exec = getAOut();
619           }
620           getArchLibs(libs);
621           return true;
622        }
623    }
624
625    std::vector<LoadedLib *>::iterator i;
626    for (i = libs.begin(); i != libs.end(); i++)
627       (*i)->setShouldClean(true);
628    libs.clear();
629
630    if (!exec) {
631       exec = getAOut();
632    }   
633    exec->setShouldClean(false);
634    libs.push_back(exec);
635    getArchLibs(libs);
636    
637    if( !reader->start() ) {
638        translate_printf("[%s:%u] - Failed to refresh libraries\n", __FILE__, __LINE__);
639        return false;
640    }
641
642    translate_printf("[%s:%u] -     Starting refresh.\n", __FILE__, __LINE__);
643    translate_printf("[%s:%u] -       trap_addr:    %lx\n", __FILE__, __LINE__, trap_addr);
644    translate_printf("[%s:%u] -       r_debug_addr: %lx\n", __FILE__, __LINE__, r_debug_addr);
645
646     if (address_size == sizeof(void*)) {
647         r_debug_native = new r_debug_dyn<r_debug>(reader, r_debug_addr);
648         if (!r_debug_native) {
649             result = true;
650             goto done;
651         } else if (!r_debug_native->is_valid()) {
652             if( interpreter ) {
653                 libs.push_back(getLoadedLibByNameAddr(interpreter_base,
654                                                       interpreter->getFilename()));
655             }
656             result = true;
657             goto done;
658         }
659         link_elm = new link_map_dyn<link_map>(reader, r_debug_native->r_map());
660     }else{ //64-bit mutator, 32-bit mutatee
661         r_debug_32 = new r_debug_dyn<r_debug_dyn32>(reader, r_debug_addr);
662         if (!r_debug_32) {
663             result = true;
664             goto done;
665         } else if (!r_debug_32->is_valid()) {
666             if( interpreter ) {
667                 libs.push_back(getLoadedLibByNameAddr(interpreter_base,
668                                                       interpreter->getFilename()));
669             }
670             result = true;
671             goto done;
672         }
673         link_elm = new link_map_dyn<link_map_dyn32>(reader, r_debug_32->r_map());
674     }
675
676    if (!link_elm->is_valid()) {
677       result = true;
678       goto done;
679    }
680
681    do {
682       if (!link_elm->l_name())
683          continue;
684       string obj_name(link_elm->l_name());
685
686       // Don't re-add the executable, it has already been added
687       if( getExecName() == string(deref_link(obj_name.c_str())) )
688           continue;
689
690       Address text = (Address) link_elm->l_addr();
691       if (obj_name == "" && !text)
692          continue;
693       if (!link_elm->is_valid())
694          goto done;
695
696 #if defined(os_linux)
697       unsigned maps_size;
698       if (obj_name == "") { //Augment using maps
699          if (!maps)
700             maps = getLinuxMaps(pid, maps_size);
701          for (unsigned i=0; maps && i<maps_size; i++) {
702             if (text == maps[i].start) {
703                obj_name = maps[i].path;
704                break;
705             }
706          }
707       }
708       if (obj_name.c_str()[0] == '[')
709          continue;
710 #endif
711       
712       string s(deref_link(obj_name.c_str()));
713       LoadedLib *ll = getLoadedLibByNameAddr(text, s);
714       loaded_lib_count++;
715       translate_printf("[%s:%u] -     New Loaded Library: %s(%lx)\n", __FILE__, __LINE__, s.c_str(), text);
716
717       libs.push_back(ll);
718    } while (link_elm->load_next());
719
720    translate_printf("[%s:%u] - Found %d libraries.\n", __FILE__, __LINE__, loaded_lib_count);
721
722    result = true;
723  done:
724    reader->done();
725    
726    //Erase old elements from the sorted_libs
727    sorted_libs.clear();
728    for (vector<LoadedLib *>::iterator i = libs.begin(); i != libs.end(); i++)
729    {
730       LoadedLib *ll = *i;
731       sorted_libs[pair<Address, string>(ll->getCodeLoadAddr(), ll->getName())] = ll;
732    }
733    
734    if (link_elm)
735       delete link_elm;
736    if (r_debug_32)
737       delete r_debug_32;
738    if (r_debug_native)
739       delete r_debug_native;
740    if (maps)
741       free(maps);
742
743    return result;
744 }
745
746 FCNode::FCNode(string f, dev_t d, ino_t i, SymbolReaderFactory *factory_) :
747    device(d),
748    inode(i),
749    parsed_file(false),
750    parse_error(false),
751    is_interpreter(false),
752    r_debug_offset(0),
753    r_trap_offset(0),
754    symreader(NULL),
755    factory(factory_)
756 {
757    filename = deref_link(f.c_str());
758 }
759
760 string FCNode::getFilename() {
761    return filename;
762 }
763
764 string FCNode::getInterpreter() {
765    parsefile();
766
767    return interpreter_name;
768 }
769
770 void FCNode::getRegions(vector<SymRegion> &regs) {
771    parsefile();
772
773    regs = regions;
774 }
775
776 unsigned FCNode::getAddrSize() {
777    parsefile();
778
779    return addr_size;
780 }
781
782 Offset FCNode::get_r_debug() {
783    parsefile();
784
785    return r_debug_offset;
786 }
787
788 Offset FCNode::get_r_trap() {
789     parsefile();
790
791     return r_trap_offset;
792 }
793
794 void FCNode::markInterpreter() {
795    if (is_interpreter)
796       return;
797
798    assert(!parsed_file);
799    is_interpreter = true;
800 }
801
802 #define NUM_DBG_BREAK_NAMES 3
803 const char *dbg_break_names[] = { "_dl_debug_state",
804                                   "r_debug_state",
805                                   "_r_debug_state" };
806
807 void FCNode::parsefile()
808 {
809    if (parsed_file || parse_error)
810       return;
811    parsed_file = true;
812    
813    assert(!symreader);
814    symreader = factory->openSymbolReader(filename);
815    if (!symreader) {
816       parse_error = true;
817       translate_printf("[%s:%u] - Failed to open %s\n", __FILE__, __LINE__,
818                        filename.c_str());
819       return;
820    }
821
822    if (is_interpreter) {
823 #if !defined(os_freebsd)
824       //We're parsing the interpreter, don't confuse this with
825       // parsing the interpreter link info (which happens below).
826       Symbol_t r_debug_sym = symreader->getSymbolByName(R_DEBUG_NAME);
827       if (!symreader->isValidSymbol(r_debug_sym)) {
828          translate_printf("[%s:%u] - Failed to find r_debug symbol in %s\n",
829                           __FILE__, __LINE__, filename.c_str());
830          parse_error = true;
831       }
832       r_debug_offset = symreader->getSymbolOffset(r_debug_sym);
833 #else
834       r_trap_offset = 0;
835       for(unsigned i = 0; i < NUM_DBG_BREAK_NAMES; ++i) {
836           Symbol_t r_trap_sym = symreader->getSymbolByName(dbg_break_names[i]);
837           if( symreader->isValidSymbol(r_trap_sym) ) {
838               r_trap_offset = symreader->getSymbolOffset(r_trap_sym);
839               break;
840           }
841       }
842
843       if( !r_trap_offset ) {
844           translate_printf("[%s:%u] - Failed to find debugging trap symbol in %s\n",
845                   __FILE__, __LINE__, filename.c_str());
846           parse_error = true;
847       }
848 #endif
849    }
850
851    addr_size = symreader->getAddressWidth();   
852    interpreter_name = symreader->getInterpreterName();
853    
854    unsigned num_regions = symreader->numRegions();
855    for (unsigned i=0; i<num_regions; i++) {
856       SymRegion sr;
857       bool result = symreader->getRegion(i, sr);
858       if (!result) {
859          translate_printf("[%s:%u] - Failed to get region info\n",
860                           __FILE__, __LINE__);
861          parse_error = true;
862          break;
863       }
864       
865       regions.push_back(sr);
866    }
867    /*factory->closeSymbolReader(symreader);
868      symreader = NULL;*/
869 }
870
871 FCNode *FileCache::getNode(const string &filename, SymbolReaderFactory *factory)
872 {
873    struct stat buf;
874    int result = stat(filename.c_str(), &buf);
875    if (result == -1)
876       return NULL;
877    if (!filename.length())
878       return NULL;
879
880    for (unsigned i=0; i<nodes.size(); i++)
881    {
882       if (nodes[i]->inode == buf.st_ino &&
883           nodes[i]->device == buf.st_dev)
884       {
885          return nodes[i];
886       }
887    }
888
889    FCNode *fc = new FCNode(filename, buf.st_dev, buf.st_ino, factory);
890    nodes.push_back(fc);
891
892    return fc;
893 }
894
895 FileCache::FileCache()
896 {
897 }
898
899 Address AddressTranslateSysV::getLibraryTrapAddrSysV() {
900   return trap_addr;
901 }