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
This commit is contained in:
Greg Clayton 2011-03-30 18:16:51 +00:00
parent ae917a3740
commit 32e0a7509c
74 changed files with 3020 additions and 1087 deletions

View File

@ -27,7 +27,8 @@ namespace lldb_private {
class Instruction
{
public:
Instruction (const Address &address, AddressClass addr_class);
Instruction (const Address &address,
AddressClass addr_class = eAddressClassInvalid);
virtual
~Instruction();
@ -202,7 +203,6 @@ public:
Debugger &debugger,
const ArchSpec &arch,
const ExecutionContext &exe_ctx,
const Address &start_addr,
uint32_t num_instructions,
uint32_t num_mixed_context_lines,
bool show_bytes,

View File

@ -320,12 +320,47 @@ public:
//------------------------------------------------------------------
/// Get const accessor for the module file specification.
///
/// This function returns the file for the module on the host system
/// that is running LLDB. This can differ from the path on the
/// platform since we might be doing remote debugging.
///
/// @return
/// A const reference to the file specification object.
//------------------------------------------------------------------
const FileSpec &
GetFileSpec () const;
GetFileSpec () const
{
return m_file;
}
//------------------------------------------------------------------
/// Get accessor for the module platform file specification.
///
/// Platform file refers to the path of the module as it is known on
/// the remote system on which it is being debugged. For local
/// debugging this is always the same as Module::GetFileSpec(). But
/// remote debugging might mention a file "/usr/lib/liba.dylib"
/// which might be locally downloaded and cached. In this case the
/// platform file could be something like:
/// "/tmp/lldb/platform-cache/remote.host.computer/usr/lib/liba.dylib"
/// The file could also be cached in a local developer kit directory.
///
/// @return
/// A const reference to the file specification object.
//------------------------------------------------------------------
const FileSpec &
GetPlatformFileSpec () const
{
if (m_platform_file)
return m_platform_file;
return m_file;
}
void
SetPlatformFileSpec (const FileSpec &file)
{
m_platform_file = file;
}
const TimeValue &
GetModificationTime () const;
@ -561,6 +596,7 @@ protected:
ArchSpec m_arch; ///< The architecture for this module.
lldb_private::UUID m_uuid; ///< Each module is assumed to have a unique identifier to help match it up to debug symbols.
FileSpec m_file; ///< The file representation on disk for this module (if there is one).
FileSpec m_platform_file;///< The path to the module on the platform on which it is being debugged
ConstString m_object_name; ///< The name an object within this module that is selected, or empty of the module is represented by \a m_file.
std::auto_ptr<ObjectFile> m_objfile_ap; ///< A pointer to the object file parser for this module.
std::auto_ptr<SymbolVendor> m_symfile_ap; ///< A pointer to the symbol vendor for this module.

View File

@ -266,9 +266,25 @@ public:
lldb::ModuleSP
FindModule (const Module *module_ptr);
//------------------------------------------------------------------
// Find a module by UUID
//
// The UUID value for a module is extracted from the ObjectFile and
// is the MD5 checksum, or a smarter object file equivalent, so
// finding modules by UUID values is very efficient and accurate.
//------------------------------------------------------------------
lldb::ModuleSP
FindModule (const UUID &uuid);
lldb::ModuleSP
FindFirstModuleForFileSpec (const FileSpec &file_spec,
const ConstString *object_name = NULL);
const ArchSpec *arch_ptr,
const ConstString *object_name);
lldb::ModuleSP
FindFirstModuleForPlatormFileSpec (const FileSpec &platform_file_spec,
const ArchSpec *arch_ptr,
const ConstString *object_name);
size_t
FindSymbolsWithNameAndType (const ConstString &name,

View File

@ -110,6 +110,12 @@ public:
static bool
GetHostname (std::string &s);
static const char *
GetUserName (uint32_t uid, std::string &user_name);
static const char *
GetGroupName (uint32_t gid, std::string &group_name);
//------------------------------------------------------------------
/// Gets the host architecture.
///
@ -337,9 +343,8 @@ public:
SetCrashDescription (const char *description);
static uint32_t
FindProcessesByName (const char *name,
NameMatchType name_match_type,
ProcessInfoList &proc_infos);
FindProcesses (const ProcessInfoMatch &match_info,
ProcessInfoList &proc_infos);
static bool
GetProcessInfo (lldb::pid_t pid, ProcessInfo &proc_info);

View File

@ -167,8 +167,13 @@ public:
virtual const OptionDefinition*
GetDefinitions () { return NULL; }
virtual void
ResetOptionValues ();
// Call this prior to parsing any options. This call will call the
// subclass ResetOptionValues() and will avoid the need for all
// ResetOptionValues() function instances from having to call the
// Option::ResetOptionValues() like they did before. This was error
// prone and subclasses shouldn't have to do it.
void
Reset ();
//------------------------------------------------------------------
/// Set the value of an option.
@ -313,6 +318,12 @@ protected:
void
OptionsSetUnion (const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set);
// Subclasses must reset their option values prior to starting a new
// option parse. Each subclass must override this function and revert
// all option settings to default values.
virtual void
ResetOptionValues () = 0;
};
} // namespace lldb_private

View File

@ -12,6 +12,7 @@
// C Includes
// C++ Includes
#include <map>
#include <string>
#include <vector>
@ -19,6 +20,7 @@
// Project includes
#include "lldb/lldb-public.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Host/Mutex.h"
@ -121,7 +123,7 @@ namespace lldb_private {
bool
GetOSKernelDescription (std::string &s);
const char *
virtual const char *
GetHostname ();
virtual const char *
@ -172,13 +174,11 @@ namespace lldb_private {
return ArchSpec(); // Return an invalid architecture
}
// Remote subclasses should override this and return a valid instance
// name if connected.
virtual const char *
GetRemoteHostname ()
{
return NULL;
}
GetUserName (uint32_t uid);
virtual const char *
GetGroupName (uint32_t gid);
//------------------------------------------------------------------
/// Locate a file for a platform.
@ -189,6 +189,15 @@ namespace lldb_private {
/// @param[in] platform_file
/// The platform file path to locate and cache locally.
///
/// @param[in] uuid_ptr
/// If we know the exact UUID of the file we are looking for, it
/// can be specified. If it is not specified, we might now know
/// the exact file. The UUID is usually some sort of MD5 checksum
/// for the file and is sometimes known by dynamic linkers/loaders.
/// If the UUID is known, it is best to supply it to platform
/// file queries to ensure we are finding the correct file, not
/// just a file at the correct path.
///
/// @param[out] local_file
/// A locally cached version of the platform file. For platforms
/// that describe the current host computer, this will just be
@ -204,6 +213,16 @@ namespace lldb_private {
const UUID *uuid_ptr,
FileSpec &local_file);
virtual Error
GetSharedModule (const FileSpec &platform_file,
const ArchSpec &arch,
const UUID *uuid_ptr,
const ConstString *object_name_ptr,
off_t object_offset,
lldb::ModuleSP &module_sp,
lldb::ModuleSP *old_module_sp_ptr,
bool *did_create_ptr);
virtual Error
ConnectRemote (Args& args);
@ -333,13 +352,16 @@ namespace lldb_private {
// bool wait_for_launch,
// Error &error) = 0;
//------------------------------------------------------------------
// The base class Platform will take care of the host platform.
// Subclasses will need to fill in the remote case.
//------------------------------------------------------------------
virtual uint32_t
FindProcessesByName (const char *name,
NameMatchType name_match_type,
ProcessInfoList &proc_infos) = 0;
FindProcesses (const ProcessInfoMatch &match_info,
ProcessInfoList &proc_infos);
virtual bool
GetProcessInfo (lldb::pid_t pid, ProcessInfo &proc_info) = 0;
GetProcessInfo (lldb::pid_t pid, ProcessInfo &proc_info);
const std::string &
GetRemoteURL () const
@ -377,6 +399,18 @@ namespace lldb_private {
m_os_version_set_while_connected = m_system_arch.IsValid();
}
// Used for column widths
uint32_t
GetMaxUserIDNameLength() const
{
return m_max_uid_name_len;
}
// Used for column widths
uint32_t
GetMaxGroupIDNameLength() const
{
return m_max_gid_name_len;
}
protected:
bool m_is_host;
// Set to true when we are able to actually set the OS version while
@ -392,6 +426,99 @@ namespace lldb_private {
uint32_t m_minor_os_version;
uint32_t m_update_os_version;
ArchSpec m_system_arch; // The architecture of the kernel or the remote platform
typedef std::map<uint32_t, ConstString> IDToNameMap;
Mutex m_uid_map_mutex;
Mutex m_gid_map_mutex;
IDToNameMap m_uid_map;
IDToNameMap m_gid_map;
uint32_t m_max_uid_name_len;
uint32_t m_max_gid_name_len;
const char *
GetCachedUserName (uint32_t uid)
{
Mutex::Locker locker (m_uid_map_mutex);
IDToNameMap::iterator pos = m_uid_map.find (uid);
if (pos != m_uid_map.end())
{
// return the empty string if our string is NULL
// so we can tell when things were in the negative
// cached (didn't find a valid user name, don't keep
// trying)
return pos->second.AsCString("");
}
return NULL;
}
const char *
SetCachedUserName (uint32_t uid, const char *name, size_t name_len)
{
Mutex::Locker locker (m_uid_map_mutex);
ConstString const_name (name);
m_uid_map[uid] = const_name;
if (m_max_uid_name_len < name_len)
m_max_uid_name_len = name_len;
// Const strings lives forever in our const string pool, so we can return the const char *
return const_name.GetCString();
}
void
SetUserNameNotFound (uint32_t uid)
{
Mutex::Locker locker (m_uid_map_mutex);
m_uid_map[uid] = ConstString();
}
void
ClearCachedUserNames ()
{
Mutex::Locker locker (m_uid_map_mutex);
m_uid_map.clear();
}
const char *
GetCachedGroupName (uint32_t gid)
{
Mutex::Locker locker (m_gid_map_mutex);
IDToNameMap::iterator pos = m_gid_map.find (gid);
if (pos != m_gid_map.end())
{
// return the empty string if our string is NULL
// so we can tell when things were in the negative
// cached (didn't find a valid group name, don't keep
// trying)
return pos->second.AsCString("");
}
return NULL;
}
const char *
SetCachedGroupName (uint32_t gid, const char *name, size_t name_len)
{
Mutex::Locker locker (m_gid_map_mutex);
ConstString const_name (name);
m_gid_map[gid] = const_name;
if (m_max_gid_name_len < name_len)
m_max_gid_name_len = name_len;
// Const strings lives forever in our const string pool, so we can return the const char *
return const_name.GetCString();
}
void
SetGroupNameNotFound (uint32_t gid)
{
Mutex::Locker locker (m_gid_map_mutex);
m_gid_map[gid] = ConstString();
}
void
ClearCachedGroupNames ()
{
Mutex::Locker locker (m_gid_map_mutex);
m_gid_map.clear();
}
private:
DISALLOW_COPY_AND_ASSIGN (Platform);
};

View File

@ -233,7 +233,8 @@ public:
m_effective_uid (UINT32_MAX),
m_effective_gid (UINT32_MAX),
m_arch(),
m_pid (LLDB_INVALID_PROCESS_ID)
m_pid (LLDB_INVALID_PROCESS_ID),
m_parent_pid (LLDB_INVALID_PROCESS_ID)
{
}
@ -246,7 +247,8 @@ public:
m_effective_uid (UINT32_MAX),
m_effective_gid (UINT32_MAX),
m_arch (arch),
m_pid (pid)
m_pid (pid),
m_parent_pid (LLDB_INVALID_PROCESS_ID)
{
}
@ -260,11 +262,14 @@ public:
m_effective_gid = UINT32_MAX;
m_arch.Clear();
m_pid = LLDB_INVALID_PROCESS_ID;
m_parent_pid = LLDB_INVALID_PROCESS_ID;
}
const char *
GetName() const
{
if (m_name.empty())
return NULL;
return m_name.c_str();
}
@ -283,12 +288,18 @@ public:
m_name.clear();
}
void
SwapName (std::string &name)
{
m_name.swap (name);
}
uint32_t
GetRealUserID() const
{
return m_real_uid;
}
uint32_t
GetRealGroupID() const
{
@ -306,6 +317,30 @@ public:
{
return m_effective_gid;
}
bool
RealUserIDIsValid () const
{
return m_real_uid != UINT32_MAX;
}
bool
RealGroupIDIsValid () const
{
return m_real_gid != UINT32_MAX;
}
bool
EffectiveUserIDIsValid () const
{
return m_effective_uid != UINT32_MAX;
}
bool
EffectiveGroupIDIsValid () const
{
return m_effective_gid != UINT32_MAX;
}
void
SetRealUserID (uint32_t uid)
@ -378,6 +413,15 @@ public:
{
return m_parent_pid != LLDB_INVALID_PROCESS_ID;
}
void
Dump (Stream &s, Platform *platform) const;
static void
DumpTableHeader (Stream &s, Platform *platform);
void
DumpAsTableRow (Stream &s, Platform *platform) const;
protected:
std::string m_name;
@ -390,6 +434,78 @@ protected:
lldb::pid_t m_parent_pid;
};
class ProcessInfoMatch
{
public:
ProcessInfoMatch () :
m_match_info (),
m_name_match_type (lldb_private::eNameMatchIgnore),
m_match_all_users (false)
{
}
ProcessInfoMatch (const char *process_name,
lldb_private::NameMatchType process_name_match_type) :
m_match_info (),
m_name_match_type (process_name_match_type),
m_match_all_users (false)
{
m_match_info.SetName (process_name);
}
ProcessInfo &
GetProcessInfo ()
{
return m_match_info;
}
const ProcessInfo &
GetProcessInfo () const
{
return m_match_info;
}
bool
GetMatchAllUsers () const
{
return m_match_all_users;
}
void
SetMatchAllUsers (bool b)
{
m_match_all_users = b;
}
lldb_private::NameMatchType
GetNameMatchType () const
{
return m_name_match_type;
}
void
SetNameMatchType (lldb_private::NameMatchType name_match_type)
{
m_name_match_type = name_match_type;
}
bool
NameMatches (const char *process_name) const;
bool
Matches (const ProcessInfo &proc_info) const;
bool
MatchAllProcesses () const;
void
Clear ();
protected:
ProcessInfo m_match_info;
lldb_private::NameMatchType m_name_match_type;
bool m_match_all_users;
};
class ProcessInfoList
{
public:
@ -451,6 +567,14 @@ public:
return false;
}
// You must ensure "idx" is valid before calling this function
const ProcessInfo &
GetProcessInfoAtIndex (uint32_t idx) const
{
assert (idx < m_infos.size());
return m_infos[idx];
}
protected:
typedef std::vector<ProcessInfo> collection;
collection m_infos;

View File

@ -135,7 +135,9 @@ private:
///
/// @see TargetList::CreateTarget(const FileSpec*, const ArchSpec*)
//------------------------------------------------------------------
Target(Debugger &debugger, const lldb::PlatformSP &platform_sp);
Target (Debugger &debugger,
const ArchSpec &target_arch,
const lldb::PlatformSP &platform_sp);
public:
~Target();
@ -345,13 +347,13 @@ public:
ArchSpec &
GetArchitecture ()
{
return m_arch_spec;
return m_arch;
}
const ArchSpec &
GetArchitecture () const
{
return m_arch_spec;
return m_arch;
}
//------------------------------------------------------------------
@ -662,7 +664,7 @@ protected:
Debugger & m_debugger;
lldb::PlatformSP m_platform_sp; ///< The platform for this target.
Mutex m_mutex; ///< An API mutex that is used by the lldb::SB* classes make the SB interface thread safe
ArchSpec m_arch_spec;
ArchSpec m_arch;
ModuleList m_images; ///< The list of images for this process (shared libraries and anything dynamically loaded).
SectionLoadList m_section_load_list;
BreakpointList m_breakpoint_list;

View File

@ -103,6 +103,7 @@ class Platform;
class Process;
class ProcessInfo;
class ProcessInfoList;
class ProcessInfoMatch;
class RegisterContext;
class RegisterLocation;
class RegisterLocationList;

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
version = "1.3">
version = "1.5">
<BuildAction
parallelizeBuildables = "NO"
buildImplicitDependencies = "YES">
@ -77,7 +77,8 @@
displayScaleIsEnabled = "NO"
displayScale = "1.00"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
useCustomWorkingDirectory = "YES"
customWorkingDirectory = "/Volumes/work/gclayton/Documents/src/lldb/build/Debug"
buildConfiguration = "Debug">
<BuildableProductRunnable>
<BuildableReference
@ -88,6 +89,12 @@
ReferencedContainer = "container:lldb.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "/Volumes/work/gclayton/Documents/src/a.out"
isEnabled = "NO">
</CommandLineArgument>
</CommandLineArguments>
<EnvironmentVariables>
<EnvironmentVariable
key = "LLDB_LAUNCH_FLAG_DISABLE_ASLR"
@ -189,4 +196,7 @@
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
<InstallAction
buildConfiguration = "Debug">
</InstallAction>
</Scheme>

View File

@ -743,7 +743,7 @@ SBTarget::FindModule (const SBFileSpec &sb_file_spec)
if (m_opaque_sp && sb_file_spec.IsValid())
{
// The module list is thread safe, no need to lock
sb_module.SetModule (m_opaque_sp->GetImages().FindFirstModuleForFileSpec (*sb_file_spec, NULL));
sb_module.SetModule (m_opaque_sp->GetImages().FindFirstModuleForFileSpec (*sb_file_spec, NULL, NULL));
}
return sb_module;
}

View File

@ -68,7 +68,6 @@ CommandObjectArgs::CommandOptions::SetOptionValue (int option_idx, const char *o
void
CommandObjectArgs::CommandOptions::ResetOptionValues ()
{
Options::ResetOptionValues();
}
const OptionDefinition*

View File

@ -235,8 +235,6 @@ CommandObjectBreakpointSet::CommandOptions::SetOptionValue (int option_idx, cons
void
CommandObjectBreakpointSet::CommandOptions::ResetOptionValues ()
{
Options::ResetOptionValues();
m_filename.clear();
m_line_num = 0;
m_column = 0;
@ -706,8 +704,6 @@ CommandObjectBreakpointList::CommandOptions::SetOptionValue (int option_idx, con
void
CommandObjectBreakpointList::CommandOptions::ResetOptionValues ()
{
Options::ResetOptionValues();
m_level = lldb::eDescriptionLevelBrief;
m_internal = false;
}
@ -1105,8 +1101,6 @@ CommandObjectBreakpointClear::CommandOptions::SetOptionValue (int option_idx, co
void
CommandObjectBreakpointClear::CommandOptions::ResetOptionValues ()
{
Options::ResetOptionValues();
m_filename.clear();
m_line_num = 0;
}
@ -1485,8 +1479,6 @@ CommandObjectBreakpointModify::CommandOptions::SetOptionValue (int option_idx, c
void
CommandObjectBreakpointModify::CommandOptions::ResetOptionValues ()
{
Options::ResetOptionValues();
m_ignore_count = 0;
m_thread_id = LLDB_INVALID_THREAD_ID;
m_thread_id_passed = false;

View File

@ -135,8 +135,6 @@ CommandObjectBreakpointCommandAdd::CommandOptions::SetOptionValue
void
CommandObjectBreakpointCommandAdd::CommandOptions::ResetOptionValues ()
{
Options::ResetOptionValues();
m_use_commands = true;
m_use_script_language = false;
m_script_language = eScriptLanguageNone;

View File

@ -69,8 +69,6 @@ private:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
m_stop_on_error = true;
m_stop_on_continue = true;
}
@ -358,7 +356,7 @@ public:
if (options)
{
// See if any options were specified as part of the alias; if so, handle them appropriately
options->ResetOptionValues ();
options->Reset ();
Args tmp_args (raw_command_string.c_str());
args.Unshift ("dummy_arg");
args.ParseAliasOptions (*options, result, option_arg_vector, raw_command_string);
@ -489,7 +487,7 @@ public:
options = sub_cmd_obj->GetOptions();
else
options = cmd_obj->GetOptions();
options->ResetOptionValues ();
options->Reset ();
std::string empty_string;
args.Unshift ("dummy_arg");
args.ParseAliasOptions (*options, result, option_arg_vector, empty_string);

View File

@ -36,12 +36,13 @@ CommandObjectDisassemble::CommandOptions::CommandOptions () :
Options(),
num_lines_context(0),
num_instructions (0),
m_func_name(),
m_start_addr(),
m_end_addr (),
m_at_pc (false),
m_plugin_name (),
m_arch()
func_name(),
start_addr(),
end_addr (),
at_pc (false),
frame_line (false),
plugin_name (),
arch()
{
ResetOptionValues();
}
@ -82,32 +83,39 @@ CommandObjectDisassemble::CommandOptions::SetOptionValue (int option_idx, const
break;
case 's':
m_start_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 0);
if (m_start_addr == LLDB_INVALID_ADDRESS)
m_start_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 16);
start_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 0);
if (start_addr == LLDB_INVALID_ADDRESS)
start_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 16);
if (m_start_addr == LLDB_INVALID_ADDRESS)
if (start_addr == LLDB_INVALID_ADDRESS)
error.SetErrorStringWithFormat ("Invalid start address string '%s'.\n", option_arg);
break;
case 'e':
m_end_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 0);
if (m_end_addr == LLDB_INVALID_ADDRESS)
m_end_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 16);
end_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 0);
if (end_addr == LLDB_INVALID_ADDRESS)
end_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 16);
if (m_end_addr == LLDB_INVALID_ADDRESS)
if (end_addr == LLDB_INVALID_ADDRESS)
error.SetErrorStringWithFormat ("Invalid end address string '%s'.\n", option_arg);
break;
case 'n':
m_func_name.assign (option_arg);
func_name.assign (option_arg);
break;
case 'p':
m_at_pc = true;
at_pc = true;
break;
case 'l':
frame_line = true;
// Disassemble the current source line kind of implies showing mixed
// source code context.
show_mixed = true;
break;
case 'P':
m_plugin_name.assign (option_arg);
plugin_name.assign (option_arg);
break;
case 'r':
@ -120,7 +128,7 @@ CommandObjectDisassemble::CommandOptions::SetOptionValue (int option_idx, const
break;
case 'a':
m_arch.SetTriple (option_arg);
arch.SetTriple (option_arg);
break;
default:
@ -134,18 +142,18 @@ CommandObjectDisassemble::CommandOptions::SetOptionValue (int option_idx, const
void
CommandObjectDisassemble::CommandOptions::ResetOptionValues ()
{
Options::ResetOptionValues();
show_mixed = false;
show_bytes = false;
num_lines_context = 0;
num_instructions = 0;
m_func_name.clear();
m_at_pc = false;
m_start_addr = LLDB_INVALID_ADDRESS;
m_end_addr = LLDB_INVALID_ADDRESS;
func_name.clear();
at_pc = false;
frame_line = false;
start_addr = LLDB_INVALID_ADDRESS;
end_addr = LLDB_INVALID_ADDRESS;
raw = false;
m_plugin_name.clear();
m_arch.Clear();
plugin_name.clear();
arch.Clear();
}
const OptionDefinition*
@ -172,7 +180,8 @@ CommandObjectDisassemble::CommandOptions::g_option_table[] =
LLDB_OPT_SET_5 , false , "count", 'c', required_argument , NULL, 0, eArgTypeNumLines, "Number of instructions to display."},
{ LLDB_OPT_SET_3 , true , "name", 'n', required_argument , NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name."},
{ LLDB_OPT_SET_4 , true , "frame", 'f', no_argument , NULL, 0, eArgTypeNone, "Disassemble from the start of the current frame's function."},
{ LLDB_OPT_SET_5 , true , "pc", 'p', no_argument , NULL, 0, eArgTypeNone, "Disassemble from the current pc."},
{ LLDB_OPT_SET_5 , true , "pc", 'p', no_argument , NULL, 0, eArgTypeNone, "Disassemble around the current pc."},
{ LLDB_OPT_SET_6 , true , "line", 'l', no_argument , NULL, 0, eArgTypeNone, "Disassemble the current frame's current source line instructions if there debug line table information, else disasemble around the pc."},
{ 0 , false , NULL, 0, 0 , NULL, 0, eArgTypeNone, NULL }
};
@ -208,10 +217,10 @@ CommandObjectDisassemble::Execute
result.SetStatus (eReturnStatusFailed);
return false;
}
if (!m_options.m_arch.IsValid())
m_options.m_arch = target->GetArchitecture();
if (!m_options.arch.IsValid())
m_options.arch = target->GetArchitecture();
if (!m_options.m_arch.IsValid())
if (!m_options.arch.IsValid())
{
result.AppendError ("use the --arch option or set the target architecure to disassemble");
result.SetStatus (eReturnStatusFailed);
@ -219,17 +228,17 @@ CommandObjectDisassemble::Execute
}
const char *plugin_name = m_options.GetPluginName ();
Disassembler *disassembler = Disassembler::FindPlugin(m_options.m_arch, plugin_name);
Disassembler *disassembler = Disassembler::FindPlugin(m_options.arch, plugin_name);
if (disassembler == NULL)
{
if (plugin_name)
result.AppendErrorWithFormat ("Unable to find Disassembler plug-in named '%s' that supports the '%s' architecture.\n",
plugin_name,
m_options.m_arch.GetArchitectureName());
m_options.arch.GetArchitectureName());
else
result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for the '%s' architecture.\n",
m_options.m_arch.GetArchitectureName());
m_options.arch.GetArchitectureName());
result.SetStatus (eReturnStatusFailed);
return false;
}
@ -252,12 +261,12 @@ CommandObjectDisassemble::Execute
ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
if (!m_options.m_func_name.empty())
if (!m_options.func_name.empty())
{
ConstString name(m_options.m_func_name.c_str());
ConstString name(m_options.func_name.c_str());
if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
m_options.m_arch,
m_options.arch,
plugin_name,
exe_ctx,
name,
@ -278,59 +287,76 @@ CommandObjectDisassemble::Execute
}
else
{
Address start_addr;
lldb::addr_t range_byte_size = DEFAULT_DISASM_BYTE_SIZE;
if (m_options.m_at_pc)
AddressRange range;
if (m_options.frame_line)
{
if (exe_ctx.frame == NULL)
LineEntry pc_line_entry (exe_ctx.frame->GetSymbolContext(eSymbolContextLineEntry).line_entry);
if (pc_line_entry.IsValid())
{
result.AppendError ("Cannot disassemble around the current PC without a selected frame.\n");
result.SetStatus (eReturnStatusFailed);
return false;
range = pc_line_entry.range;
}
start_addr = exe_ctx.frame->GetFrameCodeAddress();
if (m_options.num_instructions == 0)
else
{
// Disassembling at the PC always disassembles some number of instructions (not the whole function).
m_options.num_instructions = DEFAULT_DISASM_NUM_INS;
m_options.at_pc = true; // No line entry, so just disassemble around the current pc
m_options.show_mixed = false;
}
}
else
// Did the "m_options.frame_line" find a valid range already? If so
// skip the rest...
if (range.GetByteSize() == 0)
{
start_addr.SetOffset (m_options.m_start_addr);
if (start_addr.IsValid())
if (m_options.at_pc)
{
if (m_options.m_end_addr != LLDB_INVALID_ADDRESS)
if (exe_ctx.frame == NULL)
{
if (m_options.m_end_addr < m_options.m_start_addr)
result.AppendError ("Cannot disassemble around the current PC without a selected frame.\n");
result.SetStatus (eReturnStatusFailed);
return false;
}
range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress();
if (m_options.num_instructions == 0)
{
// Disassembling at the PC always disassembles some number of instructions (not the whole function).
m_options.num_instructions = DEFAULT_DISASM_NUM_INS;
}
}
else
{
range.GetBaseAddress().SetOffset (m_options.start_addr);
if (range.GetBaseAddress().IsValid())
{
if (m_options.end_addr != LLDB_INVALID_ADDRESS)
{
result.AppendErrorWithFormat ("End address before start address.\n");
result.SetStatus (eReturnStatusFailed);
return false;
if (m_options.end_addr <= m_options.start_addr)
{
result.AppendErrorWithFormat ("End address before start address.\n");
result.SetStatus (eReturnStatusFailed);
return false;
}
range.SetByteSize (m_options.end_addr - m_options.start_addr);
}
range_byte_size = m_options.m_end_addr - m_options.m_start_addr;
}
}
}
if (m_options.num_instructions != 0)
{
if (!start_addr.IsValid())
if (!range.GetBaseAddress().IsValid())
{
// The default action is to disassemble the current frame function.
if (exe_ctx.frame)
{
SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
if (sc.function)
start_addr = sc.function->GetAddressRange().GetBaseAddress();
range.GetBaseAddress() = sc.function->GetAddressRange().GetBaseAddress();
else if (sc.symbol && sc.symbol->GetAddressRangePtr())
start_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress();
range.GetBaseAddress() = sc.symbol->GetAddressRangePtr()->GetBaseAddress();
else
start_addr = exe_ctx.frame->GetFrameCodeAddress();
range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress();
}
if (!start_addr.IsValid())
if (!range.GetBaseAddress().IsValid())
{
result.AppendError ("invalid frame");
result.SetStatus (eReturnStatusFailed);
@ -339,10 +365,10 @@ CommandObjectDisassemble::Execute
}
if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
m_options.m_arch,
m_options.arch,
plugin_name,
exe_ctx,
start_addr,
range.GetBaseAddress(),
m_options.num_instructions,
m_options.show_mixed ? m_options.num_lines_context : 0,
m_options.show_bytes,
@ -353,19 +379,13 @@ CommandObjectDisassemble::Execute
}
else
{
result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr);
result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.start_addr);
result.SetStatus (eReturnStatusFailed);
}
}
else
{
AddressRange range;
if (start_addr.IsValid())
{
range.GetBaseAddress() = start_addr;
range.SetByteSize (range_byte_size);
}
else
if (!range.GetBaseAddress().IsValid())
{
// The default action is to disassemble the current frame function.
if (exe_ctx.frame)
@ -389,7 +409,7 @@ CommandObjectDisassemble::Execute
range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
m_options.m_arch,
m_options.arch,
plugin_name,
exe_ctx,
range,
@ -403,7 +423,7 @@ CommandObjectDisassemble::Execute
}
else
{
result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr);
result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.start_addr);
result.SetStatus (eReturnStatusFailed);
}
}

View File

@ -47,9 +47,9 @@ public:
const char *
GetPluginName ()
{
if (m_plugin_name.empty())
if (plugin_name.empty())
return NULL;
return m_plugin_name.c_str();
return plugin_name.c_str();
}
@ -58,12 +58,13 @@ public:
uint32_t num_lines_context;
uint32_t num_instructions;
bool raw;
std::string m_func_name;
lldb::addr_t m_start_addr;
lldb::addr_t m_end_addr;
bool m_at_pc;
std::string m_plugin_name;
ArchSpec m_arch;
std::string func_name;
lldb::addr_t start_addr;
lldb::addr_t end_addr;
bool at_pc;
bool frame_line;
std::string plugin_name;
ArchSpec arch;
static OptionDefinition g_option_table[];
};

View File

@ -95,7 +95,6 @@ CommandObjectExpression::CommandOptions::SetOptionValue (int option_idx, const c
void
CommandObjectExpression::CommandOptions::ResetOptionValues ()
{
Options::ResetOptionValues();
//language.Clear();
debug = false;
format = eFormatDefault;
@ -298,7 +297,7 @@ CommandObjectExpression::ExecuteRawCommandString
{
m_exe_ctx = m_interpreter.GetDebugger().GetExecutionContext();
m_options.ResetOptionValues();
m_options.Reset();
const char * expr = NULL;

View File

@ -77,7 +77,6 @@ CommandObjectFile::CommandOptions::SetOptionValue (int option_idx, const char *o
void
CommandObjectFile::CommandOptions::ResetOptionValues ()
{
Options::ResetOptionValues();
m_arch.Clear();
}

View File

@ -135,7 +135,6 @@ public:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
relative_frame_offset = INT32_MIN;
}
@ -352,8 +351,6 @@ public:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
use_objc = false;
use_regex = false;
show_args = true;

View File

@ -763,7 +763,6 @@ public:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
m_sort_order = eSortOrderNone;
}
@ -1167,7 +1166,6 @@ public:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
m_format_array.clear();
}
@ -1429,7 +1427,6 @@ public:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
m_type = eLookupTypeInvalid;
m_str.clear();
m_file.Clear();

View File

@ -208,7 +208,6 @@ public:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
log_file.clear();
log_options = 0;
}

View File

@ -164,7 +164,6 @@ public:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
m_format = eFormatBytesWithASCII;
m_byte_size = 0;
m_count = 0;
@ -493,7 +492,6 @@ public:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
m_format = eFormatBytes;
m_byte_size = 1;
m_infile.Clear();

View File

@ -68,7 +68,7 @@ public:
}
else
{
result.AppendError ("command not implemented\n");
result.AppendError ("platform create takes a platform name as an argument\n");
result.SetStatus (eReturnStatusFailed);
}
return result.Succeeded();
@ -409,6 +409,308 @@ public:
};
//----------------------------------------------------------------------
// "platform process list"
//----------------------------------------------------------------------
class CommandObjectPlatformProcessList : public CommandObject
{
public:
CommandObjectPlatformProcessList (CommandInterpreter &interpreter) :
CommandObject (interpreter,
"platform process list",
"List processes on a remote platform by name, pid, or many other matching attributes.",
"platform process list",
0)
{
}
virtual
~CommandObjectPlatformProcessList ()
{
}
virtual bool
Execute (Args& args, CommandReturnObject &result)
{
PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
if (platform_sp)
{
Error error;
if (args.GetArgumentCount() == 0)
{
if (platform_sp)
{
lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID();
if (pid != LLDB_INVALID_PROCESS_ID)
{
ProcessInfo proc_info;
if (platform_sp->GetProcessInfo (pid, proc_info))
{
proc_info.Dump (result.GetOutputStream(), platform_sp.get());
result.SetStatus (eReturnStatusSuccessFinishResult);
}
else
{
result.AppendErrorWithFormat ("no process found with pid = %i\n", pid);
result.SetStatus (eReturnStatusFailed);
}
}
else
{
ProcessInfoList proc_infos;
const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos);
if (matches == 0)
{
const char *match_desc = NULL;
const char *match_name = m_options.match_info.GetProcessInfo().GetName();
if (match_name && match_name[0])
{
switch (m_options.match_info.GetNameMatchType())
{
case eNameMatchIgnore: break;
case eNameMatchEquals: match_desc = "match"; break;
case eNameMatchContains: match_desc = "contains"; break;
case eNameMatchStartsWith: match_desc = "starts with"; break;
case eNameMatchEndsWith: match_desc = "end with"; break;
case eNameMatchRegularExpression: match_desc = "match the regular expression"; break;
}
}
if (match_desc)
result.AppendErrorWithFormat ("no processes were found that %s \"%s\" on the \"%s\" platform\n",
match_desc,
match_name,
platform_sp->GetShortPluginName());
else
result.AppendErrorWithFormat ("no processes were found on the \"%s\" platform\n", platform_sp->GetShortPluginName());
result.SetStatus (eReturnStatusFailed);
}
else
{
Stream &ostrm = result.GetOutputStream();
ProcessInfo::DumpTableHeader (ostrm, platform_sp.get());
for (uint32_t i=0; i<matches; ++i)
{
proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get());
}
}
}
}
}
else
{
result.AppendError ("invalid args: process list takes only options\n");
result.SetStatus (eReturnStatusFailed);
}
}
else
{
result.AppendError ("no platform is selected\n");
result.SetStatus (eReturnStatusFailed);
}
return result.Succeeded();
}
virtual Options *
GetOptions ()
{
return &m_options;
}
protected:
class CommandOptions : public Options
{
public:
CommandOptions () :
match_info ()
{
}
virtual
~CommandOptions ()
{
}
virtual Error
SetOptionValue (int option_idx, const char *option_arg)
{
Error error;
char short_option = (char) m_getopt_table[option_idx].val;
bool success = false;
switch (short_option)
{
case 'p':
match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
if (!success)
error.SetErrorStringWithFormat("invalid process ID string: '%s'", option_arg);
break;
case 'P':
match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
if (!success)
error.SetErrorStringWithFormat("invalid parent process ID string: '%s'", option_arg);
break;
case 'u':
match_info.GetProcessInfo().SetRealUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
if (!success)
error.SetErrorStringWithFormat("invalid user ID string: '%s'", option_arg);
break;
case 'U':
match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
if (!success)
error.SetErrorStringWithFormat("invalid effective user ID string: '%s'", option_arg);
break;
case 'g':
match_info.GetProcessInfo().SetRealGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
if (!success)
error.SetErrorStringWithFormat("invalid group ID string: '%s'", option_arg);
break;
case 'G':
match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
if (!success)
error.SetErrorStringWithFormat("invalid effective group ID string: '%s'", option_arg);
break;
case 'a':
match_info.GetProcessInfo().GetArchitecture().SetTriple (option_arg);
break;
case 'n':
match_info.GetProcessInfo().SetName (option_arg);
if (match_info.GetNameMatchType() == eNameMatchIgnore)
match_info.SetNameMatchType (eNameMatchEquals);
break;
case 'e':
match_info.SetNameMatchType (eNameMatchEndsWith);
break;
case 's':
match_info.SetNameMatchType (eNameMatchStartsWith);
break;
case 'c':
match_info.SetNameMatchType (eNameMatchContains);
break;
case 'r':
match_info.SetNameMatchType (eNameMatchRegularExpression);
break;
default:
error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
break;
}
return error;
}
void
ResetOptionValues ()
{
match_info.Clear();
}
const OptionDefinition*
GetDefinitions ()
{
return g_option_table;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table[];
// Instance variables to hold the values for command options.
ProcessInfoMatch match_info;
};
CommandOptions m_options;
};
OptionDefinition
CommandObjectPlatformProcessList::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "pid" , 'p', required_argument, NULL, 0, eArgTypePid , "List the process info for a specific process ID." },
{ LLDB_OPT_SET_2|
LLDB_OPT_SET_3|
LLDB_OPT_SET_4|
LLDB_OPT_SET_5, true , "name" , 'n', required_argument, NULL, 0, eArgTypeProcessName , "Find processes that match the supplied name." },
{ LLDB_OPT_SET_2, false, "ends-with" , 'e', no_argument , NULL, 0, eArgTypeNone , "Process names must end with the name supplied with the --name option." },
{ LLDB_OPT_SET_3, false, "starts-with" , 's', no_argument , NULL, 0, eArgTypeNone , "Process names must start with the name supplied with the --name option." },
{ LLDB_OPT_SET_4, false, "contains" , 'c', no_argument , NULL, 0, eArgTypeNone , "Process names must contain the name supplied with the --name option." },
{ LLDB_OPT_SET_5, false, "regex" , 'r', no_argument , NULL, 0, eArgTypeNone , "Process names must match name supplied with the --name option as a regular expression." },
{ LLDB_OPT_SET_2|
LLDB_OPT_SET_3|
LLDB_OPT_SET_4|
LLDB_OPT_SET_5|
LLDB_OPT_SET_6, false, "parent" , 'P', required_argument, NULL, 0, eArgTypePid , "Find processes that have a matching parent process ID." },
{ LLDB_OPT_SET_2|
LLDB_OPT_SET_3|
LLDB_OPT_SET_4|
LLDB_OPT_SET_5|
LLDB_OPT_SET_6, false, "uid" , 'u', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching user ID." },
{ LLDB_OPT_SET_2|
LLDB_OPT_SET_3|
LLDB_OPT_SET_4|
LLDB_OPT_SET_5|
LLDB_OPT_SET_6, false, "euid" , 'U', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective user ID." },
{ LLDB_OPT_SET_2|
LLDB_OPT_SET_3|
LLDB_OPT_SET_4|
LLDB_OPT_SET_5|
LLDB_OPT_SET_6, false, "gid" , 'g', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching group ID." },
{ LLDB_OPT_SET_2|
LLDB_OPT_SET_3|
LLDB_OPT_SET_4|
LLDB_OPT_SET_5|
LLDB_OPT_SET_6, false, "egid" , 'G', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective group ID." },
{ LLDB_OPT_SET_2|
LLDB_OPT_SET_3|
LLDB_OPT_SET_4|
LLDB_OPT_SET_5|
LLDB_OPT_SET_6, false, "arch" , 'a', required_argument, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." },
{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL }
};
class CommandObjectPlatformProcess : public CommandObjectMultiword
{
public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
CommandObjectPlatformProcess (CommandInterpreter &interpreter) :
CommandObjectMultiword (interpreter,
"platform process",
"A set of commands to query, launch and attach to platform processes",
"platform process [attach|launch|list] ...")
{
// LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter)));
// LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter)));
LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter)));
}
virtual
~CommandObjectPlatformProcess ()
{
}
private:
//------------------------------------------------------------------
// For CommandObjectPlatform only
//------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess);
};
//----------------------------------------------------------------------
// CommandObjectPlatform constructor
@ -425,6 +727,7 @@ CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) :
LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter)));
LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter)));
LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter)));
LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter)));
}

View File

@ -82,7 +82,6 @@ public:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
stop_at_entry = false;
in_new_tty = false;
tty_name.clear();
@ -483,7 +482,6 @@ public:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
pid = LLDB_INVALID_PROCESS_ID;
name.clear();
waitfor = false;
@ -527,7 +525,13 @@ public:
if (platform_sp)
{
ProcessInfoList process_infos;
platform_sp->FindProcessesByName (partial_name, partial_name ? eNameMatchStartsWith : eNameMatchIgnore, process_infos);
ProcessInfoMatch match_info;
if (partial_name)
{
match_info.GetProcessInfo().SetName(partial_name);
match_info.SetNameMatchType(eNameMatchStartsWith);
}
platform_sp->FindProcesses (match_info, process_infos);
const uint32_t num_matches = process_infos.GetSize();
if (num_matches > 0)
{
@ -706,7 +710,8 @@ public:
PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform ());
if (platform_sp)
{
platform_sp->FindProcessesByName (wait_name, eNameMatchEquals, process_infos);
ProcessInfoMatch match_info (wait_name, eNameMatchEquals);
platform_sp->FindProcesses (match_info, process_infos);
}
if (process_infos.GetSize() > 1)
{
@ -1011,7 +1016,6 @@ public:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
plugin_name.clear();
}
@ -1601,7 +1605,6 @@ public:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
stop.clear();
notify.clear();
pass.clear();

View File

@ -58,6 +58,12 @@ public:
{
}
Options *
GetOptions ()
{
return &m_options;
}
virtual bool
Execute
(
@ -143,8 +149,77 @@ public:
}
return result.Succeeded();
}
protected:
class CommandOptions : public Options
{
public:
CommandOptions () :
Options()
{
ResetOptionValues();
}
virtual
~CommandOptions ()
{
}
virtual Error
SetOptionValue (int option_idx, const char *option_arg)
{
Error error;
char short_option = (char) m_getopt_table[option_idx].val;
switch (short_option)
{
case 'f':
error = Args::StringToFormat (option_arg, m_format);
break;
default:
error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option);
break;
}
return error;
}
void
ResetOptionValues ()
{
m_format = eFormatBytes;
}
const OptionDefinition*
GetDefinitions ()
{
return g_option_table;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table[];
// Instance variables to hold the values for command options.
lldb::Format m_format;
};
CommandOptions m_options;
};
OptionDefinition
CommandObjectRegisterRead::CommandOptions::g_option_table[] =
{
//{ LLDB_OPT_SET_ALL, false, "language", 'l', required_argument, NULL, 0, "[c|c++|objc|objc++]", "Sets the language to use when parsing the expression."},
//{ LLDB_OPT_SET_1, false, "format", 'f', required_argument, NULL, 0, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]", "Specify the format that the expression output should use."},
{ LLDB_OPT_SET_1, false, "format", 'f', required_argument, NULL, 0, eArgTypeExprFormat, "Specify the format that the expression output should use."},
{ LLDB_OPT_SET_2, false, "object-description", 'o', no_argument, NULL, 0, eArgTypeNone, "Print the object description of the value resulting from the expression."},
{ LLDB_OPT_SET_ALL, false, "unwind-on-error", 'u', required_argument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, breakpoint hit or signal."},
{ LLDB_OPT_SET_ALL, false, "debug", 'g', no_argument, NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."},
{ LLDB_OPT_SET_ALL, false, "use-ir", 'i', no_argument, NULL, 0, eArgTypeNone, "[Temporary] Instructs the expression evaluator to use IR instead of ASTs."},
{ 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
};
//----------------------------------------------------------------------
// "register write"

View File

@ -287,8 +287,6 @@ CommandObjectSettingsSet::CommandOptions::SetOptionValue (int option_idx, const
void
CommandObjectSettingsSet::CommandOptions::ResetOptionValues ()
{
Options::ResetOptionValues ();
m_override = true;
m_reset = false;
}

View File

@ -74,8 +74,6 @@ class CommandObjectSourceInfo : public CommandObject
void
ResetOptionValues ()
{
Options::ResetOptionValues();
file_spec.Clear();
file_name.clear();
start_line = 0;
@ -200,8 +198,6 @@ class CommandObjectSourceList : public CommandObject
void
ResetOptionValues ()
{
Options::ResetOptionValues();
file_spec.Clear();
file_name.clear();
symbol_name.clear();

View File

@ -300,7 +300,6 @@ public:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
m_count = -1;
m_start = 0;
}
@ -545,7 +544,6 @@ public:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
m_avoid_no_debug = true;
m_run_mode = eOnlyDuringStepping;
m_avoid_regexp.clear();
@ -1044,7 +1042,6 @@ public:
void
ResetOptionValues ()
{
Options::ResetOptionValues();
m_thread_idx = LLDB_INVALID_THREAD_ID;
m_frame_idx = 0;
m_stop_others = false;

View File

@ -261,7 +261,6 @@ Disassembler::Disassemble
debugger,
arch,
exe_ctx,
disasm_range.GetBaseAddress(),
num_instructions,
num_mixed_context_lines,
show_bytes,
@ -302,7 +301,6 @@ Disassembler::Disassemble
debugger,
arch,
exe_ctx,
addr,
num_instructions,
num_mixed_context_lines,
show_bytes,
@ -320,7 +318,6 @@ Disassembler::PrintInstructions
Debugger &debugger,
const ArchSpec &arch,
const ExecutionContext &exe_ctx,
const Address &start_addr,
uint32_t num_instructions,
uint32_t num_mixed_context_lines,
bool show_bytes,
@ -339,41 +336,53 @@ Disassembler::PrintInstructions
SymbolContext sc;
SymbolContext prev_sc;
AddressRange sc_range;
Address addr (start_addr);
if (num_mixed_context_lines)
strm.IndentMore ();
// We extract the section to make sure we don't transition out
// of the current section when disassembling
const Section *addr_section = addr.GetSection();
Module *range_module = addr.GetModule();
Address *pc_addr_ptr = NULL;
if (exe_ctx.frame)
pc_addr_ptr = &exe_ctx.frame->GetFrameCodeAddress();
for (size_t i=0; i<num_instructions_found; ++i)
{
Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
if (inst)
{
addr_t file_addr = addr.GetFileAddress();
if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false)
{
if (range_module)
range_module->ResolveFileAddress (file_addr, addr);
else if (exe_ctx.target)
exe_ctx.target->GetImages().ResolveFileAddress (file_addr, addr);
addr_section = addr.GetSection();
}
const Address &addr = inst->GetAddress();
const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
prev_sc = sc;
if (addr_section)
Module *module = addr.GetModule();
if (module)
{
Module *module = addr_section->GetModule();
uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
if (resolved_mask)
{
if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol))
if (num_mixed_context_lines)
{
if (!sc_range.ContainsFileAddress (addr))
{
sc.GetAddressRange (eSymbolContextEverything, sc_range);
if (sc != prev_sc)
{
if (offset != 0)
strm.EOL();
sc.DumpStopContext(&strm, exe_ctx.process, addr, false, true, false);
strm.EOL();
if (sc.comp_unit && sc.line_entry.IsValid())
{
debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
sc.line_entry.line,
num_mixed_context_lines,
num_mixed_context_lines,
num_mixed_context_lines ? "->" : "",
&strm);
}
}
}
}
else if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol))
{
if (prev_sc.function || prev_sc.symbol)
strm.EOL();
@ -386,54 +395,28 @@ Disassembler::PrintInstructions
strm << '`' << sc.symbol->GetMangled().GetName();
strm << ":\n";
}
if (num_mixed_context_lines && !sc_range.ContainsFileAddress (addr))
{
sc.GetAddressRange (eSymbolContextEverything, sc_range);
if (sc != prev_sc)
{
if (offset != 0)
strm.EOL();
sc.DumpStopContext(&strm, exe_ctx.process, addr, false, true, false);
strm.EOL();
if (sc.comp_unit && sc.line_entry.IsValid())
{
debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
sc.line_entry.line,
num_mixed_context_lines,
num_mixed_context_lines,
num_mixed_context_lines ? "->" : "",
&strm);
}
}
}
}
else
{
sc.Clear();
}
}
if (num_mixed_context_lines)
strm.IndentMore ();
strm.Indent();
inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, raw);
strm.EOL();
addr.Slide(inst->GetOpcode().GetByteSize());
if (num_mixed_context_lines)
strm.IndentLess ();
if (pc_addr_ptr)
{
if (inst_is_at_pc)
strm.PutCString("-> ");
else
strm.PutCString(" ");
}
inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, raw);
strm.EOL();
}
else
{
break;
}
}
if (num_mixed_context_lines)
strm.IndentLess ();
return true;
}

View File

@ -26,6 +26,7 @@ Module::Module(const FileSpec& file_spec, const ArchSpec& arch, const ConstStrin
m_arch (arch),
m_uuid (),
m_file (file_spec),
m_platform_file(),
m_object_name (),
m_objfile_ap (),
m_symfile_ap (),
@ -448,12 +449,6 @@ Module::GetSymbolVendor (bool can_create)
return m_symfile_ap.get();
}
const FileSpec &
Module::GetFileSpec () const
{
return m_file;
}
void
Module::SetFileSpecAndObjectName (const FileSpec &file, const ConstString &object_name)
{

View File

@ -216,14 +216,20 @@ public:
ModuleMatches (const FileSpec *file_spec_ptr,
const ArchSpec *arch_ptr,
const lldb_private::UUID *uuid_ptr,
const ConstString *object_name) :
const ConstString *object_name,
bool file_spec_is_platform) :
m_file_spec_ptr (file_spec_ptr),
m_arch_ptr (arch_ptr),
m_uuid_ptr (uuid_ptr),
m_object_name (object_name)
m_object_name (object_name),
m_file_spec_compare_basename_only (false),
m_file_spec_is_platform (file_spec_is_platform)
{
if (file_spec_ptr)
m_file_spec_compare_basename_only = file_spec_ptr->GetDirectory();
}
//--------------------------------------------------------------
/// Unary predicate function object callback.
//--------------------------------------------------------------
@ -232,8 +238,21 @@ public:
{
if (m_file_spec_ptr)
{
if (!FileSpec::Equal (*m_file_spec_ptr, module_sp->GetFileSpec(), m_file_spec_ptr->GetDirectory()))
return false;
if (m_file_spec_is_platform)
{
if (!FileSpec::Equal (*m_file_spec_ptr,
module_sp->GetPlatformFileSpec(),
m_file_spec_compare_basename_only))
return false;
}
else
{
if (!FileSpec::Equal (*m_file_spec_ptr,
module_sp->GetFileSpec(),
m_file_spec_compare_basename_only))
return false;
}
}
if (m_arch_ptr && m_arch_ptr->IsValid())
@ -264,6 +283,8 @@ private:
const ArchSpec * m_arch_ptr;
const lldb_private::UUID * m_uuid_ptr;
const ConstString * m_object_name;
bool m_file_spec_compare_basename_only;
bool m_file_spec_is_platform;
};
size_t
@ -277,7 +298,7 @@ ModuleList::FindModules
) const
{
size_t existing_matches = matching_module_list.GetSize();
ModuleMatches matcher (file_spec_ptr, arch_ptr, uuid_ptr, object_name);
ModuleMatches matcher (file_spec_ptr, arch_ptr, uuid_ptr, object_name, false);
Mutex::Locker locker(m_modules_mutex);
collection::const_iterator end = m_modules.end();
@ -316,6 +337,28 @@ ModuleList::FindModule (const Module *module_ptr)
}
ModuleSP
ModuleList::FindModule (const UUID &uuid)
{
ModuleSP module_sp;
if (uuid.IsValid())
{
Mutex::Locker locker(m_modules_mutex);
collection::const_iterator pos, end = m_modules.end();
for (pos = m_modules.begin(); pos != end; ++pos)
{
if ((*pos)->GetUUID() == uuid)
{
module_sp = (*pos);
break;
}
}
}
return module_sp;
}
uint32_t
ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types)
@ -340,10 +383,16 @@ ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool ap
ModuleSP
ModuleList::FindFirstModuleForFileSpec (const FileSpec &file_spec, const ConstString *object_name)
ModuleList::FindFirstModuleForFileSpec (const FileSpec &file_spec,
const ArchSpec *arch_ptr,
const ConstString *object_name)
{
ModuleSP module_sp;
ModuleMatches matcher (&file_spec, NULL, NULL, NULL);
ModuleMatches matcher (&file_spec,
arch_ptr,
NULL,
object_name,
false);
// Scope for "locker"
{
@ -359,6 +408,32 @@ ModuleList::FindFirstModuleForFileSpec (const FileSpec &file_spec, const ConstSt
}
ModuleSP
ModuleList::FindFirstModuleForPlatormFileSpec (const FileSpec &file_spec,
const ArchSpec *arch_ptr,
const ConstString *object_name)
{
ModuleSP module_sp;
ModuleMatches matcher (&file_spec,
arch_ptr,
NULL,
object_name,
true);
// Scope for "locker"
{
Mutex::Locker locker(m_modules_mutex);
collection::const_iterator end = m_modules.end();
collection::const_iterator pos = m_modules.begin();
pos = std::find_if (pos, end, matcher);
if (pos != end)
module_sp = (*pos);
}
return module_sp;
}
size_t
ModuleList::GetSize() const

View File

@ -119,7 +119,7 @@ SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile
break;
}
s->Printf("%4u %2.2s\t", curr_line, curr_line == line ? current_line_cstr : "");
s->Printf("%2.2s %-4u\t", curr_line == line ? current_line_cstr : "", curr_line);
if (m_last_file_sp->DisplaySourceLines (curr_line, 0, 0, s) == 0)
{
m_last_file_line = UINT32_MAX;

View File

@ -24,7 +24,11 @@
#include <dlfcn.h>
#include <errno.h>
#include <grp.h>
#include <netdb.h>
#include <pwd.h>
#include <sys/types.h>
#if defined (__APPLE__)
@ -33,6 +37,7 @@
#include <mach-o/dyld.h>
#include <sys/sysctl.h>
#elif defined (__linux__)
#include <sys/wait.h>
@ -1055,6 +1060,66 @@ Host::GetHostname (std::string &s)
return false;
}
const char *
Host::GetUserName (uint32_t uid, std::string &user_name)
{
struct passwd user_info;
struct passwd *user_info_ptr = &user_info;
char user_buffer[PATH_MAX];
size_t user_buffer_size = sizeof(user_buffer);
if (::getpwuid_r (uid,
&user_info,
user_buffer,
user_buffer_size,
&user_info_ptr) == 0)
{
if (user_info_ptr)
{
user_name.assign (user_info_ptr->pw_name);
return user_name.c_str();
}
}
user_name.clear();
return NULL;
}
const char *
Host::GetGroupName (uint32_t gid, std::string &group_name)
{
char group_buffer[PATH_MAX];
size_t group_buffer_size = sizeof(group_buffer);
struct group group_info;
struct group *group_info_ptr = &group_info;
// Try the threadsafe version first
if (::getgrgid_r (gid,
&group_info,
group_buffer,
group_buffer_size,
&group_info_ptr) == 0)
{
if (group_info_ptr)
{
group_name.assign (group_info_ptr->gr_name);
return group_name.c_str();
}
}
else
{
// The threadsafe version isn't currently working
// for me on darwin, but the non-threadsafe version
// is, so I am calling it below.
group_info_ptr = ::getgrgid (gid);
if (group_info_ptr)
{
group_name.assign (group_info_ptr->gr_name);
return group_name.c_str();
}
}
group_name.clear();
return NULL;
}
#if !defined (__APPLE__) // see macosx/Host.mm
bool
@ -1072,7 +1137,7 @@ Host::GetOSKernelDescription (std::string &s)
}
uint32_t
Host::FindProcessesByName (const char *name, NameMatchType name_match_type, ProcessInfoList &process_infos)
Host::FindProcesses (const ProcessInfoMatch &match_info, ProcessInfoList &process_infos)
{
process_infos.Clear();
return process_infos.GetSize();

View File

@ -912,8 +912,7 @@ Host::GetOSVersion
}
static bool
GetMacOSXProcessName (NameMatchType name_match_type,
const char *name_match,
GetMacOSXProcessName (const ProcessInfoMatch *match_info_ptr,
ProcessInfo &process_info)
{
if (process_info.ProcessIDIsValid())
@ -923,7 +922,9 @@ GetMacOSXProcessName (NameMatchType name_match_type,
if (name_len == 0)
return false;
if (NameMatches(process_name, name_match_type, name_match))
if (match_info_ptr == NULL || NameMatches(process_name,
match_info_ptr->GetNameMatchType(),
match_info_ptr->GetProcessInfo().GetName()))
{
process_info.SetName (process_name);
return true;
@ -966,56 +967,6 @@ GetMacOSXProcessCPUType (ProcessInfo &process_info)
return false;
}
// TODO: move this into the platform
static bool
GetGroupName (uint32_t gid, std::string &group_name)
{
char group_buffer[PATH_MAX];
size_t group_buffer_size = sizeof(group_buffer);
struct group group_info;
struct group *group_info_ptr = &group_info;
// User the real user ID here, not the effective user ID
if (::getgrgid_r (gid,
&group_info,
group_buffer,
group_buffer_size,
&group_info_ptr) == 0)
{
if (group_info_ptr)
{
group_name.assign (group_info_ptr->gr_name);
return true;
}
}
group_name.clear();
return false;
}
// TODO: move this into the platform
static bool
GetUserName (uint32_t uid, std::string &user_name)
{
struct passwd user_info;
struct passwd *user_info_ptr = &user_info;
char user_buffer[PATH_MAX];
size_t user_buffer_size = sizeof(user_buffer);
if (::getpwuid_r (uid,
&user_info,
user_buffer,
user_buffer_size,
&user_info_ptr) == 0)
{
if (user_info_ptr)
{
user_name.assign (user_info_ptr->pw_name);
return true;
}
}
user_name.clear();
return false;
}
static bool
GetMacOSXProcessUserAndGroup (ProcessInfo &process_info)
{
@ -1055,7 +1006,7 @@ GetMacOSXProcessUserAndGroup (ProcessInfo &process_info)
uint32_t
Host::FindProcessesByName (const char *name, NameMatchType name_match_type, ProcessInfoList &process_infos)
Host::FindProcesses (const ProcessInfoMatch &match_info, ProcessInfoList &process_infos)
{
int num_pids;
int size_of_pids;
@ -1091,11 +1042,12 @@ Host::FindProcessesByName (const char *name, NameMatchType name_match_type, Proc
ProcessInfo process_info;
process_info.SetProcessID (bsd_info.pbi_pid);
if (GetMacOSXProcessName (name_match_type, name, process_info))
if (GetMacOSXProcessName (&match_info, process_info))
{
GetMacOSXProcessCPUType (process_info);
GetMacOSXProcessUserAndGroup (process_info);
process_infos.Append (process_info);
if (match_info.Matches (process_info))
process_infos.Append (process_info);
}
}
return process_infos.GetSize();
@ -1105,7 +1057,7 @@ bool
Host::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
{
process_info.SetProcessID(pid);
if (GetMacOSXProcessName (eNameMatchIgnore, NULL, process_info))
if (GetMacOSXProcessName (NULL, process_info))
{
GetMacOSXProcessCPUType (process_info);
GetMacOSXProcessUserAndGroup (process_info);

View File

@ -177,7 +177,7 @@ CommandObject::ParseOptions
if (options != NULL)
{
Error error;
options->ResetOptionValues();
options->Reset();
// ParseOptions calls getopt_long, which always skips the zero'th item in the array and starts at position 1,
// so we need to push a dummy value into position zero.

View File

@ -39,11 +39,12 @@ Options::~Options ()
{
}
void
Options::ResetOptionValues ()
Options::Reset ()
{
m_seen_options.clear();
// Let the subclass reset its option values
ResetOptionValues ();
}
void

View File

@ -34,7 +34,6 @@
using namespace lldb;
using namespace lldb_private;
using namespace llvm::MachO;
/// FIXME - The ObjC Runtime trampoline handler doesn't really belong here.
/// I am putting it here so I can invoke it in the Trampoline code here, but
@ -42,16 +41,37 @@ using namespace llvm::MachO;
DynamicLoaderMacOSXDYLD::DYLDImageInfo *
DynamicLoaderMacOSXDYLD::GetImageInfo (const FileSpec &file_spec, const lldb_private::UUID &uuid)
DynamicLoaderMacOSXDYLD::GetImageInfo (Module *module)
{
const UUID &module_uuid = module->GetUUID();
DYLDImageInfo::collection::iterator pos, end = m_dyld_image_infos.end();
// First try just by UUID as it is the safest.
if (module_uuid.IsValid())
{
for (pos = m_dyld_image_infos.begin(); pos != end; ++pos)
{
if (pos->uuid == module_uuid)
return &(*pos);
}
if (m_dyld.uuid == module_uuid)
return &m_dyld;
}
// Next try by platform path only for things that don't have a valid UUID
// since if a file has a valid UUID in real life it should also in the
// dyld info. This is the next safest because the paths in the dyld info
// are platform paths, not local paths. For local debugging platform == local
// paths.
const FileSpec &platform_file_spec = module->GetPlatformFileSpec();
for (pos = m_dyld_image_infos.begin(); pos != end; ++pos)
{
if (pos->uuid == uuid && pos->file_spec == file_spec)
if (pos->file_spec == platform_file_spec && pos->uuid.IsValid() == false)
return &(*pos);
}
if (m_dyld.uuid == uuid && m_dyld.file_spec == file_spec)
if (m_dyld.file_spec == platform_file_spec && m_dyld.uuid.IsValid() == false)
return &m_dyld;
return NULL;
@ -205,6 +225,35 @@ DynamicLoaderMacOSXDYLD::LocateDYLD()
return false;
}
ModuleSP
DynamicLoaderMacOSXDYLD::FindTargetModuleForDYLDImageInfo (const DYLDImageInfo &image_info, bool can_create, bool *did_create_ptr)
{
if (did_create_ptr)
*did_create_ptr = false;
ModuleSP module_sp;
ModuleList &target_images = m_process->GetTarget().GetImages();
const bool image_info_uuid_is_valid = image_info.uuid.IsValid();
if (image_info_uuid_is_valid)
module_sp = target_images.FindModule(image_info.uuid);
if (!module_sp)
{
ArchSpec arch(image_info.GetArchitecture ());
module_sp = target_images.FindFirstModuleForFileSpec (image_info.file_spec, &arch, NULL);
if (can_create && !module_sp)
{
module_sp = m_process->GetTarget().GetSharedModule (image_info.file_spec,
arch,
image_info_uuid_is_valid ? &image_info.uuid : NULL);
if (did_create_ptr)
*did_create_ptr = module_sp;
}
}
return module_sp;
}
//----------------------------------------------------------------------
// Assume that dyld is in memory at ADDR and try to parse it's load
// commands
@ -215,7 +264,7 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::
DataExtractor data; // Load command data
if (ReadMachHeader (addr, &m_dyld.header, &data))
{
if (m_dyld.header.filetype == HeaderFileTypeDynamicLinkEditor)
if (m_dyld.header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor)
{
m_dyld.address = addr;
ModuleSP dyld_module_sp;
@ -223,17 +272,10 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::
{
if (m_dyld.file_spec)
{
ArchSpec dyld_arch(eArchTypeMachO, m_dyld.header.cputype, m_dyld.header.cpusubtype);
dyld_module_sp = m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (m_dyld.file_spec);
dyld_module_sp = FindTargetModuleForDYLDImageInfo (m_dyld, true, NULL);
if (dyld_module_sp.get() == NULL || dyld_module_sp->GetArchitecture() != dyld_arch)
{
dyld_module_sp = m_process->GetTarget().GetSharedModule (m_dyld.file_spec,
dyld_arch,
&m_dyld.uuid);
}
UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
if (dyld_module_sp)
UpdateImageLoadAddress (dyld_module_sp.get(), m_dyld);
}
}
@ -307,7 +349,7 @@ DynamicLoaderMacOSXDYLD::UpdateCommPageLoadAddress(Module *module)
// updated INFO that is passed in.
//----------------------------------------------------------------------
bool
DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, struct DYLDImageInfo& info)
DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, DYLDImageInfo& info)
{
bool changed = false;
if (module)
@ -379,7 +421,7 @@ DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, struct DYLDImag
// updated INFO that is passed in.
//----------------------------------------------------------------------
bool
DynamicLoaderMacOSXDYLD::UnloadImageLoadAddress (Module *module, struct DYLDImageInfo& info)
DynamicLoaderMacOSXDYLD::UnloadImageLoadAddress (Module *module, DYLDImageInfo& info)
{
bool changed = false;
if (module)
@ -551,6 +593,8 @@ uint32_t
DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
{
LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
ModuleList& target_images = m_process->GetTarget().GetImages();
if (ReadAllImageInfosStructure ())
{
Mutex::Locker locker(m_mutex);
@ -627,13 +671,12 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
// we might have shared libraries that got loaded from
// elsewhere due to DYLD_FRAMEWORK_PATH, or DYLD_LIBRARY_PATH
// environment variables...
ModuleList& images = m_process->GetTarget().GetImages();
const size_t num_images = images.GetSize();
const size_t num_images = target_images.GetSize();
for (idx = 0; idx < num_images; ++idx)
{
ModuleSP module_sp (images.GetModuleAtIndex (idx));
ModuleSP module_sp (target_images.GetModuleAtIndex (idx));
if (GetImageInfo (module_sp->GetFileSpec(), module_sp->GetUUID()) == NULL)
if (GetImageInfo (module_sp.get()) == NULL)
unloaded_module_list.AppendIfNeeded (module_sp);
}
}
@ -658,7 +701,7 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
{
if (log)
old_dyld_all_image_infos[old_idx].PutToLog (log.get());
ModuleSP unload_image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (old_dyld_all_image_infos[old_idx].file_spec));
ModuleSP unload_image_module_sp (FindTargetModuleForDYLDImageInfo (old_dyld_all_image_infos[old_idx], false, NULL));
if (unload_image_module_sp.get())
{
if (UnloadImageLoadAddress (unload_image_module_sp.get(), old_dyld_all_image_infos[old_idx]))
@ -696,18 +739,11 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
ModuleList loaded_module_list;
for (uint32_t idx = 0; idx<num_dylibs; ++idx)
{
ArchSpec arch_spec(eArchTypeMachO, m_dyld_image_infos[idx].header.cputype, m_dyld_image_infos[idx].header.cpusubtype);
ModuleSP image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (m_dyld_image_infos[idx].file_spec));
if (image_module_sp.get() == NULL || image_module_sp->GetArchitecture() != arch_spec)
{
image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec,
arch_spec,
&m_dyld_image_infos[idx].uuid);
}
ModuleSP image_module_sp (FindTargetModuleForDYLDImageInfo (m_dyld_image_infos[idx], true, NULL));
if (image_module_sp)
{
if (m_dyld_image_infos[idx].header.filetype == HeaderFileTypeDynamicLinkEditor)
if (m_dyld_image_infos[idx].header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor)
image_module_sp->SetIsDynamicLinkEditor (true);
ObjectFile *objfile = image_module_sp->GetObjectFile ();
@ -720,17 +756,19 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get();
if (commpage_section)
{
FileSpec objfile_file_spec(objfile->GetFileSpec());
ModuleSP commpage_image_module_sp(m_process->GetTarget().GetImages().FindFirstModuleForFileSpec (objfile_file_spec, &commpage_dbstr));
if (commpage_image_module_sp.get() == NULL)
const FileSpec objfile_file_spec = objfile->GetFileSpec();
ArchSpec arch (m_dyld_image_infos[idx].GetArchitecture ());
ModuleSP commpage_image_module_sp(target_images.FindFirstModuleForFileSpec (objfile_file_spec, &arch, &commpage_dbstr));
if (!commpage_image_module_sp)
{
commpage_image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec,
arch_spec,
arch,
&m_dyld_image_infos[idx].uuid,
&commpage_dbstr,
objfile->GetOffset() + commpage_section->GetOffset());
UpdateCommPageLoadAddress(commpage_image_module_sp.get());
}
if (commpage_image_module_sp)
UpdateCommPageLoadAddress (commpage_image_module_sp.get());
}
}
}
@ -781,15 +819,15 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
// Returns true if we succeed, false if we fail for any reason.
//----------------------------------------------------------------------
bool
DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, mach_header *header, DataExtractor *load_command_data)
DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, llvm::MachO::mach_header *header, DataExtractor *load_command_data)
{
DataBufferHeap header_bytes(sizeof(mach_header), 0);
DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
Error error;
size_t bytes_read = m_process->ReadMemory (addr,
header_bytes.GetBytes(),
header_bytes.GetByteSize(),
error);
if (bytes_read == sizeof(mach_header))
if (bytes_read == sizeof(llvm::MachO::mach_header))
{
uint32_t offset = 0;
::memset (header, 0, sizeof(header));
@ -804,13 +842,13 @@ DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, mach_header *header,
case llvm::MachO::HeaderMagic32:
case llvm::MachO::HeaderMagic32Swapped:
data.SetAddressByteSize(4);
load_cmd_addr += sizeof(mach_header);
load_cmd_addr += sizeof(llvm::MachO::mach_header);
break;
case llvm::MachO::HeaderMagic64:
case llvm::MachO::HeaderMagic64Swapped:
data.SetAddressByteSize(8);
load_cmd_addr += sizeof(mach_header_64);
load_cmd_addr += sizeof(llvm::MachO::mach_header_64);
break;
default:
@ -818,7 +856,7 @@ DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, mach_header *header,
}
// Read the rest of dyld's mach header
if (data.GetU32(&offset, &header->cputype, (sizeof(mach_header)/sizeof(uint32_t)) - 1))
if (data.GetU32(&offset, &header->cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1))
{
if (load_command_data == NULL)
return true; // We were able to read the mach_header and weren't asked to read the load command bytes
@ -851,7 +889,7 @@ DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, mach_header *header,
// Parse the load commands for an image
//----------------------------------------------------------------------
uint32_t
DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, struct DYLDImageInfo& dylib_info, FileSpec *lc_id_dylinker)
DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, DYLDImageInfo& dylib_info, FileSpec *lc_id_dylinker)
{
uint32_t offset = 0;
uint32_t cmd_idx;
@ -863,15 +901,15 @@ DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, struct DY
// Clear out any load command specific data from DYLIB_INFO since
// we are about to read it.
if (data.ValidOffsetForDataOfSize (offset, sizeof(load_command)))
if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command)))
{
load_command load_cmd;
llvm::MachO::load_command load_cmd;
uint32_t load_cmd_offset = offset;
load_cmd.cmd = data.GetU32 (&offset);
load_cmd.cmdsize = data.GetU32 (&offset);
switch (load_cmd.cmd)
{
case LoadCommandSegment32:
case llvm::MachO::LoadCommandSegment32:
{
segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
segment.addr = data.GetU32 (&offset);
@ -880,7 +918,7 @@ DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, struct DY
}
break;
case LoadCommandSegment64:
case llvm::MachO::LoadCommandSegment64:
{
segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
segment.addr = data.GetU64 (&offset);
@ -889,7 +927,7 @@ DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, struct DY
}
break;
case LoadCommandDynamicLinkerIdent:
case llvm::MachO::LoadCommandDynamicLinkerIdent:
if (lc_id_dylinker)
{
uint32_t name_offset = load_cmd_offset + data.GetU32 (&offset);
@ -898,7 +936,7 @@ DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, struct DY
}
break;
case LoadCommandUUID:
case llvm::MachO::LoadCommandUUID:
dylib_info.uuid.SetBytes(data.GetData (&offset, 16));
break;
@ -920,6 +958,7 @@ void
DynamicLoaderMacOSXDYLD::UpdateAllImageInfosHeaderAndLoadCommands()
{
uint32_t exe_idx = UINT32_MAX;
LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
// Read any UUID values that we can get
for (uint32_t i = 0; i < m_dyld_all_image_infos.dylib_info_count; i++)
{
@ -931,37 +970,35 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfosHeaderAndLoadCommands()
ParseLoadCommands (data, m_dyld_image_infos[i], NULL);
if (m_dyld_image_infos[i].header.filetype == HeaderFileTypeExecutable)
if (m_dyld_image_infos[i].header.filetype == llvm::MachO::HeaderFileTypeExecutable)
exe_idx = i;
if (log)
m_dyld_image_infos[i].PutToLog (log.get());
}
}
if (exe_idx < m_dyld_image_infos.size())
{
bool set_executable = false;
ArchSpec dyld_exe_arch_spec(eArchTypeMachO, m_dyld_image_infos[exe_idx].header.cputype, m_dyld_image_infos[exe_idx].header.cpusubtype);
ModuleSP exe_module_sp(m_process->GetTarget().GetExecutableModule());
if (exe_module_sp.get())
{
if (exe_module_sp->GetFileSpec() != m_dyld_image_infos[exe_idx].file_spec ||
exe_module_sp->GetArchitecture() != dyld_exe_arch_spec)
set_executable = true;
}
else
set_executable = true;
ModuleSP exe_module_sp (FindTargetModuleForDYLDImageInfo (m_dyld_image_infos[exe_idx], false, NULL));
if (set_executable)
if (!exe_module_sp)
{
ArchSpec exe_arch_spec (m_dyld_image_infos[exe_idx].GetArchitecture ());
exe_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[exe_idx].file_spec,
dyld_exe_arch_spec,
exe_arch_spec,
&m_dyld_image_infos[exe_idx].uuid);
if (exe_module_sp.get())
}
if (exe_module_sp)
{
if (exe_module_sp.get() != m_process->GetTarget().GetExecutableModule().get())
{
// If we found the file where it purported to be, then it should
// be safe to load dependent images.
bool get_dependent_images = exe_module_sp->GetFileSpec() == m_dyld_image_infos[exe_idx].file_spec;
m_process->GetTarget().SetExecutableModule (exe_module_sp, get_dependent_images);
// Don't load dependent images since we are in dyld where we will know
// and find out about all images that are loaded
bool get_dependent_images = false;
m_process->GetTarget().SetExecutableModule (exe_module_sp,
get_dependent_images);
}
}
}

View File

@ -278,6 +278,12 @@ protected:
return lldb::endian::InlHostByteOrder();
}
lldb_private::ArchSpec
GetArchitecture () const
{
return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype);
}
const Segment *
FindSegment (const lldb_private::ConstString &name) const;
@ -337,20 +343,24 @@ protected:
uint32_t
ParseLoadCommands (const lldb_private::DataExtractor& data,
struct DYLDImageInfo& dylib_info,
DYLDImageInfo& dylib_info,
lldb_private::FileSpec *lc_id_dylinker);
bool
UpdateImageLoadAddress(lldb_private::Module *module,
struct DYLDImageInfo& info);
DYLDImageInfo& info);
bool
UnloadImageLoadAddress (lldb_private::Module *module,
struct DYLDImageInfo& info);
DYLDImageInfo& info);
lldb::ModuleSP
FindTargetModuleForDYLDImageInfo (const DYLDImageInfo &image_info,
bool can_create,
bool *did_create_ptr);
DYLDImageInfo *
GetImageInfo (const lldb_private::FileSpec &file_spec,
const lldb_private::UUID &uuid);
GetImageInfo (lldb_private::Module *module);
bool
NeedToLocateDYLD () const;

View File

@ -10105,7 +10105,7 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding
// {
// }
// }
// return true;
return true;
}
EmulateInstructionARM::ARMOpcode*

View File

@ -238,8 +238,11 @@ PlatformDarwin::GetRemoteSystemArchitecture ()
const char *
PlatformDarwin::GetRemoteHostname ()
PlatformDarwin::GetHostname ()
{
if (IsHost())
return Platform::GetHostname();
if (m_remote_platform_sp)
return m_remote_platform_sp->GetHostname ();
return NULL;
@ -311,3 +314,67 @@ PlatformDarwin::DisconnectRemote ()
return error;
}
bool
PlatformDarwin::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
{
bool sucess = false;
if (IsHost())
{
sucess = Platform::GetProcessInfo (pid, process_info);
}
else
{
if (m_remote_platform_sp)
sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info);
}
return sucess;
}
uint32_t
PlatformDarwin::FindProcesses (const ProcessInfoMatch &match_info,
ProcessInfoList &process_infos)
{
uint32_t match_count = 0;
if (IsHost())
{
// Let the base class figure out the host details
match_count = Platform::FindProcesses (match_info, process_infos);
}
else
{
// If we are remote, we can only return results if we are connected
if (m_remote_platform_sp)
match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
}
return match_count;
}
const char *
PlatformDarwin::GetUserName (uint32_t uid)
{
// Check the cache in Platform in case we have already looked this uid up
const char *user_name = Platform::GetUserName(uid);
if (user_name)
return user_name;
if (IsRemote() && m_remote_platform_sp)
return m_remote_platform_sp->GetUserName(uid);
return NULL;
}
const char *
PlatformDarwin::GetGroupName (uint32_t gid)
{
const char *group_name = Platform::GetGroupName(gid);
if (group_name)
return group_name;
if (IsRemote() && m_remote_platform_sp)
return m_remote_platform_sp->GetGroupName(gid);
return NULL;
}

View File

@ -16,61 +16,71 @@
// Project includes
#include "lldb/Target/Platform.h"
namespace lldb_private {
class PlatformDarwin : public lldb_private::Platform
{
public:
PlatformDarwin (bool is_host);
class PlatformDarwin : public Platform
{
public:
PlatformDarwin (bool is_host);
virtual
~PlatformDarwin();
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
virtual lldb_private::Error
ResolveExecutable (const lldb_private::FileSpec &exe_file,
const lldb_private::ArchSpec &arch,
lldb::ModuleSP &module_sp);
virtual
~PlatformDarwin();
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
virtual Error
ResolveExecutable (const FileSpec &exe_file,
const ArchSpec &arch,
lldb::ModuleSP &module_sp);
virtual size_t
GetSoftwareBreakpointTrapOpcode (lldb_private::Target &target,
lldb_private::BreakpointSite *bp_site);
virtual size_t
GetSoftwareBreakpointTrapOpcode (Target &target,
BreakpointSite *bp_site);
virtual bool
GetRemoteOSVersion ();
virtual bool
GetRemoteOSVersion ();
virtual bool
GetRemoteOSBuildString (std::string &s);
virtual bool
GetRemoteOSKernelDescription (std::string &s);
virtual bool
GetRemoteOSBuildString (std::string &s);
virtual bool
GetRemoteOSKernelDescription (std::string &s);
// Remote Platform subclasses need to override this function
virtual lldb_private::ArchSpec
GetRemoteSystemArchitecture ();
// Remote Platform subclasses need to override this function
virtual ArchSpec
GetRemoteSystemArchitecture ();
virtual bool
IsConnected () const;
virtual bool
IsConnected () const;
virtual lldb_private::Error
ConnectRemote (lldb_private::Args& args);
virtual Error
ConnectRemote (Args& args);
virtual lldb_private::Error
DisconnectRemote ();
virtual Error
DisconnectRemote ();
virtual const char *
GetHostname ();
virtual const char *
GetRemoteHostname ();
virtual const char *
GetUserName (uint32_t uid);
virtual const char *
GetGroupName (uint32_t gid);
virtual bool
GetProcessInfo (lldb::pid_t pid,
lldb_private::ProcessInfo &proc_info);
virtual uint32_t
FindProcesses (const lldb_private::ProcessInfoMatch &match_info,
lldb_private::ProcessInfoList &process_infos);
protected:
lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote darwin OS
protected:
lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote darwin OS
private:
DISALLOW_COPY_AND_ASSIGN (PlatformDarwin);
private:
DISALLOW_COPY_AND_ASSIGN (PlatformDarwin);
};
} // namespace lldb_private
};
#endif // liblldb_PlatformDarwin_h_

View File

@ -128,39 +128,51 @@ PlatformMacOSX::GetFile (const FileSpec &platform_file,
return Error();
}
uint32_t
PlatformMacOSX::FindProcessesByName (const char *name_match,
NameMatchType name_match_type,
ProcessInfoList &process_infos)
Error
PlatformMacOSX::GetSharedModule (const FileSpec &platform_file,
const ArchSpec &arch,
const UUID *uuid_ptr,
const ConstString *object_name_ptr,
off_t object_offset,
ModuleSP &module_sp,
ModuleSP *old_module_sp_ptr,
bool *did_create_ptr)
{
uint32_t match_count = 0;
if (IsHost())
{
match_count = Host::FindProcessesByName (name_match, name_match_type, process_infos);
}
else
{
if (m_remote_platform_sp)
match_count = m_remote_platform_sp->FindProcessesByName (name_match, name_match_type, process_infos);
}
return 0;
}
Error error;
module_sp.reset();
bool
PlatformMacOSX::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
{
bool sucess = false;
if (IsHost())
{
sucess = Host::GetProcessInfo (pid, process_info);
}
else
if (IsRemote())
{
// If we have a remote platform always, let it try and locate
// the shared module first.
if (m_remote_platform_sp)
sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info);
{
error = m_remote_platform_sp->GetSharedModule (platform_file,
arch,
uuid_ptr,
object_name_ptr,
object_offset,
module_sp,
old_module_sp_ptr,
did_create_ptr);
}
}
return sucess;
if (!module_sp)
{
// Fall back to the local platform and find the file locally
error = Platform::GetSharedModule(platform_file,
arch,
uuid_ptr,
object_name_ptr,
object_offset,
module_sp,
old_module_sp_ptr,
did_create_ptr);
}
if (module_sp)
module_sp->SetPlatformFileSpec(platform_file);
return error;
}
bool
@ -187,3 +199,4 @@ PlatformMacOSX::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
return false;
}

View File

@ -16,88 +16,88 @@
// Project includes
#include "PlatformDarwin.h"
namespace lldb_private {
class PlatformMacOSX : public PlatformDarwin
{
public:
class PlatformMacOSX : public PlatformDarwin
//------------------------------------------------------------
// Class functions
//------------------------------------------------------------
static lldb_private::Platform*
CreateInstance ();
static void
Initialize ();
static void
Terminate ();
static const char *
GetPluginNameStatic ();
static const char *
GetShortPluginNameStatic(bool is_host);
static const char *
GetDescriptionStatic(bool is_host);
//------------------------------------------------------------
// Class Methods
//------------------------------------------------------------
PlatformMacOSX (bool is_host);
virtual
~PlatformMacOSX();
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
virtual const char *
GetPluginName()
{
public:
return GetPluginNameStatic ();
}
virtual const char *
GetShortPluginName()
{
return GetShortPluginNameStatic (IsHost());
}
virtual uint32_t
GetPluginVersion()
{
return 1;
}
virtual const char *
GetDescription ()
{
return GetDescriptionStatic (IsHost());
}
//------------------------------------------------------------
// Class functions
//------------------------------------------------------------
static Platform*
CreateInstance ();
virtual lldb_private::Error
GetFile (const lldb_private::FileSpec &platform_file,
const lldb_private::UUID *uuid_ptr,
lldb_private::FileSpec &local_file);
static void
Initialize ();
lldb_private::Error
GetSharedModule (const lldb_private::FileSpec &platform_file,
const lldb_private::ArchSpec &arch,
const lldb_private::UUID *uuid_ptr,
const lldb_private::ConstString *object_name_ptr,
off_t object_offset,
lldb::ModuleSP &module_sp,
lldb::ModuleSP *old_module_sp_ptr,
bool *did_create_ptr);
static void
Terminate ();
static const char *
GetPluginNameStatic ();
virtual bool
GetSupportedArchitectureAtIndex (uint32_t idx,
lldb_private::ArchSpec &arch);
static const char *
GetShortPluginNameStatic(bool is_host);
private:
DISALLOW_COPY_AND_ASSIGN (PlatformMacOSX);
static const char *
GetDescriptionStatic(bool is_host);
//------------------------------------------------------------
// Class Methods
//------------------------------------------------------------
PlatformMacOSX (bool is_host);
virtual
~PlatformMacOSX();
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
virtual const char *
GetPluginName()
{
return GetPluginNameStatic ();
}
virtual const char *
GetShortPluginName()
{
return GetShortPluginNameStatic (IsHost());
}
virtual uint32_t
GetPluginVersion()
{
return 1;
}
virtual const char *
GetDescription ()
{
return GetDescriptionStatic (IsHost());
}
virtual Error
GetFile (const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file);
virtual uint32_t
FindProcessesByName (const char *name_match,
NameMatchType name_match_type,
ProcessInfoList &process_infos);
virtual bool
GetProcessInfo (lldb::pid_t pid, ProcessInfo &proc_info);
virtual bool
GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch);
private:
DISALLOW_COPY_AND_ASSIGN (PlatformMacOSX);
};
} // namespace lldb_private
};
#endif // liblldb_PlatformMacOSX_h_

View File

@ -151,56 +151,47 @@ PlatformRemoteiOS::ResolveExecutable (const FileSpec &exe_file,
NULL,
NULL);
if (exe_module_sp->GetObjectFile() == NULL)
{
exe_module_sp.reset();
error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain the architecture %s",
exe_file.GetDirectory().AsCString(""),
exe_file.GetDirectory() ? "/" : "",
exe_file.GetFilename().AsCString(""),
exe_arch.GetArchitectureName());
}
if (exe_module_sp->GetObjectFile())
return error;
exe_module_sp.reset();
}
else
// No valid architecture was specified or the exact ARM slice wasn't
// found so ask the platform for the architectures that we should be
// using (in the correct order) and see if we can find a match that way
StreamString arch_names;
ArchSpec platform_arch;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
{
// No valid architecture was specified, ask the platform for
// the architectures that we should be using (in the correct order)
// and see if we can find a match that way
StreamString arch_names;
ArchSpec platform_arch;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
error = ModuleList::GetSharedModule (resolved_exe_file,
platform_arch,
NULL,
NULL,
0,
exe_module_sp,
NULL,
NULL);
// Did we find an executable using one of the
if (error.Success())
{
error = ModuleList::GetSharedModule (resolved_exe_file,
platform_arch,
NULL,
NULL,
0,
exe_module_sp,
NULL,
NULL);
// Did we find an executable using one of the
if (error.Success())
{
if (exe_module_sp && exe_module_sp->GetObjectFile())
break;
else
error.SetErrorToGenericError();
}
if (idx > 0)
arch_names.PutCString (", ");
arch_names.PutCString (platform_arch.GetArchitectureName());
if (exe_module_sp && exe_module_sp->GetObjectFile())
break;
else
error.SetErrorToGenericError();
}
if (error.Fail() || !exe_module_sp)
{
error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s",
exe_file.GetDirectory().AsCString(""),
exe_file.GetDirectory() ? "/" : "",
exe_file.GetFilename().AsCString(""),
GetShortPluginName(),
arch_names.GetString().c_str());
}
if (idx > 0)
arch_names.PutCString (", ");
arch_names.PutCString (platform_arch.GetArchitectureName());
}
if (error.Fail() || !exe_module_sp)
{
error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s",
exe_file.GetDirectory().AsCString(""),
exe_file.GetDirectory() ? "/" : "",
exe_file.GetFilename().AsCString(""),
GetShortPluginName(),
arch_names.GetString().c_str());
}
}
else
@ -418,10 +409,46 @@ PlatformRemoteiOS::GetFile (const FileSpec &platform_file,
return error;
}
Error
PlatformRemoteiOS::GetSharedModule (const FileSpec &platform_file,
const ArchSpec &arch,
const UUID *uuid_ptr,
const ConstString *object_name_ptr,
off_t object_offset,
ModuleSP &module_sp,
ModuleSP *old_module_sp_ptr,
bool *did_create_ptr)
{
// For iOS, the SDK files are all cached locally on the host
// system. So first we ask for the file in the cached SDK,
// then we attempt to get a shared module for the right architecture
// with the right UUID.
Error error;
FileSpec local_file;
error = GetFile (platform_file, uuid_ptr, local_file);
if (error.Success())
{
const bool always_create = false;
error = ModuleList::GetSharedModule (local_file,
arch,
uuid_ptr,
object_name_ptr,
object_offset,
module_sp,
old_module_sp_ptr,
did_create_ptr,
always_create);
}
if (module_sp)
module_sp->SetPlatformFileSpec(platform_file);
return error;
}
uint32_t
PlatformRemoteiOS::FindProcessesByName (const char *name_match,
NameMatchType name_match_type,
ProcessInfoList &process_infos)
PlatformRemoteiOS::FindProcesses (const ProcessInfoMatch &match_info,
ProcessInfoList &process_infos)
{
// TODO: if connected, send a packet to get the remote process infos by name
process_infos.Clear();

View File

@ -16,111 +16,119 @@
// Project includes
#include "PlatformDarwin.h"
namespace lldb_private {
class PlatformRemoteiOS : public PlatformDarwin
{
public:
class PlatformRemoteiOS : public PlatformDarwin
//------------------------------------------------------------
// Class Functions
//------------------------------------------------------------
static lldb_private::Platform*
CreateInstance ();
static void
Initialize ();
static void
Terminate ();
static const char *
GetPluginNameStatic ();
static const char *
GetShortPluginNameStatic();
static const char *
GetDescriptionStatic();
//------------------------------------------------------------
// Class Methods
//------------------------------------------------------------
PlatformRemoteiOS ();
virtual
~PlatformRemoteiOS();
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
virtual const char *
GetPluginName()
{
public:
return GetPluginNameStatic();
}
virtual const char *
GetShortPluginName()
{
return GetShortPluginNameStatic();
}
virtual uint32_t
GetPluginVersion()
{
return 1;
}
//------------------------------------------------------------
// Class Functions
//------------------------------------------------------------
static Platform*
CreateInstance ();
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
virtual lldb_private::Error
ResolveExecutable (const lldb_private::FileSpec &exe_file,
const lldb_private::ArchSpec &arch,
lldb::ModuleSP &module_sp);
static void
Initialize ();
virtual const char *
GetDescription ()
{
return GetDescriptionStatic();
}
static void
Terminate ();
static const char *
GetPluginNameStatic ();
virtual void
GetStatus (lldb_private::Stream &strm);
static const char *
GetShortPluginNameStatic();
virtual lldb_private::Error
GetFile (const lldb_private::FileSpec &platform_file,
const lldb_private::UUID *uuid_ptr,
lldb_private::FileSpec &local_file);
static const char *
GetDescriptionStatic();
//------------------------------------------------------------
// Class Methods
//------------------------------------------------------------
PlatformRemoteiOS ();
lldb_private::Error
GetSharedModule (const lldb_private::FileSpec &platform_file,
const lldb_private::ArchSpec &arch,
const lldb_private::UUID *uuid_ptr,
const lldb_private::ConstString *object_name_ptr,
off_t object_offset,
lldb::ModuleSP &module_sp,
lldb::ModuleSP *old_module_sp_ptr,
bool *did_create_ptr);
virtual
~PlatformRemoteiOS();
virtual uint32_t
FindProcesses (const lldb_private::ProcessInfoMatch &match_info,
lldb_private::ProcessInfoList &process_infos);
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
virtual const char *
GetPluginName()
{
return GetPluginNameStatic();
}
virtual const char *
GetShortPluginName()
{
return GetShortPluginNameStatic();
}
virtual uint32_t
GetPluginVersion()
{
return 1;
}
virtual bool
GetProcessInfo (lldb::pid_t pid,
lldb_private::ProcessInfo &proc_info);
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
virtual Error
ResolveExecutable (const FileSpec &exe_file,
const ArchSpec &arch,
lldb::ModuleSP &module_sp);
virtual bool
GetSupportedArchitectureAtIndex (uint32_t idx,
lldb_private::ArchSpec &arch);
virtual const char *
GetDescription ()
{
return GetDescriptionStatic();
}
protected:
std::string m_device_support_directory;
std::string m_device_support_directory_for_os_version;
std::string m_build_update;
//std::vector<FileSpec> m_device_support_os_dirs;
const char *
GetDeviceSupportDirectory();
virtual void
GetStatus (Stream &strm);
const char *
GetDeviceSupportDirectoryForOSVersion();
virtual Error
GetFile (const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file);
private:
DISALLOW_COPY_AND_ASSIGN (PlatformRemoteiOS);
virtual uint32_t
FindProcessesByName (const char *name_match,
NameMatchType name_match_type,
ProcessInfoList &process_infos);
virtual bool
GetProcessInfo (lldb::pid_t pid, ProcessInfo &proc_info);
virtual bool
GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch);
protected:
std::string m_device_support_directory;
std::string m_device_support_directory_for_os_version;
std::string m_build_update;
//std::vector<FileSpec> m_device_support_os_dirs;
const char *
GetDeviceSupportDirectory();
const char *
GetDeviceSupportDirectoryForOSVersion();
private:
DISALLOW_COPY_AND_ASSIGN (PlatformRemoteiOS);
};
} // namespace lldb_private
};
#endif // liblldb_PlatformRemoteiOS_h_

View File

@ -126,20 +126,6 @@ PlatformRemoteGDBServer::~PlatformRemoteGDBServer()
{
}
uint32_t
PlatformRemoteGDBServer::FindProcessesByName (const char *name_match,
NameMatchType name_match_type,
ProcessInfoList &process_infos)
{
return 0;
}
bool
PlatformRemoteGDBServer::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
{
return false;
}
bool
PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
{
@ -240,7 +226,7 @@ PlatformRemoteGDBServer::DisconnectRemote ()
}
const char *
PlatformRemoteGDBServer::GetRemoteHostname ()
PlatformRemoteGDBServer::GetHostname ()
{
m_gdb_client.GetHostname (m_name);
if (m_name.empty())
@ -248,3 +234,47 @@ PlatformRemoteGDBServer::GetRemoteHostname ()
return m_name.c_str();
}
const char *
PlatformRemoteGDBServer::GetUserName (uint32_t uid)
{
// Try and get a cache user name first
const char *cached_user_name = Platform::GetUserName(uid);
if (cached_user_name)
return cached_user_name;
std::string name;
if (m_gdb_client.GetUserName(uid, name))
return SetCachedUserName(uid, name.c_str(), name.size());
SetUserNameNotFound(uid); // Negative cache so we don't keep sending packets
return NULL;
}
const char *
PlatformRemoteGDBServer::GetGroupName (uint32_t gid)
{
const char *cached_group_name = Platform::GetGroupName(gid);
if (cached_group_name)
return cached_group_name;
std::string name;
if (m_gdb_client.GetGroupName(gid, name))
return SetCachedGroupName(gid, name.c_str(), name.size());
SetGroupNameNotFound(gid); // Negative cache so we don't keep sending packets
return NULL;
}
uint32_t
PlatformRemoteGDBServer::FindProcesses (const ProcessInfoMatch &match_info,
ProcessInfoList &process_infos)
{
return m_gdb_client.FindProcesses (match_info, process_infos);
}
bool
PlatformRemoteGDBServer::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
{
return m_gdb_client.GetProcessInfo (pid, process_info);
}

View File

@ -19,121 +19,123 @@
#include "lldb/Target/Platform.h"
#include "../../Process/gdb-remote/GDBRemoteCommunicationClient.h"
namespace lldb_private {
class PlatformRemoteGDBServer : public lldb_private::Platform
{
public:
class PlatformRemoteGDBServer : public Platform
static void
Initialize ();
static void
Terminate ();
static lldb_private::Platform*
CreateInstance ();
static const char *
GetShortPluginNameStatic();
static const char *
GetDescriptionStatic();
PlatformRemoteGDBServer ();
virtual
~PlatformRemoteGDBServer();
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
virtual const char *
GetPluginName()
{
public:
static void
Initialize ();
static void
Terminate ();
static Platform*
CreateInstance ();
static const char *
GetShortPluginNameStatic();
static const char *
GetDescriptionStatic();
return "PlatformRemoteGDBServer";
}
virtual const char *
GetShortPluginName()
{
return GetShortPluginNameStatic();
}
virtual uint32_t
GetPluginVersion()
{
return 1;
}
PlatformRemoteGDBServer ();
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
virtual lldb_private::Error
ResolveExecutable (const lldb_private::FileSpec &exe_file,
const lldb_private::ArchSpec &arch,
lldb::ModuleSP &module_sp);
virtual
~PlatformRemoteGDBServer();
virtual const char *
GetDescription ();
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
virtual const char *
GetPluginName()
{
return "PlatformRemoteGDBServer";
}
virtual const char *
GetShortPluginName()
{
return GetShortPluginNameStatic();
}
virtual uint32_t
GetPluginVersion()
{
return 1;
}
virtual lldb_private::Error
GetFile (const lldb_private::FileSpec &platform_file,
const lldb_private::UUID *uuid_ptr,
lldb_private::FileSpec &local_file);
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
virtual Error
ResolveExecutable (const FileSpec &exe_file,
const ArchSpec &arch,
lldb::ModuleSP &module_sp);
virtual bool
GetProcessInfo (lldb::pid_t pid, lldb_private::ProcessInfo &proc_info);
virtual uint32_t
FindProcesses (const lldb_private::ProcessInfoMatch &match_info,
lldb_private::ProcessInfoList &process_infos);
virtual const char *
GetDescription ();
virtual bool
GetSupportedArchitectureAtIndex (uint32_t idx, lldb_private::ArchSpec &arch);
virtual Error
GetFile (const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file);
virtual size_t
GetSoftwareBreakpointTrapOpcode (lldb_private::Target &target,
lldb_private::BreakpointSite *bp_site);
virtual uint32_t
FindProcessesByName (const char *name_match,
NameMatchType name_match_type,
ProcessInfoList &process_infos);
virtual bool
GetRemoteOSVersion ();
virtual bool
GetProcessInfo (lldb::pid_t pid, ProcessInfo &proc_info);
virtual bool
GetRemoteOSBuildString (std::string &s);
virtual bool
GetRemoteOSKernelDescription (std::string &s);
virtual bool
GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch);
// Remote Platform subclasses need to override this function
virtual lldb_private::ArchSpec
GetRemoteSystemArchitecture ();
virtual size_t
GetSoftwareBreakpointTrapOpcode (Target &target,
BreakpointSite *bp_site);
// Remote subclasses should override this and return a valid instance
// name if connected.
virtual const char *
GetHostname ();
virtual bool
GetRemoteOSVersion ();
virtual const char *
GetUserName (uint32_t uid);
virtual const char *
GetGroupName (uint32_t gid);
virtual bool
GetRemoteOSBuildString (std::string &s);
virtual bool
GetRemoteOSKernelDescription (std::string &s);
virtual bool
IsConnected () const;
// Remote Platform subclasses need to override this function
virtual ArchSpec
GetRemoteSystemArchitecture ();
virtual lldb_private::Error
ConnectRemote (lldb_private::Args& args);
// Remote subclasses should override this and return a valid instance
// name if connected.
virtual const char *
GetRemoteHostname ();
virtual lldb_private::Error
DisconnectRemote ();
virtual bool
IsConnected () const;
protected:
GDBRemoteCommunicationClient m_gdb_client;
std::string m_platform_description; // After we connect we can get a more complete description of what we are connected to
virtual Error
ConnectRemote (Args& args);
private:
DISALLOW_COPY_AND_ASSIGN (PlatformRemoteGDBServer);
virtual Error
DisconnectRemote ();
protected:
GDBRemoteCommunicationClient m_gdb_client;
std::string m_platform_description; // After we connect we can get a more complete description of what we are connected to
private:
DISALLOW_COPY_AND_ASSIGN (PlatformRemoteGDBServer);
};
} // namespace lldb_private
};
#endif // liblldb_PlatformRemoteGDBServer_h_

View File

@ -112,13 +112,13 @@ ThreadMacOSX::GetDispatchQueueName()
m_process.GetTarget().GetArchitecture().GetAddressByteSize());
static ConstString g_dispatch_queue_offsets_symbol_name ("dispatch_queue_offsets");
const Symbol *dispatch_queue_offsets_symbol = NULL;
ModuleSP module_sp(m_process.GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libSystem.B.dylib", false)));
ModuleSP module_sp(m_process.GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libSystem.B.dylib", false), NULL, NULL));
if (module_sp)
dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
if (dispatch_queue_offsets_symbol == NULL)
{
module_sp = m_process.GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libdispatch.dylib", false));
module_sp = m_process.GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libdispatch.dylib", false), NULL, NULL);
if (module_sp)
dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
}

View File

@ -161,8 +161,8 @@ StopInfoMachException::GetDescription ()
case llvm::Triple::x86_64:
switch (m_exc_code)
{
case 1: subcode_desc = "EXC_I386_SGL"; break;
case 2: subcode_desc = "EXC_I386_BPT"; break;
case 1: code_desc = "EXC_I386_SGL"; break;
case 2: code_desc = "EXC_I386_BPT"; break;
}
break;
@ -170,14 +170,14 @@ StopInfoMachException::GetDescription ()
case llvm::Triple::ppc64:
switch (m_exc_code)
{
case 1: subcode_desc = "EXC_PPC_BREAKPOINT"; break;
case 1: code_desc = "EXC_PPC_BREAKPOINT"; break;
}
break;
case llvm::Triple::arm:
switch (m_exc_code)
{
case 1: subcode_desc = "EXC_ARM_BREAKPOINT"; break;
case 1: code_desc = "EXC_ARM_BREAKPOINT"; break;
}
break;
@ -332,7 +332,10 @@ StopInfoMachException::CreateStopReasonWithMachException
else
return StopInfoSP();
}
else if (cpu == llvm::Triple::arm)
{
return StopInfo::CreateStopReasonToTrace (thread);
}
}
}
break;

View File

@ -30,7 +30,7 @@ using namespace lldb_private;
//----------------------------------------------------------------------
GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, const char *listener_name) :
Communication(comm_name),
m_packet_timeout (1),
m_packet_timeout (60),
m_rx_packet_listener (listener_name),
m_sequence_mutex (Mutex::eMutexTypeRecursive),
m_public_is_running (false),
@ -57,7 +57,6 @@ GDBRemoteCommunication::~GDBRemoteCommunication()
}
}
char
GDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length)
{
@ -80,7 +79,7 @@ GDBRemoteCommunication::SendAck ()
log->Printf ("send packet: +");
ConnectionStatus status = eConnectionStatusSuccess;
char ack_char = '+';
return Write (&ack_char, 1, status, NULL) == 1;
return Write (&ack_char, 1, status, NULL);
}
size_t
@ -91,7 +90,15 @@ GDBRemoteCommunication::SendNack ()
log->Printf ("send packet: -");
ConnectionStatus status = eConnectionStatusSuccess;
char nack_char = '-';
return Write (&nack_char, 1, status, NULL) == 1;
return Write (&nack_char, 1, status, NULL);
}
size_t
GDBRemoteCommunication::SendPacket (lldb_private::StreamString &payload)
{
Mutex::Locker locker(m_sequence_mutex);
const std::string &p (payload.GetString());
return SendPacketNoLock (p.c_str(), p.size());
}
size_t

View File

@ -49,6 +49,9 @@ public:
SendPacket (const char *payload,
size_t payload_length);
size_t
SendPacket (lldb_private::StreamString &response);
// Wait for a packet within 'nsec' seconds
size_t
WaitForPacket (StringExtractorGDBRemote &response,

View File

@ -38,13 +38,17 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() :
GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet"),
m_supports_not_sending_acks (eLazyBoolCalculate),
m_supports_thread_suffix (eLazyBoolCalculate),
m_supports_qHostInfo (eLazyBoolCalculate),
m_supports_vCont_all (eLazyBoolCalculate),
m_supports_vCont_any (eLazyBoolCalculate),
m_supports_vCont_c (eLazyBoolCalculate),
m_supports_vCont_C (eLazyBoolCalculate),
m_supports_vCont_s (eLazyBoolCalculate),
m_supports_vCont_S (eLazyBoolCalculate),
m_qHostInfo_is_valid (eLazyBoolCalculate),
m_supports_qProcessInfoPID (true),
m_supports_qfProcessInfo (true),
m_supports_qUserName (true),
m_supports_qGroupName (true),
m_async_mutex (Mutex::eMutexTypeRecursive),
m_async_packet_predicate (false),
m_async_packet (),
@ -113,11 +117,15 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings()
{
m_supports_not_sending_acks = eLazyBoolCalculate;
m_supports_thread_suffix = eLazyBoolCalculate;
m_supports_qHostInfo = eLazyBoolCalculate;
m_supports_vCont_c = eLazyBoolCalculate;
m_supports_vCont_C = eLazyBoolCalculate;
m_supports_vCont_s = eLazyBoolCalculate;
m_supports_vCont_S = eLazyBoolCalculate;
m_qHostInfo_is_valid = eLazyBoolCalculate;
m_supports_qProcessInfoPID = true;
m_supports_qfProcessInfo = true;
m_supports_qUserName = true;
m_supports_qGroupName = true;
m_host_arch.Clear();
}
@ -759,107 +767,159 @@ GDBRemoteCommunicationClient::GetSystemArchitecture ()
bool
GDBRemoteCommunicationClient::GetHostInfo ()
{
if (m_supports_qHostInfo == eLazyBoolCalculate)
if (m_qHostInfo_is_valid == eLazyBoolCalculate)
{
m_supports_qHostInfo = eLazyBoolNo;
m_qHostInfo_is_valid = eLazyBoolNo;
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse ("qHostInfo", response, false))
{
if (response.IsUnsupportedResponse())
{
return false;
m_supports_qHostInfo = eLazyBoolYes;
std::string name;
std::string value;
uint32_t cpu = LLDB_INVALID_CPUTYPE;
uint32_t sub = 0;
std::string arch_name;
std::string os_name;
std::string vendor_name;
std::string triple;
uint32_t pointer_byte_size = 0;
StringExtractor extractor;
ByteOrder byte_order = eByteOrderInvalid;
while (response.GetNameColonValue(name, value))
{
if (name.compare("cputype") == 0)
{
// exception type in big endian hex
cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0);
}
else if (name.compare("cpusubtype") == 0)
{
// exception count in big endian hex
sub = Args::StringToUInt32 (value.c_str(), 0, 0);
}
else if (name.compare("arch") == 0)
{
arch_name.swap (value);
}
else if (name.compare("triple") == 0)
{
// The triple comes as ASCII hex bytes since it contains '-' chars
extractor.GetStringRef().swap(value);
extractor.SetFilePos(0);
extractor.GetHexByteString (triple);
}
else if (name.compare("os_build") == 0)
{
extractor.GetStringRef().swap(value);
extractor.SetFilePos(0);
extractor.GetHexByteString (m_os_build);
}
else if (name.compare("hostname") == 0)
{
extractor.GetStringRef().swap(value);
extractor.SetFilePos(0);
extractor.GetHexByteString (m_hostname);
}
else if (name.compare("os_kernel") == 0)
{
extractor.GetStringRef().swap(value);
extractor.SetFilePos(0);
extractor.GetHexByteString (m_os_kernel);
}
else if (name.compare("ostype") == 0)
{
os_name.swap (value);
}
else if (name.compare("vendor") == 0)
{
vendor_name.swap(value);
}
else if (name.compare("endian") == 0)
{
if (value.compare("little") == 0)
byte_order = eByteOrderLittle;
else if (value.compare("big") == 0)
byte_order = eByteOrderBig;
else if (value.compare("pdp") == 0)
byte_order = eByteOrderPDP;
}
else if (name.compare("ptrsize") == 0)
{
pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
}
else if (name.compare("os_version") == 0)
{
Args::StringToVersion (value.c_str(),
m_os_version_major,
m_os_version_minor,
m_os_version_update);
}
}
if (triple.empty())
else if (response.IsNormalResponse())
{
if (arch_name.empty())
std::string name;
std::string value;
uint32_t cpu = LLDB_INVALID_CPUTYPE;
uint32_t sub = 0;
std::string arch_name;
std::string os_name;
std::string vendor_name;
std::string triple;
uint32_t pointer_byte_size = 0;
StringExtractor extractor;
ByteOrder byte_order = eByteOrderInvalid;
uint32_t num_keys_decoded = 0;
while (response.GetNameColonValue(name, value))
{
if (cpu != LLDB_INVALID_CPUTYPE)
if (name.compare("cputype") == 0)
{
m_host_arch.SetArchitecture (eArchTypeMachO, cpu, sub);
// exception type in big endian hex
cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0);
if (cpu != LLDB_INVALID_CPUTYPE)
++num_keys_decoded;
}
else if (name.compare("cpusubtype") == 0)
{
// exception count in big endian hex
sub = Args::StringToUInt32 (value.c_str(), 0, 0);
if (sub != 0)
++num_keys_decoded;
}
else if (name.compare("arch") == 0)
{
arch_name.swap (value);
++num_keys_decoded;
}
else if (name.compare("triple") == 0)
{
// The triple comes as ASCII hex bytes since it contains '-' chars
extractor.GetStringRef().swap(value);
extractor.SetFilePos(0);
extractor.GetHexByteString (triple);
++num_keys_decoded;
}
else if (name.compare("os_build") == 0)
{
extractor.GetStringRef().swap(value);
extractor.SetFilePos(0);
extractor.GetHexByteString (m_os_build);
++num_keys_decoded;
}
else if (name.compare("hostname") == 0)
{
extractor.GetStringRef().swap(value);
extractor.SetFilePos(0);
extractor.GetHexByteString (m_hostname);
++num_keys_decoded;
}
else if (name.compare("os_kernel") == 0)
{
extractor.GetStringRef().swap(value);
extractor.SetFilePos(0);
extractor.GetHexByteString (m_os_kernel);
++num_keys_decoded;
}
else if (name.compare("ostype") == 0)
{
os_name.swap (value);
++num_keys_decoded;
}
else if (name.compare("vendor") == 0)
{
vendor_name.swap(value);
++num_keys_decoded;
}
else if (name.compare("endian") == 0)
{
++num_keys_decoded;
if (value.compare("little") == 0)
byte_order = eByteOrderLittle;
else if (value.compare("big") == 0)
byte_order = eByteOrderBig;
else if (value.compare("pdp") == 0)
byte_order = eByteOrderPDP;
else
--num_keys_decoded;
}
else if (name.compare("ptrsize") == 0)
{
pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
if (pointer_byte_size != 0)
++num_keys_decoded;
}
else if (name.compare("os_version") == 0)
{
Args::StringToVersion (value.c_str(),
m_os_version_major,
m_os_version_minor,
m_os_version_update);
if (m_os_version_major != UINT32_MAX)
++num_keys_decoded;
}
}
if (num_keys_decoded > 0)
m_qHostInfo_is_valid = eLazyBoolYes;
if (triple.empty())
{
if (arch_name.empty())
{
if (cpu != LLDB_INVALID_CPUTYPE)
{
m_host_arch.SetArchitecture (eArchTypeMachO, cpu, sub);
if (pointer_byte_size)
{
assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
}
if (byte_order != eByteOrderInvalid)
{
assert (byte_order == m_host_arch.GetByteOrder());
}
if (!vendor_name.empty())
m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
if (!os_name.empty())
m_host_arch.GetTriple().setVendorName (llvm::StringRef (os_name));
}
}
else
{
std::string triple;
triple += arch_name;
triple += '-';
if (vendor_name.empty())
triple += "unknown";
else
triple += vendor_name;
triple += '-';
if (os_name.empty())
triple += "unknown";
else
triple += os_name;
m_host_arch.SetTriple (triple.c_str());
if (pointer_byte_size)
{
assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
@ -868,27 +928,11 @@ GDBRemoteCommunicationClient::GetHostInfo ()
{
assert (byte_order == m_host_arch.GetByteOrder());
}
if (!vendor_name.empty())
m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
if (!os_name.empty())
m_host_arch.GetTriple().setVendorName (llvm::StringRef (os_name));
}
}
else
{
std::string triple;
triple += arch_name;
triple += '-';
if (vendor_name.empty())
triple += "unknown";
else
triple += vendor_name;
triple += '-';
if (os_name.empty())
triple += "unknown";
else
triple += os_name;
m_host_arch.SetTriple (triple.c_str());
if (pointer_byte_size)
{
@ -898,24 +942,11 @@ GDBRemoteCommunicationClient::GetHostInfo ()
{
assert (byte_order == m_host_arch.GetByteOrder());
}
}
}
}
else
{
m_host_arch.SetTriple (triple.c_str());
if (pointer_byte_size)
{
assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
}
if (byte_order != eByteOrderInvalid)
{
assert (byte_order == m_host_arch.GetByteOrder());
}
}
}
}
return m_supports_qHostInfo == eLazyBoolYes;
return m_qHostInfo_is_valid == eLazyBoolYes;
}
int
@ -927,10 +958,10 @@ GDBRemoteCommunicationClient::SendAttach
{
if (pid != LLDB_INVALID_PROCESS_ID)
{
StreamString packet;
packet.Printf("vAttach;%x", pid);
if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
char packet[64];
const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%x", pid);
assert (packet_len < sizeof(packet));
if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
{
if (response.IsErrorResponse())
return response.GetError();
@ -943,7 +974,7 @@ GDBRemoteCommunicationClient::SendAttach
const lldb_private::ArchSpec &
GDBRemoteCommunicationClient::GetHostArchitecture ()
{
if (m_supports_qHostInfo == eLazyBoolCalculate)
if (m_qHostInfo_is_valid == eLazyBoolCalculate)
GetHostInfo ();
return m_host_arch;
}
@ -952,12 +983,13 @@ addr_t
GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions)
{
char packet[64];
::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size,
permissions & lldb::ePermissionsReadable ? "r" : "",
permissions & lldb::ePermissionsWritable ? "w" : "",
permissions & lldb::ePermissionsExecutable ? "x" : "");
const int packet_len = ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size,
permissions & lldb::ePermissionsReadable ? "r" : "",
permissions & lldb::ePermissionsWritable ? "w" : "",
permissions & lldb::ePermissionsExecutable ? "x" : "");
assert (packet_len < sizeof(packet));
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse (packet, response, false))
if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
{
if (!response.IsErrorResponse())
return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
@ -969,9 +1001,10 @@ bool
GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr)
{
char packet[64];
snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr);
const int packet_len = ::snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr);
assert (packet_len < sizeof(packet));
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse (packet, response, false))
if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
{
if (response.IsOKResponse())
return true;
@ -1070,11 +1103,11 @@ GDBRemoteCommunicationClient::SetWorkingDir (char const *path)
int
GDBRemoteCommunicationClient::SetDisableASLR (bool enable)
{
StreamString packet;
packet.Printf("QSetDisableASLR:%i", enable ? 1 : 0);
char packet[32];
const int packet_len = ::snprintf (packet, sizeof (packet), "QSetDisableASLR:%i", enable ? 1 : 0);
assert (packet_len < sizeof(packet));
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
{
if (response.IsOKResponse())
return 0;
@ -1084,3 +1117,251 @@ GDBRemoteCommunicationClient::SetDisableASLR (bool enable)
}
return -1;
}
bool
GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemote &response, ProcessInfo &process_info)
{
if (response.IsNormalResponse())
{
std::string name;
std::string value;
StringExtractor extractor;
while (response.GetNameColonValue(name, value))
{
if (name.compare("pid") == 0)
{
process_info.SetProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0));
}
else if (name.compare("ppid") == 0)
{
process_info.SetParentProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0));
}
else if (name.compare("uid") == 0)
{
process_info.SetRealUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
}
else if (name.compare("euid") == 0)
{
process_info.SetEffectiveUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
}
else if (name.compare("gid") == 0)
{
process_info.SetRealGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
}
else if (name.compare("egid") == 0)
{
process_info.SetEffectiveGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
}
else if (name.compare("triple") == 0)
{
// The triple comes as ASCII hex bytes since it contains '-' chars
extractor.GetStringRef().swap(value);
extractor.SetFilePos(0);
extractor.GetHexByteString (value);
process_info.GetArchitecture ().SetTriple (value.c_str());
}
else if (name.compare("name") == 0)
{
StringExtractor extractor;
// The the process name from ASCII hex bytes since we can't
// control the characters in a process name
extractor.GetStringRef().swap(value);
extractor.SetFilePos(0);
extractor.GetHexByteString (value);
process_info.SwapName (value);
}
}
if (process_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
return true;
}
return false;
}
bool
GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
{
process_info.Clear();
if (m_supports_qProcessInfoPID)
{
char packet[32];
const int packet_len = ::snprintf (packet, sizeof (packet), "qProcessInfoPID:%i", pid);
assert (packet_len < sizeof(packet));
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
{
if (response.IsUnsupportedResponse())
{
m_supports_qProcessInfoPID = false;
return false;
}
return DecodeProcessInfoResponse (response, process_info);
}
}
return false;
}
uint32_t
GDBRemoteCommunicationClient::FindProcesses (const ProcessInfoMatch &match_info,
ProcessInfoList &process_infos)
{
process_infos.Clear();
if (m_supports_qfProcessInfo)
{
StreamString packet;
packet.PutCString ("qfProcessInfo");
if (!match_info.MatchAllProcesses())
{
packet.PutChar (':');
const char *name = match_info.GetProcessInfo().GetName();
bool has_name_match = false;
if (name && name[0])
{
has_name_match = true;
NameMatchType name_match_type = match_info.GetNameMatchType();
switch (name_match_type)
{
case eNameMatchIgnore:
has_name_match = false;
break;
case eNameMatchEquals:
packet.PutCString ("name_match:equals;");
break;
case eNameMatchContains:
packet.PutCString ("name_match:contains;");
break;
case eNameMatchStartsWith:
packet.PutCString ("name_match:starts_with;");
break;
case eNameMatchEndsWith:
packet.PutCString ("name_match:ends_with;");
break;
case eNameMatchRegularExpression:
packet.PutCString ("name_match:regex;");
break;
}
if (has_name_match)
{
packet.PutCString ("name:");
packet.PutBytesAsRawHex8(name, ::strlen(name));
packet.PutChar (';');
}
}
if (match_info.GetProcessInfo().ProcessIDIsValid())
packet.Printf("pid:%u;",match_info.GetProcessInfo().GetProcessID());
if (match_info.GetProcessInfo().ParentProcessIDIsValid())
packet.Printf("parent_pid:%u;",match_info.GetProcessInfo().GetParentProcessID());
if (match_info.GetProcessInfo().RealUserIDIsValid())
packet.Printf("uid:%u;",match_info.GetProcessInfo().GetRealUserID());
if (match_info.GetProcessInfo().RealGroupIDIsValid())
packet.Printf("gid:%u;",match_info.GetProcessInfo().GetRealGroupID());
if (match_info.GetProcessInfo().EffectiveUserIDIsValid())
packet.Printf("euid:%u;",match_info.GetProcessInfo().GetEffectiveUserID());
if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
packet.Printf("egid:%u;",match_info.GetProcessInfo().GetEffectiveGroupID());
if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
packet.Printf("all_users:%u;",match_info.GetMatchAllUsers() ? 1 : 0);
if (match_info.GetProcessInfo().GetArchitecture().IsValid())
{
const ArchSpec &match_arch = match_info.GetProcessInfo().GetArchitecture();
const llvm::Triple &triple = match_arch.GetTriple();
packet.PutCString("triple:");
packet.PutCStringAsRawHex8(triple.getTriple().c_str());
packet.PutChar (';');
}
}
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
{
if (response.IsUnsupportedResponse())
{
m_supports_qfProcessInfo = false;
return 0;
}
do
{
ProcessInfo process_info;
if (!DecodeProcessInfoResponse (response, process_info))
break;
process_infos.Append(process_info);
response.GetStringRef().clear();
response.SetFilePos(0);
} while (SendPacketAndWaitForResponse ("qsProcessInfo", strlen ("qsProcessInfo"), response, false));
}
}
return process_infos.GetSize();
}
bool
GDBRemoteCommunicationClient::GetUserName (uint32_t uid, std::string &name)
{
if (m_supports_qUserName)
{
char packet[32];
const int packet_len = ::snprintf (packet, sizeof (packet), "qUserName:%i", uid);
assert (packet_len < sizeof(packet));
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
{
if (response.IsUnsupportedResponse())
{
m_supports_qUserName = false;
return false;
}
if (response.IsNormalResponse())
{
// Make sure we parsed the right number of characters. The response is
// the hex encoded user name and should make up the entire packet.
// If there are any non-hex ASCII bytes, the length won't match below..
if (response.GetHexByteString (name) * 2 == response.GetStringRef().size())
return true;
}
}
}
return false;
}
bool
GDBRemoteCommunicationClient::GetGroupName (uint32_t gid, std::string &name)
{
if (m_supports_qGroupName)
{
char packet[32];
const int packet_len = ::snprintf (packet, sizeof (packet), "qGroupName:%i", gid);
assert (packet_len < sizeof(packet));
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
{
if (response.IsUnsupportedResponse())
{
m_supports_qGroupName = false;
return false;
}
if (response.IsNormalResponse())
{
// Make sure we parsed the right number of characters. The response is
// the hex encoded group name and should make up the entire packet.
// If there are any non-hex ASCII bytes, the length won't match below..
if (response.GetHexByteString (name) * 2 == response.GetStringRef().size())
return true;
}
}
}
return false;
}

View File

@ -212,6 +212,20 @@ public:
bool
GetSupportsThreadSuffix ();
bool
GetProcessInfo (lldb::pid_t pid,
lldb_private::ProcessInfo &process_info);
uint32_t
FindProcesses (const lldb_private::ProcessInfoMatch &process_match_info,
lldb_private::ProcessInfoList &process_infos);
bool
GetUserName (uint32_t uid, std::string &name);
bool
GetGroupName (uint32_t gid, std::string &name);
bool
HasFullVContSupport ()
{
@ -239,13 +253,17 @@ protected:
//------------------------------------------------------------------
lldb_private::LazyBool m_supports_not_sending_acks;
lldb_private::LazyBool m_supports_thread_suffix;
lldb_private::LazyBool m_supports_qHostInfo;
lldb_private::LazyBool m_supports_vCont_all;
lldb_private::LazyBool m_supports_vCont_any;
lldb_private::LazyBool m_supports_vCont_c;
lldb_private::LazyBool m_supports_vCont_C;
lldb_private::LazyBool m_supports_vCont_s;
lldb_private::LazyBool m_supports_vCont_S;
lldb_private::LazyBool m_qHostInfo_is_valid;
bool m_supports_qProcessInfoPID;
bool m_supports_qfProcessInfo;
bool m_supports_qUserName;
bool m_supports_qGroupName;
// If we need to send a packet while the target is running, the m_async_XXX
// member variables take care of making this happen.
@ -263,6 +281,9 @@ protected:
std::string m_os_kernel;
std::string m_hostname;
bool
DecodeProcessInfoResponse (StringExtractorGDBRemote &response,
lldb_private::ProcessInfo &process_info);
private:
//------------------------------------------------------------------
// For GDBRemoteCommunicationClient only

View File

@ -97,13 +97,28 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout
break;
case StringExtractorGDBRemote::eServerPacketType_unimplemented:
return SendUnimplementedResponse () > 0;
return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
return Handle_qHostInfo ();
return Handle_qHostInfo (packet);
case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
return Handle_qProcessInfoPID (packet);
case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
return Handle_qfProcessInfo (packet);
case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
return Handle_qsProcessInfo (packet);
case StringExtractorGDBRemote::eServerPacketType_qUserName:
return Handle_qUserName (packet);
case StringExtractorGDBRemote::eServerPacketType_qGroupName:
return Handle_qGroupName (packet);
case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
return Handle_QStartNoAckMode ();
return Handle_QStartNoAckMode (packet);
}
return true;
}
@ -119,11 +134,22 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout
}
size_t
GDBRemoteCommunicationServer::SendUnimplementedResponse ()
GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
{
// TODO: Log the packet we aren't handling...
return SendPacket ("");
}
size_t
GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
{
char packet[16];
int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err);
assert (packet_len < sizeof(packet));
return SendPacket (packet, packet_len);
}
size_t
GDBRemoteCommunicationServer::SendOKResponse ()
{
@ -139,7 +165,7 @@ GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
}
bool
GDBRemoteCommunicationServer::Handle_qHostInfo ()
GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
{
StreamString response;
@ -204,13 +230,208 @@ GDBRemoteCommunicationServer::Handle_qHostInfo ()
response.PutChar(';');
}
return SendPacket (response.GetString().c_str(),response.GetString().size()) > 0;
return SendPacket (response) > 0;
}
static void
CreateProcessInfoResponse (const ProcessInfo &proc_info, StreamString &response)
{
response.Printf ("pid:%i;ppid:%i;uid:%i;gid:%i;euid:%i;egid:%i;",
proc_info.GetProcessID(),
proc_info.GetParentProcessID(),
proc_info.GetRealUserID(),
proc_info.GetRealGroupID(),
proc_info.GetEffectiveUserID(),
proc_info.GetEffectiveGroupID());
response.PutCString ("name:");
response.PutCStringAsRawHex8(proc_info.GetName());
response.PutChar(';');
const ArchSpec &proc_arch = proc_info.GetArchitecture();
if (proc_arch.IsValid())
{
const llvm::Triple &proc_triple = proc_arch.GetTriple();
response.PutCString("triple:");
response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
response.PutChar(';');
}
}
bool
GDBRemoteCommunicationServer::Handle_QStartNoAckMode ()
GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
{
// Packet format: "qProcessInfoPID:%i" where %i is the pid
packet.SetFilePos(strlen ("qProcessInfoPID:"));
lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
if (pid != LLDB_INVALID_PROCESS_ID)
{
ProcessInfo proc_info;
if (Host::GetProcessInfo(pid, proc_info))
{
StreamString response;
CreateProcessInfoResponse (proc_info, response);
return SendPacket (response);
}
}
return SendErrorResponse (1);
}
bool
GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
{
m_proc_infos_index = 0;
m_proc_infos.Clear();
ProcessInfoMatch match_info;
packet.SetFilePos(strlen ("qfProcessInfo"));
if (packet.GetChar() == ':')
{
std::string key;
std::string value;
while (packet.GetNameColonValue(key, value))
{
bool success = true;
if (key.compare("name") == 0)
{
StringExtractor extractor;
extractor.GetStringRef().swap(value);
extractor.GetHexByteString (value);
match_info.GetProcessInfo().SetName (value.c_str());
}
else if (key.compare("name_match") == 0)
{
if (value.compare("equals") == 0)
{
match_info.SetNameMatchType (eNameMatchEquals);
}
else if (value.compare("starts_with") == 0)
{
match_info.SetNameMatchType (eNameMatchStartsWith);
}
else if (value.compare("ends_with") == 0)
{
match_info.SetNameMatchType (eNameMatchEndsWith);
}
else if (value.compare("contains") == 0)
{
match_info.SetNameMatchType (eNameMatchContains);
}
else if (value.compare("regex") == 0)
{
match_info.SetNameMatchType (eNameMatchRegularExpression);
}
else
{
success = false;
}
}
else if (key.compare("pid") == 0)
{
match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
}
else if (key.compare("parent_pid") == 0)
{
match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
}
else if (key.compare("uid") == 0)
{
match_info.GetProcessInfo().SetRealUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
}
else if (key.compare("gid") == 0)
{
match_info.GetProcessInfo().SetRealGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
}
else if (key.compare("euid") == 0)
{
match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
}
else if (key.compare("egid") == 0)
{
match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
}
else if (key.compare("all_users") == 0)
{
match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
}
else if (key.compare("triple") == 0)
{
match_info.GetProcessInfo().GetArchitecture().SetTriple(value.c_str());
}
else
{
success = false;
}
if (!success)
return SendErrorResponse (2);
}
}
if (Host::FindProcesses (match_info, m_proc_infos))
{
// We found something, return the first item by calling the get
// subsequent process info packet handler...
return Handle_qsProcessInfo (packet);
}
return SendErrorResponse (3);
}
bool
GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
{
if (m_proc_infos_index < m_proc_infos.GetSize())
{
StreamString response;
CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
++m_proc_infos_index;
return SendPacket (response);
}
return SendErrorResponse (4);
}
bool
GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
{
// Packet format: "qUserName:%i" where %i is the uid
packet.SetFilePos(strlen ("qUserName:"));
uint32_t uid = packet.GetU32 (UINT32_MAX);
if (uid != UINT32_MAX)
{
std::string name;
if (Host::GetUserName (uid, name))
{
StreamString response;
response.PutCStringAsRawHex8 (name.c_str());
return SendPacket (response);
}
}
return SendErrorResponse (5);
}
bool
GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
{
// Packet format: "qGroupName:%i" where %i is the gid
packet.SetFilePos(strlen ("qGroupName:"));
uint32_t gid = packet.GetU32 (UINT32_MAX);
if (gid != UINT32_MAX)
{
std::string name;
if (Host::GetGroupName (gid, name))
{
StreamString response;
response.PutCStringAsRawHex8 (name.c_str());
return SendPacket (response);
}
}
return SendErrorResponse (6);
}
bool
GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
{
// Send response first before changing m_send_acks to we ack this packet
SendOKResponse ();
m_send_acks = false;
return true;

View File

@ -14,9 +14,12 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Target/Process.h"
#include "GDBRemoteCommunication.h"
class ProcessGDBRemote;
class StringExtractorGDBRemote;
class GDBRemoteCommunicationServer : public GDBRemoteCommunication
{
@ -52,18 +55,38 @@ public:
protected:
lldb::thread_t m_async_thread;
lldb_private::ProcessInfoList m_proc_infos;
uint32_t m_proc_infos_index;
size_t
SendUnimplementedResponse ();
SendUnimplementedResponse (const char *packet);
size_t
SendErrorResponse (uint8_t error);
size_t
SendOKResponse ();
bool
Handle_qHostInfo ();
Handle_qHostInfo (StringExtractorGDBRemote &packet);
bool
Handle_qProcessInfoPID (StringExtractorGDBRemote &packet);
bool
Handle_qfProcessInfo (StringExtractorGDBRemote &packet);
bool
Handle_qsProcessInfo (StringExtractorGDBRemote &packet);
bool
Handle_qUserName (StringExtractorGDBRemote &packet);
bool
Handle_qGroupName (StringExtractorGDBRemote &packet);
bool
Handle_QStartNoAckMode ();
Handle_QStartNoAckMode (StringExtractorGDBRemote &packet);
private:
//------------------------------------------------------------------

View File

@ -495,15 +495,15 @@ GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters()
{ "sp", "r13", 4, 52, eEncodingUint, eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, 13 }},
{ "lr", "r14", 4, 56, eEncodingUint, eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, 14 }},
{ "pc", "r15", 4, 60, eEncodingUint, eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, 15 }},
{ NULL, NULL, 12, 64, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 16 }},
{ NULL, NULL, 12, 76, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 17 }},
{ NULL, NULL, 12, 88, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 18 }},
{ NULL, NULL, 12, 100, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 19 }},
{ NULL, NULL, 12, 112, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 20 }},
{ NULL, NULL, 12, 124, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 21 }},
{ NULL, NULL, 12, 136, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 22 }},
{ NULL, NULL, 12, 148, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 23 }},
{ NULL, NULL, 12, 160, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 24 }},
// { NULL, NULL, 12, 64, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 16 }},
// { NULL, NULL, 12, 76, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 17 }},
// { NULL, NULL, 12, 88, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 18 }},
// { NULL, NULL, 12, 100, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 19 }},
// { NULL, NULL, 12, 112, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 20 }},
// { NULL, NULL, 12, 124, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 21 }},
// { NULL, NULL, 12, 136, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 22 }},
// { NULL, NULL, 12, 148, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 23 }},
// { NULL, NULL, 12, 160, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 24 }},
{ "cpsr", "psr", 4, 172, eEncodingUint, eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 25 }},
{ "s0", NULL, 4, 176, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 26 }},
{ "s1", NULL, 4, 180, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 27 }},

View File

@ -312,6 +312,7 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
else
{
response_type = StringExtractorGDBRemote::eError;
break;
}
}
@ -377,6 +378,7 @@ ProcessGDBRemote::DoConnectRemote (const char *remote_url)
{
// We have a valid process
SetID (pid);
UpdateThreadListIfNeeded ();
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, response, false))
{
@ -601,23 +603,28 @@ ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
return error;
}
if (m_gdb_comm.StartReadThread(&error))
// We always seem to be able to open a connection to a local port
// so we need to make sure we can then send data to it. If we can't
// then we aren't actually connected to anything, so try and do the
// handshake with the remote GDB server and make sure that goes
// alright.
if (!m_gdb_comm.HandshakeWithServer (NULL))
{
// Send an initial ack
m_gdb_comm.SendAck();
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
m_debugserver_thread = Host::StartMonitoringChildProcess (MonitorDebugserverProcess,
this,
m_debugserver_pid,
false);
m_gdb_comm.ResetDiscoverableSettings();
m_gdb_comm.GetSendAcks ();
m_gdb_comm.GetThreadSuffixSupported ();
m_gdb_comm.GetHostInfo ();
m_gdb_comm.GetVContSupported ('c');
m_gdb_comm.Disconnect();
if (error.Success())
error.SetErrorString("not connected to remote gdb server");
return error;
}
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
m_debugserver_thread = Host::StartMonitoringChildProcess (MonitorDebugserverProcess,
this,
m_debugserver_pid,
false);
m_gdb_comm.ResetDiscoverableSettings();
m_gdb_comm.QueryNoAckModeSupported ();
m_gdb_comm.GetThreadSuffixSupported ();
m_gdb_comm.GetHostInfo ();
m_gdb_comm.GetVContSupported ('c');
return error;
}
@ -633,9 +640,6 @@ ProcessGDBRemote::DidLaunchOrAttach ()
BuildDynamicRegisterInfo (false);
StreamString strm;
// See if the GDB server supports the qHostInfo information
const ArchSpec &gdb_remote_arch = m_gdb_comm.GetHostArchitecture();
@ -2364,13 +2368,13 @@ ProcessGDBRemote::GetDispatchQueueNameForThread
{
static ConstString g_dispatch_queue_offsets_symbol_name ("dispatch_queue_offsets");
const Symbol *dispatch_queue_offsets_symbol = NULL;
ModuleSP module_sp(GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libSystem.B.dylib", false)));
ModuleSP module_sp(GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libSystem.B.dylib", false), NULL, NULL));
if (module_sp)
dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
if (dispatch_queue_offsets_symbol == NULL)
{
module_sp = GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libdispatch.dylib", false));
module_sp = GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libdispatch.dylib", false), NULL, NULL);
if (module_sp)
dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
}

View File

@ -474,9 +474,9 @@ SymbolContextSpecifier::AddSpecification (const char *spec_string, Specification
break;
case eModuleSpecified:
{
// See if we can find the Module, if so stick it in the SymbolContext.
FileSpec module_spec(spec_string, true);
lldb::ModuleSP module_sp = m_target_sp->GetImages().FindFirstModuleForFileSpec (module_spec);
// See if we can find the Module, if so stick it in the SymbolContext.
FileSpec module_spec(spec_string, false);
lldb::ModuleSP module_sp = m_target_sp->GetImages().FindFirstModuleForFileSpec (module_spec, NULL, NULL);
m_type |= eModuleSpecified;
if (module_sp)
m_module_sp = module_sp;
@ -487,7 +487,7 @@ SymbolContextSpecifier::AddSpecification (const char *spec_string, Specification
case eFileSpecified:
// CompUnits can't necessarily be resolved here, since an inlined function might show up in
// a number of CompUnits. Instead we just convert to a FileSpec and store it away.
m_file_spec_ap.reset (new FileSpec (spec_string, true));
m_file_spec_ap.reset (new FileSpec (spec_string, false));
m_type |= eFileSpecified;
break;
case eLineStartSpecified:

View File

@ -78,6 +78,35 @@ Platform::GetFile (const FileSpec &platform_file,
return Error();
}
Error
Platform::GetSharedModule (const FileSpec &platform_file,
const ArchSpec &arch,
const UUID *uuid_ptr,
const ConstString *object_name_ptr,
off_t object_offset,
ModuleSP &module_sp,
ModuleSP *old_module_sp_ptr,
bool *did_create_ptr)
{
// Don't do any path remapping for the default implementation
// of the platform GetSharedModule function, just call through
// to our static ModuleList function. Platform subclasses that
// implement remote debugging, might have a developer kits
// installed that have cached versions of the files for the
// remote target, or might implement a download and cache
// locally implementation.
const bool always_create = false;
return ModuleList::GetSharedModule (platform_file,
arch,
uuid_ptr,
object_name_ptr,
object_offset,
module_sp,
old_module_sp_ptr,
did_create_ptr,
always_create);
}
PlatformSP
Platform::Create (const char *platform_name, Error &error)
@ -127,7 +156,14 @@ Platform::Platform (bool is_host) :
m_name (),
m_major_os_version (UINT32_MAX),
m_minor_os_version (UINT32_MAX),
m_update_os_version (UINT32_MAX)
m_update_os_version (UINT32_MAX),
m_system_arch(),
m_uid_map_mutex (Mutex::eMutexTypeNormal),
m_gid_map_mutex (Mutex::eMutexTypeNormal),
m_uid_map(),
m_gid_map(),
m_max_uid_name_len (0),
m_max_gid_name_len (0)
{
}
@ -148,18 +184,18 @@ Platform::GetStatus (Stream &strm)
uint32_t minor = UINT32_MAX;
uint32_t update = UINT32_MAX;
std::string s;
strm.Printf ("Platform: %s\n", GetShortPluginName());
strm.Printf (" Platform: %s\n", GetShortPluginName());
ArchSpec arch (GetSystemArchitecture());
if (arch.IsValid())
{
if (!arch.GetTriple().str().empty())
strm.Printf("Triple: %s\n", arch.GetTriple().str().c_str());
strm.Printf(" Triple: %s\n", arch.GetTriple().str().c_str());
}
if (GetOSVersion(major, minor, update))
{
strm.Printf("OS: %u", major);
strm.Printf("OS Version: %u", major);
if (minor != UINT32_MAX)
strm.Printf(".%u", minor);
if (update != UINT32_MAX)
@ -172,18 +208,18 @@ Platform::GetStatus (Stream &strm)
}
if (GetOSKernelDescription (s))
strm.Printf("Kernel: %s\n", s.c_str());
strm.Printf(" Kernel: %s\n", s.c_str());
if (IsHost())
{
strm.Printf("Hostname: %s\n", GetHostname());
strm.Printf(" Hostname: %s\n", GetHostname());
}
else
{
if (IsConnected())
strm.Printf("Remote hostname: %s\n", GetHostname());
else
strm.PutCString("Not connected to a remote platform.\n");
const bool is_connected = IsConnected();
if (is_connected)
strm.Printf(" Hostname: %s\n", GetHostname());
strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
}
}
@ -266,33 +302,46 @@ Platform::GetOSKernelDescription (std::string &s)
const char *
Platform::GetHostname ()
{
if (m_name.empty())
if (IsHost() && m_name.empty())
{
if (IsHost())
{
if (!Host::GetHostname(m_name))
return "localhost";
}
else
{
if (IsConnected())
{
const char *instance_name = GetRemoteHostname ();
if (instance_name)
m_name.assign (instance_name);
}
else
{
return "remote";
}
}
if (!Host::GetHostname(m_name))
return "localhost";
}
if (m_name.empty())
return NULL;
return m_name.c_str();
}
const char *
Platform::GetUserName (uint32_t uid)
{
const char *user_name = GetCachedUserName(uid);
if (user_name)
return user_name;
if (IsHost())
{
std::string name;
if (Host::GetUserName(uid, name))
return SetCachedUserName (uid, name.c_str(), name.size());
}
if (!m_name.empty())
return m_name.c_str();
return NULL;
}
const char *
Platform::GetGroupName (uint32_t gid)
{
const char *group_name = GetCachedGroupName(gid);
if (group_name)
return group_name;
if (IsHost())
{
std::string name;
if (Host::GetGroupName(gid, name))
return SetCachedGroupName (gid, name.c_str(), name.size());
}
return NULL;
}
bool
Platform::SetOSVersion (uint32_t major,
@ -447,3 +496,23 @@ Platform::DisconnectRemote ()
error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetShortPluginName());
return error;
}
bool
Platform::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
{
// Take care of the host case so that each subclass can just
// call Platform::GetProcessInfo (pid, process_info)
if (IsHost())
return Host::GetProcessInfo (pid, process_info);
return false;
}
uint32_t
Platform::FindProcesses (const ProcessInfoMatch &match_info,
ProcessInfoList &process_infos)
{
uint32_t match_count = 0;
if (IsHost())
match_count = Host::FindProcesses (match_info, process_infos);
return match_count;
}

View File

@ -38,6 +38,172 @@
using namespace lldb;
using namespace lldb_private;
void
ProcessInfo::Dump (Stream &s, Platform *platform) const
{
const char *cstr;
if (m_pid != LLDB_INVALID_PROCESS_ID) s.Printf (" pid = %i\n", m_pid);
if (!m_name.empty()) s.Printf (" name = \"%s\"\n", m_name.c_str());
if (m_arch.IsValid()) s.Printf (" arch = %s\n", m_arch.GetTriple().str().c_str());
if (m_parent_pid != LLDB_INVALID_PROCESS_ID)s.Printf ("parent = %i\n", m_parent_pid);
if (m_real_uid != UINT32_MAX)
{
cstr = platform->GetUserName (m_real_uid);
s.Printf (" uid = %u %s\n", m_real_uid, cstr ? cstr : "");
}
if (m_real_gid != UINT32_MAX)
{
cstr = platform->GetGroupName (m_real_gid);
s.Printf (" gid = %u %s\n", m_real_gid, cstr ? cstr : "");
}
if (m_effective_uid != UINT32_MAX)
{
cstr = platform->GetUserName (m_effective_uid);
s.Printf (" euid = %u %s\n", m_effective_uid, cstr ? cstr : "");
}
if (m_effective_gid != UINT32_MAX)
{
cstr = platform->GetGroupName (m_effective_gid);
s.Printf (" egid = %u %s\n", m_effective_gid, cstr ? cstr : "");
}
}
void
ProcessInfo::DumpTableHeader (Stream &s, Platform *platform)
{
// s.PutCString ("PID PARENT UID GID EUID EGID TRIPLE NAME\n");
// s.PutCString ("====== ====== ===== ===== ===== ===== ======================== ============================\n");
s.PutCString ("PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME\n");
s.PutCString ("====== ====== ========== ========== ========== ========== ======================== ============================\n");
}
void
ProcessInfo::DumpAsTableRow (Stream &s, Platform *platform) const
{
if (m_pid != LLDB_INVALID_PROCESS_ID)
{
const char *cstr;
s.Printf ("%-6u %-6u ", m_pid, m_parent_pid);
cstr = platform->GetUserName (m_real_uid);
if (cstr && cstr[0]) // Watch for empty string that indicates lookup failed
s.Printf ("%-10s ", cstr);
else
s.Printf ("%-10u ", m_real_uid);
cstr = platform->GetGroupName (m_real_gid);
if (cstr && cstr[0]) // Watch for empty string that indicates lookup failed
s.Printf ("%-10s ", cstr);
else
s.Printf ("%-10u ", m_real_gid);
cstr = platform->GetUserName (m_effective_uid);
if (cstr && cstr[0]) // Watch for empty string that indicates lookup failed
s.Printf ("%-10s ", cstr);
else
s.Printf ("%-10u ", m_effective_uid);
cstr = platform->GetGroupName (m_effective_gid);
if (cstr && cstr[0]) // Watch for empty string that indicates lookup failed
s.Printf ("%-10s ", cstr);
else
s.Printf ("%-10u ", m_effective_gid);
s.Printf ("%-24s %s\n",
m_arch.IsValid() ? m_arch.GetTriple().str().c_str() : "",
m_name.c_str());
}
}
bool
ProcessInfoMatch::NameMatches (const char *process_name) const
{
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
ProcessInfoMatch::Matches (const ProcessInfo &proc_info) const
{
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;
if (m_match_info.RealUserIDIsValid () &&
m_match_info.GetRealUserID() != proc_info.GetRealUserID())
return false;
if (m_match_info.RealGroupIDIsValid () &&
m_match_info.GetRealGroupID() != proc_info.GetRealGroupID())
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() &&
m_match_info.GetArchitecture() != proc_info.GetArchitecture())
return false;
return true;
}
bool
ProcessInfoMatch::MatchAllProcesses () const
{
if (m_name_match_type != eNameMatchIgnore)
return false;
if (m_match_info.ProcessIDIsValid())
return false;
if (m_match_info.ParentProcessIDIsValid())
return false;
if (m_match_info.RealUserIDIsValid ())
return false;
if (m_match_info.RealGroupIDIsValid ())
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
ProcessInfoMatch::Clear()
{
m_match_info.Clear();
m_name_match_type = eNameMatchIgnore;
m_match_all_users = false;
}
//----------------------------------------------------------------------
// MemoryCache constructor
@ -1727,7 +1893,10 @@ Process::Attach (const char *process_name, bool wait_for_launch)
PlatformSP platform_sp (m_target.GetDebugger().GetPlatformList().GetSelectedPlatform ());
if (platform_sp)
{
platform_sp->FindProcessesByName (process_name, eNameMatchEquals, process_infos);
ProcessInfoMatch match_info;
match_info.GetProcessInfo().SetName(process_name);
match_info.SetNameMatchType (eNameMatchEquals);
platform_sp->FindProcesses (match_info, process_infos);
if (process_infos.GetSize() > 1)
{
error.SetErrorStringWithFormat ("More than one process named %s\n", process_name);
@ -1829,13 +1998,28 @@ Process::ConnectRemote (const char *remote_url)
Error error (DoConnectRemote (remote_url));
if (error.Success())
{
StartPrivateStateThread();
// If we attached and actually have a process on the other end, then
// this ended up being the equivalent of an attach.
if (GetID() != LLDB_INVALID_PROCESS_ID)
{
CompleteAttach ();
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);
}
}
if (PrivateStateThreadIsValid ())
ResumePrivateStateThread ();
else
StartPrivateStateThread ();
}
return error;
}

View File

@ -39,22 +39,25 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// Target constructor
//----------------------------------------------------------------------
Target::Target(Debugger &debugger, const lldb::PlatformSP &platform_sp) :
Broadcaster("lldb.target"),
m_platform_sp (platform_sp),
Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::PlatformSP &platform_sp) :
Broadcaster ("lldb.target"),
ExecutionContextScope (),
TargetInstanceSettings (*GetSettingsController()),
m_debugger (debugger),
m_platform_sp (platform_sp),
m_mutex (Mutex::eMutexTypeRecursive),
m_images(),
m_arch (target_arch),
m_images (),
m_section_load_list (),
m_breakpoint_list (false),
m_internal_breakpoint_list (true),
m_process_sp(),
m_search_filter_sp(),
m_process_sp (),
m_search_filter_sp (),
m_image_search_paths (ImageSearchPathsChanged, this),
m_scratch_ast_context_ap (NULL),
m_persistent_variables (),
m_stop_hook_next_id(0)
m_stop_hooks (),
m_stop_hook_next_id (0)
{
SetEventName (eBroadcastBitBreakpointChanged, "breakpoint-changed");
SetEventName (eBroadcastBitModulesLoaded, "modules-loaded");
@ -412,10 +415,9 @@ Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
m_images.Append(executable_sp); // The first image is our exectuable file
ArchSpec exe_arch = executable_sp->GetArchitecture();
// If we haven't set an architecture yet, reset our architecture based on what we found in the executable module.
if (!m_arch_spec.IsValid())
m_arch_spec = exe_arch;
if (!m_arch.IsValid())
m_arch = executable_sp->GetArchitecture();
FileSpecList dependent_files;
ObjectFile *executable_objfile = executable_sp->GetObjectFile();
@ -433,7 +435,7 @@ Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
platform_dependent_file_spec = dependent_file_spec;
ModuleSP image_module_sp(GetSharedModule (platform_dependent_file_spec,
exe_arch));
m_arch));
if (image_module_sp.get())
{
//image_module_sp->Dump(&s);// REMOVE THIS, DEBUG ONLY
@ -445,9 +447,9 @@ Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
}
// Now see if we know the target triple, and if so, create our scratch AST context:
if (m_arch_spec.IsValid())
if (m_arch.IsValid())
{
m_scratch_ast_context_ap.reset (new ClangASTContext(m_arch_spec.GetTriple().str().c_str()));
m_scratch_ast_context_ap.reset (new ClangASTContext(m_arch.GetTriple().str().c_str()));
}
}
@ -458,22 +460,22 @@ Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
bool
Target::SetArchitecture (const ArchSpec &arch_spec)
{
if (m_arch_spec == arch_spec)
if (m_arch == arch_spec)
{
// If we're setting the architecture to our current architecture, we
// don't need to do anything.
return true;
}
else if (!m_arch_spec.IsValid())
else if (!m_arch.IsValid())
{
// If we haven't got a valid arch spec, then we just need to set it.
m_arch_spec = arch_spec;
m_arch = arch_spec;
return true;
}
else
{
// If we have an executable file, try to reset the executable to the desired architecture
m_arch_spec = arch_spec;
m_arch = arch_spec;
ModuleSP executable_sp = GetExecutableModule ();
m_images.Clear();
m_scratch_ast_context_ap.reset();
@ -668,10 +670,9 @@ Target::GetSharedModule
bool did_create_module = false;
ModuleSP module_sp;
// If there are image search path entries, try to use them first to acquire a suitable image.
Error error;
// If there are image search path entries, try to use them first to acquire a suitable image.
if (m_image_search_paths.GetSize())
{
FileSpec transformed_spec;
@ -682,13 +683,26 @@ Target::GetSharedModule
}
}
// If a module hasn't been found yet, use the unmodified path.
if (!module_sp)
// The platform is responsible for finding and caching an appropriate
// module in the shared module cache.
if (m_platform_sp)
{
error = (ModuleList::GetSharedModule (file_spec, arch, uuid_ptr, object_name, object_offset, module_sp, &old_module_sp, &did_create_module));
FileSpec platform_file_spec;
error = m_platform_sp->GetSharedModule (file_spec,
arch,
uuid_ptr,
object_name,
object_offset,
module_sp,
&old_module_sp,
&did_create_module);
}
else
{
error.SetErrorString("no platform is currently set");
}
// If a module hasn't been found yet, use the unmodified path.
if (module_sp)
{
m_images.Append (module_sp);
@ -1130,17 +1144,17 @@ Target::RunStopHooks ()
bool echo_commands = false;
bool print_results = true;
GetDebugger().GetCommandInterpreter().HandleCommands (cur_hook_sp->GetCommands(),
&exc_ctx_with_reasons[i],
stop_on_continue,
stop_on_error,
echo_commands,
print_results,
result);
&exc_ctx_with_reasons[i],
stop_on_continue,
stop_on_error,
echo_commands,
print_results,
result);
// If the command started the target going again, we should bag out of
// running the stop hooks.
if ((result.GetStatus() == eReturnStatusSuccessContinuingNoResult)
|| (result.GetStatus() == eReturnStatusSuccessContinuingResult))
if ((result.GetStatus() == eReturnStatusSuccessContinuingNoResult) ||
(result.GetStatus() == eReturnStatusSuccessContinuingResult))
{
result.AppendMessageWithFormat ("Aborting stop hooks, hook %d set the program running.", cur_hook_sp->GetID());
keep_going = false;

View File

@ -68,7 +68,6 @@ TargetList::CreateTarget
{
ModuleSP exe_module_sp;
FileSpec resolved_file(file);
ArchSpec platform_arch;
if (platform_sp)
error = platform_sp->ResolveExecutable (file, arch, exe_module_sp);
@ -94,7 +93,7 @@ TargetList::CreateTarget
}
return error;
}
target_sp.reset(new Target(debugger, platform_sp));
target_sp.reset(new Target(debugger, arch, platform_sp));
target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
}
}
@ -102,9 +101,7 @@ TargetList::CreateTarget
{
// No file was specified, just create an empty target with any arch
// if a valid arch was specified
target_sp.reset(new Target(debugger, platform_sp));
if (arch.IsValid())
target_sp->SetArchitecture(arch);
target_sp.reset(new Target(debugger, arch, platform_sp));
}
if (target_sp)

View File

@ -156,6 +156,26 @@ StringExtractor::GetHexU8 (uint8_t fail_value)
return fail_value;
}
uint32_t
StringExtractor::GetU32 (uint32_t fail_value, int base)
{
if (m_index < m_packet.size())
{
char *end = NULL;
const char *start = m_packet.c_str();
const char *uint_cstr = start + m_index;
uint32_t result = ::strtoul (uint_cstr, &end, base);
if (end && end != uint_cstr)
{
m_index = end - start;
return result;
}
}
return fail_value;
}
uint32_t
StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
{

View File

@ -98,6 +98,9 @@ public:
bool
GetNameColonValue (std::string &name, std::string &value);
uint32_t
GetU32 (uint32_t fail_value, int base = 0);
uint32_t
GetHexMaxU32 (bool little_endian, uint32_t fail_value);

View File

@ -81,8 +81,18 @@ StringExtractorGDBRemote::GetServerPacketType () const
break;
case 'q':
if (strcmp (packet_cstr, "qHostInfo") == 0)
if (packet_cstr[1] == 'H' && 0 == ::strcmp (packet_cstr, "qHostInfo"))
return eServerPacketType_qHostInfo;
else if (packet_cstr[1] == 'P' && 0 == ::strncmp(packet_cstr, "qProcessInfoPID:", strlen("qProcessInfoPID:")))
return eServerPacketType_qProcessInfoPID;
else if (packet_cstr[1] == 'f' && 0 == ::strncmp(packet_cstr, "qfProcessInfo", strlen("qfProcessInfo")))
return eServerPacketType_qfProcessInfo;
else if (packet_cstr[1] == 'U' && 0 == ::strncmp(packet_cstr, "qUserName:", strlen("qUserName:")))
return eServerPacketType_qUserName;
else if (packet_cstr[1] == 'G' && 0 == ::strncmp(packet_cstr, "qGroupName:", strlen("qGroupName:")))
return eServerPacketType_qGroupName;
else if (packet_cstr[1] == 's' && 0 == ::strcmp (packet_cstr, "qsProcessInfo"))
return eServerPacketType_qsProcessInfo;
break;
}
return eServerPacketType_unimplemented;

View File

@ -47,6 +47,11 @@ public:
eServerPacketType_unimplemented,
eServerPacketType_interrupt, // CTRL+c packet or "\x03"
eServerPacketType_qHostInfo,
eServerPacketType_qProcessInfoPID,
eServerPacketType_qfProcessInfo,
eServerPacketType_qsProcessInfo,
eServerPacketType_qUserName,
eServerPacketType_qGroupName,
eServerPacketType_QStartNoAckMode
};

View File

@ -465,8 +465,11 @@
);
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 131;
"GCC_VERSION[sdk=iphoneos*][arch=*]" = 4.2;
"GCC_VERSION[sdk=macosx*][arch=*]" = "";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
SDKROOT = "";
STRIP_INSTALLED_PRODUCT = NO;
VALID_ARCHS = "armv4t armv5 armv6 armv7 i386 ppc ppc64 ppc7400 ppc970 x86_64";
VERSIONING_SYSTEM = "apple-generic";
@ -486,6 +489,7 @@
DEAD_CODE_STRIPPING = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
SDKROOT = "";
STRIPFLAGS = "-x";
STRIP_STYLE = debugging;
VALID_ARCHS = "armv4t armv5 armv6 armv7 i386 ppc ppc64 ppc7400 ppc970 x86_64";
@ -506,6 +510,7 @@
DEAD_CODE_STRIPPING = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
SDKROOT = "";
STRIPFLAGS = "-x";
STRIP_STYLE = debugging;
VALID_ARCHS = "armv4t armv5 armv6 armv7 i386 ppc ppc64 ppc7400 ppc970 x86_64";

View File

@ -90,6 +90,13 @@ DNBLogEnabled ()
return g_log_callback != NULL;
}
bool
DNBLogEnabledForAny (uint32_t mask)
{
if (g_log_callback)
return (g_log_bits & mask) != 0;
return false;
}
static inline void
_DNBLogVAPrintf(uint32_t flags, const char *format, va_list args)
{

View File

@ -51,6 +51,7 @@ uint32_t DNBLogSetLogMask (uint32_t mask) DNB_EXPORT;
uint32_t DNBLogGetLogMask () DNB_EXPORT;
void DNBLogSetLogCallback (DNBCallbackLog callback, void *baton) DNB_EXPORT;
bool DNBLogEnabled () DNB_EXPORT;
bool DNBLogEnabledForAny (uint32_t mask) DNB_EXPORT;
int DNBLogGetDebug () DNB_EXPORT;
void DNBLogSetDebug (int g) DNB_EXPORT;
int DNBLogGetVerbose () DNB_EXPORT;
@ -60,7 +61,7 @@ void DNBLogSetVerbose (int g) DNB_EXPORT;
#define DNBLogDebug(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogDebug(fmt, ## __VA_ARGS__); } } while (0)
#define DNBLogDebugVerbose(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogDebugVerbose(fmt, ## __VA_ARGS__); } } while (0)
#define DNBLogThreaded(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogThreaded(fmt, ## __VA_ARGS__); } } while (0)
#define DNBLogThreadedIf(mask, fmt, ...) do { if (DNBLogEnabled()) { _DNBLogThreadedIf(mask, fmt, ## __VA_ARGS__); } } while (0)
#define DNBLogThreadedIf(mask, fmt, ...) do { if (DNBLogEnabledForAny(mask)) { _DNBLogThreaded(fmt, ## __VA_ARGS__); } } while (0)
#define DNBLogError(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogError(fmt, ## __VA_ARGS__); } } while (0)
#define DNBLogFatalError(err, fmt, ...) do { if (DNBLogEnabled()) { _DNBLogFatalError(err, fmt, ## __VA_ARGS__); } } while (0)
#define DNBLogVerbose(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogVerbose(fmt, ## __VA_ARGS__); } } while (0)

View File

@ -93,6 +93,29 @@ static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE };
#define MNEMONIC_STRING_SIZE 32
#define OPERAND_STRING_SIZE 128
void
DNBArchMachARM::Initialize()
{
DNBArchPluginInfo arch_plugin_info =
{
CPU_TYPE_ARM,
DNBArchMachARM::Create,
DNBArchMachARM::GetRegisterSetInfo,
DNBArchMachARM::SoftwareBreakpointOpcode
};
// Register this arch plug-in with the main protocol class
DNBArchProtocol::RegisterArchPlugin (arch_plugin_info);
}
DNBArchProtocol *
DNBArchMachARM::Create (MachThread *thread)
{
return new DNBArchMachARM (thread);
}
const uint8_t * const
DNBArchMachARM::SoftwareBreakpointOpcode (nub_size_t byte_size)
{
@ -153,8 +176,29 @@ DNBArchMachARM::GetGPRState(bool force)
mach_msg_type_number_t count = ARM_THREAD_STATE_COUNT;
kern_return_t kret = ::thread_get_state(m_thread->ThreadID(), ARM_THREAD_STATE, (thread_state_t)&m_state.context.gpr, &count);
uint32_t *r = &m_state.context.gpr.__r[0];
DNBLogThreadedIf(LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x regs r0=%8.8x r1=%8.8x r2=%8.8x r3=%8.8x r4=%8.8x r5=%8.8x r6=%8.8x r7=%8.8x r8=%8.8x r9=%8.8x r10=%8.8x r11=%8.8x s12=%8.8x sp=%8.8x lr=%8.8x pc=%8.8x cpsr=%8.8x", m_thread->ThreadID(), ARM_THREAD_STATE, ARM_THREAD_STATE_COUNT, kret,
r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15], r[16]);
DNBLogThreadedIf(LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count = %u) regs r0=%8.8x r1=%8.8x r2=%8.8x r3=%8.8x r4=%8.8x r5=%8.8x r6=%8.8x r7=%8.8x r8=%8.8x r9=%8.8x r10=%8.8x r11=%8.8x s12=%8.8x sp=%8.8x lr=%8.8x pc=%8.8x cpsr=%8.8x",
m_thread->ThreadID(),
ARM_THREAD_STATE,
ARM_THREAD_STATE_COUNT,
kret,
count,
r[0],
r[1],
r[2],
r[3],
r[4],
r[5],
r[6],
r[7],
r[8],
r[9],
r[10],
r[11],
r[12],
r[13],
r[14],
r[15],
r[16]);
m_state.SetError(set, Read, kret);
return kret;
}
@ -170,6 +214,24 @@ DNBArchMachARM::GetVFPState(bool force)
// Read the registers from our thread
mach_msg_type_number_t count = ARM_VFP_STATE_COUNT;
kern_return_t kret = ::thread_get_state(m_thread->ThreadID(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, &count);
if (DNBLogEnabledForAny (LOG_THREAD))
{
uint32_t *r = &m_state.context.vfp.__r[0];
DNBLogThreaded ("thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count => %u)",
m_thread->ThreadID(),
ARM_THREAD_STATE,
ARM_THREAD_STATE_COUNT,
kret,
count);
DNBLogThreaded(" s0=%8.8x s1=%8.8x s2=%8.8x s3=%8.8x s4=%8.8x s5=%8.8x s6=%8.8x s7=%8.8x",r[ 0],r[ 1],r[ 2],r[ 3],r[ 4],r[ 5],r[ 6],r[ 7]);
DNBLogThreaded(" s8=%8.8x s9=%8.8x s10=%8.8x s11=%8.8x s12=%8.8x s13=%8.8x s14=%8.8x s15=%8.8x",r[ 8],r[ 9],r[10],r[11],r[12],r[13],r[14],r[15]);
DNBLogThreaded(" s16=%8.8x s17=%8.8x s18=%8.8x s19=%8.8x s20=%8.8x s21=%8.8x s22=%8.8x s23=%8.8x",r[16],r[17],r[18],r[19],r[20],r[21],r[22],r[23]);
DNBLogThreaded(" s24=%8.8x s25=%8.8x s26=%8.8x s27=%8.8x s28=%8.8x s29=%8.8x s30=%8.8x s31=%8.8x",r[24],r[25],r[26],r[27],r[28],r[29],r[30],r[31]);
DNBLogThreaded(" s32=%8.8x s33=%8.8x s34=%8.8x s35=%8.8x s36=%8.8x s37=%8.8x s38=%8.8x s39=%8.8x",r[32],r[33],r[34],r[35],r[36],r[37],r[38],r[39]);
DNBLogThreaded(" s40=%8.8x s41=%8.8x s42=%8.8x s43=%8.8x s44=%8.8x s45=%8.8x s46=%8.8x s47=%8.8x",r[40],r[41],r[42],r[43],r[44],r[45],r[46],r[47]);
DNBLogThreaded(" s48=%8.8x s49=%8.8x s50=%8.8x s51=%8.8x s52=%8.8x s53=%8.8x s54=%8.8x s55=%8.8x",r[48],r[49],r[50],r[51],r[52],r[53],r[54],r[55]);
DNBLogThreaded(" s56=%8.8x s57=%8.8x s58=%8.8x s59=%8.8x s60=%8.8x s61=%8.8x s62=%8.8x s63=%8.8x fpscr=%8.8x",r[56],r[57],r[58],r[59],r[60],r[61],r[62],r[63],r[64]);
}
m_state.SetError(set, Read, kret);
return kret;
}
@ -2338,6 +2400,22 @@ enum
vfp_s29,
vfp_s30,
vfp_s31,
vfp_d0,
vfp_d1,
vfp_d2,
vfp_d3,
vfp_d4,
vfp_d5,
vfp_d6,
vfp_d7,
vfp_d8,
vfp_d9,
vfp_d10,
vfp_d11,
vfp_d12,
vfp_d13,
vfp_d14,
vfp_d15,
vfp_d16,
vfp_d17,
vfp_d18,
@ -2445,8 +2523,8 @@ enum
#define GPR_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::GPR, __r[idx]))
#define GPR_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::GPR, __##reg))
#define VFP_S_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::FPU, __r[idx]) + offsetof (DNBArchMachARM::Context, vfp))
#define VFP_D_OFFSET_IDX(idx) (VFP_S_OFFSET_IDX (32) + (((idx) - 16) * 8))
#define VFP_S_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::FPU, __r[(idx)]) + offsetof (DNBArchMachARM::Context, vfp))
#define VFP_D_OFFSET_IDX(idx) (VFP_S_OFFSET_IDX ((idx) * 2))
#define VFP_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::FPU, __##reg) + offsetof (DNBArchMachARM::Context, vfp))
#define EXC_OFFSET(reg) (offsetof (DNBArchMachARM::EXC, __##reg) + offsetof (DNBArchMachARM::Context, exc))
@ -2456,9 +2534,11 @@ enum
// sizes and offsets.
#define DEFINE_GPR_IDX(idx, reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_IDX(idx), gcc_##reg, dwarf_##reg, gen, gdb_##reg }
#define DEFINE_GPR_NAME(reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_NAME(reg), gcc_##reg, dwarf_##reg, gen, gdb_##reg }
#define DEFINE_VFP_S_IDX(idx) { e_regSetVFP, vfp_s##idx, "s" #idx, NULL, IEEE754, 4, Float, VFP_S_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_s##idx, INVALID_NUB_REGNUM, gdb_s##idx }
#define DEFINE_VFP_D_IDX(idx) { e_regSetVFP, vfp_d##idx, "d" #idx, NULL, IEEE754, 8, Float, VFP_D_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_s##idx, INVALID_NUB_REGNUM, gdb_s##idx }
//#define FLOAT_FORMAT Float
#define FLOAT_FORMAT Hex
#define DEFINE_VFP_S_IDX(idx) { e_regSetVFP, vfp_s##idx, "s" #idx, NULL, IEEE754, FLOAT_FORMAT, 4, VFP_S_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_s##idx, INVALID_NUB_REGNUM, gdb_s##idx }
//#define DEFINE_VFP_D_IDX(idx) { e_regSetVFP, vfp_d##idx, "d" #idx, NULL, IEEE754, Float, 8, VFP_D_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_d##idx, INVALID_NUB_REGNUM, gdb_d##idx }
#define DEFINE_VFP_D_IDX(idx) { e_regSetVFP, vfp_d##idx, "d" #idx, NULL, IEEE754, FLOAT_FORMAT, 8, VFP_D_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_d##idx, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM }
// General purpose registers
const DNBRegisterInfo
@ -2519,6 +2599,22 @@ DNBArchMachARM::g_vfp_registers[] =
DEFINE_VFP_S_IDX (29),
DEFINE_VFP_S_IDX (30),
DEFINE_VFP_S_IDX (31),
DEFINE_VFP_D_IDX (0),
DEFINE_VFP_D_IDX (1),
DEFINE_VFP_D_IDX (2),
DEFINE_VFP_D_IDX (3),
DEFINE_VFP_D_IDX (4),
DEFINE_VFP_D_IDX (5),
DEFINE_VFP_D_IDX (6),
DEFINE_VFP_D_IDX (7),
DEFINE_VFP_D_IDX (8),
DEFINE_VFP_D_IDX (9),
DEFINE_VFP_D_IDX (10),
DEFINE_VFP_D_IDX (11),
DEFINE_VFP_D_IDX (12),
DEFINE_VFP_D_IDX (13),
DEFINE_VFP_D_IDX (14),
DEFINE_VFP_D_IDX (15),
DEFINE_VFP_D_IDX (16),
DEFINE_VFP_D_IDX (17),
DEFINE_VFP_D_IDX (18),
@ -2535,7 +2631,7 @@ DNBArchMachARM::g_vfp_registers[] =
DEFINE_VFP_D_IDX (29),
DEFINE_VFP_D_IDX (30),
DEFINE_VFP_D_IDX (31),
{ e_regSetVFP, vfp_fpscr, "fpscr", NULL, Uint, 4, Hex, VFP_OFFSET_NAME(fpscr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, gdb_fpscr }
{ e_regSetVFP, vfp_fpscr, "fpscr", NULL, Uint, Hex, 4, VFP_OFFSET_NAME(fpscr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, gdb_fpscr }
};
// Exception registers
@ -2543,9 +2639,9 @@ DNBArchMachARM::g_vfp_registers[] =
const DNBRegisterInfo
DNBArchMachARM::g_exc_registers[] =
{
{ e_regSetVFP, exc_exception , "exception" , NULL, Uint, 4, Hex, EXC_OFFSET(exception) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM },
{ e_regSetVFP, exc_fsr , "fsr" , NULL, Uint, 4, Hex, EXC_OFFSET(fsr) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM },
{ e_regSetVFP, exc_far , "far" , NULL, Uint, 4, Hex, EXC_OFFSET(far) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM }
{ e_regSetVFP, exc_exception , "exception" , NULL, Uint, Hex, 4, EXC_OFFSET(exception) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM },
{ e_regSetVFP, exc_fsr , "fsr" , NULL, Uint, Hex, 4, EXC_OFFSET(fsr) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM },
{ e_regSetVFP, exc_far , "far" , NULL, Uint, Hex, 4, EXC_OFFSET(far) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM }
};
// Number of registers in each register set
@ -2633,12 +2729,20 @@ DNBArchMachARM::GetRegisterValue(int set, int reg, DNBRegisterValue *value)
break;
case e_regSetVFP:
if (reg < 32)
if (reg <= vfp_s31)
{
value->value.uint32 = m_state.context.vfp.__r[reg];
return true;
}
else if (reg == 32)
else if (reg <= vfp_d31)
{
uint32_t d_reg_idx = reg - vfp_d0;
uint32_t s_reg_idx = d_reg_idx * 2;
value->value.v_sint32[0] = m_state.context.vfp.__r[s_reg_idx + 0];
value->value.v_sint32[1] = m_state.context.vfp.__r[s_reg_idx + 1];
return true;
}
else if (reg == vfp_fpscr)
{
value->value.uint32 = m_state.context.vfp.__fpscr;
return true;
@ -2712,12 +2816,20 @@ DNBArchMachARM::SetRegisterValue(int set, int reg, const DNBRegisterValue *value
break;
case e_regSetVFP:
if (reg < 32)
if (reg <= vfp_s31)
{
m_state.context.vfp.__r[reg] = value->value.float64;
m_state.context.vfp.__r[reg] = value->value.uint32;
success = true;
}
else if (reg == 32)
else if (reg <= vfp_d31)
{
uint32_t d_reg_idx = reg - vfp_d0;
uint32_t s_reg_idx = d_reg_idx * 2;
m_state.context.vfp.__r[s_reg_idx + 0] = value->value.v_sint32[0];
m_state.context.vfp.__r[s_reg_idx + 1] = value->value.v_sint32[1];
success = true;
}
else if (reg == vfp_fpscr)
{
m_state.context.vfp.__fpscr = value->value.uint32;
success = true;

View File

@ -45,6 +45,7 @@ public:
{
}
static void Initialize();
static const DNBRegisterSetInfo *
GetRegisterSetInfo(nub_size_t *num_reg_sets);
@ -63,6 +64,7 @@ public:
virtual void ThreadWillResume();
virtual bool ThreadDidStop();
static DNBArchProtocol *Create (MachThread *thread);
static const uint8_t * const SoftwareBreakpointOpcode (nub_size_t byte_size);
static uint32_t GetCPUType();

View File

@ -842,7 +842,7 @@ g_gdb_register_map_arm[] =
{ 21, 12, "f5", {0}, k_zero_bytes, 0},
{ 22, 12, "f6", {0}, k_zero_bytes, 0},
{ 23, 12, "f7", {0}, k_zero_bytes, 0},
{ 24, 4, "fps", {0}, NULL, 0},
{ 24, 4, "fps", {0}, k_zero_bytes, 0},
{ 25, 4,"cpsr", {0}, NULL, 1},
{ 26, 4, "s0", {0}, NULL, 0},
{ 27, 4, "s1", {0}, NULL, 0},
@ -3351,30 +3351,3 @@ RNBRemote::HandlePacket_qHostInfo (const char *p)
strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
return SendPacket (strm.str());
}
rnb_err_t
RNBRemote::HandlePacket_qProcessInfo (const char *p)
{
return RNBRemote::HandlePacket_UNIMPLEMENTED (p);
}
rnb_err_t
RNBRemote::HandlePacket_qfProcessInfoAll (const char *p)
{
return RNBRemote::HandlePacket_UNIMPLEMENTED (p);
}
rnb_err_t
RNBRemote::HandlePacket_qfProcessInfoName (const char *p)
{
return RNBRemote::HandlePacket_UNIMPLEMENTED (p);
}
rnb_err_t
RNBRemote::HandlePacket_qsProcessInfo (const char *p)
{
return RNBRemote::HandlePacket_UNIMPLEMENTED (p);
}

View File

@ -91,10 +91,6 @@ public:
query_shlib_notify_info_addr, // 'qShlibInfoAddr'
query_step_packet_supported, // 'qStepPacketSupported'
query_host_info, // 'qHostInfo'
platform_proc_info_for_pid, // 'qProcessInfo:<PID>' -- get process info for process by ID
platform_proc_info_first_all, // 'qfProcessInfoAll' -- list all processes
platform_proc_info_first_name, // 'qfProcessInfoName:<HEXNAME>' -- list all processes that match "name"
platform_proc_info_subsequent, // 'qsProcessInfo' -- get subsequent matches for 'qfProcessInfo*' queries
pass_signals_to_inferior, // 'QPassSignals'
start_noack_mode, // 'QStartNoAckMode'
prefix_reg_packets_with_tid, // 'QPrefixRegisterPacketsWithThreadID
@ -165,10 +161,6 @@ public:
rnb_err_t HandlePacket_qThreadExtraInfo (const char *p);
rnb_err_t HandlePacket_qThreadStopInfo (const char *p);
rnb_err_t HandlePacket_qHostInfo (const char *p);
rnb_err_t HandlePacket_qProcessInfo (const char *p);
rnb_err_t HandlePacket_qfProcessInfoAll (const char *p);
rnb_err_t HandlePacket_qfProcessInfoName (const char *p);
rnb_err_t HandlePacket_qsProcessInfo (const char *p);
rnb_err_t HandlePacket_QStartNoAckMode (const char *p);
rnb_err_t HandlePacket_QThreadSuffixSupported (const char *p);
rnb_err_t HandlePacket_QSetLogging (const char *p);