2010-06-09 00:52:24 +08:00
//===-- Process.cpp ---------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
2012-12-05 08:20:57 +08:00
# include "lldb/lldb-python.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Target/Process.h"
# include "lldb/lldb-private-log.h"
# include "lldb/Breakpoint/StoppointCallbackContext.h"
# include "lldb/Breakpoint/BreakpointLocation.h"
# include "lldb/Core/Event.h"
2010-11-16 13:07:41 +08:00
# include "lldb/Core/ConnectionFileDescriptor.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Core/Debugger.h"
2010-11-16 13:07:41 +08:00
# include "lldb/Core/InputReader.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Core/Log.h"
<rdar://problem/11757916>
Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes:
- Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file".
- modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly
- Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was.
- modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile()
Cleaned up header includes a bit as well.
llvm-svn: 162860
2012-08-30 05:13:06 +08:00
# include "lldb/Core/Module.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Core/PluginManager.h"
# include "lldb/Core/State.h"
2011-04-08 06:46:35 +08:00
# include "lldb/Expression/ClangUserExpression.h"
2010-09-04 08:03:46 +08:00
# include "lldb/Interpreter/CommandInterpreter.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Host/Host.h"
# include "lldb/Target/ABI.h"
2010-11-04 09:54:29 +08:00
# include "lldb/Target/DynamicLoader.h"
2011-08-22 10:49:39 +08:00
# include "lldb/Target/OperatingSystem.h"
2010-09-23 10:01:19 +08:00
# include "lldb/Target/LanguageRuntime.h"
# include "lldb/Target/CPPLanguageRuntime.h"
# include "lldb/Target/ObjCLanguageRuntime.h"
2011-03-09 06:40:15 +08:00
# include "lldb/Target/Platform.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Target/RegisterContext.h"
2010-08-04 09:40:35 +08:00
# include "lldb/Target/StopInfo.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Target/Target.h"
# include "lldb/Target/TargetList.h"
# include "lldb/Target/Thread.h"
# include "lldb/Target/ThreadPlan.h"
2012-04-10 09:21:57 +08:00
# include "lldb/Target/ThreadPlanBase.h"
2010-06-09 00:52:24 +08:00
using namespace lldb ;
using namespace lldb_private ;
2012-08-23 01:17:09 +08:00
// Comment out line below to disable memory caching, overriding the process setting
// target.process.disable-memory-cache
# define ENABLE_MEMORY_CACHING
# ifdef ENABLE_MEMORY_CACHING
# define DISABLE_MEM_CACHE_DEFAULT false
# else
# define DISABLE_MEM_CACHE_DEFAULT true
# endif
class ProcessOptionValueProperties : public OptionValueProperties
{
public :
ProcessOptionValueProperties ( const ConstString & name ) :
OptionValueProperties ( name )
{
}
// This constructor is used when creating ProcessOptionValueProperties when it
// is part of a new lldb_private::Process instance. It will copy all current
// global property values as needed
ProcessOptionValueProperties ( ProcessProperties * global_properties ) :
OptionValueProperties ( * global_properties - > GetValueProperties ( ) )
{
}
virtual const Property *
GetPropertyAtIndex ( const ExecutionContext * exe_ctx , bool will_modify , uint32_t idx ) const
{
// When gettings the value for a key from the process options, we will always
// try and grab the setting from the current process if there is one. Else we just
// use the one from this instance.
if ( exe_ctx )
{
Process * process = exe_ctx - > GetProcessPtr ( ) ;
if ( process )
{
ProcessOptionValueProperties * instance_properties = static_cast < ProcessOptionValueProperties * > ( process - > GetValueProperties ( ) . get ( ) ) ;
if ( this ! = instance_properties )
return instance_properties - > ProtectedGetPropertyAtIndex ( idx ) ;
}
}
return ProtectedGetPropertyAtIndex ( idx ) ;
}
} ;
static PropertyDefinition
g_properties [ ] =
{
{ " disable-memory-cache " , OptionValue : : eTypeBoolean , false , DISABLE_MEM_CACHE_DEFAULT , NULL , NULL , " Disable reading and caching of memory in fixed-size units. " } ,
2012-11-29 08:41:12 +08:00
{ " extra-startup-command " , OptionValue : : eTypeArray , false , OptionValue : : eTypeString , NULL , NULL , " A list containing extra commands understood by the particular process plugin used. "
" For instance, to turn on debugserver logging set this to \" QSetLogging:bitmask=LOG_DEFAULT; \" " } ,
2013-02-01 03:48:57 +08:00
{ " ignore-breakpoints-in-expressions " , OptionValue : : eTypeBoolean , true , true , NULL , NULL , " If true, breakpoints will be ignored during expression evaluation. " } ,
{ " unwind-on-error-in-expressions " , OptionValue : : eTypeBoolean , true , true , NULL , NULL , " If true, errors in expression evaluation will unwind the stack back to the state before the call. " } ,
2012-11-30 02:48:47 +08:00
{ " python-os-plugin-path " , OptionValue : : eTypeFileSpec , false , true , NULL , NULL , " A path to a python OS plug-in module file that contains a OperatingSystemPlugIn class. " } ,
2013-01-26 10:19:28 +08:00
{ " stop-on-sharedlibrary-events " , OptionValue : : eTypeBoolean , true , false , NULL , NULL , " If true, stop when a shared library is loaded or unloaded. " } ,
2012-08-23 01:17:09 +08:00
{ NULL , OptionValue : : eTypeInvalid , false , 0 , NULL , NULL , NULL }
} ;
enum {
ePropertyDisableMemCache ,
2012-10-19 06:40:37 +08:00
ePropertyExtraStartCommand ,
2013-01-15 10:47:48 +08:00
ePropertyIgnoreBreakpointsInExpressions ,
ePropertyUnwindOnErrorInExpressions ,
2013-01-26 10:19:28 +08:00
ePropertyPythonOSPluginPath ,
ePropertyStopOnSharedLibraryEvents
2012-08-23 01:17:09 +08:00
} ;
ProcessProperties : : ProcessProperties ( bool is_global ) :
Properties ( )
{
if ( is_global )
{
m_collection_sp . reset ( new ProcessOptionValueProperties ( ConstString ( " process " ) ) ) ;
m_collection_sp - > Initialize ( g_properties ) ;
m_collection_sp - > AppendProperty ( ConstString ( " thread " ) ,
2013-01-26 10:19:28 +08:00
ConstString ( " Settings specific to threads. " ) ,
2012-08-23 01:17:09 +08:00
true ,
Thread : : GetGlobalProperties ( ) - > GetValueProperties ( ) ) ;
}
else
m_collection_sp . reset ( new ProcessOptionValueProperties ( Process : : GetGlobalProperties ( ) . get ( ) ) ) ;
}
ProcessProperties : : ~ ProcessProperties ( )
{
}
bool
ProcessProperties : : GetDisableMemoryCache ( ) const
{
const uint32_t idx = ePropertyDisableMemCache ;
return m_collection_sp - > GetPropertyAtIndexAsBoolean ( NULL , idx , g_properties [ idx ] . default_uint_value ! = 0 ) ;
}
Args
ProcessProperties : : GetExtraStartupCommands ( ) const
{
Args args ;
const uint32_t idx = ePropertyExtraStartCommand ;
m_collection_sp - > GetPropertyAtIndexAsArgs ( NULL , idx , args ) ;
return args ;
}
void
ProcessProperties : : SetExtraStartupCommands ( const Args & args )
{
const uint32_t idx = ePropertyExtraStartCommand ;
m_collection_sp - > SetPropertyAtIndexFromArgs ( NULL , idx , args ) ;
}
2012-10-19 06:40:37 +08:00
FileSpec
ProcessProperties : : GetPythonOSPluginPath ( ) const
{
const uint32_t idx = ePropertyPythonOSPluginPath ;
return m_collection_sp - > GetPropertyAtIndexAsFileSpec ( NULL , idx ) ;
}
void
ProcessProperties : : SetPythonOSPluginPath ( const FileSpec & file )
{
const uint32_t idx = ePropertyPythonOSPluginPath ;
m_collection_sp - > SetPropertyAtIndexAsFileSpec ( NULL , idx , file ) ;
}
2013-01-15 10:47:48 +08:00
bool
ProcessProperties : : GetIgnoreBreakpointsInExpressions ( ) const
{
const uint32_t idx = ePropertyIgnoreBreakpointsInExpressions ;
return m_collection_sp - > GetPropertyAtIndexAsBoolean ( NULL , idx , g_properties [ idx ] . default_uint_value ! = 0 ) ;
}
void
ProcessProperties : : SetIgnoreBreakpointsInExpressions ( bool ignore )
{
const uint32_t idx = ePropertyIgnoreBreakpointsInExpressions ;
m_collection_sp - > SetPropertyAtIndexAsBoolean ( NULL , idx , ignore ) ;
}
bool
ProcessProperties : : GetUnwindOnErrorInExpressions ( ) const
{
const uint32_t idx = ePropertyUnwindOnErrorInExpressions ;
return m_collection_sp - > GetPropertyAtIndexAsBoolean ( NULL , idx , g_properties [ idx ] . default_uint_value ! = 0 ) ;
}
void
ProcessProperties : : SetUnwindOnErrorInExpressions ( bool ignore )
{
const uint32_t idx = ePropertyUnwindOnErrorInExpressions ;
m_collection_sp - > SetPropertyAtIndexAsBoolean ( NULL , idx , ignore ) ;
}
2013-01-26 10:19:28 +08:00
bool
ProcessProperties : : GetStopOnSharedLibraryEvents ( ) const
{
const uint32_t idx = ePropertyStopOnSharedLibraryEvents ;
return m_collection_sp - > GetPropertyAtIndexAsBoolean ( NULL , idx , g_properties [ idx ] . default_uint_value ! = 0 ) ;
}
void
ProcessProperties : : SetStopOnSharedLibraryEvents ( bool stop )
{
const uint32_t idx = ePropertyStopOnSharedLibraryEvents ;
m_collection_sp - > SetPropertyAtIndexAsBoolean ( NULL , idx , stop ) ;
}
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
void
2011-04-12 13:54:46 +08:00
ProcessInstanceInfo : : Dump ( Stream & s , Platform * platform ) const
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
{
const char * cstr ;
2011-04-01 08:29:43 +08:00
if ( m_pid ! = LLDB_INVALID_PROCESS_ID )
2012-11-30 05:49:15 +08:00
s . Printf ( " pid = % " PRIu64 " \n " , m_pid ) ;
2011-04-01 08:29:43 +08:00
if ( m_parent_pid ! = LLDB_INVALID_PROCESS_ID )
2012-11-30 05:49:15 +08:00
s . Printf ( " parent = % " PRIu64 " \n " , m_parent_pid ) ;
2011-04-01 08:29:43 +08:00
if ( m_executable )
{
s . Printf ( " name = %s \n " , m_executable . GetFilename ( ) . GetCString ( ) ) ;
s . PutCString ( " file = " ) ;
m_executable . Dump ( & s ) ;
s . EOL ( ) ;
}
2011-04-12 13:54:46 +08:00
const uint32_t argc = m_arguments . GetArgumentCount ( ) ;
2011-04-01 08:29:43 +08:00
if ( argc > 0 )
{
for ( uint32_t i = 0 ; i < argc ; i + + )
{
2011-04-12 13:54:46 +08:00
const char * arg = m_arguments . GetArgumentAtIndex ( i ) ;
2011-04-01 08:29:43 +08:00
if ( i < 10 )
2011-04-12 13:54:46 +08:00
s . Printf ( " arg[%u] = %s \n " , i , arg ) ;
2011-04-01 08:29:43 +08:00
else
2011-04-12 13:54:46 +08:00
s . Printf ( " arg[%u] = %s \n " , i , arg ) ;
2011-04-01 08:29:43 +08:00
}
}
2011-04-12 13:54:46 +08:00
const uint32_t envc = m_environment . GetArgumentCount ( ) ;
if ( envc > 0 )
{
for ( uint32_t i = 0 ; i < envc ; i + + )
{
const char * env = m_environment . GetArgumentAtIndex ( i ) ;
if ( i < 10 )
s . Printf ( " env[%u] = %s \n " , i , env ) ;
else
s . Printf ( " env[%u] = %s \n " , i , env ) ;
}
}
2011-04-01 08:29:43 +08:00
if ( m_arch . IsValid ( ) )
s . Printf ( " arch = %s \n " , m_arch . GetTriple ( ) . str ( ) . c_str ( ) ) ;
2011-04-12 13:54:46 +08:00
if ( m_uid ! = UINT32_MAX )
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
{
2011-04-12 13:54:46 +08:00
cstr = platform - > GetUserName ( m_uid ) ;
s . Printf ( " uid = %-5u (%s) \n " , m_uid , cstr ? cstr : " " ) ;
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
}
2011-04-12 13:54:46 +08:00
if ( m_gid ! = UINT32_MAX )
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
{
2011-04-12 13:54:46 +08:00
cstr = platform - > GetGroupName ( m_gid ) ;
s . Printf ( " gid = %-5u (%s) \n " , m_gid , cstr ? cstr : " " ) ;
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
}
2011-04-12 13:54:46 +08:00
if ( m_euid ! = UINT32_MAX )
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
{
2011-04-12 13:54:46 +08:00
cstr = platform - > GetUserName ( m_euid ) ;
s . Printf ( " euid = %-5u (%s) \n " , m_euid , cstr ? cstr : " " ) ;
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
}
2011-04-12 13:54:46 +08:00
if ( m_egid ! = UINT32_MAX )
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
{
2011-04-12 13:54:46 +08:00
cstr = platform - > GetGroupName ( m_egid ) ;
s . Printf ( " egid = %-5u (%s) \n " , m_egid , cstr ? cstr : " " ) ;
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
}
}
void
2011-04-12 13:54:46 +08:00
ProcessInstanceInfo : : DumpTableHeader ( Stream & s , Platform * platform , bool show_args , bool verbose )
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
{
2011-04-12 13:54:46 +08:00
const char * label ;
if ( show_args | | verbose )
label = " ARGUMENTS " ;
else
label = " NAME " ;
2011-04-01 08:29:43 +08:00
if ( verbose )
{
2011-04-12 13:54:46 +08:00
s . Printf ( " PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE %s \n " , label ) ;
2011-04-01 08:29:43 +08:00
s . PutCString ( " ====== ====== ========== ========== ========== ========== ======================== ============================ \n " ) ;
}
else
{
2011-04-12 13:54:46 +08:00
s . Printf ( " PID PARENT USER ARCH %s \n " , label ) ;
2011-04-01 08:29:43 +08:00
s . PutCString ( " ====== ====== ========== ======= ============================ \n " ) ;
}
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
}
void
2011-04-12 13:54:46 +08:00
ProcessInstanceInfo : : DumpAsTableRow ( Stream & s , Platform * platform , bool show_args , bool verbose ) const
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
{
if ( m_pid ! = LLDB_INVALID_PROCESS_ID )
{
const char * cstr ;
2012-11-30 05:49:15 +08:00
s . Printf ( " %-6 " PRIu64 " %-6 " PRIu64 " " , m_pid , m_parent_pid ) ;
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
2011-04-01 08:29:43 +08:00
if ( verbose )
{
2011-04-12 13:54:46 +08:00
cstr = platform - > GetUserName ( m_uid ) ;
2011-04-01 08:29:43 +08:00
if ( cstr & & cstr [ 0 ] ) // Watch for empty string that indicates lookup failed
s . Printf ( " %-10s " , cstr ) ;
else
2011-04-12 13:54:46 +08:00
s . Printf ( " %-10u " , m_uid ) ;
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
2011-04-12 13:54:46 +08:00
cstr = platform - > GetGroupName ( m_gid ) ;
2011-04-01 08:29:43 +08:00
if ( cstr & & cstr [ 0 ] ) // Watch for empty string that indicates lookup failed
s . Printf ( " %-10s " , cstr ) ;
else
2011-04-12 13:54:46 +08:00
s . Printf ( " %-10u " , m_gid ) ;
2011-04-01 08:29:43 +08:00
2011-04-12 13:54:46 +08:00
cstr = platform - > GetUserName ( m_euid ) ;
2011-04-01 08:29:43 +08:00
if ( cstr & & cstr [ 0 ] ) // Watch for empty string that indicates lookup failed
s . Printf ( " %-10s " , cstr ) ;
else
2011-04-12 13:54:46 +08:00
s . Printf ( " %-10u " , m_euid ) ;
2011-04-01 08:29:43 +08:00
2011-04-12 13:54:46 +08:00
cstr = platform - > GetGroupName ( m_egid ) ;
2011-04-01 08:29:43 +08:00
if ( cstr & & cstr [ 0 ] ) // Watch for empty string that indicates lookup failed
s . Printf ( " %-10s " , cstr ) ;
else
2011-04-12 13:54:46 +08:00
s . Printf ( " %-10u " , m_egid ) ;
2011-04-01 08:29:43 +08:00
s . Printf ( " %-24s " , m_arch . IsValid ( ) ? m_arch . GetTriple ( ) . str ( ) . c_str ( ) : " " ) ;
}
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
else
2011-04-01 08:29:43 +08:00
{
2011-09-21 05:44:10 +08:00
s . Printf ( " %-10s %-7d %s " ,
2011-04-12 13:54:46 +08:00
platform - > GetUserName ( m_euid ) ,
2011-04-01 08:29:43 +08:00
( int ) m_arch . GetTriple ( ) . getArchName ( ) . size ( ) ,
m_arch . GetTriple ( ) . getArchName ( ) . data ( ) ) ;
}
2011-04-12 13:54:46 +08:00
if ( verbose | | show_args )
2011-04-01 08:29:43 +08:00
{
2011-04-12 13:54:46 +08:00
const uint32_t argc = m_arguments . GetArgumentCount ( ) ;
2011-04-01 08:29:43 +08:00
if ( argc > 0 )
{
for ( uint32_t i = 0 ; i < argc ; i + + )
{
if ( i > 0 )
s . PutChar ( ' ' ) ;
2011-04-12 13:54:46 +08:00
s . PutCString ( m_arguments . GetArgumentAtIndex ( i ) ) ;
2011-04-01 08:29:43 +08:00
}
}
}
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
else
2011-04-01 08:29:43 +08:00
{
s . PutCString ( GetName ( ) ) ;
}
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
2011-04-01 08:29:43 +08:00
s . EOL ( ) ;
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
}
}
2011-04-12 13:54:46 +08:00
void
2012-10-18 06:57:12 +08:00
ProcessInfo : : SetArguments ( char const * * argv , bool first_arg_is_executable )
2011-11-04 05:22:33 +08:00
{
m_arguments . SetArguments ( argv ) ;
// Is the first argument the executable?
if ( first_arg_is_executable )
{
const char * first_arg = m_arguments . GetArgumentAtIndex ( 0 ) ;
if ( first_arg )
{
// Yes the first argument is an executable, set it as the executable
// in the launch options. Don't resolve the file path as the path
// could be a remote platform path
const bool resolve = false ;
m_executable . SetFile ( first_arg , resolve ) ;
}
}
}
void
2012-10-18 06:57:12 +08:00
ProcessInfo : : SetArguments ( const Args & args , bool first_arg_is_executable )
2011-04-12 13:54:46 +08:00
{
// Copy all arguments
m_arguments = args ;
// Is the first argument the executable?
if ( first_arg_is_executable )
{
2011-11-04 05:22:33 +08:00
const char * first_arg = m_arguments . GetArgumentAtIndex ( 0 ) ;
2011-04-12 13:54:46 +08:00
if ( first_arg )
{
// Yes the first argument is an executable, set it as the executable
// in the launch options. Don't resolve the file path as the path
// could be a remote platform path
const bool resolve = false ;
m_executable . SetFile ( first_arg , resolve ) ;
}
}
}
2011-11-08 10:43:13 +08:00
void
2011-11-18 06:14:31 +08:00
ProcessLaunchInfo : : FinalizeFileActions ( Target * target , bool default_to_use_pty )
2011-11-08 10:43:13 +08:00
{
// If notthing was specified, then check the process for any default
// settings that were set with "settings set"
if ( m_file_actions . empty ( ) )
{
if ( m_flags . Test ( eLaunchFlagDisableSTDIO ) )
{
2012-03-06 12:01:04 +08:00
AppendSuppressFileAction ( STDIN_FILENO , true , false ) ;
AppendSuppressFileAction ( STDOUT_FILENO , false , true ) ;
AppendSuppressFileAction ( STDERR_FILENO , false , true ) ;
2011-11-08 10:43:13 +08:00
}
else
{
// Check for any values that might have gotten set with any of:
// (lldb) settings set target.input-path
// (lldb) settings set target.output-path
// (lldb) settings set target.error-path
2012-08-23 01:17:09 +08:00
FileSpec in_path ;
FileSpec out_path ;
FileSpec err_path ;
2011-11-08 10:43:13 +08:00
if ( target )
{
2012-03-06 12:01:04 +08:00
in_path = target - > GetStandardInputPath ( ) ;
out_path = target - > GetStandardOutputPath ( ) ;
err_path = target - > GetStandardErrorPath ( ) ;
2011-11-18 06:14:31 +08:00
}
2012-08-23 01:17:09 +08:00
if ( in_path | | out_path | | err_path )
{
char path [ PATH_MAX ] ;
if ( in_path & & in_path . GetPath ( path , sizeof ( path ) ) )
AppendOpenFileAction ( STDIN_FILENO , path , true , false ) ;
if ( out_path & & out_path . GetPath ( path , sizeof ( path ) ) )
AppendOpenFileAction ( STDOUT_FILENO , path , false , true ) ;
if ( err_path & & err_path . GetPath ( path , sizeof ( path ) ) )
AppendOpenFileAction ( STDERR_FILENO , path , false , true ) ;
}
else if ( default_to_use_pty )
2011-11-18 06:14:31 +08:00
{
if ( m_pty . OpenFirstAvailableMaster ( O_RDWR | O_NOCTTY , NULL , 0 ) )
2011-11-08 10:43:13 +08:00
{
2012-08-23 01:17:09 +08:00
const char * slave_path = m_pty . GetSlaveName ( NULL , 0 ) ;
AppendOpenFileAction ( STDIN_FILENO , slave_path , true , false ) ;
AppendOpenFileAction ( STDOUT_FILENO , slave_path , false , true ) ;
AppendOpenFileAction ( STDERR_FILENO , slave_path , false , true ) ;
2011-11-08 10:43:13 +08:00
}
}
}
}
}
2011-11-15 11:53:30 +08:00
bool
2012-04-14 09:42:46 +08:00
ProcessLaunchInfo : : ConvertArgumentsForLaunchingInShell ( Error & error ,
bool localhost ,
bool will_debug ,
bool first_arg_is_full_shell_command )
2011-11-15 11:53:30 +08:00
{
error . Clear ( ) ;
if ( GetFlags ( ) . Test ( eLaunchFlagLaunchInShell ) )
{
const char * shell_executable = GetShell ( ) ;
if ( shell_executable )
{
char shell_resolved_path [ PATH_MAX ] ;
if ( localhost )
{
FileSpec shell_filespec ( shell_executable , true ) ;
if ( ! shell_filespec . Exists ( ) )
{
// Resolve the path in case we just got "bash", "sh" or "tcsh"
if ( ! shell_filespec . ResolveExecutableLocation ( ) )
{
error . SetErrorStringWithFormat ( " invalid shell path '%s' " , shell_executable ) ;
return false ;
}
}
shell_filespec . GetPath ( shell_resolved_path , sizeof ( shell_resolved_path ) ) ;
shell_executable = shell_resolved_path ;
}
2012-10-18 06:57:12 +08:00
const char * * argv = GetArguments ( ) . GetConstArgumentVector ( ) ;
if ( argv = = NULL | | argv [ 0 ] = = NULL )
return false ;
2011-11-15 11:53:30 +08:00
Args shell_arguments ;
std : : string safe_arg ;
shell_arguments . AppendArgument ( shell_executable ) ;
shell_arguments . AppendArgument ( " -c " ) ;
2012-04-14 09:42:46 +08:00
StreamString shell_command ;
if ( will_debug )
2011-11-15 11:53:30 +08:00
{
2012-10-18 06:57:12 +08:00
// Add a modified PATH environment variable in case argv[0]
// is a relative path
const char * argv0 = argv [ 0 ] ;
if ( argv0 & & ( argv0 [ 0 ] ! = ' / ' & & argv0 [ 0 ] ! = ' ~ ' ) )
{
// We have a relative path to our executable which may not work if
// we just try to run "a.out" (without it being converted to "./a.out")
const char * working_dir = GetWorkingDirectory ( ) ;
2013-02-14 11:54:39 +08:00
// Be sure to put quotes around PATH's value in case any paths have spaces...
std : : string new_path ( " PATH= \" " ) ;
2012-10-18 06:57:12 +08:00
const size_t empty_path_len = new_path . size ( ) ;
if ( working_dir & & working_dir [ 0 ] )
{
new_path + = working_dir ;
}
else
{
char current_working_dir [ PATH_MAX ] ;
const char * cwd = getcwd ( current_working_dir , sizeof ( current_working_dir ) ) ;
if ( cwd & & cwd [ 0 ] )
new_path + = cwd ;
}
const char * curr_path = getenv ( " PATH " ) ;
if ( curr_path )
{
if ( new_path . size ( ) > empty_path_len )
new_path + = ' : ' ;
new_path + = curr_path ;
}
2013-02-14 11:54:39 +08:00
new_path + = " \" " ;
2012-10-18 06:57:12 +08:00
shell_command . PutCString ( new_path . c_str ( ) ) ;
}
2012-04-14 09:42:46 +08:00
shell_command . PutCString ( " exec " ) ;
2012-10-18 06:57:12 +08:00
# if defined(__APPLE__)
// Only Apple supports /usr/bin/arch being able to specify the architecture
2012-04-14 09:42:46 +08:00
if ( GetArchitecture ( ) . IsValid ( ) )
{
shell_command . Printf ( " /usr/bin/arch -arch %s " , GetArchitecture ( ) . GetArchitectureName ( ) ) ;
2012-10-18 06:57:12 +08:00
// Set the resume count to 2:
2012-04-14 09:42:46 +08:00
// 1 - stop in shell
// 2 - stop in /usr/bin/arch
// 3 - then we will stop in our program
SetResumeCount ( 2 ) ;
}
else
{
2012-10-18 06:57:12 +08:00
// Set the resume count to 1:
2012-04-14 09:42:46 +08:00
// 1 - stop in shell
// 2 - then we will stop in our program
SetResumeCount ( 1 ) ;
}
2012-10-18 06:57:12 +08:00
# else
// Set the resume count to 1:
// 1 - stop in shell
// 2 - then we will stop in our program
SetResumeCount ( 1 ) ;
# endif
2011-11-15 11:53:30 +08:00
}
2012-10-18 06:57:12 +08:00
if ( first_arg_is_full_shell_command )
2011-11-15 11:53:30 +08:00
{
2012-10-18 06:57:12 +08:00
// There should only be one argument that is the shell command itself to be used as is
if ( argv [ 0 ] & & ! argv [ 1 ] )
shell_command . Printf ( " %s " , argv [ 0 ] ) ;
2012-04-14 09:42:46 +08:00
else
2012-10-18 06:57:12 +08:00
return false ;
2011-11-15 11:53:30 +08:00
}
2012-04-14 09:42:46 +08:00
else
{
2012-10-18 06:57:12 +08:00
for ( size_t i = 0 ; argv [ i ] ! = NULL ; + + i )
{
const char * arg = Args : : GetShellSafeArgument ( argv [ i ] , safe_arg ) ;
shell_command . Printf ( " %s " , arg ) ;
}
2012-04-14 09:42:46 +08:00
}
2012-10-18 06:57:12 +08:00
shell_arguments . AppendArgument ( shell_command . GetString ( ) . c_str ( ) ) ;
2011-11-15 11:53:30 +08:00
m_executable . SetFile ( shell_executable , false ) ;
m_arguments = shell_arguments ;
return true ;
}
else
{
error . SetErrorString ( " invalid shell path " ) ;
}
}
else
{
error . SetErrorString ( " not launching in shell " ) ;
}
return false ;
}
2011-04-12 13:54:46 +08:00
bool
ProcessLaunchInfo : : FileAction : : Open ( int fd , const char * path , bool read , bool write )
{
if ( ( read | | write ) & & fd > = 0 & & path & & path [ 0 ] )
{
m_action = eFileActionOpen ;
m_fd = fd ;
if ( read & & write )
2011-11-15 11:53:30 +08:00
m_arg = O_NOCTTY | O_CREAT | O_RDWR ;
2011-04-12 13:54:46 +08:00
else if ( read )
2011-11-15 11:53:30 +08:00
m_arg = O_NOCTTY | O_RDONLY ;
2011-04-12 13:54:46 +08:00
else
2011-11-15 11:53:30 +08:00
m_arg = O_NOCTTY | O_CREAT | O_WRONLY ;
2011-04-12 13:54:46 +08:00
m_path . assign ( path ) ;
return true ;
}
else
{
Clear ( ) ;
}
return false ;
}
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
bool
2011-04-12 13:54:46 +08:00
ProcessLaunchInfo : : FileAction : : Close ( int fd )
{
Clear ( ) ;
if ( fd > = 0 )
{
m_action = eFileActionClose ;
m_fd = fd ;
}
return m_fd > = 0 ;
}
bool
ProcessLaunchInfo : : FileAction : : Duplicate ( int fd , int dup_fd )
{
Clear ( ) ;
if ( fd > = 0 & & dup_fd > = 0 )
{
m_action = eFileActionDuplicate ;
m_fd = fd ;
m_arg = dup_fd ;
}
return m_fd > = 0 ;
}
bool
ProcessLaunchInfo : : FileAction : : AddPosixSpawnFileAction ( posix_spawn_file_actions_t * file_actions ,
const FileAction * info ,
Log * log ,
Error & error )
{
if ( info = = NULL )
return false ;
switch ( info - > m_action )
{
case eFileActionNone :
error . Clear ( ) ;
break ;
case eFileActionClose :
if ( info - > m_fd = = - 1 )
error . SetErrorString ( " invalid fd for posix_spawn_file_actions_addclose(...) " ) ;
else
{
error . SetError ( : : posix_spawn_file_actions_addclose ( file_actions , info - > m_fd ) ,
eErrorTypePOSIX ) ;
if ( log & & ( error . Fail ( ) | | log ) )
error . PutToLog ( log , " posix_spawn_file_actions_addclose (action=%p, fd=%i) " ,
file_actions , info - > m_fd ) ;
}
break ;
case eFileActionDuplicate :
if ( info - > m_fd = = - 1 )
error . SetErrorString ( " invalid fd for posix_spawn_file_actions_adddup2(...) " ) ;
else if ( info - > m_arg = = - 1 )
error . SetErrorString ( " invalid duplicate fd for posix_spawn_file_actions_adddup2(...) " ) ;
else
{
error . SetError ( : : posix_spawn_file_actions_adddup2 ( file_actions , info - > m_fd , info - > m_arg ) ,
eErrorTypePOSIX ) ;
if ( log & & ( error . Fail ( ) | | log ) )
error . PutToLog ( log , " posix_spawn_file_actions_adddup2 (action=%p, fd=%i, dup_fd=%i) " ,
file_actions , info - > m_fd , info - > m_arg ) ;
}
break ;
case eFileActionOpen :
if ( info - > m_fd = = - 1 )
error . SetErrorString ( " invalid fd in posix_spawn_file_actions_addopen(...) " ) ;
else
{
int oflag = info - > m_arg ;
2011-11-15 11:53:30 +08:00
2011-04-12 13:54:46 +08:00
mode_t mode = 0 ;
2011-11-15 11:53:30 +08:00
if ( oflag & O_CREAT )
mode = 0640 ;
2011-04-12 13:54:46 +08:00
error . SetError ( : : posix_spawn_file_actions_addopen ( file_actions ,
info - > m_fd ,
info - > m_path . c_str ( ) ,
oflag ,
mode ) ,
eErrorTypePOSIX ) ;
if ( error . Fail ( ) | | log )
error . PutToLog ( log ,
" posix_spawn_file_actions_addopen (action=%p, fd=%i, path='%s', oflag=%i, mode=%i) " ,
file_actions , info - > m_fd , info - > m_path . c_str ( ) , oflag , mode ) ;
}
break ;
}
return error . Success ( ) ;
}
Error
2011-04-13 08:18:08 +08:00
ProcessLaunchCommandOptions : : SetOptionValue ( uint32_t option_idx , const char * option_arg )
2011-04-12 13:54:46 +08:00
{
Error error ;
2012-12-04 08:32:51 +08:00
const int short_option = m_getopt_table [ option_idx ] . val ;
2011-04-12 13:54:46 +08:00
switch ( short_option )
{
case ' s ' : // Stop at program entry point
launch_info . GetFlags ( ) . Set ( eLaunchFlagStopAtEntry ) ;
break ;
2012-03-06 12:01:04 +08:00
case ' i ' : // STDIN for read only
2011-04-12 13:54:46 +08:00
{
ProcessLaunchInfo : : FileAction action ;
2012-03-06 12:01:04 +08:00
if ( action . Open ( STDIN_FILENO , option_arg , true , false ) )
2011-04-12 13:54:46 +08:00
launch_info . AppendFileAction ( action ) ;
}
break ;
2012-03-06 12:01:04 +08:00
case ' o ' : // Open STDOUT for write only
2011-04-12 13:54:46 +08:00
{
ProcessLaunchInfo : : FileAction action ;
2012-03-06 12:01:04 +08:00
if ( action . Open ( STDOUT_FILENO , option_arg , false , true ) )
2011-04-12 13:54:46 +08:00
launch_info . AppendFileAction ( action ) ;
}
break ;
2012-03-06 12:01:04 +08:00
case ' e ' : // STDERR for write only
2011-04-12 13:54:46 +08:00
{
ProcessLaunchInfo : : FileAction action ;
2012-03-06 12:01:04 +08:00
if ( action . Open ( STDERR_FILENO , option_arg , false , true ) )
2011-04-12 13:54:46 +08:00
launch_info . AppendFileAction ( action ) ;
}
break ;
2012-03-06 12:01:04 +08:00
2011-04-12 13:54:46 +08:00
case ' p ' : // Process plug-in name
launch_info . SetProcessPluginName ( option_arg ) ;
break ;
case ' n ' : // Disable STDIO
{
ProcessLaunchInfo : : FileAction action ;
2012-03-06 12:01:04 +08:00
if ( action . Open ( STDIN_FILENO , " /dev/null " , true , false ) )
2011-04-12 13:54:46 +08:00
launch_info . AppendFileAction ( action ) ;
2012-03-06 12:01:04 +08:00
if ( action . Open ( STDOUT_FILENO , " /dev/null " , false , true ) )
2011-04-12 13:54:46 +08:00
launch_info . AppendFileAction ( action ) ;
2012-03-06 12:01:04 +08:00
if ( action . Open ( STDERR_FILENO , " /dev/null " , false , true ) )
2011-04-12 13:54:46 +08:00
launch_info . AppendFileAction ( action ) ;
}
break ;
case ' w ' :
launch_info . SetWorkingDirectory ( option_arg ) ;
break ;
case ' t ' : // Open process in new terminal window
launch_info . GetFlags ( ) . Set ( eLaunchFlagLaunchInTTY ) ;
break ;
case ' a ' :
2012-05-08 09:45:38 +08:00
if ( ! launch_info . GetArchitecture ( ) . SetTriple ( option_arg , m_interpreter . GetPlatform ( true ) . get ( ) ) )
launch_info . GetArchitecture ( ) . SetTriple ( option_arg ) ;
2011-04-12 13:54:46 +08:00
break ;
case ' A ' :
launch_info . GetFlags ( ) . Set ( eLaunchFlagDisableASLR ) ;
break ;
2011-11-04 05:22:33 +08:00
case ' c ' :
2011-11-15 11:53:30 +08:00
if ( option_arg & & option_arg [ 0 ] )
launch_info . SetShell ( option_arg ) ;
else
launch_info . SetShell ( " /bin/bash " ) ;
2011-11-04 05:22:33 +08:00
break ;
2011-04-12 13:54:46 +08:00
case ' v ' :
launch_info . GetEnvironmentEntries ( ) . AppendArgument ( option_arg ) ;
break ;
default :
2011-10-26 08:56:27 +08:00
error . SetErrorStringWithFormat ( " unrecognized short option character '%c' " , short_option ) ;
2011-04-12 13:54:46 +08:00
break ;
}
return error ;
}
OptionDefinition
ProcessLaunchCommandOptions : : g_option_table [ ] =
{
{ LLDB_OPT_SET_ALL , false , " stop-at-entry " , ' s ' , no_argument , NULL , 0 , eArgTypeNone , " Stop at the entry point of the program when launching a process. " } ,
{ LLDB_OPT_SET_ALL , false , " disable-aslr " , ' A ' , no_argument , NULL , 0 , eArgTypeNone , " Disable address space layout randomization when launching a process. " } ,
{ LLDB_OPT_SET_ALL , false , " plugin " , ' p ' , required_argument , NULL , 0 , eArgTypePlugin , " Name of the process plugin you want to use. " } ,
2012-10-24 09:12:14 +08:00
{ LLDB_OPT_SET_ALL , false , " working-dir " , ' w ' , required_argument , NULL , 0 , eArgTypeDirectoryName , " Set the current working directory to <path> when running the inferior. " } ,
2011-04-12 13:54:46 +08:00
{ LLDB_OPT_SET_ALL , false , " arch " , ' a ' , required_argument , NULL , 0 , eArgTypeArchitecture , " Set the architecture for the process to launch when ambiguous. " } ,
{ LLDB_OPT_SET_ALL , false , " environment " , ' v ' , required_argument , NULL , 0 , eArgTypeNone , " Specify an environment variable name/value stirng (--environement NAME=VALUE). Can be specified multiple times for subsequent environment entries. " } ,
2012-10-24 09:12:14 +08:00
{ LLDB_OPT_SET_ALL , false , " shell " , ' c ' , optional_argument , NULL , 0 , eArgTypeFilename , " Run the process in a shell (not supported on all platforms). " } ,
2011-04-12 13:54:46 +08:00
2012-10-24 09:12:14 +08:00
{ LLDB_OPT_SET_1 , false , " stdin " , ' i ' , required_argument , NULL , 0 , eArgTypeFilename , " Redirect stdin for the process to <filename>. " } ,
{ LLDB_OPT_SET_1 , false , " stdout " , ' o ' , required_argument , NULL , 0 , eArgTypeFilename , " Redirect stdout for the process to <filename>. " } ,
{ LLDB_OPT_SET_1 , false , " stderr " , ' e ' , required_argument , NULL , 0 , eArgTypeFilename , " Redirect stderr for the process to <filename>. " } ,
2011-04-12 13:54:46 +08:00
{ LLDB_OPT_SET_2 , false , " tty " , ' t ' , no_argument , NULL , 0 , eArgTypeNone , " Start the process in a terminal (not supported on all platforms). " } ,
{ LLDB_OPT_SET_3 , false , " no-stdio " , ' n ' , no_argument , NULL , 0 , eArgTypeNone , " Do not set up for terminal I/O to go to running process. " } ,
{ 0 , false , NULL , 0 , 0 , NULL , 0 , eArgTypeNone , NULL }
} ;
bool
ProcessInstanceInfoMatch : : NameMatches ( const char * process_name ) const
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
{
if ( m_name_match_type = = eNameMatchIgnore | | process_name = = NULL )
return true ;
const char * match_name = m_match_info . GetName ( ) ;
if ( ! match_name )
return true ;
return lldb_private : : NameMatches ( process_name , m_name_match_type , match_name ) ;
}
bool
2011-04-12 13:54:46 +08:00
ProcessInstanceInfoMatch : : Matches ( const ProcessInstanceInfo & proc_info ) const
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
{
if ( ! NameMatches ( proc_info . GetName ( ) ) )
return false ;
if ( m_match_info . ProcessIDIsValid ( ) & &
m_match_info . GetProcessID ( ) ! = proc_info . GetProcessID ( ) )
return false ;
if ( m_match_info . ParentProcessIDIsValid ( ) & &
m_match_info . GetParentProcessID ( ) ! = proc_info . GetParentProcessID ( ) )
return false ;
2011-04-12 13:54:46 +08:00
if ( m_match_info . UserIDIsValid ( ) & &
m_match_info . GetUserID ( ) ! = proc_info . GetUserID ( ) )
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
return false ;
2011-04-12 13:54:46 +08:00
if ( m_match_info . GroupIDIsValid ( ) & &
m_match_info . GetGroupID ( ) ! = proc_info . GetGroupID ( ) )
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
return false ;
if ( m_match_info . EffectiveUserIDIsValid ( ) & &
m_match_info . GetEffectiveUserID ( ) ! = proc_info . GetEffectiveUserID ( ) )
return false ;
if ( m_match_info . EffectiveGroupIDIsValid ( ) & &
m_match_info . GetEffectiveGroupID ( ) ! = proc_info . GetEffectiveGroupID ( ) )
return false ;
if ( m_match_info . GetArchitecture ( ) . IsValid ( ) & &
2012-12-14 06:07:14 +08:00
! m_match_info . GetArchitecture ( ) . IsCompatibleMatch ( proc_info . GetArchitecture ( ) ) )
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
return false ;
return true ;
}
bool
2011-04-12 13:54:46 +08:00
ProcessInstanceInfoMatch : : MatchAllProcesses ( ) const
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
{
if ( m_name_match_type ! = eNameMatchIgnore )
return false ;
if ( m_match_info . ProcessIDIsValid ( ) )
return false ;
if ( m_match_info . ParentProcessIDIsValid ( ) )
return false ;
2011-04-12 13:54:46 +08:00
if ( m_match_info . UserIDIsValid ( ) )
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
return false ;
2011-04-12 13:54:46 +08:00
if ( m_match_info . GroupIDIsValid ( ) )
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
return false ;
if ( m_match_info . EffectiveUserIDIsValid ( ) )
return false ;
if ( m_match_info . EffectiveGroupIDIsValid ( ) )
return false ;
if ( m_match_info . GetArchitecture ( ) . IsValid ( ) )
return false ;
if ( m_match_all_users )
return false ;
return true ;
}
void
2011-04-12 13:54:46 +08:00
ProcessInstanceInfoMatch : : Clear ( )
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
{
m_match_info . Clear ( ) ;
m_name_match_type = eNameMatchIgnore ;
m_match_all_users = false ;
}
2011-01-07 14:08:19 +08:00
2012-02-09 14:16:32 +08:00
ProcessSP
Process : : FindPlugin ( Target & target , const char * plugin_name , Listener & listener , const FileSpec * crash_file_path )
2010-06-09 00:52:24 +08:00
{
2013-01-17 01:29:04 +08:00
static uint32_t g_process_unique_id = 0 ;
2012-02-09 14:16:32 +08:00
ProcessSP process_sp ;
2010-06-09 00:52:24 +08:00
ProcessCreateInstance create_callback = NULL ;
if ( plugin_name )
{
create_callback = PluginManager : : GetProcessCreateCallbackForPluginName ( plugin_name ) ;
if ( create_callback )
{
2012-02-09 14:16:32 +08:00
process_sp = create_callback ( target , listener , crash_file_path ) ;
if ( process_sp )
{
2013-01-17 01:29:04 +08:00
if ( process_sp - > CanDebug ( target , true ) )
{
process_sp - > m_process_unique_id = + + g_process_unique_id ;
}
else
2012-02-09 14:16:32 +08:00
process_sp . reset ( ) ;
}
2010-06-09 00:52:24 +08:00
}
}
else
{
2010-07-10 04:39:50 +08:00
for ( uint32_t idx = 0 ; ( create_callback = PluginManager : : GetProcessCreateCallbackAtIndex ( idx ) ) ! = NULL ; + + idx )
2010-06-09 00:52:24 +08:00
{
2012-02-09 14:16:32 +08:00
process_sp = create_callback ( target , listener , crash_file_path ) ;
if ( process_sp )
{
2013-01-17 01:29:04 +08:00
if ( process_sp - > CanDebug ( target , false ) )
{
process_sp - > m_process_unique_id = + + g_process_unique_id ;
2012-02-09 14:16:32 +08:00
break ;
2013-01-17 01:29:04 +08:00
}
else
process_sp . reset ( ) ;
2012-02-09 14:16:32 +08:00
}
2010-06-09 00:52:24 +08:00
}
}
2012-02-09 14:16:32 +08:00
return process_sp ;
2010-06-09 00:52:24 +08:00
}
2012-02-16 14:50:00 +08:00
ConstString &
Process : : GetStaticBroadcasterClass ( )
{
static ConstString class_name ( " lldb.process " ) ;
return class_name ;
}
2010-06-09 00:52:24 +08:00
//----------------------------------------------------------------------
// Process constructor
//----------------------------------------------------------------------
Process : : Process ( Target & target , Listener & listener ) :
2012-08-23 01:17:09 +08:00
ProcessProperties ( false ) ,
2010-06-09 00:52:24 +08:00
UserID ( LLDB_INVALID_PROCESS_ID ) ,
2012-02-16 14:50:00 +08:00
Broadcaster ( & ( target . GetDebugger ( ) ) , " lldb.process " ) ,
2010-06-09 00:52:24 +08:00
m_target ( target ) ,
m_public_state ( eStateUnloaded ) ,
m_private_state ( eStateUnloaded ) ,
2012-02-16 14:50:00 +08:00
m_private_state_broadcaster ( NULL , " lldb.process.internal_state_broadcaster " ) ,
m_private_state_control_broadcaster ( NULL , " lldb.process.internal_state_control_broadcaster " ) ,
2010-06-09 00:52:24 +08:00
m_private_state_listener ( " lldb.process.internal_state_listener " ) ,
m_private_state_control_wait ( ) ,
m_private_state_thread ( LLDB_INVALID_HOST_THREAD ) ,
2011-08-09 10:12:22 +08:00
m_mod_id ( ) ,
2013-01-17 01:29:04 +08:00
m_process_unique_id ( 0 ) ,
2010-06-09 00:52:24 +08:00
m_thread_index_id ( 0 ) ,
2013-01-09 06:10:01 +08:00
m_thread_id_to_index_id_map ( ) ,
2010-06-09 00:52:24 +08:00
m_exit_status ( - 1 ) ,
m_exit_string ( ) ,
m_thread_list ( this ) ,
m_notifications ( ) ,
2010-11-18 13:57:03 +08:00
m_image_tokens ( ) ,
m_listener ( listener ) ,
m_breakpoint_site_list ( ) ,
m_dynamic_checkers_ap ( ) ,
2010-11-16 13:07:41 +08:00
m_unix_signals ( ) ,
2010-11-18 13:57:03 +08:00
m_abi_sp ( ) ,
2010-11-16 13:07:41 +08:00
m_process_input_reader ( ) ,
2011-01-10 05:07:35 +08:00
m_stdio_communication ( " process.stdio " ) ,
2010-11-18 13:57:03 +08:00
m_stdio_communication_mutex ( Mutex : : eMutexTypeRecursive ) ,
2011-01-07 14:08:19 +08:00
m_stdout_data ( ) ,
2011-11-13 12:45:22 +08:00
m_stderr_data ( ) ,
2012-11-17 08:21:04 +08:00
m_profile_data_comm_mutex ( Mutex : : eMutexTypeRecursive ) ,
m_profile_data ( ) ,
2011-05-17 11:37:42 +08:00
m_memory_cache ( * this ) ,
m_allocated_memory_cache ( * this ) ,
2011-11-17 12:46:02 +08:00
m_should_detach ( false ) ,
2011-09-21 07:01:51 +08:00
m_next_event_action_ap ( ) ,
2012-04-06 08:10:21 +08:00
m_run_lock ( ) ,
2012-06-06 08:29:30 +08:00
m_currently_handling_event ( false ) ,
2012-08-23 05:34:33 +08:00
m_finalize_called ( false ) ,
2013-02-09 09:29:05 +08:00
m_last_broadcast_state ( eStateInvalid ) ,
2013-03-05 11:33:59 +08:00
m_destroy_in_process ( false ) ,
m_can_jit ( eCanJITDontKnow )
2010-06-09 00:52:24 +08:00
{
2012-02-16 14:50:00 +08:00
CheckInWithManager ( ) ;
2010-09-27 08:30:10 +08:00
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_OBJECT ) ) ;
2010-06-09 00:52:24 +08:00
if ( log )
log - > Printf ( " %p Process::Process() " , this ) ;
2010-10-31 11:01:06 +08:00
SetEventName ( eBroadcastBitStateChanged , " state-changed " ) ;
SetEventName ( eBroadcastBitInterrupt , " interrupt " ) ;
SetEventName ( eBroadcastBitSTDOUT , " stdout-available " ) ;
SetEventName ( eBroadcastBitSTDERR , " stderr-available " ) ;
2012-11-17 08:21:04 +08:00
SetEventName ( eBroadcastBitProfileData , " profile-data-available " ) ;
2010-10-31 11:01:06 +08:00
2012-10-30 04:52:08 +08:00
m_private_state_control_broadcaster . SetEventName ( eBroadcastInternalStateControlStop , " control-stop " ) ;
m_private_state_control_broadcaster . SetEventName ( eBroadcastInternalStateControlPause , " control-pause " ) ;
m_private_state_control_broadcaster . SetEventName ( eBroadcastInternalStateControlResume , " control-resume " ) ;
2010-06-09 00:52:24 +08:00
listener . StartListeningForEvents ( this ,
eBroadcastBitStateChanged |
eBroadcastBitInterrupt |
eBroadcastBitSTDOUT |
2012-11-17 08:21:04 +08:00
eBroadcastBitSTDERR |
eBroadcastBitProfileData ) ;
2010-06-09 00:52:24 +08:00
m_private_state_listener . StartListeningForEvents ( & m_private_state_broadcaster ,
2012-07-28 07:57:19 +08:00
eBroadcastBitStateChanged |
eBroadcastBitInterrupt ) ;
2010-06-09 00:52:24 +08:00
m_private_state_listener . StartListeningForEvents ( & m_private_state_control_broadcaster ,
eBroadcastInternalStateControlStop |
eBroadcastInternalStateControlPause |
eBroadcastInternalStateControlResume ) ;
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
Process : : ~ Process ( )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_OBJECT ) ) ;
2010-06-09 00:52:24 +08:00
if ( log )
log - > Printf ( " %p Process::~Process() " , this ) ;
StopPrivateStateThread ( ) ;
}
2012-08-23 01:17:09 +08:00
const ProcessPropertiesSP &
Process : : GetGlobalProperties ( )
{
static ProcessPropertiesSP g_settings_sp ;
if ( ! g_settings_sp )
g_settings_sp . reset ( new ProcessProperties ( true ) ) ;
return g_settings_sp ;
}
2010-06-09 00:52:24 +08:00
void
Process : : Finalize ( )
{
2011-11-17 12:46:02 +08:00
switch ( GetPrivateState ( ) )
{
case eStateConnected :
case eStateAttaching :
case eStateLaunching :
case eStateStopped :
case eStateRunning :
case eStateStepping :
case eStateCrashed :
case eStateSuspended :
if ( GetShouldDetach ( ) )
Detach ( ) ;
else
Destroy ( ) ;
break ;
case eStateInvalid :
case eStateUnloaded :
case eStateDetached :
case eStateExited :
break ;
}
2011-10-01 08:45:15 +08:00
// Clear our broadcaster before we proceed with destroying
Broadcaster : : Clear ( ) ;
2010-06-09 00:52:24 +08:00
// Do any cleanup needed prior to being destructed... Subclasses
// that override this method should call this superclass method as well.
2011-02-17 01:54:55 +08:00
// We need to destroy the loader before the derived Process class gets destroyed
// since it is very likely that undoing the loader will require access to the real process.
2012-01-21 07:08:34 +08:00
m_dynamic_checkers_ap . reset ( ) ;
m_abi_sp . reset ( ) ;
2011-08-22 10:49:39 +08:00
m_os_ap . reset ( ) ;
2012-01-21 07:08:34 +08:00
m_dyld_ap . reset ( ) ;
2012-01-30 04:56:30 +08:00
m_thread_list . Destroy ( ) ;
2012-01-21 07:08:34 +08:00
std : : vector < Notifications > empty_notifications ;
m_notifications . swap ( empty_notifications ) ;
m_image_tokens . clear ( ) ;
m_memory_cache . Clear ( ) ;
m_allocated_memory_cache . Clear ( ) ;
m_language_runtimes . clear ( ) ;
m_next_event_action_ap . reset ( ) ;
2012-10-30 04:52:08 +08:00
//#ifdef LLDB_CONFIGURATION_DEBUG
// StreamFile s(stdout, false);
// EventSP event_sp;
// while (m_private_state_listener.GetNextEvent(event_sp))
// {
// event_sp->Dump (&s);
// s.EOL();
// }
//#endif
// We have to be very careful here as the m_private_state_listener might
// contain events that have ProcessSP values in them which can keep this
// process around forever. These events need to be cleared out.
m_private_state_listener . Clear ( ) ;
2012-08-23 05:34:33 +08:00
m_finalize_called = true ;
2010-06-09 00:52:24 +08:00
}
void
Process : : RegisterNotificationCallbacks ( const Notifications & callbacks )
{
m_notifications . push_back ( callbacks ) ;
if ( callbacks . initialize ! = NULL )
callbacks . initialize ( callbacks . baton , this ) ;
}
bool
Process : : UnregisterNotificationCallbacks ( const Notifications & callbacks )
{
std : : vector < Notifications > : : iterator pos , end = m_notifications . end ( ) ;
for ( pos = m_notifications . begin ( ) ; pos ! = end ; + + pos )
{
if ( pos - > baton = = callbacks . baton & &
pos - > initialize = = callbacks . initialize & &
pos - > process_state_changed = = callbacks . process_state_changed )
{
m_notifications . erase ( pos ) ;
return true ;
}
}
return false ;
}
void
Process : : SynchronouslyNotifyStateChanged ( StateType state )
{
std : : vector < Notifications > : : iterator notification_pos , notification_end = m_notifications . end ( ) ;
for ( notification_pos = m_notifications . begin ( ) ; notification_pos ! = notification_end ; + + notification_pos )
{
if ( notification_pos - > process_state_changed )
notification_pos - > process_state_changed ( notification_pos - > baton , this , state ) ;
}
}
// FIXME: We need to do some work on events before the general Listener sees them.
// For instance if we are continuing from a breakpoint, we need to ensure that we do
// the little "insert real insn, step & stop" trick. But we can't do that when the
// event is delivered by the broadcaster - since that is done on the thread that is
// waiting for new events, so if we needed more than one event for our handling, we would
// stall. So instead we do it when we fetch the event off of the queue.
//
StateType
Process : : GetNextEvent ( EventSP & event_sp )
{
StateType state = eStateInvalid ;
if ( m_listener . GetNextEventForBroadcaster ( this , event_sp ) & & event_sp )
state = Process : : ProcessEventData : : GetStateFromEvent ( event_sp . get ( ) ) ;
return state ;
}
StateType
2012-09-11 10:33:37 +08:00
Process : : WaitForProcessToStop ( const TimeValue * timeout , lldb : : EventSP * event_sp_ptr )
2010-06-09 00:52:24 +08:00
{
2011-08-09 10:12:22 +08:00
// We can't just wait for a "stopped" event, because the stopped event may have restarted the target.
// We have to actually check each event, and in the case of a stopped event check the restarted flag
// on the event.
2012-09-11 10:33:37 +08:00
if ( event_sp_ptr )
event_sp_ptr - > reset ( ) ;
2011-08-09 10:12:22 +08:00
StateType state = GetState ( ) ;
// If we are exited or detached, we won't ever get back to any
// other valid state...
if ( state = = eStateDetached | | state = = eStateExited )
return state ;
while ( state ! = eStateInvalid )
{
2012-09-11 10:33:37 +08:00
EventSP event_sp ;
2011-08-09 10:12:22 +08:00
state = WaitForStateChangedEvents ( timeout , event_sp ) ;
2012-09-11 10:33:37 +08:00
if ( event_sp_ptr & & event_sp )
* event_sp_ptr = event_sp ;
2011-08-09 10:12:22 +08:00
switch ( state )
{
case eStateCrashed :
case eStateDetached :
case eStateExited :
case eStateUnloaded :
return state ;
case eStateStopped :
if ( Process : : ProcessEventData : : GetRestartedFromEvent ( event_sp . get ( ) ) )
continue ;
else
return state ;
default :
continue ;
}
}
return state ;
2010-06-09 00:52:24 +08:00
}
StateType
Process : : WaitForState
(
const TimeValue * timeout ,
const StateType * match_states , const uint32_t num_match_states
)
{
EventSP event_sp ;
uint32_t i ;
2010-10-07 12:19:01 +08:00
StateType state = GetState ( ) ;
2010-06-09 00:52:24 +08:00
while ( state ! = eStateInvalid )
{
2010-10-07 12:19:01 +08:00
// If we are exited or detached, we won't ever get back to any
// other valid state...
if ( state = = eStateDetached | | state = = eStateExited )
return state ;
2010-06-09 00:52:24 +08:00
state = WaitForStateChangedEvents ( timeout , event_sp ) ;
for ( i = 0 ; i < num_match_states ; + + i )
{
if ( match_states [ i ] = = state )
return state ;
}
}
return state ;
}
2010-10-12 07:53:14 +08:00
bool
Process : : HijackProcessEvents ( Listener * listener )
{
if ( listener ! = NULL )
{
2012-07-28 07:57:19 +08:00
return HijackBroadcaster ( listener , eBroadcastBitStateChanged | eBroadcastBitInterrupt ) ;
2010-10-12 07:53:14 +08:00
}
else
return false ;
}
void
Process : : RestoreProcessEvents ( )
{
RestoreBroadcaster ( ) ;
}
2011-02-08 13:20:59 +08:00
bool
Process : : HijackPrivateProcessEvents ( Listener * listener )
{
if ( listener ! = NULL )
{
2012-07-28 07:57:19 +08:00
return m_private_state_broadcaster . HijackBroadcaster ( listener , eBroadcastBitStateChanged | eBroadcastBitInterrupt ) ;
2011-02-08 13:20:59 +08:00
}
else
return false ;
}
void
Process : : RestorePrivateProcessEvents ( )
{
m_private_state_broadcaster . RestoreBroadcaster ( ) ;
}
2010-06-09 00:52:24 +08:00
StateType
Process : : WaitForStateChangedEvents ( const TimeValue * timeout , EventSP & event_sp )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
2010-06-09 00:52:24 +08:00
if ( log )
log - > Printf ( " Process::%s (timeout = %p, event_sp)... " , __FUNCTION__ , timeout ) ;
StateType state = eStateInvalid ;
2010-10-19 11:25:40 +08:00
if ( m_listener . WaitForEventForBroadcasterWithType ( timeout ,
this ,
2012-07-28 07:57:19 +08:00
eBroadcastBitStateChanged | eBroadcastBitInterrupt ,
2010-10-19 11:25:40 +08:00
event_sp ) )
2012-07-28 07:57:19 +08:00
{
if ( event_sp & & event_sp - > GetType ( ) = = eBroadcastBitStateChanged )
state = Process : : ProcessEventData : : GetStateFromEvent ( event_sp . get ( ) ) ;
else if ( log )
log - > Printf ( " Process::%s got no event or was interrupted. " , __FUNCTION__ ) ;
}
2010-06-09 00:52:24 +08:00
if ( log )
log - > Printf ( " Process::%s (timeout = %p, event_sp) => %s " ,
__FUNCTION__ ,
timeout ,
StateAsCString ( state ) ) ;
return state ;
}
Event *
Process : : PeekAtStateChangedEvents ( )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
2010-06-09 00:52:24 +08:00
if ( log )
log - > Printf ( " Process::%s... " , __FUNCTION__ ) ;
Event * event_ptr ;
2010-10-19 11:25:40 +08:00
event_ptr = m_listener . PeekAtNextEventForBroadcasterWithType ( this ,
eBroadcastBitStateChanged ) ;
2010-06-09 00:52:24 +08:00
if ( log )
{
if ( event_ptr )
{
log - > Printf ( " Process::%s (event_ptr) => %s " ,
__FUNCTION__ ,
StateAsCString ( ProcessEventData : : GetStateFromEvent ( event_ptr ) ) ) ;
}
else
{
log - > Printf ( " Process::%s no events found " ,
__FUNCTION__ ) ;
}
}
return event_ptr ;
}
StateType
Process : : WaitForStateChangedEventsPrivate ( const TimeValue * timeout , EventSP & event_sp )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
2010-06-09 00:52:24 +08:00
if ( log )
log - > Printf ( " Process::%s (timeout = %p, event_sp)... " , __FUNCTION__ , timeout ) ;
StateType state = eStateInvalid ;
2011-01-23 07:43:18 +08:00
if ( m_private_state_listener . WaitForEventForBroadcasterWithType ( timeout ,
& m_private_state_broadcaster ,
2012-07-28 07:57:19 +08:00
eBroadcastBitStateChanged | eBroadcastBitInterrupt ,
2011-01-23 07:43:18 +08:00
event_sp ) )
2012-07-28 07:57:19 +08:00
if ( event_sp & & event_sp - > GetType ( ) = = eBroadcastBitStateChanged )
state = Process : : ProcessEventData : : GetStateFromEvent ( event_sp . get ( ) ) ;
2010-06-09 00:52:24 +08:00
// This is a bit of a hack, but when we wait here we could very well return
// to the command-line, and that could disable the log, which would render the
// log we got above invalid.
if ( log )
2011-01-23 07:43:18 +08:00
{
if ( state = = eStateInvalid )
log - > Printf ( " Process::%s (timeout = %p, event_sp) => TIMEOUT " , __FUNCTION__ , timeout ) ;
else
log - > Printf ( " Process::%s (timeout = %p, event_sp) => %s " , __FUNCTION__ , timeout , StateAsCString ( state ) ) ;
}
2010-06-09 00:52:24 +08:00
return state ;
}
bool
Process : : WaitForEventsPrivate ( const TimeValue * timeout , EventSP & event_sp , bool control_only )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
2010-06-09 00:52:24 +08:00
if ( log )
log - > Printf ( " Process::%s (timeout = %p, event_sp)... " , __FUNCTION__ , timeout ) ;
if ( control_only )
return m_private_state_listener . WaitForEventForBroadcaster ( timeout , & m_private_state_control_broadcaster , event_sp ) ;
else
return m_private_state_listener . WaitForEvent ( timeout , event_sp ) ;
}
bool
Process : : IsRunning ( ) const
{
return StateIsRunningState ( m_public_state . GetValue ( ) ) ;
}
int
Process : : GetExitStatus ( )
{
if ( m_public_state . GetValue ( ) = = eStateExited )
return m_exit_status ;
return - 1 ;
}
2010-12-04 08:10:17 +08:00
2010-06-09 00:52:24 +08:00
const char *
Process : : GetExitDescription ( )
{
if ( m_public_state . GetValue ( ) = = eStateExited & & ! m_exit_string . empty ( ) )
return m_exit_string . c_str ( ) ;
return NULL ;
}
2011-01-23 07:43:18 +08:00
bool
2010-06-09 00:52:24 +08:00
Process : : SetExitStatus ( int status , const char * cstr )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS ) ) ;
2011-01-25 10:58:48 +08:00
if ( log )
log - > Printf ( " Process::SetExitStatus (status=%i (0x%8.8x), description=%s%s%s) " ,
status , status ,
cstr ? " \" " : " " ,
cstr ? cstr : " NULL " ,
cstr ? " \" " : " " ) ;
2011-01-23 07:43:18 +08:00
// We were already in the exited state
if ( m_private_state . GetValue ( ) = = eStateExited )
2011-01-25 10:58:48 +08:00
{
2011-01-27 07:47:29 +08:00
if ( log )
log - > Printf ( " Process::SetExitStatus () ignoring exit status because state was already set to eStateExited " ) ;
2011-01-23 07:43:18 +08:00
return false ;
2011-01-25 10:58:48 +08:00
}
2011-01-23 07:43:18 +08:00
m_exit_status = status ;
if ( cstr )
m_exit_string = cstr ;
else
m_exit_string . clear ( ) ;
2010-06-09 00:52:24 +08:00
2011-01-23 07:43:18 +08:00
DidExit ( ) ;
2010-12-08 13:08:21 +08:00
2011-01-23 07:43:18 +08:00
SetPrivateState ( eStateExited ) ;
return true ;
2010-06-09 00:52:24 +08:00
}
// This static callback can be used to watch for local child processes on
// the current host. The the child process exits, the process will be
// found in the global target list (we want to be completely sure that the
// lldb_private::Process doesn't go away before we can deliver the signal.
bool
2011-11-16 13:37:56 +08:00
Process : : SetProcessExitStatus ( void * callback_baton ,
lldb : : pid_t pid ,
bool exited ,
int signo , // Zero for no signal
int exit_status // Exit value of process if signal is zero
2010-06-09 00:52:24 +08:00
)
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
2011-11-16 13:37:56 +08:00
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::SetProcessExitStatus (baton=%p, pid=% " PRIu64 " , exited=%i, signal=%i, exit_status=%i) \n " ,
2011-11-16 13:37:56 +08:00
callback_baton ,
pid ,
exited ,
signo ,
exit_status ) ;
if ( exited )
2010-06-09 00:52:24 +08:00
{
2010-06-23 09:19:29 +08:00
TargetSP target_sp ( Debugger : : FindTargetWithProcessID ( pid ) ) ;
2010-06-09 00:52:24 +08:00
if ( target_sp )
{
ProcessSP process_sp ( target_sp - > GetProcessSP ( ) ) ;
if ( process_sp )
{
const char * signal_cstr = NULL ;
if ( signo )
signal_cstr = process_sp - > GetUnixSignals ( ) . GetSignalAsCString ( signo ) ;
process_sp - > SetExitStatus ( exit_status , signal_cstr ) ;
}
}
return true ;
}
return false ;
}
2011-08-22 10:49:39 +08:00
void
Process : : UpdateThreadListIfNeeded ( )
{
const uint32_t stop_id = GetStopID ( ) ;
if ( m_thread_list . GetSize ( false ) = = 0 | | stop_id ! = m_thread_list . GetStopID ( ) )
{
2011-11-17 09:23:07 +08:00
const StateType state = GetPrivateState ( ) ;
if ( StateIsStoppedState ( state , true ) )
{
Mutex : : Locker locker ( m_thread_list . GetMutex ( ) ) ;
2011-11-17 12:46:02 +08:00
// m_thread_list does have its own mutex, but we need to
// hold onto the mutex between the call to UpdateThreadList(...)
// and the os->UpdateThreadList(...) so it doesn't change on us
2011-11-17 09:23:07 +08:00
ThreadList new_thread_list ( this ) ;
// Always update the thread list with the protocol specific
2012-04-10 08:18:59 +08:00
// thread list, but only update if "true" is returned
if ( UpdateThreadList ( m_thread_list , new_thread_list ) )
{
2013-03-02 04:04:25 +08:00
// Don't call into the OperatingSystem to update the thread list if we are shutting down, since
// that may call back into the SBAPI's, requiring the API lock which is already held by whoever is
// shutting us down, causing a deadlock.
if ( ! m_destroy_in_process )
{
OperatingSystem * os = GetOperatingSystem ( ) ;
if ( os )
os - > UpdateThreadList ( m_thread_list , new_thread_list ) ;
m_thread_list . Update ( new_thread_list ) ;
m_thread_list . SetStopID ( stop_id ) ;
}
2012-04-10 08:18:59 +08:00
}
2011-11-17 09:23:07 +08:00
}
2011-08-22 10:49:39 +08:00
}
}
<rdar://problem/13010007>
Added the ability for OS plug-ins to lazily populate the thread this. The python OS plug-in classes can now implement the following method:
class OperatingSystemPlugin:
def create_thread(self, tid, context):
# Return a dictionary for a new thread to create it on demand
This will add a new thread to the thread list if it doesn't already exist. The example code in lldb/examples/python/operating_system.py has been updated to show how this call us used.
Cleaned up the code in PythonDataObjects.cpp/h:
- renamed all classes that started with PythonData* to be Python*.
- renamed PythonArray to PythonList. Cleaned up the code to use inheritance where
- Centralized the code that does ref counting in the PythonObject class to a single function.
- Made the "bool PythonObject::Reset(PyObject *)" function be virtual so each subclass can correctly check to ensure a PyObject is of the right type before adopting the object.
- Cleaned up all APIs and added new constructors for the Python* classes to they can all construct form:
- PyObject *
- const PythonObject &
- const lldb::ScriptInterpreterObjectSP &
Cleaned up code in ScriptInterpreterPython:
- Made calling python functions safer by templatizing the production of value formats. Python specifies the value formats based on built in C types (long, long long, etc), and code often uses typedefs for uint32_t, uint64_t, etc when passing arguments down to python. We will now always produce correct value formats as the templatized code will "do the right thing" all the time.
- Fixed issues with the ScriptInterpreterPython::Locker where entering the session and leaving the session had a bunch of issues that could cause the "lldb" module globals lldb.debugger, lldb.target, lldb.process, lldb.thread, and lldb.frame to not be initialized.
llvm-svn: 172873
2013-01-19 07:41:08 +08:00
ThreadSP
Process : : CreateOSPluginThread ( lldb : : tid_t tid , lldb : : addr_t context )
{
OperatingSystem * os = GetOperatingSystem ( ) ;
if ( os )
return os - > CreateThread ( tid , context ) ;
return ThreadSP ( ) ;
}
2013-01-09 06:10:01 +08:00
// This is obsoleted. Staged removal for Xcode.
2010-06-09 00:52:24 +08:00
uint32_t
Process : : GetNextThreadIndexID ( )
{
return + + m_thread_index_id ;
}
2013-01-09 06:10:01 +08:00
uint32_t
Process : : GetNextThreadIndexID ( uint64_t thread_id )
{
return AssignIndexIDToThread ( thread_id ) ;
}
bool
Process : : HasAssignedIndexIDToThread ( uint64_t thread_id )
{
std : : map < uint64_t , uint32_t > : : iterator iterator = m_thread_id_to_index_id_map . find ( thread_id ) ;
if ( iterator = = m_thread_id_to_index_id_map . end ( ) )
{
return false ;
}
else
{
return true ;
}
}
uint32_t
Process : : AssignIndexIDToThread ( uint64_t thread_id )
{
uint32_t result = 0 ;
std : : map < uint64_t , uint32_t > : : iterator iterator = m_thread_id_to_index_id_map . find ( thread_id ) ;
if ( iterator = = m_thread_id_to_index_id_map . end ( ) )
{
result = + + m_thread_index_id ;
m_thread_id_to_index_id_map [ thread_id ] = result ;
}
else
{
result = iterator - > second ;
}
return result ;
}
2010-06-09 00:52:24 +08:00
StateType
Process : : GetState ( )
{
// If any other threads access this we will need a mutex for it
return m_public_state . GetValue ( ) ;
}
void
Process : : SetPublicState ( StateType new_state )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS ) ) ;
2010-06-09 00:52:24 +08:00
if ( log )
log - > Printf ( " Process::SetPublicState (%s) " , StateAsCString ( new_state ) ) ;
2012-04-06 00:12:35 +08:00
const StateType old_state = m_public_state . GetValue ( ) ;
2010-06-09 00:52:24 +08:00
m_public_state . SetValue ( new_state ) ;
2012-04-19 09:40:33 +08:00
// On the transition from Run to Stopped, we unlock the writer end of the
// run lock. The lock gets locked in Resume, which is the public API
// to tell the program to run.
2012-04-06 00:12:35 +08:00
if ( ! IsHijackedForEvent ( eBroadcastBitStateChanged ) )
{
2012-06-02 09:16:20 +08:00
if ( new_state = = eStateDetached )
2012-04-06 00:12:35 +08:00
{
2012-06-02 09:16:20 +08:00
if ( log )
log - > Printf ( " Process::SetPublicState (%s) -- unlocking run lock for detach " , StateAsCString ( new_state ) ) ;
m_run_lock . WriteUnlock ( ) ;
}
else
{
const bool old_state_is_stopped = StateIsStoppedState ( old_state , false ) ;
const bool new_state_is_stopped = StateIsStoppedState ( new_state , false ) ;
if ( old_state_is_stopped ! = new_state_is_stopped )
2012-04-06 00:12:35 +08:00
{
2012-06-02 09:16:20 +08:00
if ( new_state_is_stopped )
{
if ( log )
log - > Printf ( " Process::SetPublicState (%s) -- unlocking run lock " , StateAsCString ( new_state ) ) ;
m_run_lock . WriteUnlock ( ) ;
}
2012-04-06 00:12:35 +08:00
}
}
}
2010-06-09 00:52:24 +08:00
}
2012-04-19 09:40:33 +08:00
Error
Process : : Resume ( )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS ) ) ;
2012-04-19 09:40:33 +08:00
if ( log )
log - > Printf ( " Process::Resume -- locking run lock " ) ;
if ( ! m_run_lock . WriteTryLock ( ) )
{
Error error ( " Resume request failed - process still running. " ) ;
if ( log )
log - > Printf ( " Process::Resume: -- WriteTryLock failed, not resuming. " ) ;
return error ;
}
return PrivateResume ( ) ;
}
2010-06-09 00:52:24 +08:00
StateType
Process : : GetPrivateState ( )
{
return m_private_state . GetValue ( ) ;
}
void
Process : : SetPrivateState ( StateType new_state )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_STATE | LIBLLDB_LOG_PROCESS ) ) ;
2010-06-09 00:52:24 +08:00
bool state_changed = false ;
if ( log )
log - > Printf ( " Process::SetPrivateState (%s) " , StateAsCString ( new_state ) ) ;
Mutex : : Locker locker ( m_private_state . GetMutex ( ) ) ;
const StateType old_state = m_private_state . GetValueNoLock ( ) ;
state_changed = old_state ! = new_state ;
2012-04-06 00:12:35 +08:00
// This code is left commented out in case we ever need to control
// the private process state with another run lock. Right now it doesn't
// seem like we need to do this, but if we ever do, we can uncomment and
// use this code.
// const bool old_state_is_stopped = StateIsStoppedState(old_state, false);
// const bool new_state_is_stopped = StateIsStoppedState(new_state, false);
// if (old_state_is_stopped != new_state_is_stopped)
// {
// if (new_state_is_stopped)
// m_private_run_lock.WriteUnlock();
// else
// m_private_run_lock.WriteLock();
// }
2010-06-09 00:52:24 +08:00
if ( state_changed )
{
m_private_state . SetValueNoLock ( new_state ) ;
2011-11-17 09:23:07 +08:00
if ( StateIsStoppedState ( new_state , false ) )
2010-06-09 00:52:24 +08:00
{
2011-08-09 10:12:22 +08:00
m_mod_id . BumpStopID ( ) ;
2011-01-07 14:08:19 +08:00
m_memory_cache . Clear ( ) ;
2010-06-09 00:52:24 +08:00
if ( log )
2011-08-09 10:12:22 +08:00
log - > Printf ( " Process::SetPrivateState (%s) stop_id = %u " , StateAsCString ( new_state ) , m_mod_id . GetStopID ( ) ) ;
2010-06-09 00:52:24 +08:00
}
// Use our target to get a shared pointer to ourselves...
2012-10-30 04:52:08 +08:00
if ( m_finalize_called & & PrivateStateThreadIsValid ( ) = = false )
BroadcastEvent ( eBroadcastBitStateChanged , new ProcessEventData ( shared_from_this ( ) , new_state ) ) ;
else
m_private_state_broadcaster . BroadcastEvent ( eBroadcastBitStateChanged , new ProcessEventData ( shared_from_this ( ) , new_state ) ) ;
2010-06-09 00:52:24 +08:00
}
else
{
if ( log )
2011-09-21 05:44:10 +08:00
log - > Printf ( " Process::SetPrivateState (%s) state didn't change. Ignoring... " , StateAsCString ( new_state ) ) ;
2010-06-09 00:52:24 +08:00
}
}
2011-11-08 11:00:11 +08:00
void
Process : : SetRunningUserExpression ( bool on )
{
m_mod_id . SetRunningUserExpression ( on ) ;
}
2010-06-09 00:52:24 +08:00
addr_t
Process : : GetImageInfoAddress ( )
{
return LLDB_INVALID_ADDRESS ;
}
2010-11-04 09:54:29 +08:00
//----------------------------------------------------------------------
// LoadImage
//
// This function provides a default implementation that works for most
// unix variants. Any Process subclasses that need to do shared library
// loading differently should override LoadImage and UnloadImage and
// do what is needed.
//----------------------------------------------------------------------
uint32_t
Process : : LoadImage ( const FileSpec & image_spec , Error & error )
{
2012-04-18 08:05:19 +08:00
char path [ PATH_MAX ] ;
image_spec . GetPath ( path , sizeof ( path ) ) ;
2010-11-04 09:54:29 +08:00
DynamicLoader * loader = GetDynamicLoader ( ) ;
if ( loader )
{
error = loader - > CanLoadImage ( ) ;
if ( error . Fail ( ) )
return LLDB_INVALID_IMAGE_TOKEN ;
}
if ( error . Success ( ) )
{
ThreadSP thread_sp ( GetThreadList ( ) . GetSelectedThread ( ) ) ;
if ( thread_sp )
{
StackFrameSP frame_sp ( thread_sp - > GetStackFrameAtIndex ( 0 ) ) ;
if ( frame_sp )
{
ExecutionContext exe_ctx ;
frame_sp - > CalculateExecutionContext ( exe_ctx ) ;
2013-01-15 10:47:48 +08:00
const bool unwind_on_error = true ;
const bool ignore_breakpoints = true ;
2010-11-04 09:54:29 +08:00
StreamString expr ;
expr . Printf ( " dlopen ( \" %s \" , 2) " , path ) ;
const char * prefix = " extern \" C \" void* dlopen (const char *path, int mode); \n " ;
2010-11-30 10:22:11 +08:00
lldb : : ValueObjectSP result_valobj_sp ;
2012-11-01 04:49:04 +08:00
ClangUserExpression : : Evaluate ( exe_ctx ,
eExecutionPolicyAlways ,
lldb : : eLanguageTypeUnknown ,
ClangUserExpression : : eResultTypeAny ,
unwind_on_error ,
2013-01-15 10:47:48 +08:00
ignore_breakpoints ,
2012-11-01 04:49:04 +08:00
expr . GetData ( ) ,
prefix ,
result_valobj_sp ,
true ,
ClangUserExpression : : kDefaultTimeout ) ;
2011-09-09 08:01:43 +08:00
error = result_valobj_sp - > GetError ( ) ;
if ( error . Success ( ) )
2010-11-04 09:54:29 +08:00
{
Scalar scalar ;
2011-03-31 08:19:25 +08:00
if ( result_valobj_sp - > ResolveValue ( scalar ) )
2010-11-04 09:54:29 +08:00
{
addr_t image_ptr = scalar . ULongLong ( LLDB_INVALID_ADDRESS ) ;
if ( image_ptr ! = 0 & & image_ptr ! = LLDB_INVALID_ADDRESS )
{
uint32_t image_token = m_image_tokens . size ( ) ;
m_image_tokens . push_back ( image_ptr ) ;
return image_token ;
}
}
}
}
}
}
2012-04-18 08:05:19 +08:00
if ( ! error . AsCString ( ) )
error . SetErrorStringWithFormat ( " unable to load '%s' " , path ) ;
2010-11-04 09:54:29 +08:00
return LLDB_INVALID_IMAGE_TOKEN ;
}
//----------------------------------------------------------------------
// UnloadImage
//
// This function provides a default implementation that works for most
// unix variants. Any Process subclasses that need to do shared library
// loading differently should override LoadImage and UnloadImage and
// do what is needed.
//----------------------------------------------------------------------
Error
Process : : UnloadImage ( uint32_t image_token )
{
Error error ;
if ( image_token < m_image_tokens . size ( ) )
{
const addr_t image_addr = m_image_tokens [ image_token ] ;
if ( image_addr = = LLDB_INVALID_ADDRESS )
{
error . SetErrorString ( " image already unloaded " ) ;
}
else
{
DynamicLoader * loader = GetDynamicLoader ( ) ;
if ( loader )
error = loader - > CanLoadImage ( ) ;
if ( error . Success ( ) )
{
ThreadSP thread_sp ( GetThreadList ( ) . GetSelectedThread ( ) ) ;
if ( thread_sp )
{
StackFrameSP frame_sp ( thread_sp - > GetStackFrameAtIndex ( 0 ) ) ;
if ( frame_sp )
{
ExecutionContext exe_ctx ;
frame_sp - > CalculateExecutionContext ( exe_ctx ) ;
2013-01-15 10:47:48 +08:00
const bool unwind_on_error = true ;
const bool ignore_breakpoints = true ;
2010-11-04 09:54:29 +08:00
StreamString expr ;
2012-11-30 05:49:15 +08:00
expr . Printf ( " dlclose ((void *)0x% " PRIx64 " ) " , image_addr ) ;
2010-11-04 09:54:29 +08:00
const char * prefix = " extern \" C \" int dlclose(void* handle); \n " ;
2010-11-30 10:22:11 +08:00
lldb : : ValueObjectSP result_valobj_sp ;
2012-11-01 04:49:04 +08:00
ClangUserExpression : : Evaluate ( exe_ctx ,
eExecutionPolicyAlways ,
lldb : : eLanguageTypeUnknown ,
ClangUserExpression : : eResultTypeAny ,
unwind_on_error ,
2013-01-15 10:47:48 +08:00
ignore_breakpoints ,
2012-11-01 04:49:04 +08:00
expr . GetData ( ) ,
prefix ,
result_valobj_sp ,
true ,
ClangUserExpression : : kDefaultTimeout ) ;
2010-11-04 09:54:29 +08:00
if ( result_valobj_sp - > GetError ( ) . Success ( ) )
{
Scalar scalar ;
2011-03-31 08:19:25 +08:00
if ( result_valobj_sp - > ResolveValue ( scalar ) )
2010-11-04 09:54:29 +08:00
{
if ( scalar . UInt ( 1 ) )
{
error . SetErrorStringWithFormat ( " expression failed: \" %s \" " , expr . GetData ( ) ) ;
}
else
{
m_image_tokens [ image_token ] = LLDB_INVALID_ADDRESS ;
}
}
}
else
{
error = result_valobj_sp - > GetError ( ) ;
}
}
}
}
}
}
else
{
error . SetErrorString ( " invalid image token " ) ;
}
return error ;
}
2011-05-12 02:39:18 +08:00
const lldb : : ABISP &
2010-06-09 00:52:24 +08:00
Process : : GetABI ( )
{
2011-05-12 02:39:18 +08:00
if ( ! m_abi_sp )
m_abi_sp = ABI : : FindPlugin ( m_target . GetArchitecture ( ) ) ;
return m_abi_sp ;
2010-06-09 00:52:24 +08:00
}
2010-09-23 10:01:19 +08:00
LanguageRuntime *
2012-03-10 08:22:19 +08:00
Process : : GetLanguageRuntime ( lldb : : LanguageType language , bool retry_if_null )
2010-09-23 10:01:19 +08:00
{
LanguageRuntimeCollection : : iterator pos ;
pos = m_language_runtimes . find ( language ) ;
2012-03-10 08:22:19 +08:00
if ( pos = = m_language_runtimes . end ( ) | | ( retry_if_null & & ! ( * pos ) . second ) )
2010-09-23 10:01:19 +08:00
{
2012-03-10 08:22:19 +08:00
lldb : : LanguageRuntimeSP runtime_sp ( LanguageRuntime : : FindPlugin ( this , language ) ) ;
2010-09-23 10:01:19 +08:00
2012-03-10 08:22:19 +08:00
m_language_runtimes [ language ] = runtime_sp ;
return runtime_sp . get ( ) ;
2010-09-23 10:01:19 +08:00
}
else
return ( * pos ) . second . get ( ) ;
}
CPPLanguageRuntime *
2012-03-10 08:22:19 +08:00
Process : : GetCPPLanguageRuntime ( bool retry_if_null )
2010-09-23 10:01:19 +08:00
{
2012-03-10 08:22:19 +08:00
LanguageRuntime * runtime = GetLanguageRuntime ( eLanguageTypeC_plus_plus , retry_if_null ) ;
2010-09-23 10:01:19 +08:00
if ( runtime ! = NULL & & runtime - > GetLanguageType ( ) = = eLanguageTypeC_plus_plus )
return static_cast < CPPLanguageRuntime * > ( runtime ) ;
return NULL ;
}
ObjCLanguageRuntime *
2012-03-10 08:22:19 +08:00
Process : : GetObjCLanguageRuntime ( bool retry_if_null )
2010-09-23 10:01:19 +08:00
{
2012-03-10 08:22:19 +08:00
LanguageRuntime * runtime = GetLanguageRuntime ( eLanguageTypeObjC , retry_if_null ) ;
2010-09-23 10:01:19 +08:00
if ( runtime ! = NULL & & runtime - > GetLanguageType ( ) = = eLanguageTypeObjC )
return static_cast < ObjCLanguageRuntime * > ( runtime ) ;
return NULL ;
}
2012-05-22 00:51:35 +08:00
bool
Process : : IsPossibleDynamicValue ( ValueObject & in_value )
{
if ( in_value . IsDynamic ( ) )
return false ;
LanguageType known_type = in_value . GetObjectRuntimeLanguage ( ) ;
if ( known_type ! = eLanguageTypeUnknown & & known_type ! = eLanguageTypeC )
{
LanguageRuntime * runtime = GetLanguageRuntime ( known_type ) ;
return runtime ? runtime - > CouldHaveDynamicValue ( in_value ) : false ;
}
LanguageRuntime * cpp_runtime = GetLanguageRuntime ( eLanguageTypeC_plus_plus ) ;
if ( cpp_runtime & & cpp_runtime - > CouldHaveDynamicValue ( in_value ) )
return true ;
LanguageRuntime * objc_runtime = GetLanguageRuntime ( eLanguageTypeObjC ) ;
return objc_runtime ? objc_runtime - > CouldHaveDynamicValue ( in_value ) : false ;
}
2010-06-09 00:52:24 +08:00
BreakpointSiteList &
Process : : GetBreakpointSiteList ( )
{
return m_breakpoint_site_list ;
}
const BreakpointSiteList &
Process : : GetBreakpointSiteList ( ) const
{
return m_breakpoint_site_list ;
}
void
Process : : DisableAllBreakpointSites ( )
{
m_breakpoint_site_list . SetEnabledForAll ( false ) ;
2012-07-04 08:35:43 +08:00
size_t num_sites = m_breakpoint_site_list . GetSize ( ) ;
for ( size_t i = 0 ; i < num_sites ; i + + )
{
2013-02-15 10:06:30 +08:00
DisableBreakpointSite ( m_breakpoint_site_list . GetByIndex ( i ) . get ( ) ) ;
2012-07-04 08:35:43 +08:00
}
2010-06-09 00:52:24 +08:00
}
Error
Process : : ClearBreakpointSiteByID ( lldb : : user_id_t break_id )
{
Error error ( DisableBreakpointSiteByID ( break_id ) ) ;
if ( error . Success ( ) )
m_breakpoint_site_list . Remove ( break_id ) ;
return error ;
}
Error
Process : : DisableBreakpointSiteByID ( lldb : : user_id_t break_id )
{
Error error ;
BreakpointSiteSP bp_site_sp = m_breakpoint_site_list . FindByID ( break_id ) ;
if ( bp_site_sp )
{
if ( bp_site_sp - > IsEnabled ( ) )
2013-02-15 10:06:30 +08:00
error = DisableBreakpointSite ( bp_site_sp . get ( ) ) ;
2010-06-09 00:52:24 +08:00
}
else
{
2012-11-30 05:49:15 +08:00
error . SetErrorStringWithFormat ( " invalid breakpoint site ID: % " PRIu64 , break_id ) ;
2010-06-09 00:52:24 +08:00
}
return error ;
}
Error
Process : : EnableBreakpointSiteByID ( lldb : : user_id_t break_id )
{
Error error ;
BreakpointSiteSP bp_site_sp = m_breakpoint_site_list . FindByID ( break_id ) ;
if ( bp_site_sp )
{
if ( ! bp_site_sp - > IsEnabled ( ) )
2013-02-15 10:06:30 +08:00
error = EnableBreakpointSite ( bp_site_sp . get ( ) ) ;
2010-06-09 00:52:24 +08:00
}
else
{
2012-11-30 05:49:15 +08:00
error . SetErrorStringWithFormat ( " invalid breakpoint site ID: % " PRIu64 , break_id ) ;
2010-06-09 00:52:24 +08:00
}
return error ;
}
2010-07-17 08:56:13 +08:00
lldb : : break_id_t
2012-01-30 04:56:30 +08:00
Process : : CreateBreakpointSite ( const BreakpointLocationSP & owner , bool use_hardware )
2010-06-09 00:52:24 +08:00
{
2011-05-20 02:17:41 +08:00
const addr_t load_addr = owner - > GetAddress ( ) . GetOpcodeLoadAddress ( & m_target ) ;
2010-06-09 00:52:24 +08:00
if ( load_addr ! = LLDB_INVALID_ADDRESS )
{
BreakpointSiteSP bp_site_sp ;
// Look up this breakpoint site. If it exists, then add this new owner, otherwise
// create a new breakpoint site and add it.
bp_site_sp = m_breakpoint_site_list . FindByAddress ( load_addr ) ;
if ( bp_site_sp )
{
bp_site_sp - > AddOwner ( owner ) ;
owner - > SetBreakpointSite ( bp_site_sp ) ;
return bp_site_sp - > GetID ( ) ;
}
else
{
2013-01-26 02:06:21 +08:00
bp_site_sp . reset ( new BreakpointSite ( & m_breakpoint_site_list , owner , load_addr , use_hardware ) ) ;
2010-06-09 00:52:24 +08:00
if ( bp_site_sp )
{
2013-02-15 10:06:30 +08:00
if ( EnableBreakpointSite ( bp_site_sp . get ( ) ) . Success ( ) )
2010-06-09 00:52:24 +08:00
{
owner - > SetBreakpointSite ( bp_site_sp ) ;
return m_breakpoint_site_list . Add ( bp_site_sp ) ;
}
}
}
}
// We failed to enable the breakpoint
return LLDB_INVALID_BREAK_ID ;
}
void
Process : : RemoveOwnerFromBreakpointSite ( lldb : : user_id_t owner_id , lldb : : user_id_t owner_loc_id , BreakpointSiteSP & bp_site_sp )
{
uint32_t num_owners = bp_site_sp - > RemoveOwner ( owner_id , owner_loc_id ) ;
if ( num_owners = = 0 )
{
2013-02-15 10:06:30 +08:00
DisableBreakpointSite ( bp_site_sp . get ( ) ) ;
2010-06-09 00:52:24 +08:00
m_breakpoint_site_list . RemoveByAddress ( bp_site_sp - > GetLoadAddress ( ) ) ;
}
}
size_t
Process : : RemoveBreakpointOpcodesFromBuffer ( addr_t bp_addr , size_t size , uint8_t * buf ) const
{
size_t bytes_removed = 0 ;
addr_t intersect_addr ;
size_t intersect_size ;
size_t opcode_offset ;
size_t idx ;
2011-09-17 16:33:22 +08:00
BreakpointSiteSP bp_sp ;
2011-06-30 03:42:28 +08:00
BreakpointSiteList bp_sites_in_range ;
2010-06-09 00:52:24 +08:00
2011-06-30 03:42:28 +08:00
if ( m_breakpoint_site_list . FindInRange ( bp_addr , bp_addr + size , bp_sites_in_range ) )
2010-06-09 00:52:24 +08:00
{
2011-09-17 16:33:22 +08:00
for ( idx = 0 ; ( bp_sp = bp_sites_in_range . GetByIndex ( idx ) ) ; + + idx )
2010-06-09 00:52:24 +08:00
{
2011-09-17 16:33:22 +08:00
if ( bp_sp - > GetType ( ) = = BreakpointSite : : eSoftware )
2010-06-09 00:52:24 +08:00
{
2011-09-17 16:33:22 +08:00
if ( bp_sp - > IntersectsRange ( bp_addr , size , & intersect_addr , & intersect_size , & opcode_offset ) )
2011-06-30 03:42:28 +08:00
{
assert ( bp_addr < = intersect_addr & & intersect_addr < bp_addr + size ) ;
assert ( bp_addr < intersect_addr + intersect_size & & intersect_addr + intersect_size < = bp_addr + size ) ;
2011-09-17 16:33:22 +08:00
assert ( opcode_offset + intersect_size < = bp_sp - > GetByteSize ( ) ) ;
2011-06-30 03:42:28 +08:00
size_t buf_offset = intersect_addr - bp_addr ;
2011-09-17 16:33:22 +08:00
: : memcpy ( buf + buf_offset , bp_sp - > GetSavedOpcodeBytes ( ) + opcode_offset , intersect_size ) ;
2011-06-30 03:42:28 +08:00
}
2010-06-09 00:52:24 +08:00
}
}
}
return bytes_removed ;
}
2011-03-19 09:12:21 +08:00
size_t
Process : : GetSoftwareBreakpointTrapOpcode ( BreakpointSite * bp_site )
{
PlatformSP platform_sp ( m_target . GetPlatform ( ) ) ;
if ( platform_sp )
return platform_sp - > GetSoftwareBreakpointTrapOpcode ( m_target , bp_site ) ;
return 0 ;
}
2010-06-09 00:52:24 +08:00
Error
Process : : EnableSoftwareBreakpoint ( BreakpointSite * bp_site )
{
Error error ;
assert ( bp_site ! = NULL ) ;
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_BREAKPOINTS ) ) ;
2010-06-09 00:52:24 +08:00
const addr_t bp_addr = bp_site - > GetLoadAddress ( ) ;
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x% " PRIx64 , bp_site - > GetID ( ) , ( uint64_t ) bp_addr ) ;
2010-06-09 00:52:24 +08:00
if ( bp_site - > IsEnabled ( ) )
{
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x% " PRIx64 " -- already enabled " , bp_site - > GetID ( ) , ( uint64_t ) bp_addr ) ;
2010-06-09 00:52:24 +08:00
return error ;
}
if ( bp_addr = = LLDB_INVALID_ADDRESS )
{
error . SetErrorString ( " BreakpointSite contains an invalid load address. " ) ;
return error ;
}
// Ask the lldb::Process subclass to fill in the correct software breakpoint
// trap for the breakpoint site
const size_t bp_opcode_size = GetSoftwareBreakpointTrapOpcode ( bp_site ) ;
if ( bp_opcode_size = = 0 )
{
2012-11-30 05:49:15 +08:00
error . SetErrorStringWithFormat ( " Process::GetSoftwareBreakpointTrapOpcode() returned zero, unable to get breakpoint trap for address 0x% " PRIx64 , bp_addr ) ;
2010-06-09 00:52:24 +08:00
}
else
{
const uint8_t * const bp_opcode_bytes = bp_site - > GetTrapOpcodeBytes ( ) ;
if ( bp_opcode_bytes = = NULL )
{
error . SetErrorString ( " BreakpointSite doesn't contain a valid breakpoint trap opcode. " ) ;
return error ;
}
// Save the original opcode by reading it
if ( DoReadMemory ( bp_addr , bp_site - > GetSavedOpcodeBytes ( ) , bp_opcode_size , error ) = = bp_opcode_size )
{
// Write a software breakpoint in place of the original opcode
if ( DoWriteMemory ( bp_addr , bp_opcode_bytes , bp_opcode_size , error ) = = bp_opcode_size )
{
uint8_t verify_bp_opcode_bytes [ 64 ] ;
if ( DoReadMemory ( bp_addr , verify_bp_opcode_bytes , bp_opcode_size , error ) = = bp_opcode_size )
{
if ( : : memcmp ( bp_opcode_bytes , verify_bp_opcode_bytes , bp_opcode_size ) = = 0 )
{
bp_site - > SetEnabled ( true ) ;
bp_site - > SetType ( BreakpointSite : : eSoftware ) ;
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x% " PRIx64 " -- SUCCESS " ,
2010-06-09 00:52:24 +08:00
bp_site - > GetID ( ) ,
( uint64_t ) bp_addr ) ;
}
else
2011-10-26 08:56:27 +08:00
error . SetErrorString ( " failed to verify the breakpoint trap in memory. " ) ;
2010-06-09 00:52:24 +08:00
}
else
error . SetErrorString ( " Unable to read memory to verify breakpoint trap. " ) ;
}
else
error . SetErrorString ( " Unable to write breakpoint trap to memory. " ) ;
}
else
error . SetErrorString ( " Unable to read memory at breakpoint address. " ) ;
}
2011-01-12 12:20:03 +08:00
if ( log & & error . Fail ( ) )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x% " PRIx64 " -- FAILED: %s " ,
2010-06-09 00:52:24 +08:00
bp_site - > GetID ( ) ,
( uint64_t ) bp_addr ,
error . AsCString ( ) ) ;
return error ;
}
Error
Process : : DisableSoftwareBreakpoint ( BreakpointSite * bp_site )
{
Error error ;
assert ( bp_site ! = NULL ) ;
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_BREAKPOINTS ) ) ;
2010-06-09 00:52:24 +08:00
addr_t bp_addr = bp_site - > GetLoadAddress ( ) ;
lldb : : user_id_t breakID = bp_site - > GetID ( ) ;
if ( log )
2013-02-15 10:06:30 +08:00
log - > Printf ( " Process::DisableSoftwareBreakpoint (breakID = % " PRIu64 " ) addr = 0x% " PRIx64 , breakID , ( uint64_t ) bp_addr ) ;
2010-06-09 00:52:24 +08:00
if ( bp_site - > IsHardware ( ) )
{
error . SetErrorString ( " Breakpoint site is a hardware breakpoint. " ) ;
}
else if ( bp_site - > IsEnabled ( ) )
{
const size_t break_op_size = bp_site - > GetByteSize ( ) ;
const uint8_t * const break_op = bp_site - > GetTrapOpcodeBytes ( ) ;
if ( break_op_size > 0 )
{
// Clear a software breakoint instruction
2010-07-10 04:39:50 +08:00
uint8_t curr_break_op [ 8 ] ;
2010-07-21 02:41:11 +08:00
assert ( break_op_size < = sizeof ( curr_break_op ) ) ;
2010-06-09 00:52:24 +08:00
bool break_op_found = false ;
// Read the breakpoint opcode
if ( DoReadMemory ( bp_addr , curr_break_op , break_op_size , error ) = = break_op_size )
{
bool verify = false ;
// Make sure we have the a breakpoint opcode exists at this address
if ( : : memcmp ( curr_break_op , break_op , break_op_size ) = = 0 )
{
break_op_found = true ;
// We found a valid breakpoint opcode at this address, now restore
// the saved opcode.
if ( DoWriteMemory ( bp_addr , bp_site - > GetSavedOpcodeBytes ( ) , break_op_size , error ) = = break_op_size )
{
verify = true ;
}
else
error . SetErrorString ( " Memory write failed when restoring original opcode. " ) ;
}
else
{
error . SetErrorString ( " Original breakpoint trap is no longer in memory. " ) ;
// Set verify to true and so we can check if the original opcode has already been restored
verify = true ;
}
if ( verify )
{
2010-07-10 04:39:50 +08:00
uint8_t verify_opcode [ 8 ] ;
2010-07-21 02:41:11 +08:00
assert ( break_op_size < sizeof ( verify_opcode ) ) ;
2010-06-09 00:52:24 +08:00
// Verify that our original opcode made it back to the inferior
if ( DoReadMemory ( bp_addr , verify_opcode , break_op_size , error ) = = break_op_size )
{
// compare the memory we just read with the original opcode
if ( : : memcmp ( bp_site - > GetSavedOpcodeBytes ( ) , verify_opcode , break_op_size ) = = 0 )
{
// SUCCESS
bp_site - > SetEnabled ( false ) ;
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::DisableSoftwareBreakpoint (site_id = %d) addr = 0x% " PRIx64 " -- SUCCESS " , bp_site - > GetID ( ) , ( uint64_t ) bp_addr ) ;
2010-06-09 00:52:24 +08:00
return error ;
}
else
{
if ( break_op_found )
error . SetErrorString ( " Failed to restore original opcode. " ) ;
}
}
else
error . SetErrorString ( " Failed to read memory to verify that breakpoint trap was restored. " ) ;
}
}
else
error . SetErrorString ( " Unable to read memory that should contain the breakpoint trap. " ) ;
}
}
else
{
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::DisableSoftwareBreakpoint (site_id = %d) addr = 0x% " PRIx64 " -- already disabled " , bp_site - > GetID ( ) , ( uint64_t ) bp_addr ) ;
2010-06-09 00:52:24 +08:00
return error ;
}
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::DisableSoftwareBreakpoint (site_id = %d) addr = 0x% " PRIx64 " -- FAILED: %s " ,
2010-06-09 00:52:24 +08:00
bp_site - > GetID ( ) ,
( uint64_t ) bp_addr ,
error . AsCString ( ) ) ;
return error ;
}
2011-01-07 14:08:19 +08:00
// Uncomment to verify memory caching works after making changes to caching code
//#define VERIFY_MEMORY_READS
size_t
Process : : ReadMemory ( addr_t addr , void * buf , size_t size , Error & error )
{
2012-06-08 06:26:42 +08:00
if ( ! GetDisableMemoryCache ( ) )
{
# if defined (VERIFY_MEMORY_READS)
// Memory caching is enabled, with debug verification
if ( buf & & size )
{
// Uncomment the line below to make sure memory caching is working.
// I ran this through the test suite and got no assertions, so I am
// pretty confident this is working well. If any changes are made to
// memory caching, uncomment the line below and test your changes!
// Verify all memory reads by using the cache first, then redundantly
// reading the same memory from the inferior and comparing to make sure
// everything is exactly the same.
std : : string verify_buf ( size , ' \0 ' ) ;
assert ( verify_buf . size ( ) = = size ) ;
const size_t cache_bytes_read = m_memory_cache . Read ( this , addr , buf , size , error ) ;
Error verify_error ;
const size_t verify_bytes_read = ReadMemoryFromInferior ( addr , const_cast < char * > ( verify_buf . data ( ) ) , verify_buf . size ( ) , verify_error ) ;
assert ( cache_bytes_read = = verify_bytes_read ) ;
assert ( memcmp ( buf , verify_buf . data ( ) , verify_buf . size ( ) ) = = 0 ) ;
assert ( verify_error . Success ( ) = = error . Success ( ) ) ;
return cache_bytes_read ;
}
return 0 ;
# else // !defined(VERIFY_MEMORY_READS)
// Memory caching is enabled, without debug verification
return m_memory_cache . Read ( addr , buf , size , error ) ;
# endif // defined (VERIFY_MEMORY_READS)
}
else
{
// Memory caching is disabled
return ReadMemoryFromInferior ( addr , buf , size , error ) ;
2011-01-07 14:08:19 +08:00
}
}
2012-05-19 07:20:01 +08:00
size_t
Process : : ReadCStringFromMemory ( addr_t addr , std : : string & out_str , Error & error )
{
2012-05-19 08:18:00 +08:00
char buf [ 256 ] ;
2012-05-19 07:20:01 +08:00
out_str . clear ( ) ;
addr_t curr_addr = addr ;
while ( 1 )
{
size_t length = ReadCStringFromMemory ( curr_addr , buf , sizeof ( buf ) , error ) ;
if ( length = = 0 )
break ;
out_str . append ( buf , length ) ;
// If we got "length - 1" bytes, we didn't get the whole C string, we
// need to read some more characters
if ( length = = sizeof ( buf ) - 1 )
curr_addr + = length ;
else
break ;
}
return out_str . size ( ) ;
}
2011-01-07 14:08:19 +08:00
2011-04-12 13:54:46 +08:00
size_t
2011-12-15 11:14:23 +08:00
Process : : ReadCStringFromMemory ( addr_t addr , char * dst , size_t dst_max_len , Error & result_error )
2011-04-12 13:54:46 +08:00
{
size_t total_cstr_len = 0 ;
if ( dst & & dst_max_len )
{
2011-12-15 11:14:23 +08:00
result_error . Clear ( ) ;
2011-04-12 13:54:46 +08:00
// NULL out everything just to be safe
memset ( dst , 0 , dst_max_len ) ;
Error error ;
addr_t curr_addr = addr ;
const size_t cache_line_size = m_memory_cache . GetMemoryCacheLineSize ( ) ;
size_t bytes_left = dst_max_len - 1 ;
char * curr_dst = dst ;
while ( bytes_left > 0 )
{
addr_t cache_line_bytes_left = cache_line_size - ( curr_addr % cache_line_size ) ;
addr_t bytes_to_read = std : : min < addr_t > ( bytes_left , cache_line_bytes_left ) ;
size_t bytes_read = ReadMemory ( curr_addr , curr_dst , bytes_to_read , error ) ;
if ( bytes_read = = 0 )
{
2011-12-15 11:14:23 +08:00
result_error = error ;
2011-04-12 13:54:46 +08:00
dst [ total_cstr_len ] = ' \0 ' ;
break ;
}
const size_t len = strlen ( curr_dst ) ;
total_cstr_len + = len ;
if ( len < bytes_to_read )
break ;
curr_dst + = bytes_read ;
curr_addr + = bytes_read ;
bytes_left - = bytes_read ;
}
}
2011-12-15 11:14:23 +08:00
else
{
if ( dst = = NULL )
result_error . SetErrorString ( " invalid arguments " ) ;
else
result_error . Clear ( ) ;
}
2011-04-12 13:54:46 +08:00
return total_cstr_len ;
}
2011-01-07 14:08:19 +08:00
size_t
Process : : ReadMemoryFromInferior ( addr_t addr , void * buf , size_t size , Error & error )
2010-06-09 00:52:24 +08:00
{
if ( buf = = NULL | | size = = 0 )
return 0 ;
size_t bytes_read = 0 ;
uint8_t * bytes = ( uint8_t * ) buf ;
while ( bytes_read < size )
{
const size_t curr_size = size - bytes_read ;
const size_t curr_bytes_read = DoReadMemory ( addr + bytes_read ,
bytes + bytes_read ,
curr_size ,
error ) ;
bytes_read + = curr_bytes_read ;
if ( curr_bytes_read = = curr_size | | curr_bytes_read = = 0 )
break ;
}
// Replace any software breakpoint opcodes that fall into this range back
// into "buf" before we return
if ( bytes_read > 0 )
RemoveBreakpointOpcodesFromBuffer ( addr , bytes_read , ( uint8_t * ) buf ) ;
return bytes_read ;
}
2010-12-17 04:01:20 +08:00
uint64_t
Added new lldb_private::Process memory read/write functions to stop a bunch
of duplicated code from appearing all over LLDB:
lldb::addr_t
Process::ReadPointerFromMemory (lldb::addr_t vm_addr, Error &error);
bool
Process::WritePointerToMemory (lldb::addr_t vm_addr, lldb::addr_t ptr_value, Error &error);
size_t
Process::ReadScalarIntegerFromMemory (lldb::addr_t addr, uint32_t byte_size, bool is_signed, Scalar &scalar, Error &error);
size_t
Process::WriteScalarToMemory (lldb::addr_t vm_addr, const Scalar &scalar, uint32_t size, Error &error);
in lldb_private::Process the following functions were renamed:
From:
uint64_t
Process::ReadUnsignedInteger (lldb::addr_t load_addr,
size_t byte_size,
Error &error);
To:
uint64_t
Process::ReadUnsignedIntegerFromMemory (lldb::addr_t load_addr,
size_t byte_size,
uint64_t fail_value,
Error &error);
Cleaned up a lot of code that was manually doing what the above functions do
to use the functions listed above.
Added the ability to get a scalar value as a buffer that can be written down
to a process (byte swapping the Scalar value if needed):
uint32_t
Scalar::GetAsMemoryData (void *dst,
uint32_t dst_len,
lldb::ByteOrder dst_byte_order,
Error &error) const;
The "dst_len" can be smaller that the size of the scalar and the least
significant bytes will be written. "dst_len" can also be larger and the
most significant bytes will be padded with zeroes.
Centralized the code that adds or removes address bits for callable and opcode
addresses into lldb_private::Target:
lldb::addr_t
Target::GetCallableLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const;
lldb::addr_t
Target::GetOpcodeLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const;
All necessary lldb_private::Address functions now use the target versions so
changes should only need to happen in one place if anything needs updating.
Fixed up a lot of places that were calling :
addr_t
Address::GetLoadAddress(Target*);
to call the Address::GetCallableLoadAddress() or Address::GetOpcodeLoadAddress()
as needed. There were many places in the breakpoint code where things could
go wrong for ARM if these weren't used.
llvm-svn: 131878
2011-05-23 06:46:53 +08:00
Process : : ReadUnsignedIntegerFromMemory ( lldb : : addr_t vm_addr , size_t integer_byte_size , uint64_t fail_value , Error & error )
2010-12-17 04:01:20 +08:00
{
Added new lldb_private::Process memory read/write functions to stop a bunch
of duplicated code from appearing all over LLDB:
lldb::addr_t
Process::ReadPointerFromMemory (lldb::addr_t vm_addr, Error &error);
bool
Process::WritePointerToMemory (lldb::addr_t vm_addr, lldb::addr_t ptr_value, Error &error);
size_t
Process::ReadScalarIntegerFromMemory (lldb::addr_t addr, uint32_t byte_size, bool is_signed, Scalar &scalar, Error &error);
size_t
Process::WriteScalarToMemory (lldb::addr_t vm_addr, const Scalar &scalar, uint32_t size, Error &error);
in lldb_private::Process the following functions were renamed:
From:
uint64_t
Process::ReadUnsignedInteger (lldb::addr_t load_addr,
size_t byte_size,
Error &error);
To:
uint64_t
Process::ReadUnsignedIntegerFromMemory (lldb::addr_t load_addr,
size_t byte_size,
uint64_t fail_value,
Error &error);
Cleaned up a lot of code that was manually doing what the above functions do
to use the functions listed above.
Added the ability to get a scalar value as a buffer that can be written down
to a process (byte swapping the Scalar value if needed):
uint32_t
Scalar::GetAsMemoryData (void *dst,
uint32_t dst_len,
lldb::ByteOrder dst_byte_order,
Error &error) const;
The "dst_len" can be smaller that the size of the scalar and the least
significant bytes will be written. "dst_len" can also be larger and the
most significant bytes will be padded with zeroes.
Centralized the code that adds or removes address bits for callable and opcode
addresses into lldb_private::Target:
lldb::addr_t
Target::GetCallableLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const;
lldb::addr_t
Target::GetOpcodeLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const;
All necessary lldb_private::Address functions now use the target versions so
changes should only need to happen in one place if anything needs updating.
Fixed up a lot of places that were calling :
addr_t
Address::GetLoadAddress(Target*);
to call the Address::GetCallableLoadAddress() or Address::GetOpcodeLoadAddress()
as needed. There were many places in the breakpoint code where things could
go wrong for ARM if these weren't used.
llvm-svn: 131878
2011-05-23 06:46:53 +08:00
Scalar scalar ;
if ( ReadScalarIntegerFromMemory ( vm_addr , integer_byte_size , false , scalar , error ) )
return scalar . ULongLong ( fail_value ) ;
return fail_value ;
}
addr_t
Process : : ReadPointerFromMemory ( lldb : : addr_t vm_addr , Error & error )
{
Scalar scalar ;
if ( ReadScalarIntegerFromMemory ( vm_addr , GetAddressByteSize ( ) , false , scalar , error ) )
return scalar . ULongLong ( LLDB_INVALID_ADDRESS ) ;
return LLDB_INVALID_ADDRESS ;
}
bool
Process : : WritePointerToMemory ( lldb : : addr_t vm_addr ,
lldb : : addr_t ptr_value ,
Error & error )
{
Scalar scalar ;
const uint32_t addr_byte_size = GetAddressByteSize ( ) ;
if ( addr_byte_size < = 4 )
scalar = ( uint32_t ) ptr_value ;
2010-12-17 04:01:20 +08:00
else
Added new lldb_private::Process memory read/write functions to stop a bunch
of duplicated code from appearing all over LLDB:
lldb::addr_t
Process::ReadPointerFromMemory (lldb::addr_t vm_addr, Error &error);
bool
Process::WritePointerToMemory (lldb::addr_t vm_addr, lldb::addr_t ptr_value, Error &error);
size_t
Process::ReadScalarIntegerFromMemory (lldb::addr_t addr, uint32_t byte_size, bool is_signed, Scalar &scalar, Error &error);
size_t
Process::WriteScalarToMemory (lldb::addr_t vm_addr, const Scalar &scalar, uint32_t size, Error &error);
in lldb_private::Process the following functions were renamed:
From:
uint64_t
Process::ReadUnsignedInteger (lldb::addr_t load_addr,
size_t byte_size,
Error &error);
To:
uint64_t
Process::ReadUnsignedIntegerFromMemory (lldb::addr_t load_addr,
size_t byte_size,
uint64_t fail_value,
Error &error);
Cleaned up a lot of code that was manually doing what the above functions do
to use the functions listed above.
Added the ability to get a scalar value as a buffer that can be written down
to a process (byte swapping the Scalar value if needed):
uint32_t
Scalar::GetAsMemoryData (void *dst,
uint32_t dst_len,
lldb::ByteOrder dst_byte_order,
Error &error) const;
The "dst_len" can be smaller that the size of the scalar and the least
significant bytes will be written. "dst_len" can also be larger and the
most significant bytes will be padded with zeroes.
Centralized the code that adds or removes address bits for callable and opcode
addresses into lldb_private::Target:
lldb::addr_t
Target::GetCallableLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const;
lldb::addr_t
Target::GetOpcodeLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const;
All necessary lldb_private::Address functions now use the target versions so
changes should only need to happen in one place if anything needs updating.
Fixed up a lot of places that were calling :
addr_t
Address::GetLoadAddress(Target*);
to call the Address::GetCallableLoadAddress() or Address::GetOpcodeLoadAddress()
as needed. There were many places in the breakpoint code where things could
go wrong for ARM if these weren't used.
llvm-svn: 131878
2011-05-23 06:46:53 +08:00
scalar = ptr_value ;
return WriteScalarToMemory ( vm_addr , scalar , addr_byte_size , error ) = = addr_byte_size ;
2010-12-17 04:01:20 +08:00
}
2010-06-09 00:52:24 +08:00
size_t
Process : : WriteMemoryPrivate ( addr_t addr , const void * buf , size_t size , Error & error )
{
size_t bytes_written = 0 ;
const uint8_t * bytes = ( const uint8_t * ) buf ;
while ( bytes_written < size )
{
const size_t curr_size = size - bytes_written ;
const size_t curr_bytes_written = DoWriteMemory ( addr + bytes_written ,
bytes + bytes_written ,
curr_size ,
error ) ;
bytes_written + = curr_bytes_written ;
if ( curr_bytes_written = = curr_size | | curr_bytes_written = = 0 )
break ;
}
return bytes_written ;
}
size_t
Process : : WriteMemory ( addr_t addr , const void * buf , size_t size , Error & error )
{
2011-01-07 14:08:19 +08:00
# if defined (ENABLE_MEMORY_CACHING)
m_memory_cache . Flush ( addr , size ) ;
# endif
2010-06-09 00:52:24 +08:00
if ( buf = = NULL | | size = = 0 )
return 0 ;
2011-04-16 08:01:13 +08:00
2011-08-09 10:12:22 +08:00
m_mod_id . BumpMemoryID ( ) ;
2011-04-16 08:01:13 +08:00
2010-06-09 00:52:24 +08:00
// We need to write any data that would go where any current software traps
// (enabled software breakpoints) any software traps (breakpoints) that we
// may have placed in our tasks memory.
BreakpointSiteList : : collection : : const_iterator iter = m_breakpoint_site_list . GetMap ( ) - > lower_bound ( addr ) ;
BreakpointSiteList : : collection : : const_iterator end = m_breakpoint_site_list . GetMap ( ) - > end ( ) ;
if ( iter = = end | | iter - > second - > GetLoadAddress ( ) > addr + size )
2011-05-16 10:35:02 +08:00
return WriteMemoryPrivate ( addr , buf , size , error ) ;
2010-06-09 00:52:24 +08:00
BreakpointSiteList : : collection : : const_iterator pos ;
size_t bytes_written = 0 ;
2010-07-10 04:39:50 +08:00
addr_t intersect_addr = 0 ;
size_t intersect_size = 0 ;
size_t opcode_offset = 0 ;
2010-06-09 00:52:24 +08:00
const uint8_t * ubuf = ( const uint8_t * ) buf ;
for ( pos = iter ; pos ! = end ; + + pos )
{
BreakpointSiteSP bp ;
bp = pos - > second ;
assert ( bp - > IntersectsRange ( addr , size , & intersect_addr , & intersect_size , & opcode_offset ) ) ;
assert ( addr < = intersect_addr & & intersect_addr < addr + size ) ;
assert ( addr < intersect_addr + intersect_size & & intersect_addr + intersect_size < = addr + size ) ;
assert ( opcode_offset + intersect_size < = bp - > GetByteSize ( ) ) ;
// Check for bytes before this breakpoint
const addr_t curr_addr = addr + bytes_written ;
if ( intersect_addr > curr_addr )
{
// There are some bytes before this breakpoint that we need to
// just write to memory
size_t curr_size = intersect_addr - curr_addr ;
size_t curr_bytes_written = WriteMemoryPrivate ( curr_addr ,
ubuf + bytes_written ,
curr_size ,
error ) ;
bytes_written + = curr_bytes_written ;
if ( curr_bytes_written ! = curr_size )
{
// We weren't able to write all of the requested bytes, we
// are done looping and will return the number of bytes that
// we have written so far.
break ;
}
}
// Now write any bytes that would cover up any software breakpoints
// directly into the breakpoint opcode buffer
: : memcpy ( bp - > GetSavedOpcodeBytes ( ) + opcode_offset , ubuf + bytes_written , intersect_size ) ;
bytes_written + = intersect_size ;
}
// Write any remaining bytes after the last breakpoint if we have any left
if ( bytes_written < size )
bytes_written + = WriteMemoryPrivate ( addr + bytes_written ,
ubuf + bytes_written ,
size - bytes_written ,
error ) ;
2011-04-16 08:01:13 +08:00
2010-06-09 00:52:24 +08:00
return bytes_written ;
}
Added new lldb_private::Process memory read/write functions to stop a bunch
of duplicated code from appearing all over LLDB:
lldb::addr_t
Process::ReadPointerFromMemory (lldb::addr_t vm_addr, Error &error);
bool
Process::WritePointerToMemory (lldb::addr_t vm_addr, lldb::addr_t ptr_value, Error &error);
size_t
Process::ReadScalarIntegerFromMemory (lldb::addr_t addr, uint32_t byte_size, bool is_signed, Scalar &scalar, Error &error);
size_t
Process::WriteScalarToMemory (lldb::addr_t vm_addr, const Scalar &scalar, uint32_t size, Error &error);
in lldb_private::Process the following functions were renamed:
From:
uint64_t
Process::ReadUnsignedInteger (lldb::addr_t load_addr,
size_t byte_size,
Error &error);
To:
uint64_t
Process::ReadUnsignedIntegerFromMemory (lldb::addr_t load_addr,
size_t byte_size,
uint64_t fail_value,
Error &error);
Cleaned up a lot of code that was manually doing what the above functions do
to use the functions listed above.
Added the ability to get a scalar value as a buffer that can be written down
to a process (byte swapping the Scalar value if needed):
uint32_t
Scalar::GetAsMemoryData (void *dst,
uint32_t dst_len,
lldb::ByteOrder dst_byte_order,
Error &error) const;
The "dst_len" can be smaller that the size of the scalar and the least
significant bytes will be written. "dst_len" can also be larger and the
most significant bytes will be padded with zeroes.
Centralized the code that adds or removes address bits for callable and opcode
addresses into lldb_private::Target:
lldb::addr_t
Target::GetCallableLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const;
lldb::addr_t
Target::GetOpcodeLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const;
All necessary lldb_private::Address functions now use the target versions so
changes should only need to happen in one place if anything needs updating.
Fixed up a lot of places that were calling :
addr_t
Address::GetLoadAddress(Target*);
to call the Address::GetCallableLoadAddress() or Address::GetOpcodeLoadAddress()
as needed. There were many places in the breakpoint code where things could
go wrong for ARM if these weren't used.
llvm-svn: 131878
2011-05-23 06:46:53 +08:00
size_t
2013-01-26 02:06:21 +08:00
Process : : WriteScalarToMemory ( addr_t addr , const Scalar & scalar , size_t byte_size , Error & error )
Added new lldb_private::Process memory read/write functions to stop a bunch
of duplicated code from appearing all over LLDB:
lldb::addr_t
Process::ReadPointerFromMemory (lldb::addr_t vm_addr, Error &error);
bool
Process::WritePointerToMemory (lldb::addr_t vm_addr, lldb::addr_t ptr_value, Error &error);
size_t
Process::ReadScalarIntegerFromMemory (lldb::addr_t addr, uint32_t byte_size, bool is_signed, Scalar &scalar, Error &error);
size_t
Process::WriteScalarToMemory (lldb::addr_t vm_addr, const Scalar &scalar, uint32_t size, Error &error);
in lldb_private::Process the following functions were renamed:
From:
uint64_t
Process::ReadUnsignedInteger (lldb::addr_t load_addr,
size_t byte_size,
Error &error);
To:
uint64_t
Process::ReadUnsignedIntegerFromMemory (lldb::addr_t load_addr,
size_t byte_size,
uint64_t fail_value,
Error &error);
Cleaned up a lot of code that was manually doing what the above functions do
to use the functions listed above.
Added the ability to get a scalar value as a buffer that can be written down
to a process (byte swapping the Scalar value if needed):
uint32_t
Scalar::GetAsMemoryData (void *dst,
uint32_t dst_len,
lldb::ByteOrder dst_byte_order,
Error &error) const;
The "dst_len" can be smaller that the size of the scalar and the least
significant bytes will be written. "dst_len" can also be larger and the
most significant bytes will be padded with zeroes.
Centralized the code that adds or removes address bits for callable and opcode
addresses into lldb_private::Target:
lldb::addr_t
Target::GetCallableLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const;
lldb::addr_t
Target::GetOpcodeLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const;
All necessary lldb_private::Address functions now use the target versions so
changes should only need to happen in one place if anything needs updating.
Fixed up a lot of places that were calling :
addr_t
Address::GetLoadAddress(Target*);
to call the Address::GetCallableLoadAddress() or Address::GetOpcodeLoadAddress()
as needed. There were many places in the breakpoint code where things could
go wrong for ARM if these weren't used.
llvm-svn: 131878
2011-05-23 06:46:53 +08:00
{
if ( byte_size = = UINT32_MAX )
byte_size = scalar . GetByteSize ( ) ;
if ( byte_size > 0 )
{
uint8_t buf [ 32 ] ;
const size_t mem_size = scalar . GetAsMemoryData ( buf , byte_size , GetByteOrder ( ) , error ) ;
if ( mem_size > 0 )
return WriteMemory ( addr , buf , mem_size , error ) ;
else
error . SetErrorString ( " failed to get scalar as memory data " ) ;
}
else
{
error . SetErrorString ( " invalid scalar value " ) ;
}
return 0 ;
}
size_t
Process : : ReadScalarIntegerFromMemory ( addr_t addr ,
uint32_t byte_size ,
bool is_signed ,
Scalar & scalar ,
Error & error )
{
uint64_t uval ;
if ( byte_size < = sizeof ( uval ) )
{
size_t bytes_read = ReadMemory ( addr , & uval , byte_size , error ) ;
if ( bytes_read = = byte_size )
{
DataExtractor data ( & uval , sizeof ( uval ) , GetByteOrder ( ) , GetAddressByteSize ( ) ) ;
2013-01-26 02:06:21 +08:00
lldb : : offset_t offset = 0 ;
Added new lldb_private::Process memory read/write functions to stop a bunch
of duplicated code from appearing all over LLDB:
lldb::addr_t
Process::ReadPointerFromMemory (lldb::addr_t vm_addr, Error &error);
bool
Process::WritePointerToMemory (lldb::addr_t vm_addr, lldb::addr_t ptr_value, Error &error);
size_t
Process::ReadScalarIntegerFromMemory (lldb::addr_t addr, uint32_t byte_size, bool is_signed, Scalar &scalar, Error &error);
size_t
Process::WriteScalarToMemory (lldb::addr_t vm_addr, const Scalar &scalar, uint32_t size, Error &error);
in lldb_private::Process the following functions were renamed:
From:
uint64_t
Process::ReadUnsignedInteger (lldb::addr_t load_addr,
size_t byte_size,
Error &error);
To:
uint64_t
Process::ReadUnsignedIntegerFromMemory (lldb::addr_t load_addr,
size_t byte_size,
uint64_t fail_value,
Error &error);
Cleaned up a lot of code that was manually doing what the above functions do
to use the functions listed above.
Added the ability to get a scalar value as a buffer that can be written down
to a process (byte swapping the Scalar value if needed):
uint32_t
Scalar::GetAsMemoryData (void *dst,
uint32_t dst_len,
lldb::ByteOrder dst_byte_order,
Error &error) const;
The "dst_len" can be smaller that the size of the scalar and the least
significant bytes will be written. "dst_len" can also be larger and the
most significant bytes will be padded with zeroes.
Centralized the code that adds or removes address bits for callable and opcode
addresses into lldb_private::Target:
lldb::addr_t
Target::GetCallableLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const;
lldb::addr_t
Target::GetOpcodeLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const;
All necessary lldb_private::Address functions now use the target versions so
changes should only need to happen in one place if anything needs updating.
Fixed up a lot of places that were calling :
addr_t
Address::GetLoadAddress(Target*);
to call the Address::GetCallableLoadAddress() or Address::GetOpcodeLoadAddress()
as needed. There were many places in the breakpoint code where things could
go wrong for ARM if these weren't used.
llvm-svn: 131878
2011-05-23 06:46:53 +08:00
if ( byte_size < = 4 )
scalar = data . GetMaxU32 ( & offset , byte_size ) ;
else
scalar = data . GetMaxU64 ( & offset , byte_size ) ;
if ( is_signed )
scalar . SignExtend ( byte_size * 8 ) ;
return bytes_read ;
}
}
else
{
error . SetErrorStringWithFormat ( " byte size of %u is too large for integer scalar type " , byte_size ) ;
}
return 0 ;
}
2011-05-17 11:37:42 +08:00
# define USE_ALLOCATE_MEMORY_CACHE 1
2010-06-09 00:52:24 +08:00
addr_t
Process : : AllocateMemory ( size_t size , uint32_t permissions , Error & error )
{
2011-06-21 01:32:44 +08:00
if ( GetPrivateState ( ) ! = eStateStopped )
return LLDB_INVALID_ADDRESS ;
2011-05-17 11:37:42 +08:00
# if defined (USE_ALLOCATE_MEMORY_CACHE)
return m_allocated_memory_cache . AllocateMemory ( size , permissions , error ) ;
# else
2011-01-24 03:58:49 +08:00
addr_t allocated_addr = DoAllocateMemory ( size , permissions , error ) ;
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
2011-01-24 03:58:49 +08:00
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::AllocateMemory(size=%4zu, permissions=%s) => 0x%16.16 " PRIx64 " (m_stop_id = %u m_memory_id = %u) " ,
2011-01-24 03:58:49 +08:00
size ,
2011-05-17 11:37:42 +08:00
GetPermissionsAsCString ( permissions ) ,
2011-01-24 03:58:49 +08:00
( uint64_t ) allocated_addr ,
2011-08-09 10:12:22 +08:00
m_mod_id . GetStopID ( ) ,
m_mod_id . GetMemoryID ( ) ) ;
2011-01-24 03:58:49 +08:00
return allocated_addr ;
2011-05-17 11:37:42 +08:00
# endif
2010-06-09 00:52:24 +08:00
}
2011-09-21 07:01:51 +08:00
bool
Process : : CanJIT ( )
{
2012-02-15 06:50:38 +08:00
if ( m_can_jit = = eCanJITDontKnow )
{
Error err ;
uint64_t allocated_memory = AllocateMemory ( 8 ,
ePermissionsReadable | ePermissionsWritable | ePermissionsExecutable ,
err ) ;
if ( err . Success ( ) )
m_can_jit = eCanJITYes ;
else
m_can_jit = eCanJITNo ;
DeallocateMemory ( allocated_memory ) ;
}
2011-09-21 07:01:51 +08:00
return m_can_jit = = eCanJITYes ;
}
void
Process : : SetCanJIT ( bool can_jit )
{
m_can_jit = ( can_jit ? eCanJITYes : eCanJITNo ) ;
}
2010-06-09 00:52:24 +08:00
Error
Process : : DeallocateMemory ( addr_t ptr )
{
2011-05-17 11:37:42 +08:00
Error error ;
# if defined (USE_ALLOCATE_MEMORY_CACHE)
if ( ! m_allocated_memory_cache . DeallocateMemory ( ptr ) )
{
2012-11-30 05:49:15 +08:00
error . SetErrorStringWithFormat ( " deallocation of memory at 0x% " PRIx64 " failed. " , ( uint64_t ) ptr ) ;
2011-05-17 11:37:42 +08:00
}
# else
error = DoDeallocateMemory ( ptr ) ;
2011-01-24 03:58:49 +08:00
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
2011-01-24 03:58:49 +08:00
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::DeallocateMemory(addr=0x%16.16 " PRIx64 " ) => err = %s (m_stop_id = %u, m_memory_id = %u) " ,
2011-01-24 03:58:49 +08:00
ptr ,
error . AsCString ( " SUCCESS " ) ,
2011-08-09 10:12:22 +08:00
m_mod_id . GetStopID ( ) ,
m_mod_id . GetMemoryID ( ) ) ;
2011-05-17 11:37:42 +08:00
# endif
2011-01-24 03:58:49 +08:00
return error ;
2010-06-09 00:52:24 +08:00
}
2012-11-17 08:33:14 +08:00
2012-02-05 10:38:54 +08:00
ModuleSP
2012-02-14 07:10:39 +08:00
Process : : ReadModuleFromMemory ( const FileSpec & file_spec ,
2013-02-02 05:38:35 +08:00
lldb : : addr_t header_addr )
2012-02-05 10:38:54 +08:00
{
2012-02-25 05:55:59 +08:00
ModuleSP module_sp ( new Module ( file_spec , ArchSpec ( ) ) ) ;
2012-02-05 10:38:54 +08:00
if ( module_sp )
{
2012-02-25 05:55:59 +08:00
Error error ;
ObjectFile * objfile = module_sp - > GetMemoryObjectFile ( shared_from_this ( ) , header_addr , error ) ;
if ( objfile )
return module_sp ;
2012-02-05 10:38:54 +08:00
}
2012-02-25 05:55:59 +08:00
return ModuleSP ( ) ;
2012-02-05 10:38:54 +08:00
}
2010-06-09 00:52:24 +08:00
Error
2012-12-18 10:03:49 +08:00
Process : : EnableWatchpoint ( Watchpoint * watchpoint , bool notify )
2010-06-09 00:52:24 +08:00
{
Error error ;
error . SetErrorString ( " watchpoints are not supported " ) ;
return error ;
}
Error
2012-12-18 10:03:49 +08:00
Process : : DisableWatchpoint ( Watchpoint * watchpoint , bool notify )
2010-06-09 00:52:24 +08:00
{
Error error ;
error . SetErrorString ( " watchpoints are not supported " ) ;
return error ;
}
StateType
Process : : WaitForProcessStopPrivate ( const TimeValue * timeout , EventSP & event_sp )
{
StateType state ;
// Now wait for the process to launch and return control to us, and then
// call DidLaunch:
while ( 1 )
{
2011-01-23 07:43:18 +08:00
event_sp . reset ( ) ;
state = WaitForStateChangedEventsPrivate ( timeout , event_sp ) ;
2011-11-17 09:23:07 +08:00
if ( StateIsStoppedState ( state , false ) )
2010-06-09 00:52:24 +08:00
break ;
2011-01-23 07:43:18 +08:00
// If state is invalid, then we timed out
if ( state = = eStateInvalid )
break ;
if ( event_sp )
2010-06-09 00:52:24 +08:00
HandlePrivateEvent ( event_sp ) ;
}
return state ;
}
Error
2011-11-04 05:22:33 +08:00
Process : : Launch ( const ProcessLaunchInfo & launch_info )
2010-06-09 00:52:24 +08:00
{
Error error ;
m_abi_sp . reset ( ) ;
2011-02-16 12:46:07 +08:00
m_dyld_ap . reset ( ) ;
2011-08-22 10:49:39 +08:00
m_os_ap . reset ( ) ;
2010-11-16 13:07:41 +08:00
m_process_input_reader . reset ( ) ;
2010-06-09 00:52:24 +08:00
2011-08-11 10:48:45 +08:00
Module * exe_module = m_target . GetExecutableModulePointer ( ) ;
2010-06-09 00:52:24 +08:00
if ( exe_module )
{
2011-04-30 09:09:13 +08:00
char local_exec_file_path [ PATH_MAX ] ;
char platform_exec_file_path [ PATH_MAX ] ;
exe_module - > GetFileSpec ( ) . GetPath ( local_exec_file_path , sizeof ( local_exec_file_path ) ) ;
exe_module - > GetPlatformFileSpec ( ) . GetPath ( platform_exec_file_path , sizeof ( platform_exec_file_path ) ) ;
2010-06-09 00:52:24 +08:00
if ( exe_module - > GetFileSpec ( ) . Exists ( ) )
{
2011-02-25 06:24:29 +08:00
if ( PrivateStateThreadIsValid ( ) )
PausePrivateStateThread ( ) ;
2010-06-09 00:52:24 +08:00
error = WillLaunch ( exe_module ) ;
if ( error . Success ( ) )
{
2010-10-07 12:19:01 +08:00
SetPublicState ( eStateLaunching ) ;
2011-11-17 12:46:02 +08:00
m_should_detach = false ;
2010-06-09 00:52:24 +08:00
2012-09-05 04:29:05 +08:00
if ( m_run_lock . WriteTryLock ( ) )
{
// Now launch using these arguments.
error = DoLaunch ( exe_module , launch_info ) ;
}
else
{
// This shouldn't happen
error . SetErrorString ( " failed to acquire process run lock " ) ;
}
2010-06-09 00:52:24 +08:00
if ( error . Fail ( ) )
{
if ( GetID ( ) ! = LLDB_INVALID_PROCESS_ID )
{
SetID ( LLDB_INVALID_PROCESS_ID ) ;
const char * error_string = error . AsCString ( ) ;
if ( error_string = = NULL )
error_string = " launch failed " ;
SetExitStatus ( - 1 , error_string ) ;
}
}
else
{
EventSP event_sp ;
2011-06-22 09:42:17 +08:00
TimeValue timeout_time ;
timeout_time = TimeValue : : Now ( ) ;
timeout_time . OffsetWithSeconds ( 10 ) ;
StateType state = WaitForProcessStopPrivate ( & timeout_time , event_sp ) ;
2010-06-09 00:52:24 +08:00
2011-06-22 09:42:17 +08:00
if ( state = = eStateInvalid | | event_sp . get ( ) = = NULL )
{
// We were able to launch the process, but we failed to
// catch the initial stop.
SetExitStatus ( 0 , " failed to catch stop after launch " ) ;
Destroy ( ) ;
}
else if ( state = = eStateStopped | | state = = eStateCrashed )
2010-06-09 00:52:24 +08:00
{
2011-02-16 12:46:07 +08:00
2010-06-09 00:52:24 +08:00
DidLaunch ( ) ;
2012-02-14 07:10:39 +08:00
DynamicLoader * dyld = GetDynamicLoader ( ) ;
if ( dyld )
dyld - > DidLaunch ( ) ;
2011-02-16 12:46:07 +08:00
2011-08-22 10:49:39 +08:00
m_os_ap . reset ( OperatingSystem : : FindPlugin ( this , NULL ) ) ;
2010-06-09 00:52:24 +08:00
// This delays passing the stopped event to listeners till DidLaunch gets
// a chance to complete...
HandlePrivateEvent ( event_sp ) ;
2011-02-25 06:24:29 +08:00
if ( PrivateStateThreadIsValid ( ) )
ResumePrivateStateThread ( ) ;
else
StartPrivateStateThread ( ) ;
2010-06-09 00:52:24 +08:00
}
else if ( state = = eStateExited )
{
// We exited while trying to launch somehow. Don't call DidLaunch as that's
// not likely to work, and return an invalid pid.
HandlePrivateEvent ( event_sp ) ;
}
}
}
}
else
{
2011-10-26 08:56:27 +08:00
error . SetErrorStringWithFormat ( " file doesn't exist: '%s' " , local_exec_file_path ) ;
2010-06-09 00:52:24 +08:00
}
}
return error ;
}
2012-02-09 14:16:32 +08:00
Error
Process : : LoadCore ( )
{
Error error = DoLoadCore ( ) ;
if ( error . Success ( ) )
{
if ( PrivateStateThreadIsValid ( ) )
ResumePrivateStateThread ( ) ;
else
StartPrivateStateThread ( ) ;
2012-02-14 07:10:39 +08:00
DynamicLoader * dyld = GetDynamicLoader ( ) ;
if ( dyld )
dyld - > DidAttach ( ) ;
m_os_ap . reset ( OperatingSystem : : FindPlugin ( this , NULL ) ) ;
2012-02-09 14:16:32 +08:00
// We successfully loaded a core file, now pretend we stopped so we can
// show all of the threads in the core file and explore the crashed
// state.
SetPrivateState ( eStateStopped ) ;
}
return error ;
}
2012-02-14 07:10:39 +08:00
DynamicLoader *
Process : : GetDynamicLoader ( )
{
if ( m_dyld_ap . get ( ) = = NULL )
m_dyld_ap . reset ( DynamicLoader : : FindPlugin ( this , NULL ) ) ;
return m_dyld_ap . get ( ) ;
}
2012-02-09 14:16:32 +08:00
2011-01-29 09:49:25 +08:00
Process : : NextEventAction : : EventActionResult
Process : : AttachCompletionHandler : : PerformAction ( lldb : : EventSP & event_sp )
2010-06-09 00:52:24 +08:00
{
2011-01-29 09:49:25 +08:00
StateType state = ProcessEventData : : GetStateFromEvent ( event_sp . get ( ) ) ;
switch ( state )
2010-06-09 00:52:24 +08:00
{
2011-01-29 15:10:55 +08:00
case eStateRunning :
2011-02-25 06:24:29 +08:00
case eStateConnected :
2011-01-29 15:10:55 +08:00
return eEventActionRetry ;
case eStateStopped :
case eStateCrashed :
2011-11-12 10:10:56 +08:00
{
// During attach, prior to sending the eStateStopped event,
2012-04-13 02:49:31 +08:00
// lldb_private::Process subclasses must set the new process ID.
2011-11-12 10:10:56 +08:00
assert ( m_process - > GetID ( ) ! = LLDB_INVALID_PROCESS_ID ) ;
if ( m_exec_count > 0 )
{
- - m_exec_count ;
2012-04-19 09:40:33 +08:00
m_process - > PrivateResume ( ) ;
2012-05-23 23:46:31 +08:00
Process : : ProcessEventData : : SetRestartedInEvent ( event_sp . get ( ) , true ) ;
2011-11-12 10:10:56 +08:00
return eEventActionRetry ;
}
else
{
m_process - > CompleteAttach ( ) ;
return eEventActionSuccess ;
}
}
2011-01-29 15:10:55 +08:00
break ;
2011-11-12 10:10:56 +08:00
2011-01-29 15:10:55 +08:00
default :
case eStateExited :
case eStateInvalid :
break ;
2010-06-09 00:52:24 +08:00
}
2011-11-12 10:10:56 +08:00
m_exit_string . assign ( " No valid Process " ) ;
return eEventActionExit ;
2011-01-29 09:49:25 +08:00
}
Process : : NextEventAction : : EventActionResult
Process : : AttachCompletionHandler : : HandleBeingInterrupted ( )
{
return eEventActionSuccess ;
}
const char *
Process : : AttachCompletionHandler : : GetExitString ( )
{
return m_exit_string . c_str ( ) ;
2010-06-09 00:52:24 +08:00
}
Error
2011-11-15 11:53:30 +08:00
Process : : Attach ( ProcessAttachInfo & attach_info )
2010-06-09 00:52:24 +08:00
{
m_abi_sp . reset ( ) ;
2010-11-16 13:07:41 +08:00
m_process_input_reader . reset ( ) ;
2011-02-16 12:46:07 +08:00
m_dyld_ap . reset ( ) ;
2011-08-22 10:49:39 +08:00
m_os_ap . reset ( ) ;
2010-08-10 07:31:02 +08:00
2011-11-15 11:53:30 +08:00
lldb : : pid_t attach_pid = attach_info . GetProcessID ( ) ;
2011-03-09 06:40:15 +08:00
Error error ;
2011-11-15 11:53:30 +08:00
if ( attach_pid = = LLDB_INVALID_PROCESS_ID )
2010-08-10 07:31:02 +08:00
{
2011-11-15 11:53:30 +08:00
char process_name [ PATH_MAX ] ;
2011-09-15 09:10:17 +08:00
2011-11-15 11:53:30 +08:00
if ( attach_info . GetExecutableFile ( ) . GetPath ( process_name , sizeof ( process_name ) ) )
2010-08-18 05:54:19 +08:00
{
2011-11-15 11:53:30 +08:00
const bool wait_for_launch = attach_info . GetWaitForLaunch ( ) ;
if ( wait_for_launch )
2011-03-09 06:40:15 +08:00
{
2011-11-15 11:53:30 +08:00
error = WillAttachToProcessWithName ( process_name , wait_for_launch ) ;
if ( error . Success ( ) )
{
2012-10-13 00:10:12 +08:00
if ( m_run_lock . WriteTryLock ( ) )
{
m_should_detach = true ;
SetPublicState ( eStateAttaching ) ;
// Now attach using these arguments.
error = DoAttachToProcessWithName ( process_name , wait_for_launch , attach_info ) ;
}
else
{
// This shouldn't happen
error . SetErrorString ( " failed to acquire process run lock " ) ;
}
2011-11-17 12:46:02 +08:00
2011-11-15 11:53:30 +08:00
if ( error . Fail ( ) )
{
if ( GetID ( ) ! = LLDB_INVALID_PROCESS_ID )
{
SetID ( LLDB_INVALID_PROCESS_ID ) ;
if ( error . AsCString ( ) = = NULL )
error . SetErrorString ( " attach failed " ) ;
SetExitStatus ( - 1 , error . AsCString ( ) ) ;
}
}
else
{
SetNextEventAction ( new Process : : AttachCompletionHandler ( this , attach_info . GetResumeCount ( ) ) ) ;
StartPrivateStateThread ( ) ;
}
return error ;
}
2011-03-09 06:40:15 +08:00
}
2011-11-15 11:53:30 +08:00
else
2011-03-09 06:40:15 +08:00
{
2011-11-15 11:53:30 +08:00
ProcessInstanceInfoList process_infos ;
PlatformSP platform_sp ( m_target . GetPlatform ( ) ) ;
if ( platform_sp )
{
ProcessInstanceInfoMatch match_info ;
match_info . GetProcessInfo ( ) = attach_info ;
match_info . SetNameMatchType ( eNameMatchEquals ) ;
platform_sp - > FindProcesses ( match_info , process_infos ) ;
const uint32_t num_matches = process_infos . GetSize ( ) ;
if ( num_matches = = 1 )
{
attach_pid = process_infos . GetProcessIDAtIndex ( 0 ) ;
// Fall through and attach using the above process ID
}
else
{
match_info . GetProcessInfo ( ) . GetExecutableFile ( ) . GetPath ( process_name , sizeof ( process_name ) ) ;
if ( num_matches > 1 )
error . SetErrorStringWithFormat ( " more than one process named %s " , process_name ) ;
else
error . SetErrorStringWithFormat ( " could not find a process named %s " , process_name ) ;
}
}
else
{
error . SetErrorString ( " invalid platform, can't find processes by name " ) ;
return error ;
}
2011-03-09 06:40:15 +08:00
}
}
else
2011-11-15 11:53:30 +08:00
{
error . SetErrorString ( " invalid process name " ) ;
2010-08-18 05:54:19 +08:00
}
2010-08-10 07:31:02 +08:00
}
2011-11-15 11:53:30 +08:00
if ( attach_pid ! = LLDB_INVALID_PROCESS_ID )
2010-06-09 00:52:24 +08:00
{
2011-11-15 11:53:30 +08:00
error = WillAttachToProcessWithID ( attach_pid ) ;
2011-03-09 06:40:15 +08:00
if ( error . Success ( ) )
2010-06-09 00:52:24 +08:00
{
2011-11-15 11:53:30 +08:00
2012-10-13 00:10:12 +08:00
if ( m_run_lock . WriteTryLock ( ) )
{
// Now attach using these arguments.
m_should_detach = true ;
SetPublicState ( eStateAttaching ) ;
error = DoAttachToProcessWithID ( attach_pid , attach_info ) ;
}
else
{
// This shouldn't happen
error . SetErrorString ( " failed to acquire process run lock " ) ;
}
2011-11-15 11:53:30 +08:00
if ( error . Success ( ) )
{
SetNextEventAction ( new Process : : AttachCompletionHandler ( this , attach_info . GetResumeCount ( ) ) ) ;
StartPrivateStateThread ( ) ;
}
else
2010-06-09 00:52:24 +08:00
{
2011-03-09 06:40:15 +08:00
if ( GetID ( ) ! = LLDB_INVALID_PROCESS_ID )
{
SetID ( LLDB_INVALID_PROCESS_ID ) ;
const char * error_string = error . AsCString ( ) ;
if ( error_string = = NULL )
error_string = " attach failed " ;
2010-06-09 00:52:24 +08:00
2011-03-09 06:40:15 +08:00
SetExitStatus ( - 1 , error_string ) ;
}
}
2010-06-09 00:52:24 +08:00
}
}
return error ;
}
2011-02-16 12:46:07 +08:00
void
Process : : CompleteAttach ( )
{
// Let the process subclass figure out at much as it can about the process
// before we go looking for a dynamic loader plug-in.
DidAttach ( ) ;
2011-09-15 09:10:17 +08:00
// We just attached. If we have a platform, ask it for the process architecture, and if it isn't
// the same as the one we've already set, switch architectures.
PlatformSP platform_sp ( m_target . GetPlatform ( ) ) ;
assert ( platform_sp . get ( ) ) ;
if ( platform_sp )
{
2012-05-08 09:45:38 +08:00
const ArchSpec & target_arch = m_target . GetArchitecture ( ) ;
2013-01-12 04:49:54 +08:00
if ( target_arch . IsValid ( ) & & ! platform_sp - > IsCompatibleArchitecture ( target_arch , false , NULL ) )
2012-05-08 09:45:38 +08:00
{
ArchSpec platform_arch ;
platform_sp = platform_sp - > GetPlatformForArchitecture ( target_arch , & platform_arch ) ;
if ( platform_sp )
{
m_target . SetPlatform ( platform_sp ) ;
m_target . SetArchitecture ( platform_arch ) ;
}
}
else
{
ProcessInstanceInfo process_info ;
platform_sp - > GetProcessInfo ( GetID ( ) , process_info ) ;
const ArchSpec & process_arch = process_info . GetArchitecture ( ) ;
2012-12-14 06:07:14 +08:00
if ( process_arch . IsValid ( ) & & ! m_target . GetArchitecture ( ) . IsExactMatch ( process_arch ) )
2012-05-08 09:45:38 +08:00
m_target . SetArchitecture ( process_arch ) ;
}
2011-09-15 09:10:17 +08:00
}
// We have completed the attach, now it is time to find the dynamic loader
2011-02-16 12:46:07 +08:00
// plug-in
2012-02-14 07:10:39 +08:00
DynamicLoader * dyld = GetDynamicLoader ( ) ;
if ( dyld )
dyld - > DidAttach ( ) ;
2011-02-16 12:46:07 +08:00
2011-08-22 10:49:39 +08:00
m_os_ap . reset ( OperatingSystem : : FindPlugin ( this , NULL ) ) ;
2011-02-16 12:46:07 +08:00
// Figure out which one is the executable, and set that in our target:
2012-11-08 10:22:02 +08:00
const ModuleList & target_modules = m_target . GetImages ( ) ;
2012-05-30 10:19:25 +08:00
Mutex : : Locker modules_locker ( target_modules . GetMutex ( ) ) ;
size_t num_modules = target_modules . GetSize ( ) ;
ModuleSP new_executable_module_sp ;
2011-02-16 12:46:07 +08:00
for ( int i = 0 ; i < num_modules ; i + + )
{
2012-05-30 10:19:25 +08:00
ModuleSP module_sp ( target_modules . GetModuleAtIndexUnlocked ( i ) ) ;
2011-04-12 13:54:46 +08:00
if ( module_sp & & module_sp - > IsExecutable ( ) )
2011-02-16 12:46:07 +08:00
{
2011-08-11 10:48:45 +08:00
if ( m_target . GetExecutableModulePointer ( ) ! = module_sp . get ( ) )
2012-05-30 10:19:25 +08:00
new_executable_module_sp = module_sp ;
2011-02-16 12:46:07 +08:00
break ;
}
}
2012-05-30 10:19:25 +08:00
if ( new_executable_module_sp )
m_target . SetExecutableModule ( new_executable_module_sp , false ) ;
2011-02-16 12:46:07 +08:00
}
2011-02-04 09:58:07 +08:00
Error
2012-09-29 12:02:01 +08:00
Process : : ConnectRemote ( Stream * strm , const char * remote_url )
2011-02-04 09:58:07 +08:00
{
m_abi_sp . reset ( ) ;
m_process_input_reader . reset ( ) ;
// Find the process and its architecture. Make sure it matches the architecture
// of the current Target, and if not adjust it.
2012-09-29 12:02:01 +08:00
Error error ( DoConnectRemote ( strm , remote_url ) ) ;
2011-02-04 09:58:07 +08:00
if ( error . Success ( ) )
{
2011-02-25 06:24:29 +08:00
if ( GetID ( ) ! = LLDB_INVALID_PROCESS_ID )
{
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
EventSP event_sp ;
StateType state = WaitForProcessStopPrivate ( NULL , event_sp ) ;
if ( state = = eStateStopped | | state = = eStateCrashed )
{
// If we attached and actually have a process on the other end, then
// this ended up being the equivalent of an attach.
CompleteAttach ( ) ;
// This delays passing the stopped event to listeners till
// CompleteAttach gets a chance to complete...
HandlePrivateEvent ( event_sp ) ;
}
2011-02-25 06:24:29 +08:00
}
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-31 02:16:51 +08:00
if ( PrivateStateThreadIsValid ( ) )
ResumePrivateStateThread ( ) ;
else
StartPrivateStateThread ( ) ;
2011-02-04 09:58:07 +08:00
}
return error ;
}
2010-06-09 00:52:24 +08:00
Error
2012-04-19 09:40:33 +08:00
Process : : PrivateResume ( )
2010-06-09 00:52:24 +08:00
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_STEP ) ) ;
2010-06-09 00:52:24 +08:00
if ( log )
2013-02-09 09:29:05 +08:00
log - > Printf ( " Process::PrivateResume() m_stop_id = %u, public state: %s private state: %s " ,
2011-08-09 10:12:22 +08:00
m_mod_id . GetStopID ( ) ,
2011-01-24 14:34:17 +08:00
StateAsCString ( m_public_state . GetValue ( ) ) ,
StateAsCString ( m_private_state . GetValue ( ) ) ) ;
2010-06-09 00:52:24 +08:00
Error error ( WillResume ( ) ) ;
// Tell the process it is about to resume before the thread list
if ( error . Success ( ) )
{
2010-12-03 04:53:05 +08:00
// Now let the thread list know we are about to resume so it
2010-06-09 00:52:24 +08:00
// can let all of our threads know that they are about to be
// resumed. Threads will each be called with
// Thread::WillResume(StateType) where StateType contains the state
// that they are supposed to have when the process is resumed
// (suspended/running/stepping). Threads should also check
// their resume signal in lldb::Thread::GetResumeSignal()
// to see if they are suppoed to start back up with a signal.
if ( m_thread_list . WillResume ( ) )
{
2012-04-07 08:00:41 +08:00
// Last thing, do the PreResumeActions.
if ( ! RunPreResumeActions ( ) )
2010-06-09 00:52:24 +08:00
{
2013-02-09 09:29:05 +08:00
error . SetErrorStringWithFormat ( " Process::PrivateResume PreResumeActions failed, not resuming. " ) ;
2012-04-07 08:00:41 +08:00
}
else
{
m_mod_id . BumpResumeID ( ) ;
error = DoResume ( ) ;
if ( error . Success ( ) )
{
DidResume ( ) ;
m_thread_list . DidResume ( ) ;
if ( log )
log - > Printf ( " Process thinks the process has resumed. " ) ;
}
2010-06-09 00:52:24 +08:00
}
}
else
{
2012-09-01 09:02:41 +08:00
// Somebody wanted to run without running. So generate a continue & a stopped event,
// and let the world handle them.
if ( log )
log - > Printf ( " Process::PrivateResume() asked to simulate a start & stop. " ) ;
SetPrivateState ( eStateRunning ) ;
SetPrivateState ( eStateStopped ) ;
2010-06-09 00:52:24 +08:00
}
}
2011-01-24 14:34:17 +08:00
else if ( log )
2013-02-09 09:29:05 +08:00
log - > Printf ( " Process::PrivateResume() got an error \" %s \" . " , error . AsCString ( " <unknown error> " ) ) ;
2010-06-09 00:52:24 +08:00
return error ;
}
Error
Process : : Halt ( )
{
2012-06-06 08:29:30 +08:00
// First make sure we aren't in the middle of handling an event, or we might restart. This is pretty weak, since
// we could just straightaway get another event. It just narrows the window...
m_currently_handling_event . WaitForValueEqualTo ( false ) ;
2011-01-29 09:49:25 +08:00
// Pause our private state thread so we can ensure no one else eats
// the stop event out from under us.
2011-02-08 13:20:59 +08:00
Listener halt_listener ( " lldb.process.halt_listener " ) ;
HijackPrivateProcessEvents ( & halt_listener ) ;
2011-01-29 09:49:25 +08:00
EventSP event_sp ;
2011-01-29 15:10:55 +08:00
Error error ( WillHalt ( ) ) ;
2010-06-09 00:52:24 +08:00
2011-01-29 15:10:55 +08:00
if ( error . Success ( ) )
2011-01-29 09:49:25 +08:00
{
2010-11-18 13:57:03 +08:00
2011-01-29 15:10:55 +08:00
bool caused_stop = false ;
// Ask the process subclass to actually halt our process
error = DoHalt ( caused_stop ) ;
2010-06-09 00:52:24 +08:00
if ( error . Success ( ) )
2010-11-17 10:32:00 +08:00
{
2011-01-29 15:10:55 +08:00
if ( m_public_state . GetValue ( ) = = eStateAttaching )
{
SetExitStatus ( SIGKILL , " Cancelled async attach. " ) ;
Destroy ( ) ;
}
else
2010-11-17 10:32:00 +08:00
{
2011-01-29 09:49:25 +08:00
// If "caused_stop" is true, then DoHalt stopped the process. If
// "caused_stop" is false, the process was already stopped.
// If the DoHalt caused the process to stop, then we want to catch
// this event and set the interrupted bool to true before we pass
// this along so clients know that the process was interrupted by
// a halt command.
if ( caused_stop )
2010-11-18 13:57:03 +08:00
{
2011-02-08 13:20:59 +08:00
// Wait for 1 second for the process to stop.
2011-01-29 09:49:25 +08:00
TimeValue timeout_time ;
timeout_time = TimeValue : : Now ( ) ;
timeout_time . OffsetWithSeconds ( 1 ) ;
2011-02-08 13:20:59 +08:00
bool got_event = halt_listener . WaitForEvent ( & timeout_time , event_sp ) ;
StateType state = ProcessEventData : : GetStateFromEvent ( event_sp . get ( ) ) ;
2011-01-29 09:49:25 +08:00
2011-02-08 13:20:59 +08:00
if ( ! got_event | | state = = eStateInvalid )
2010-11-18 13:57:03 +08:00
{
2011-01-29 09:49:25 +08:00
// We timeout out and didn't get a stop event...
2011-02-08 13:20:59 +08:00
error . SetErrorStringWithFormat ( " Halt timed out. State = %s " , StateAsCString ( GetState ( ) ) ) ;
2010-11-18 13:57:03 +08:00
}
else
{
2011-11-17 09:23:07 +08:00
if ( StateIsStoppedState ( state , false ) )
2011-01-29 09:49:25 +08:00
{
// We caused the process to interrupt itself, so mark this
// as such in the stop event so clients can tell an interrupted
// process from a natural stop
ProcessEventData : : SetInterruptedInEvent ( event_sp . get ( ) , true ) ;
}
else
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
2011-01-29 09:49:25 +08:00
if ( log )
log - > Printf ( " Process::Halt() failed to stop, state is: %s " , StateAsCString ( state ) ) ;
error . SetErrorString ( " Did not get stopped event after halt. " ) ;
}
2010-11-18 13:57:03 +08:00
}
}
2011-01-29 09:49:25 +08:00
DidHalt ( ) ;
}
2010-11-17 10:32:00 +08:00
}
2011-01-29 09:49:25 +08:00
}
// Resume our private state thread before we post the event (if any)
2011-02-08 13:20:59 +08:00
RestorePrivateProcessEvents ( ) ;
2010-11-18 13:57:03 +08:00
2011-01-29 09:49:25 +08:00
// Post any event we might have consumed. If all goes well, we will have
// stopped the process, intercepted the event and set the interrupted
// bool in the event. Post it to the private event queue and that will end up
// correctly setting the state.
if ( event_sp )
m_private_state_broadcaster . BroadcastEvent ( event_sp ) ;
2010-11-18 13:57:03 +08:00
2010-06-09 00:52:24 +08:00
return error ;
}
2013-03-29 09:18:12 +08:00
Error
Process : : HaltForDestroyOrDetach ( lldb : : EventSP & exit_event_sp )
{
Error error ;
if ( m_public_state . GetValue ( ) = = eStateRunning )
{
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
if ( log )
log - > Printf ( " Process::Destroy() About to halt. " ) ;
error = Halt ( ) ;
if ( error . Success ( ) )
{
// Consume the halt event.
TimeValue timeout ( TimeValue : : Now ( ) ) ;
timeout . OffsetWithSeconds ( 1 ) ;
StateType state = WaitForProcessToStop ( & timeout , & exit_event_sp ) ;
// If the process exited while we were waiting for it to stop, put the exited event into
// the shared pointer passed in and return. Our caller doesn't need to do anything else, since
// they don't have a process anymore...
if ( state = = eStateExited | | m_private_state . GetValue ( ) = = eStateExited )
{
if ( log )
log - > Printf ( " Process::HaltForDestroyOrDetach() Process exited while waiting to Halt. " ) ;
return error ;
}
else
exit_event_sp . reset ( ) ; // It is ok to consume any non-exit stop events
if ( state ! = eStateStopped )
{
if ( log )
log - > Printf ( " Process::HaltForDestroyOrDetach() Halt failed to stop, state is: %s " , StateAsCString ( state ) ) ;
// If we really couldn't stop the process then we should just error out here, but if the
// lower levels just bobbled sending the event and we really are stopped, then continue on.
StateType private_state = m_private_state . GetValue ( ) ;
if ( private_state ! = eStateStopped )
{
return error ;
}
}
}
else
{
if ( log )
log - > Printf ( " Process::HaltForDestroyOrDetach() Halt got error: %s " , error . AsCString ( ) ) ;
}
}
return error ;
}
2010-06-09 00:52:24 +08:00
Error
Process : : Detach ( )
{
2013-03-29 09:18:12 +08:00
EventSP exit_event_sp ;
Error error ;
m_destroy_in_process = true ;
error = WillDetach ( ) ;
2010-06-09 00:52:24 +08:00
if ( error . Success ( ) )
{
2013-03-29 09:18:12 +08:00
if ( DetachRequiresHalt ( ) )
{
error = HaltForDestroyOrDetach ( exit_event_sp ) ;
if ( ! error . Success ( ) )
{
m_destroy_in_process = false ;
return error ;
}
else if ( exit_event_sp )
{
// We shouldn't need to do anything else here. There's no process left to detach from...
StopPrivateStateThread ( ) ;
m_destroy_in_process = false ;
return error ;
}
}
2010-06-09 00:52:24 +08:00
error = DoDetach ( ) ;
if ( error . Success ( ) )
{
DidDetach ( ) ;
StopPrivateStateThread ( ) ;
}
}
2013-03-29 09:18:12 +08:00
m_destroy_in_process = false ;
// If we exited when we were waiting for a process to stop, then
// forward the event here so we don't lose the event
if ( exit_event_sp )
{
// Directly broadcast our exited event because we shut down our
// private state thread above
BroadcastEvent ( exit_event_sp ) ;
}
// If we have been interrupted (to kill us) in the middle of running, we may not end up propagating
// the last events through the event system, in which case we might strand the write lock. Unlock
// it here so when we do to tear down the process we don't get an error destroying the lock.
m_run_lock . WriteUnlock ( ) ;
2010-06-09 00:52:24 +08:00
return error ;
}
Error
Process : : Destroy ( )
{
2013-03-02 04:04:25 +08:00
// Tell ourselves we are in the process of destroying the process, so that we don't do any unnecessary work
// that might hinder the destruction. Remember to set this back to false when we are done. That way if the attempt
// failed and the process stays around for some reason it won't be in a confused state.
m_destroy_in_process = true ;
2010-06-09 00:52:24 +08:00
Error error ( WillDestroy ( ) ) ;
if ( error . Success ( ) )
{
2012-09-11 10:33:37 +08:00
EventSP exit_event_sp ;
2013-03-29 09:18:12 +08:00
if ( DestroyRequiresHalt ( ) )
2012-05-23 23:46:31 +08:00
{
2013-03-29 09:18:12 +08:00
error = HaltForDestroyOrDetach ( exit_event_sp ) ;
2012-05-23 23:46:31 +08:00
}
2013-03-29 09:18:12 +08:00
2012-06-06 08:29:30 +08:00
if ( m_public_state . GetValue ( ) ! = eStateRunning )
{
// Ditch all thread plans, and remove all our breakpoints: in case we have to restart the target to
// kill it, we don't want it hitting a breakpoint...
// Only do this if we've stopped, however, since if we didn't manage to halt it above, then
// we're not going to have much luck doing this now.
m_thread_list . DiscardThreadPlans ( ) ;
DisableAllBreakpointSites ( ) ;
}
2013-03-29 09:18:12 +08:00
2010-06-09 00:52:24 +08:00
error = DoDestroy ( ) ;
if ( error . Success ( ) )
{
DidDestroy ( ) ;
StopPrivateStateThread ( ) ;
}
2010-11-16 13:07:41 +08:00
m_stdio_communication . StopReadThread ( ) ;
m_stdio_communication . Disconnect ( ) ;
if ( m_process_input_reader & & m_process_input_reader - > IsActive ( ) )
m_target . GetDebugger ( ) . PopInputReader ( m_process_input_reader ) ;
if ( m_process_input_reader )
m_process_input_reader . reset ( ) ;
2012-09-11 10:33:37 +08:00
// If we exited when we were waiting for a process to stop, then
// forward the event here so we don't lose the event
if ( exit_event_sp )
{
// Directly broadcast our exited event because we shut down our
// private state thread above
BroadcastEvent ( exit_event_sp ) ;
}
2012-04-13 02:49:31 +08:00
// If we have been interrupted (to kill us) in the middle of running, we may not end up propagating
// the last events through the event system, in which case we might strand the write lock. Unlock
// it here so when we do to tear down the process we don't get an error destroying the lock.
m_run_lock . WriteUnlock ( ) ;
2010-06-09 00:52:24 +08:00
}
2013-03-02 04:04:25 +08:00
m_destroy_in_process = false ;
2010-06-09 00:52:24 +08:00
return error ;
}
Error
Process : : Signal ( int signal )
{
Error error ( WillSignal ( ) ) ;
if ( error . Success ( ) )
{
error = DoSignal ( signal ) ;
if ( error . Success ( ) )
DidSignal ( ) ;
}
return error ;
}
2011-02-16 05:59:32 +08:00
lldb : : ByteOrder
Process : : GetByteOrder ( ) const
2010-06-09 00:52:24 +08:00
{
2011-02-16 05:59:32 +08:00
return m_target . GetArchitecture ( ) . GetByteOrder ( ) ;
2010-06-09 00:52:24 +08:00
}
uint32_t
2011-02-16 05:59:32 +08:00
Process : : GetAddressByteSize ( ) const
2010-06-09 00:52:24 +08:00
{
2011-02-16 05:59:32 +08:00
return m_target . GetArchitecture ( ) . GetAddressByteSize ( ) ;
2010-06-09 00:52:24 +08:00
}
2011-02-16 05:59:32 +08:00
2010-06-09 00:52:24 +08:00
bool
Process : : ShouldBroadcastEvent ( Event * event_ptr )
{
const StateType state = Process : : ProcessEventData : : GetStateFromEvent ( event_ptr ) ;
bool return_value = true ;
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_EVENTS | LIBLLDB_LOG_PROCESS ) ) ;
2013-02-09 09:29:05 +08:00
2010-06-09 00:52:24 +08:00
switch ( state )
{
2011-02-04 09:58:07 +08:00
case eStateConnected :
2010-06-09 00:52:24 +08:00
case eStateAttaching :
case eStateLaunching :
case eStateDetached :
case eStateExited :
case eStateUnloaded :
// These events indicate changes in the state of the debugging session, always report them.
return_value = true ;
break ;
case eStateInvalid :
// We stopped for no apparent reason, don't report it.
return_value = false ;
break ;
case eStateRunning :
case eStateStepping :
// If we've started the target running, we handle the cases where we
// are already running and where there is a transition from stopped to
// running differently.
// running -> running: Automatically suppress extra running events
// stopped -> running: Report except when there is one or more no votes
// and no yes votes.
SynchronouslyNotifyStateChanged ( state ) ;
2013-02-09 09:29:05 +08:00
switch ( m_last_broadcast_state )
2010-06-09 00:52:24 +08:00
{
case eStateRunning :
case eStateStepping :
// We always suppress multiple runnings with no PUBLIC stop in between.
return_value = false ;
break ;
default :
// TODO: make this work correctly. For now always report
// run if we aren't running so we don't miss any runnning
// events. If I run the lldb/test/thread/a.out file and
// break at main.cpp:58, run and hit the breakpoints on
// multiple threads, then somehow during the stepping over
// of all breakpoints no run gets reported.
// This is a transition from stop to run.
switch ( m_thread_list . ShouldReportRun ( event_ptr ) )
{
case eVoteYes :
case eVoteNoOpinion :
return_value = true ;
break ;
case eVoteNo :
return_value = false ;
break ;
}
break ;
}
break ;
case eStateStopped :
case eStateCrashed :
case eStateSuspended :
{
// We've stopped. First see if we're going to restart the target.
// If we are going to stop, then we always broadcast the event.
// If we aren't going to stop, let the thread plans decide if we're going to report this event.
2010-06-19 12:45:32 +08:00
// If no thread has an opinion, we don't report it.
2012-05-16 09:32:14 +08:00
RefreshStateAfterStop ( ) ;
2010-11-17 10:32:00 +08:00
if ( ProcessEventData : : GetInterruptedFromEvent ( event_ptr ) )
{
2010-11-18 13:57:03 +08:00
if ( log )
2013-02-09 09:29:05 +08:00
log - > Printf ( " Process::ShouldBroadcastEvent (%p) stopped due to an interrupt, state: %s " ,
event_ptr ,
StateAsCString ( state ) ) ;
return_value = true ;
2010-11-17 10:32:00 +08:00
}
else
2010-06-09 00:52:24 +08:00
{
2013-02-09 09:29:05 +08:00
// It makes no sense to ask "ShouldStop" if we've already been restarted...
// Asking the thread list is also not likely to go well, since we are running again.
// So in that case just report the event.
bool was_restarted = ProcessEventData : : GetRestartedFromEvent ( event_ptr ) ;
bool should_resume = false ;
if ( ! was_restarted )
should_resume = m_thread_list . ShouldStop ( event_ptr ) = = false ;
if ( was_restarted | | should_resume )
2010-06-09 00:52:24 +08:00
{
2013-02-09 09:29:05 +08:00
Vote stop_vote = m_thread_list . ShouldReportStop ( event_ptr ) ;
if ( log )
log - > Printf ( " Process::ShouldBroadcastEvent: should_stop: %i state: %s was_restarted: %i stop_vote: %d. " ,
should_resume ,
StateAsCString ( state ) ,
was_restarted ,
stop_vote ) ;
switch ( stop_vote )
2010-06-09 00:52:24 +08:00
{
case eVoteYes :
2013-02-09 09:29:05 +08:00
return_value = true ;
break ;
2010-06-09 00:52:24 +08:00
case eVoteNoOpinion :
case eVoteNo :
return_value = false ;
break ;
}
2013-02-09 09:29:05 +08:00
2012-09-06 05:13:56 +08:00
if ( ! was_restarted )
2013-02-09 09:29:05 +08:00
{
if ( log )
log - > Printf ( " Process::ShouldBroadcastEvent (%p) Restarting process from state: %s " , event_ptr , StateAsCString ( state ) ) ;
ProcessEventData : : SetRestartedInEvent ( event_ptr , true ) ;
2012-09-06 05:13:56 +08:00
PrivateResume ( ) ;
2013-02-09 09:29:05 +08:00
}
2010-06-09 00:52:24 +08:00
}
else
{
return_value = true ;
SynchronouslyNotifyStateChanged ( state ) ;
}
}
}
2013-02-09 09:29:05 +08:00
break ;
2010-06-09 00:52:24 +08:00
}
2013-02-09 09:29:05 +08:00
// We do some coalescing of events (for instance two consecutive running events get coalesced.)
// But we only coalesce against events we actually broadcast. So we use m_last_broadcast_state
// to track that. NB - you can't use "m_public_state.GetValue()" for that purpose, as was originally done,
// because the PublicState reflects the last event pulled off the queue, and there may be several
// events stacked up on the queue unserviced. So the PublicState may not reflect the last broadcasted event
// yet. m_last_broadcast_state gets updated here.
if ( return_value )
m_last_broadcast_state = state ;
2010-06-09 00:52:24 +08:00
if ( log )
2013-02-09 09:29:05 +08:00
log - > Printf ( " Process::ShouldBroadcastEvent (%p) => new state: %s, last broadcast state: %s - %s " ,
event_ptr ,
StateAsCString ( state ) ,
StateAsCString ( m_last_broadcast_state ) ,
return_value ? " YES " : " NO " ) ;
2010-06-09 00:52:24 +08:00
return return_value ;
}
bool
2012-04-07 08:00:41 +08:00
Process : : StartPrivateStateThread ( bool force )
2010-06-09 00:52:24 +08:00
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EVENTS ) ) ;
2010-06-09 00:52:24 +08:00
2011-04-12 13:54:46 +08:00
bool already_running = PrivateStateThreadIsValid ( ) ;
2010-06-09 00:52:24 +08:00
if ( log )
2011-04-12 13:54:46 +08:00
log - > Printf ( " Process::%s()%s " , __FUNCTION__ , already_running ? " already running " : " starting private state thread " ) ;
2012-04-07 08:00:41 +08:00
if ( ! force & & already_running )
2011-04-12 13:54:46 +08:00
return true ;
2010-06-09 00:52:24 +08:00
// Create a thread that watches our internal state and controls which
// events make it to clients (into the DCProcess event queue).
2011-01-10 05:07:35 +08:00
char thread_name [ 1024 ] ;
2012-04-07 08:00:41 +08:00
if ( already_running )
2012-11-30 05:49:15 +08:00
snprintf ( thread_name , sizeof ( thread_name ) , " <lldb.process.internal-state-override(pid=% " PRIu64 " )> " , GetID ( ) ) ;
2012-04-07 08:00:41 +08:00
else
2012-11-30 05:49:15 +08:00
snprintf ( thread_name , sizeof ( thread_name ) , " <lldb.process.internal-state(pid=% " PRIu64 " )> " , GetID ( ) ) ;
2012-04-10 09:21:57 +08:00
// Create the private state thread, and start it running.
2011-01-10 05:07:35 +08:00
m_private_state_thread = Host : : ThreadCreate ( thread_name , Process : : PrivateStateThread , this , NULL ) ;
2012-04-10 09:21:57 +08:00
bool success = IS_VALID_LLDB_HOST_THREAD ( m_private_state_thread ) ;
if ( success )
{
ResumePrivateStateThread ( ) ;
return true ;
}
else
return false ;
2010-06-09 00:52:24 +08:00
}
void
Process : : PausePrivateStateThread ( )
{
ControlPrivateStateThread ( eBroadcastInternalStateControlPause ) ;
}
void
Process : : ResumePrivateStateThread ( )
{
ControlPrivateStateThread ( eBroadcastInternalStateControlResume ) ;
}
void
Process : : StopPrivateStateThread ( )
{
2011-04-12 13:54:46 +08:00
if ( PrivateStateThreadIsValid ( ) )
ControlPrivateStateThread ( eBroadcastInternalStateControlStop ) ;
2012-04-13 02:49:31 +08:00
else
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
2012-04-13 02:49:31 +08:00
if ( log )
2013-02-09 09:29:05 +08:00
log - > Printf ( " Went to stop the private state thread, but it was already invalid. " ) ;
2012-04-13 02:49:31 +08:00
}
2010-06-09 00:52:24 +08:00
}
void
Process : : ControlPrivateStateThread ( uint32_t signal )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
2010-06-09 00:52:24 +08:00
assert ( signal = = eBroadcastInternalStateControlStop | |
signal = = eBroadcastInternalStateControlPause | |
signal = = eBroadcastInternalStateControlResume ) ;
if ( log )
2011-01-23 01:43:17 +08:00
log - > Printf ( " Process::%s (signal = %d) " , __FUNCTION__ , signal ) ;
2010-06-09 00:52:24 +08:00
2011-01-23 01:43:17 +08:00
// Signal the private state thread. First we should copy this is case the
// thread starts exiting since the private state thread will NULL this out
// when it exits
const lldb : : thread_t private_state_thread = m_private_state_thread ;
2011-02-08 09:34:25 +08:00
if ( IS_VALID_LLDB_HOST_THREAD ( private_state_thread ) )
2010-06-09 00:52:24 +08:00
{
TimeValue timeout_time ;
bool timed_out ;
m_private_state_control_broadcaster . BroadcastEvent ( signal , NULL ) ;
timeout_time = TimeValue : : Now ( ) ;
timeout_time . OffsetWithSeconds ( 2 ) ;
2012-04-13 02:49:31 +08:00
if ( log )
log - > Printf ( " Sending control event of type: %d. " , signal ) ;
2010-06-09 00:52:24 +08:00
m_private_state_control_wait . WaitForValueEqualTo ( true , & timeout_time , & timed_out ) ;
m_private_state_control_wait . SetValue ( false , eBroadcastNever ) ;
if ( signal = = eBroadcastInternalStateControlStop )
{
if ( timed_out )
2012-04-13 02:49:31 +08:00
{
Error error ;
Host : : ThreadCancel ( private_state_thread , & error ) ;
if ( log )
log - > Printf ( " Timed out responding to the control event, cancel got error: \" %s \" . " , error . AsCString ( ) ) ;
}
else
{
if ( log )
log - > Printf ( " The control event killed the private state thread without having to cancel. " ) ;
}
2010-06-09 00:52:24 +08:00
thread_result_t result = NULL ;
2011-01-23 01:43:17 +08:00
Host : : ThreadJoin ( private_state_thread , & result , NULL ) ;
2010-07-23 02:34:21 +08:00
m_private_state_thread = LLDB_INVALID_HOST_THREAD ;
2010-06-09 00:52:24 +08:00
}
}
2012-04-13 02:49:31 +08:00
else
{
if ( log )
log - > Printf ( " Private state thread already dead, no need to signal it to stop. " ) ;
}
2010-06-09 00:52:24 +08:00
}
2012-07-28 07:57:19 +08:00
void
Process : : SendAsyncInterrupt ( )
{
if ( PrivateStateThreadIsValid ( ) )
m_private_state_broadcaster . BroadcastEvent ( Process : : eBroadcastBitInterrupt , NULL ) ;
else
BroadcastEvent ( Process : : eBroadcastBitInterrupt , NULL ) ;
}
2010-06-09 00:52:24 +08:00
void
Process : : HandlePrivateEvent ( EventSP & event_sp )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
2012-06-06 08:29:30 +08:00
m_currently_handling_event . SetValue ( true , eBroadcastNever ) ;
2011-01-29 09:49:25 +08:00
2011-01-25 10:58:48 +08:00
const StateType new_state = Process : : ProcessEventData : : GetStateFromEvent ( event_sp . get ( ) ) ;
2011-01-29 09:49:25 +08:00
// First check to see if anybody wants a shot at this event:
2011-01-29 12:05:41 +08:00
if ( m_next_event_action_ap . get ( ) ! = NULL )
2011-01-29 09:49:25 +08:00
{
2011-01-29 12:05:41 +08:00
NextEventAction : : EventActionResult action_result = m_next_event_action_ap - > PerformAction ( event_sp ) ;
2013-02-09 09:29:05 +08:00
if ( log )
log - > Printf ( " Ran next event action, result was %d. " , action_result ) ;
2011-01-29 09:49:25 +08:00
switch ( action_result )
{
case NextEventAction : : eEventActionSuccess :
SetNextEventAction ( NULL ) ;
break ;
2011-11-12 10:10:56 +08:00
2011-01-29 09:49:25 +08:00
case NextEventAction : : eEventActionRetry :
break ;
2011-11-12 10:10:56 +08:00
2011-01-29 09:49:25 +08:00
case NextEventAction : : eEventActionExit :
2011-01-29 09:57:31 +08:00
// Handle Exiting Here. If we already got an exited event,
// we should just propagate it. Otherwise, swallow this event,
// and set our state to exit so the next event will kill us.
if ( new_state ! = eStateExited )
{
// FIXME: should cons up an exited event, and discard this one.
2011-01-29 12:05:41 +08:00
SetExitStatus ( 0 , m_next_event_action_ap - > GetExitString ( ) ) ;
2011-01-29 09:57:31 +08:00
SetNextEventAction ( NULL ) ;
return ;
}
SetNextEventAction ( NULL ) ;
2011-01-29 09:49:25 +08:00
break ;
}
}
2010-06-09 00:52:24 +08:00
// See if we should broadcast this state to external clients?
const bool should_broadcast = ShouldBroadcastEvent ( event_sp . get ( ) ) ;
if ( should_broadcast )
{
if ( log )
{
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::%s (pid = % " PRIu64 " ) broadcasting new state %s (old state %s) to %s " ,
2011-01-25 10:58:48 +08:00
__FUNCTION__ ,
GetID ( ) ,
StateAsCString ( new_state ) ,
StateAsCString ( GetState ( ) ) ,
IsHijackedForEvent ( eBroadcastBitStateChanged ) ? " hijacked " : " public " ) ;
2010-06-09 00:52:24 +08:00
}
Add a first pass at a "stop hook" mechanism. This allows you to add commands that get run every time the debugger stops, whether due to a breakpoint, the end of a step, interrupt, etc. You can also specify in which context you want the stop hook to run, for instance only on a particular thread, or only in a particular shared library, function, file, line range within a file.
Still need to add "in methods of a class" to the specifiers, and the ability to write the stop hooks in the Scripting language as well as in the Command Language.
llvm-svn: 127457
2011-03-11 11:53:59 +08:00
Process : : ProcessEventData : : SetUpdateStateOnRemoval ( event_sp . get ( ) ) ;
2011-01-25 10:58:48 +08:00
if ( StateIsRunningState ( new_state ) )
2010-11-16 13:07:41 +08:00
PushProcessInputReader ( ) ;
else
PopProcessInputReader ( ) ;
Add a first pass at a "stop hook" mechanism. This allows you to add commands that get run every time the debugger stops, whether due to a breakpoint, the end of a step, interrupt, etc. You can also specify in which context you want the stop hook to run, for instance only on a particular thread, or only in a particular shared library, function, file, line range within a file.
Still need to add "in methods of a class" to the specifiers, and the ability to write the stop hooks in the Scripting language as well as in the Command Language.
llvm-svn: 127457
2011-03-11 11:53:59 +08:00
2010-06-09 00:52:24 +08:00
BroadcastEvent ( event_sp ) ;
}
else
{
if ( log )
{
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::%s (pid = % " PRIu64 " ) suppressing state %s (old state %s): should_broadcast == false " ,
2011-01-25 10:58:48 +08:00
__FUNCTION__ ,
GetID ( ) ,
StateAsCString ( new_state ) ,
2011-09-21 05:44:10 +08:00
StateAsCString ( GetState ( ) ) ) ;
2010-06-09 00:52:24 +08:00
}
}
2012-06-06 08:29:30 +08:00
m_currently_handling_event . SetValue ( false , eBroadcastAlways ) ;
2010-06-09 00:52:24 +08:00
}
void *
Process : : PrivateStateThread ( void * arg )
{
Process * proc = static_cast < Process * > ( arg ) ;
void * result = proc - > RunPrivateStateThread ( ) ;
return result ;
}
void *
Process : : RunPrivateStateThread ( )
{
2012-04-10 09:21:57 +08:00
bool control_only = true ;
2012-04-13 02:49:31 +08:00
m_private_state_control_wait . SetValue ( false , eBroadcastNever ) ;
2010-06-09 00:52:24 +08:00
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
2010-06-09 00:52:24 +08:00
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::%s (arg = %p, pid = % " PRIu64 " ) thread starting... " , __FUNCTION__ , this , GetID ( ) ) ;
2010-06-09 00:52:24 +08:00
bool exit_now = false ;
while ( ! exit_now )
{
EventSP event_sp ;
WaitForEventsPrivate ( NULL , event_sp , control_only ) ;
if ( event_sp - > BroadcasterIs ( & m_private_state_control_broadcaster ) )
{
2012-04-13 02:49:31 +08:00
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::%s (arg = %p, pid = % " PRIu64 " ) got a control event: %d " , __FUNCTION__ , this , GetID ( ) , event_sp - > GetType ( ) ) ;
2012-04-13 02:49:31 +08:00
2010-06-09 00:52:24 +08:00
switch ( event_sp - > GetType ( ) )
{
case eBroadcastInternalStateControlStop :
exit_now = true ;
break ; // doing any internal state managment below
case eBroadcastInternalStateControlPause :
control_only = true ;
break ;
case eBroadcastInternalStateControlResume :
control_only = false ;
break ;
}
2010-11-17 10:32:00 +08:00
2010-06-09 00:52:24 +08:00
m_private_state_control_wait . SetValue ( true , eBroadcastAlways ) ;
2010-11-17 10:32:00 +08:00
continue ;
2010-06-09 00:52:24 +08:00
}
2012-07-28 07:57:19 +08:00
else if ( event_sp - > GetType ( ) = = eBroadcastBitInterrupt )
{
if ( m_public_state . GetValue ( ) = = eStateAttaching )
{
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::%s (arg = %p, pid = % " PRIu64 " ) woke up with an interrupt while attaching - forwarding interrupt. " , __FUNCTION__ , this , GetID ( ) ) ;
2012-07-28 07:57:19 +08:00
BroadcastEvent ( eBroadcastBitInterrupt , NULL ) ;
}
else
{
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::%s (arg = %p, pid = % " PRIu64 " ) woke up with an interrupt - Halting. " , __FUNCTION__ , this , GetID ( ) ) ;
2012-07-28 07:57:19 +08:00
Halt ( ) ;
}
continue ;
}
2010-06-09 00:52:24 +08:00
const StateType internal_state = Process : : ProcessEventData : : GetStateFromEvent ( event_sp . get ( ) ) ;
if ( internal_state ! = eStateInvalid )
{
HandlePrivateEvent ( event_sp ) ;
}
2010-10-18 12:14:23 +08:00
if ( internal_state = = eStateInvalid | |
internal_state = = eStateExited | |
internal_state = = eStateDetached )
2010-11-17 10:32:00 +08:00
{
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::%s (arg = %p, pid = % " PRIu64 " ) about to exit with internal state %s... " , __FUNCTION__ , this , GetID ( ) , StateAsCString ( internal_state ) ) ;
2010-11-17 10:32:00 +08:00
2010-06-09 00:52:24 +08:00
break ;
2010-11-17 10:32:00 +08:00
}
2010-06-09 00:52:24 +08:00
}
2010-10-30 05:48:37 +08:00
// Verify log is still enabled before attempting to write to it...
2010-06-09 00:52:24 +08:00
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::%s (arg = %p, pid = % " PRIu64 " ) thread exiting... " , __FUNCTION__ , this , GetID ( ) ) ;
2010-06-09 00:52:24 +08:00
2011-01-22 15:12:45 +08:00
m_private_state_control_wait . SetValue ( true , eBroadcastAlways ) ;
m_private_state_thread = LLDB_INVALID_HOST_THREAD ;
2010-06-09 00:52:24 +08:00
return NULL ;
}
//------------------------------------------------------------------
// Process Event Data
//------------------------------------------------------------------
Process : : ProcessEventData : : ProcessEventData ( ) :
EventData ( ) ,
m_process_sp ( ) ,
m_state ( eStateInvalid ) ,
2010-07-10 04:39:50 +08:00
m_restarted ( false ) ,
2011-05-23 05:45:01 +08:00
m_update_state ( 0 ) ,
2010-11-17 10:32:00 +08:00
m_interrupted ( false )
2010-06-09 00:52:24 +08:00
{
}
Process : : ProcessEventData : : ProcessEventData ( const ProcessSP & process_sp , StateType state ) :
EventData ( ) ,
m_process_sp ( process_sp ) ,
m_state ( state ) ,
2010-07-10 04:39:50 +08:00
m_restarted ( false ) ,
2011-05-23 05:45:01 +08:00
m_update_state ( 0 ) ,
2010-11-17 10:32:00 +08:00
m_interrupted ( false )
2010-06-09 00:52:24 +08:00
{
}
Process : : ProcessEventData : : ~ ProcessEventData ( )
{
}
const ConstString &
Process : : ProcessEventData : : GetFlavorString ( )
{
static ConstString g_flavor ( " Process::ProcessEventData " ) ;
return g_flavor ;
}
const ConstString &
Process : : ProcessEventData : : GetFlavor ( ) const
{
return ProcessEventData : : GetFlavorString ( ) ;
}
void
Process : : ProcessEventData : : DoOnRemoval ( Event * event_ptr )
{
// This function gets called twice for each event, once when the event gets pulled
2011-05-23 05:45:01 +08:00
// off of the private process event queue, and then any number of times, first when it gets pulled off of
// the public event queue, then other times when we're pretending that this is where we stopped at the
// end of expression evaluation. m_update_state is used to distinguish these
// three cases; it is 0 when we're just pulling it off for private handling,
// and > 1 for expression evaluation, and we don't want to do the breakpoint command handling then.
2010-06-09 00:52:24 +08:00
2011-05-23 05:45:01 +08:00
if ( m_update_state ! = 1 )
2010-06-09 00:52:24 +08:00
return ;
2013-02-09 09:29:05 +08:00
2010-06-09 00:52:24 +08:00
m_process_sp - > SetPublicState ( m_state ) ;
// If we're stopped and haven't restarted, then do the breakpoint commands here:
if ( m_state = = eStateStopped & & ! m_restarted )
2011-11-08 11:00:11 +08:00
{
ThreadList & curr_thread_list = m_process_sp - > GetThreadList ( ) ;
2011-12-02 07:28:38 +08:00
uint32_t num_threads = curr_thread_list . GetSize ( ) ;
uint32_t idx ;
2010-08-04 09:40:35 +08:00
2011-08-09 10:12:22 +08:00
// The actions might change one of the thread's stop_info's opinions about whether we should
// stop the process, so we need to query that as we go.
2011-11-08 11:00:11 +08:00
// One other complication here, is that we try to catch any case where the target has run (except for expressions)
// and immediately exit, but if we get that wrong (which is possible) then the thread list might have changed, and
// that would cause our iteration here to crash. We could make a copy of the thread list, but we'd really like
// to also know if it has changed at all, so we make up a vector of the thread ID's and check what we get back
// against this list & bag out if anything differs.
2011-12-02 07:28:38 +08:00
std : : vector < uint32_t > thread_index_array ( num_threads ) ;
2011-11-08 11:00:11 +08:00
for ( idx = 0 ; idx < num_threads ; + + idx )
thread_index_array [ idx ] = curr_thread_list . GetThreadAtIndex ( idx ) - > GetIndexID ( ) ;
2012-12-14 06:24:15 +08:00
// Use this to track whether we should continue from here. We will only continue the target running if
// no thread says we should stop. Of course if some thread's PerformAction actually sets the target running,
// then it doesn't matter what the other threads say...
bool still_should_stop = false ;
2011-08-09 10:12:22 +08:00
2010-06-09 00:52:24 +08:00
for ( idx = 0 ; idx < num_threads ; + + idx )
{
2011-11-08 11:00:11 +08:00
curr_thread_list = m_process_sp - > GetThreadList ( ) ;
if ( curr_thread_list . GetSize ( ) ! = num_threads )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_STEP | LIBLLDB_LOG_PROCESS ) ) ;
2011-12-02 04:26:15 +08:00
if ( log )
2011-12-02 07:28:38 +08:00
log - > Printf ( " Number of threads changed from %u to %u while processing event. " , num_threads , curr_thread_list . GetSize ( ) ) ;
2011-11-08 11:00:11 +08:00
break ;
}
lldb : : ThreadSP thread_sp = curr_thread_list . GetThreadAtIndex ( idx ) ;
if ( thread_sp - > GetIndexID ( ) ! = thread_index_array [ idx ] )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_STEP | LIBLLDB_LOG_PROCESS ) ) ;
2011-12-02 04:26:15 +08:00
if ( log )
2011-12-02 07:28:38 +08:00
log - > Printf ( " The thread at position %u changed from %u to %u while processing event. " ,
2011-12-02 04:26:15 +08:00
idx ,
thread_index_array [ idx ] ,
thread_sp - > GetIndexID ( ) ) ;
2011-11-08 11:00:11 +08:00
break ;
}
2010-10-20 08:39:53 +08:00
StopInfoSP stop_info_sp = thread_sp - > GetStopInfo ( ) ;
2012-10-16 08:09:33 +08:00
if ( stop_info_sp & & stop_info_sp - > IsValid ( ) )
2010-06-09 00:52:24 +08:00
{
2013-02-09 09:29:05 +08:00
bool this_thread_wants_to_stop ;
if ( stop_info_sp - > GetOverrideShouldStop ( ) )
2011-08-09 10:12:22 +08:00
{
2013-02-09 09:29:05 +08:00
this_thread_wants_to_stop = stop_info_sp - > GetOverriddenShouldStopValue ( ) ;
}
else
{
stop_info_sp - > PerformAction ( event_ptr ) ;
// The stop action might restart the target. If it does, then we want to mark that in the
// event so that whoever is receiving it will know to wait for the running event and reflect
// that state appropriately.
// We also need to stop processing actions, since they aren't expecting the target to be running.
// FIXME: we might have run.
if ( stop_info_sp - > HasTargetRunSinceMe ( ) )
{
SetRestarted ( true ) ;
break ;
}
this_thread_wants_to_stop = stop_info_sp - > ShouldStop ( event_ptr ) ;
2011-08-09 10:12:22 +08:00
}
2012-12-14 06:24:15 +08:00
if ( still_should_stop = = false )
still_should_stop = this_thread_wants_to_stop ;
2010-06-09 00:52:24 +08:00
}
}
2010-08-10 08:59:59 +08:00
2011-08-09 10:12:22 +08:00
if ( m_process_sp - > GetPrivateState ( ) ! = eStateRunning )
Add a first pass at a "stop hook" mechanism. This allows you to add commands that get run every time the debugger stops, whether due to a breakpoint, the end of a step, interrupt, etc. You can also specify in which context you want the stop hook to run, for instance only on a particular thread, or only in a particular shared library, function, file, line range within a file.
Still need to add "in methods of a class" to the specifiers, and the ability to write the stop hooks in the Scripting language as well as in the Command Language.
llvm-svn: 127457
2011-03-11 11:53:59 +08:00
{
2011-08-09 10:12:22 +08:00
if ( ! still_should_stop )
{
// We've been asked to continue, so do that here.
Add a first pass at a "stop hook" mechanism. This allows you to add commands that get run every time the debugger stops, whether due to a breakpoint, the end of a step, interrupt, etc. You can also specify in which context you want the stop hook to run, for instance only on a particular thread, or only in a particular shared library, function, file, line range within a file.
Still need to add "in methods of a class" to the specifiers, and the ability to write the stop hooks in the Scripting language as well as in the Command Language.
llvm-svn: 127457
2011-03-11 11:53:59 +08:00
SetRestarted ( true ) ;
2012-04-19 09:40:33 +08:00
// Use the public resume method here, since this is just
// extending a public resume.
2013-02-09 09:29:05 +08:00
m_process_sp - > PrivateResume ( ) ;
2011-08-09 10:12:22 +08:00
}
else
{
// If we didn't restart, run the Stop Hooks here:
// They might also restart the target, so watch for that.
m_process_sp - > GetTarget ( ) . RunStopHooks ( ) ;
if ( m_process_sp - > GetPrivateState ( ) = = eStateRunning )
SetRestarted ( true ) ;
}
Add a first pass at a "stop hook" mechanism. This allows you to add commands that get run every time the debugger stops, whether due to a breakpoint, the end of a step, interrupt, etc. You can also specify in which context you want the stop hook to run, for instance only on a particular thread, or only in a particular shared library, function, file, line range within a file.
Still need to add "in methods of a class" to the specifiers, and the ability to write the stop hooks in the Scripting language as well as in the Command Language.
llvm-svn: 127457
2011-03-11 11:53:59 +08:00
}
2010-06-09 00:52:24 +08:00
}
}
void
Process : : ProcessEventData : : Dump ( Stream * s ) const
{
if ( m_process_sp )
2012-11-30 05:49:15 +08:00
s - > Printf ( " process = %p (pid = % " PRIu64 " ), " , m_process_sp . get ( ) , m_process_sp - > GetID ( ) ) ;
2010-06-09 00:52:24 +08:00
2011-04-12 13:54:46 +08:00
s - > Printf ( " state = %s " , StateAsCString ( GetState ( ) ) ) ;
2010-06-09 00:52:24 +08:00
}
const Process : : ProcessEventData *
Process : : ProcessEventData : : GetEventDataFromEvent ( const Event * event_ptr )
{
if ( event_ptr )
{
const EventData * event_data = event_ptr - > GetData ( ) ;
if ( event_data & & event_data - > GetFlavor ( ) = = ProcessEventData : : GetFlavorString ( ) )
return static_cast < const ProcessEventData * > ( event_ptr - > GetData ( ) ) ;
}
return NULL ;
}
ProcessSP
Process : : ProcessEventData : : GetProcessFromEvent ( const Event * event_ptr )
{
ProcessSP process_sp ;
const ProcessEventData * data = GetEventDataFromEvent ( event_ptr ) ;
if ( data )
process_sp = data - > GetProcessSP ( ) ;
return process_sp ;
}
StateType
Process : : ProcessEventData : : GetStateFromEvent ( const Event * event_ptr )
{
const ProcessEventData * data = GetEventDataFromEvent ( event_ptr ) ;
if ( data = = NULL )
return eStateInvalid ;
else
return data - > GetState ( ) ;
}
bool
Process : : ProcessEventData : : GetRestartedFromEvent ( const Event * event_ptr )
{
const ProcessEventData * data = GetEventDataFromEvent ( event_ptr ) ;
if ( data = = NULL )
return false ;
else
return data - > GetRestarted ( ) ;
}
void
Process : : ProcessEventData : : SetRestartedInEvent ( Event * event_ptr , bool new_value )
{
ProcessEventData * data = const_cast < ProcessEventData * > ( GetEventDataFromEvent ( event_ptr ) ) ;
if ( data ! = NULL )
data - > SetRestarted ( new_value ) ;
}
2013-02-09 09:29:05 +08:00
size_t
Process : : ProcessEventData : : GetNumRestartedReasons ( const Event * event_ptr )
{
ProcessEventData * data = const_cast < ProcessEventData * > ( GetEventDataFromEvent ( event_ptr ) ) ;
if ( data ! = NULL )
return data - > GetNumRestartedReasons ( ) ;
else
return 0 ;
}
const char *
Process : : ProcessEventData : : GetRestartedReasonAtIndex ( const Event * event_ptr , size_t idx )
{
ProcessEventData * data = const_cast < ProcessEventData * > ( GetEventDataFromEvent ( event_ptr ) ) ;
if ( data ! = NULL )
return data - > GetRestartedReasonAtIndex ( idx ) ;
else
return NULL ;
}
void
Process : : ProcessEventData : : AddRestartedReason ( Event * event_ptr , const char * reason )
{
ProcessEventData * data = const_cast < ProcessEventData * > ( GetEventDataFromEvent ( event_ptr ) ) ;
if ( data ! = NULL )
data - > AddRestartedReason ( reason ) ;
}
2010-11-17 10:32:00 +08:00
bool
Process : : ProcessEventData : : GetInterruptedFromEvent ( const Event * event_ptr )
{
const ProcessEventData * data = GetEventDataFromEvent ( event_ptr ) ;
if ( data = = NULL )
return false ;
else
return data - > GetInterrupted ( ) ;
}
void
Process : : ProcessEventData : : SetInterruptedInEvent ( Event * event_ptr , bool new_value )
{
ProcessEventData * data = const_cast < ProcessEventData * > ( GetEventDataFromEvent ( event_ptr ) ) ;
if ( data ! = NULL )
data - > SetInterrupted ( new_value ) ;
}
2010-06-09 00:52:24 +08:00
bool
Process : : ProcessEventData : : SetUpdateStateOnRemoval ( Event * event_ptr )
{
ProcessEventData * data = const_cast < ProcessEventData * > ( GetEventDataFromEvent ( event_ptr ) ) ;
if ( data )
{
data - > SetUpdateStateOnRemoval ( ) ;
return true ;
}
return false ;
}
2012-02-18 13:35:26 +08:00
lldb : : TargetSP
Process : : CalculateTarget ( )
{
return m_target . shared_from_this ( ) ;
}
2010-06-09 00:52:24 +08:00
void
2010-10-04 09:05:56 +08:00
Process : : CalculateExecutionContext ( ExecutionContext & exe_ctx )
2010-06-09 00:52:24 +08:00
{
2011-09-22 12:58:26 +08:00
exe_ctx . SetTargetPtr ( & m_target ) ;
exe_ctx . SetProcessPtr ( this ) ;
exe_ctx . SetThreadPtr ( NULL ) ;
exe_ctx . SetFramePtr ( NULL ) ;
2010-06-09 00:52:24 +08:00
}
2011-03-09 06:40:15 +08:00
//uint32_t
//Process::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
//{
// return 0;
//}
//
//ArchSpec
//Process::GetArchSpecForExistingProcess (lldb::pid_t pid)
//{
// return Host::GetArchSpecForExistingProcess (pid);
//}
//
//ArchSpec
//Process::GetArchSpecForExistingProcess (const char *process_name)
//{
// return Host::GetArchSpecForExistingProcess (process_name);
//}
//
2010-11-16 13:07:41 +08:00
void
Process : : AppendSTDOUT ( const char * s , size_t len )
{
2010-11-18 13:57:03 +08:00
Mutex : : Locker locker ( m_stdio_communication_mutex ) ;
2010-11-16 13:07:41 +08:00
m_stdout_data . append ( s , len ) ;
2012-10-30 04:52:08 +08:00
BroadcastEventIfUnique ( eBroadcastBitSTDOUT , new ProcessEventData ( shared_from_this ( ) , GetState ( ) ) ) ;
2010-11-16 13:07:41 +08:00
}
2011-11-13 12:45:22 +08:00
void
Process : : AppendSTDERR ( const char * s , size_t len )
{
Mutex : : Locker locker ( m_stdio_communication_mutex ) ;
m_stderr_data . append ( s , len ) ;
2012-10-30 04:52:08 +08:00
BroadcastEventIfUnique ( eBroadcastBitSTDERR , new ProcessEventData ( shared_from_this ( ) , GetState ( ) ) ) ;
2011-11-13 12:45:22 +08:00
}
2012-11-17 08:21:04 +08:00
void
Process : : BroadcastAsyncProfileData ( const char * s , size_t len )
{
Mutex : : Locker locker ( m_profile_data_comm_mutex ) ;
2012-11-30 06:14:45 +08:00
m_profile_data . push_back ( s ) ;
2012-11-17 08:21:04 +08:00
BroadcastEventIfUnique ( eBroadcastBitProfileData , new ProcessEventData ( shared_from_this ( ) , GetState ( ) ) ) ;
}
size_t
Process : : GetAsyncProfileData ( char * buf , size_t buf_size , Error & error )
{
Mutex : : Locker locker ( m_profile_data_comm_mutex ) ;
2012-11-30 06:14:45 +08:00
if ( m_profile_data . empty ( ) )
return 0 ;
size_t bytes_available = m_profile_data . front ( ) . size ( ) ;
2012-11-17 08:21:04 +08:00
if ( bytes_available > 0 )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
2012-11-17 08:21:04 +08:00
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::GetProfileData (buf = %p, size = % " PRIu64 " ) " , buf , ( uint64_t ) buf_size ) ;
2012-11-17 08:21:04 +08:00
if ( bytes_available > buf_size )
{
2012-11-30 06:14:45 +08:00
memcpy ( buf , m_profile_data . front ( ) . data ( ) , buf_size ) ;
m_profile_data . front ( ) . erase ( 0 , buf_size ) ;
2012-11-17 08:21:04 +08:00
bytes_available = buf_size ;
}
else
{
2012-11-30 06:14:45 +08:00
memcpy ( buf , m_profile_data . front ( ) . data ( ) , bytes_available ) ;
m_profile_data . erase ( m_profile_data . begin ( ) ) ;
2012-11-17 08:21:04 +08:00
}
}
return bytes_available ;
}
2011-11-13 12:45:22 +08:00
//------------------------------------------------------------------
// Process STDIO
//------------------------------------------------------------------
size_t
Process : : GetSTDOUT ( char * buf , size_t buf_size , Error & error )
{
Mutex : : Locker locker ( m_stdio_communication_mutex ) ;
size_t bytes_available = m_stdout_data . size ( ) ;
if ( bytes_available > 0 )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
2011-11-13 12:45:22 +08:00
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::GetSTDOUT (buf = %p, size = % " PRIu64 " ) " , buf , ( uint64_t ) buf_size ) ;
2011-11-13 12:45:22 +08:00
if ( bytes_available > buf_size )
{
memcpy ( buf , m_stdout_data . c_str ( ) , buf_size ) ;
m_stdout_data . erase ( 0 , buf_size ) ;
bytes_available = buf_size ;
}
else
{
memcpy ( buf , m_stdout_data . c_str ( ) , bytes_available ) ;
m_stdout_data . clear ( ) ;
}
}
return bytes_available ;
}
size_t
Process : : GetSTDERR ( char * buf , size_t buf_size , Error & error )
{
Mutex : : Locker locker ( m_stdio_communication_mutex ) ;
size_t bytes_available = m_stderr_data . size ( ) ;
if ( bytes_available > 0 )
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_PROCESS ) ) ;
2011-11-13 12:45:22 +08:00
if ( log )
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::GetSTDERR (buf = %p, size = % " PRIu64 " ) " , buf , ( uint64_t ) buf_size ) ;
2011-11-13 12:45:22 +08:00
if ( bytes_available > buf_size )
{
memcpy ( buf , m_stderr_data . c_str ( ) , buf_size ) ;
m_stderr_data . erase ( 0 , buf_size ) ;
bytes_available = buf_size ;
}
else
{
memcpy ( buf , m_stderr_data . c_str ( ) , bytes_available ) ;
m_stderr_data . clear ( ) ;
}
}
return bytes_available ;
}
2010-11-16 13:07:41 +08:00
void
Process : : STDIOReadThreadBytesReceived ( void * baton , const void * src , size_t src_len )
{
Process * process = ( Process * ) baton ;
process - > AppendSTDOUT ( static_cast < const char * > ( src ) , src_len ) ;
}
size_t
Process : : ProcessInputReaderCallback ( void * baton ,
InputReader & reader ,
lldb : : InputReaderAction notification ,
const char * bytes ,
size_t bytes_len )
{
Process * process = ( Process * ) baton ;
switch ( notification )
{
case eInputReaderActivate :
break ;
case eInputReaderDeactivate :
break ;
case eInputReaderReactivate :
break ;
This patch captures and serializes all output being written by the
command line driver, including the lldb prompt being output by
editline, the asynchronous process output & error messages, and
asynchronous messages written by target stop-hooks.
As part of this it introduces a new Stream class,
StreamAsynchronousIO. A StreamAsynchronousIO object is created with a
broadcaster, who will eventually broadcast the stream's data for a
listener to handle, and an event type indicating what type of event
the broadcaster will broadcast. When the Write method is called on a
StreamAsynchronousIO object, the data is appended to an internal
string. When the Flush method is called on a StreamAsynchronousIO
object, it broadcasts it's data string and clears the string.
Anything in lldb-core that needs to generate asynchronous output for
the end-user should use the StreamAsynchronousIO objects.
I have also added a new notification type for InputReaders, to let
them know that a asynchronous output has been written. This is to
allow the input readers to, for example, refresh their prompts and
lines, if desired. I added the case statements to all the input
readers to catch this notification, but I haven't added any code for
handling them yet (except to the IOChannel input reader).
llvm-svn: 130721
2011-05-03 04:41:46 +08:00
case eInputReaderAsynchronousOutputWritten :
break ;
2010-11-16 13:07:41 +08:00
case eInputReaderGotToken :
{
Error error ;
process - > PutSTDIN ( bytes , bytes_len , error ) ;
}
break ;
2010-11-20 04:47:54 +08:00
case eInputReaderInterrupt :
process - > Halt ( ) ;
break ;
case eInputReaderEndOfFile :
process - > AppendSTDOUT ( " ^D " , 2 ) ;
break ;
2010-11-16 13:07:41 +08:00
case eInputReaderDone :
break ;
}
return bytes_len ;
}
void
Process : : ResetProcessInputReader ( )
{
m_process_input_reader . reset ( ) ;
}
void
2011-11-18 06:14:31 +08:00
Process : : SetSTDIOFileDescriptor ( int file_descriptor )
2010-11-16 13:07:41 +08:00
{
// First set up the Read Thread for reading/handling process I/O
std : : auto_ptr < ConnectionFileDescriptor > conn_ap ( new ConnectionFileDescriptor ( file_descriptor , true ) ) ;
if ( conn_ap . get ( ) )
{
m_stdio_communication . SetConnection ( conn_ap . release ( ) ) ;
if ( m_stdio_communication . IsConnected ( ) )
{
m_stdio_communication . SetReadThreadBytesReceivedCallback ( STDIOReadThreadBytesReceived , this ) ;
m_stdio_communication . StartReadThread ( ) ;
// Now read thread is set up, set up input reader.
if ( ! m_process_input_reader . get ( ) )
{
m_process_input_reader . reset ( new InputReader ( m_target . GetDebugger ( ) ) ) ;
Error err ( m_process_input_reader - > Initialize ( Process : : ProcessInputReaderCallback ,
this ,
eInputReaderGranularityByte ,
NULL ,
NULL ,
false ) ) ;
if ( err . Fail ( ) )
m_process_input_reader . reset ( ) ;
}
}
}
}
void
Process : : PushProcessInputReader ( )
{
if ( m_process_input_reader & & ! m_process_input_reader - > IsActive ( ) )
m_target . GetDebugger ( ) . PushInputReader ( m_process_input_reader ) ;
}
void
Process : : PopProcessInputReader ( )
{
if ( m_process_input_reader & & m_process_input_reader - > IsActive ( ) )
m_target . GetDebugger ( ) . PopInputReader ( m_process_input_reader ) ;
}
2011-02-18 09:44:25 +08:00
// The process needs to know about installed plug-ins
2010-11-19 07:32:35 +08:00
void
2011-03-11 06:14:10 +08:00
Process : : SettingsInitialize ( )
2010-11-19 07:32:35 +08:00
{
2012-08-23 01:17:09 +08:00
// static std::vector<OptionEnumValueElement> g_plugins;
//
// int i=0;
// const char *name;
// OptionEnumValueElement option_enum;
// while ((name = PluginManager::GetProcessPluginNameAtIndex (i)) != NULL)
// {
// if (name)
// {
// option_enum.value = i;
// option_enum.string_value = name;
// option_enum.usage = PluginManager::GetProcessPluginDescriptionAtIndex (i);
// g_plugins.push_back (option_enum);
// }
// ++i;
// }
// option_enum.value = 0;
// option_enum.string_value = NULL;
// option_enum.usage = NULL;
// g_plugins.push_back (option_enum);
//
// for (i=0; (name = SettingsController::instance_settings_table[i].var_name); ++i)
// {
// if (::strcmp (name, "plugin") == 0)
// {
// SettingsController::instance_settings_table[i].enum_values = &g_plugins[0];
// break;
// }
// }
//
2012-08-23 02:39:03 +08:00
Thread : : SettingsInitialize ( ) ;
2010-11-19 07:32:35 +08:00
}
2010-09-04 08:03:46 +08:00
2011-02-18 09:44:25 +08:00
void
2011-03-11 06:14:10 +08:00
Process : : SettingsTerminate ( )
2010-11-19 07:32:35 +08:00
{
2012-08-23 02:39:03 +08:00
Thread : : SettingsTerminate ( ) ;
2010-09-04 08:03:46 +08:00
}
2010-12-14 10:59:59 +08:00
ExecutionResults
2010-11-30 10:22:11 +08:00
Process : : RunThreadPlan ( ExecutionContext & exe_ctx ,
2012-04-07 08:00:41 +08:00
lldb : : ThreadPlanSP & thread_plan_sp ,
2010-11-30 10:22:11 +08:00
bool stop_others ,
2012-10-17 05:41:58 +08:00
bool run_others ,
2013-01-15 10:47:48 +08:00
bool unwind_on_error ,
bool ignore_breakpoints ,
2012-10-17 05:41:58 +08:00
uint32_t timeout_usec ,
2010-11-30 10:22:11 +08:00
Stream & errors )
{
ExecutionResults return_value = eExecutionSetupError ;
2011-01-20 10:03:18 +08:00
if ( thread_plan_sp . get ( ) = = NULL )
{
errors . Printf ( " RunThreadPlan called with empty thread plan. " ) ;
2011-03-25 05:19:54 +08:00
return eExecutionSetupError ;
2011-01-20 10:03:18 +08:00
}
2013-03-28 08:05:34 +08:00
if ( ! thread_plan_sp - > ValidatePlan ( NULL ) )
{
errors . Printf ( " RunThreadPlan called with an invalid thread plan. " ) ;
return eExecutionSetupError ;
}
2011-09-22 12:58:26 +08:00
if ( exe_ctx . GetProcessPtr ( ) ! = this )
{
errors . Printf ( " RunThreadPlan called on wrong process. " ) ;
return eExecutionSetupError ;
}
Thread * thread = exe_ctx . GetThreadPtr ( ) ;
if ( thread = = NULL )
{
errors . Printf ( " RunThreadPlan called with invalid thread. " ) ;
return eExecutionSetupError ;
}
2011-01-20 10:03:18 +08:00
2011-05-18 06:24:54 +08:00
// We rely on the thread plan we are running returning "PlanCompleted" if when it successfully completes.
// For that to be true the plan can't be private - since private plans suppress themselves in the
// GetCompletedPlan call.
bool orig_plan_private = thread_plan_sp - > GetPrivate ( ) ;
thread_plan_sp - > SetPrivate ( false ) ;
2011-01-24 14:34:17 +08:00
if ( m_private_state . GetValue ( ) ! = eStateStopped )
{
errors . Printf ( " RunThreadPlan called while the private state was not stopped. " ) ;
2011-03-25 05:19:54 +08:00
return eExecutionSetupError ;
2011-01-24 14:34:17 +08:00
}
2011-08-13 08:56:10 +08:00
// Save the thread & frame from the exe_ctx for restoration after we run
2011-09-22 12:58:26 +08:00
const uint32_t thread_idx_id = thread - > GetIndexID ( ) ;
2013-02-20 07:22:45 +08:00
StackFrameSP selected_frame_sp = thread - > GetSelectedFrame ( ) ;
if ( ! selected_frame_sp )
{
thread - > SetSelectedFrame ( 0 ) ;
selected_frame_sp = thread - > GetSelectedFrame ( ) ;
if ( ! selected_frame_sp )
{
errors . Printf ( " RunThreadPlan called without a selected frame on thread %d " , thread_idx_id ) ;
return eExecutionSetupError ;
}
}
StackID ctx_frame_id = selected_frame_sp - > GetStackID ( ) ;
2010-11-30 10:22:11 +08:00
// N.B. Running the target may unset the currently selected thread and frame. We don't want to do that either,
// so we should arrange to reset them as well.
2011-09-22 12:58:26 +08:00
lldb : : ThreadSP selected_thread_sp = GetThreadList ( ) . GetSelectedThread ( ) ;
2010-11-30 10:22:11 +08:00
2011-08-13 08:56:10 +08:00
uint32_t selected_tid ;
StackID selected_stack_id ;
2011-09-19 02:59:15 +08:00
if ( selected_thread_sp )
2010-11-30 10:22:11 +08:00
{
selected_tid = selected_thread_sp - > GetIndexID ( ) ;
2011-08-13 08:56:10 +08:00
selected_stack_id = selected_thread_sp - > GetSelectedFrame ( ) - > GetStackID ( ) ;
2010-11-30 10:22:11 +08:00
}
else
{
selected_tid = LLDB_INVALID_THREAD_ID ;
}
2012-04-07 08:00:41 +08:00
lldb : : thread_t backup_private_state_thread = LLDB_INVALID_HOST_THREAD ;
2012-04-10 09:21:57 +08:00
lldb : : StateType old_state ;
lldb : : ThreadPlanSP stopper_base_plan_sp ;
2012-04-07 08:00:41 +08:00
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_STEP | LIBLLDB_LOG_PROCESS ) ) ;
2012-04-07 08:00:41 +08:00
if ( Host : : GetCurrentThread ( ) = = m_private_state_thread )
{
2012-04-10 09:21:57 +08:00
// Yikes, we are running on the private state thread! So we can't wait for public events on this thread, since
// we are the thread that is generating public events.
2012-04-07 08:00:41 +08:00
// The simplest thing to do is to spin up a temporary thread to handle private state thread events while
2012-04-10 09:21:57 +08:00
// we are fielding public events here.
if ( log )
2012-11-17 09:41:04 +08:00
log - > Printf ( " Running thread plan on private state thread, spinning up another state thread to handle the events. " ) ;
2012-04-10 09:21:57 +08:00
2012-04-07 08:00:41 +08:00
backup_private_state_thread = m_private_state_thread ;
2012-04-10 09:21:57 +08:00
// One other bit of business: we want to run just this thread plan and anything it pushes, and then stop,
// returning control here.
// But in the normal course of things, the plan above us on the stack would be given a shot at the stop
// event before deciding to stop, and we don't want that. So we insert a "stopper" base plan on the stack
// before the plan we want to run. Since base plans always stop and return control to the user, that will
// do just what we want.
stopper_base_plan_sp . reset ( new ThreadPlanBase ( * thread ) ) ;
thread - > QueueThreadPlan ( stopper_base_plan_sp , false ) ;
// Have to make sure our public state is stopped, since otherwise the reporting logic below doesn't work correctly.
old_state = m_public_state . GetValue ( ) ;
m_public_state . SetValueNoLock ( eStateStopped ) ;
// Now spin up the private state thread:
2012-04-07 08:00:41 +08:00
StartPrivateStateThread ( true ) ;
}
thread - > QueueThreadPlan ( thread_plan_sp , false ) ; // This used to pass "true" does that make sense?
2010-11-30 10:22:11 +08:00
2011-01-24 05:14:08 +08:00
Listener listener ( " lldb.process.listener.run-thread-plan " ) ;
2011-02-08 13:20:59 +08:00
2012-07-12 05:31:24 +08:00
lldb : : EventSP event_to_broadcast_sp ;
2011-02-08 13:20:59 +08:00
2010-11-30 10:22:11 +08:00
{
2012-07-12 05:31:24 +08:00
// This process event hijacker Hijacks the Public events and its destructor makes sure that the process events get
// restored on exit to the function.
//
// If the event needs to propagate beyond the hijacker (e.g., the process exits during execution), then the event
// is put into event_to_broadcast_sp for rebroadcasting.
2011-02-08 13:20:59 +08:00
2012-07-12 05:31:24 +08:00
ProcessEventHijacker run_thread_plan_hijacker ( * this , & listener ) ;
if ( log )
2011-02-08 13:20:59 +08:00
{
2012-07-12 05:31:24 +08:00
StreamString s ;
thread_plan_sp - > GetDescription ( & s , lldb : : eDescriptionLevelVerbose ) ;
2012-11-30 05:49:15 +08:00
log - > Printf ( " Process::RunThreadPlan(): Resuming thread %u - 0x%4.4 " PRIx64 " to run thread plan \" %s \" . " ,
2012-07-12 05:31:24 +08:00
thread - > GetIndexID ( ) ,
thread - > GetID ( ) ,
s . GetData ( ) ) ;
}
bool got_event ;
lldb : : EventSP event_sp ;
lldb : : StateType stop_state = lldb : : eStateInvalid ;
TimeValue * timeout_ptr = NULL ;
TimeValue real_timeout ;
2013-02-09 09:29:05 +08:00
bool before_first_timeout = true ; // This is set to false the first time that we have to halt the target.
2012-07-12 05:31:24 +08:00
bool do_resume = true ;
2013-01-15 10:47:48 +08:00
bool handle_running_event = true ;
2012-10-17 05:41:58 +08:00
const uint64_t default_one_thread_timeout_usec = 250000 ;
2012-07-12 05:31:24 +08:00
2013-02-09 09:29:05 +08:00
// This is just for accounting:
uint32_t num_resumes = 0 ;
TimeValue one_thread_timeout = TimeValue : : Now ( ) ;
TimeValue final_timeout = one_thread_timeout ;
if ( run_others )
{
// If we are running all threads then we take half the time to run all threads, bounded by
// .25 sec.
if ( timeout_usec = = 0 )
one_thread_timeout . OffsetWithMicroSeconds ( default_one_thread_timeout_usec ) ;
else
{
uint64_t computed_timeout = computed_timeout = timeout_usec / 2 ;
if ( computed_timeout > default_one_thread_timeout_usec )
computed_timeout = default_one_thread_timeout_usec ;
one_thread_timeout . OffsetWithMicroSeconds ( computed_timeout ) ;
}
final_timeout . OffsetWithMicroSeconds ( timeout_usec ) ;
}
else
{
if ( timeout_usec ! = 0 )
final_timeout . OffsetWithMicroSeconds ( timeout_usec ) ;
}
2012-11-27 07:52:18 +08:00
// This while loop must exit out the bottom, there's cleanup that we need to do when we are done.
// So don't call return anywhere within it.
2012-07-12 05:31:24 +08:00
while ( 1 )
{
// We usually want to resume the process if we get to the top of the loop.
// The only exception is if we get two running events with no intervening
// stop, which can happen, we will just wait for then next stop event.
2013-02-09 09:29:05 +08:00
if ( log )
log - > Printf ( " Top of while loop: do_resume: %i handle_running_event: %i before_first_timeout: %i. " ,
do_resume ,
handle_running_event ,
before_first_timeout ) ;
2011-02-08 13:20:59 +08:00
2013-01-15 10:47:48 +08:00
if ( do_resume | | handle_running_event )
2011-02-08 13:20:59 +08:00
{
2012-07-12 05:31:24 +08:00
// Do the initial resume and wait for the running event before going further.
2013-01-15 10:47:48 +08:00
if ( do_resume )
2012-07-12 05:31:24 +08:00
{
2013-02-09 09:29:05 +08:00
num_resumes + + ;
2013-01-15 10:47:48 +08:00
Error resume_error = PrivateResume ( ) ;
if ( ! resume_error . Success ( ) )
{
2013-02-09 09:29:05 +08:00
errors . Printf ( " Error resuming inferior the %d time: \" %s \" . \n " ,
num_resumes ,
resume_error . AsCString ( ) ) ;
2013-01-15 10:47:48 +08:00
return_value = eExecutionSetupError ;
break ;
}
2012-07-12 05:31:24 +08:00
}
2013-02-09 09:29:05 +08:00
TimeValue resume_timeout = TimeValue : : Now ( ) ;
resume_timeout . OffsetWithMicroSeconds ( 500000 ) ;
got_event = listener . WaitForEvent ( & resume_timeout , event_sp ) ;
2012-07-12 05:31:24 +08:00
if ( ! got_event )
{
if ( log )
2013-02-09 09:29:05 +08:00
log - > Printf ( " Process::RunThreadPlan(): didn't get any event after resume %d, exiting. " ,
num_resumes ) ;
2011-02-08 13:20:59 +08:00
2013-02-09 09:29:05 +08:00
errors . Printf ( " Didn't get any event after resume %d, exiting. " , num_resumes ) ;
2012-07-12 05:31:24 +08:00
return_value = eExecutionSetupError ;
break ;
}
stop_state = Process : : ProcessEventData : : GetStateFromEvent ( event_sp . get ( ) ) ;
2013-02-09 09:29:05 +08:00
2012-07-12 05:31:24 +08:00
if ( stop_state ! = eStateRunning )
{
2013-02-09 09:29:05 +08:00
bool restarted = false ;
if ( stop_state = = eStateStopped )
{
restarted = Process : : ProcessEventData : : GetRestartedFromEvent ( event_sp . get ( ) ) ;
if ( log )
log - > Printf ( " Process::RunThreadPlan(): didn't get running event after "
" resume %d, got %s instead (restarted: %i, do_resume: %i, handle_running_event: %i). " ,
num_resumes ,
StateAsCString ( stop_state ) ,
restarted ,
do_resume ,
handle_running_event ) ;
}
if ( restarted )
{
// This is probably an overabundance of caution, I don't think I should ever get a stopped & restarted
// event here. But if I do, the best thing is to Halt and then get out of here.
Halt ( ) ;
}
2012-10-17 05:41:58 +08:00
errors . Printf ( " Didn't get running event after initial resume, got %s instead. " ,
StateAsCString ( stop_state ) ) ;
2012-07-12 05:31:24 +08:00
return_value = eExecutionSetupError ;
break ;
}
2011-02-08 13:20:59 +08:00
if ( log )
2012-07-12 05:31:24 +08:00
log - > PutCString ( " Process::RunThreadPlan(): resuming succeeded. " ) ;
// We need to call the function synchronously, so spin waiting for it to return.
// If we get interrupted while executing, we're going to lose our context, and
// won't be able to gather the result at this point.
// We set the timeout AFTER the resume, since the resume takes some time and we
// don't want to charge that to the timeout.
2013-02-09 09:29:05 +08:00
}
else
{
if ( log )
log - > PutCString ( " Process::RunThreadPlan(): waiting for next event. " ) ;
}
2012-10-17 05:41:58 +08:00
2013-02-09 09:29:05 +08:00
if ( before_first_timeout )
{
if ( run_others )
timeout_ptr = & one_thread_timeout ;
2012-07-17 07:10:35 +08:00
else
{
2013-02-09 09:29:05 +08:00
if ( timeout_usec = = 0 )
timeout_ptr = NULL ;
else
timeout_ptr = & final_timeout ;
2012-07-17 07:10:35 +08:00
}
2011-02-08 13:20:59 +08:00
}
2012-07-12 05:31:24 +08:00
else
2011-02-08 13:20:59 +08:00
{
2013-02-09 09:29:05 +08:00
if ( timeout_usec = = 0 )
timeout_ptr = NULL ;
else
timeout_ptr = & final_timeout ;
2011-02-08 13:20:59 +08:00
}
2013-02-09 09:29:05 +08:00
do_resume = true ;
handle_running_event = true ;
2012-07-12 05:31:24 +08:00
// Now wait for the process to stop again:
event_sp . reset ( ) ;
2012-04-14 07:09:49 +08:00
2012-07-12 05:31:24 +08:00
if ( log )
2012-04-14 07:09:49 +08:00
{
2012-07-12 05:31:24 +08:00
if ( timeout_ptr )
{
2013-02-22 07:55:31 +08:00
log - > Printf ( " Process::RunThreadPlan(): about to wait - now is % " PRIu64 " - endpoint is % " PRIu64 ,
2013-02-09 09:29:05 +08:00
TimeValue : : Now ( ) . GetAsMicroSecondsSinceJan1_1970 ( ) ,
timeout_ptr - > GetAsMicroSecondsSinceJan1_1970 ( ) ) ;
2012-07-12 05:31:24 +08:00
}
else
{
log - > Printf ( " Process::RunThreadPlan(): about to wait forever. " ) ;
}
2012-04-14 07:09:49 +08:00
}
2012-07-12 05:31:24 +08:00
got_event = listener . WaitForEvent ( timeout_ptr , event_sp ) ;
if ( got_event )
2011-02-08 13:20:59 +08:00
{
2012-07-12 05:31:24 +08:00
if ( event_sp . get ( ) )
2011-02-08 13:20:59 +08:00
{
2012-07-12 05:31:24 +08:00
bool keep_going = false ;
2012-07-28 07:57:19 +08:00
if ( event_sp - > GetType ( ) = = eBroadcastBitInterrupt )
2011-05-17 09:10:11 +08:00
{
2012-07-28 07:57:19 +08:00
Halt ( ) ;
return_value = eExecutionInterrupted ;
errors . Printf ( " Execution halted by user interrupt. " ) ;
if ( log )
log - > Printf ( " Process::RunThreadPlan(): Got interrupted by eBroadcastBitInterrupted, exiting. " ) ;
2013-02-09 09:29:05 +08:00
break ;
2012-07-28 07:57:19 +08:00
}
else
{
stop_state = Process : : ProcessEventData : : GetStateFromEvent ( event_sp . get ( ) ) ;
if ( log )
log - > Printf ( " Process::RunThreadPlan(): in while loop, got event: %s. " , StateAsCString ( stop_state ) ) ;
switch ( stop_state )
2011-05-17 09:10:11 +08:00
{
2012-07-28 07:57:19 +08:00
case lldb : : eStateStopped :
2011-06-04 06:12:42 +08:00
{
2013-02-09 09:29:05 +08:00
// We stopped, figure out what we are going to do now.
2012-07-28 07:57:19 +08:00
ThreadSP thread_sp = GetThreadList ( ) . FindThreadByIndexID ( thread_idx_id ) ;
if ( ! thread_sp )
2012-07-12 05:31:24 +08:00
{
2012-07-28 07:57:19 +08:00
// Ooh, our thread has vanished. Unlikely that this was successful execution...
2012-07-12 05:31:24 +08:00
if ( log )
2012-07-28 07:57:19 +08:00
log - > Printf ( " Process::RunThreadPlan(): execution completed but our thread (index-id=%u) has vanished. " , thread_idx_id ) ;
return_value = eExecutionInterrupted ;
2012-07-12 05:31:24 +08:00
}
else
{
2013-02-09 09:29:05 +08:00
// If we were restarted, we just need to go back up to fetch another event.
if ( Process : : ProcessEventData : : GetRestartedFromEvent ( event_sp . get ( ) ) )
2012-07-28 07:57:19 +08:00
{
if ( log )
2013-02-09 09:29:05 +08:00
{
log - > Printf ( " Process::RunThreadPlan(): Got a stop and restart, so we'll continue waiting. " ) ;
}
keep_going = true ;
do_resume = false ;
handle_running_event = true ;
2012-07-28 07:57:19 +08:00
}
else
{
2013-02-09 09:29:05 +08:00
StopInfoSP stop_info_sp ( thread_sp - > GetStopInfo ( ) ) ;
StopReason stop_reason = eStopReasonInvalid ;
if ( stop_info_sp )
stop_reason = stop_info_sp - > GetStopReason ( ) ;
// FIXME: We only check if the stop reason is plan complete, should we make sure that
// it is OUR plan that is complete?
if ( stop_reason = = eStopReasonPlanComplete )
2013-01-15 10:47:48 +08:00
{
if ( log )
2013-02-09 09:29:05 +08:00
log - > PutCString ( " Process::RunThreadPlan(): execution completed successfully. " ) ;
// Now mark this plan as private so it doesn't get reported as the stop reason
// after this point.
if ( thread_plan_sp )
thread_plan_sp - > SetPrivate ( orig_plan_private ) ;
return_value = eExecutionCompleted ;
2013-01-15 10:47:48 +08:00
}
else
{
2013-02-09 09:29:05 +08:00
// Something restarted the target, so just wait for it to stop for real.
2013-01-15 10:47:48 +08:00
if ( stop_reason = = eStopReasonBreakpoint )
2013-02-09 09:29:05 +08:00
{
if ( log )
log - > Printf ( " Process::RunThreadPlan() stopped for breakpoint: %s. " , stop_info_sp - > GetDescription ( ) ) ;
2013-01-15 10:47:48 +08:00
return_value = eExecutionHitBreakpoint ;
2013-02-09 09:29:05 +08:00
}
2013-01-15 10:47:48 +08:00
else
2013-02-09 09:29:05 +08:00
{
if ( log )
log - > PutCString ( " Process::RunThreadPlan(): thread plan didn't successfully complete. " ) ;
2013-01-15 10:47:48 +08:00
return_value = eExecutionInterrupted ;
2013-02-09 09:29:05 +08:00
}
2013-01-15 10:47:48 +08:00
}
2012-07-28 07:57:19 +08:00
}
2012-07-12 05:31:24 +08:00
}
2012-07-28 07:57:19 +08:00
}
break ;
2011-06-04 06:12:42 +08:00
2012-07-28 07:57:19 +08:00
case lldb : : eStateRunning :
2013-02-09 09:29:05 +08:00
// This shouldn't really happen, but sometimes we do get two running events without an
// intervening stop, and in that case we should just go back to waiting for the stop.
2012-07-28 07:57:19 +08:00
do_resume = false ;
keep_going = true ;
2013-01-15 10:47:48 +08:00
handle_running_event = false ;
2012-07-28 07:57:19 +08:00
break ;
2011-06-04 06:12:42 +08:00
2012-07-28 07:57:19 +08:00
default :
if ( log )
log - > Printf ( " Process::RunThreadPlan(): execution stopped with unexpected state: %s. " , StateAsCString ( stop_state ) ) ;
if ( stop_state = = eStateExited )
event_to_broadcast_sp = event_sp ;
2012-08-09 01:35:10 +08:00
errors . Printf ( " Execution stopped with unexpected state. \n " ) ;
2012-07-28 07:57:19 +08:00
return_value = eExecutionInterrupted ;
break ;
}
2012-07-12 05:31:24 +08:00
}
2012-07-28 07:57:19 +08:00
2012-07-12 05:31:24 +08:00
if ( keep_going )
continue ;
else
break ;
}
else
{
2011-02-08 13:20:59 +08:00
if ( log )
2012-07-12 05:31:24 +08:00
log - > PutCString ( " Process::RunThreadPlan(): got_event was true, but the event pointer was null. How odd... " ) ;
2011-03-25 05:19:54 +08:00
return_value = eExecutionInterrupted ;
2011-02-08 13:20:59 +08:00
break ;
}
2012-07-12 05:31:24 +08:00
}
2011-02-08 13:20:59 +08:00
else
{
2012-07-12 05:31:24 +08:00
// If we didn't get an event that means we've timed out...
// We will interrupt the process here. Depending on what we were asked to do we will
// either exit, or try with all threads running for the same timeout.
if ( log ) {
2012-10-17 05:41:58 +08:00
if ( run_others )
2012-07-12 05:31:24 +08:00
{
2013-02-09 09:29:05 +08:00
uint64_t remaining_time = final_timeout - TimeValue : : Now ( ) ;
if ( before_first_timeout )
log - > Printf ( " Process::RunThreadPlan(): Running function with one thread timeout timed out, "
" running till for % " PRId64 " usec with all threads enabled. " ,
remaining_time ) ;
2012-07-12 05:31:24 +08:00
else
log - > Printf ( " Process::RunThreadPlan(): Restarting function with all threads enabled "
2012-10-17 05:41:58 +08:00
" and timeout: %d timed out, abandoning execution. " ,
timeout_usec ) ;
2012-07-12 05:31:24 +08:00
}
2011-02-08 13:20:59 +08:00
else
2012-07-12 05:31:24 +08:00
log - > Printf ( " Process::RunThreadPlan(): Running function with timeout: %d timed out, "
2012-10-17 05:41:58 +08:00
" abandoning execution. " ,
timeout_usec ) ;
2011-02-08 13:20:59 +08:00
}
2013-02-09 09:29:05 +08:00
// It is possible that between the time we issued the Halt, and we get around to calling Halt the target
// could have stopped. That's fine, Halt will figure that out and send the appropriate Stopped event.
// BUT it is also possible that we stopped & restarted (e.g. hit a signal with "stop" set to false.) In
// that case, we'll get the stopped & restarted event, and we should go back to waiting for the Halt's
// stopped event. That's what this while loop does.
bool back_to_top = true ;
uint32_t try_halt_again = 0 ;
bool do_halt = true ;
const uint32_t num_retries = 5 ;
while ( try_halt_again < num_retries )
2011-02-08 13:20:59 +08:00
{
2013-02-09 09:29:05 +08:00
Error halt_error ;
if ( do_halt )
2011-02-08 13:20:59 +08:00
{
2012-07-12 05:31:24 +08:00
if ( log )
2013-02-09 09:29:05 +08:00
log - > Printf ( " Process::RunThreadPlan(): Running Halt. " ) ;
halt_error = Halt ( ) ;
2012-07-12 05:31:24 +08:00
}
2013-02-09 09:29:05 +08:00
if ( halt_error . Success ( ) )
2012-07-12 05:31:24 +08:00
{
if ( log )
2013-02-09 09:29:05 +08:00
log - > PutCString ( " Process::RunThreadPlan(): Halt succeeded. " ) ;
2012-07-12 05:31:24 +08:00
2013-02-09 09:29:05 +08:00
real_timeout = TimeValue : : Now ( ) ;
real_timeout . OffsetWithMicroSeconds ( 500000 ) ;
2011-02-08 13:20:59 +08:00
2013-02-09 09:29:05 +08:00
got_event = listener . WaitForEvent ( & real_timeout , event_sp ) ;
if ( got_event )
{
stop_state = Process : : ProcessEventData : : GetStateFromEvent ( event_sp . get ( ) ) ;
if ( log )
2012-07-12 05:31:24 +08:00
{
2013-02-09 09:29:05 +08:00
log - > Printf ( " Process::RunThreadPlan(): Stopped with event: %s " , StateAsCString ( stop_state ) ) ;
if ( stop_state = = lldb : : eStateStopped
& & Process : : ProcessEventData : : GetInterruptedFromEvent ( event_sp . get ( ) ) )
log - > PutCString ( " Event was the Halt interruption event. " ) ;
2012-07-12 05:31:24 +08:00
}
2013-02-09 09:29:05 +08:00
if ( stop_state = = lldb : : eStateStopped )
2012-07-12 05:31:24 +08:00
{
2013-02-09 09:29:05 +08:00
// Between the time we initiated the Halt and the time we delivered it, the process could have
// already finished its job. Check that here:
if ( thread - > IsThreadPlanDone ( thread_plan_sp . get ( ) ) )
{
if ( log )
log - > PutCString ( " Process::RunThreadPlan(): Even though we timed out, the call plan was done. "
" Exiting wait loop. " ) ;
return_value = eExecutionCompleted ;
back_to_top = false ;
break ;
}
if ( Process : : ProcessEventData : : GetRestartedFromEvent ( event_sp . get ( ) ) )
{
if ( log )
log - > PutCString ( " Process::RunThreadPlan(): Went to halt but got a restarted event, there must be an un-restarted stopped event so try again... "
" Exiting wait loop. " ) ;
try_halt_again + + ;
do_halt = false ;
continue ;
}
if ( ! run_others )
{
if ( log )
log - > PutCString ( " Process::RunThreadPlan(): try_all_threads was false, we stopped so now we're quitting. " ) ;
return_value = eExecutionInterrupted ;
back_to_top = false ;
break ;
}
if ( before_first_timeout )
{
// Set all the other threads to run, and return to the top of the loop, which will continue;
before_first_timeout = false ;
thread_plan_sp - > SetStopOthers ( false ) ;
if ( log )
log - > PutCString ( " Process::RunThreadPlan(): about to resume. " ) ;
back_to_top = true ;
break ;
}
else
{
// Running all threads failed, so return Interrupted.
if ( log )
log - > PutCString ( " Process::RunThreadPlan(): running all threads timed out. " ) ;
return_value = eExecutionInterrupted ;
back_to_top = false ;
break ;
}
2012-07-12 05:31:24 +08:00
}
2011-02-08 13:20:59 +08:00
}
else
2013-02-09 09:29:05 +08:00
{ if ( log )
log - > PutCString ( " Process::RunThreadPlan(): halt said it succeeded, but I got no event. "
" I'm getting out of here passing Interrupted. " ) ;
2011-03-25 05:19:54 +08:00
return_value = eExecutionInterrupted ;
2013-02-09 09:29:05 +08:00
back_to_top = false ;
break ;
2011-02-08 13:20:59 +08:00
}
}
2013-02-09 09:29:05 +08:00
else
{
try_halt_again + + ;
continue ;
}
2011-01-24 05:14:08 +08:00
}
2013-02-09 09:29:05 +08:00
if ( ! back_to_top | | try_halt_again > num_retries )
break ;
else
continue ;
2012-07-12 05:31:24 +08:00
}
} // END WAIT LOOP
2010-11-30 10:22:11 +08:00
2012-07-12 05:31:24 +08:00
// If we had to start up a temporary private state thread to run this thread plan, shut it down now.
if ( IS_VALID_LLDB_HOST_THREAD ( backup_private_state_thread ) )
2012-04-10 09:21:57 +08:00
{
2012-07-12 05:31:24 +08:00
StopPrivateStateThread ( ) ;
Error error ;
m_private_state_thread = backup_private_state_thread ;
2012-08-09 08:50:26 +08:00
if ( stopper_base_plan_sp )
2010-11-30 10:22:11 +08:00
{
2012-07-12 05:31:24 +08:00
thread - > DiscardThreadPlansUpToPlan ( stopper_base_plan_sp ) ;
2011-02-08 13:20:59 +08:00
}
2012-07-12 05:31:24 +08:00
m_public_state . SetValueNoLock ( old_state ) ;
2011-02-08 13:20:59 +08:00
2012-07-12 05:31:24 +08:00
}
2013-01-15 10:47:48 +08:00
// Restore the thread state if we are going to discard the plan execution. There are three cases where this
// could happen:
// 1) The execution successfully completed
// 2) We hit a breakpoint, and ignore_breakpoints was true
// 3) We got some other error, and discard_on_error was true
bool should_unwind = ( return_value = = eExecutionInterrupted & & unwind_on_error )
| | ( return_value = = eExecutionHitBreakpoint & & ignore_breakpoints ) ;
2012-11-27 07:52:18 +08:00
2013-01-15 10:47:48 +08:00
if ( return_value = = eExecutionCompleted
| | should_unwind )
2012-11-27 07:52:18 +08:00
{
thread_plan_sp - > RestoreThreadState ( ) ;
}
2012-07-12 05:31:24 +08:00
// Now do some processing on the results of the run:
2013-01-15 10:47:48 +08:00
if ( return_value = = eExecutionInterrupted | | return_value = = eExecutionHitBreakpoint )
2012-07-12 05:31:24 +08:00
{
if ( log )
2011-02-08 13:20:59 +08:00
{
2012-07-12 05:31:24 +08:00
StreamString s ;
if ( event_sp )
event_sp - > Dump ( & s ) ;
else
2011-01-22 09:30:53 +08:00
{
2012-07-12 05:31:24 +08:00
log - > PutCString ( " Process::RunThreadPlan(): Stop event that interrupted us is NULL. " ) ;
2011-01-22 09:30:53 +08:00
}
2012-07-12 05:31:24 +08:00
StreamString ts ;
const char * event_explanation = NULL ;
2010-11-30 10:22:11 +08:00
2012-07-12 05:31:24 +08:00
do
2010-11-30 10:22:11 +08:00
{
2012-07-28 07:57:19 +08:00
if ( ! event_sp )
2012-07-12 05:31:24 +08:00
{
2012-07-28 07:57:19 +08:00
event_explanation = " <no event> " ;
2012-07-12 05:31:24 +08:00
break ;
}
2012-07-28 07:57:19 +08:00
else if ( event_sp - > GetType ( ) = = eBroadcastBitInterrupt )
2010-11-30 10:22:11 +08:00
{
2012-07-28 07:57:19 +08:00
event_explanation = " <user interrupt> " ;
2012-07-12 05:31:24 +08:00
break ;
2010-11-30 10:22:11 +08:00
}
2012-07-28 07:57:19 +08:00
else
2011-01-22 09:30:53 +08:00
{
2012-07-28 07:57:19 +08:00
const Process : : ProcessEventData * event_data = Process : : ProcessEventData : : GetEventDataFromEvent ( event_sp . get ( ) ) ;
if ( ! event_data )
{
event_explanation = " <no event data> " ;
break ;
}
2012-07-12 05:31:24 +08:00
2012-07-28 07:57:19 +08:00
Process * process = event_data - > GetProcessSP ( ) . get ( ) ;
if ( ! process )
2012-07-12 05:31:24 +08:00
{
2012-07-28 07:57:19 +08:00
event_explanation = " <no process> " ;
break ;
2012-07-12 05:31:24 +08:00
}
2012-07-28 07:57:19 +08:00
ThreadList & thread_list = process - > GetThreadList ( ) ;
2012-07-12 05:31:24 +08:00
2012-07-28 07:57:19 +08:00
uint32_t num_threads = thread_list . GetSize ( ) ;
uint32_t thread_index ;
ts . Printf ( " <%u threads> " , num_threads ) ;
2012-07-12 05:31:24 +08:00
2012-07-28 07:57:19 +08:00
for ( thread_index = 0 ;
thread_index < num_threads ;
+ + thread_index )
2012-07-12 05:31:24 +08:00
{
2012-07-28 07:57:19 +08:00
Thread * thread = thread_list . GetThreadAtIndex ( thread_index ) . get ( ) ;
if ( ! thread )
{
ts . Printf ( " <?> " ) ;
continue ;
}
2012-11-30 05:49:15 +08:00
ts . Printf ( " <0x%4.4 " PRIx64 " " , thread - > GetID ( ) ) ;
2012-07-28 07:57:19 +08:00
RegisterContext * register_context = thread - > GetRegisterContext ( ) . get ( ) ;
if ( register_context )
2012-11-30 05:49:15 +08:00
ts . Printf ( " [ip 0x% " PRIx64 " ] " , register_context - > GetPC ( ) ) ;
2012-07-28 07:57:19 +08:00
else
ts . Printf ( " [ip unknown] " ) ;
lldb : : StopInfoSP stop_info_sp = thread - > GetStopInfo ( ) ;
if ( stop_info_sp )
{
const char * stop_desc = stop_info_sp - > GetDescription ( ) ;
if ( stop_desc )
ts . PutCString ( stop_desc ) ;
}
ts . Printf ( " > " ) ;
2012-07-12 05:31:24 +08:00
}
2012-07-28 07:57:19 +08:00
event_explanation = ts . GetData ( ) ;
2011-01-22 09:30:53 +08:00
}
2012-07-12 05:31:24 +08:00
} while ( 0 ) ;
2011-02-08 13:20:59 +08:00
2012-07-28 07:57:19 +08:00
if ( event_explanation )
log - > Printf ( " Process::RunThreadPlan(): execution interrupted: %s %s " , s . GetData ( ) , event_explanation ) ;
2011-08-10 06:24:33 +08:00
else
2012-07-28 07:57:19 +08:00
log - > Printf ( " Process::RunThreadPlan(): execution interrupted: %s " , s . GetData ( ) ) ;
}
2013-01-15 10:47:48 +08:00
if ( should_unwind & & thread_plan_sp )
2012-07-28 07:57:19 +08:00
{
if ( log )
log - > Printf ( " Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p. " , thread_plan_sp . get ( ) ) ;
thread - > DiscardThreadPlansUpToPlan ( thread_plan_sp ) ;
thread_plan_sp - > SetPrivate ( orig_plan_private ) ;
}
else
{
if ( log )
log - > Printf ( " Process::RunThreadPlan: ExecutionInterrupted - for plan: %p not discarding. " , thread_plan_sp . get ( ) ) ;
2012-07-12 05:31:24 +08:00
}
}
else if ( return_value = = eExecutionSetupError )
{
if ( log )
log - > PutCString ( " Process::RunThreadPlan(): execution set up error. " ) ;
2011-02-08 13:20:59 +08:00
2013-01-15 10:47:48 +08:00
if ( unwind_on_error & & thread_plan_sp )
2010-11-30 10:22:11 +08:00
{
2011-09-22 12:58:26 +08:00
thread - > DiscardThreadPlansUpToPlan ( thread_plan_sp ) ;
2011-08-09 10:12:22 +08:00
thread_plan_sp - > SetPrivate ( orig_plan_private ) ;
2010-11-30 10:22:11 +08:00
}
2012-07-12 05:31:24 +08:00
}
else
{
if ( thread - > IsThreadPlanDone ( thread_plan_sp . get ( ) ) )
{
if ( log )
log - > PutCString ( " Process::RunThreadPlan(): thread plan is done " ) ;
return_value = eExecutionCompleted ;
}
else if ( thread - > WasThreadPlanDiscarded ( thread_plan_sp . get ( ) ) )
{
if ( log )
log - > PutCString ( " Process::RunThreadPlan(): thread plan was discarded " ) ;
return_value = eExecutionDiscarded ;
}
2012-04-14 07:09:49 +08:00
else
{
if ( log )
2012-07-12 05:31:24 +08:00
log - > PutCString ( " Process::RunThreadPlan(): thread plan stopped in mid course " ) ;
2013-01-15 10:47:48 +08:00
if ( unwind_on_error & & thread_plan_sp )
2012-07-12 05:31:24 +08:00
{
if ( log )
2013-01-15 10:47:48 +08:00
log - > PutCString ( " Process::RunThreadPlan(): discarding thread plan 'cause unwind_on_error is set. " ) ;
2012-07-12 05:31:24 +08:00
thread - > DiscardThreadPlansUpToPlan ( thread_plan_sp ) ;
thread_plan_sp - > SetPrivate ( orig_plan_private ) ;
}
2012-04-14 07:09:49 +08:00
}
2010-11-30 10:22:11 +08:00
}
2012-07-12 05:31:24 +08:00
// Thread we ran the function in may have gone away because we ran the target
// Check that it's still there, and if it is put it back in the context. Also restore the
// frame in the context if it is still present.
thread = GetThreadList ( ) . FindThreadByIndexID ( thread_idx_id , true ) . get ( ) ;
if ( thread )
2011-02-08 13:20:59 +08:00
{
2012-07-12 05:31:24 +08:00
exe_ctx . SetFrameSP ( thread - > GetFrameWithStackID ( ctx_frame_id ) ) ;
2011-02-08 13:20:59 +08:00
}
2012-07-12 05:31:24 +08:00
// Also restore the current process'es selected frame & thread, since this function calling may
// be done behind the user's back.
if ( selected_tid ! = LLDB_INVALID_THREAD_ID )
2011-02-08 13:20:59 +08:00
{
2012-07-12 05:31:24 +08:00
if ( GetThreadList ( ) . SetSelectedThreadByIndexID ( selected_tid ) & & selected_stack_id . IsValid ( ) )
2011-02-08 13:20:59 +08:00
{
2012-07-12 05:31:24 +08:00
// We were able to restore the selected thread, now restore the frame:
StackFrameSP old_frame_sp = GetThreadList ( ) . GetSelectedThread ( ) - > GetFrameWithStackID ( selected_stack_id ) ;
if ( old_frame_sp )
GetThreadList ( ) . GetSelectedThread ( ) - > SetSelectedFrame ( old_frame_sp . get ( ) ) ;
2011-02-08 13:20:59 +08:00
}
}
}
2010-11-30 10:22:11 +08:00
2012-07-12 05:31:24 +08:00
// If the process exited during the run of the thread plan, notify everyone.
2010-11-30 10:22:11 +08:00
2012-07-12 05:31:24 +08:00
if ( event_to_broadcast_sp )
2010-11-30 10:22:11 +08:00
{
2012-07-12 05:31:24 +08:00
if ( log )
log - > PutCString ( " Process::RunThreadPlan(): rebroadcasting event. " ) ;
BroadcastEvent ( event_to_broadcast_sp ) ;
2010-11-30 10:22:11 +08:00
}
return return_value ;
}
const char *
Process : : ExecutionResultAsCString ( ExecutionResults result )
{
const char * result_name ;
switch ( result )
{
2011-03-25 05:19:54 +08:00
case eExecutionCompleted :
2010-11-30 10:22:11 +08:00
result_name = " eExecutionCompleted " ;
break ;
2011-03-25 05:19:54 +08:00
case eExecutionDiscarded :
2010-11-30 10:22:11 +08:00
result_name = " eExecutionDiscarded " ;
break ;
2011-03-25 05:19:54 +08:00
case eExecutionInterrupted :
2010-11-30 10:22:11 +08:00
result_name = " eExecutionInterrupted " ;
break ;
2013-01-15 10:47:48 +08:00
case eExecutionHitBreakpoint :
result_name = " eExecutionHitBreakpoint " ;
break ;
2011-03-25 05:19:54 +08:00
case eExecutionSetupError :
2010-11-30 10:22:11 +08:00
result_name = " eExecutionSetupError " ;
break ;
2011-03-25 05:19:54 +08:00
case eExecutionTimedOut :
2010-11-30 10:22:11 +08:00
result_name = " eExecutionTimedOut " ;
break ;
}
return result_name ;
}
Centralized a lot of the status information for processes,
threads, and stack frame down in the lldb_private::Process,
lldb_private::Thread, lldb_private::StackFrameList and the
lldb_private::StackFrame classes. We had some command line
commands that had duplicate versions of the process status
output ("thread list" and "process status" for example).
Removed the "file" command and placed it where it should
have been: "target create". Made an alias for "file" to
"target create" so we stay compatible with GDB commands.
We can now have multple usable targets in lldb at the
same time. This is nice for comparing two runs of a program
or debugging more than one binary at the same time. The
new command is "target select <target-idx>" and also to see
a list of the current targets you can use the new "target list"
command. The flow in a debug session can be:
(lldb) target create /path/to/exe/a.out
(lldb) breakpoint set --name main
(lldb) run
... hit breakpoint
(lldb) target create /bin/ls
(lldb) run /tmp
Process 36001 exited with status = 0 (0x00000000)
(lldb) target list
Current targets:
target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped )
* target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited )
(lldb) target select 0
Current targets:
* target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped )
target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited )
(lldb) bt
* thread #1: tid = 0x2d03, 0x0000000100000b9a a.out`main + 42 at main.c:16, stop reason = breakpoint 1.1
frame #0: 0x0000000100000b9a a.out`main + 42 at main.c:16
frame #1: 0x0000000100000b64 a.out`start + 52
Above we created a target for "a.out" and ran and hit a
breakpoint at "main". Then we created a new target for /bin/ls
and ran it. Then we listed the targest and selected our original
"a.out" program, so we showed two concurent debug sessions
going on at the same time.
llvm-svn: 129695
2011-04-18 16:33:37 +08:00
void
Process : : GetStatus ( Stream & strm )
{
const StateType state = GetState ( ) ;
2011-11-17 09:23:07 +08:00
if ( StateIsStoppedState ( state , false ) )
Centralized a lot of the status information for processes,
threads, and stack frame down in the lldb_private::Process,
lldb_private::Thread, lldb_private::StackFrameList and the
lldb_private::StackFrame classes. We had some command line
commands that had duplicate versions of the process status
output ("thread list" and "process status" for example).
Removed the "file" command and placed it where it should
have been: "target create". Made an alias for "file" to
"target create" so we stay compatible with GDB commands.
We can now have multple usable targets in lldb at the
same time. This is nice for comparing two runs of a program
or debugging more than one binary at the same time. The
new command is "target select <target-idx>" and also to see
a list of the current targets you can use the new "target list"
command. The flow in a debug session can be:
(lldb) target create /path/to/exe/a.out
(lldb) breakpoint set --name main
(lldb) run
... hit breakpoint
(lldb) target create /bin/ls
(lldb) run /tmp
Process 36001 exited with status = 0 (0x00000000)
(lldb) target list
Current targets:
target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped )
* target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited )
(lldb) target select 0
Current targets:
* target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped )
target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited )
(lldb) bt
* thread #1: tid = 0x2d03, 0x0000000100000b9a a.out`main + 42 at main.c:16, stop reason = breakpoint 1.1
frame #0: 0x0000000100000b9a a.out`main + 42 at main.c:16
frame #1: 0x0000000100000b64 a.out`start + 52
Above we created a target for "a.out" and ran and hit a
breakpoint at "main". Then we created a new target for /bin/ls
and ran it. Then we listed the targest and selected our original
"a.out" program, so we showed two concurent debug sessions
going on at the same time.
llvm-svn: 129695
2011-04-18 16:33:37 +08:00
{
if ( state = = eStateExited )
{
int exit_status = GetExitStatus ( ) ;
const char * exit_description = GetExitDescription ( ) ;
2012-11-30 05:49:15 +08:00
strm . Printf ( " Process % " PRIu64 " exited with status = %i (0x%8.8x) %s \n " ,
Centralized a lot of the status information for processes,
threads, and stack frame down in the lldb_private::Process,
lldb_private::Thread, lldb_private::StackFrameList and the
lldb_private::StackFrame classes. We had some command line
commands that had duplicate versions of the process status
output ("thread list" and "process status" for example).
Removed the "file" command and placed it where it should
have been: "target create". Made an alias for "file" to
"target create" so we stay compatible with GDB commands.
We can now have multple usable targets in lldb at the
same time. This is nice for comparing two runs of a program
or debugging more than one binary at the same time. The
new command is "target select <target-idx>" and also to see
a list of the current targets you can use the new "target list"
command. The flow in a debug session can be:
(lldb) target create /path/to/exe/a.out
(lldb) breakpoint set --name main
(lldb) run
... hit breakpoint
(lldb) target create /bin/ls
(lldb) run /tmp
Process 36001 exited with status = 0 (0x00000000)
(lldb) target list
Current targets:
target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped )
* target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited )
(lldb) target select 0
Current targets:
* target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped )
target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited )
(lldb) bt
* thread #1: tid = 0x2d03, 0x0000000100000b9a a.out`main + 42 at main.c:16, stop reason = breakpoint 1.1
frame #0: 0x0000000100000b9a a.out`main + 42 at main.c:16
frame #1: 0x0000000100000b64 a.out`start + 52
Above we created a target for "a.out" and ran and hit a
breakpoint at "main". Then we created a new target for /bin/ls
and ran it. Then we listed the targest and selected our original
"a.out" program, so we showed two concurent debug sessions
going on at the same time.
llvm-svn: 129695
2011-04-18 16:33:37 +08:00
GetID ( ) ,
exit_status ,
exit_status ,
exit_description ? exit_description : " " ) ;
}
else
{
if ( state = = eStateConnected )
strm . Printf ( " Connected to remote target. \n " ) ;
else
2012-11-30 05:49:15 +08:00
strm . Printf ( " Process % " PRIu64 " %s \n " , GetID ( ) , StateAsCString ( state ) ) ;
Centralized a lot of the status information for processes,
threads, and stack frame down in the lldb_private::Process,
lldb_private::Thread, lldb_private::StackFrameList and the
lldb_private::StackFrame classes. We had some command line
commands that had duplicate versions of the process status
output ("thread list" and "process status" for example).
Removed the "file" command and placed it where it should
have been: "target create". Made an alias for "file" to
"target create" so we stay compatible with GDB commands.
We can now have multple usable targets in lldb at the
same time. This is nice for comparing two runs of a program
or debugging more than one binary at the same time. The
new command is "target select <target-idx>" and also to see
a list of the current targets you can use the new "target list"
command. The flow in a debug session can be:
(lldb) target create /path/to/exe/a.out
(lldb) breakpoint set --name main
(lldb) run
... hit breakpoint
(lldb) target create /bin/ls
(lldb) run /tmp
Process 36001 exited with status = 0 (0x00000000)
(lldb) target list
Current targets:
target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped )
* target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited )
(lldb) target select 0
Current targets:
* target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped )
target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited )
(lldb) bt
* thread #1: tid = 0x2d03, 0x0000000100000b9a a.out`main + 42 at main.c:16, stop reason = breakpoint 1.1
frame #0: 0x0000000100000b9a a.out`main + 42 at main.c:16
frame #1: 0x0000000100000b64 a.out`start + 52
Above we created a target for "a.out" and ran and hit a
breakpoint at "main". Then we created a new target for /bin/ls
and ran it. Then we listed the targest and selected our original
"a.out" program, so we showed two concurent debug sessions
going on at the same time.
llvm-svn: 129695
2011-04-18 16:33:37 +08:00
}
}
else
{
2012-11-30 05:49:15 +08:00
strm . Printf ( " Process % " PRIu64 " is running. \n " , GetID ( ) ) ;
Centralized a lot of the status information for processes,
threads, and stack frame down in the lldb_private::Process,
lldb_private::Thread, lldb_private::StackFrameList and the
lldb_private::StackFrame classes. We had some command line
commands that had duplicate versions of the process status
output ("thread list" and "process status" for example).
Removed the "file" command and placed it where it should
have been: "target create". Made an alias for "file" to
"target create" so we stay compatible with GDB commands.
We can now have multple usable targets in lldb at the
same time. This is nice for comparing two runs of a program
or debugging more than one binary at the same time. The
new command is "target select <target-idx>" and also to see
a list of the current targets you can use the new "target list"
command. The flow in a debug session can be:
(lldb) target create /path/to/exe/a.out
(lldb) breakpoint set --name main
(lldb) run
... hit breakpoint
(lldb) target create /bin/ls
(lldb) run /tmp
Process 36001 exited with status = 0 (0x00000000)
(lldb) target list
Current targets:
target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped )
* target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited )
(lldb) target select 0
Current targets:
* target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped )
target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited )
(lldb) bt
* thread #1: tid = 0x2d03, 0x0000000100000b9a a.out`main + 42 at main.c:16, stop reason = breakpoint 1.1
frame #0: 0x0000000100000b9a a.out`main + 42 at main.c:16
frame #1: 0x0000000100000b64 a.out`start + 52
Above we created a target for "a.out" and ran and hit a
breakpoint at "main". Then we created a new target for /bin/ls
and ran it. Then we listed the targest and selected our original
"a.out" program, so we showed two concurent debug sessions
going on at the same time.
llvm-svn: 129695
2011-04-18 16:33:37 +08:00
}
}
size_t
Process : : GetThreadStatus ( Stream & strm ,
bool only_threads_with_stop_reason ,
uint32_t start_frame ,
uint32_t num_frames ,
uint32_t num_frames_with_source )
{
size_t num_thread_infos_dumped = 0 ;
2012-09-11 04:50:15 +08:00
Mutex : : Locker locker ( GetThreadList ( ) . GetMutex ( ) ) ;
Centralized a lot of the status information for processes,
threads, and stack frame down in the lldb_private::Process,
lldb_private::Thread, lldb_private::StackFrameList and the
lldb_private::StackFrame classes. We had some command line
commands that had duplicate versions of the process status
output ("thread list" and "process status" for example).
Removed the "file" command and placed it where it should
have been: "target create". Made an alias for "file" to
"target create" so we stay compatible with GDB commands.
We can now have multple usable targets in lldb at the
same time. This is nice for comparing two runs of a program
or debugging more than one binary at the same time. The
new command is "target select <target-idx>" and also to see
a list of the current targets you can use the new "target list"
command. The flow in a debug session can be:
(lldb) target create /path/to/exe/a.out
(lldb) breakpoint set --name main
(lldb) run
... hit breakpoint
(lldb) target create /bin/ls
(lldb) run /tmp
Process 36001 exited with status = 0 (0x00000000)
(lldb) target list
Current targets:
target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped )
* target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited )
(lldb) target select 0
Current targets:
* target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped )
target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited )
(lldb) bt
* thread #1: tid = 0x2d03, 0x0000000100000b9a a.out`main + 42 at main.c:16, stop reason = breakpoint 1.1
frame #0: 0x0000000100000b9a a.out`main + 42 at main.c:16
frame #1: 0x0000000100000b64 a.out`start + 52
Above we created a target for "a.out" and ran and hit a
breakpoint at "main". Then we created a new target for /bin/ls
and ran it. Then we listed the targest and selected our original
"a.out" program, so we showed two concurent debug sessions
going on at the same time.
llvm-svn: 129695
2011-04-18 16:33:37 +08:00
const size_t num_threads = GetThreadList ( ) . GetSize ( ) ;
for ( uint32_t i = 0 ; i < num_threads ; i + + )
{
Thread * thread = GetThreadList ( ) . GetThreadAtIndex ( i ) . get ( ) ;
if ( thread )
{
if ( only_threads_with_stop_reason )
{
2012-10-16 08:09:33 +08:00
StopInfoSP stop_info_sp = thread - > GetStopInfo ( ) ;
if ( stop_info_sp . get ( ) = = NULL | | ! stop_info_sp - > IsValid ( ) )
Centralized a lot of the status information for processes,
threads, and stack frame down in the lldb_private::Process,
lldb_private::Thread, lldb_private::StackFrameList and the
lldb_private::StackFrame classes. We had some command line
commands that had duplicate versions of the process status
output ("thread list" and "process status" for example).
Removed the "file" command and placed it where it should
have been: "target create". Made an alias for "file" to
"target create" so we stay compatible with GDB commands.
We can now have multple usable targets in lldb at the
same time. This is nice for comparing two runs of a program
or debugging more than one binary at the same time. The
new command is "target select <target-idx>" and also to see
a list of the current targets you can use the new "target list"
command. The flow in a debug session can be:
(lldb) target create /path/to/exe/a.out
(lldb) breakpoint set --name main
(lldb) run
... hit breakpoint
(lldb) target create /bin/ls
(lldb) run /tmp
Process 36001 exited with status = 0 (0x00000000)
(lldb) target list
Current targets:
target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped )
* target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited )
(lldb) target select 0
Current targets:
* target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped )
target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited )
(lldb) bt
* thread #1: tid = 0x2d03, 0x0000000100000b9a a.out`main + 42 at main.c:16, stop reason = breakpoint 1.1
frame #0: 0x0000000100000b9a a.out`main + 42 at main.c:16
frame #1: 0x0000000100000b64 a.out`start + 52
Above we created a target for "a.out" and ran and hit a
breakpoint at "main". Then we created a new target for /bin/ls
and ran it. Then we listed the targest and selected our original
"a.out" program, so we showed two concurent debug sessions
going on at the same time.
llvm-svn: 129695
2011-04-18 16:33:37 +08:00
continue ;
}
thread - > GetStatus ( strm ,
start_frame ,
num_frames ,
num_frames_with_source ) ;
+ + num_thread_infos_dumped ;
}
}
return num_thread_infos_dumped ;
}
2012-02-22 12:37:26 +08:00
void
Process : : AddInvalidMemoryRegion ( const LoadRange & region )
{
m_memory_cache . AddInvalidRange ( region . GetRangeBase ( ) , region . GetByteSize ( ) ) ;
}
bool
Process : : RemoveInvalidMemoryRange ( const LoadRange & region )
{
return m_memory_cache . RemoveInvalidRange ( region . GetRangeBase ( ) , region . GetByteSize ( ) ) ;
}
2012-04-07 08:00:41 +08:00
void
Process : : AddPreResumeAction ( PreResumeActionCallback callback , void * baton )
{
m_pre_resume_actions . push_back ( PreResumeCallbackAndBaton ( callback , baton ) ) ;
}
bool
Process : : RunPreResumeActions ( )
{
bool result = true ;
while ( ! m_pre_resume_actions . empty ( ) )
{
struct PreResumeCallbackAndBaton action = m_pre_resume_actions . back ( ) ;
m_pre_resume_actions . pop_back ( ) ;
bool this_result = action . callback ( action . baton ) ;
if ( result = = true ) result = this_result ;
}
return result ;
}
void
Process : : ClearPreResumeActions ( )
{
m_pre_resume_actions . clear ( ) ;
}
2012-02-22 12:37:26 +08:00
2012-05-18 10:38:05 +08:00
void
Process : : Flush ( )
{
m_thread_list . Flush ( ) ;
}
2012-12-05 08:16:59 +08:00
void
Process : : DidExec ( )
{
Target & target = GetTarget ( ) ;
target . CleanupProcess ( ) ;
ModuleList unloaded_modules ( target . GetImages ( ) ) ;
target . ModulesDidUnload ( unloaded_modules ) ;
target . GetSectionLoadList ( ) . Clear ( ) ;
m_dynamic_checkers_ap . reset ( ) ;
m_abi_sp . reset ( ) ;
m_os_ap . reset ( ) ;
m_dyld_ap . reset ( ) ;
m_image_tokens . clear ( ) ;
m_allocated_memory_cache . Clear ( ) ;
m_language_runtimes . clear ( ) ;
DoDidExec ( ) ;
CompleteAttach ( ) ;
}