ThreadPlanStepInRange.cpp revision 20594b1b003f63ed34ebafeec37634ee44552339
124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===-- ThreadPlanStepInRange.cpp -------------------------------*- C++ -*-===//
224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//                     The LLVM Compiler Infrastructure
424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This file is distributed under the University of Illinois Open Source
624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// License. See LICENSE.TXT for details.
724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===//
924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/ThreadPlanStepInRange.h"
1124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// C Includes
1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// C++ Includes
1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Other libraries and framework includes
1524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Project includes
1624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/lldb-private-log.h"
1824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/Log.h"
1924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/Stream.h"
20809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham#include "lldb/Symbol/Symbol.h"
2124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/Process.h"
2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/RegisterContext.h"
2324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/Thread.h"
2424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/ThreadPlanStepOut.h"
2524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/ThreadPlanStepThrough.h"
26809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham#include "lldb/Core/RegularExpression.h"
2724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb;
2924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb_private;
3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
3124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattneruint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eAvoidNoDebug;
3224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
3324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
3424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// ThreadPlanStepInRange: Step through a stack range, either stepping over or into
3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// based on the value of \a type.
3624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
3724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
3824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerThreadPlanStepInRange::ThreadPlanStepInRange
3924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
4024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    Thread &thread,
4124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const AddressRange &range,
4224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const SymbolContext &addr_context,
4324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    lldb::RunMode stop_others
4424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner) :
455a47e8bcc7277dc3683f2af2aeb9717184e8360cJim Ingham    ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others),
4624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL)
4724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
4824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    SetFlagsToDefault ();
49809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham    // SetAvoidRegexp("^std\\:\\:.*");
5024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
5124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
5224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerThreadPlanStepInRange::~ThreadPlanStepInRange ()
5324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
5424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
5524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
5624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
5724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
5824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
5924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (level == lldb::eDescriptionLevelBrief)
6024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        s->Printf("step in");
6124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
6224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
6324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        s->Printf ("Stepping through range (stepping into functions): ");
6424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_address_range.Dump (s, &m_thread.GetProcess(), Address::DumpStyleLoadAddress);
6524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
6624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
6724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
6824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
6924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerThreadPlanStepInRange::ShouldStop (Event *event_ptr)
7024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
7124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
7224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_no_more_plans = false;
7324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
7424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (log)
7524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
7624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        StreamString s;
7724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        s.Address (m_thread.GetRegisterContext()->GetPC(), m_thread.GetProcess().GetAddressByteSize());
7824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        log->Printf("ThreadPlanStepInRange reached %s.", s.GetData());
7924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
8024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
8124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // If we're still in the range, keep going.
8224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (InRange())
8324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return false;
8424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
8524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // If we're in an older frame then we should stop.
8624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (FrameIsOlder())
8724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return true;
8824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
8924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // See if we are in a place we should step through (i.e. a trampoline of some sort):
9024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // One tricky bit here is that some stubs don't push a frame, so we have to check
9124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // both the case of a frame that is younger, or the same as this frame.
9224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // However, if the frame is the same, and we are still in the symbol we started
9324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // in, the we don't need to do this.  This first check isn't strictly necessary,
9424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // but it is more efficient.
9524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
9624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (!FrameIsYounger() && InSymbol())
9724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
9824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        SetPlanComplete();
9924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return true;
10024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
10124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
10224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ThreadPlan* new_plan = NULL;
10324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
10481cfc99a02ee8c7f58c41236c7c034baaeb9fee8Jim Ingham    // Stepping through should be done stopping other threads in general, since we're setting a breakpoint and
10581cfc99a02ee8c7f58c41236c7c034baaeb9fee8Jim Ingham    // continuing...
10681cfc99a02ee8c7f58c41236c7c034baaeb9fee8Jim Ingham
10724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    bool stop_others;
10881cfc99a02ee8c7f58c41236c7c034baaeb9fee8Jim Ingham    if (m_stop_others != lldb::eAllThreads)
10924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        stop_others = true;
11024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
11124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        stop_others = false;
11224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
11324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    new_plan = m_thread.QueueThreadPlanForStepThrough (false, stop_others);
11424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // If not, give the "should_stop" callback a chance to push a plan to get us out of here.
11524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // But only do that if we actually have stepped in.
11624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (!new_plan && FrameIsYounger())
11724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        new_plan = InvokeShouldStopHereCallback();
11824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
11924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (new_plan == NULL)
12024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
12124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_no_more_plans = true;
12224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        SetPlanComplete();
12324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return true;
12424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
12524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
12624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
12724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        m_no_more_plans = false;
12824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return false;
12924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
13024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
13124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
13224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
13324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerThreadPlanStepInRange::SetFlagsToDefault ()
13424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
13524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values);
13624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
13724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
138809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Inghamvoid
139809ab9bcd5eb7aa87fb662a89a327384f892b923Jim InghamThreadPlanStepInRange::SetAvoidRegexp(const char *name)
140809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham{
141809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham    if (m_avoid_regexp_ap.get() == NULL)
142809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham        m_avoid_regexp_ap.reset (new RegularExpression(name));
143809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham
144809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham    m_avoid_regexp_ap->Compile (name);
145809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham}
146809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham
14724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
14824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerThreadPlanStepInRange::SetDefaultFlagValue (uint32_t new_value)
14924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
15024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // TODO: Should we test this for sanity?
15124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ThreadPlanStepInRange::s_default_flag_values = new_value;
15224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
15324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
154809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Inghambool
155809ab9bcd5eb7aa87fb662a89a327384f892b923Jim InghamThreadPlanStepInRange::FrameMatchesAvoidRegexp ()
156809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham{
157809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham    StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get();
158809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham
15920594b1b003f63ed34ebafeec37634ee44552339Jim Ingham    RegularExpression *avoid_regexp_to_use;
16020594b1b003f63ed34ebafeec37634ee44552339Jim Ingham
16120594b1b003f63ed34ebafeec37634ee44552339Jim Ingham    avoid_regexp_to_use = m_avoid_regexp_ap.get();
16220594b1b003f63ed34ebafeec37634ee44552339Jim Ingham    if (avoid_regexp_to_use == NULL)
16320594b1b003f63ed34ebafeec37634ee44552339Jim Ingham        avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp();
16420594b1b003f63ed34ebafeec37634ee44552339Jim Ingham
16520594b1b003f63ed34ebafeec37634ee44552339Jim Ingham    if (avoid_regexp_to_use != NULL)
166809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham    {
167809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham        SymbolContext sc = frame->GetSymbolContext(eSymbolContextSymbol);
168809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham        if (sc.symbol != NULL)
169809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham        {
170809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham            const char *unnamed_symbol = "<UNKNOWN>";
171809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham            const char *sym_name = sc.symbol->GetMangled().GetName().AsCString(unnamed_symbol);
172809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham            if (strcmp (sym_name, unnamed_symbol) != 0)
17320594b1b003f63ed34ebafeec37634ee44552339Jim Ingham               return avoid_regexp_to_use->Execute(sym_name);
174809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham        }
175809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham    }
176809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham    return false;
177809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham}
178809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham
17924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerThreadPlan *
18024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton)
18124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
182809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham    bool should_step_out = false;
183809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham    StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
184809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham
18524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (flags.IsSet(eAvoidNoDebug))
18624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
18724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (!frame->HasDebugInformation())
188809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham            should_step_out = true;
189809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham    }
190809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham
191809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham    if (!should_step_out)
192809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham    {
193809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham        if (current_plan->GetKind() == eKindStepInRange)
19424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
195809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham            ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
196809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham            should_step_out = step_in_range_plan->FrameMatchesAvoidRegexp ();
19724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
19824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
199809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham
200809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham    if (should_step_out)
201809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham    {
202809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham        // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions.
203809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham        return current_plan->GetThread().QueueThreadPlanForStepOut (false, NULL, true,
204809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham                                                                    current_plan->StopOthers(),
205809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham                                                                    eVoteNo, eVoteNoOpinion);
206809ab9bcd5eb7aa87fb662a89a327384f892b923Jim Ingham    }
20724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
20824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return NULL;
20924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
210