]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Symbol/Function.cpp
Vendor import of lldb release_39 branch r276489:
[FreeBSD/FreeBSD.git] / source / Symbol / Function.cpp
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 "lldb/Target/Language.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 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(ConstString(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, LanguageType language) const
145 {
146 //    s->Indent("[inlined] ");
147     s->Indent();
148     if (m_mangled)
149         s->PutCString (m_mangled.GetName(language).AsCString());
150     else
151         s->PutCString (m_name.AsCString());
152 }
153
154
155 ConstString
156 InlineFunctionInfo::GetName (LanguageType language) const
157 {
158     if (m_mangled)
159         return m_mangled.GetName(language);
160     return m_name;
161 }
162
163 ConstString
164 InlineFunctionInfo::GetDisplayName (LanguageType language) const
165 {
166     if (m_mangled)
167         return m_mangled.GetDisplayDemangledName(language);
168     return m_name;
169 }
170
171 Declaration &
172 InlineFunctionInfo::GetCallSite ()
173 {
174     return m_call_decl;
175 }
176
177 const Declaration &
178 InlineFunctionInfo::GetCallSite () const
179 {
180     return m_call_decl;
181 }
182
183
184 Mangled&
185 InlineFunctionInfo::GetMangled()
186 {
187     return m_mangled;
188 }
189
190 const Mangled&
191 InlineFunctionInfo::GetMangled() const
192 {
193     return m_mangled;
194 }
195
196 size_t
197 InlineFunctionInfo::MemorySize() const
198 {
199     return FunctionInfo::MemorySize() + m_mangled.MemorySize();
200 }
201
202 //----------------------------------------------------------------------
203 //
204 //----------------------------------------------------------------------
205 Function::Function
206 (
207     CompileUnit *comp_unit,
208     lldb::user_id_t func_uid,
209     lldb::user_id_t type_uid,
210     const Mangled &mangled,
211     Type * type,
212     const AddressRange& range
213 ) :
214     UserID (func_uid),
215     m_comp_unit (comp_unit),
216     m_type_uid (type_uid),
217     m_type (type),
218     m_mangled (mangled),
219     m_block (func_uid),
220     m_range (range),
221     m_frame_base (nullptr),
222     m_flags (),
223     m_prologue_byte_size (0)
224 {
225     m_block.SetParentScope(this);
226     assert(comp_unit != nullptr);
227 }
228
229 Function::Function
230 (
231     CompileUnit *comp_unit,
232     lldb::user_id_t func_uid,
233     lldb::user_id_t type_uid,
234     const char *mangled,
235     Type *type,
236     const AddressRange &range
237 ) :
238     UserID (func_uid),
239     m_comp_unit (comp_unit),
240     m_type_uid (type_uid),
241     m_type (type),
242     m_mangled (ConstString(mangled), true),
243     m_block (func_uid),
244     m_range (range),
245     m_frame_base (nullptr),
246     m_flags (),
247     m_prologue_byte_size (0)
248 {
249     m_block.SetParentScope(this);
250     assert(comp_unit != nullptr);
251 }
252
253
254 Function::~Function()
255 {
256 }
257
258 void
259 Function::GetStartLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
260 {
261     line_no = 0;
262     source_file.Clear();
263     
264     if (m_comp_unit == nullptr)
265         return;
266         
267     if (m_type != nullptr && m_type->GetDeclaration().GetLine() != 0)
268     {
269         source_file = m_type->GetDeclaration().GetFile();
270         line_no = m_type->GetDeclaration().GetLine();
271     }
272     else 
273     {
274         LineTable *line_table = m_comp_unit->GetLineTable();
275         if (line_table == nullptr)
276             return;
277             
278         LineEntry line_entry;
279         if (line_table->FindLineEntryByAddress (GetAddressRange().GetBaseAddress(), line_entry, nullptr))
280         {
281             line_no = line_entry.line;
282             source_file = line_entry.file;
283         }
284     }
285 }
286
287 void
288 Function::GetEndLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
289 {
290     line_no = 0;
291     source_file.Clear();
292     
293     // The -1 is kind of cheesy, but I want to get the last line entry for the given function, not the 
294     // first entry of the next.
295     Address scratch_addr(GetAddressRange().GetBaseAddress());
296     scratch_addr.SetOffset (scratch_addr.GetOffset() + GetAddressRange().GetByteSize() - 1);
297     
298     LineTable *line_table = m_comp_unit->GetLineTable();
299     if (line_table == nullptr)
300         return;
301         
302     LineEntry line_entry;
303     if (line_table->FindLineEntryByAddress (scratch_addr, line_entry, nullptr))
304     {
305         line_no = line_entry.line;
306         source_file = line_entry.file;
307     }
308 }
309
310 Block &
311 Function::GetBlock (bool can_create)
312 {
313     if (!m_block.BlockInfoHasBeenParsed() && can_create)
314     {
315         SymbolContext sc;
316         CalculateSymbolContext(&sc);
317         if (sc.module_sp)
318         {
319             sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc);
320         }
321         else
322         {
323             Host::SystemLog (Host::eSystemLogError, 
324                              "error: unable to find module shared pointer for function '%s' in %s\n", 
325                              GetName().GetCString(),
326                              m_comp_unit->GetPath().c_str());
327         }
328         m_block.SetBlockInfoHasBeenParsed (true, true);
329     }
330     return m_block;
331 }
332
333 CompileUnit*
334 Function::GetCompileUnit()
335 {
336     return m_comp_unit;
337 }
338
339 const CompileUnit*
340 Function::GetCompileUnit() const
341 {
342     return m_comp_unit;
343 }
344
345
346 void
347 Function::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target)
348 {
349     Type* func_type = GetType();
350     const char *name = func_type ? func_type->GetName().AsCString() : "<unknown>";
351     
352     *s << "id = " << (const UserID&)*this << ", name = \"" << name << "\", range = ";
353     
354     Address::DumpStyle fallback_style;
355     if (level == eDescriptionLevelVerbose)
356         fallback_style = Address::DumpStyleModuleWithFileAddress;
357     else
358         fallback_style = Address::DumpStyleFileAddress;
359     GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, fallback_style);
360 }
361
362 void
363 Function::Dump(Stream *s, bool show_context) const
364 {
365     s->Printf("%p: ", static_cast<const void*>(this));
366     s->Indent();
367     *s << "Function" << static_cast<const UserID&>(*this);
368
369     m_mangled.Dump(s);
370
371     if (m_type)
372         s->Printf(", type = %p", static_cast<void*>(m_type));
373     else if (m_type_uid != LLDB_INVALID_UID)
374         s->Printf(", type_uid = 0x%8.8" PRIx64, m_type_uid);
375
376     s->EOL();
377     // Dump the root object
378     if (m_block.BlockInfoHasBeenParsed ())
379         m_block.Dump(s, m_range.GetBaseAddress().GetFileAddress(), INT_MAX, show_context);
380 }
381
382
383 void
384 Function::CalculateSymbolContext(SymbolContext* sc)
385 {
386     sc->function = this;
387     m_comp_unit->CalculateSymbolContext(sc);
388 }
389
390 ModuleSP
391 Function::CalculateSymbolContextModule ()
392 {
393     SectionSP section_sp (m_range.GetBaseAddress().GetSection());
394     if (section_sp)
395         return section_sp->GetModule();
396     
397     return this->GetCompileUnit()->GetModule();
398 }
399
400 CompileUnit *
401 Function::CalculateSymbolContextCompileUnit ()
402 {
403     return this->GetCompileUnit();
404 }
405
406 Function *
407 Function::CalculateSymbolContextFunction ()
408 {
409     return this;
410 }
411
412 lldb::DisassemblerSP
413 Function::GetInstructions (const ExecutionContext &exe_ctx,
414                            const char *flavor,
415                            bool prefer_file_cache)
416 {
417     ModuleSP module_sp (GetAddressRange().GetBaseAddress().GetModule());
418     if (module_sp)
419     {
420         const bool prefer_file_cache = false;
421         return Disassembler::DisassembleRange (module_sp->GetArchitecture(),
422                                                nullptr,
423                                                flavor,
424                                                exe_ctx,
425                                                GetAddressRange(),
426                                                prefer_file_cache);
427     }
428     return lldb::DisassemblerSP();
429 }
430
431 bool
432 Function::GetDisassembly (const ExecutionContext &exe_ctx,
433                           const char *flavor,
434                           bool prefer_file_cache,
435                           Stream &strm)
436 {
437     lldb::DisassemblerSP disassembler_sp = GetInstructions (exe_ctx, flavor, prefer_file_cache);
438     if (disassembler_sp)
439     {
440         const bool show_address = true;
441         const bool show_bytes = false;
442         disassembler_sp->GetInstructionList().Dump (&strm, show_address, show_bytes, &exe_ctx);
443         return true;
444     }
445     return false;
446 }
447
448
449 //Symbol *
450 //Function::CalculateSymbolContextSymbol ()
451 //{
452 //    return // TODO: find the symbol for the function???
453 //}
454
455
456 void
457 Function::DumpSymbolContext(Stream *s)
458 {
459     m_comp_unit->DumpSymbolContext(s);
460     s->Printf(", Function{0x%8.8" PRIx64 "}", GetID());
461 }
462
463 size_t
464 Function::MemorySize () const
465 {
466     size_t mem_size = sizeof(Function) + m_block.MemorySize();
467     return mem_size;
468 }
469
470 bool
471 Function::GetIsOptimized ()
472 {
473     bool result = false;
474
475     // Currently optimization is only indicted by the
476     // vendor extension DW_AT_APPLE_optimized which
477     // is set on a compile unit level.
478     if (m_comp_unit)
479     {
480         result = m_comp_unit->GetIsOptimized();
481     }
482     return result;
483 }
484
485 bool
486 Function::IsTopLevelFunction ()
487 {
488     bool result = false;
489     
490     if (Language* language = Language::FindPlugin(GetLanguage()))
491         result = language->IsTopLevelFunction(*this);
492     
493     return result;
494 }
495
496 ConstString
497 Function::GetDisplayName () const
498 {
499     if (!m_mangled)
500         return ConstString();
501     return m_mangled.GetDisplayDemangledName(GetLanguage());
502 }
503
504 CompilerDeclContext
505 Function::GetDeclContext()
506 {
507     ModuleSP module_sp = CalculateSymbolContextModule ();
508
509     if (module_sp)
510     {
511         SymbolVendor *sym_vendor = module_sp->GetSymbolVendor();
512
513         if (sym_vendor)
514         {
515             SymbolFile *sym_file = sym_vendor->GetSymbolFile();
516
517             if (sym_file)
518                 return sym_file->GetDeclContextForUID (GetID());
519         }
520     }
521     return CompilerDeclContext();
522 }
523
524 Type*
525 Function::GetType()
526 {
527     if (m_type == nullptr)
528     {
529         SymbolContext sc;
530         
531         CalculateSymbolContext (&sc);
532         
533         if (!sc.module_sp)
534             return nullptr;
535         
536         SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
537         
538         if (sym_vendor == nullptr)
539             return nullptr;
540         
541         SymbolFile *sym_file = sym_vendor->GetSymbolFile();
542         
543         if (sym_file == nullptr)
544             return nullptr;
545         
546         m_type = sym_file->ResolveTypeUID(m_type_uid);
547     }
548     return m_type;
549 }
550
551 const Type*
552 Function::GetType() const
553 {
554     return m_type;
555 }
556
557 CompilerType
558 Function::GetCompilerType()
559 {
560     Type *function_type = GetType();
561     if (function_type)
562         return function_type->GetFullCompilerType ();
563     return CompilerType();
564 }
565
566 uint32_t
567 Function::GetPrologueByteSize ()
568 {
569     if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize))
570     {
571         m_flags.Set(flagsCalculatedPrologueSize);
572         LineTable* line_table = m_comp_unit->GetLineTable ();
573         uint32_t prologue_end_line_idx = 0;
574         
575         if (line_table)
576         {
577             LineEntry first_line_entry;
578             uint32_t first_line_entry_idx = UINT32_MAX;
579             if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), first_line_entry, &first_line_entry_idx))
580             {
581                 // Make sure the first line entry isn't already the end of the prologue
582                 addr_t prologue_end_file_addr = LLDB_INVALID_ADDRESS;
583                 addr_t line_zero_end_file_addr = LLDB_INVALID_ADDRESS;
584                 
585                 if (first_line_entry.is_prologue_end)
586                 {
587                     prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress();
588                     prologue_end_line_idx = first_line_entry_idx;
589                 }
590                 else
591                 {
592                     // Check the first few instructions and look for one that has
593                     // is_prologue_end set to true.
594                     const uint32_t last_line_entry_idx = first_line_entry_idx + 6;
595                     for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx)
596                     {
597                         LineEntry line_entry;
598                         if (line_table->GetLineEntryAtIndex (idx, line_entry))
599                         {
600                             if (line_entry.is_prologue_end)
601                             {
602                                 prologue_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress();
603                                 prologue_end_line_idx = idx;
604                                 break;
605                             }
606                         }
607                     }
608                 }
609
610                 // If we didn't find the end of the prologue in the line tables,
611                 // then just use the end address of the first line table entry
612                 if (prologue_end_file_addr == LLDB_INVALID_ADDRESS)
613                 {
614                     // Check the first few instructions and look for one that has
615                     // a line number that's different than the first entry.
616                     uint32_t last_line_entry_idx = first_line_entry_idx + 6;
617                     for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx)
618                     {
619                         LineEntry line_entry;
620                         if (line_table->GetLineEntryAtIndex (idx, line_entry))
621                         {
622                             if (line_entry.line != first_line_entry.line)
623                             {
624                                 prologue_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress();
625                                 prologue_end_line_idx = idx;
626                                 break;
627                             }
628                         }
629                     }
630
631                     if (prologue_end_file_addr == LLDB_INVALID_ADDRESS)
632                     {
633                         prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress() + first_line_entry.range.GetByteSize();
634                         prologue_end_line_idx = first_line_entry_idx;
635                     }
636                 }
637                     
638                 const addr_t func_start_file_addr = m_range.GetBaseAddress().GetFileAddress();
639                 const addr_t func_end_file_addr = func_start_file_addr + m_range.GetByteSize();
640                 
641                 // Now calculate the offset to pass the subsequent line 0 entries.
642                 uint32_t first_non_zero_line = prologue_end_line_idx;
643                 while (1)
644                 {
645                     LineEntry line_entry;
646                     if (line_table->GetLineEntryAtIndex(first_non_zero_line, line_entry))
647                     {
648                         if (line_entry.line != 0)
649                             break;
650                     }
651                     if (line_entry.range.GetBaseAddress().GetFileAddress() >= func_end_file_addr)
652                         break;
653
654                     first_non_zero_line++;
655                 }
656                 
657                 if (first_non_zero_line > prologue_end_line_idx)
658                 {
659                     LineEntry first_non_zero_entry;
660                     if (line_table->GetLineEntryAtIndex(first_non_zero_line, first_non_zero_entry))
661                     {
662                         line_zero_end_file_addr = first_non_zero_entry.range.GetBaseAddress().GetFileAddress();
663                     }
664                 }
665
666                 // Verify that this prologue end file address in the function's
667                 // address range just to be sure
668                 if (func_start_file_addr < prologue_end_file_addr && prologue_end_file_addr < func_end_file_addr)
669                 {
670                     m_prologue_byte_size = prologue_end_file_addr - func_start_file_addr;
671                 }
672                 
673                 if (prologue_end_file_addr < line_zero_end_file_addr && line_zero_end_file_addr < func_end_file_addr)
674                 {
675                     m_prologue_byte_size += line_zero_end_file_addr - prologue_end_file_addr;
676                 }
677             }
678         }
679     }
680     
681         return m_prologue_byte_size;
682 }
683
684 lldb::LanguageType
685 Function::GetLanguage() const
686 {
687     if (m_comp_unit)
688         return m_comp_unit->GetLanguage();
689     else
690         return lldb::eLanguageTypeUnknown;
691 }
692
693 ConstString
694 Function::GetName() const
695 {
696     LanguageType language = lldb::eLanguageTypeUnknown;
697     if (m_comp_unit)
698         language = m_comp_unit->GetLanguage();
699     return m_mangled.GetName(language);
700 }
701
702 ConstString
703 Function::GetNameNoArguments() const
704 {
705     LanguageType language = lldb::eLanguageTypeUnknown;
706     if (m_comp_unit)
707         language = m_comp_unit->GetLanguage();
708     return m_mangled.GetName(language, Mangled::ePreferDemangledWithoutArguments);
709 }
710
711
712