use dwarf_next_lines to read .debug_line without .debug_info
[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 const 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     // This string will be pointed to, so it has to persist.
78     static std::string emptyStr;
79     return emptyStr;
80 }
81
82
83 string Module::getCompDir()
84 {
85     if(!compDir_.empty()) return compDir_;
86
87 #if defined(cap_dwarf)
88     if(info_.empty())
89     {
90         return "";
91     }
92
93     auto& cu = info_[0];
94     if(!dwarf_hasattr(&cu, DW_AT_comp_dir))
95     {
96         return "";
97     }
98
99     Dwarf_Attribute attr;
100     auto comp_dir = dwarf_formstring( dwarf_attr(&cu, DW_AT_comp_dir, &attr) );
101     compDir_ = std::string( comp_dir ? comp_dir : "" );
102     return compDir_;
103
104 #else
105     // TODO Implement this for non-dwarf format
106     return compDir_;
107 #endif
108 }
109
110
111 bool Module::findSymbol(std::vector<Symbol *> &found, 
112                         const std::string& name,
113                         Symbol::SymbolType sType, 
114                         NameType nameType,
115                         bool isRegex,
116                         bool checkCase,
117                         bool includeUndefined) {
118     unsigned orig_size = found.size();
119     std::vector<Symbol *> obj_syms;
120     
121     if (exec()->findSymbol(obj_syms, name, sType, nameType, isRegex, checkCase, includeUndefined)) {
122         return false;
123     }
124     
125     for (unsigned i = 0; i < obj_syms.size(); i++) {
126         if (obj_syms[i]->getModule() == this)
127             found.push_back(obj_syms[i]);
128     }
129     
130     if (found.size() > orig_size) 
131         return true;
132     
133     return false;        
134 }
135
136 bool Module::getAllSymbols(std::vector<Symbol *> &found) {
137     unsigned orig_size = found.size();
138     std::vector<Symbol *> obj_syms;
139     
140     if (!exec()->getAllSymbols(obj_syms)) {
141         return false;
142     }
143     
144     for (unsigned i = 0; i < obj_syms.size(); i++) {
145         if (obj_syms[i]->getModule() == this)
146             found.push_back(obj_syms[i]);
147     }
148     
149     if (found.size() > orig_size) 
150         return true;
151     
152     return false;        
153 }
154
155 const std::string &Module::fileName() const
156 {
157    return fileName_;
158 }
159
160 const std::string &Module::fullName() const
161 {
162    return fullName_;
163 }
164
165  Symtab *Module::exec() const
166 {
167    return exec_;
168 }
169
170 supportedLanguages Module::language() const
171 {
172    return language_;
173 }
174
175 bool Module::getAddressRanges(std::vector<AddressRange >&ranges,
176       std::string lineSource, unsigned int lineNo)
177 {
178    unsigned int originalSize = ranges.size();
179
180    LineInformation *lineInformation = parseLineInformation();
181    if (lineInformation)
182       lineInformation->getAddressRanges( lineSource.c_str(), lineNo, ranges );
183
184    if ( ranges.size() != originalSize )
185       return true;
186
187    return false;
188 }
189
190 bool Module::getSourceLines(std::vector<Statement::Ptr> &lines, Offset addressInRange)
191 {
192    unsigned int originalSize = lines.size();
193
194    LineInformation *lineInformation = parseLineInformation();
195    if (lineInformation)
196       lineInformation->getSourceLines( addressInRange, lines );
197
198    if ( lines.size() != originalSize )
199       return true;
200
201    return false;
202 }
203
204 bool Module::getSourceLines(std::vector<LineNoTuple> &lines, Offset addressInRange)
205 {
206    unsigned int originalSize = lines.size();
207
208     LineInformation *lineInformation = parseLineInformation();
209
210 //    cout << "Module " << fileName() << " searching for line info in " << lineInformation << endl;
211    if (lineInformation)
212       lineInformation->getSourceLines( addressInRange, lines );
213
214    if ( lines.size() != originalSize )
215       return true;
216    
217    return false;
218 }
219
220 LineInformation *Module::parseLineInformation() {
221     // Allocate if none
222     if (!lineInfo_)
223     {
224         lineInfo_ = new LineInformation;
225         // share our string table
226         lineInfo_->setStrings(strings_);
227     }
228     if (exec()->getObject()->hasDebugInfo()) {
229         // Parse any CUs that have been added to our list
230         if(!info_.empty()) {
231             for(auto cu = info_.begin();
232                     cu != info_.end();
233                     ++cu)
234             {
235                 exec()->getObject()->parseLineInfoForCU(*cu, lineInfo_);
236             }
237         }
238
239         // Before clearing the CU list (why is it even done anyway?), make sure to
240         // call getCompDir so the comp_dir is stored in a static variable.
241         getCompDir();
242
243         // Clear list of work to do
244         info_.clear();
245     } else {
246         exec()->getObject()->parseLineInfo(lineInfo_);
247     }
248     return lineInfo_;
249 }
250
251 bool Module::getStatements(std::vector<LineInformation::Statement_t> &statements)
252 {
253         unsigned initial_size = statements.size();
254         LineInformation *li = parseLineInformation();
255     if(!li) return false;
256
257     std::copy(li->begin(), li->end(), std::back_inserter(statements));
258
259         return (statements.size() > initial_size);
260 }
261
262 vector<Type *> *Module::getAllTypes()
263 {
264         exec_->parseTypesNow();
265         if(typeInfo_) return typeInfo_->getAllTypes();
266         return NULL;
267         
268 }
269
270 vector<pair<string, Type *> > *Module::getAllGlobalVars()
271 {
272         exec_->parseTypesNow();
273         if(typeInfo_) return typeInfo_->getAllGlobalVariables();
274         return NULL;    
275 }
276
277 typeCollection *Module::getModuleTypes()
278 {
279         exec_->parseTypesNow();
280         return getModuleTypesPrivate();
281 }
282
283 typeCollection *Module::getModuleTypesPrivate()
284 {
285   return typeInfo_;
286 }
287
288 bool Module::findType(Type *&type, std::string name)
289 {
290         typeCollection *tc = getModuleTypes();
291         if (!tc) return false;
292
293    type = tc->findType(name);
294
295    if (type == NULL)
296       return false;
297
298    return true;
299 }
300
301 bool Module::findVariableType(Type *&type, std::string name)
302 {
303         typeCollection *tc = getModuleTypes();
304         if (!tc) return false;
305
306         type = tc->findVariableType(name);
307
308    if (type == NULL)
309       return false;
310
311    return true;
312 }
313
314
315 bool Module::setLineInfo(LineInformation *lineInfo)
316 {
317     assert(!lineInfo_);
318     //delete lineInfo_;
319     lineInfo_ = lineInfo;
320     return true;
321 }
322
323 LineInformation *Module::getLineInformation()
324 {
325   return lineInfo_;
326 }
327
328 bool Module::findLocalVariable(std::vector<localVar *>&vars, std::string name)
329 {
330         std::vector<Function *>mod_funcs;
331
332         if (!exec_->getAllFunctions(mod_funcs))
333         {
334                 return false;
335         }
336
337         unsigned origSize = vars.size();
338
339         for (unsigned int i = 0; i < mod_funcs.size(); i++)
340         {
341                 mod_funcs[i]->findLocalVariable(vars, name);
342         }
343
344         if (vars.size() > origSize)
345                 return true;
346
347         return false;
348 }
349
350 Module::Module(supportedLanguages lang, Offset adr,
351       std::string fullNm, Symtab *img) :
352    lineInfo_(NULL),
353    typeInfo_(NULL),
354    fullName_(fullNm),
355    compDir_(""),
356    language_(lang),
357    addr_(adr),
358    exec_(img),
359    strings_(new StringTable),
360    ranges_finalized(false)
361 {
362    fileName_ = extract_pathname_tail(fullNm);
363 }
364
365 Module::Module() :
366    lineInfo_(NULL),
367    typeInfo_(NULL),
368    fileName_(""),
369    fullName_(""),
370    compDir_(""),
371    language_(lang_Unknown),
372    addr_(0),
373    exec_(NULL),
374    strings_(new StringTable),
375     ranges_finalized(false)
376 {
377 }
378
379 Module::Module(const Module &mod) :
380    LookupInterface(),
381    lineInfo_(mod.lineInfo_),
382    typeInfo_(mod.typeInfo_),
383    info_(mod.info_),
384    fileName_(mod.fileName_),
385    fullName_(mod.fullName_),
386    compDir_(mod.compDir_),
387    language_(mod.language_),
388    addr_(mod.addr_),
389    exec_(mod.exec_),
390    strings_(mod.strings_),
391     ranges_finalized(mod.ranges_finalized)
392
393 {
394 }
395
396 Module::~Module()
397 {
398   delete lineInfo_;
399   delete typeInfo_;
400   
401 }
402
403 bool Module::isShared() const
404 {
405    return exec_->getObjectType() == obj_SharedLib;
406 }
407
408 bool Module::getAllSymbolsByType(std::vector<Symbol *> &found, Symbol::SymbolType sType)
409 {
410    unsigned orig_size = found.size();
411    std::vector<Symbol *> obj_syms;
412
413    if (!exec()->getAllSymbolsByType(obj_syms, sType))
414       return false;
415
416    for (unsigned i = 0; i < obj_syms.size(); i++) 
417    {
418       if (obj_syms[i]->getModule() == this)
419          found.push_back(obj_syms[i]);
420    }
421
422    if (found.size() > orig_size)
423    {
424       return true;
425    }
426
427    serr = No_Such_Symbol;
428    return false;
429 }
430
431 bool Module::getAllFunctions(std::vector<Function *> &ret)
432 {
433     return exec()->getAllFunctions(ret);
434 }
435
436 bool Module::operator==(Module &mod) 
437 {
438    if (exec_ && !mod.exec_) return false;
439    if (!exec_ && mod.exec_) return false;
440    if (exec_)
441    {
442            if (exec_->file() != mod.exec_->file()) return false;
443            if (exec_->name() != mod.exec_->name()) return false;
444    }
445
446    return (
447          (language_==mod.language_)
448          && (addr_==mod.addr_)
449          && (fullName_==mod.fullName_)
450          && (fileName_==mod.fileName_)
451          && (lineInfo_ == mod.lineInfo_)
452          );
453 }
454
455 bool Module::setName(std::string newName)
456 {
457    fullName_ = newName;
458    fileName_ = extract_pathname_tail(fullName_);
459    return true;
460 }
461
462 void Module::setLanguage(supportedLanguages lang)
463 {
464    language_ = lang;
465 }
466
467 Offset Module::addr() const
468 {
469    return addr_;
470 }
471
472 bool Module::setDefaultNamespacePrefix(string str)
473 {
474     return exec_->setDefaultNamespacePrefix(str);
475 }
476
477 bool Module::findVariablesByName(std::vector<Variable *> &ret, const std::string& name,
478                                  NameType nameType,
479                                  bool isRegex,
480                                  bool checkCase) {
481   bool succ = false;
482   std::vector<Variable *> tmp;
483
484   if (!exec()->findVariablesByName(tmp, name, nameType, isRegex, checkCase)) {
485     return false;
486   }
487   for (unsigned i = 0; i < tmp.size(); i++) {
488     if (tmp[i]->getModule() == this) {
489       ret.push_back(tmp[i]);
490       succ = true;
491     }
492   }
493   return succ;
494 }
495
496 void Module::addRange(Dyninst::Address low, Dyninst::Address high)
497 {
498     dwarf_printf("Adding range [%lx, %lx) to %s\n", low, high, fileName().c_str());
499     std::set<AddressRange>::iterator lb = ranges.lower_bound(AddressRange(low, high));
500     if(lb != ranges.end() && lb->first <= low)
501     {
502         if(lb->second >= high)
503         {
504             return;
505         }
506         ranges.insert(AddressRange(lb->first, high));
507 //        printf("Actual is [%lx, %lx) due to overlap with [%lx, %lx)\n", lb->first, high, lb->first, lb->second);
508         ranges.erase(lb);
509     }
510     else
511     {
512         ranges.insert(AddressRange(low, high));
513     }
514
515 //    ranges.push_back(std::make_pair(low, high));
516 //    exec_->mod_lookup()->insert(new ModRange(low, high, this));
517 }
518
519 void Module::finalizeRanges()
520 {
521     if(ranges.empty()) {
522         return;
523     }
524     auto bit = ranges.begin();
525     Address ext_s = bit->first;
526     Address ext_e = ext_s;
527
528     for( ; bit != ranges.end(); ++bit) {
529         if(bit->first > ext_e) {
530             finalizeOneRange(ext_s, ext_e);
531             ext_s = bit->first;
532         }
533         ext_e = bit->second;
534     }
535     finalizeOneRange(ext_s, ext_e);
536     ranges_finalized = true;
537     ranges.clear();
538 }
539
540 void Module::finalizeOneRange(Address ext_s, Address ext_e) const {
541     ModRange* r = new ModRange(ext_s, ext_e, const_cast<Module*>(this));
542     ModRangeLookup* lookup = exec_->mod_lookup();
543 //    cout << "Inserting range " << std::hex << (*r) << std::dec << endl;
544     lookup->insert(r);
545 }
546
547 void Module::addDebugInfo(Module::DebugInfoT info) {
548 //    cout << "Adding CU DIE to " << fileName() << endl;
549     info_.push_back(info);
550
551 }
552
553 StringTablePtr & Module::getStrings() {
554     return strings_;
555 }
556