2010-06-08 16:52:24 +00:00
//===-- CommandObjectRegister.cpp -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
2016-02-23 01:43:44 +00:00
# include "CommandObjectRegister.h"
2016-09-06 20:57:50 +00:00
# include "lldb/Core/Debugger.h"
2011-05-09 20:18:18 +00:00
# include "lldb/Core/RegisterValue.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Core/Scalar.h"
2017-03-22 23:33:16 +00:00
# include "lldb/Host/OptionParser.h"
2010-06-23 01:19:29 +00:00
# include "lldb/Interpreter/CommandInterpreter.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Interpreter/CommandReturnObject.h"
2011-10-25 06:44:01 +00:00
# include "lldb/Interpreter/OptionGroupFormat.h"
2012-08-22 17:17:09 +00:00
# include "lldb/Interpreter/OptionValueArray.h"
2015-03-03 19:23:09 +00:00
# include "lldb/Interpreter/OptionValueBoolean.h"
2012-08-22 17:17:09 +00:00
# include "lldb/Interpreter/OptionValueUInt64.h"
2016-09-06 20:57:50 +00:00
# include "lldb/Interpreter/Options.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Target/ExecutionContext.h"
2011-05-05 02:16:20 +00:00
# include "lldb/Target/Process.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Target/RegisterContext.h"
2013-12-06 01:12:00 +00:00
# include "lldb/Target/SectionLoadList.h"
2011-05-05 02:16:20 +00:00
# include "lldb/Target/Thread.h"
2018-04-17 18:53:35 +00:00
# include "lldb/Utility/Args.h"
2017-03-04 01:30:05 +00:00
# include "lldb/Utility/DataExtractor.h"
2017-06-06 14:06:17 +00:00
# include "llvm/Support/Errno.h"
2010-06-08 16:52:24 +00:00
using namespace lldb ;
using namespace lldb_private ;
//----------------------------------------------------------------------
// "register read"
//----------------------------------------------------------------------
Convert option tables to ArrayRefs.
This change is very mechanical. All it does is change the
signature of `Options::GetDefinitions()` and `OptionGroup::
GetDefinitions()` to return an `ArrayRef<OptionDefinition>`
instead of a `const OptionDefinition *`. In the case of the
former, it deletes the sentinel entry from every table, and
in the case of the latter, it removes the `GetNumDefinitions()`
method from the interface. These are no longer necessary as
`ArrayRef` carries its own length.
In the former case, iteration was done by using a sentinel
entry, so there was no knowledge of length. Because of this
the individual option tables were allowed to be defined below
the corresponding class (after all, only a pointer was needed).
Now, however, the length must be known at compile time to
construct the `ArrayRef`, and as a result it is necessary to
move every option table before its corresponding class. This
results in this CL looking very big, but in terms of substance
there is not much here.
Differential revision: https://reviews.llvm.org/D24834
llvm-svn: 282188
2016-09-22 20:22:55 +00:00
static OptionDefinition g_register_read_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , false , " alternate " , ' A ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Display register names using the alternate register name if there is one. " } ,
{ LLDB_OPT_SET_1 , false , " set " , ' s ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeIndex , " Specify which register sets to dump by index. " } ,
{ LLDB_OPT_SET_2 , false , " all " , ' a ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Show all register sets. " } ,
// clang-format on
} ;
2016-09-06 20:57:50 +00:00
class CommandObjectRegisterRead : public CommandObjectParsed {
2010-06-08 16:52:24 +00:00
public :
2016-09-06 20:57:50 +00:00
CommandObjectRegisterRead ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " register read " ,
" Dump the contents of one or more register values from the current "
" frame. If no register is specified, dumps them all. " ,
nullptr ,
eCommandRequiresFrame | eCommandRequiresRegContext |
eCommandProcessMustBeLaunched | eCommandProcessMustBePaused ) ,
m_option_group ( ) , m_format_options ( eFormatDefault ) ,
m_command_options ( ) {
CommandArgumentEntry arg ;
CommandArgumentData register_arg ;
// Define the first (and only) variant of this arg.
register_arg . arg_type = eArgTypeRegisterName ;
register_arg . arg_repetition = eArgRepeatStar ;
// There is only one variant this argument could be; put it into the
// argument entry.
arg . push_back ( register_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
// Add the "--format"
m_option_group . Append ( & m_format_options ,
OptionGroupFormat : : OPTION_GROUP_FORMAT |
OptionGroupFormat : : OPTION_GROUP_GDB_FMT ,
LLDB_OPT_SET_ALL ) ;
m_option_group . Append ( & m_command_options ) ;
m_option_group . Finalize ( ) ;
}
~ CommandObjectRegisterRead ( ) override = default ;
Options * GetOptions ( ) override { return & m_option_group ; }
bool DumpRegister ( const ExecutionContext & exe_ctx , Stream & strm ,
RegisterContext * reg_ctx , const RegisterInfo * reg_info ) {
if ( reg_info ) {
RegisterValue reg_value ;
if ( reg_ctx - > ReadRegister ( reg_info , reg_value ) ) {
strm . Indent ( ) ;
bool prefix_with_altname = ( bool ) m_command_options . alternate_name ;
bool prefix_with_name = ! prefix_with_altname ;
reg_value . Dump ( & strm , reg_info , prefix_with_name , prefix_with_altname ,
m_format_options . GetFormat ( ) , 8 ) ;
if ( ( reg_info - > encoding = = eEncodingUint ) | |
( reg_info - > encoding = = eEncodingSint ) ) {
Process * process = exe_ctx . GetProcessPtr ( ) ;
if ( process & & reg_info - > byte_size = = process - > GetAddressByteSize ( ) ) {
addr_t reg_addr = reg_value . GetAsUInt64 ( LLDB_INVALID_ADDRESS ) ;
if ( reg_addr ! = LLDB_INVALID_ADDRESS ) {
Address so_reg_addr ;
if ( exe_ctx . GetTargetRef ( )
. GetSectionLoadList ( )
. ResolveLoadAddress ( reg_addr , so_reg_addr ) ) {
strm . PutCString ( " " ) ;
so_reg_addr . Dump ( & strm , exe_ctx . GetBestExecutionContextScope ( ) ,
Address : : DumpStyleResolvedDescription ) ;
}
2011-04-22 03:55:06 +00:00
}
2016-09-06 20:57:50 +00:00
}
2011-04-22 03:55:06 +00:00
}
2016-09-06 20:57:50 +00:00
strm . EOL ( ) ;
return true ;
}
2011-04-22 03:55:06 +00:00
}
2016-09-06 20:57:50 +00:00
return false ;
}
bool DumpRegisterSet ( const ExecutionContext & exe_ctx , Stream & strm ,
RegisterContext * reg_ctx , size_t set_idx ,
bool primitive_only = false ) {
uint32_t unavailable_count = 0 ;
uint32_t available_count = 0 ;
if ( ! reg_ctx )
return false ; // thread has no registers (i.e. core files are corrupt,
// incomplete crash logs...)
const RegisterSet * const reg_set = reg_ctx - > GetRegisterSet ( set_idx ) ;
if ( reg_set ) {
strm . Printf ( " %s: \n " , ( reg_set - > name ? reg_set - > name : " unknown " ) ) ;
strm . IndentMore ( ) ;
const size_t num_registers = reg_set - > num_registers ;
for ( size_t reg_idx = 0 ; reg_idx < num_registers ; + + reg_idx ) {
const uint32_t reg = reg_set - > registers [ reg_idx ] ;
const RegisterInfo * reg_info = reg_ctx - > GetRegisterInfoAtIndex ( reg ) ;
// Skip the dumping of derived register if primitive_only is true.
if ( primitive_only & & reg_info & & reg_info - > value_regs )
continue ;
if ( DumpRegister ( exe_ctx , strm , reg_ctx , reg_info ) )
+ + available_count ;
else
+ + unavailable_count ;
}
strm . IndentLess ( ) ;
if ( unavailable_count ) {
strm . Indent ( ) ;
strm . Printf ( " %u registers were unavailable. \n " , unavailable_count ) ;
}
strm . EOL ( ) ;
2011-04-22 03:55:06 +00:00
}
2016-09-06 20:57:50 +00:00
return available_count > 0 ;
}
2011-04-22 03:55:06 +00:00
2012-06-08 21:56:10 +00:00
protected :
2016-09-06 20:57:50 +00:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Stream & strm = result . GetOutputStream ( ) ;
RegisterContext * reg_ctx = m_exe_ctx . GetRegisterContext ( ) ;
const RegisterInfo * reg_info = nullptr ;
if ( command . GetArgumentCount ( ) = = 0 ) {
size_t set_idx ;
size_t num_register_sets = 1 ;
const size_t set_array_size = m_command_options . set_indexes . GetSize ( ) ;
if ( set_array_size > 0 ) {
for ( size_t i = 0 ; i < set_array_size ; + + i ) {
set_idx = m_command_options . set_indexes [ i ] - > GetUInt64Value ( UINT32_MAX ,
nullptr ) ;
if ( set_idx < reg_ctx - > GetRegisterSetCount ( ) ) {
if ( ! DumpRegisterSet ( m_exe_ctx , strm , reg_ctx , set_idx ) ) {
if ( errno )
2017-06-06 14:06:17 +00:00
result . AppendErrorWithFormatv ( " register read failed: {0} \n " ,
llvm : : sys : : StrError ( ) ) ;
2016-09-06 20:57:50 +00:00
else
result . AppendError ( " unknown error while reading registers. \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
break ;
Expanded the flags that can be set for a command object in lldb_private::CommandObject. This list of available flags are:
enum
{
//----------------------------------------------------------------------
// eFlagRequiresTarget
//
// Ensures a valid target is contained in m_exe_ctx prior to executing
// the command. If a target doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidTargetDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidTargetDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresTarget = (1u << 0),
//----------------------------------------------------------------------
// eFlagRequiresProcess
//
// Ensures a valid process is contained in m_exe_ctx prior to executing
// the command. If a process doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidProcessDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidProcessDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresProcess = (1u << 1),
//----------------------------------------------------------------------
// eFlagRequiresThread
//
// Ensures a valid thread is contained in m_exe_ctx prior to executing
// the command. If a thread doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidThreadDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidThreadDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresThread = (1u << 2),
//----------------------------------------------------------------------
// eFlagRequiresFrame
//
// Ensures a valid frame is contained in m_exe_ctx prior to executing
// the command. If a frame doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidFrameDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidFrameDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresFrame = (1u << 3),
//----------------------------------------------------------------------
// eFlagRequiresRegContext
//
// Ensures a valid register context (from the selected frame if there
// is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx)
// is availble from m_exe_ctx prior to executing the command. If a
// target doesn't exist or is invalid, the command will fail and
// CommandObject::GetInvalidRegContextDescription() will be returned as
// the error. CommandObject subclasses can override the virtual function
// for GetInvalidRegContextDescription() to provide custom strings when
// needed.
//----------------------------------------------------------------------
eFlagRequiresRegContext = (1u << 4),
//----------------------------------------------------------------------
// eFlagTryTargetAPILock
//
// Attempts to acquire the target lock if a target is selected in the
// command interpreter. If the command object fails to acquire the API
// lock, the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eFlagTryTargetAPILock = (1u << 5),
//----------------------------------------------------------------------
// eFlagProcessMustBeLaunched
//
// Verifies that there is a launched process in m_exe_ctx, if there
// isn't, the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eFlagProcessMustBeLaunched = (1u << 6),
//----------------------------------------------------------------------
// eFlagProcessMustBePaused
//
// Verifies that there is a paused process in m_exe_ctx, if there
// isn't, the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eFlagProcessMustBePaused = (1u << 7)
};
Now each command object contains a "ExecutionContext m_exe_ctx;" member variable that gets initialized prior to running the command. The validity of the target objects in m_exe_ctx are checked to ensure that any target/process/thread/frame/reg context that are required are valid prior to executing the command. Each command object also contains a Mutex::Locker m_api_locker which gets used if eFlagTryTargetAPILock is set. This centralizes a lot of checking code that was previously and inconsistently implemented across many commands.
llvm-svn: 171990
2013-01-09 19:44:40 +00:00
}
2016-09-06 20:57:50 +00:00
} else {
result . AppendErrorWithFormat (
" invalid register set index: % " PRIu64 " \n " , ( uint64_t ) set_idx ) ;
result . SetStatus ( eReturnStatusFailed ) ;
break ;
}
Expanded the flags that can be set for a command object in lldb_private::CommandObject. This list of available flags are:
enum
{
//----------------------------------------------------------------------
// eFlagRequiresTarget
//
// Ensures a valid target is contained in m_exe_ctx prior to executing
// the command. If a target doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidTargetDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidTargetDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresTarget = (1u << 0),
//----------------------------------------------------------------------
// eFlagRequiresProcess
//
// Ensures a valid process is contained in m_exe_ctx prior to executing
// the command. If a process doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidProcessDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidProcessDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresProcess = (1u << 1),
//----------------------------------------------------------------------
// eFlagRequiresThread
//
// Ensures a valid thread is contained in m_exe_ctx prior to executing
// the command. If a thread doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidThreadDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidThreadDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresThread = (1u << 2),
//----------------------------------------------------------------------
// eFlagRequiresFrame
//
// Ensures a valid frame is contained in m_exe_ctx prior to executing
// the command. If a frame doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidFrameDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidFrameDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresFrame = (1u << 3),
//----------------------------------------------------------------------
// eFlagRequiresRegContext
//
// Ensures a valid register context (from the selected frame if there
// is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx)
// is availble from m_exe_ctx prior to executing the command. If a
// target doesn't exist or is invalid, the command will fail and
// CommandObject::GetInvalidRegContextDescription() will be returned as
// the error. CommandObject subclasses can override the virtual function
// for GetInvalidRegContextDescription() to provide custom strings when
// needed.
//----------------------------------------------------------------------
eFlagRequiresRegContext = (1u << 4),
//----------------------------------------------------------------------
// eFlagTryTargetAPILock
//
// Attempts to acquire the target lock if a target is selected in the
// command interpreter. If the command object fails to acquire the API
// lock, the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eFlagTryTargetAPILock = (1u << 5),
//----------------------------------------------------------------------
// eFlagProcessMustBeLaunched
//
// Verifies that there is a launched process in m_exe_ctx, if there
// isn't, the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eFlagProcessMustBeLaunched = (1u << 6),
//----------------------------------------------------------------------
// eFlagProcessMustBePaused
//
// Verifies that there is a paused process in m_exe_ctx, if there
// isn't, the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eFlagProcessMustBePaused = (1u << 7)
};
Now each command object contains a "ExecutionContext m_exe_ctx;" member variable that gets initialized prior to running the command. The validity of the target objects in m_exe_ctx are checked to ensure that any target/process/thread/frame/reg context that are required are valid prior to executing the command. Each command object also contains a Mutex::Locker m_api_locker which gets used if eFlagTryTargetAPILock is set. This centralizes a lot of checking code that was previously and inconsistently implemented across many commands.
llvm-svn: 171990
2013-01-09 19:44:40 +00:00
}
2016-09-06 20:57:50 +00:00
} else {
if ( m_command_options . dump_all_sets )
num_register_sets = reg_ctx - > GetRegisterSetCount ( ) ;
for ( set_idx = 0 ; set_idx < num_register_sets ; + + set_idx ) {
// When dump_all_sets option is set, dump primitive as well as derived
// registers.
DumpRegisterSet ( m_exe_ctx , strm , reg_ctx , set_idx ,
! m_command_options . dump_all_sets . GetCurrentValue ( ) ) ;
2010-06-08 16:52:24 +00:00
}
2016-09-06 20:57:50 +00:00
}
} else {
if ( m_command_options . dump_all_sets ) {
result . AppendError ( " the --all option can't be used when registers "
" names are supplied as arguments \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
} else if ( m_command_options . set_indexes . GetSize ( ) > 0 ) {
result . AppendError ( " the --set <set> option can't be used when "
" registers names are supplied as arguments \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
} else {
2016-12-09 05:46:41 +00:00
for ( auto & entry : command ) {
2016-09-06 20:57:50 +00:00
// in most LLDB commands we accept $rbx as the name for register RBX -
2016-12-09 05:46:41 +00:00
// and here we would reject it and non-existant. we should be more
// consistent towards the user and allow them to say reg read $rbx -
// internally, however, we should be strict and not allow ourselves
2016-09-06 20:57:50 +00:00
// to call our registers $rbx in our own API
2016-12-09 05:46:41 +00:00
auto arg_str = entry . ref ;
arg_str . consume_front ( " $ " ) ;
reg_info = reg_ctx - > GetRegisterInfoByName ( arg_str ) ;
2016-09-06 20:57:50 +00:00
if ( reg_info ) {
if ( ! DumpRegister ( m_exe_ctx , strm , reg_ctx , reg_info ) )
strm . Printf ( " %-12s = error: unavailable \n " , reg_info - > name ) ;
} else {
result . AppendErrorWithFormat ( " Invalid register name '%s'. \n " ,
2016-12-09 05:46:41 +00:00
arg_str . str ( ) . c_str ( ) ) ;
2016-09-06 20:57:50 +00:00
}
}
}
2010-06-08 16:52:24 +00:00
}
2016-09-06 20:57:50 +00:00
return result . Succeeded ( ) ;
}
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-30 18:16:51 +00:00
2016-09-06 20:57:50 +00:00
class CommandOptions : public OptionGroup {
public :
CommandOptions ( )
: OptionGroup ( ) ,
set_indexes ( OptionValue : : ConvertTypeToMask ( OptionValue : : eTypeUInt64 ) ) ,
dump_all_sets ( false , false ) , // Initial and default values are false
alternate_name ( false , false ) { }
2016-02-23 01:43:44 +00:00
2016-09-06 20:57:50 +00:00
~ CommandOptions ( ) override = default ;
2016-02-23 01:43:44 +00:00
Convert option tables to ArrayRefs.
This change is very mechanical. All it does is change the
signature of `Options::GetDefinitions()` and `OptionGroup::
GetDefinitions()` to return an `ArrayRef<OptionDefinition>`
instead of a `const OptionDefinition *`. In the case of the
former, it deletes the sentinel entry from every table, and
in the case of the latter, it removes the `GetNumDefinitions()`
method from the interface. These are no longer necessary as
`ArrayRef` carries its own length.
In the former case, iteration was done by using a sentinel
entry, so there was no knowledge of length. Because of this
the individual option tables were allowed to be defined below
the corresponding class (after all, only a pointer was needed).
Now, however, the length must be known at compile time to
construct the `ArrayRef`, and as a result it is necessary to
move every option table before its corresponding class. This
results in this CL looking very big, but in terms of substance
there is not much here.
Differential revision: https://reviews.llvm.org/D24834
llvm-svn: 282188
2016-09-22 20:22:55 +00:00
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
2016-09-22 21:06:13 +00:00
return llvm : : makeArrayRef ( g_register_read_options ) ;
Convert option tables to ArrayRefs.
This change is very mechanical. All it does is change the
signature of `Options::GetDefinitions()` and `OptionGroup::
GetDefinitions()` to return an `ArrayRef<OptionDefinition>`
instead of a `const OptionDefinition *`. In the case of the
former, it deletes the sentinel entry from every table, and
in the case of the latter, it removes the `GetNumDefinitions()`
method from the interface. These are no longer necessary as
`ArrayRef` carries its own length.
In the former case, iteration was done by using a sentinel
entry, so there was no knowledge of length. Because of this
the individual option tables were allowed to be defined below
the corresponding class (after all, only a pointer was needed).
Now, however, the length must be known at compile time to
construct the `ArrayRef`, and as a result it is necessary to
move every option table before its corresponding class. This
results in this CL looking very big, but in terms of substance
there is not much here.
Differential revision: https://reviews.llvm.org/D24834
llvm-svn: 282188
2016-09-22 20:22:55 +00:00
}
2011-10-25 06:44:01 +00:00
2016-09-06 20:57:50 +00:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
set_indexes . Clear ( ) ;
dump_all_sets . Clear ( ) ;
alternate_name . Clear ( ) ;
}
2017-05-12 04:51:55 +00:00
Status SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_value ,
ExecutionContext * execution_context ) override {
Status error ;
Convert option tables to ArrayRefs.
This change is very mechanical. All it does is change the
signature of `Options::GetDefinitions()` and `OptionGroup::
GetDefinitions()` to return an `ArrayRef<OptionDefinition>`
instead of a `const OptionDefinition *`. In the case of the
former, it deletes the sentinel entry from every table, and
in the case of the latter, it removes the `GetNumDefinitions()`
method from the interface. These are no longer necessary as
`ArrayRef` carries its own length.
In the former case, iteration was done by using a sentinel
entry, so there was no knowledge of length. Because of this
the individual option tables were allowed to be defined below
the corresponding class (after all, only a pointer was needed).
Now, however, the length must be known at compile time to
construct the `ArrayRef`, and as a result it is necessary to
move every option table before its corresponding class. This
results in this CL looking very big, but in terms of substance
there is not much here.
Differential revision: https://reviews.llvm.org/D24834
llvm-svn: 282188
2016-09-22 20:22:55 +00:00
const int short_option = GetDefinitions ( ) [ option_idx ] . short_option ;
2016-09-06 20:57:50 +00:00
switch ( short_option ) {
case ' s ' : {
OptionValueSP value_sp ( OptionValueUInt64 : : Create ( option_value , error ) ) ;
if ( value_sp )
set_indexes . AppendValue ( value_sp ) ;
} break ;
case ' a ' :
// When we don't use OptionValue::SetValueFromCString(const char *) to
// set an option value, it won't be marked as being set in the options
// so we make a call to let users know the value was set via option
dump_all_sets . SetCurrentValue ( true ) ;
dump_all_sets . SetOptionWasSet ( ) ;
break ;
case ' A ' :
// When we don't use OptionValue::SetValueFromCString(const char *) to
// set an option value, it won't be marked as being set in the options
// so we make a call to let users know the value was set via option
alternate_name . SetCurrentValue ( true ) ;
dump_all_sets . SetOptionWasSet ( ) ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized short option '%c' " ,
short_option ) ;
break ;
}
return error ;
}
// Instance variables to hold the values for command options.
OptionValueArray set_indexes ;
OptionValueBoolean dump_all_sets ;
OptionValueBoolean alternate_name ;
} ;
OptionGroupOptions m_option_group ;
OptionGroupFormat m_format_options ;
CommandOptions m_command_options ;
2010-06-08 16:52:24 +00:00
} ;
//----------------------------------------------------------------------
// "register write"
//----------------------------------------------------------------------
2016-09-06 20:57:50 +00:00
class CommandObjectRegisterWrite : public CommandObjectParsed {
2010-06-08 16:52:24 +00:00
public :
2016-09-06 20:57:50 +00:00
CommandObjectRegisterWrite ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " register write " ,
" Modify a single register value. " , nullptr ,
eCommandRequiresFrame | eCommandRequiresRegContext |
eCommandProcessMustBeLaunched |
eCommandProcessMustBePaused ) {
CommandArgumentEntry arg1 ;
CommandArgumentEntry arg2 ;
CommandArgumentData register_arg ;
CommandArgumentData value_arg ;
// Define the first (and only) variant of this arg.
register_arg . arg_type = eArgTypeRegisterName ;
register_arg . arg_repetition = eArgRepeatPlain ;
// There is only one variant this argument could be; put it into the
// argument entry.
arg1 . push_back ( register_arg ) ;
// Define the first (and only) variant of this arg.
value_arg . arg_type = eArgTypeValue ;
value_arg . arg_repetition = eArgRepeatPlain ;
// There is only one variant this argument could be; put it into the
// argument entry.
arg2 . push_back ( value_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg1 ) ;
m_arguments . push_back ( arg2 ) ;
}
~ CommandObjectRegisterWrite ( ) override = default ;
2010-06-08 16:52:24 +00:00
2012-06-08 21:56:10 +00:00
protected :
2016-09-06 20:57:50 +00:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
DataExtractor reg_data ;
RegisterContext * reg_ctx = m_exe_ctx . GetRegisterContext ( ) ;
if ( command . GetArgumentCount ( ) ! = 2 ) {
result . AppendError (
" register write takes exactly 2 arguments: <reg-name> <value> " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
} else {
2016-12-09 05:46:41 +00:00
auto reg_name = command [ 0 ] . ref ;
auto value_str = command [ 1 ] . ref ;
2016-09-06 20:57:50 +00:00
// in most LLDB commands we accept $rbx as the name for register RBX - and
2016-12-09 05:46:41 +00:00
// here we would reject it and non-existant. we should be more consistent
// towards the user and allow them to say reg write $rbx - internally,
// however, we should be strict and not allow ourselves to call our
// registers $rbx in our own API
reg_name . consume_front ( " $ " ) ;
2016-09-06 20:57:50 +00:00
const RegisterInfo * reg_info = reg_ctx - > GetRegisterInfoByName ( reg_name ) ;
if ( reg_info ) {
RegisterValue reg_value ;
2017-05-12 04:51:55 +00:00
Status error ( reg_value . SetValueFromString ( reg_info , value_str ) ) ;
2016-09-06 20:57:50 +00:00
if ( error . Success ( ) ) {
if ( reg_ctx - > WriteRegister ( reg_info , reg_value ) ) {
// Toss all frames and anything else in the thread
// after a register has been written.
m_exe_ctx . GetThreadRef ( ) . Flush ( ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return true ;
}
Expanded the flags that can be set for a command object in lldb_private::CommandObject. This list of available flags are:
enum
{
//----------------------------------------------------------------------
// eFlagRequiresTarget
//
// Ensures a valid target is contained in m_exe_ctx prior to executing
// the command. If a target doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidTargetDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidTargetDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresTarget = (1u << 0),
//----------------------------------------------------------------------
// eFlagRequiresProcess
//
// Ensures a valid process is contained in m_exe_ctx prior to executing
// the command. If a process doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidProcessDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidProcessDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresProcess = (1u << 1),
//----------------------------------------------------------------------
// eFlagRequiresThread
//
// Ensures a valid thread is contained in m_exe_ctx prior to executing
// the command. If a thread doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidThreadDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidThreadDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresThread = (1u << 2),
//----------------------------------------------------------------------
// eFlagRequiresFrame
//
// Ensures a valid frame is contained in m_exe_ctx prior to executing
// the command. If a frame doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidFrameDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidFrameDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresFrame = (1u << 3),
//----------------------------------------------------------------------
// eFlagRequiresRegContext
//
// Ensures a valid register context (from the selected frame if there
// is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx)
// is availble from m_exe_ctx prior to executing the command. If a
// target doesn't exist or is invalid, the command will fail and
// CommandObject::GetInvalidRegContextDescription() will be returned as
// the error. CommandObject subclasses can override the virtual function
// for GetInvalidRegContextDescription() to provide custom strings when
// needed.
//----------------------------------------------------------------------
eFlagRequiresRegContext = (1u << 4),
//----------------------------------------------------------------------
// eFlagTryTargetAPILock
//
// Attempts to acquire the target lock if a target is selected in the
// command interpreter. If the command object fails to acquire the API
// lock, the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eFlagTryTargetAPILock = (1u << 5),
//----------------------------------------------------------------------
// eFlagProcessMustBeLaunched
//
// Verifies that there is a launched process in m_exe_ctx, if there
// isn't, the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eFlagProcessMustBeLaunched = (1u << 6),
//----------------------------------------------------------------------
// eFlagProcessMustBePaused
//
// Verifies that there is a paused process in m_exe_ctx, if there
// isn't, the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eFlagProcessMustBePaused = (1u << 7)
};
Now each command object contains a "ExecutionContext m_exe_ctx;" member variable that gets initialized prior to running the command. The validity of the target objects in m_exe_ctx are checked to ensure that any target/process/thread/frame/reg context that are required are valid prior to executing the command. Each command object also contains a Mutex::Locker m_api_locker which gets used if eFlagTryTargetAPILock is set. This centralizes a lot of checking code that was previously and inconsistently implemented across many commands.
llvm-svn: 171990
2013-01-09 19:44:40 +00:00
}
2016-09-06 20:57:50 +00:00
if ( error . AsCString ( ) ) {
result . AppendErrorWithFormat (
2016-12-09 05:46:41 +00:00
" Failed to write register '%s' with value '%s': %s \n " ,
reg_name . str ( ) . c_str ( ) , value_str . str ( ) . c_str ( ) ,
error . AsCString ( ) ) ;
2016-09-06 20:57:50 +00:00
} else {
result . AppendErrorWithFormat (
2016-12-09 05:46:41 +00:00
" Failed to write register '%s' with value '%s' " ,
reg_name . str ( ) . c_str ( ) , value_str . str ( ) . c_str ( ) ) ;
2010-06-08 16:52:24 +00:00
}
2016-09-06 20:57:50 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
} else {
result . AppendErrorWithFormat ( " Register not found for '%s'. \n " ,
2016-12-09 05:46:41 +00:00
reg_name . str ( ) . c_str ( ) ) ;
2016-09-06 20:57:50 +00:00
result . SetStatus ( eReturnStatusFailed ) ;
}
2010-06-08 16:52:24 +00:00
}
2016-09-06 20:57:50 +00:00
return result . Succeeded ( ) ;
}
2010-06-08 16:52:24 +00:00
} ;
//----------------------------------------------------------------------
// CommandObjectRegister constructor
//----------------------------------------------------------------------
2016-07-14 22:03:10 +00:00
CommandObjectRegister : : CommandObjectRegister ( CommandInterpreter & interpreter )
: CommandObjectMultiword ( interpreter , " register " ,
2016-09-06 20:57:50 +00:00
" Commands to access registers for the current "
" thread and stack frame. " ,
" register [read|write] ... " ) {
LoadSubCommand ( " read " ,
CommandObjectSP ( new CommandObjectRegisterRead ( interpreter ) ) ) ;
LoadSubCommand ( " write " ,
CommandObjectSP ( new CommandObjectRegisterWrite ( interpreter ) ) ) ;
2010-06-08 16:52:24 +00:00
}
2016-02-23 01:43:44 +00:00
CommandObjectRegister : : ~ CommandObjectRegister ( ) = default ;