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