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/Disassembler.h"
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/Section.h"
14 #include "lldb/Host/Host.h"
15 #include "lldb/Symbol/CompilerType.h"
16 #include "lldb/Symbol/CompileUnit.h"
17 #include "lldb/Symbol/LineTable.h"
18 #include "lldb/Symbol/SymbolFile.h"
19 #include "lldb/Symbol/SymbolVendor.h"
20 #include "llvm/Support/Casting.h"
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 
25 //----------------------------------------------------------------------
26 // Basic function information is contained in the FunctionInfo class.
27 // It is designed to contain the name, linkage name, and declaration
28 // location.
29 //----------------------------------------------------------------------
30 FunctionInfo::FunctionInfo (const char *name, const Declaration *decl_ptr) :
31     m_name(name),
32     m_declaration(decl_ptr)
33 {
34 }
35 
36 
37 FunctionInfo::FunctionInfo (const ConstString& name, const Declaration *decl_ptr) :
38     m_name(name),
39     m_declaration(decl_ptr)
40 {
41 }
42 
43 
44 FunctionInfo::~FunctionInfo()
45 {
46 }
47 
48 void
49 FunctionInfo::Dump(Stream *s, bool show_fullpaths) const
50 {
51     if (m_name)
52         *s << ", name = \"" << m_name << "\"";
53     m_declaration.Dump(s, show_fullpaths);
54 }
55 
56 
57 int
58 FunctionInfo::Compare(const FunctionInfo& a, const FunctionInfo& b)
59 {
60     int result = ConstString::Compare(a.GetName(), b.GetName());
61     if (result)
62         return result;
63 
64     return Declaration::Compare(a.m_declaration, b.m_declaration);
65 }
66 
67 
68 Declaration&
69 FunctionInfo::GetDeclaration()
70 {
71     return m_declaration;
72 }
73 
74 const Declaration&
75 FunctionInfo::GetDeclaration() const
76 {
77     return m_declaration;
78 }
79 
80 ConstString
81 FunctionInfo::GetName() const
82 {
83     return m_name;
84 }
85 
86 size_t
87 FunctionInfo::MemorySize() const
88 {
89     return m_name.MemorySize() + m_declaration.MemorySize();
90 }
91 
92 
93 InlineFunctionInfo::InlineFunctionInfo
94 (
95     const char *name,
96     const char *mangled,
97     const Declaration *decl_ptr,
98     const Declaration *call_decl_ptr
99 ) :
100     FunctionInfo(name, decl_ptr),
101     m_mangled(ConstString(mangled), true),
102     m_call_decl (call_decl_ptr)
103 {
104 }
105 
106 InlineFunctionInfo::InlineFunctionInfo
107 (
108     const ConstString& name,
109     const Mangled &mangled,
110     const Declaration *decl_ptr,
111     const Declaration *call_decl_ptr
112 ) :
113     FunctionInfo(name, decl_ptr),
114     m_mangled(mangled),
115     m_call_decl (call_decl_ptr)
116 {
117 }
118 
119 InlineFunctionInfo::~InlineFunctionInfo()
120 {
121 }
122 
123 int
124 InlineFunctionInfo::Compare(const InlineFunctionInfo& a, const InlineFunctionInfo& b)
125 {
126 
127     int result = FunctionInfo::Compare(a, b);
128     if (result)
129         return result;
130     // only compare the mangled names if both have them
131     return Mangled::Compare(a.m_mangled, a.m_mangled);
132 }
133 
134 void
135 InlineFunctionInfo::Dump(Stream *s, bool show_fullpaths) const
136 {
137     FunctionInfo::Dump(s, show_fullpaths);
138     if (m_mangled)
139         m_mangled.Dump(s);
140 }
141 
142 void
143 InlineFunctionInfo::DumpStopContext (Stream *s, LanguageType language) const
144 {
145 //    s->Indent("[inlined] ");
146     s->Indent();
147     if (m_mangled)
148         s->PutCString (m_mangled.GetName(language).AsCString());
149     else
150         s->PutCString (m_name.AsCString());
151 }
152 
153 
154 ConstString
155 InlineFunctionInfo::GetName (LanguageType language) const
156 {
157     if (m_mangled)
158         return m_mangled.GetName(language);
159     return m_name;
160 }
161 
162 ConstString
163 InlineFunctionInfo::GetDisplayName (LanguageType language) const
164 {
165     if (m_mangled)
166         return m_mangled.GetDisplayDemangledName(language);
167     return m_name;
168 }
169 
170 Declaration &
171 InlineFunctionInfo::GetCallSite ()
172 {
173     return m_call_decl;
174 }
175 
176 const Declaration &
177 InlineFunctionInfo::GetCallSite () const
178 {
179     return m_call_decl;
180 }
181 
182 
183 Mangled&
184 InlineFunctionInfo::GetMangled()
185 {
186     return m_mangled;
187 }
188 
189 const Mangled&
190 InlineFunctionInfo::GetMangled() const
191 {
192     return m_mangled;
193 }
194 
195 size_t
196 InlineFunctionInfo::MemorySize() const
197 {
198     return FunctionInfo::MemorySize() + m_mangled.MemorySize();
199 }
200 
201 //----------------------------------------------------------------------
202 //
203 //----------------------------------------------------------------------
204 Function::Function
205 (
206     CompileUnit *comp_unit,
207     lldb::user_id_t func_uid,
208     lldb::user_id_t type_uid,
209     const Mangled &mangled,
210     Type * type,
211     const AddressRange& range
212 ) :
213     UserID (func_uid),
214     m_comp_unit (comp_unit),
215     m_type_uid (type_uid),
216     m_type (type),
217     m_mangled (mangled),
218     m_block (func_uid),
219     m_range (range),
220     m_frame_base (),
221     m_flags (),
222     m_prologue_byte_size (0)
223 {
224     m_block.SetParentScope(this);
225     assert(comp_unit != nullptr);
226 }
227 
228 Function::Function
229 (
230     CompileUnit *comp_unit,
231     lldb::user_id_t func_uid,
232     lldb::user_id_t type_uid,
233     const char *mangled,
234     Type *type,
235     const AddressRange &range
236 ) :
237     UserID (func_uid),
238     m_comp_unit (comp_unit),
239     m_type_uid (type_uid),
240     m_type (type),
241     m_mangled (ConstString(mangled), true),
242     m_block (func_uid),
243     m_range (range),
244     m_frame_base (),
245     m_flags (),
246     m_prologue_byte_size (0)
247 {
248     m_block.SetParentScope(this);
249     assert(comp_unit != nullptr);
250 }
251 
252 
253 Function::~Function()
254 {
255 }
256 
257 void
258 Function::GetStartLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
259 {
260     line_no = 0;
261     source_file.Clear();
262 
263     if (m_comp_unit == nullptr)
264         return;
265 
266     if (m_type != nullptr && m_type->GetDeclaration().GetLine() != 0)
267     {
268         source_file = m_type->GetDeclaration().GetFile();
269         line_no = m_type->GetDeclaration().GetLine();
270     }
271     else
272     {
273         LineTable *line_table = m_comp_unit->GetLineTable();
274         if (line_table == nullptr)
275             return;
276 
277         LineEntry line_entry;
278         if (line_table->FindLineEntryByAddress (GetAddressRange().GetBaseAddress(), line_entry, nullptr))
279         {
280             line_no = line_entry.line;
281             source_file = line_entry.file;
282         }
283     }
284 }
285 
286 void
287 Function::GetEndLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
288 {
289     line_no = 0;
290     source_file.Clear();
291 
292     // The -1 is kind of cheesy, but I want to get the last line entry for the given function, not the
293     // first entry of the next.
294     Address scratch_addr(GetAddressRange().GetBaseAddress());
295     scratch_addr.SetOffset (scratch_addr.GetOffset() + GetAddressRange().GetByteSize() - 1);
296 
297     LineTable *line_table = m_comp_unit->GetLineTable();
298     if (line_table == nullptr)
299         return;
300 
301     LineEntry line_entry;
302     if (line_table->FindLineEntryByAddress (scratch_addr, line_entry, nullptr))
303     {
304         line_no = line_entry.line;
305         source_file = line_entry.file;
306     }
307 }
308 
309 Block &
310 Function::GetBlock (bool can_create)
311 {
312     if (!m_block.BlockInfoHasBeenParsed() && can_create)
313     {
314         SymbolContext sc;
315         CalculateSymbolContext(&sc);
316         if (sc.module_sp)
317         {
318             sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc);
319         }
320         else
321         {
322             Host::SystemLog (Host::eSystemLogError,
323                              "error: unable to find module shared pointer for function '%s' in %s\n",
324                              GetName().GetCString(),
325                              m_comp_unit->GetPath().c_str());
326         }
327         m_block.SetBlockInfoHasBeenParsed (true, true);
328     }
329     return m_block;
330 }
331 
332 CompileUnit*
333 Function::GetCompileUnit()
334 {
335     return m_comp_unit;
336 }
337 
338 const CompileUnit*
339 Function::GetCompileUnit() const
340 {
341     return m_comp_unit;
342 }
343 
344 
345 void
346 Function::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target)
347 {
348     Type* func_type = GetType();
349     const char *name = func_type ? func_type->GetName().AsCString() : "<unknown>";
350 
351     *s << "id = " << (const UserID&)*this << ", name = \"" << name << "\", range = ";
352 
353     Address::DumpStyle fallback_style;
354     if (level == eDescriptionLevelVerbose)
355         fallback_style = Address::DumpStyleModuleWithFileAddress;
356     else
357         fallback_style = Address::DumpStyleFileAddress;
358     GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, fallback_style);
359 }
360 
361 void
362 Function::Dump(Stream *s, bool show_context) const
363 {
364     s->Printf("%p: ", static_cast<const void*>(this));
365     s->Indent();
366     *s << "Function" << static_cast<const UserID&>(*this);
367 
368     m_mangled.Dump(s);
369 
370     if (m_type)
371         s->Printf(", type = %p", static_cast<void*>(m_type));
372     else if (m_type_uid != LLDB_INVALID_UID)
373         s->Printf(", type_uid = 0x%8.8" PRIx64, m_type_uid);
374 
375     s->EOL();
376     // Dump the root object
377     if (m_block.BlockInfoHasBeenParsed ())
378         m_block.Dump(s, m_range.GetBaseAddress().GetFileAddress(), INT_MAX, show_context);
379 }
380 
381 
382 void
383 Function::CalculateSymbolContext(SymbolContext* sc)
384 {
385     sc->function = this;
386     m_comp_unit->CalculateSymbolContext(sc);
387 }
388 
389 ModuleSP
390 Function::CalculateSymbolContextModule ()
391 {
392     SectionSP section_sp (m_range.GetBaseAddress().GetSection());
393     if (section_sp)
394         return section_sp->GetModule();
395 
396     return this->GetCompileUnit()->GetModule();
397 }
398 
399 CompileUnit *
400 Function::CalculateSymbolContextCompileUnit ()
401 {
402     return this->GetCompileUnit();
403 }
404 
405 Function *
406 Function::CalculateSymbolContextFunction ()
407 {
408     return this;
409 }
410 
411 lldb::DisassemblerSP
412 Function::GetInstructions (const ExecutionContext &exe_ctx,
413                            const char *flavor,
414                            bool prefer_file_cache)
415 {
416     ModuleSP module_sp (GetAddressRange().GetBaseAddress().GetModule());
417     if (module_sp)
418     {
419         const bool prefer_file_cache = false;
420         return Disassembler::DisassembleRange (module_sp->GetArchitecture(),
421                                                nullptr,
422                                                flavor,
423                                                exe_ctx,
424                                                GetAddressRange(),
425                                                prefer_file_cache);
426     }
427     return lldb::DisassemblerSP();
428 }
429 
430 bool
431 Function::GetDisassembly (const ExecutionContext &exe_ctx,
432                           const char *flavor,
433                           bool prefer_file_cache,
434                           Stream &strm)
435 {
436     lldb::DisassemblerSP disassembler_sp = GetInstructions (exe_ctx, flavor, prefer_file_cache);
437     if (disassembler_sp)
438     {
439         const bool show_address = true;
440         const bool show_bytes = false;
441         disassembler_sp->GetInstructionList().Dump (&strm, show_address, show_bytes, &exe_ctx);
442         return true;
443     }
444     return false;
445 }
446 
447 
448 //Symbol *
449 //Function::CalculateSymbolContextSymbol ()
450 //{
451 //    return // TODO: find the symbol for the function???
452 //}
453 
454 
455 void
456 Function::DumpSymbolContext(Stream *s)
457 {
458     m_comp_unit->DumpSymbolContext(s);
459     s->Printf(", Function{0x%8.8" PRIx64 "}", GetID());
460 }
461 
462 size_t
463 Function::MemorySize () const
464 {
465     size_t mem_size = sizeof(Function) + m_block.MemorySize();
466     return mem_size;
467 }
468 
469 bool
470 Function::GetIsOptimized ()
471 {
472     bool result = false;
473 
474     // Currently optimization is only indicted by the
475     // vendor extension DW_AT_APPLE_optimized which
476     // is set on a compile unit level.
477     if (m_comp_unit)
478     {
479         result = m_comp_unit->GetIsOptimized();
480     }
481     return result;
482 }
483 
484 ConstString
485 Function::GetDisplayName () const
486 {
487     if (!m_mangled)
488         return ConstString();
489     return m_mangled.GetDisplayDemangledName(GetLanguage());
490 }
491 
492 clang::DeclContext *
493 Function::GetClangDeclContext()
494 {
495     SymbolContext sc;
496 
497     CalculateSymbolContext (&sc);
498 
499     if (!sc.module_sp)
500         return nullptr;
501 
502     SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
503 
504     if (!sym_vendor)
505         return nullptr;
506 
507     SymbolFile *sym_file = sym_vendor->GetSymbolFile();
508 
509     if (!sym_file)
510         return nullptr;
511 
512     return sym_file->GetClangDeclContextForTypeUID (sc, m_uid);
513 }
514 
515 Type*
516 Function::GetType()
517 {
518     if (m_type == nullptr)
519     {
520         SymbolContext sc;
521 
522         CalculateSymbolContext (&sc);
523 
524         if (!sc.module_sp)
525             return nullptr;
526 
527         SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
528 
529         if (sym_vendor == nullptr)
530             return nullptr;
531 
532         SymbolFile *sym_file = sym_vendor->GetSymbolFile();
533 
534         if (sym_file == nullptr)
535             return nullptr;
536 
537         m_type = sym_file->ResolveTypeUID(m_type_uid);
538     }
539     return m_type;
540 }
541 
542 const Type*
543 Function::GetType() const
544 {
545     return m_type;
546 }
547 
548 CompilerType
549 Function::GetClangType()
550 {
551     Type *function_type = GetType();
552     if (function_type)
553         return function_type->GetClangFullType();
554     return CompilerType();
555 }
556 
557 uint32_t
558 Function::GetPrologueByteSize ()
559 {
560     if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize))
561     {
562         m_flags.Set(flagsCalculatedPrologueSize);
563         LineTable* line_table = m_comp_unit->GetLineTable ();
564         if (line_table)
565         {
566             LineEntry first_line_entry;
567             uint32_t first_line_entry_idx = UINT32_MAX;
568             if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), first_line_entry, &first_line_entry_idx))
569             {
570                 // Make sure the first line entry isn't already the end of the prologue
571                 addr_t prologue_end_file_addr = LLDB_INVALID_ADDRESS;
572                 if (first_line_entry.is_prologue_end)
573                 {
574                     prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress();
575                 }
576                 else
577                 {
578                     // Check the first few instructions and look for one that has
579                     // is_prologue_end set to true.
580                     const uint32_t last_line_entry_idx = first_line_entry_idx + 6;
581                     for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx)
582                     {
583                         LineEntry line_entry;
584                         if (line_table->GetLineEntryAtIndex (idx, line_entry))
585                         {
586                             if (line_entry.is_prologue_end)
587                             {
588                                 prologue_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress();
589                                 break;
590                             }
591                         }
592                     }
593                 }
594 
595                 // If we didn't find the end of the prologue in the line tables,
596                 // then just use the end address of the first line table entry
597                 if (prologue_end_file_addr == LLDB_INVALID_ADDRESS)
598                 {
599                     // Check the first few instructions and look for one that has
600                     // a line number that's different than the first entry.
601                     const uint32_t last_line_entry_idx = first_line_entry_idx + 6;
602                     for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx)
603                     {
604                         LineEntry line_entry;
605                         if (line_table->GetLineEntryAtIndex (idx, line_entry))
606                         {
607                             if (line_entry.line != first_line_entry.line)
608                             {
609                                 prologue_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress();
610                                 break;
611                             }
612                         }
613                     }
614 
615                     if (prologue_end_file_addr == LLDB_INVALID_ADDRESS)
616                     {
617                         prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress() + first_line_entry.range.GetByteSize();
618                     }
619                 }
620                 const addr_t func_start_file_addr = m_range.GetBaseAddress().GetFileAddress();
621                 const addr_t func_end_file_addr = func_start_file_addr + m_range.GetByteSize();
622 
623                 // Verify that this prologue end file address in the function's
624                 // address range just to be sure
625                 if (func_start_file_addr < prologue_end_file_addr && prologue_end_file_addr < func_end_file_addr)
626                 {
627                     m_prologue_byte_size = prologue_end_file_addr - func_start_file_addr;
628                 }
629             }
630         }
631     }
632     return m_prologue_byte_size;
633 }
634 
635 lldb::LanguageType
636 Function::GetLanguage() const
637 {
638     if (m_comp_unit)
639         return m_comp_unit->GetLanguage();
640     else
641         return lldb::eLanguageTypeUnknown;
642 }
643 
644 ConstString
645 Function::GetName() const
646 {
647     LanguageType language = lldb::eLanguageTypeUnknown;
648     if (m_comp_unit)
649         language = m_comp_unit->GetLanguage();
650     return m_mangled.GetName(language);
651 }
652 
653 ConstString
654 Function::GetNameNoArguments() const
655 {
656     LanguageType language = lldb::eLanguageTypeUnknown;
657     if (m_comp_unit)
658         language = m_comp_unit->GetLanguage();
659     return m_mangled.GetName(language, Mangled::ePreferDemangledWithoutArguments);
660 }
661 
662 
663 
664