Correcting declaration of variable for the value of DW_AT_comp_dir of Modules.
[dyninst.git] / symtabAPI / src / Module.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #include <string.h>
32 #include <common/src/debug_common.h>
33 #include "debug.h"
34
35 #include "Annotatable.h"
36 #include "Module.h"
37 #include "Symtab.h"
38 #include "Collections.h"
39 #include "Function.h"
40 #include "Variable.h"
41 #include "LineInformation.h"
42 #include "symutil.h"
43 #include "annotations.h"
44
45 #include "common/src/pathName.h"
46 #include "common/src/serialize.h"
47 #include "Object.h"
48 #include <boost/foreach.hpp>
49
50 #if defined(cap_dwarf)
51 #include "dwarfWalker.h"
52 #include "dwarf.h"
53 #endif
54
55 using namespace Dyninst;
56 using namespace Dyninst::SymtabAPI;
57 using namespace std;
58
59 static SymtabError serr;
60
61 StringTablePtr Statement::getStrings_() const {
62     return strings_;
63 }
64
65 void Statement::setStrings_(StringTablePtr strings) {
66     Statement::strings_ = strings;
67 }
68 std::string Statement::getFile() const {
69     if(strings_) {
70         if(file_index_ < strings_->size()) {
71             // can't be ->[] on shared pointer to multi_index container or compiler gets confused
72             return (*strings_)[file_index_].str;
73
74         }
75
76     }
77     return "";
78 }
79
80
81 string Module::getCompDir()
82 {
83     if(!compDir_.empty()) return compDir_;
84
85 #if defined(cap_dwarf)
86     if(info_.empty())
87     {
88         return "";
89     }
90
91     auto& cu = info_[0];
92     if(!dwarf_hasattr(&cu, DW_AT_comp_dir))
93     {
94         return "";
95     }
96
97     Dwarf_Attribute attr;
98     auto comp_dir = dwarf_formstring( dwarf_attr(&cu, DW_AT_comp_dir, &attr) );
99     compDir_ = std::string( comp_dir ? comp_dir : "" );
100     return compDir_;
101
102 #else
103     // TODO Implement this for non-dwarf format
104     return compDir_;
105 #endif
106 }
107
108
109 bool Module::findSymbol(std::vector<Symbol *> &found, 
110                         const std::string& name,
111                         Symbol::SymbolType sType, 
112                         NameType nameType,
113                         bool isRegex,
114                         bool checkCase,
115                         bool includeUndefined) {
116     unsigned orig_size = found.size();
117     std::vector<Symbol *> obj_syms;
118     
119     if (exec()->findSymbol(obj_syms, name, sType, nameType, isRegex, checkCase, includeUndefined)) {
120         return false;
121     }
122     
123     for (unsigned i = 0; i < obj_syms.size(); i++) {
124         if (obj_syms[i]->getModule() == this)
125             found.push_back(obj_syms[i]);
126     }
127     
128     if (found.size() > orig_size) 
129         return true;
130     
131     return false;        
132 }
133
134 bool Module::getAllSymbols(std::vector<Symbol *> &found) {
135     unsigned orig_size = found.size();
136     std::vector<Symbol *> obj_syms;
137     
138     if (!exec()->getAllSymbols(obj_syms)) {
139         return false;
140     }
141     
142     for (unsigned i = 0; i < obj_syms.size(); i++) {
143         if (obj_syms[i]->getModule() == this)
144             found.push_back(obj_syms[i]);
145     }
146     
147     if (found.size() > orig_size) 
148         return true;
149     
150     return false;        
151 }
152
153 const std::string &Module::fileName() const
154 {
155    return fileName_;
156 }
157
158 const std::string &Module::fullName() const
159 {
160    return fullName_;
161 }
162
163  Symtab *Module::exec() const
164 {
165    return exec_;
166 }
167
168 supportedLanguages Module::language() const
169 {
170    return language_;
171 }
172
173 bool Module::getAddressRanges(std::vector<AddressRange >&ranges,
174       std::string lineSource, unsigned int lineNo)
175 {
176    unsigned int originalSize = ranges.size();
177
178    LineInformation *lineInformation = parseLineInformation();
179    if (lineInformation)
180       lineInformation->getAddressRanges( lineSource.c_str(), lineNo, ranges );
181
182    if ( ranges.size() != originalSize )
183       return true;
184
185    return false;
186 }
187
188 bool Module::getSourceLines(std::vector<Statement::Ptr> &lines, Offset addressInRange)
189 {
190    unsigned int originalSize = lines.size();
191
192    LineInformation *lineInformation = parseLineInformation();
193    if (lineInformation)
194       lineInformation->getSourceLines( addressInRange, lines );
195
196    if ( lines.size() != originalSize )
197       return true;
198
199    return false;
200 }
201
202 bool Module::getSourceLines(std::vector<LineNoTuple> &lines, Offset addressInRange)
203 {
204    unsigned int originalSize = lines.size();
205
206     LineInformation *lineInformation = parseLineInformation();
207
208 //    cout << "Module " << fileName() << " searching for line info in " << lineInformation << endl;
209    if (lineInformation)
210       lineInformation->getSourceLines( addressInRange, lines );
211
212    if ( lines.size() != originalSize )
213       return true;
214    
215    return false;
216 }
217
218 LineInformation *Module::parseLineInformation() {
219     // Allocate if none
220     if (!lineInfo_)
221     {
222         lineInfo_ = new LineInformation;
223         // share our string table
224         lineInfo_->setStrings(strings_);
225     }
226     // Parse any CUs that have been added to our list
227     if(!info_.empty()) {
228         for(auto cu = info_.begin();
229                 cu != info_.end();
230                 ++cu)
231         {
232             exec()->getObject()->parseLineInfoForCU(*cu, lineInfo_);
233         }
234     }
235
236     // Before clearing the CU list (why is it even done anyway?), make sure to
237     // call getCompDir so the comp_dir is stored in a static variable.
238     getCompDir();
239
240     // Clear list of work to do
241     info_.clear();
242     return lineInfo_;
243 }
244
245 bool Module::getStatements(std::vector<LineInformation::Statement_t> &statements)
246 {
247         unsigned initial_size = statements.size();
248         LineInformation *li = parseLineInformation();
249     if(!li) return false;
250
251     std::copy(li->begin(), li->end(), std::back_inserter(statements));
252
253         return (statements.size() > initial_size);
254 }
255
256 vector<Type *> *Module::getAllTypes()
257 {
258         exec_->parseTypesNow();
259         if(typeInfo_) return typeInfo_->getAllTypes();
260         return NULL;
261         
262 }
263
264 vector<pair<string, Type *> > *Module::getAllGlobalVars()
265 {
266         exec_->parseTypesNow();
267         if(typeInfo_) return typeInfo_->getAllGlobalVariables();
268         return NULL;    
269 }
270
271 typeCollection *Module::getModuleTypes()
272 {
273         exec_->parseTypesNow();
274         return getModuleTypesPrivate();
275 }
276
277 typeCollection *Module::getModuleTypesPrivate()
278 {
279   return typeInfo_;
280 }
281
282 bool Module::findType(Type *&type, std::string name)
283 {
284         typeCollection *tc = getModuleTypes();
285         if (!tc) return false;
286
287    type = tc->findType(name);
288
289    if (type == NULL)
290       return false;
291
292    return true;
293 }
294
295 bool Module::findVariableType(Type *&type, std::string name)
296 {
297         typeCollection *tc = getModuleTypes();
298         if (!tc) return false;
299
300         type = tc->findVariableType(name);
301
302    if (type == NULL)
303       return false;
304
305    return true;
306 }
307
308
309 bool Module::setLineInfo(LineInformation *lineInfo)
310 {
311     assert(!lineInfo_);
312     //delete lineInfo_;
313     lineInfo_ = lineInfo;
314     return true;
315 }
316
317 LineInformation *Module::getLineInformation()
318 {
319   return lineInfo_;
320 }
321
322 bool Module::findLocalVariable(std::vector<localVar *>&vars, std::string name)
323 {
324         std::vector<Function *>mod_funcs;
325
326         if (!exec_->getAllFunctions(mod_funcs))
327         {
328                 return false;
329         }
330
331         unsigned origSize = vars.size();
332
333         for (unsigned int i = 0; i < mod_funcs.size(); i++)
334         {
335                 mod_funcs[i]->findLocalVariable(vars, name);
336         }
337
338         if (vars.size() > origSize)
339                 return true;
340
341         return false;
342 }
343
344 Module::Module(supportedLanguages lang, Offset adr,
345       std::string fullNm, Symtab *img) :
346    lineInfo_(NULL),
347    typeInfo_(NULL),
348    fullName_(fullNm),
349    compDir_(""),
350    language_(lang),
351    addr_(adr),
352    exec_(img),
353    strings_(new StringTable),
354    ranges_finalized(false)
355 {
356    fileName_ = extract_pathname_tail(fullNm);
357 }
358
359 Module::Module() :
360    lineInfo_(NULL),
361    typeInfo_(NULL),
362    fileName_(""),
363    fullName_(""),
364    compDir_(""),
365    language_(lang_Unknown),
366    addr_(0),
367    exec_(NULL),
368    strings_(new StringTable),
369     ranges_finalized(false)
370 {
371 }
372
373 Module::Module(const Module &mod) :
374    LookupInterface(),
375    lineInfo_(mod.lineInfo_),
376    typeInfo_(mod.typeInfo_),
377    info_(mod.info_),
378    fileName_(mod.fileName_),
379    fullName_(mod.fullName_),
380    compDir_(mod.compDir_),
381    language_(mod.language_),
382    addr_(mod.addr_),
383    exec_(mod.exec_),
384    strings_(mod.strings_),
385     ranges_finalized(mod.ranges_finalized)
386
387 {
388 }
389
390 Module::~Module()
391 {
392   delete lineInfo_;
393   delete typeInfo_;
394   
395 }
396
397 bool Module::isShared() const
398 {
399    return exec_->getObjectType() == obj_SharedLib;
400 }
401
402 bool Module::getAllSymbolsByType(std::vector<Symbol *> &found, Symbol::SymbolType sType)
403 {
404    unsigned orig_size = found.size();
405    std::vector<Symbol *> obj_syms;
406
407    if (!exec()->getAllSymbolsByType(obj_syms, sType))
408       return false;
409
410    for (unsigned i = 0; i < obj_syms.size(); i++) 
411    {
412       if (obj_syms[i]->getModule() == this)
413          found.push_back(obj_syms[i]);
414    }
415
416    if (found.size() > orig_size)
417    {
418       return true;
419    }
420
421    serr = No_Such_Symbol;
422    return false;
423 }
424
425 bool Module::getAllFunctions(std::vector<Function *> &ret)
426 {
427     return exec()->getAllFunctions(ret);
428 }
429
430 bool Module::operator==(Module &mod) 
431 {
432    if (exec_ && !mod.exec_) return false;
433    if (!exec_ && mod.exec_) return false;
434    if (exec_)
435    {
436            if (exec_->file() != mod.exec_->file()) return false;
437            if (exec_->name() != mod.exec_->name()) return false;
438    }
439
440    return (
441          (language_==mod.language_)
442          && (addr_==mod.addr_)
443          && (fullName_==mod.fullName_)
444          && (fileName_==mod.fileName_)
445          && (lineInfo_ == mod.lineInfo_)
446          );
447 }
448
449 bool Module::setName(std::string newName)
450 {
451    fullName_ = newName;
452    fileName_ = extract_pathname_tail(fullName_);
453    return true;
454 }
455
456 void Module::setLanguage(supportedLanguages lang)
457 {
458    language_ = lang;
459 }
460
461 Offset Module::addr() const
462 {
463    return addr_;
464 }
465
466 bool Module::setDefaultNamespacePrefix(string str)
467 {
468     return exec_->setDefaultNamespacePrefix(str);
469 }
470
471 bool Module::findVariablesByName(std::vector<Variable *> &ret, const std::string& name,
472                                  NameType nameType,
473                                  bool isRegex,
474                                  bool checkCase) {
475   bool succ = false;
476   std::vector<Variable *> tmp;
477
478   if (!exec()->findVariablesByName(tmp, name, nameType, isRegex, checkCase)) {
479     return false;
480   }
481   for (unsigned i = 0; i < tmp.size(); i++) {
482     if (tmp[i]->getModule() == this) {
483       ret.push_back(tmp[i]);
484       succ = true;
485     }
486   }
487   return succ;
488 }
489
490 void Module::addRange(Dyninst::Address low, Dyninst::Address high)
491 {
492     dwarf_printf("Adding range [%lx, %lx) to %s\n", low, high, fileName().c_str());
493     std::set<AddressRange>::iterator lb = ranges.lower_bound(AddressRange(low, high));
494     if(lb != ranges.end() && lb->first <= low)
495     {
496         if(lb->second >= high)
497         {
498             return;
499         }
500         ranges.insert(AddressRange(lb->first, high));
501 //        printf("Actual is [%lx, %lx) due to overlap with [%lx, %lx)\n", lb->first, high, lb->first, lb->second);
502         ranges.erase(lb);
503     }
504     else
505     {
506         ranges.insert(AddressRange(low, high));
507     }
508
509 //    ranges.push_back(std::make_pair(low, high));
510 //    exec_->mod_lookup()->insert(new ModRange(low, high, this));
511 }
512
513 void Module::finalizeRanges()
514 {
515     if(ranges.empty()) {
516         return;
517     }
518     auto bit = ranges.begin();
519     Address ext_s = bit->first;
520     Address ext_e = ext_s;
521
522     for( ; bit != ranges.end(); ++bit) {
523         if(bit->first > ext_e) {
524             finalizeOneRange(ext_s, ext_e);
525             ext_s = bit->first;
526         }
527         ext_e = bit->second;
528     }
529     finalizeOneRange(ext_s, ext_e);
530     ranges_finalized = true;
531     ranges.clear();
532 }
533
534 void Module::finalizeOneRange(Address ext_s, Address ext_e) const {
535     ModRange* r = new ModRange(ext_s, ext_e, const_cast<Module*>(this));
536     ModRangeLookup* lookup = exec_->mod_lookup();
537 //    cout << "Inserting range " << std::hex << (*r) << std::dec << endl;
538     lookup->insert(r);
539 }
540
541 void Module::addDebugInfo(Module::DebugInfoT info) {
542 //    cout << "Adding CU DIE to " << fileName() << endl;
543     info_.push_back(info);
544
545 }
546
547 StringTablePtr & Module::getStrings() {
548     return strings_;
549 }
550