2010-06-09 00:52:24 +08:00
|
|
|
//===-- Target.cpp ----------------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "lldb/Target/Target.h"
|
|
|
|
|
|
|
|
// C Includes
|
|
|
|
// C++ Includes
|
|
|
|
// Other libraries and framework includes
|
|
|
|
// Project includes
|
|
|
|
#include "lldb/Breakpoint/BreakpointResolver.h"
|
|
|
|
#include "lldb/Breakpoint/BreakpointResolverAddress.h"
|
|
|
|
#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
|
|
|
|
#include "lldb/Breakpoint/BreakpointResolverName.h"
|
2010-10-29 08:29:03 +08:00
|
|
|
#include "lldb/Core/DataBufferMemoryMap.h"
|
2010-12-14 10:59:59 +08:00
|
|
|
#include "lldb/Core/Debugger.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
#include "lldb/Core/Event.h"
|
|
|
|
#include "lldb/Core/Log.h"
|
|
|
|
#include "lldb/Core/StreamString.h"
|
2010-12-14 10:59:59 +08:00
|
|
|
#include "lldb/Core/Timer.h"
|
|
|
|
#include "lldb/Core/ValueObject.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
#include "lldb/Host/Host.h"
|
|
|
|
#include "lldb/lldb-private-log.h"
|
|
|
|
#include "lldb/Symbol/ObjectFile.h"
|
|
|
|
#include "lldb/Target/Process.h"
|
2010-12-14 10:59:59 +08:00
|
|
|
#include "lldb/Target/StackFrame.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
using namespace lldb;
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Target constructor
|
|
|
|
//----------------------------------------------------------------------
|
2010-06-23 09:19:29 +08:00
|
|
|
Target::Target(Debugger &debugger) :
|
2010-10-31 11:01:06 +08:00
|
|
|
Broadcaster("lldb.target"),
|
2010-11-19 11:46:01 +08:00
|
|
|
TargetInstanceSettings (*GetSettingsController()),
|
2010-06-23 09:19:29 +08:00
|
|
|
m_debugger (debugger),
|
2010-06-09 00:52:24 +08:00
|
|
|
m_images(),
|
2010-09-15 07:36:40 +08:00
|
|
|
m_section_load_list (),
|
2010-06-09 00:52:24 +08:00
|
|
|
m_breakpoint_list (false),
|
|
|
|
m_internal_breakpoint_list (true),
|
|
|
|
m_process_sp(),
|
|
|
|
m_triple(),
|
|
|
|
m_search_filter_sp(),
|
|
|
|
m_image_search_paths (ImageSearchPathsChanged, this),
|
2010-12-14 10:59:59 +08:00
|
|
|
m_scratch_ast_context_ap (NULL),
|
|
|
|
m_persistent_variables ()
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-10-31 11:01:06 +08:00
|
|
|
SetEventName (eBroadcastBitBreakpointChanged, "breakpoint-changed");
|
|
|
|
SetEventName (eBroadcastBitModulesLoaded, "modules-loaded");
|
|
|
|
SetEventName (eBroadcastBitModulesUnloaded, "modules-unloaded");
|
|
|
|
|
2010-11-06 09:53:30 +08:00
|
|
|
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
|
2010-06-09 00:52:24 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf ("%p Target::Target()", this);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Destructor
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
Target::~Target()
|
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
|
2010-06-09 00:52:24 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf ("%p Target::~Target()", this);
|
|
|
|
DeleteCurrentProcess ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-10-26 11:11:13 +08:00
|
|
|
Target::Dump (Stream *s, lldb::DescriptionLevel description_level)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-10-08 08:21:05 +08:00
|
|
|
// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
|
2010-10-26 11:11:13 +08:00
|
|
|
if (description_level != lldb::eDescriptionLevelBrief)
|
|
|
|
{
|
|
|
|
s->Indent();
|
|
|
|
s->PutCString("Target\n");
|
|
|
|
s->IndentMore();
|
2010-10-29 12:59:35 +08:00
|
|
|
m_images.Dump(s);
|
|
|
|
m_breakpoint_list.Dump(s);
|
|
|
|
m_internal_breakpoint_list.Dump(s);
|
|
|
|
s->IndentLess();
|
2010-10-26 11:11:13 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-10-30 12:51:46 +08:00
|
|
|
s->PutCString (GetExecutableModule()->GetFileSpec().GetFilename().GetCString());
|
2010-10-26 11:11:13 +08:00
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Target::DeleteCurrentProcess ()
|
|
|
|
{
|
|
|
|
if (m_process_sp.get())
|
|
|
|
{
|
2010-09-15 07:52:43 +08:00
|
|
|
m_section_load_list.Clear();
|
2010-06-09 00:52:24 +08:00
|
|
|
if (m_process_sp->IsAlive())
|
|
|
|
m_process_sp->Destroy();
|
|
|
|
else
|
|
|
|
m_process_sp->Finalize();
|
|
|
|
|
|
|
|
// Do any cleanup of the target we need to do between process instances.
|
|
|
|
// NB It is better to do this before destroying the process in case the
|
|
|
|
// clean up needs some help from the process.
|
|
|
|
m_breakpoint_list.ClearAllBreakpointSites();
|
|
|
|
m_internal_breakpoint_list.ClearAllBreakpointSites();
|
|
|
|
m_process_sp.reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const lldb::ProcessSP &
|
|
|
|
Target::CreateProcess (Listener &listener, const char *plugin_name)
|
|
|
|
{
|
|
|
|
DeleteCurrentProcess ();
|
|
|
|
m_process_sp.reset(Process::FindPlugin(*this, plugin_name, listener));
|
|
|
|
return m_process_sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
const lldb::ProcessSP &
|
|
|
|
Target::GetProcessSP () const
|
|
|
|
{
|
|
|
|
return m_process_sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
lldb::TargetSP
|
|
|
|
Target::GetSP()
|
|
|
|
{
|
2010-06-23 09:19:29 +08:00
|
|
|
return m_debugger.GetTargetList().GetTargetSP(this);
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
BreakpointList &
|
|
|
|
Target::GetBreakpointList(bool internal)
|
|
|
|
{
|
|
|
|
if (internal)
|
|
|
|
return m_internal_breakpoint_list;
|
|
|
|
else
|
|
|
|
return m_breakpoint_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
const BreakpointList &
|
|
|
|
Target::GetBreakpointList(bool internal) const
|
|
|
|
{
|
|
|
|
if (internal)
|
|
|
|
return m_internal_breakpoint_list;
|
|
|
|
else
|
|
|
|
return m_breakpoint_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
BreakpointSP
|
|
|
|
Target::GetBreakpointByID (break_id_t break_id)
|
|
|
|
{
|
|
|
|
BreakpointSP bp_sp;
|
|
|
|
|
|
|
|
if (LLDB_BREAK_ID_IS_INTERNAL (break_id))
|
|
|
|
bp_sp = m_internal_breakpoint_list.FindBreakpointByID (break_id);
|
|
|
|
else
|
|
|
|
bp_sp = m_breakpoint_list.FindBreakpointByID (break_id);
|
|
|
|
|
|
|
|
return bp_sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
BreakpointSP
|
|
|
|
Target::CreateBreakpoint (const FileSpec *containingModule, const FileSpec &file, uint32_t line_no, bool check_inlines, bool internal)
|
|
|
|
{
|
|
|
|
SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule));
|
|
|
|
BreakpointResolverSP resolver_sp(new BreakpointResolverFileLine (NULL, file, line_no, check_inlines));
|
|
|
|
return CreateBreakpoint (filter_sp, resolver_sp, internal);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BreakpointSP
|
Added support for inlined stack frames being represented as real stack frames
which is now on by default. Frames are gotten from the unwinder as concrete
frames, then if inline frames are to be shown, extra information to track
and reconstruct these frames is cached with each Thread and exanded as needed.
I added an inline height as part of the lldb_private::StackID class, the class
that helps us uniquely identify stack frames. This allows for two frames to
shared the same call frame address, yet differ only in inline height.
Fixed setting breakpoint by address to not require addresses to resolve.
A quick example:
% cat main.cpp
% ./build/Debug/lldb test/stl/a.out
Current executable set to 'test/stl/a.out' (x86_64).
(lldb) breakpoint set --address 0x0000000100000d31
Breakpoint created: 1: address = 0x0000000100000d31, locations = 1
(lldb) r
Launching 'a.out' (x86_64)
(lldb) Process 38031 Stopped
* thread #1: tid = 0x2e03, pc = 0x0000000100000d31, where = a.out`main [inlined] std::string::_M_data() const at /usr/include/c++/4.2.1/bits/basic_string.h:280, stop reason = breakpoint 1.1, queue = com.apple.main-thread
277
278 _CharT*
279 _M_data() const
280 -> { return _M_dataplus._M_p; }
281
282 _CharT*
283 _M_data(_CharT* __p)
(lldb) bt
thread #1: tid = 0x2e03, stop reason = breakpoint 1.1, queue = com.apple.main-thread
frame #0: pc = 0x0000000100000d31, where = a.out`main [inlined] std::string::_M_data() const at /usr/include/c++/4.2.1/bits/basic_string.h:280
frame #1: pc = 0x0000000100000d31, where = a.out`main [inlined] std::string::_M_rep() const at /usr/include/c++/4.2.1/bits/basic_string.h:288
frame #2: pc = 0x0000000100000d31, where = a.out`main [inlined] std::string::size() const at /usr/include/c++/4.2.1/bits/basic_string.h:606
frame #3: pc = 0x0000000100000d31, where = a.out`main [inlined] operator<< <char, std::char_traits<char>, std::allocator<char> > at /usr/include/c++/4.2.1/bits/basic_string.h:2414
frame #4: pc = 0x0000000100000d31, where = a.out`main + 33 at /Volumes/work/gclayton/Documents/src/lldb/test/stl/main.cpp:14
frame #5: pc = 0x0000000100000d08, where = a.out`start + 52
Each inline frame contains only the variables that they contain and each inlined
stack frame is treated as a single entity.
llvm-svn: 111877
2010-08-24 08:45:41 +08:00
|
|
|
Target::CreateBreakpoint (lldb::addr_t addr, bool internal)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
|
|
|
Address so_addr;
|
|
|
|
// Attempt to resolve our load address if possible, though it is ok if
|
|
|
|
// it doesn't resolve to section/offset.
|
|
|
|
|
Added support for inlined stack frames being represented as real stack frames
which is now on by default. Frames are gotten from the unwinder as concrete
frames, then if inline frames are to be shown, extra information to track
and reconstruct these frames is cached with each Thread and exanded as needed.
I added an inline height as part of the lldb_private::StackID class, the class
that helps us uniquely identify stack frames. This allows for two frames to
shared the same call frame address, yet differ only in inline height.
Fixed setting breakpoint by address to not require addresses to resolve.
A quick example:
% cat main.cpp
% ./build/Debug/lldb test/stl/a.out
Current executable set to 'test/stl/a.out' (x86_64).
(lldb) breakpoint set --address 0x0000000100000d31
Breakpoint created: 1: address = 0x0000000100000d31, locations = 1
(lldb) r
Launching 'a.out' (x86_64)
(lldb) Process 38031 Stopped
* thread #1: tid = 0x2e03, pc = 0x0000000100000d31, where = a.out`main [inlined] std::string::_M_data() const at /usr/include/c++/4.2.1/bits/basic_string.h:280, stop reason = breakpoint 1.1, queue = com.apple.main-thread
277
278 _CharT*
279 _M_data() const
280 -> { return _M_dataplus._M_p; }
281
282 _CharT*
283 _M_data(_CharT* __p)
(lldb) bt
thread #1: tid = 0x2e03, stop reason = breakpoint 1.1, queue = com.apple.main-thread
frame #0: pc = 0x0000000100000d31, where = a.out`main [inlined] std::string::_M_data() const at /usr/include/c++/4.2.1/bits/basic_string.h:280
frame #1: pc = 0x0000000100000d31, where = a.out`main [inlined] std::string::_M_rep() const at /usr/include/c++/4.2.1/bits/basic_string.h:288
frame #2: pc = 0x0000000100000d31, where = a.out`main [inlined] std::string::size() const at /usr/include/c++/4.2.1/bits/basic_string.h:606
frame #3: pc = 0x0000000100000d31, where = a.out`main [inlined] operator<< <char, std::char_traits<char>, std::allocator<char> > at /usr/include/c++/4.2.1/bits/basic_string.h:2414
frame #4: pc = 0x0000000100000d31, where = a.out`main + 33 at /Volumes/work/gclayton/Documents/src/lldb/test/stl/main.cpp:14
frame #5: pc = 0x0000000100000d08, where = a.out`start + 52
Each inline frame contains only the variables that they contain and each inlined
stack frame is treated as a single entity.
llvm-svn: 111877
2010-08-24 08:45:41 +08:00
|
|
|
// Try and resolve as a load address if possible
|
2010-09-15 07:36:40 +08:00
|
|
|
m_section_load_list.ResolveLoadAddress(addr, so_addr);
|
Added support for inlined stack frames being represented as real stack frames
which is now on by default. Frames are gotten from the unwinder as concrete
frames, then if inline frames are to be shown, extra information to track
and reconstruct these frames is cached with each Thread and exanded as needed.
I added an inline height as part of the lldb_private::StackID class, the class
that helps us uniquely identify stack frames. This allows for two frames to
shared the same call frame address, yet differ only in inline height.
Fixed setting breakpoint by address to not require addresses to resolve.
A quick example:
% cat main.cpp
% ./build/Debug/lldb test/stl/a.out
Current executable set to 'test/stl/a.out' (x86_64).
(lldb) breakpoint set --address 0x0000000100000d31
Breakpoint created: 1: address = 0x0000000100000d31, locations = 1
(lldb) r
Launching 'a.out' (x86_64)
(lldb) Process 38031 Stopped
* thread #1: tid = 0x2e03, pc = 0x0000000100000d31, where = a.out`main [inlined] std::string::_M_data() const at /usr/include/c++/4.2.1/bits/basic_string.h:280, stop reason = breakpoint 1.1, queue = com.apple.main-thread
277
278 _CharT*
279 _M_data() const
280 -> { return _M_dataplus._M_p; }
281
282 _CharT*
283 _M_data(_CharT* __p)
(lldb) bt
thread #1: tid = 0x2e03, stop reason = breakpoint 1.1, queue = com.apple.main-thread
frame #0: pc = 0x0000000100000d31, where = a.out`main [inlined] std::string::_M_data() const at /usr/include/c++/4.2.1/bits/basic_string.h:280
frame #1: pc = 0x0000000100000d31, where = a.out`main [inlined] std::string::_M_rep() const at /usr/include/c++/4.2.1/bits/basic_string.h:288
frame #2: pc = 0x0000000100000d31, where = a.out`main [inlined] std::string::size() const at /usr/include/c++/4.2.1/bits/basic_string.h:606
frame #3: pc = 0x0000000100000d31, where = a.out`main [inlined] operator<< <char, std::char_traits<char>, std::allocator<char> > at /usr/include/c++/4.2.1/bits/basic_string.h:2414
frame #4: pc = 0x0000000100000d31, where = a.out`main + 33 at /Volumes/work/gclayton/Documents/src/lldb/test/stl/main.cpp:14
frame #5: pc = 0x0000000100000d08, where = a.out`start + 52
Each inline frame contains only the variables that they contain and each inlined
stack frame is treated as a single entity.
llvm-svn: 111877
2010-08-24 08:45:41 +08:00
|
|
|
if (!so_addr.IsValid())
|
|
|
|
{
|
|
|
|
// The address didn't resolve, so just set this as an absolute address
|
|
|
|
so_addr.SetOffset (addr);
|
|
|
|
}
|
|
|
|
BreakpointSP bp_sp (CreateBreakpoint(so_addr, internal));
|
2010-06-09 00:52:24 +08:00
|
|
|
return bp_sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
BreakpointSP
|
|
|
|
Target::CreateBreakpoint (Address &addr, bool internal)
|
|
|
|
{
|
|
|
|
TargetSP target_sp = this->GetSP();
|
|
|
|
SearchFilterSP filter_sp(new SearchFilter (target_sp));
|
|
|
|
BreakpointResolverSP resolver_sp (new BreakpointResolverAddress (NULL, addr));
|
|
|
|
return CreateBreakpoint (filter_sp, resolver_sp, internal);
|
|
|
|
}
|
|
|
|
|
|
|
|
BreakpointSP
|
2010-06-29 05:30:43 +08:00
|
|
|
Target::CreateBreakpoint (FileSpec *containingModule, const char *func_name, uint32_t func_name_type_mask, bool internal)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-06-29 05:30:43 +08:00
|
|
|
BreakpointSP bp_sp;
|
|
|
|
if (func_name)
|
|
|
|
{
|
|
|
|
SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule));
|
|
|
|
BreakpointResolverSP resolver_sp (new BreakpointResolverName (NULL, func_name, func_name_type_mask, Breakpoint::Exact));
|
|
|
|
bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal);
|
|
|
|
}
|
|
|
|
return bp_sp;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SearchFilterSP
|
|
|
|
Target::GetSearchFilterForModule (const FileSpec *containingModule)
|
|
|
|
{
|
|
|
|
SearchFilterSP filter_sp;
|
|
|
|
lldb::TargetSP target_sp = this->GetSP();
|
|
|
|
if (containingModule != NULL)
|
|
|
|
{
|
|
|
|
// TODO: We should look into sharing module based search filters
|
|
|
|
// across many breakpoints like we do for the simple target based one
|
|
|
|
filter_sp.reset (new SearchFilterByModule (target_sp, *containingModule));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_search_filter_sp.get() == NULL)
|
|
|
|
m_search_filter_sp.reset (new SearchFilter (target_sp));
|
|
|
|
filter_sp = m_search_filter_sp;
|
|
|
|
}
|
|
|
|
return filter_sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
BreakpointSP
|
|
|
|
Target::CreateBreakpoint (FileSpec *containingModule, RegularExpression &func_regex, bool internal)
|
|
|
|
{
|
|
|
|
SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule));
|
|
|
|
BreakpointResolverSP resolver_sp(new BreakpointResolverName (NULL, func_regex));
|
|
|
|
|
|
|
|
return CreateBreakpoint (filter_sp, resolver_sp, internal);
|
|
|
|
}
|
|
|
|
|
|
|
|
BreakpointSP
|
|
|
|
Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool internal)
|
|
|
|
{
|
|
|
|
BreakpointSP bp_sp;
|
|
|
|
if (filter_sp && resolver_sp)
|
|
|
|
{
|
|
|
|
bp_sp.reset(new Breakpoint (*this, filter_sp, resolver_sp));
|
|
|
|
resolver_sp->SetBreakpoint (bp_sp.get());
|
|
|
|
|
|
|
|
if (internal)
|
2010-07-24 07:33:17 +08:00
|
|
|
m_internal_breakpoint_list.Add (bp_sp, false);
|
2010-06-09 00:52:24 +08:00
|
|
|
else
|
2010-07-24 07:33:17 +08:00
|
|
|
m_breakpoint_list.Add (bp_sp, true);
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2010-11-06 09:53:30 +08:00
|
|
|
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
2010-06-09 00:52:24 +08:00
|
|
|
if (log)
|
|
|
|
{
|
|
|
|
StreamString s;
|
|
|
|
bp_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
|
|
|
|
log->Printf ("Target::%s (internal = %s) => break_id = %s\n", __FUNCTION__, internal ? "yes" : "no", s.GetData());
|
|
|
|
}
|
|
|
|
|
|
|
|
bp_sp->ResolveBreakpoint();
|
|
|
|
}
|
2010-10-15 07:45:03 +08:00
|
|
|
|
|
|
|
if (!internal && bp_sp)
|
|
|
|
{
|
|
|
|
m_last_created_breakpoint = bp_sp;
|
|
|
|
}
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
return bp_sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Target::RemoveAllBreakpoints (bool internal_also)
|
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
2010-06-09 00:52:24 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf ("Target::%s (internal_also = %s)\n", __FUNCTION__, internal_also ? "yes" : "no");
|
|
|
|
|
2010-07-24 07:33:17 +08:00
|
|
|
m_breakpoint_list.RemoveAll (true);
|
2010-06-09 00:52:24 +08:00
|
|
|
if (internal_also)
|
2010-07-24 07:33:17 +08:00
|
|
|
m_internal_breakpoint_list.RemoveAll (false);
|
2010-10-15 07:45:03 +08:00
|
|
|
|
|
|
|
m_last_created_breakpoint.reset();
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Target::DisableAllBreakpoints (bool internal_also)
|
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
2010-06-09 00:52:24 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf ("Target::%s (internal_also = %s)\n", __FUNCTION__, internal_also ? "yes" : "no");
|
|
|
|
|
|
|
|
m_breakpoint_list.SetEnabledAll (false);
|
|
|
|
if (internal_also)
|
|
|
|
m_internal_breakpoint_list.SetEnabledAll (false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Target::EnableAllBreakpoints (bool internal_also)
|
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
2010-06-09 00:52:24 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf ("Target::%s (internal_also = %s)\n", __FUNCTION__, internal_also ? "yes" : "no");
|
|
|
|
|
|
|
|
m_breakpoint_list.SetEnabledAll (true);
|
|
|
|
if (internal_also)
|
|
|
|
m_internal_breakpoint_list.SetEnabledAll (true);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Target::RemoveBreakpointByID (break_id_t break_id)
|
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
2010-06-09 00:52:24 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf ("Target::%s (break_id = %i, internal = %s)\n", __FUNCTION__, break_id, LLDB_BREAK_ID_IS_INTERNAL (break_id) ? "yes" : "no");
|
|
|
|
|
|
|
|
if (DisableBreakpointByID (break_id))
|
|
|
|
{
|
|
|
|
if (LLDB_BREAK_ID_IS_INTERNAL (break_id))
|
2010-07-24 07:33:17 +08:00
|
|
|
m_internal_breakpoint_list.Remove(break_id, false);
|
2010-06-09 00:52:24 +08:00
|
|
|
else
|
2010-10-15 07:45:03 +08:00
|
|
|
{
|
|
|
|
if (m_last_created_breakpoint->GetID() == break_id)
|
|
|
|
m_last_created_breakpoint.reset();
|
2010-07-24 07:33:17 +08:00
|
|
|
m_breakpoint_list.Remove(break_id, true);
|
2010-10-15 07:45:03 +08:00
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Target::DisableBreakpointByID (break_id_t break_id)
|
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
2010-06-09 00:52:24 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf ("Target::%s (break_id = %i, internal = %s)\n", __FUNCTION__, break_id, LLDB_BREAK_ID_IS_INTERNAL (break_id) ? "yes" : "no");
|
|
|
|
|
|
|
|
BreakpointSP bp_sp;
|
|
|
|
|
|
|
|
if (LLDB_BREAK_ID_IS_INTERNAL (break_id))
|
|
|
|
bp_sp = m_internal_breakpoint_list.FindBreakpointByID (break_id);
|
|
|
|
else
|
|
|
|
bp_sp = m_breakpoint_list.FindBreakpointByID (break_id);
|
|
|
|
if (bp_sp)
|
|
|
|
{
|
|
|
|
bp_sp->SetEnabled (false);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Target::EnableBreakpointByID (break_id_t break_id)
|
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
2010-06-09 00:52:24 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf ("Target::%s (break_id = %i, internal = %s)\n",
|
|
|
|
__FUNCTION__,
|
|
|
|
break_id,
|
|
|
|
LLDB_BREAK_ID_IS_INTERNAL (break_id) ? "yes" : "no");
|
|
|
|
|
|
|
|
BreakpointSP bp_sp;
|
|
|
|
|
|
|
|
if (LLDB_BREAK_ID_IS_INTERNAL (break_id))
|
|
|
|
bp_sp = m_internal_breakpoint_list.FindBreakpointByID (break_id);
|
|
|
|
else
|
|
|
|
bp_sp = m_breakpoint_list.FindBreakpointByID (break_id);
|
|
|
|
|
|
|
|
if (bp_sp)
|
|
|
|
{
|
|
|
|
bp_sp->SetEnabled (true);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ModuleSP
|
|
|
|
Target::GetExecutableModule ()
|
|
|
|
{
|
|
|
|
ModuleSP executable_sp;
|
|
|
|
if (m_images.GetSize() > 0)
|
|
|
|
executable_sp = m_images.GetModuleAtIndex(0);
|
|
|
|
return executable_sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
|
|
|
|
{
|
|
|
|
m_images.Clear();
|
|
|
|
m_scratch_ast_context_ap.reset();
|
|
|
|
|
|
|
|
if (executable_sp.get())
|
|
|
|
{
|
|
|
|
Timer scoped_timer (__PRETTY_FUNCTION__,
|
|
|
|
"Target::SetExecutableModule (executable = '%s/%s')",
|
|
|
|
executable_sp->GetFileSpec().GetDirectory().AsCString(),
|
|
|
|
executable_sp->GetFileSpec().GetFilename().AsCString());
|
|
|
|
|
|
|
|
m_images.Append(executable_sp); // The first image is our exectuable file
|
|
|
|
|
|
|
|
ArchSpec exe_arch = executable_sp->GetArchitecture();
|
2010-08-10 07:31:02 +08:00
|
|
|
// If we haven't set an architecture yet, reset our architecture based on what we found in the executable module.
|
|
|
|
if (!m_arch_spec.IsValid())
|
|
|
|
m_arch_spec = exe_arch;
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
FileSpecList dependent_files;
|
|
|
|
ObjectFile * executable_objfile = executable_sp->GetObjectFile();
|
|
|
|
if (executable_objfile == NULL)
|
|
|
|
{
|
|
|
|
|
|
|
|
FileSpec bundle_executable(executable_sp->GetFileSpec());
|
Added a new Host call to find LLDB related paths:
static bool
Host::GetLLDBPath (lldb::PathType path_type, FileSpec &file_spec);
This will fill in "file_spec" with an appropriate path that is appropriate
for the current Host OS. MacOSX will return paths within the LLDB.framework,
and other unixes will return the paths they want. The current PathType
enums are:
typedef enum PathType
{
ePathTypeLLDBShlibDir, // The directory where the lldb.so (unix) or LLDB mach-o file in LLDB.framework (MacOSX) exists
ePathTypeSupportExecutableDir, // Find LLDB support executable directory (debugserver, etc)
ePathTypeHeaderDir, // Find LLDB header file directory
ePathTypePythonDir // Find Python modules (PYTHONPATH) directory
} PathType;
All places that were finding executables are and python paths are now updated
to use this Host call.
Added another new host call to launch the inferior in a terminal. This ability
will be very host specific and doesn't need to be supported on all systems.
MacOSX currently will create a new .command file and tell Terminal.app to open
the .command file. It also uses the new "darwin-debug" app which is a small
app that uses posix to exec (no fork) and stop at the entry point of the
program. The GDB remote plug-in is almost able launch a process and attach to
it, it currently will spawn the process, but it won't attach to it just yet.
This will let LLDB not have to share the terminal with another process and a
new terminal window will pop up when you launch. This won't get hooked up
until we work out all of the kinks. The new Host function is:
static lldb::pid_t
Host::LaunchInNewTerminal (
const char **argv, // argv[0] is executable
const char **envp,
const ArchSpec *arch_spec,
bool stop_at_entry,
bool disable_aslr);
Cleaned up FileSpec::GetPath to not use strncpy() as it was always zero
filling the entire path buffer.
Fixed an issue with the dynamic checker function where I missed a '$' prefix
that should have been added.
llvm-svn: 116690
2010-10-18 06:03:32 +08:00
|
|
|
if (Host::ResolveExecutableInBundle (bundle_executable))
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
|
|
|
ModuleSP bundle_exe_module_sp(GetSharedModule(bundle_executable,
|
|
|
|
exe_arch));
|
|
|
|
SetExecutableModule (bundle_exe_module_sp, get_dependent_files);
|
|
|
|
if (bundle_exe_module_sp->GetObjectFile() != NULL)
|
|
|
|
executable_sp = bundle_exe_module_sp;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (executable_objfile)
|
|
|
|
{
|
|
|
|
executable_objfile->GetDependentModules(dependent_files);
|
|
|
|
for (uint32_t i=0; i<dependent_files.GetSize(); i++)
|
|
|
|
{
|
|
|
|
ModuleSP image_module_sp(GetSharedModule(dependent_files.GetFileSpecPointerAtIndex(i),
|
|
|
|
exe_arch));
|
|
|
|
if (image_module_sp.get())
|
|
|
|
{
|
|
|
|
//image_module_sp->Dump(&s);// REMOVE THIS, DEBUG ONLY
|
|
|
|
ObjectFile *objfile = image_module_sp->GetObjectFile();
|
|
|
|
if (objfile)
|
|
|
|
objfile->GetDependentModules(dependent_files);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now see if we know the target triple, and if so, create our scratch AST context:
|
|
|
|
ConstString target_triple;
|
|
|
|
if (GetTargetTriple(target_triple))
|
|
|
|
{
|
|
|
|
m_scratch_ast_context_ap.reset (new ClangASTContext(target_triple.GetCString()));
|
|
|
|
}
|
|
|
|
}
|
2010-09-27 08:30:10 +08:00
|
|
|
|
|
|
|
UpdateInstanceName();
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ModuleList&
|
|
|
|
Target::GetImages ()
|
|
|
|
{
|
|
|
|
return m_images;
|
|
|
|
}
|
|
|
|
|
|
|
|
ArchSpec
|
|
|
|
Target::GetArchitecture () const
|
|
|
|
{
|
2010-08-10 07:31:02 +08:00
|
|
|
return m_arch_spec;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Target::SetArchitecture (const ArchSpec &arch_spec)
|
|
|
|
{
|
|
|
|
if (m_arch_spec == arch_spec)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-08-10 07:31:02 +08:00
|
|
|
// If we're setting the architecture to our current architecture, we
|
|
|
|
// don't need to do anything.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (!m_arch_spec.IsValid())
|
|
|
|
{
|
|
|
|
// If we haven't got a valid arch spec, then we just need to set it.
|
|
|
|
m_arch_spec = arch_spec;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If we have an executable file, try to reset the executable to the desired architecture
|
|
|
|
m_arch_spec = arch_spec;
|
|
|
|
ModuleSP executable_sp = GetExecutableModule ();
|
|
|
|
m_images.Clear();
|
|
|
|
m_scratch_ast_context_ap.reset();
|
|
|
|
m_triple.Clear();
|
|
|
|
// Need to do something about unsetting breakpoints.
|
|
|
|
|
|
|
|
if (executable_sp)
|
|
|
|
{
|
|
|
|
FileSpec exec_file_spec = executable_sp->GetFileSpec();
|
|
|
|
Error error = ModuleList::GetSharedModule(exec_file_spec,
|
|
|
|
arch_spec,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
executable_sp,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (!error.Fail() && executable_sp)
|
|
|
|
{
|
|
|
|
SetExecutableModule (executable_sp, true);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Target::GetTargetTriple(ConstString &triple)
|
|
|
|
{
|
|
|
|
triple.Clear();
|
|
|
|
|
|
|
|
if (m_triple)
|
|
|
|
{
|
|
|
|
triple = m_triple;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Module *exe_module = GetExecutableModule().get();
|
|
|
|
if (exe_module)
|
|
|
|
{
|
|
|
|
ObjectFile *objfile = exe_module->GetObjectFile();
|
|
|
|
if (objfile)
|
|
|
|
{
|
|
|
|
objfile->GetTargetTriple(m_triple);
|
|
|
|
triple = m_triple;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return !triple.IsEmpty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Target::ModuleAdded (ModuleSP &module_sp)
|
|
|
|
{
|
|
|
|
// A module is being added to this target for the first time
|
|
|
|
ModuleList module_list;
|
|
|
|
module_list.Append(module_sp);
|
|
|
|
ModulesDidLoad (module_list);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Target::ModuleUpdated (ModuleSP &old_module_sp, ModuleSP &new_module_sp)
|
|
|
|
{
|
|
|
|
// A module is being added to this target for the first time
|
|
|
|
ModuleList module_list;
|
|
|
|
module_list.Append (old_module_sp);
|
|
|
|
ModulesDidUnload (module_list);
|
|
|
|
module_list.Clear ();
|
|
|
|
module_list.Append (new_module_sp);
|
|
|
|
ModulesDidLoad (module_list);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Target::ModulesDidLoad (ModuleList &module_list)
|
|
|
|
{
|
|
|
|
m_breakpoint_list.UpdateBreakpoints (module_list, true);
|
|
|
|
// TODO: make event data that packages up the module_list
|
|
|
|
BroadcastEvent (eBroadcastBitModulesLoaded, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Target::ModulesDidUnload (ModuleList &module_list)
|
|
|
|
{
|
|
|
|
m_breakpoint_list.UpdateBreakpoints (module_list, false);
|
2010-12-07 07:51:26 +08:00
|
|
|
|
|
|
|
// Remove the images from the target image list
|
|
|
|
m_images.Remove(module_list);
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
// TODO: make event data that packages up the module_list
|
|
|
|
BroadcastEvent (eBroadcastBitModulesUnloaded, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
2010-07-01 07:04:24 +08:00
|
|
|
Target::ReadMemory (const Address& addr, void *dst, size_t dst_len, Error &error)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
|
|
|
error.Clear();
|
2010-07-01 07:03:03 +08:00
|
|
|
|
|
|
|
bool process_is_valid = m_process_sp && m_process_sp->IsAlive();
|
|
|
|
|
|
|
|
Address resolved_addr(addr);
|
|
|
|
if (!resolved_addr.IsSectionOffset())
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-07-01 07:03:03 +08:00
|
|
|
if (process_is_valid)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-09-15 07:36:40 +08:00
|
|
|
m_section_load_list.ResolveLoadAddress (addr.GetOffset(), resolved_addr);
|
2010-07-01 07:03:03 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_images.ResolveFileAddress(addr.GetOffset(), resolved_addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (process_is_valid)
|
|
|
|
{
|
2010-09-15 07:36:40 +08:00
|
|
|
lldb::addr_t load_addr = resolved_addr.GetLoadAddress (this);
|
2010-07-01 07:03:03 +08:00
|
|
|
if (load_addr == LLDB_INVALID_ADDRESS)
|
|
|
|
{
|
|
|
|
if (resolved_addr.GetModule() && resolved_addr.GetModule()->GetFileSpec())
|
|
|
|
error.SetErrorStringWithFormat("%s[0x%llx] can't be resolved, %s in not currently loaded.\n",
|
|
|
|
resolved_addr.GetModule()->GetFileSpec().GetFilename().AsCString(),
|
|
|
|
resolved_addr.GetFileAddress());
|
2010-06-09 00:52:24 +08:00
|
|
|
else
|
2010-07-01 07:03:03 +08:00
|
|
|
error.SetErrorStringWithFormat("0x%llx can't be resolved.\n", resolved_addr.GetFileAddress());
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2010-07-01 07:03:03 +08:00
|
|
|
else
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-07-01 07:03:03 +08:00
|
|
|
size_t bytes_read = m_process_sp->ReadMemory(load_addr, dst, dst_len, error);
|
2010-06-09 00:52:24 +08:00
|
|
|
if (bytes_read != dst_len)
|
|
|
|
{
|
|
|
|
if (error.Success())
|
|
|
|
{
|
|
|
|
if (bytes_read == 0)
|
2010-07-01 07:03:03 +08:00
|
|
|
error.SetErrorStringWithFormat("Read memory from 0x%llx failed.\n", load_addr);
|
2010-06-09 00:52:24 +08:00
|
|
|
else
|
2010-07-01 07:03:03 +08:00
|
|
|
error.SetErrorStringWithFormat("Only %zu of %zu bytes were read from memory at 0x%llx.\n", bytes_read, dst_len, load_addr);
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
}
|
2010-07-01 07:03:03 +08:00
|
|
|
if (bytes_read)
|
|
|
|
return bytes_read;
|
|
|
|
// If the address is not section offset we have an address that
|
|
|
|
// doesn't resolve to any address in any currently loaded shared
|
|
|
|
// libaries and we failed to read memory so there isn't anything
|
|
|
|
// more we can do. If it is section offset, we might be able to
|
|
|
|
// read cached memory from the object file.
|
|
|
|
if (!resolved_addr.IsSectionOffset())
|
|
|
|
return 0;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
}
|
2010-07-01 07:03:03 +08:00
|
|
|
|
|
|
|
const Section *section = resolved_addr.GetSection();
|
|
|
|
if (section && section->GetModule())
|
|
|
|
{
|
|
|
|
ObjectFile *objfile = section->GetModule()->GetObjectFile();
|
|
|
|
return section->ReadSectionDataFromObjectFile (objfile,
|
|
|
|
resolved_addr.GetOffset(),
|
|
|
|
dst,
|
|
|
|
dst_len);
|
|
|
|
}
|
|
|
|
return 0;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ModuleSP
|
|
|
|
Target::GetSharedModule
|
|
|
|
(
|
|
|
|
const FileSpec& file_spec,
|
|
|
|
const ArchSpec& arch,
|
|
|
|
const UUID *uuid_ptr,
|
|
|
|
const ConstString *object_name,
|
|
|
|
off_t object_offset,
|
|
|
|
Error *error_ptr
|
|
|
|
)
|
|
|
|
{
|
|
|
|
// Don't pass in the UUID so we can tell if we have a stale value in our list
|
|
|
|
ModuleSP old_module_sp; // This will get filled in if we have a new version of the library
|
|
|
|
bool did_create_module = false;
|
|
|
|
ModuleSP module_sp;
|
|
|
|
|
|
|
|
// If there are image search path entries, try to use them first to acquire a suitable image.
|
|
|
|
|
|
|
|
Error error;
|
|
|
|
|
|
|
|
if (m_image_search_paths.GetSize())
|
|
|
|
{
|
|
|
|
FileSpec transformed_spec;
|
|
|
|
if (m_image_search_paths.RemapPath (file_spec.GetDirectory(), transformed_spec.GetDirectory()))
|
|
|
|
{
|
|
|
|
transformed_spec.GetFilename() = file_spec.GetFilename();
|
|
|
|
error = ModuleList::GetSharedModule (transformed_spec, arch, uuid_ptr, object_name, object_offset, module_sp, &old_module_sp, &did_create_module);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If a module hasn't been found yet, use the unmodified path.
|
|
|
|
|
|
|
|
if (!module_sp)
|
|
|
|
{
|
|
|
|
error = (ModuleList::GetSharedModule (file_spec, arch, uuid_ptr, object_name, object_offset, module_sp, &old_module_sp, &did_create_module));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (module_sp)
|
|
|
|
{
|
|
|
|
m_images.Append (module_sp);
|
|
|
|
if (did_create_module)
|
|
|
|
{
|
|
|
|
if (old_module_sp && m_images.GetIndexForModule (old_module_sp.get()) != LLDB_INVALID_INDEX32)
|
|
|
|
ModuleUpdated(old_module_sp, module_sp);
|
|
|
|
else
|
|
|
|
ModuleAdded(module_sp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (error_ptr)
|
|
|
|
*error_ptr = error;
|
|
|
|
return module_sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Target *
|
|
|
|
Target::CalculateTarget ()
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
Process *
|
|
|
|
Target::CalculateProcess ()
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Thread *
|
|
|
|
Target::CalculateThread ()
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
StackFrame *
|
|
|
|
Target::CalculateStackFrame ()
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-10-04 09:05:56 +08:00
|
|
|
Target::CalculateExecutionContext (ExecutionContext &exe_ctx)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
|
|
|
exe_ctx.target = this;
|
|
|
|
exe_ctx.process = NULL; // Do NOT fill in process...
|
|
|
|
exe_ctx.thread = NULL;
|
|
|
|
exe_ctx.frame = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
PathMappingList &
|
|
|
|
Target::GetImageSearchPathList ()
|
|
|
|
{
|
|
|
|
return m_image_search_paths;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Target::ImageSearchPathsChanged
|
|
|
|
(
|
|
|
|
const PathMappingList &path_list,
|
|
|
|
void *baton
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Target *target = (Target *)baton;
|
|
|
|
if (target->m_images.GetSize() > 1)
|
|
|
|
{
|
|
|
|
ModuleSP exe_module_sp (target->GetExecutableModule());
|
|
|
|
if (exe_module_sp)
|
|
|
|
{
|
|
|
|
target->m_images.Clear();
|
|
|
|
target->SetExecutableModule (exe_module_sp, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ClangASTContext *
|
|
|
|
Target::GetScratchClangASTContext()
|
|
|
|
{
|
|
|
|
return m_scratch_ast_context_ap.get();
|
|
|
|
}
|
2010-09-21 04:44:43 +08:00
|
|
|
|
2010-11-19 07:32:35 +08:00
|
|
|
void
|
|
|
|
Target::Initialize ()
|
2010-09-21 04:44:43 +08:00
|
|
|
{
|
2010-11-19 07:32:35 +08:00
|
|
|
UserSettingsControllerSP &usc = GetSettingsController();
|
|
|
|
usc.reset (new SettingsController);
|
|
|
|
UserSettingsController::InitializeSettingsController (usc,
|
|
|
|
SettingsController::global_settings_table,
|
|
|
|
SettingsController::instance_settings_table);
|
|
|
|
}
|
2010-09-21 04:44:43 +08:00
|
|
|
|
2010-11-19 07:32:35 +08:00
|
|
|
void
|
|
|
|
Target::Terminate ()
|
|
|
|
{
|
|
|
|
UserSettingsControllerSP &usc = GetSettingsController();
|
|
|
|
UserSettingsController::FinalizeSettingsController (usc);
|
|
|
|
usc.reset();
|
|
|
|
}
|
2010-09-21 04:44:43 +08:00
|
|
|
|
2010-11-19 07:32:35 +08:00
|
|
|
UserSettingsControllerSP &
|
|
|
|
Target::GetSettingsController ()
|
|
|
|
{
|
|
|
|
static UserSettingsControllerSP g_settings_controller;
|
2010-09-21 04:44:43 +08:00
|
|
|
return g_settings_controller;
|
|
|
|
}
|
|
|
|
|
|
|
|
ArchSpec
|
|
|
|
Target::GetDefaultArchitecture ()
|
|
|
|
{
|
2010-11-19 11:46:01 +08:00
|
|
|
lldb::UserSettingsControllerSP &settings_controller = GetSettingsController();
|
2010-09-21 04:44:43 +08:00
|
|
|
lldb::SettableVariableType var_type;
|
|
|
|
Error err;
|
|
|
|
StringList result = settings_controller->GetVariable ("target.default-arch", var_type, "[]", err);
|
|
|
|
|
|
|
|
const char *default_name = "";
|
|
|
|
if (result.GetSize() == 1 && err.Success())
|
|
|
|
default_name = result.GetStringAtIndex (0);
|
|
|
|
|
|
|
|
ArchSpec default_arch (default_name);
|
|
|
|
return default_arch;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Target::SetDefaultArchitecture (ArchSpec new_arch)
|
|
|
|
{
|
|
|
|
if (new_arch.IsValid())
|
2010-11-19 11:46:01 +08:00
|
|
|
GetSettingsController ()->SetVariable ("target.default-arch",
|
|
|
|
new_arch.AsCString(),
|
|
|
|
lldb::eVarSetOperationAssign,
|
|
|
|
false,
|
|
|
|
"[]");
|
2010-09-21 04:44:43 +08:00
|
|
|
}
|
|
|
|
|
2010-10-04 09:05:56 +08:00
|
|
|
Target *
|
|
|
|
Target::GetTargetFromContexts (const ExecutionContext *exe_ctx_ptr, const SymbolContext *sc_ptr)
|
|
|
|
{
|
|
|
|
// The target can either exist in the "process" of ExecutionContext, or in
|
|
|
|
// the "target_sp" member of SymbolContext. This accessor helper function
|
|
|
|
// will get the target from one of these locations.
|
|
|
|
|
|
|
|
Target *target = NULL;
|
|
|
|
if (sc_ptr != NULL)
|
|
|
|
target = sc_ptr->target_sp.get();
|
|
|
|
if (target == NULL)
|
|
|
|
{
|
|
|
|
if (exe_ctx_ptr != NULL && exe_ctx_ptr->process != NULL)
|
|
|
|
target = &exe_ctx_ptr->process->GetTarget();
|
|
|
|
}
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-09-27 08:30:10 +08:00
|
|
|
void
|
|
|
|
Target::UpdateInstanceName ()
|
|
|
|
{
|
|
|
|
StreamString sstr;
|
|
|
|
|
|
|
|
ModuleSP module_sp = GetExecutableModule();
|
|
|
|
if (module_sp)
|
|
|
|
{
|
2010-10-27 10:06:37 +08:00
|
|
|
sstr.Printf ("%s_%s",
|
|
|
|
module_sp->GetFileSpec().GetFilename().AsCString(),
|
2010-09-27 08:30:10 +08:00
|
|
|
module_sp->GetArchitecture().AsCString());
|
2010-11-19 11:46:01 +08:00
|
|
|
GetSettingsController()->RenameInstanceSettings (GetInstanceName().AsCString(),
|
|
|
|
sstr.GetData());
|
2010-09-27 08:30:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-29 08:29:03 +08:00
|
|
|
const char *
|
|
|
|
Target::GetExpressionPrefixContentsAsCString ()
|
|
|
|
{
|
|
|
|
return m_expr_prefix_contents.c_str();
|
|
|
|
}
|
|
|
|
|
2010-12-14 10:59:59 +08:00
|
|
|
ExecutionResults
|
|
|
|
Target::EvaluateExpression
|
|
|
|
(
|
|
|
|
const char *expr_cstr,
|
|
|
|
StackFrame *frame,
|
|
|
|
bool unwind_on_error,
|
|
|
|
lldb::ValueObjectSP &result_valobj_sp
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ExecutionResults execution_results = eExecutionSetupError;
|
|
|
|
|
|
|
|
result_valobj_sp.reset();
|
|
|
|
|
|
|
|
ExecutionContext exe_ctx;
|
|
|
|
if (frame)
|
|
|
|
{
|
|
|
|
frame->CalculateExecutionContext(exe_ctx);
|
2010-12-15 13:08:08 +08:00
|
|
|
Error error;
|
|
|
|
const bool check_ptr_vs_member = true;
|
|
|
|
result_valobj_sp = frame->GetValueForVariableExpressionPath (expr_cstr, check_ptr_vs_member, error);
|
2010-12-14 10:59:59 +08:00
|
|
|
}
|
|
|
|
else if (m_process_sp)
|
|
|
|
{
|
|
|
|
m_process_sp->CalculateExecutionContext(exe_ctx);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CalculateExecutionContext(exe_ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result_valobj_sp)
|
|
|
|
{
|
|
|
|
execution_results = eExecutionCompleted;
|
|
|
|
// We got a result from the frame variable expression path above...
|
|
|
|
ConstString persistent_variable_name (m_persistent_variables.GetNextPersistentVariableName());
|
|
|
|
|
|
|
|
lldb::ValueObjectSP const_valobj_sp;
|
|
|
|
|
|
|
|
// Check in case our value is already a constant value
|
|
|
|
if (result_valobj_sp->GetIsConstant())
|
|
|
|
{
|
|
|
|
const_valobj_sp = result_valobj_sp;
|
|
|
|
const_valobj_sp->SetName (persistent_variable_name);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
const_valobj_sp = result_valobj_sp->CreateConstantValue (exe_ctx.GetBestExecutionContextScope(),
|
|
|
|
persistent_variable_name);
|
|
|
|
|
|
|
|
result_valobj_sp = const_valobj_sp;
|
|
|
|
|
|
|
|
ClangExpressionVariableSP clang_expr_variable_sp(m_persistent_variables.CreatePersistentVariable(result_valobj_sp));
|
|
|
|
assert (clang_expr_variable_sp.get());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Make sure we aren't just trying to see the value of a persistent
|
|
|
|
// variable (something like "$0")
|
|
|
|
lldb::ClangExpressionVariableSP persistent_var_sp (m_persistent_variables.GetVariable (expr_cstr));
|
|
|
|
if (persistent_var_sp)
|
|
|
|
{
|
|
|
|
result_valobj_sp = persistent_var_sp->GetValueObject ();
|
|
|
|
execution_results = eExecutionCompleted;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const char *prefix = GetExpressionPrefixContentsAsCString();
|
|
|
|
|
|
|
|
execution_results = ClangUserExpression::Evaluate (exe_ctx,
|
|
|
|
unwind_on_error,
|
|
|
|
expr_cstr,
|
|
|
|
prefix,
|
|
|
|
result_valobj_sp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return execution_results;
|
|
|
|
}
|
|
|
|
|
2010-09-21 04:44:43 +08:00
|
|
|
//--------------------------------------------------------------
|
|
|
|
// class Target::SettingsController
|
|
|
|
//--------------------------------------------------------------
|
|
|
|
|
|
|
|
Target::SettingsController::SettingsController () :
|
|
|
|
UserSettingsController ("target", Debugger::GetSettingsController()),
|
|
|
|
m_default_architecture ()
|
|
|
|
{
|
|
|
|
m_default_settings.reset (new TargetInstanceSettings (*this, false,
|
|
|
|
InstanceSettings::GetDefaultName().AsCString()));
|
|
|
|
}
|
|
|
|
|
|
|
|
Target::SettingsController::~SettingsController ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
lldb::InstanceSettingsSP
|
|
|
|
Target::SettingsController::CreateInstanceSettings (const char *instance_name)
|
|
|
|
{
|
2010-11-19 11:46:01 +08:00
|
|
|
TargetInstanceSettings *new_settings = new TargetInstanceSettings (*GetSettingsController(),
|
|
|
|
false,
|
|
|
|
instance_name);
|
2010-09-21 04:44:43 +08:00
|
|
|
lldb::InstanceSettingsSP new_settings_sp (new_settings);
|
|
|
|
return new_settings_sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ConstString &
|
|
|
|
Target::SettingsController::DefArchVarName ()
|
|
|
|
{
|
|
|
|
static ConstString def_arch_var_name ("default-arch");
|
|
|
|
|
|
|
|
return def_arch_var_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Target::SettingsController::SetGlobalVariable (const ConstString &var_name,
|
|
|
|
const char *index_value,
|
|
|
|
const char *value,
|
|
|
|
const SettingEntry &entry,
|
|
|
|
const lldb::VarSetOperationType op,
|
|
|
|
Error&err)
|
|
|
|
{
|
|
|
|
if (var_name == DefArchVarName())
|
|
|
|
{
|
|
|
|
ArchSpec tmp_spec (value);
|
|
|
|
if (tmp_spec.IsValid())
|
|
|
|
m_default_architecture = tmp_spec;
|
|
|
|
else
|
|
|
|
err.SetErrorStringWithFormat ("'%s' is not a valid architecture.", value);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
Target::SettingsController::GetGlobalVariable (const ConstString &var_name,
|
|
|
|
StringList &value,
|
|
|
|
Error &err)
|
|
|
|
{
|
|
|
|
if (var_name == DefArchVarName())
|
|
|
|
{
|
2010-10-27 10:06:37 +08:00
|
|
|
// If the arch is invalid (the default), don't show a string for it
|
|
|
|
if (m_default_architecture.IsValid())
|
|
|
|
value.AppendString (m_default_architecture.AsCString());
|
2010-09-21 04:44:43 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
err.SetErrorStringWithFormat ("unrecognized variable name '%s'", var_name.AsCString());
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------
|
|
|
|
// class TargetInstanceSettings
|
|
|
|
//--------------------------------------------------------------
|
|
|
|
|
2010-12-04 08:10:17 +08:00
|
|
|
TargetInstanceSettings::TargetInstanceSettings
|
|
|
|
(
|
|
|
|
UserSettingsController &owner,
|
|
|
|
bool live_instance,
|
|
|
|
const char *name
|
|
|
|
) :
|
|
|
|
InstanceSettings (owner, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance)
|
2010-09-21 04:44:43 +08:00
|
|
|
{
|
|
|
|
// CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called
|
|
|
|
// until the vtables for TargetInstanceSettings are properly set up, i.e. AFTER all the initializers.
|
|
|
|
// For this reason it has to be called here, rather than in the initializer or in the parent constructor.
|
|
|
|
// This is true for CreateInstanceName() too.
|
|
|
|
|
|
|
|
if (GetInstanceName () == InstanceSettings::InvalidName())
|
|
|
|
{
|
|
|
|
ChangeInstanceName (std::string (CreateInstanceName().AsCString()));
|
|
|
|
m_owner.RegisterInstanceSettings (this);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (live_instance)
|
|
|
|
{
|
|
|
|
const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
|
|
|
|
CopyInstanceSettings (pending_settings,false);
|
|
|
|
//m_owner.RemovePendingSettings (m_instance_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TargetInstanceSettings::TargetInstanceSettings (const TargetInstanceSettings &rhs) :
|
2010-11-19 11:46:01 +08:00
|
|
|
InstanceSettings (*Target::GetSettingsController(), CreateInstanceName().AsCString())
|
2010-09-21 04:44:43 +08:00
|
|
|
{
|
|
|
|
if (m_instance_name != InstanceSettings::GetDefaultName())
|
|
|
|
{
|
|
|
|
const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
|
|
|
|
CopyInstanceSettings (pending_settings,false);
|
|
|
|
//m_owner.RemovePendingSettings (m_instance_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TargetInstanceSettings::~TargetInstanceSettings ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TargetInstanceSettings&
|
|
|
|
TargetInstanceSettings::operator= (const TargetInstanceSettings &rhs)
|
|
|
|
{
|
|
|
|
if (this != &rhs)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2010-10-29 08:29:03 +08:00
|
|
|
#define EXPR_PREFIX_STRING "expr-prefix"
|
2010-09-21 04:44:43 +08:00
|
|
|
|
|
|
|
void
|
|
|
|
TargetInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name,
|
|
|
|
const char *index_value,
|
|
|
|
const char *value,
|
|
|
|
const ConstString &instance_name,
|
|
|
|
const SettingEntry &entry,
|
|
|
|
lldb::VarSetOperationType op,
|
|
|
|
Error &err,
|
|
|
|
bool pending)
|
|
|
|
{
|
2010-10-29 08:29:03 +08:00
|
|
|
static ConstString expr_prefix_str (EXPR_PREFIX_STRING);
|
|
|
|
|
|
|
|
if (var_name == expr_prefix_str)
|
|
|
|
{
|
|
|
|
switch (op)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
err.SetErrorToGenericError ();
|
|
|
|
err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
|
|
|
|
return;
|
|
|
|
case lldb::eVarSetOperationAssign:
|
|
|
|
{
|
|
|
|
FileSpec file_spec(value, true);
|
|
|
|
|
|
|
|
if (!file_spec.Exists())
|
|
|
|
{
|
|
|
|
err.SetErrorToGenericError ();
|
|
|
|
err.SetErrorStringWithFormat ("%s does not exist.\n", value);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataBufferMemoryMap buf;
|
|
|
|
|
|
|
|
if (!buf.MemoryMapFromFileSpec(&file_spec) &&
|
|
|
|
buf.GetError().Fail())
|
|
|
|
{
|
|
|
|
err.SetErrorToGenericError ();
|
|
|
|
err.SetErrorStringWithFormat ("Couldn't read from %s: %s\n", value, buf.GetError().AsCString());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_expr_prefix_path = value;
|
|
|
|
m_expr_prefix_contents.assign(reinterpret_cast<const char *>(buf.GetBytes()), buf.GetByteSize());
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
case lldb::eVarSetOperationAppend:
|
|
|
|
err.SetErrorToGenericError ();
|
|
|
|
err.SetErrorString ("Cannot append to a path.\n");
|
|
|
|
return;
|
|
|
|
case lldb::eVarSetOperationClear:
|
|
|
|
m_expr_prefix_path.clear ();
|
|
|
|
m_expr_prefix_contents.clear ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2010-09-21 04:44:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TargetInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &new_settings,
|
2010-10-29 08:29:03 +08:00
|
|
|
bool pending)
|
2010-09-21 04:44:43 +08:00
|
|
|
{
|
2010-10-29 08:29:03 +08:00
|
|
|
TargetInstanceSettings *new_settings_ptr = static_cast <TargetInstanceSettings *> (new_settings.get());
|
|
|
|
|
|
|
|
if (!new_settings_ptr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_expr_prefix_path = new_settings_ptr->m_expr_prefix_path;
|
|
|
|
m_expr_prefix_contents = new_settings_ptr->m_expr_prefix_contents;
|
2010-09-21 04:44:43 +08:00
|
|
|
}
|
|
|
|
|
2010-09-21 05:37:42 +08:00
|
|
|
bool
|
2010-09-21 04:44:43 +08:00
|
|
|
TargetInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
|
|
|
|
const ConstString &var_name,
|
|
|
|
StringList &value,
|
2010-09-21 05:37:42 +08:00
|
|
|
Error *err)
|
2010-09-21 04:44:43 +08:00
|
|
|
{
|
2010-10-29 08:29:03 +08:00
|
|
|
static ConstString expr_prefix_str (EXPR_PREFIX_STRING);
|
|
|
|
|
|
|
|
if (var_name == expr_prefix_str)
|
|
|
|
{
|
|
|
|
value.AppendString (m_expr_prefix_path.c_str(), m_expr_prefix_path.size());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (err)
|
|
|
|
err->SetErrorStringWithFormat ("unrecognized variable name '%s'", var_name.AsCString());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2010-09-21 04:44:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const ConstString
|
|
|
|
TargetInstanceSettings::CreateInstanceName ()
|
|
|
|
{
|
|
|
|
StreamString sstr;
|
2010-09-27 08:30:10 +08:00
|
|
|
static int instance_count = 1;
|
|
|
|
|
2010-09-21 04:44:43 +08:00
|
|
|
sstr.Printf ("target_%d", instance_count);
|
|
|
|
++instance_count;
|
|
|
|
|
|
|
|
const ConstString ret_val (sstr.GetData());
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------
|
|
|
|
// Target::SettingsController Variable Tables
|
|
|
|
//--------------------------------------------------
|
|
|
|
|
|
|
|
SettingEntry
|
|
|
|
Target::SettingsController::global_settings_table[] =
|
|
|
|
{
|
2010-10-29 08:29:03 +08:00
|
|
|
//{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"},
|
|
|
|
{ "default-arch", eSetVarTypeString, NULL, NULL, false, false, "Default architecture to choose, when there's a choice." },
|
2010-09-21 04:44:43 +08:00
|
|
|
{ NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
SettingEntry
|
|
|
|
Target::SettingsController::instance_settings_table[] =
|
|
|
|
{
|
2010-10-29 08:29:03 +08:00
|
|
|
//{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"},
|
|
|
|
{ EXPR_PREFIX_STRING, eSetVarTypeString, NULL, NULL, false, false, "Path to a file containing expressions to be prepended to all expressions." },
|
2010-09-21 04:44:43 +08:00
|
|
|
{ NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
|
|
|
|
};
|