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 (nullptr),
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 (nullptr),
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 CompilerDeclContext
493 Function::GetDeclContext()
494 {
495     ModuleSP module_sp = CalculateSymbolContextModule ();
496 
497     if (module_sp)
498     {
499         SymbolVendor *sym_vendor = module_sp->GetSymbolVendor();
500 
501         if (sym_vendor)
502         {
503             SymbolFile *sym_file = sym_vendor->GetSymbolFile();
504 
505             if (sym_file)
506                 return sym_file->GetDeclContextForUID (GetID());
507         }
508     }
509     return CompilerDeclContext();
510 }
511 
512 Type*
513 Function::GetType()
514 {
515     if (m_type == nullptr)
516     {
517         SymbolContext sc;
518 
519         CalculateSymbolContext (&sc);
520 
521         if (!sc.module_sp)
522             return nullptr;
523 
524         SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
525 
526         if (sym_vendor == nullptr)
527             return nullptr;
528 
529         SymbolFile *sym_file = sym_vendor->GetSymbolFile();
530 
531         if (sym_file == nullptr)
532             return nullptr;
533 
534         m_type = sym_file->ResolveTypeUID(m_type_uid);
535     }
536     return m_type;
537 }
538 
539 const Type*
540 Function::GetType() const
541 {
542     return m_type;
543 }
544 
545 CompilerType
546 Function::GetCompilerType()
547 {
548     Type *function_type = GetType();
549     if (function_type)
550         return function_type->GetFullCompilerType ();
551     return CompilerType();
552 }
553 
554 uint32_t
555 Function::GetPrologueByteSize ()
556 {
557     if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize))
558     {
559         m_flags.Set(flagsCalculatedPrologueSize);
560         LineTable* line_table = m_comp_unit->GetLineTable ();
561         if (line_table)
562         {
563             LineEntry first_line_entry;
564             uint32_t first_line_entry_idx = UINT32_MAX;
565             if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), first_line_entry, &first_line_entry_idx))
566             {
567                 // Make sure the first line entry isn't already the end of the prologue
568                 addr_t prologue_end_file_addr = LLDB_INVALID_ADDRESS;
569                 if (first_line_entry.is_prologue_end)
570                 {
571                     prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress();
572                 }
573                 else
574                 {
575                     // Check the first few instructions and look for one that has
576                     // is_prologue_end set to true.
577                     const uint32_t last_line_entry_idx = first_line_entry_idx + 6;
578                     for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx)
579                     {
580                         LineEntry line_entry;
581                         if (line_table->GetLineEntryAtIndex (idx, line_entry))
582                         {
583                             if (line_entry.is_prologue_end)
584                             {
585                                 prologue_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress();
586                                 break;
587                             }
588                         }
589                     }
590                 }
591 
592                 // If we didn't find the end of the prologue in the line tables,
593                 // then just use the end address of the first line table entry
594                 if (prologue_end_file_addr == LLDB_INVALID_ADDRESS)
595                 {
596                     // Check the first few instructions and look for one that has
597                     // a line number that's different than the first entry.
598                     const uint32_t last_line_entry_idx = first_line_entry_idx + 6;
599                     for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx)
600                     {
601                         LineEntry line_entry;
602                         if (line_table->GetLineEntryAtIndex (idx, line_entry))
603                         {
604                             if (line_entry.line != first_line_entry.line)
605                             {
606                                 prologue_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress();
607                                 break;
608                             }
609                         }
610                     }
611 
612                     if (prologue_end_file_addr == LLDB_INVALID_ADDRESS)
613                     {
614                         prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress() + first_line_entry.range.GetByteSize();
615                     }
616                 }
617                 const addr_t func_start_file_addr = m_range.GetBaseAddress().GetFileAddress();
618                 const addr_t func_end_file_addr = func_start_file_addr + m_range.GetByteSize();
619 
620                 // Verify that this prologue end file address in the function's
621                 // address range just to be sure
622                 if (func_start_file_addr < prologue_end_file_addr && prologue_end_file_addr < func_end_file_addr)
623                 {
624                     m_prologue_byte_size = prologue_end_file_addr - func_start_file_addr;
625                 }
626             }
627         }
628     }
629     return m_prologue_byte_size;
630 }
631 
632 lldb::LanguageType
633 Function::GetLanguage() const
634 {
635     if (m_comp_unit)
636         return m_comp_unit->GetLanguage();
637     else
638         return lldb::eLanguageTypeUnknown;
639 }
640 
641 ConstString
642 Function::GetName() const
643 {
644     LanguageType language = lldb::eLanguageTypeUnknown;
645     if (m_comp_unit)
646         language = m_comp_unit->GetLanguage();
647     return m_mangled.GetName(language);
648 }
649 
650 ConstString
651 Function::GetNameNoArguments() const
652 {
653     LanguageType language = lldb::eLanguageTypeUnknown;
654     if (m_comp_unit)
655         language = m_comp_unit->GetLanguage();
656     return m_mangled.GetName(language, Mangled::ePreferDemangledWithoutArguments);
657 }
658 
659 
660 
661