1 //===-- Function.cpp --------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Symbol/Function.h"
11 #include "lldb/Core/Module.h"
12 #include "lldb/Core/Section.h"
13 #include "lldb/Symbol/ClangASTType.h"
14 #include "lldb/Symbol/ClangASTContext.h"
15 #include "lldb/Symbol/CompileUnit.h"
16 #include "lldb/Symbol/LineTable.h"
17 #include "lldb/Symbol/SymbolFile.h"
18 #include "lldb/Symbol/SymbolVendor.h"
19 #include "clang/AST/Type.h"
20 #include "clang/AST/CanonicalType.h"
21 #include "llvm/Support/Casting.h"
22 
23 using namespace lldb;
24 using namespace lldb_private;
25 
26 //----------------------------------------------------------------------
27 // Basic function information is contained in the FunctionInfo class.
28 // It is designed to contain the name, linkage name, and declaration
29 // location.
30 //----------------------------------------------------------------------
31 FunctionInfo::FunctionInfo (const char *name, const Declaration *decl_ptr) :
32     m_name(name),
33     m_declaration(decl_ptr)
34 {
35 }
36 
37 
38 FunctionInfo::FunctionInfo (const ConstString& name, const Declaration *decl_ptr) :
39     m_name(name),
40     m_declaration(decl_ptr)
41 {
42 }
43 
44 
45 FunctionInfo::~FunctionInfo()
46 {
47 }
48 
49 void
50 FunctionInfo::Dump(Stream *s, bool show_fullpaths) const
51 {
52     if (m_name)
53         *s << ", name = \"" << m_name << "\"";
54     m_declaration.Dump(s, show_fullpaths);
55 }
56 
57 
58 int
59 FunctionInfo::Compare(const FunctionInfo& a, const FunctionInfo& b)
60 {
61     int result = ConstString::Compare(a.GetName(), b.GetName());
62     if (result)
63         return result;
64 
65     return Declaration::Compare(a.m_declaration, b.m_declaration);
66 }
67 
68 
69 Declaration&
70 FunctionInfo::GetDeclaration()
71 {
72     return m_declaration;
73 }
74 
75 const Declaration&
76 FunctionInfo::GetDeclaration() const
77 {
78     return m_declaration;
79 }
80 
81 const ConstString&
82 FunctionInfo::GetName() const
83 {
84     return m_name;
85 }
86 
87 size_t
88 FunctionInfo::MemorySize() const
89 {
90     return m_name.MemorySize() + m_declaration.MemorySize();
91 }
92 
93 
94 InlineFunctionInfo::InlineFunctionInfo
95 (
96     const char *name,
97     const char *mangled,
98     const Declaration *decl_ptr,
99     const Declaration *call_decl_ptr
100 ) :
101     FunctionInfo(name, decl_ptr),
102     m_mangled(mangled, true),
103     m_call_decl (call_decl_ptr)
104 {
105 }
106 
107 InlineFunctionInfo::InlineFunctionInfo
108 (
109     const ConstString& name,
110     const Mangled &mangled,
111     const Declaration *decl_ptr,
112     const Declaration *call_decl_ptr
113 ) :
114     FunctionInfo(name, decl_ptr),
115     m_mangled(mangled),
116     m_call_decl (call_decl_ptr)
117 {
118 }
119 
120 InlineFunctionInfo::~InlineFunctionInfo()
121 {
122 }
123 
124 int
125 InlineFunctionInfo::Compare(const InlineFunctionInfo& a, const InlineFunctionInfo& b)
126 {
127 
128     int result = FunctionInfo::Compare(a, b);
129     if (result)
130         return result;
131     // only compare the mangled names if both have them
132     return Mangled::Compare(a.m_mangled, a.m_mangled);
133 }
134 
135 void
136 InlineFunctionInfo::Dump(Stream *s, bool show_fullpaths) const
137 {
138     FunctionInfo::Dump(s, show_fullpaths);
139     if (m_mangled)
140         m_mangled.Dump(s);
141 }
142 
143 void
144 InlineFunctionInfo::DumpStopContext (Stream *s) const
145 {
146 //    s->Indent("[inlined] ");
147     s->Indent();
148     if (m_mangled)
149         s->PutCString (m_mangled.GetName().AsCString());
150     else
151         s->PutCString (m_name.AsCString());
152 }
153 
154 
155 const ConstString &
156 InlineFunctionInfo::GetName () const
157 {
158     if (m_mangled)
159         return m_mangled.GetName();
160     return m_name;
161 }
162 
163 
164 Declaration &
165 InlineFunctionInfo::GetCallSite ()
166 {
167     return m_call_decl;
168 }
169 
170 const Declaration &
171 InlineFunctionInfo::GetCallSite () const
172 {
173     return m_call_decl;
174 }
175 
176 
177 Mangled&
178 InlineFunctionInfo::GetMangled()
179 {
180     return m_mangled;
181 }
182 
183 const Mangled&
184 InlineFunctionInfo::GetMangled() const
185 {
186     return m_mangled;
187 }
188 
189 size_t
190 InlineFunctionInfo::MemorySize() const
191 {
192     return FunctionInfo::MemorySize() + m_mangled.MemorySize();
193 }
194 
195 //----------------------------------------------------------------------
196 //
197 //----------------------------------------------------------------------
198 Function::Function
199 (
200     CompileUnit *comp_unit,
201     lldb::user_id_t func_uid,
202     lldb::user_id_t type_uid,
203     const Mangled &mangled,
204     Type * type,
205     const AddressRange& range
206 ) :
207     UserID (func_uid),
208     m_comp_unit (comp_unit),
209     m_type_uid (type_uid),
210     m_type (type),
211     m_mangled (mangled),
212     m_block (func_uid),
213     m_range (range),
214     m_frame_base (),
215     m_flags (),
216     m_prologue_byte_size (0)
217 {
218     m_block.SetParentScope(this);
219     assert(comp_unit != NULL);
220 }
221 
222 Function::Function
223 (
224     CompileUnit *comp_unit,
225     lldb::user_id_t func_uid,
226     lldb::user_id_t type_uid,
227     const char *mangled,
228     Type *type,
229     const AddressRange &range
230 ) :
231     UserID (func_uid),
232     m_comp_unit (comp_unit),
233     m_type_uid (type_uid),
234     m_type (type),
235     m_mangled (mangled, true),
236     m_block (func_uid),
237     m_range (range),
238     m_frame_base (),
239     m_flags (),
240     m_prologue_byte_size (0)
241 {
242     m_block.SetParentScope(this);
243     assert(comp_unit != NULL);
244 }
245 
246 
247 Function::~Function()
248 {
249 }
250 
251 void
252 Function::GetStartLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
253 {
254     line_no = 0;
255     source_file.Clear();
256 
257     if (m_comp_unit == NULL)
258         return;
259 
260     if (m_type != NULL && m_type->GetDeclaration().GetLine() != 0)
261     {
262         source_file = m_type->GetDeclaration().GetFile();
263         line_no = m_type->GetDeclaration().GetLine();
264     }
265     else
266     {
267         LineTable *line_table = m_comp_unit->GetLineTable();
268         if (line_table == NULL)
269             return;
270 
271         LineEntry line_entry;
272         if (line_table->FindLineEntryByAddress (GetAddressRange().GetBaseAddress(), line_entry, NULL))
273         {
274             line_no = line_entry.line;
275             source_file = line_entry.file;
276         }
277     }
278 }
279 
280 void
281 Function::GetEndLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
282 {
283     line_no = 0;
284     source_file.Clear();
285 
286     // The -1 is kind of cheesy, but I want to get the last line entry for the given function, not the
287     // first entry of the next.
288     Address scratch_addr(GetAddressRange().GetBaseAddress());
289     scratch_addr.SetOffset (scratch_addr.GetOffset() + GetAddressRange().GetByteSize() - 1);
290 
291     LineTable *line_table = m_comp_unit->GetLineTable();
292     if (line_table == NULL)
293         return;
294 
295     LineEntry line_entry;
296     if (line_table->FindLineEntryByAddress (scratch_addr, line_entry, NULL))
297     {
298         line_no = line_entry.line;
299         source_file = line_entry.file;
300     }
301 }
302 
303 Block &
304 Function::GetBlock (bool can_create)
305 {
306     if (!m_block.BlockInfoHasBeenParsed() && can_create)
307     {
308         SymbolContext sc;
309         CalculateSymbolContext(&sc);
310         if (sc.module_sp)
311         {
312             sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc);
313         }
314         else
315         {
316             ::fprintf (stderr,
317                        "unable to find module shared pointer for function '%s' in %s%s%s\n",
318                        GetName().GetCString(),
319                        m_comp_unit->GetDirectory().GetCString(),
320                        m_comp_unit->GetDirectory() ? "/" : "",
321                        m_comp_unit->GetFilename().GetCString());
322         }
323         m_block.SetBlockInfoHasBeenParsed (true, true);
324     }
325     return m_block;
326 }
327 
328 CompileUnit*
329 Function::GetCompileUnit()
330 {
331     return m_comp_unit;
332 }
333 
334 const CompileUnit*
335 Function::GetCompileUnit() const
336 {
337     return m_comp_unit;
338 }
339 
340 
341 void
342 Function::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target)
343 {
344     Type* func_type = GetType();
345     *s << "id = " << (const UserID&)*this << ", name = \"" << func_type->GetName() << "\", range = ";
346 
347     Address::DumpStyle fallback_style;
348     if (level == eDescriptionLevelVerbose)
349         fallback_style = Address::DumpStyleModuleWithFileAddress;
350     else
351         fallback_style = Address::DumpStyleFileAddress;
352     GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, fallback_style);
353 }
354 
355 void
356 Function::Dump(Stream *s, bool show_context) const
357 {
358     s->Printf("%p: ", this);
359     s->Indent();
360     *s << "Function" << (const UserID&)*this;
361 
362     m_mangled.Dump(s);
363 
364     if (m_type)
365     {
366         s->Printf(", type = %p", m_type);
367     }
368     else if (m_type_uid != LLDB_INVALID_UID)
369     {
370         s->Printf(", type_uid = 0x%8.8x", m_type_uid);
371     }
372 
373     s->EOL();
374     // Dump the root object
375     if (m_block.BlockInfoHasBeenParsed ())
376         m_block.Dump(s, m_range.GetBaseAddress().GetFileAddress(), INT_MAX, show_context);
377 }
378 
379 
380 void
381 Function::CalculateSymbolContext(SymbolContext* sc)
382 {
383     sc->function = this;
384     m_comp_unit->CalculateSymbolContext(sc);
385 }
386 
387 Module *
388 Function::CalculateSymbolContextModule ()
389 {
390     const Section *section = m_range.GetBaseAddress().GetSection();
391     if (section)
392     {
393         const Section *linked_section = section->GetLinkedSection();
394         if (linked_section)
395             return linked_section->GetModule();
396         else
397             return section->GetModule();
398     }
399 
400     return this->GetCompileUnit()->GetModule();
401 }
402 
403 CompileUnit *
404 Function::CalculateSymbolContextCompileUnit ()
405 {
406     return this->GetCompileUnit();
407 }
408 
409 Function *
410 Function::CalculateSymbolContextFunction ()
411 {
412     return this;
413 }
414 
415 //Symbol *
416 //Function::CalculateSymbolContextSymbol ()
417 //{
418 //    return // TODO: find the symbol for the function???
419 //}
420 
421 
422 void
423 Function::DumpSymbolContext(Stream *s)
424 {
425     m_comp_unit->DumpSymbolContext(s);
426     s->Printf(", Function{0x%8.8x}", GetID());
427 }
428 
429 size_t
430 Function::MemorySize () const
431 {
432     size_t mem_size = sizeof(Function) + m_block.MemorySize();
433     return mem_size;
434 }
435 
436 clang::DeclContext *
437 Function::GetClangDeclContext()
438 {
439     SymbolContext sc;
440 
441     CalculateSymbolContext (&sc);
442 
443     if (!sc.module_sp)
444         return NULL;
445 
446     SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
447 
448     if (!sym_vendor)
449         return NULL;
450 
451     SymbolFile *sym_file = sym_vendor->GetSymbolFile();
452 
453     if (!sym_file)
454         return NULL;
455 
456     return sym_file->GetClangDeclContextForTypeUID (sc, m_uid);
457 }
458 
459 Type*
460 Function::GetType()
461 {
462     if (m_type == NULL)
463     {
464         SymbolContext sc;
465 
466         CalculateSymbolContext (&sc);
467 
468         if (!sc.module_sp)
469             return NULL;
470 
471         SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
472 
473         if (sym_vendor == NULL)
474             return NULL;
475 
476         SymbolFile *sym_file = sym_vendor->GetSymbolFile();
477 
478         if (sym_file == NULL)
479             return NULL;
480 
481         m_type = sym_file->ResolveTypeUID(m_type_uid);
482     }
483     return m_type;
484 }
485 
486 const Type*
487 Function::GetType() const
488 {
489     return m_type;
490 }
491 
492 clang_type_t
493 Function::GetReturnClangType ()
494 {
495     clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetClangFullType()));
496     const clang::FunctionType *function_type = llvm::dyn_cast<clang::FunctionType> (clang_type);
497     if (function_type)
498         return function_type->getResultType().getAsOpaquePtr();
499     return NULL;
500 }
501 
502 int
503 Function::GetArgumentCount ()
504 {
505     clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetClangFullType()));
506     assert (clang_type->isFunctionType());
507     if (!clang_type->isFunctionProtoType())
508         return -1;
509 
510     const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast<clang::FunctionProtoType>(clang_type);
511     if (function_proto_type != NULL)
512         return function_proto_type->getNumArgs();
513 
514     return 0;
515 }
516 
517 clang_type_t
518 Function::GetArgumentTypeAtIndex (size_t idx)
519 {
520     clang::QualType clang_type (clang::QualType::getFromOpaquePtr(GetType()->GetClangFullType()));
521     const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast<clang::FunctionProtoType>(clang_type);
522     if (function_proto_type)
523     {
524         unsigned num_args = function_proto_type->getNumArgs();
525         if (idx >= num_args)
526             return NULL;
527 
528         return (function_proto_type->arg_type_begin())[idx].getAsOpaquePtr();
529     }
530     return NULL;
531 }
532 
533 bool
534 Function::IsVariadic ()
535 {
536    const clang::Type *clang_type = static_cast<clang::QualType *>(GetType()->GetClangFullType())->getTypePtr();
537    assert (clang_type->isFunctionType());
538    if (!clang_type->isFunctionProtoType())
539         return false;
540 
541     const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast<clang::FunctionProtoType>(clang_type);
542     if (function_proto_type)
543         return function_proto_type->isVariadic();
544 
545     return false;
546 }
547 
548 uint32_t
549 Function::GetPrologueByteSize ()
550 {
551     if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize))
552     {
553         m_flags.Set(flagsCalculatedPrologueSize);
554         LineTable* line_table = m_comp_unit->GetLineTable ();
555         if (line_table)
556         {
557             LineEntry line_entry;
558             if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), line_entry))
559             {
560                 // We need to take the delta of the end of the first line entry
561                 // as a file address and the start file address of the function
562                 // in case the first line entry doesn't start at the beginning
563                 // of the function.
564                 const addr_t func_start_file_addr = m_range.GetBaseAddress().GetFileAddress();
565                 const addr_t line_entry_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress() + line_entry.range.GetByteSize();
566                 if (line_entry_end_file_addr > func_start_file_addr)
567                     m_prologue_byte_size = line_entry_end_file_addr - func_start_file_addr;
568             }
569         }
570     }
571     return m_prologue_byte_size;
572 }
573 
574 
575 
576