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