Home | History | Annotate | Download | only in Symbol
      1 //===-- FuncUnwinders.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/Core/AddressRange.h"
     11 #include "lldb/Core/Address.h"
     12 #include "lldb/Symbol/FuncUnwinders.h"
     13 #include "lldb/Symbol/DWARFCallFrameInfo.h"
     14 #include "lldb/Symbol/ObjectFile.h"
     15 #include "lldb/Symbol/UnwindPlan.h"
     16 #include "lldb/Symbol/UnwindTable.h"
     17 #include "lldb/Target/ABI.h"
     18 #include "lldb/Target/ExecutionContext.h"
     19 #include "lldb/Target/Process.h"
     20 #include "lldb/Target/Thread.h"
     21 #include "lldb/Target/Target.h"
     22 #include "lldb/Target/UnwindAssembly.h"
     23 
     24 using namespace lldb;
     25 using namespace lldb_private;
     26 
     27 
     28 FuncUnwinders::FuncUnwinders
     29 (
     30     UnwindTable& unwind_table,
     31     UnwindAssembly *assembly_profiler,
     32     AddressRange range
     33 ) :
     34     m_unwind_table(unwind_table),
     35     m_assembly_profiler(assembly_profiler),
     36     m_range(range),
     37     m_mutex (Mutex::eMutexTypeNormal),
     38     m_unwind_plan_call_site_sp (),
     39     m_unwind_plan_non_call_site_sp (),
     40     m_unwind_plan_fast_sp (),
     41     m_unwind_plan_arch_default_sp (),
     42     m_tried_unwind_at_call_site (false),
     43     m_tried_unwind_at_non_call_site (false),
     44     m_tried_unwind_fast (false),
     45     m_tried_unwind_arch_default (false),
     46     m_tried_unwind_arch_default_at_func_entry (false),
     47     m_first_non_prologue_insn()
     48 {
     49 }
     50 
     51 FuncUnwinders::~FuncUnwinders ()
     52 {
     53 }
     54 
     55 UnwindPlanSP
     56 FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset)
     57 {
     58     // Lock the mutex to ensure we can always give out the most appropriate
     59     // information. We want to make sure if someone requests a call site unwind
     60     // plan, that they get one and don't run into a race condition where one
     61     // thread has started to create the unwind plan and has put it into
     62     // m_unwind_plan_call_site_sp, and have another thread enter this function
     63     // and return the partially filled in m_unwind_plan_call_site_sp pointer.
     64     // We also want to make sure that we lock out other unwind plans from
     65     // being accessed until this one is done creating itself in case someone
     66     // had some code like:
     67     //  UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
     68     //  if (best_unwind_plan == NULL)
     69     //      best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
     70     Mutex::Locker locker (m_mutex);
     71     if (m_tried_unwind_at_call_site == false && m_unwind_plan_call_site_sp.get() == NULL)
     72     {
     73         m_tried_unwind_at_call_site = true;
     74         // We have cases (e.g. with _sigtramp on Mac OS X) where the hand-written eh_frame unwind info for a
     75         // function does not cover the entire range of the function and so the FDE only lists a subset of the
     76         // address range.  If we try to look up the unwind info by the starting address of the function
     77         // (i.e. m_range.GetBaseAddress()) we may not find the eh_frame FDE.  We need to use the actual byte offset
     78         // into the function when looking it up.
     79 
     80         if (m_range.GetBaseAddress().IsValid())
     81         {
     82             Address current_pc (m_range.GetBaseAddress ());
     83             if (current_offset != -1)
     84                 current_pc.SetOffset (current_pc.GetOffset() + current_offset);
     85 
     86             DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
     87             if (eh_frame)
     88             {
     89                 m_unwind_plan_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
     90                 if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_call_site_sp))
     91                     m_unwind_plan_call_site_sp.reset();
     92             }
     93         }
     94     }
     95     return m_unwind_plan_call_site_sp;
     96 }
     97 
     98 UnwindPlanSP
     99 FuncUnwinders::GetUnwindPlanAtNonCallSite (Thread& thread)
    100 {
    101     // Lock the mutex to ensure we can always give out the most appropriate
    102     // information. We want to make sure if someone requests an unwind
    103     // plan, that they get one and don't run into a race condition where one
    104     // thread has started to create the unwind plan and has put it into
    105     // the unique pointer member variable, and have another thread enter this function
    106     // and return the partially filled pointer contained in the unique pointer.
    107     // We also want to make sure that we lock out other unwind plans from
    108     // being accessed until this one is done creating itself in case someone
    109     // had some code like:
    110     //  UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
    111     //  if (best_unwind_plan == NULL)
    112     //      best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
    113     Mutex::Locker locker (m_mutex);
    114     if (m_tried_unwind_at_non_call_site == false && m_unwind_plan_non_call_site_sp.get() == NULL)
    115     {
    116         m_tried_unwind_at_non_call_site = true;
    117         m_unwind_plan_non_call_site_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
    118         if (!m_assembly_profiler->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_non_call_site_sp))
    119             m_unwind_plan_non_call_site_sp.reset();
    120     }
    121     return m_unwind_plan_non_call_site_sp;
    122 }
    123 
    124 UnwindPlanSP
    125 FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread)
    126 {
    127     // Lock the mutex to ensure we can always give out the most appropriate
    128     // information. We want to make sure if someone requests an unwind
    129     // plan, that they get one and don't run into a race condition where one
    130     // thread has started to create the unwind plan and has put it into
    131     // the unique pointer member variable, and have another thread enter this function
    132     // and return the partially filled pointer contained in the unique pointer.
    133     // We also want to make sure that we lock out other unwind plans from
    134     // being accessed until this one is done creating itself in case someone
    135     // had some code like:
    136     //  UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
    137     //  if (best_unwind_plan == NULL)
    138     //      best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
    139     Mutex::Locker locker (m_mutex);
    140     if (m_tried_unwind_fast == false && m_unwind_plan_fast_sp.get() == NULL)
    141     {
    142         m_tried_unwind_fast = true;
    143         m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
    144         if (!m_assembly_profiler->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp))
    145             m_unwind_plan_fast_sp.reset();
    146     }
    147     return m_unwind_plan_fast_sp;
    148 }
    149 
    150 UnwindPlanSP
    151 FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread)
    152 {
    153     // Lock the mutex to ensure we can always give out the most appropriate
    154     // information. We want to make sure if someone requests an unwind
    155     // plan, that they get one and don't run into a race condition where one
    156     // thread has started to create the unwind plan and has put it into
    157     // the unique pointer member variable, and have another thread enter this function
    158     // and return the partially filled pointer contained in the unique pointer.
    159     // We also want to make sure that we lock out other unwind plans from
    160     // being accessed until this one is done creating itself in case someone
    161     // had some code like:
    162     //  UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
    163     //  if (best_unwind_plan == NULL)
    164     //      best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
    165     Mutex::Locker locker (m_mutex);
    166     if (m_tried_unwind_arch_default == false && m_unwind_plan_arch_default_sp.get() == NULL)
    167     {
    168         m_tried_unwind_arch_default = true;
    169         Address current_pc;
    170         ProcessSP process_sp (thread.CalculateProcess());
    171         if (process_sp)
    172         {
    173             ABI *abi = process_sp->GetABI().get();
    174             if (abi)
    175             {
    176                 m_unwind_plan_arch_default_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
    177                 if (m_unwind_plan_arch_default_sp)
    178                     abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp);
    179             }
    180         }
    181     }
    182 
    183     return m_unwind_plan_arch_default_sp;
    184 }
    185 
    186 UnwindPlanSP
    187 FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry (Thread& thread)
    188 {
    189     // Lock the mutex to ensure we can always give out the most appropriate
    190     // information. We want to make sure if someone requests an unwind
    191     // plan, that they get one and don't run into a race condition where one
    192     // thread has started to create the unwind plan and has put it into
    193     // the unique pointer member variable, and have another thread enter this function
    194     // and return the partially filled pointer contained in the unique pointer.
    195     // We also want to make sure that we lock out other unwind plans from
    196     // being accessed until this one is done creating itself in case someone
    197     // had some code like:
    198     //  UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
    199     //  if (best_unwind_plan == NULL)
    200     //      best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
    201     Mutex::Locker locker (m_mutex);
    202     if (m_tried_unwind_arch_default_at_func_entry == false && m_unwind_plan_arch_default_at_func_entry_sp.get() == NULL)
    203     {
    204         m_tried_unwind_arch_default_at_func_entry = true;
    205         Address current_pc;
    206         ProcessSP process_sp (thread.CalculateProcess());
    207         if (process_sp)
    208         {
    209             ABI *abi = process_sp->GetABI().get();
    210             if (abi)
    211             {
    212                 m_unwind_plan_arch_default_at_func_entry_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
    213                 if (m_unwind_plan_arch_default_at_func_entry_sp)
    214                     abi->CreateFunctionEntryUnwindPlan(*m_unwind_plan_arch_default_at_func_entry_sp);
    215             }
    216         }
    217     }
    218 
    219     return m_unwind_plan_arch_default_sp;
    220 }
    221 
    222 
    223 Address&
    224 FuncUnwinders::GetFirstNonPrologueInsn (Target& target)
    225 {
    226     if (m_first_non_prologue_insn.IsValid())
    227         return m_first_non_prologue_insn;
    228     ExecutionContext exe_ctx (target.shared_from_this(), false);
    229     m_assembly_profiler->FirstNonPrologueInsn (m_range, exe_ctx, m_first_non_prologue_insn);
    230     return m_first_non_prologue_insn;
    231 }
    232 
    233 const Address&
    234 FuncUnwinders::GetFunctionStartAddress () const
    235 {
    236     return m_range.GetBaseAddress();
    237 }
    238 
    239 void
    240 FuncUnwinders::InvalidateNonCallSiteUnwindPlan (lldb_private::Thread& thread)
    241 {
    242     UnwindPlanSP arch_default = GetUnwindPlanArchitectureDefault (thread);
    243     if (arch_default && m_tried_unwind_at_call_site)
    244     {
    245         m_unwind_plan_call_site_sp = arch_default;
    246     }
    247 }
    248