Home | History | Annotate | Download | only in Target
      1 //===-- ThreadPlanRunToAddress.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/Target/ThreadPlanRunToAddress.h"
     11 
     12 // C Includes
     13 // C++ Includes
     14 // Other libraries and framework includes
     15 // Project includes
     16 #include "lldb/lldb-private-log.h"
     17 #include "lldb/Core/Log.h"
     18 #include "lldb/Core/Stream.h"
     19 #include "lldb/Target/Target.h"
     20 #include "lldb/Target/Process.h"
     21 #include "lldb/Target/Thread.h"
     22 #include "lldb/Target/RegisterContext.h"
     23 
     24 using namespace lldb;
     25 using namespace lldb_private;
     26 
     27 //----------------------------------------------------------------------
     28 // ThreadPlanRunToAddress: Continue plan
     29 //----------------------------------------------------------------------
     30 
     31 ThreadPlanRunToAddress::ThreadPlanRunToAddress
     32 (
     33     Thread &thread,
     34     Address &address,
     35     bool stop_others
     36 ) :
     37     ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
     38     m_stop_others (stop_others),
     39     m_addresses (),
     40     m_break_ids ()
     41 {
     42     m_addresses.push_back (address.GetOpcodeLoadAddress (m_thread.CalculateTarget().get()));
     43     SetInitialBreakpoints();
     44 }
     45 
     46 ThreadPlanRunToAddress::ThreadPlanRunToAddress
     47 (
     48     Thread &thread,
     49     lldb::addr_t address,
     50     bool stop_others
     51 ) :
     52     ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
     53     m_stop_others (stop_others),
     54     m_addresses (),
     55     m_break_ids ()
     56 {
     57     m_addresses.push_back(m_thread.CalculateTarget()->GetOpcodeLoadAddress(address));
     58     SetInitialBreakpoints();
     59 }
     60 
     61 ThreadPlanRunToAddress::ThreadPlanRunToAddress
     62 (
     63     Thread &thread,
     64     const std::vector<lldb::addr_t> &addresses,
     65     bool stop_others
     66 ) :
     67     ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
     68     m_stop_others (stop_others),
     69     m_addresses (addresses),
     70     m_break_ids ()
     71 {
     72     // Convert all addressses into opcode addresses to make sure we set
     73     // breakpoints at the correct address.
     74     Target &target = thread.GetProcess()->GetTarget();
     75     std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();
     76     for (pos = m_addresses.begin(); pos != end; ++pos)
     77         *pos = target.GetOpcodeLoadAddress (*pos);
     78 
     79     SetInitialBreakpoints();
     80 }
     81 
     82 void
     83 ThreadPlanRunToAddress::SetInitialBreakpoints ()
     84 {
     85     size_t num_addresses = m_addresses.size();
     86     m_break_ids.resize(num_addresses);
     87 
     88     for (size_t i = 0; i < num_addresses; i++)
     89     {
     90         Breakpoint *breakpoint;
     91         breakpoint = m_thread.CalculateTarget()->CreateBreakpoint (m_addresses[i], true).get();
     92         if (breakpoint != NULL)
     93         {
     94             m_break_ids[i] = breakpoint->GetID();
     95             breakpoint->SetThreadID(m_thread.GetID());
     96             breakpoint->SetBreakpointKind("run-to-address");
     97         }
     98     }
     99 }
    100 
    101 ThreadPlanRunToAddress::~ThreadPlanRunToAddress ()
    102 {
    103     size_t num_break_ids = m_break_ids.size();
    104     for (size_t i = 0; i <  num_break_ids; i++)
    105     {
    106         m_thread.CalculateTarget()->RemoveBreakpointByID (m_break_ids[i]);
    107     }
    108 }
    109 
    110 void
    111 ThreadPlanRunToAddress::GetDescription (Stream *s, lldb::DescriptionLevel level)
    112 {
    113     size_t num_addresses = m_addresses.size();
    114 
    115     if (level == lldb::eDescriptionLevelBrief)
    116     {
    117         if (num_addresses == 0)
    118         {
    119             s->Printf ("run to address with no addresses given.");
    120             return;
    121         }
    122         else if (num_addresses == 1)
    123             s->Printf ("run to address: ");
    124         else
    125             s->Printf ("run to addresses: ");
    126 
    127         for (size_t i = 0; i < num_addresses; i++)
    128         {
    129             s->Address (m_addresses[i], sizeof (addr_t));
    130             s->Printf(" ");
    131         }
    132     }
    133     else
    134     {
    135         if (num_addresses == 0)
    136         {
    137             s->Printf ("run to address with no addresses given.");
    138             return;
    139         }
    140         else if (num_addresses == 1)
    141             s->Printf ("Run to address: ");
    142         else
    143         {
    144             s->Printf ("Run to addresses: ");
    145         }
    146 
    147         for (size_t i = 0; i < num_addresses; i++)
    148         {
    149             if (num_addresses > 1)
    150             {
    151                 s->Printf("\n");
    152                 s->Indent();
    153             }
    154 
    155             s->Address(m_addresses[i], sizeof (addr_t));
    156             s->Printf (" using breakpoint: %d - ", m_break_ids[i]);
    157             Breakpoint *breakpoint = m_thread.CalculateTarget()->GetBreakpointByID (m_break_ids[i]).get();
    158             if (breakpoint)
    159                 breakpoint->Dump (s);
    160             else
    161                 s->Printf ("but the breakpoint has been deleted.");
    162         }
    163     }
    164 }
    165 
    166 bool
    167 ThreadPlanRunToAddress::ValidatePlan (Stream *error)
    168 {
    169     // If we couldn't set the breakpoint for some reason, then this won't
    170     // work.
    171     bool all_bps_good = true;
    172     size_t num_break_ids = m_break_ids.size();
    173 
    174     for (size_t i = 0; i < num_break_ids; i++)
    175     {
    176         if (m_break_ids[i] == LLDB_INVALID_BREAK_ID)
    177         {
    178             all_bps_good = false;
    179             if (error)
    180             {
    181                 error->Printf ("Could not set breakpoint for address: ");
    182                 error->Address (m_addresses[i], sizeof (addr_t));
    183                 error->Printf ("\n");
    184             }
    185         }
    186     }
    187     return all_bps_good;
    188 }
    189 
    190 bool
    191 ThreadPlanRunToAddress::DoPlanExplainsStop (Event *event_ptr)
    192 {
    193     return AtOurAddress();
    194 }
    195 
    196 bool
    197 ThreadPlanRunToAddress::ShouldStop (Event *event_ptr)
    198 {
    199     return false;
    200 }
    201 
    202 bool
    203 ThreadPlanRunToAddress::StopOthers ()
    204 {
    205     return m_stop_others;
    206 }
    207 
    208 void
    209 ThreadPlanRunToAddress::SetStopOthers (bool new_value)
    210 {
    211     m_stop_others = new_value;
    212 }
    213 
    214 StateType
    215 ThreadPlanRunToAddress::GetPlanRunState ()
    216 {
    217     return eStateRunning;
    218 }
    219 
    220 bool
    221 ThreadPlanRunToAddress::WillStop ()
    222 {
    223     return true;
    224 }
    225 
    226 bool
    227 ThreadPlanRunToAddress::MischiefManaged ()
    228 {
    229     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    230 
    231     if (AtOurAddress())
    232     {
    233         // Remove the breakpoint
    234         size_t num_break_ids = m_break_ids.size();
    235 
    236         for (size_t i = 0; i < num_break_ids; i++)
    237         {
    238             if (m_break_ids[i] != LLDB_INVALID_BREAK_ID)
    239             {
    240                 m_thread.CalculateTarget()->RemoveBreakpointByID (m_break_ids[i]);
    241                 m_break_ids[i] = LLDB_INVALID_BREAK_ID;
    242             }
    243         }
    244         if (log)
    245             log->Printf("Completed run to address plan.");
    246         ThreadPlan::MischiefManaged ();
    247         return true;
    248     }
    249     else
    250         return false;
    251 }
    252 
    253 bool
    254 ThreadPlanRunToAddress::AtOurAddress ()
    255 {
    256     lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
    257     bool found_it = false;
    258     size_t num_addresses = m_addresses.size();
    259     for (size_t i = 0; i < num_addresses; i++)
    260     {
    261         if (m_addresses[i] == current_address)
    262         {
    263             found_it = true;
    264             break;
    265         }
    266     }
    267     return found_it;
    268 }
    269