Import lldb as of SVN r196259 (git 3be86e5)
(A number of files not required for the FreeBSD build have been removed.) Sponsored by: DARPA, AFRL
This commit is contained in:
parent
f21a844f60
commit
86758c7188
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/lldb/dist/; revision=258882 svn path=/vendor/lldb/lldb-r196259/; revision=258883; tag=vendor/lldb/lldb-r196259
@ -10,9 +10,11 @@
|
||||
#ifndef LLDB_SBDebugger_h_
|
||||
#define LLDB_SBDebugger_h_
|
||||
|
||||
#include "lldb/API/SBDefines.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lldb/API/SBDefines.h"
|
||||
#include "lldb/API/SBPlatform.h"
|
||||
|
||||
namespace lldb {
|
||||
|
||||
class SBDebugger
|
||||
@ -153,6 +155,12 @@ class SBDebugger
|
||||
void
|
||||
SetSelectedTarget (SBTarget& target);
|
||||
|
||||
lldb::SBPlatform
|
||||
GetSelectedPlatform();
|
||||
|
||||
void
|
||||
SetSelectedPlatform(lldb::SBPlatform &platform);
|
||||
|
||||
lldb::SBSourceManager
|
||||
GetSourceManager ();
|
||||
|
||||
|
@ -72,6 +72,7 @@ class SBError {
|
||||
friend class SBCommunication;
|
||||
friend class SBHostOS;
|
||||
friend class SBInputReader;
|
||||
friend class SBPlatform;
|
||||
friend class SBProcess;
|
||||
friend class SBThread;
|
||||
friend class SBTarget;
|
||||
|
@ -65,6 +65,12 @@ class SBExpressionOptions
|
||||
void
|
||||
SetTryAllThreads (bool run_others = true);
|
||||
|
||||
bool
|
||||
GetTrapExceptions () const;
|
||||
|
||||
void
|
||||
SetTrapExceptions (bool trap_exceptions = true);
|
||||
|
||||
protected:
|
||||
|
||||
SBExpressionOptions (lldb_private::EvaluateExpressionOptions &expression_options);
|
||||
|
@ -45,6 +45,12 @@ class SBFileSpec
|
||||
const char *
|
||||
GetDirectory() const;
|
||||
|
||||
void
|
||||
SetFilename(const char *filename);
|
||||
|
||||
void
|
||||
SetDirectory(const char *directory);
|
||||
|
||||
uint32_t
|
||||
GetPath (char *dst_path, size_t dst_len) const;
|
||||
|
||||
@ -65,6 +71,7 @@ class SBFileSpec
|
||||
friend class SBLineEntry;
|
||||
friend class SBModule;
|
||||
friend class SBModuleSpec;
|
||||
friend class SBPlatform;
|
||||
friend class SBProcess;
|
||||
friend class SBSourceManager;
|
||||
friend class SBThread;
|
||||
|
@ -76,6 +76,42 @@ class SBModule
|
||||
bool
|
||||
SetPlatformFileSpec (const lldb::SBFileSpec &platform_file);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get accessor for the remote install path for a module.
|
||||
///
|
||||
/// When debugging to a remote platform by connecting to a remote
|
||||
/// platform, the install path of the module can be set. If the
|
||||
/// install path is set, every time the process is about to launch
|
||||
/// the target will install this module on the remote platform prior
|
||||
/// to launching.
|
||||
///
|
||||
/// @return
|
||||
/// A file specification object.
|
||||
//------------------------------------------------------------------
|
||||
lldb::SBFileSpec
|
||||
GetRemoteInstallFileSpec ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Set accessor for the remote install path for a module.
|
||||
///
|
||||
/// When debugging to a remote platform by connecting to a remote
|
||||
/// platform, the install path of the module can be set. If the
|
||||
/// install path is set, every time the process is about to launch
|
||||
/// the target will install this module on the remote platform prior
|
||||
/// to launching.
|
||||
///
|
||||
/// If \a file specifies a full path to an install location, the
|
||||
/// module will be installed to this path. If the path is relative
|
||||
/// (no directory specified, or the path is partial like "usr/lib"
|
||||
/// or "./usr/lib", then the install path will be resolved using
|
||||
/// the platform's current working directory as the base path.
|
||||
///
|
||||
/// @param[in]
|
||||
/// A file specification object.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
SetRemoteInstallFileSpec (lldb::SBFileSpec &file);
|
||||
|
||||
lldb::ByteOrder
|
||||
GetByteOrder ();
|
||||
|
||||
|
198
include/lldb/API/SBPlatform.h
Normal file
198
include/lldb/API/SBPlatform.h
Normal file
@ -0,0 +1,198 @@
|
||||
//===-- SBPlatform.h --------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLDB_SBPlatform_h_
|
||||
#define LLDB_SBPlatform_h_
|
||||
|
||||
#include "lldb/API/SBDefines.h"
|
||||
|
||||
struct PlatformConnectOptions;
|
||||
struct PlatformShellCommand;
|
||||
|
||||
namespace lldb {
|
||||
|
||||
class SBPlatformConnectOptions
|
||||
{
|
||||
public:
|
||||
SBPlatformConnectOptions (const char *url);
|
||||
|
||||
SBPlatformConnectOptions (const SBPlatformConnectOptions &rhs);
|
||||
|
||||
~SBPlatformConnectOptions ();
|
||||
|
||||
void
|
||||
operator=(const SBPlatformConnectOptions &rhs);
|
||||
|
||||
const char *
|
||||
GetURL();
|
||||
|
||||
void
|
||||
SetURL(const char *url);
|
||||
|
||||
bool
|
||||
GetRsyncEnabled();
|
||||
|
||||
void
|
||||
EnableRsync (const char *options,
|
||||
const char *remote_path_prefix,
|
||||
bool omit_remote_hostname);
|
||||
|
||||
void
|
||||
DisableRsync ();
|
||||
|
||||
const char *
|
||||
GetLocalCacheDirectory();
|
||||
|
||||
void
|
||||
SetLocalCacheDirectory(const char *path);
|
||||
protected:
|
||||
PlatformConnectOptions *m_opaque_ptr;
|
||||
};
|
||||
|
||||
class SBPlatformShellCommand
|
||||
{
|
||||
public:
|
||||
SBPlatformShellCommand (const char *shell_command);
|
||||
|
||||
SBPlatformShellCommand (const SBPlatformShellCommand &rhs);
|
||||
|
||||
~SBPlatformShellCommand();
|
||||
|
||||
void
|
||||
Clear();
|
||||
|
||||
const char *
|
||||
GetCommand();
|
||||
|
||||
void
|
||||
SetCommand(const char *shell_command);
|
||||
|
||||
const char *
|
||||
GetWorkingDirectory ();
|
||||
|
||||
void
|
||||
SetWorkingDirectory (const char *path);
|
||||
|
||||
uint32_t
|
||||
GetTimeoutSeconds ();
|
||||
|
||||
void
|
||||
SetTimeoutSeconds (uint32_t sec);
|
||||
|
||||
int
|
||||
GetSignal ();
|
||||
|
||||
int
|
||||
GetStatus ();
|
||||
|
||||
const char *
|
||||
GetOutput ();
|
||||
|
||||
protected:
|
||||
friend class SBPlatform;
|
||||
|
||||
PlatformShellCommand *m_opaque_ptr;
|
||||
};
|
||||
|
||||
class SBPlatform
|
||||
{
|
||||
public:
|
||||
|
||||
SBPlatform ();
|
||||
|
||||
SBPlatform (const char *platform_name);
|
||||
|
||||
~SBPlatform();
|
||||
|
||||
bool
|
||||
IsValid () const;
|
||||
|
||||
void
|
||||
Clear ();
|
||||
|
||||
const char *
|
||||
GetWorkingDirectory();
|
||||
|
||||
bool
|
||||
SetWorkingDirectory(const char *path);
|
||||
|
||||
const char *
|
||||
GetName ();
|
||||
|
||||
SBError
|
||||
ConnectRemote (SBPlatformConnectOptions &connect_options);
|
||||
|
||||
void
|
||||
DisconnectRemote ();
|
||||
|
||||
bool
|
||||
IsConnected();
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// The following functions will work if the platform is connected
|
||||
//----------------------------------------------------------------------
|
||||
const char *
|
||||
GetTriple();
|
||||
|
||||
const char *
|
||||
GetHostname ();
|
||||
|
||||
const char *
|
||||
GetOSBuild ();
|
||||
|
||||
const char *
|
||||
GetOSDescription ();
|
||||
|
||||
uint32_t
|
||||
GetOSMajorVersion ();
|
||||
|
||||
uint32_t
|
||||
GetOSMinorVersion ();
|
||||
|
||||
uint32_t
|
||||
GetOSUpdateVersion ();
|
||||
|
||||
SBError
|
||||
Put (SBFileSpec &src, SBFileSpec &dst);
|
||||
|
||||
SBError
|
||||
Get (SBFileSpec &src, SBFileSpec &dst);
|
||||
|
||||
SBError
|
||||
Install (SBFileSpec& src, SBFileSpec& dst);
|
||||
|
||||
SBError
|
||||
Run (SBPlatformShellCommand &shell_command);
|
||||
|
||||
SBError
|
||||
MakeDirectory (const char *path, uint32_t file_permissions = eFilePermissionsDirectoryDefault);
|
||||
|
||||
uint32_t
|
||||
GetFilePermissions (const char *path);
|
||||
|
||||
SBError
|
||||
SetFilePermissions (const char *path, uint32_t file_permissions);
|
||||
|
||||
protected:
|
||||
|
||||
friend class SBDebugger;
|
||||
friend class SBTarget;
|
||||
|
||||
lldb::PlatformSP
|
||||
GetSP () const;
|
||||
|
||||
void
|
||||
SetSP (const lldb::PlatformSP& platform_sp);
|
||||
|
||||
lldb::PlatformSP m_opaque_sp;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBPlatform_h_
|
@ -267,6 +267,23 @@ class SBTarget
|
||||
lldb::SBProcess
|
||||
GetProcess ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Install any binaries that need to be installed.
|
||||
///
|
||||
/// This function does nothing when debugging on the host system.
|
||||
/// When connected to remote platforms, the target's main executable
|
||||
/// and any modules that have their remote install path set will be
|
||||
/// installed on the remote platform. If the main executable doesn't
|
||||
/// have an install location set, it will be installed in the remote
|
||||
/// platform's working directory.
|
||||
///
|
||||
/// @return
|
||||
/// An error describing anything that went wrong during
|
||||
/// installation.
|
||||
//------------------------------------------------------------------
|
||||
SBError
|
||||
Install();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Launch a new process.
|
||||
///
|
||||
|
@ -202,7 +202,10 @@ class SBThread
|
||||
GetStatus (lldb::SBStream &status) const;
|
||||
|
||||
SBThread
|
||||
GetExtendedBacktrace (const char *type);
|
||||
GetExtendedBacktraceThread (const char *type);
|
||||
|
||||
uint32_t
|
||||
GetExtendedBacktraceOriginatingIndexID ();
|
||||
|
||||
protected:
|
||||
friend class SBBreakpoint;
|
||||
|
@ -311,6 +311,24 @@ class Breakpoint:
|
||||
//------------------------------------------------------------------
|
||||
lldb::BreakpointLocationSP
|
||||
GetLocationAtIndex (size_t index);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Removes all invalid breakpoint locations.
|
||||
///
|
||||
/// Removes all breakpoint locations with architectures that aren't
|
||||
/// compatible with \a arch. Also remove any breakpoint locations
|
||||
/// with whose locations have address where the section has been
|
||||
/// deleted (module and object files no longer exist).
|
||||
///
|
||||
/// This is typically used after the process calls exec, or anytime
|
||||
/// the architecture of the target changes.
|
||||
///
|
||||
/// @param[in] arch
|
||||
/// If valid, check the module in each breakpoint to make sure
|
||||
/// they are compatible, otherwise, ignore architecture.
|
||||
//------------------------------------------------------------------
|
||||
void
|
||||
RemoveInvalidLocations (const ArchSpec &arch);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// The next section deals with various breakpoint options.
|
||||
|
@ -132,6 +132,25 @@ class BreakpointList
|
||||
bool
|
||||
Remove (lldb::break_id_t breakID, bool notify);
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Removes all invalid breakpoint locations.
|
||||
///
|
||||
/// Removes all breakpoint locations in the list with architectures
|
||||
/// that aren't compatible with \a arch. Also remove any breakpoint
|
||||
/// locations with whose locations have address where the section
|
||||
/// has been deleted (module and object files no longer exist).
|
||||
///
|
||||
/// This is typically used after the process calls exec, or anytime
|
||||
/// the architecture of the target changes.
|
||||
///
|
||||
/// @param[in] arch
|
||||
/// If valid, check the module in each breakpoint to make sure
|
||||
/// they are compatible, otherwise, ignore architecture.
|
||||
//------------------------------------------------------------------
|
||||
void
|
||||
RemoveInvalidLocations (const ArchSpec &arch);
|
||||
|
||||
void
|
||||
SetEnabledAll (bool enabled);
|
||||
|
||||
|
@ -250,6 +250,9 @@ friend class Breakpoint;
|
||||
|
||||
bool
|
||||
RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp);
|
||||
|
||||
void
|
||||
RemoveInvalidLocations (const ArchSpec &arch);
|
||||
|
||||
typedef std::vector<lldb::BreakpointLocationSP> collection;
|
||||
typedef std::map<lldb_private::Address,
|
||||
@ -257,7 +260,7 @@ friend class Breakpoint;
|
||||
Address::ModulePointerAndOffsetLessThanFunctionObject> addr_map;
|
||||
|
||||
Breakpoint &m_owner;
|
||||
collection m_locations;
|
||||
collection m_locations; // Vector of locations, sorted by ID
|
||||
addr_map m_address_to_location;
|
||||
mutable Mutex m_mutex;
|
||||
lldb::break_id_t m_next_id;
|
||||
|
@ -534,6 +534,16 @@ class Address
|
||||
bool
|
||||
CalculateSymbolContextLineEntry (LineEntry &line_entry) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Returns true if the section should be valid, but isn't because
|
||||
// the shared pointer to the section can't be reconstructed from
|
||||
// a weak pointer that contains a valid weak reference to a section.
|
||||
// Returns false if the section weak pointer has no reference to
|
||||
// a section, or if the section is still valid
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
SectionWasDeleted() const;
|
||||
|
||||
protected:
|
||||
//------------------------------------------------------------------
|
||||
// Member variables.
|
||||
@ -550,7 +560,7 @@ class Address
|
||||
// have a valid section.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
SectionWasDeleted() const;
|
||||
SectionWasDeletedPrivate() const;
|
||||
|
||||
};
|
||||
|
||||
|
@ -17,9 +17,6 @@
|
||||
#include <stack>
|
||||
|
||||
#include "lldb/lldb-public.h"
|
||||
|
||||
#include "lldb/API/SBDefines.h"
|
||||
|
||||
#include "lldb/Core/Broadcaster.h"
|
||||
#include "lldb/Core/Communication.h"
|
||||
#include "lldb/Core/InputReaderStack.h"
|
||||
@ -55,6 +52,10 @@ friend class SourceManager; // For GetSourceFileCache.
|
||||
|
||||
public:
|
||||
|
||||
typedef lldb::DynamicLibrarySP (*LoadPluginCallbackType) (const lldb::DebuggerSP &debugger_sp,
|
||||
const FileSpec& spec,
|
||||
Error& error);
|
||||
|
||||
static lldb::DebuggerSP
|
||||
CreateInstance (lldb::LogOutputCallback log_callback = NULL, void *baton = NULL);
|
||||
|
||||
@ -65,7 +66,7 @@ friend class SourceManager; // For GetSourceFileCache.
|
||||
FindTargetWithProcess (Process *process);
|
||||
|
||||
static void
|
||||
Initialize ();
|
||||
Initialize (LoadPluginCallbackType load_plugin_callback);
|
||||
|
||||
static void
|
||||
Terminate ();
|
||||
@ -333,9 +334,7 @@ friend class SourceManager; // For GetSourceFileCache.
|
||||
{
|
||||
return m_instance_name;
|
||||
}
|
||||
|
||||
typedef bool (*LLDBCommandPluginInit) (lldb::SBDebugger& debugger);
|
||||
|
||||
|
||||
bool
|
||||
LoadPlugin (const FileSpec& spec, Error& error);
|
||||
|
||||
@ -377,6 +376,7 @@ friend class SourceManager; // For GetSourceFileCache.
|
||||
LogStreamMap m_log_streams;
|
||||
lldb::StreamSP m_log_callback_stream_sp;
|
||||
ConstString m_instance_name;
|
||||
static LoadPluginCallbackType g_load_plugin_callback;
|
||||
typedef std::vector<lldb::DynamicLibrarySP> LoadedPluginsList;
|
||||
LoadedPluginsList m_loaded_plugins;
|
||||
|
||||
|
@ -569,6 +569,18 @@ class Module :
|
||||
m_platform_file = file;
|
||||
}
|
||||
|
||||
const FileSpec &
|
||||
GetRemoteInstallFileSpec () const
|
||||
{
|
||||
return m_remote_install_file;
|
||||
}
|
||||
|
||||
void
|
||||
SetRemoteInstallFileSpec (const FileSpec &file)
|
||||
{
|
||||
m_remote_install_file = file;
|
||||
}
|
||||
|
||||
const FileSpec &
|
||||
GetSymbolFileFileSpec () const
|
||||
{
|
||||
@ -1059,6 +1071,7 @@ class 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
|
||||
FileSpec m_remote_install_file; ///< If set when debugging on remote platforms, this module will be installed at this location
|
||||
FileSpec m_symfile_spec; ///< If this path is valid, then this is the file that _will_ be used as the symbol file for this module
|
||||
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.
|
||||
uint64_t m_object_offset;
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
#include "lldb/Core/ConstString.h"
|
||||
#include "lldb/DataFormatters/FormatClasses.h"
|
||||
#include "lldb/DataFormatters/TypeSynthetic.h"
|
||||
#include "lldb/Target/ExecutionContext.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
|
@ -18,6 +18,7 @@
|
||||
// Project includes
|
||||
#include "lldb/lldb-public.h"
|
||||
#include "lldb/Core/ConstString.h"
|
||||
#include "lldb/Host/Mutex.h"
|
||||
#include "lldb/DataFormatters/FormatClasses.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
@ -10,9 +10,6 @@
|
||||
#ifndef lldb_FormatClasses_h_
|
||||
#define lldb_FormatClasses_h_
|
||||
|
||||
// C Includes
|
||||
#include <stdint.h>
|
||||
|
||||
// C++ Includes
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -23,17 +20,86 @@
|
||||
#include "lldb/lldb-public.h"
|
||||
#include "lldb/lldb-enumerations.h"
|
||||
|
||||
#include "lldb/Core/ValueObject.h"
|
||||
#include "lldb/Interpreter/ScriptInterpreterPython.h"
|
||||
#include "lldb/Symbol/ClangASTType.h"
|
||||
#include "lldb/Symbol/Type.h"
|
||||
|
||||
#include "lldb/DataFormatters/TypeFormat.h"
|
||||
#include "lldb/DataFormatters/TypeSummary.h"
|
||||
#include "lldb/DataFormatters/TypeSynthetic.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
class FormattersMatchCandidate
|
||||
{
|
||||
public:
|
||||
|
||||
FormattersMatchCandidate (ConstString name,
|
||||
uint32_t reason,
|
||||
bool strip_ptr,
|
||||
bool strip_ref,
|
||||
bool strip_tydef) :
|
||||
m_type_name(name),
|
||||
m_reason(reason),
|
||||
m_stripped_pointer(strip_ptr),
|
||||
m_stripped_reference(strip_ref),
|
||||
m_stripped_typedef(strip_tydef)
|
||||
{
|
||||
}
|
||||
|
||||
~FormattersMatchCandidate ()
|
||||
{}
|
||||
|
||||
ConstString
|
||||
GetTypeName () const
|
||||
{
|
||||
return m_type_name;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetReason () const
|
||||
{
|
||||
return m_reason;
|
||||
}
|
||||
|
||||
bool
|
||||
DidStripPointer () const
|
||||
{
|
||||
return m_stripped_pointer;
|
||||
}
|
||||
|
||||
bool
|
||||
DidStripReference () const
|
||||
{
|
||||
return m_stripped_reference;
|
||||
}
|
||||
|
||||
bool
|
||||
DidStripTypedef () const
|
||||
{
|
||||
return m_stripped_typedef;
|
||||
}
|
||||
|
||||
template <class Formatter>
|
||||
bool
|
||||
IsMatch (const std::shared_ptr<Formatter>& formatter_sp) const
|
||||
{
|
||||
if (!formatter_sp)
|
||||
return false;
|
||||
if (formatter_sp->Cascades() == false && DidStripTypedef())
|
||||
return false;
|
||||
if (formatter_sp->SkipsPointers() && DidStripPointer())
|
||||
return false;
|
||||
if (formatter_sp->SkipsReferences() && DidStripReference())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
ConstString m_type_name;
|
||||
uint32_t m_reason;
|
||||
bool m_stripped_pointer;
|
||||
bool m_stripped_reference;
|
||||
bool m_stripped_typedef;
|
||||
};
|
||||
|
||||
typedef std::vector<FormattersMatchCandidate> FormattersMatchVector;
|
||||
|
||||
class TypeNameSpecifierImpl
|
||||
{
|
||||
public:
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "lldb/lldb-enumerations.h"
|
||||
|
||||
#include "lldb/DataFormatters/FormatCache.h"
|
||||
#include "lldb/DataFormatters/FormatClasses.h"
|
||||
#include "lldb/DataFormatters/FormatNavigator.h"
|
||||
#include "lldb/DataFormatters/TypeCategory.h"
|
||||
#include "lldb/DataFormatters/TypeCategoryMap.h"
|
||||
@ -213,7 +214,36 @@ class FormatManager : public IFormatChangeListener
|
||||
{
|
||||
}
|
||||
|
||||
static FormattersMatchVector
|
||||
GetPossibleMatches (ValueObject& valobj,
|
||||
lldb::DynamicValueType use_dynamic)
|
||||
{
|
||||
FormattersMatchVector matches;
|
||||
GetPossibleMatches (valobj,
|
||||
valobj.GetClangType(),
|
||||
lldb_private::eFormatterChoiceCriterionDirectChoice,
|
||||
use_dynamic,
|
||||
matches,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true);
|
||||
return matches;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static void
|
||||
GetPossibleMatches (ValueObject& valobj,
|
||||
ClangASTType clang_type,
|
||||
uint32_t reason,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
FormattersMatchVector& entries,
|
||||
bool did_strip_ptr,
|
||||
bool did_strip_ref,
|
||||
bool did_strip_typedef,
|
||||
bool root_level = false);
|
||||
|
||||
FormatCache m_format_cache;
|
||||
NamedSummariesMap m_named_summaries_map;
|
||||
std::atomic<uint32_t> m_last_revision;
|
||||
|
@ -26,6 +26,9 @@
|
||||
#include "lldb/Core/ValueObject.h"
|
||||
|
||||
#include "lldb/DataFormatters/FormatClasses.h"
|
||||
#include "lldb/DataFormatters/TypeFormat.h"
|
||||
#include "lldb/DataFormatters/TypeSummary.h"
|
||||
#include "lldb/DataFormatters/TypeSynthetic.h"
|
||||
|
||||
#include "lldb/Symbol/ClangASTContext.h"
|
||||
#include "lldb/Symbol/ClangASTType.h"
|
||||
@ -459,228 +462,29 @@ class FormatNavigator
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Get_BitfieldMatch (ValueObject& valobj,
|
||||
ConstString typeName,
|
||||
MapValueType& entry,
|
||||
uint32_t& reason)
|
||||
{
|
||||
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
|
||||
// for bitfields, append size to the typename so one can custom format them
|
||||
StreamString sstring;
|
||||
sstring.Printf("%s:%d",typeName.AsCString(),valobj.GetBitfieldBitSize());
|
||||
ConstString bitfieldname = ConstString(sstring.GetData());
|
||||
if (log)
|
||||
log->Printf("[Get_BitfieldMatch] appended bitfield info, final result is %s", bitfieldname.GetCString());
|
||||
if (Get(bitfieldname, entry))
|
||||
{
|
||||
if (log)
|
||||
log->Printf("[Get_BitfieldMatch] bitfield direct match found, returning");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField;
|
||||
if (log)
|
||||
log->Printf("[Get_BitfieldMatch] no bitfield direct match");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Get_ObjC (ValueObject& valobj,
|
||||
MapValueType& entry)
|
||||
{
|
||||
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
|
||||
lldb::ProcessSP process_sp = valobj.GetProcessSP();
|
||||
ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime();
|
||||
if (runtime == NULL)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("[Get_ObjC] no valid ObjC runtime, skipping dynamic");
|
||||
return false;
|
||||
}
|
||||
ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj));
|
||||
if (!objc_class_sp)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("[Get_ObjC] invalid ISA, skipping dynamic");
|
||||
return false;
|
||||
}
|
||||
ConstString name (objc_class_sp->GetClassName());
|
||||
if (log)
|
||||
log->Printf("[Get_ObjC] dynamic type inferred is %s - looking for direct dynamic match", name.GetCString());
|
||||
if (Get(name, entry))
|
||||
{
|
||||
if (log)
|
||||
log->Printf("[Get_ObjC] direct dynamic match found, returning");
|
||||
return true;
|
||||
}
|
||||
if (log)
|
||||
log->Printf("[Get_ObjC] no dynamic match");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Get_Impl (ValueObject& valobj,
|
||||
ClangASTType clang_type,
|
||||
MapValueType& entry,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
uint32_t& reason)
|
||||
{
|
||||
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
|
||||
|
||||
if (!clang_type.IsValid())
|
||||
bool
|
||||
Get (const FormattersMatchVector& candidates,
|
||||
MapValueType& entry,
|
||||
uint32_t *reason)
|
||||
{
|
||||
for (const FormattersMatchCandidate& candidate : candidates)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("[Get_Impl] type is invalid, returning");
|
||||
return false;
|
||||
}
|
||||
|
||||
clang_type = clang_type.RemoveFastQualifiers();
|
||||
|
||||
ConstString typeName(clang_type.GetConstTypeName());
|
||||
|
||||
if (valobj.GetBitfieldBitSize() > 0)
|
||||
{
|
||||
if (Get_BitfieldMatch(valobj, typeName, entry, reason))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (log)
|
||||
log->Printf("[Get_Impl] trying to get %s for VO name %s of type %s",
|
||||
m_name.c_str(),
|
||||
valobj.GetName().AsCString(),
|
||||
typeName.AsCString());
|
||||
|
||||
if (Get(typeName, entry))
|
||||
{
|
||||
if (log)
|
||||
log->Printf("[Get] direct match found, returning");
|
||||
return true;
|
||||
}
|
||||
if (log)
|
||||
log->Printf("[Get_Impl] no direct match");
|
||||
|
||||
// strip pointers and references and see if that helps
|
||||
if (clang_type.IsReferenceType())
|
||||
{
|
||||
if (log)
|
||||
log->Printf("[Get_Impl] stripping reference");
|
||||
if (Get_Impl(valobj, clang_type.GetNonReferenceType(), entry, use_dynamic, reason) && !entry->SkipsReferences())
|
||||
if (Get(candidate.GetTypeName(),entry))
|
||||
{
|
||||
reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (clang_type.IsPointerType())
|
||||
{
|
||||
if (log)
|
||||
log->Printf("[Get_Impl] stripping pointer");
|
||||
if (Get_Impl(valobj, clang_type.GetPointeeType(), entry, use_dynamic, reason) && !entry->SkipsPointers())
|
||||
{
|
||||
reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool canBeObjCDynamic = valobj.GetClangType().IsPossibleDynamicType (NULL,
|
||||
false, // no C++
|
||||
true); // yes ObjC
|
||||
|
||||
if (canBeObjCDynamic)
|
||||
{
|
||||
if (use_dynamic != lldb::eNoDynamicValues)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("[Get_Impl] allowed to figure out dynamic ObjC type");
|
||||
if (Get_ObjC(valobj,entry))
|
||||
if (candidate.IsMatch(entry) == false)
|
||||
{
|
||||
reason |= lldb_private::eFormatterChoiceCriterionDynamicObjCDiscovery;
|
||||
return true;
|
||||
entry.reset();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (log)
|
||||
log->Printf("[Get_Impl] dynamic disabled or failed - stripping ObjC pointer");
|
||||
if (Get_Impl(valobj, clang_type.GetPointeeType(), entry, use_dynamic, reason) && !entry->SkipsPointers())
|
||||
{
|
||||
reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// try to strip typedef chains
|
||||
if (clang_type.IsTypedefType())
|
||||
{
|
||||
if (log)
|
||||
log->Printf("[Get_Impl] stripping typedef");
|
||||
if ((Get_Impl(valobj, clang_type.GetTypedefedType(), entry, use_dynamic, reason)) && entry->Cascades())
|
||||
{
|
||||
reason |= lldb_private::eFormatterChoiceCriterionNavigatedTypedefs;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// out of luck here
|
||||
return false;
|
||||
}
|
||||
|
||||
// we are separately passing in valobj and type because the valobj is fixed (and is used for ObjC discovery and bitfield size)
|
||||
// but the type can change (e.g. stripping pointers, ...)
|
||||
bool Get (ValueObject& valobj,
|
||||
ClangASTType clang_type,
|
||||
MapValueType& entry,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
uint32_t& reason)
|
||||
{
|
||||
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
|
||||
|
||||
if (Get_Impl (valobj, clang_type, entry, use_dynamic, reason))
|
||||
return true;
|
||||
|
||||
// try going to the unqualified type
|
||||
do {
|
||||
if (log)
|
||||
log->Printf("[Get] trying the unqualified type");
|
||||
if (!clang_type.IsValid())
|
||||
break;
|
||||
|
||||
ClangASTType unqual_clang_ast_type = clang_type.GetFullyUnqualifiedType();
|
||||
if (!unqual_clang_ast_type.IsValid())
|
||||
{
|
||||
if (log)
|
||||
log->Printf("[Get] could not get the unqual_clang_ast_type");
|
||||
break;
|
||||
}
|
||||
if (unqual_clang_ast_type.GetOpaqueQualType() != clang_type.GetOpaqueQualType())
|
||||
{
|
||||
if (log)
|
||||
log->Printf("[Get] unqualified type is there and is not the same, let's try");
|
||||
if (Get_Impl (valobj, unqual_clang_ast_type,entry, use_dynamic, reason))
|
||||
return true;
|
||||
}
|
||||
else if (log)
|
||||
log->Printf("[Get] unqualified type same as original type");
|
||||
} while(false);
|
||||
|
||||
// if all else fails, go to static type
|
||||
if (valobj.IsDynamic())
|
||||
{
|
||||
if (log)
|
||||
log->Printf("[Get] going to static value");
|
||||
lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue());
|
||||
if (static_value_sp)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("[Get] has a static value - actually use it");
|
||||
if (Get(*static_value_sp.get(), static_value_sp->GetClangType(), entry, use_dynamic, reason))
|
||||
else
|
||||
{
|
||||
reason |= lldb_private::eFormatterChoiceCriterionWentToStaticValue;
|
||||
if(reason)
|
||||
*reason = candidate.GetReason();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "lldb/lldb-public.h"
|
||||
#include "lldb/lldb-enumerations.h"
|
||||
|
||||
#include "lldb/DataFormatters/FormatClasses.h"
|
||||
#include "lldb/DataFormatters/FormatNavigator.h"
|
||||
|
||||
namespace lldb_private {
|
||||
@ -177,23 +178,22 @@ namespace lldb_private {
|
||||
return m_enabled_position;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Get (ValueObject& valobj,
|
||||
const FormattersMatchVector& candidates,
|
||||
lldb::TypeFormatImplSP& entry,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
uint32_t* reason = NULL);
|
||||
|
||||
bool
|
||||
Get (ValueObject& valobj,
|
||||
const FormattersMatchVector& candidates,
|
||||
lldb::TypeSummaryImplSP& entry,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
uint32_t* reason = NULL);
|
||||
|
||||
bool
|
||||
Get (ValueObject& valobj,
|
||||
const FormattersMatchVector& candidates,
|
||||
lldb::SyntheticChildrenSP& entry,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
uint32_t* reason = NULL);
|
||||
|
||||
void
|
||||
|
@ -226,143 +226,6 @@ class ClangFunction : public ClangExpression
|
||||
ValueList &arg_values,
|
||||
Stream &errors);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// [Static] Execute a function, passing it a single void* parameter.
|
||||
/// ClangFunction uses this to call the wrapper function.
|
||||
///
|
||||
/// @param[in] exe_ctx
|
||||
/// The execution context to insert the function and its arguments
|
||||
/// into.
|
||||
///
|
||||
/// @param[in] function_address
|
||||
/// The address of the function in the target process.
|
||||
///
|
||||
/// @param[in] void_arg
|
||||
/// The value of the void* parameter.
|
||||
///
|
||||
/// @param[in] stop_others
|
||||
/// True if other threads should pause during execution.
|
||||
///
|
||||
/// @param[in] try_all_threads
|
||||
/// If the timeout expires, true if other threads should run. If
|
||||
/// the function may try to take locks, this is useful.
|
||||
///
|
||||
/// @param[in] unwind_on_error
|
||||
/// If true, and the execution stops before completion, we unwind the
|
||||
/// function call, and return the program state to what it was before the
|
||||
/// execution. If false, we leave the program in the stopped state.
|
||||
///
|
||||
/// @param[in] timeout_usec
|
||||
/// Timeout value (0 for no timeout). If try_all_threads is true, then we
|
||||
/// will try on one thread for the lesser of .25 sec and half the total timeout.
|
||||
/// then switch to running all threads, otherwise this will be the total timeout.
|
||||
///
|
||||
/// @param[in] errors
|
||||
/// The stream to write errors to.
|
||||
///
|
||||
/// @param[in] this_arg
|
||||
/// If non-NULL, the function is invoked like a C++ method, with the
|
||||
/// value pointed to by the pointer as its 'this' argument.
|
||||
///
|
||||
/// @return
|
||||
/// Returns one of the ExecutionResults enum indicating function call status.
|
||||
//------------------------------------------------------------------
|
||||
static ExecutionResults
|
||||
ExecuteFunction (ExecutionContext &exe_ctx,
|
||||
lldb::addr_t function_address,
|
||||
lldb::addr_t &void_arg,
|
||||
bool stop_others,
|
||||
bool try_all_threads,
|
||||
bool unwind_on_error,
|
||||
bool ignore_breakpoints,
|
||||
uint32_t timeout_usec,
|
||||
Stream &errors,
|
||||
lldb::addr_t* this_arg = 0);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Run the function this ClangFunction was created with.
|
||||
///
|
||||
/// This simple version will run the function stopping other threads
|
||||
/// for a fixed timeout period (1000 usec) and if it does not complete,
|
||||
/// we halt the process and try with all threads running.
|
||||
///
|
||||
/// @param[in] exe_ctx
|
||||
/// The thread & process in which this function will run.
|
||||
///
|
||||
/// @param[in] errors
|
||||
/// Errors will be written here if there are any.
|
||||
///
|
||||
/// @param[out] results
|
||||
/// The result value will be put here after running the function.
|
||||
///
|
||||
/// @return
|
||||
/// Returns one of the ExecutionResults enum indicating function call status.
|
||||
//------------------------------------------------------------------
|
||||
ExecutionResults
|
||||
ExecuteFunction(ExecutionContext &exe_ctx,
|
||||
Stream &errors,
|
||||
Value &results);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Run the function this ClangFunction was created with.
|
||||
///
|
||||
/// This simple version will run the function obeying the stop_others
|
||||
/// argument. There is no timeout.
|
||||
///
|
||||
/// @param[in] exe_ctx
|
||||
/// The thread & process in which this function will run.
|
||||
///
|
||||
/// @param[in] errors
|
||||
/// Errors will be written here if there are any.
|
||||
///
|
||||
/// @param[in] stop_others
|
||||
/// If \b true, run only this thread, if \b false let all threads run.
|
||||
///
|
||||
/// @param[out] results
|
||||
/// The result value will be put here after running the function.
|
||||
///
|
||||
/// @return
|
||||
/// Returns one of the ExecutionResults enum indicating function call status.
|
||||
//------------------------------------------------------------------
|
||||
ExecutionResults
|
||||
ExecuteFunction(ExecutionContext &exe_ctx,
|
||||
Stream &errors, bool stop_others,
|
||||
Value &results);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Run the function this ClangFunction was created with.
|
||||
///
|
||||
/// This simple version will run the function on one thread. If \a timeout_usec
|
||||
/// is not zero, we time out after that timeout. If \a try_all_threads is true, then we will
|
||||
/// resume with all threads on, otherwise we halt the process, and eExecutionInterrupted will be returned.
|
||||
///
|
||||
/// @param[in] exe_ctx
|
||||
/// The thread & process in which this function will run.
|
||||
///
|
||||
/// @param[in] errors
|
||||
/// Errors will be written here if there are any.
|
||||
///
|
||||
/// @param[in] timeout_usec
|
||||
/// Timeout value (0 for no timeout). If try_all_threads is true, then we
|
||||
/// will try on one thread for the lesser of .25 sec and half the total timeout.
|
||||
/// then switch to running all threads, otherwise this will be the total timeout.
|
||||
///
|
||||
/// @param[in] try_all_threads
|
||||
/// If \b true, run only this thread, if \b false let all threads run.
|
||||
///
|
||||
/// @param[out] results
|
||||
/// The result value will be put here after running the function.
|
||||
///
|
||||
/// @return
|
||||
/// Returns one of the ExecutionResults enum indicating function call status.
|
||||
//------------------------------------------------------------------
|
||||
ExecutionResults
|
||||
ExecuteFunction(ExecutionContext &exe_ctx,
|
||||
Stream &errors,
|
||||
uint32_t single_thread_timeout_usec,
|
||||
bool try_all_threads,
|
||||
Value &results);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Run the function this ClangFunction was created with.
|
||||
///
|
||||
@ -381,17 +244,8 @@ class ClangFunction : public ClangExpression
|
||||
/// @param[in] errors
|
||||
/// Errors will be written here if there are any.
|
||||
///
|
||||
/// @param[in] stop_others
|
||||
/// If \b true, run only this thread, if \b false let all threads run.
|
||||
///
|
||||
/// @param[in] timeout_usec
|
||||
/// Timeout value (0 for no timeout). If try_all_threads is true, then we
|
||||
/// will try on one thread for the lesser of .25 sec and half the total timeout.
|
||||
/// then switch to running all threads, otherwise this will be the total timeout.
|
||||
///
|
||||
///
|
||||
/// @param[in] try_all_threads
|
||||
/// If \b true, run only this thread, if \b false let all threads run.
|
||||
/// @param[in] options
|
||||
/// The options for this expression execution.
|
||||
///
|
||||
/// @param[out] results
|
||||
/// The result value will be put here after running the function.
|
||||
@ -402,62 +256,10 @@ class ClangFunction : public ClangExpression
|
||||
ExecutionResults
|
||||
ExecuteFunction(ExecutionContext &exe_ctx,
|
||||
lldb::addr_t *args_addr_ptr,
|
||||
Stream &errors,
|
||||
bool stop_others,
|
||||
uint32_t timeout_usec,
|
||||
bool try_all_threads,
|
||||
bool unwind_on_error,
|
||||
bool ignore_breakpoints,
|
||||
const EvaluateExpressionOptions &options,
|
||||
Stream &errors,
|
||||
Value &results);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// [static] Get a thread plan to run a function.
|
||||
///
|
||||
/// @param[in] exe_ctx
|
||||
/// The execution context to insert the function and its arguments
|
||||
/// into.
|
||||
///
|
||||
/// @param[in] func_addr
|
||||
/// The address of the function in the target process.
|
||||
///
|
||||
/// @param[in] args_addr_ref
|
||||
/// The value of the void* parameter.
|
||||
///
|
||||
/// @param[in] errors
|
||||
/// The stream to write errors to.
|
||||
///
|
||||
/// @param[in] stop_others
|
||||
/// True if other threads should pause during execution.
|
||||
///
|
||||
/// @param[in] unwind_on_error
|
||||
/// True if the thread plan may simply be discarded if an error occurs.
|
||||
///
|
||||
/// @param[in] ignore_breakpoints
|
||||
/// True if the expression execution will ignore breakpoint hits and continue executing.
|
||||
///
|
||||
/// @param[in] this_arg
|
||||
/// If non-NULL (and cmd_arg is NULL), the function is invoked like a C++
|
||||
/// method, with the value pointed to by the pointer as its 'this'
|
||||
/// argument.
|
||||
///
|
||||
/// @param[in] cmd_arg
|
||||
/// If non-NULL, the function is invoked like an Objective-C method, with
|
||||
/// this_arg in the 'self' slot and cmd_arg in the '_cmd' slot
|
||||
///
|
||||
/// @return
|
||||
/// A ThreadPlan for executing the function.
|
||||
//------------------------------------------------------------------
|
||||
static ThreadPlan *
|
||||
GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
|
||||
lldb::addr_t func_addr,
|
||||
lldb::addr_t &args_addr_ref,
|
||||
Stream &errors,
|
||||
bool stop_others,
|
||||
bool unwind_on_error,
|
||||
bool ignore_breakpoints,
|
||||
lldb::addr_t *this_arg = 0,
|
||||
lldb::addr_t *cmd_arg = 0);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get a thread plan to run the function this ClangFunction was created with.
|
||||
///
|
||||
@ -468,8 +270,8 @@ class ClangFunction : public ClangExpression
|
||||
/// @param[in] func_addr
|
||||
/// The address of the function in the target process.
|
||||
///
|
||||
/// @param[in] args_addr_ref
|
||||
/// The value of the void* parameter.
|
||||
/// @param[in] args_addr
|
||||
/// The address of the argument struct.
|
||||
///
|
||||
/// @param[in] errors
|
||||
/// The stream to write errors to.
|
||||
@ -485,20 +287,9 @@ class ClangFunction : public ClangExpression
|
||||
//------------------------------------------------------------------
|
||||
ThreadPlan *
|
||||
GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
|
||||
lldb::addr_t &args_addr_ref,
|
||||
Stream &errors,
|
||||
bool stop_others,
|
||||
bool unwind_on_error = true,
|
||||
bool ignore_breakpoints = true)
|
||||
{
|
||||
return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
|
||||
m_jit_start_addr,
|
||||
args_addr_ref,
|
||||
errors,
|
||||
stop_others,
|
||||
unwind_on_error,
|
||||
ignore_breakpoints);
|
||||
}
|
||||
lldb::addr_t args_addr,
|
||||
const EvaluateExpressionOptions &options,
|
||||
Stream &errors);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the result of the function from its struct
|
||||
|
@ -150,10 +150,6 @@ class ClangUserExpression : public ClangExpression
|
||||
ClangUserExpressionSP &shared_ptr_to_me,
|
||||
lldb::ClangExpressionVariableSP &result);
|
||||
|
||||
ThreadPlan *
|
||||
GetThreadPlanToExecuteJITExpression (Stream &error_stream,
|
||||
ExecutionContext &exe_ctx);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Apply the side effects of the function to program state.
|
||||
///
|
||||
|
406
include/lldb/Host/Debug.h
Normal file
406
include/lldb/Host/Debug.h
Normal file
@ -0,0 +1,406 @@
|
||||
//===-- Debug.h -------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef liblldb_Debug_h_
|
||||
#define liblldb_Debug_h_
|
||||
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Core/StreamString.h"
|
||||
#include "lldb/Host/Mutex.h"
|
||||
#include <vector>
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Tells a thread what it needs to do when the process is resumed.
|
||||
//------------------------------------------------------------------
|
||||
struct ResumeAction
|
||||
{
|
||||
lldb::tid_t tid; // The thread ID that this action applies to, LLDB_INVALID_THREAD_ID for the default thread action
|
||||
lldb::StateType state; // Valid values are eStateStopped/eStateSuspended, eStateRunning, and eStateStepping.
|
||||
int signal; // When resuming this thread, resume it with this signal if this value is > 0
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// A class that contains instructions for all threads for
|
||||
// NativeProcessProtocol::Resume(). Each thread can either run, stay
|
||||
// suspended, or step when the process is resumed. We optionally
|
||||
// have the ability to also send a signal to the thread when the
|
||||
// action is run or step.
|
||||
//------------------------------------------------------------------
|
||||
class ResumeActionList
|
||||
{
|
||||
public:
|
||||
ResumeActionList () :
|
||||
m_actions (),
|
||||
m_signal_handled ()
|
||||
{
|
||||
}
|
||||
|
||||
ResumeActionList (lldb::StateType default_action, int signal) :
|
||||
m_actions(),
|
||||
m_signal_handled ()
|
||||
{
|
||||
SetDefaultThreadActionIfNeeded (default_action, signal);
|
||||
}
|
||||
|
||||
|
||||
ResumeActionList (const ResumeAction *actions, size_t num_actions) :
|
||||
m_actions (),
|
||||
m_signal_handled ()
|
||||
{
|
||||
if (actions && num_actions)
|
||||
{
|
||||
m_actions.assign (actions, actions + num_actions);
|
||||
m_signal_handled.assign (num_actions, false);
|
||||
}
|
||||
}
|
||||
|
||||
~ResumeActionList()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
IsEmpty() const
|
||||
{
|
||||
return m_actions.empty();
|
||||
}
|
||||
|
||||
void
|
||||
Append (const ResumeAction &action)
|
||||
{
|
||||
m_actions.push_back (action);
|
||||
m_signal_handled.push_back (false);
|
||||
}
|
||||
|
||||
void
|
||||
AppendAction (lldb::tid_t tid,
|
||||
lldb::StateType state,
|
||||
int signal = 0)
|
||||
{
|
||||
ResumeAction action = { tid, state, signal };
|
||||
Append (action);
|
||||
}
|
||||
|
||||
void
|
||||
AppendResumeAll ()
|
||||
{
|
||||
AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateRunning);
|
||||
}
|
||||
|
||||
void
|
||||
AppendSuspendAll ()
|
||||
{
|
||||
AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateStopped);
|
||||
}
|
||||
|
||||
void
|
||||
AppendStepAll ()
|
||||
{
|
||||
AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateStepping);
|
||||
}
|
||||
|
||||
const ResumeAction *
|
||||
GetActionForThread (lldb::tid_t tid, bool default_ok) const
|
||||
{
|
||||
const size_t num_actions = m_actions.size();
|
||||
for (size_t i=0; i<num_actions; ++i)
|
||||
{
|
||||
if (m_actions[i].tid == tid)
|
||||
return &m_actions[i];
|
||||
}
|
||||
if (default_ok && tid != LLDB_INVALID_THREAD_ID)
|
||||
return GetActionForThread (LLDB_INVALID_THREAD_ID, false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
NumActionsWithState (lldb::StateType state) const
|
||||
{
|
||||
size_t count = 0;
|
||||
const size_t num_actions = m_actions.size();
|
||||
for (size_t i=0; i<num_actions; ++i)
|
||||
{
|
||||
if (m_actions[i].state == state)
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool
|
||||
SetDefaultThreadActionIfNeeded (lldb::StateType action, int signal)
|
||||
{
|
||||
if (GetActionForThread (LLDB_INVALID_THREAD_ID, true) == NULL)
|
||||
{
|
||||
// There isn't a default action so we do need to set it.
|
||||
ResumeAction default_action = {LLDB_INVALID_THREAD_ID, action, signal };
|
||||
m_actions.push_back (default_action);
|
||||
m_signal_handled.push_back (false);
|
||||
return true; // Return true as we did add the default action
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
SetSignalHandledForThread (lldb::tid_t tid) const
|
||||
{
|
||||
if (tid != LLDB_INVALID_THREAD_ID)
|
||||
{
|
||||
const size_t num_actions = m_actions.size();
|
||||
for (size_t i=0; i<num_actions; ++i)
|
||||
{
|
||||
if (m_actions[i].tid == tid)
|
||||
m_signal_handled[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ResumeAction *
|
||||
GetFirst() const
|
||||
{
|
||||
return m_actions.data();
|
||||
}
|
||||
|
||||
size_t
|
||||
GetSize () const
|
||||
{
|
||||
return m_actions.size();
|
||||
}
|
||||
|
||||
void
|
||||
Clear()
|
||||
{
|
||||
m_actions.clear();
|
||||
m_signal_handled.clear();
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<ResumeAction> m_actions;
|
||||
mutable std::vector<bool> m_signal_handled;
|
||||
};
|
||||
|
||||
struct ThreadStopInfo
|
||||
{
|
||||
lldb::StopReason reason;
|
||||
union
|
||||
{
|
||||
// eStopTypeSignal
|
||||
struct
|
||||
{
|
||||
uint32_t signo;
|
||||
} signal;
|
||||
|
||||
// eStopTypeException
|
||||
struct
|
||||
{
|
||||
uint64_t type;
|
||||
uint32_t data_count;
|
||||
lldb::addr_t data[2];
|
||||
} exception;
|
||||
} details;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// NativeThreadProtocol
|
||||
//------------------------------------------------------------------
|
||||
class NativeThreadProtocol {
|
||||
|
||||
public:
|
||||
NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid) :
|
||||
m_process (process),
|
||||
m_tid (tid)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~NativeThreadProtocol()
|
||||
{
|
||||
}
|
||||
virtual const char *GetName() = 0;
|
||||
virtual lldb::StateType GetState () = 0;
|
||||
virtual Error ReadRegister (uint32_t reg, RegisterValue ®_value) = 0;
|
||||
virtual Error WriteRegister (uint32_t reg, const RegisterValue ®_value) = 0;
|
||||
virtual Error SaveAllRegisters (lldb::DataBufferSP &data_sp) = 0;
|
||||
virtual Error RestoreAllRegisters (lldb::DataBufferSP &data_sp) = 0;
|
||||
virtual bool GetStopReason (ThreadStopInfo &stop_info) = 0;
|
||||
|
||||
lldb::tid_t
|
||||
GetID() const
|
||||
{
|
||||
return m_tid;
|
||||
}
|
||||
protected:
|
||||
NativeProcessProtocol *m_process;
|
||||
lldb::tid_t m_tid;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// NativeProcessProtocol
|
||||
//------------------------------------------------------------------
|
||||
class NativeProcessProtocol {
|
||||
public:
|
||||
|
||||
static NativeProcessProtocol *
|
||||
CreateInstance (lldb::pid_t pid);
|
||||
|
||||
// lldb_private::Host calls should be used to launch a process for debugging, and
|
||||
// then the process should be attached to. When attaching to a process
|
||||
// lldb_private::Host calls should be used to locate the process to attach to,
|
||||
// and then this function should be called.
|
||||
NativeProcessProtocol (lldb::pid_t pid) :
|
||||
m_pid (pid),
|
||||
m_threads(),
|
||||
m_threads_mutex (Mutex::eMutexTypeRecursive),
|
||||
m_state (lldb::eStateInvalid),
|
||||
m_exit_status(0),
|
||||
m_exit_description()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~NativeProcessProtocol ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual Error Resume (const ResumeActionList &resume_actions) = 0;
|
||||
virtual Error Halt () = 0;
|
||||
virtual Error Detach () = 0;
|
||||
virtual Error Signal (int signo) = 0;
|
||||
virtual Error Kill () = 0;
|
||||
|
||||
virtual Error ReadMemory (lldb::addr_t addr, void *buf, lldb::addr_t size, lldb::addr_t &bytes_read) = 0;
|
||||
virtual Error WriteMemory (lldb::addr_t addr, const void *buf, lldb::addr_t size, lldb::addr_t &bytes_written) = 0;
|
||||
virtual Error AllocateMemory (lldb::addr_t size, uint32_t permissions, lldb::addr_t &addr) = 0;
|
||||
virtual Error DeallocateMemory (lldb::addr_t addr) = 0;
|
||||
|
||||
virtual lldb::addr_t GetSharedLibraryInfoAddress () = 0;
|
||||
|
||||
virtual bool IsAlive () = 0;
|
||||
virtual size_t UpdateThreads () = 0;
|
||||
virtual bool GetArchitecture (ArchSpec &arch) = 0;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Breakpoint functions
|
||||
//----------------------------------------------------------------------
|
||||
virtual Error SetBreakpoint (lldb::addr_t addr, size_t size, bool hardware) = 0;
|
||||
virtual Error RemoveBreakpoint (lldb::addr_t addr, size_t size) = 0;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Watchpoint functions
|
||||
//----------------------------------------------------------------------
|
||||
virtual uint32_t GetMaxWatchpoints () = 0;
|
||||
virtual Error SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) = 0;
|
||||
virtual Error RemoveWatchpoint (lldb::addr_t addr) = 0;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Accessors
|
||||
//----------------------------------------------------------------------
|
||||
lldb::pid_t
|
||||
GetID() const
|
||||
{
|
||||
return m_pid;
|
||||
}
|
||||
|
||||
lldb::StateType
|
||||
GetState () const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
bool
|
||||
IsRunning () const
|
||||
{
|
||||
return m_state == lldb::eStateRunning || IsStepping();
|
||||
}
|
||||
|
||||
bool
|
||||
IsStepping () const
|
||||
{
|
||||
return m_state == lldb::eStateStepping;
|
||||
}
|
||||
|
||||
bool
|
||||
CanResume () const
|
||||
{
|
||||
return m_state == lldb::eStateStopped;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SetState (lldb::StateType state)
|
||||
{
|
||||
m_state = state;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Exit Status
|
||||
//----------------------------------------------------------------------
|
||||
virtual bool
|
||||
GetExitStatus (int *status)
|
||||
{
|
||||
if (m_state == lldb::eStateExited)
|
||||
{
|
||||
*status = m_exit_status;
|
||||
return true;
|
||||
}
|
||||
*status = 0;
|
||||
return false;
|
||||
}
|
||||
virtual bool
|
||||
SetExitStatus (int status, const char *exit_description)
|
||||
{
|
||||
// Exit status already set
|
||||
if (m_state == lldb::eStateExited)
|
||||
return false;
|
||||
m_state = lldb::eStateExited;
|
||||
m_exit_status = status;
|
||||
if (exit_description && exit_description[0])
|
||||
m_exit_description = exit_description;
|
||||
else
|
||||
m_exit_description.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Access to threads
|
||||
//----------------------------------------------------------------------
|
||||
lldb::NativeThreadProtocolSP
|
||||
GetThreadAtIndex (uint32_t idx)
|
||||
{
|
||||
Mutex::Locker locker(m_threads_mutex);
|
||||
if (idx < m_threads.size())
|
||||
return m_threads[idx];
|
||||
return lldb::NativeThreadProtocolSP();
|
||||
}
|
||||
|
||||
lldb::NativeThreadProtocolSP
|
||||
GetThreadByID (lldb::tid_t tid)
|
||||
{
|
||||
Mutex::Locker locker(m_threads_mutex);
|
||||
for (auto thread_sp : m_threads)
|
||||
{
|
||||
if (thread_sp->GetID() == tid)
|
||||
return thread_sp;
|
||||
}
|
||||
return lldb::NativeThreadProtocolSP();
|
||||
}
|
||||
|
||||
protected:
|
||||
lldb::pid_t m_pid;
|
||||
std::vector<lldb::NativeThreadProtocolSP> m_threads;
|
||||
mutable Mutex m_threads_mutex;
|
||||
lldb::StateType m_state;
|
||||
int m_exit_status;
|
||||
std::string m_exit_description;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // #ifndef liblldb_Debug_h_
|
@ -40,46 +40,13 @@ class File
|
||||
eOpenOptionTruncate = (1u << 3), // Truncate file when opening
|
||||
eOpenOptionNonBlocking = (1u << 4), // File reads
|
||||
eOpenOptionCanCreate = (1u << 5), // Create file if doesn't already exist
|
||||
eOpenOptionCanCreateNewOnly = (1u << 6) // Can create file only if it doesn't already exist
|
||||
eOpenOptionCanCreateNewOnly = (1u << 6), // Can create file only if it doesn't already exist
|
||||
eOpenoptionDontFollowSymlinks = (1u << 7)
|
||||
};
|
||||
|
||||
static mode_t
|
||||
ConvertOpenOptionsForPOSIXOpen (uint32_t open_options);
|
||||
|
||||
enum Permissions
|
||||
{
|
||||
ePermissionsUserRead = (1u << 8),
|
||||
ePermissionsUserWrite = (1u << 7),
|
||||
ePermissionsUserExecute = (1u << 6),
|
||||
ePermissionsGroupRead = (1u << 5),
|
||||
ePermissionsGroupWrite = (1u << 4),
|
||||
ePermissionsGroupExecute = (1u << 3),
|
||||
ePermissionsWorldRead = (1u << 2),
|
||||
ePermissionsWorldWrite = (1u << 1),
|
||||
ePermissionsWorldExecute = (1u << 0),
|
||||
|
||||
ePermissionsUserRW = (ePermissionsUserRead | ePermissionsUserWrite | 0 ),
|
||||
ePermissionsUserRX = (ePermissionsUserRead | 0 | ePermissionsUserExecute ),
|
||||
ePermissionsUserRWX = (ePermissionsUserRead | ePermissionsUserWrite | ePermissionsUserExecute ),
|
||||
|
||||
ePermissionsGroupRW = (ePermissionsGroupRead | ePermissionsGroupWrite | 0 ),
|
||||
ePermissionsGroupRX = (ePermissionsGroupRead | 0 | ePermissionsGroupExecute ),
|
||||
ePermissionsGroupRWX = (ePermissionsGroupRead | ePermissionsGroupWrite | ePermissionsGroupExecute ),
|
||||
|
||||
ePermissionsWorldRW = (ePermissionsWorldRead | ePermissionsWorldWrite | 0 ),
|
||||
ePermissionsWorldRX = (ePermissionsWorldRead | 0 | ePermissionsWorldExecute ),
|
||||
ePermissionsWorldRWX = (ePermissionsWorldRead | ePermissionsWorldWrite | ePermissionsWorldExecute ),
|
||||
|
||||
ePermissionsEveryoneR = (ePermissionsUserRead | ePermissionsGroupRead | ePermissionsWorldRead ),
|
||||
ePermissionsEveryoneW = (ePermissionsUserWrite | ePermissionsGroupWrite | ePermissionsWorldWrite ),
|
||||
ePermissionsEveryoneX = (ePermissionsUserExecute | ePermissionsGroupExecute | ePermissionsWorldExecute ),
|
||||
|
||||
ePermissionsEveryoneRW = (ePermissionsEveryoneR | ePermissionsEveryoneW | 0 ),
|
||||
ePermissionsEveryoneRX = (ePermissionsEveryoneR | 0 | ePermissionsEveryoneX ),
|
||||
ePermissionsEveryoneRWX = (ePermissionsEveryoneR | ePermissionsEveryoneW | ePermissionsEveryoneX ),
|
||||
ePermissionsDefault = (ePermissionsUserRW | ePermissionsGroupRead)
|
||||
};
|
||||
|
||||
File() :
|
||||
m_descriptor (kInvalidDescriptor),
|
||||
m_stream (kInvalidStream),
|
||||
@ -120,7 +87,7 @@ class File
|
||||
//------------------------------------------------------------------
|
||||
File (const char *path,
|
||||
uint32_t options,
|
||||
uint32_t permissions = ePermissionsDefault);
|
||||
uint32_t permissions = lldb::eFilePermissionsFileDefault);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Constructor with FileSpec.
|
||||
@ -142,7 +109,7 @@ class File
|
||||
//------------------------------------------------------------------
|
||||
File (const FileSpec& filespec,
|
||||
uint32_t options,
|
||||
uint32_t permissions = ePermissionsDefault);
|
||||
uint32_t permissions = lldb::eFilePermissionsFileDefault);
|
||||
|
||||
File (int fd, bool tranfer_ownership) :
|
||||
m_descriptor (fd),
|
||||
@ -236,7 +203,7 @@ class File
|
||||
Error
|
||||
Open (const char *path,
|
||||
uint32_t options,
|
||||
uint32_t permissions = ePermissionsDefault);
|
||||
uint32_t permissions = lldb::eFilePermissionsFileDefault);
|
||||
|
||||
Error
|
||||
Close ();
|
||||
|
@ -420,6 +420,21 @@ class FileSpec
|
||||
FileType
|
||||
GetFileType () const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return the current permissions of the path.
|
||||
///
|
||||
/// Returns a bitmask for the current permissions of the file
|
||||
/// ( zero or more of the permission bits defined in
|
||||
/// File::Permissions).
|
||||
///
|
||||
/// @return
|
||||
/// Zero if the file doesn't exist or we are unable to get
|
||||
/// information for the file, otherwise one or more permission
|
||||
/// bits from the File::Permissions enumeration.
|
||||
//------------------------------------------------------------------
|
||||
uint32_t
|
||||
GetPermissions () const;
|
||||
|
||||
bool
|
||||
IsDirectory () const
|
||||
{
|
||||
@ -636,7 +651,7 @@ class FileSpec
|
||||
void
|
||||
RemoveLastPathComponent ();
|
||||
|
||||
const char*
|
||||
ConstString
|
||||
GetLastPathComponent () const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -510,13 +510,28 @@ class Host
|
||||
const char *symbol_name,
|
||||
Error &error);
|
||||
|
||||
static uint32_t
|
||||
MakeDirectory (const char* path, mode_t mode);
|
||||
static Error
|
||||
MakeDirectory (const char* path, uint32_t mode);
|
||||
|
||||
static Error
|
||||
GetFilePermissions (const char* path, uint32_t &file_permissions);
|
||||
|
||||
static Error
|
||||
SetFilePermissions (const char* path, uint32_t file_permissions);
|
||||
|
||||
static Error
|
||||
Symlink (const char *src, const char *dst);
|
||||
|
||||
static Error
|
||||
Readlink (const char *path, char *buf, size_t buf_len);
|
||||
|
||||
static Error
|
||||
Unlink (const char *path);
|
||||
|
||||
static lldb::user_id_t
|
||||
OpenFile (const FileSpec& file_spec,
|
||||
uint32_t flags,
|
||||
mode_t mode,
|
||||
uint32_t mode,
|
||||
Error &error);
|
||||
|
||||
static bool
|
||||
|
@ -10,6 +10,10 @@
|
||||
#ifndef liblldb_OptionParser_h_
|
||||
#define liblldb_OptionParser_h_
|
||||
|
||||
#include <string>
|
||||
|
||||
struct option;
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
typedef struct Option
|
||||
@ -46,6 +50,7 @@ class OptionParser
|
||||
static char* GetOptionArgument();
|
||||
static int GetOptionIndex();
|
||||
static int GetOptionErrorCause();
|
||||
static std::string GetShortOptionString(struct option *long_options);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -19,11 +19,7 @@
|
||||
#include "lldb/Core/ConstString.h"
|
||||
#include "lldb/Core/Flags.h"
|
||||
#include "lldb/Interpreter/OptionValue.h"
|
||||
#if defined (__APPLE__)
|
||||
#include <Python/Python.h>
|
||||
#else
|
||||
#include <Python.h>
|
||||
#endif
|
||||
#include "lldb/lldb-python.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
|
@ -17,12 +17,7 @@
|
||||
|
||||
#else
|
||||
|
||||
#if defined (__APPLE__)
|
||||
#include <Python/Python.h>
|
||||
#else
|
||||
#include <Python.h>
|
||||
#endif
|
||||
|
||||
#include "lldb/lldb-python.h"
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/Interpreter/ScriptInterpreter.h"
|
||||
#include "lldb/Core/InputReader.h"
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/Symbol/Type.h"
|
||||
#include "lldb/Utility/Iterable.h"
|
||||
#include <map>
|
||||
#include <functional>
|
||||
|
||||
@ -51,6 +52,15 @@ class TypeList
|
||||
|
||||
lldb::TypeSP
|
||||
GetTypeAtIndex(uint32_t idx);
|
||||
|
||||
typedef std::multimap<lldb::user_id_t, lldb::TypeSP> collection;
|
||||
typedef AdaptedIterable<collection, lldb::TypeSP, map_adapter> TypeIterable;
|
||||
|
||||
TypeIterable
|
||||
Types ()
|
||||
{
|
||||
return TypeIterable(m_types);
|
||||
}
|
||||
|
||||
void
|
||||
ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const;
|
||||
@ -75,7 +85,6 @@ class TypeList
|
||||
RemoveMismatchedTypes (lldb::TypeClass type_class);
|
||||
|
||||
private:
|
||||
typedef std::multimap<lldb::user_id_t, lldb::TypeSP> collection;
|
||||
typedef collection::iterator iterator;
|
||||
typedef collection::const_iterator const_iterator;
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "lldb/Core/PluginInterface.h"
|
||||
#include "lldb/lldb-private.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
class ABI :
|
||||
@ -35,12 +37,7 @@ class ABI :
|
||||
lldb::addr_t sp,
|
||||
lldb::addr_t functionAddress,
|
||||
lldb::addr_t returnAddress,
|
||||
lldb::addr_t *arg1_ptr = NULL,
|
||||
lldb::addr_t *arg2_ptr = NULL,
|
||||
lldb::addr_t *arg3_ptr = NULL,
|
||||
lldb::addr_t *arg4_ptr = NULL,
|
||||
lldb::addr_t *arg5_ptr = NULL,
|
||||
lldb::addr_t *arg6_ptr = NULL) const = 0;
|
||||
llvm::ArrayRef<lldb::addr_t> args) const = 0;
|
||||
|
||||
virtual bool
|
||||
GetArgumentValues (Thread &thread,
|
||||
|
@ -66,6 +66,12 @@ class LanguageRuntime :
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool
|
||||
ExceptionBreakpointsAreSet ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
|
||||
{
|
||||
|
@ -40,7 +40,8 @@ namespace lldb_private {
|
||||
/// @li listing and getting info for existing processes
|
||||
/// @li attaching and possibly debugging the platform's kernel
|
||||
//----------------------------------------------------------------------
|
||||
class Platform : public PluginInterface
|
||||
class Platform :
|
||||
public PluginInterface
|
||||
{
|
||||
public:
|
||||
|
||||
@ -214,8 +215,7 @@ namespace lldb_private {
|
||||
bool
|
||||
GetOSKernelDescription (std::string &s);
|
||||
|
||||
// Returns the the hostname if we are connected, else the short plugin
|
||||
// name.
|
||||
// Returns the the name of the platform
|
||||
ConstString
|
||||
GetName ();
|
||||
|
||||
@ -269,6 +269,15 @@ namespace lldb_private {
|
||||
{
|
||||
return ArchSpec(); // Return an invalid architecture
|
||||
}
|
||||
|
||||
virtual ConstString
|
||||
GetRemoteWorkingDirectory()
|
||||
{
|
||||
return m_working_dir;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
SetRemoteWorkingDirectory(const ConstString &path);
|
||||
|
||||
virtual const char *
|
||||
GetUserName (uint32_t uid);
|
||||
@ -384,10 +393,13 @@ namespace lldb_private {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Subclasses should NOT need to implement this function as it uses
|
||||
/// the Platform::LaunchProcess() followed by Platform::Attach ()
|
||||
/// Subclasses do not need to implement this function as it uses
|
||||
/// the Platform::LaunchProcess() followed by Platform::Attach ().
|
||||
/// Remote platforms will want to subclass this function in order
|
||||
/// to be able to intercept STDIO and possibly launch a separate
|
||||
/// process that will debug the debuggee.
|
||||
//------------------------------------------------------------------
|
||||
lldb::ProcessSP
|
||||
virtual lldb::ProcessSP
|
||||
DebugProcess (ProcessLaunchInfo &launch_info,
|
||||
Debugger &debugger,
|
||||
Target *target, // Can be NULL, if NULL create a new target, else use existing one
|
||||
@ -542,6 +554,12 @@ namespace lldb_private {
|
||||
{
|
||||
m_sdk_build = sdk_build;
|
||||
}
|
||||
|
||||
ConstString
|
||||
GetWorkingDirectory ();
|
||||
|
||||
bool
|
||||
SetWorkingDirectory (const ConstString &path);
|
||||
|
||||
// There may be modules that we don't want to find by default for operations like "setting breakpoint by name".
|
||||
// The platform will return "true" from this call if the passed in module happens to be one of these.
|
||||
@ -552,23 +570,19 @@ namespace lldb_private {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual uint32_t
|
||||
MakeDirectory (const std::string &path,
|
||||
mode_t mode)
|
||||
{
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
// this need not be virtual: the core behavior is in
|
||||
// MakeDirectory(std::string,mode_t)
|
||||
uint32_t
|
||||
MakeDirectory (const FileSpec &spec,
|
||||
mode_t mode);
|
||||
virtual Error
|
||||
MakeDirectory (const char *path, uint32_t permissions);
|
||||
|
||||
virtual Error
|
||||
GetFilePermissions (const char *path, uint32_t &file_permissions);
|
||||
|
||||
virtual Error
|
||||
SetFilePermissions (const char *path, uint32_t file_permissions);
|
||||
|
||||
virtual lldb::user_id_t
|
||||
OpenFile (const FileSpec& file_spec,
|
||||
uint32_t flags,
|
||||
mode_t mode,
|
||||
uint32_t mode,
|
||||
Error &error)
|
||||
{
|
||||
return UINT64_MAX;
|
||||
@ -609,29 +623,55 @@ namespace lldb_private {
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual Error
|
||||
GetFile (const FileSpec& source,
|
||||
const FileSpec& destination);
|
||||
|
||||
virtual Error
|
||||
PutFile (const FileSpec& source,
|
||||
const FileSpec& destination,
|
||||
uint32_t uid = UINT32_MAX,
|
||||
uint32_t gid = UINT32_MAX);
|
||||
|
||||
|
||||
virtual Error
|
||||
CreateSymlink (const char *src, // The name of the link is in src
|
||||
const char *dst);// The symlink points to dst
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// Install a file or directory to the remote system.
|
||||
///
|
||||
/// Install is similar to Platform::PutFile(), but it differs in that if
|
||||
/// an application/framework/shared library is installed on a remote
|
||||
/// platform and the remote platform requires something to be done to
|
||||
/// register the application/framework/shared library, then this extra
|
||||
/// registration can be done.
|
||||
///
|
||||
/// @param[in] src
|
||||
/// The source file/directory to install on the remote system.
|
||||
///
|
||||
/// @param[in] dst
|
||||
/// The destination file/directory where \a src will be installed.
|
||||
/// If \a dst has no filename specified, then its filename will
|
||||
/// be set from \a src. It \a dst has no directory specified, it
|
||||
/// will use the platform working directory. If \a dst has a
|
||||
/// directory specified, but the directory path is relative, the
|
||||
/// platform working directory will be prepended to the relative
|
||||
/// directory.
|
||||
///
|
||||
/// @return
|
||||
/// An error object that describes anything that went wrong.
|
||||
//----------------------------------------------------------------------
|
||||
virtual Error
|
||||
Install (const FileSpec& src, const FileSpec& dst);
|
||||
|
||||
virtual size_t
|
||||
GetEnvironment (StringList &environment);
|
||||
|
||||
virtual Error
|
||||
GetFile (const FileSpec& source,
|
||||
const FileSpec& destination);
|
||||
|
||||
virtual bool
|
||||
GetFileExists (const lldb_private::FileSpec& file_spec);
|
||||
|
||||
virtual uint32_t
|
||||
GetFilePermissions (const lldb_private::FileSpec &file_spec,
|
||||
Error &error)
|
||||
{
|
||||
error.SetErrorStringWithFormat ("Platform::GetFilePermissions() is not supported in the %s platform", GetName().GetCString());
|
||||
return 0;
|
||||
}
|
||||
virtual Error
|
||||
Unlink (const char *path);
|
||||
|
||||
virtual bool
|
||||
GetSupportsRSync ()
|
||||
@ -806,6 +846,7 @@ namespace lldb_private {
|
||||
bool m_system_arch_set_while_connected;
|
||||
ConstString m_sdk_sysroot; // the root location of where the SDK files are all located
|
||||
ConstString m_sdk_build;
|
||||
ConstString m_working_dir; // The working directory which is used when installing modules that have no install path set
|
||||
std::string m_remote_url;
|
||||
std::string m_name;
|
||||
uint32_t m_major_os_version;
|
||||
|
@ -1745,7 +1745,7 @@ friend class StopInfo;
|
||||
/// the error object is success.
|
||||
//------------------------------------------------------------------
|
||||
virtual Error
|
||||
Launch (const ProcessLaunchInfo &launch_info);
|
||||
Launch (ProcessLaunchInfo &launch_info);
|
||||
|
||||
virtual Error
|
||||
LoadCore ();
|
||||
@ -2502,11 +2502,7 @@ friend class StopInfo;
|
||||
ExecutionResults
|
||||
RunThreadPlan (ExecutionContext &exe_ctx,
|
||||
lldb::ThreadPlanSP &thread_plan_sp,
|
||||
bool stop_others,
|
||||
bool run_others,
|
||||
bool unwind_on_error,
|
||||
bool ignore_breakpoints,
|
||||
uint32_t timeout_usec,
|
||||
const EvaluateExpressionOptions &options,
|
||||
Stream &errors);
|
||||
|
||||
static const char *
|
||||
@ -3304,6 +3300,23 @@ friend class StopInfo;
|
||||
{
|
||||
return m_thread_list;
|
||||
}
|
||||
|
||||
// When ExtendedBacktraces are requested, the HistoryThreads that are
|
||||
// created need an owner -- they're saved here in the Process. The
|
||||
// threads in this list are not iterated over - driver programs need to
|
||||
// request the extended backtrace calls starting from a root concrete
|
||||
// thread one by one.
|
||||
ThreadList &
|
||||
GetExtendedThreadList ()
|
||||
{
|
||||
return m_extended_thread_list;
|
||||
}
|
||||
|
||||
ThreadList::ThreadIterable
|
||||
Threads ()
|
||||
{
|
||||
return m_thread_list.Threads();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetNextThreadIndexID (uint64_t thread_id);
|
||||
@ -3670,6 +3683,8 @@ friend class StopInfo;
|
||||
ThreadList m_thread_list_real; ///< The threads for this process as are known to the protocol we are debugging with
|
||||
ThreadList m_thread_list; ///< The threads for this process as the user will see them. This is usually the same as
|
||||
///< m_thread_list_real, but might be different if there is an OS plug-in creating memory threads
|
||||
ThreadList m_extended_thread_list; ///< Owner for extended threads that may be generated, cleared on natural stops
|
||||
uint32_t m_extended_thread_stop_id; ///< The natural stop id when extended_thread_list was last updated
|
||||
std::vector<Notifications> m_notifications; ///< The list of notifications that this process can deliver.
|
||||
std::vector<lldb::addr_t> m_image_tokens;
|
||||
Listener &m_listener;
|
||||
|
71
include/lldb/Target/RegisterCheckpoint.h
Normal file
71
include/lldb/Target/RegisterCheckpoint.h
Normal file
@ -0,0 +1,71 @@
|
||||
//===-- RegisterCheckpoint.h ------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef liblldb_RegisterCheckpoint_h_
|
||||
#define liblldb_RegisterCheckpoint_h_
|
||||
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/Core/UserID.h"
|
||||
#include "lldb/Target/StackID.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
// Inherit from UserID in case pushing/popping all register values can be
|
||||
// done using a 64 bit integer that holds a baton/cookie instead of actually
|
||||
// having to read all register values into a buffer
|
||||
class RegisterCheckpoint : public UserID
|
||||
{
|
||||
public:
|
||||
|
||||
enum class Reason {
|
||||
// An expression is about to be run on the thread if the protocol that
|
||||
// talks to the debuggee supports checkpointing the registers using a
|
||||
// push/pop then the UserID base class in the RegisterCheckpoint can
|
||||
// be used to store the baton/cookie that refers to the remote saved
|
||||
// state.
|
||||
eExpression,
|
||||
// The register checkpoint wants the raw register bytes, so they must
|
||||
// be read into m_data_sp, or the save/restore checkpoint should fail.
|
||||
eDataBackup
|
||||
};
|
||||
|
||||
RegisterCheckpoint(Reason reason) :
|
||||
UserID(0),
|
||||
m_data_sp (),
|
||||
m_reason(reason)
|
||||
{
|
||||
}
|
||||
|
||||
~RegisterCheckpoint()
|
||||
{
|
||||
}
|
||||
|
||||
lldb::DataBufferSP &
|
||||
GetData()
|
||||
{
|
||||
return m_data_sp;
|
||||
}
|
||||
|
||||
const lldb::DataBufferSP &
|
||||
GetData() const
|
||||
{
|
||||
return m_data_sp;
|
||||
}
|
||||
|
||||
protected:
|
||||
lldb::DataBufferSP m_data_sp;
|
||||
Reason m_reason;
|
||||
|
||||
// Make RegisterCheckpointSP if you wish to share the data in this class.
|
||||
DISALLOW_COPY_AND_ASSIGN(RegisterCheckpoint);
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // liblldb_RegisterCheckpoint_h_
|
@ -59,6 +59,18 @@ class RegisterContext :
|
||||
virtual bool
|
||||
WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) = 0;
|
||||
|
||||
virtual bool
|
||||
ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// These two functions are used to implement "push" and "pop" of register states. They are used primarily
|
||||
// for expression evaluation, where we need to push a new state (storing the old one in data_sp) and then
|
||||
// restoring the original state by passing the data_sp we got from ReadAllRegisters to WriteAllRegisterValues.
|
||||
@ -67,10 +79,10 @@ class RegisterContext :
|
||||
// so these API's should only be used when this behavior is needed.
|
||||
|
||||
virtual bool
|
||||
ReadAllRegisterValues (lldb::DataBufferSP &data_sp) = 0;
|
||||
|
||||
ReadAllRegisterValues (lldb_private::RegisterCheckpoint ®_checkpoint);
|
||||
|
||||
virtual bool
|
||||
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) = 0;
|
||||
WriteAllRegisterValues (const lldb_private::RegisterCheckpoint ®_checkpoint);
|
||||
|
||||
bool
|
||||
CopyFromRegisterContext (lldb::RegisterContextSP context);
|
||||
|
@ -127,7 +127,7 @@ class SystemRuntime :
|
||||
/// An empty vector may be returned if no thread origin extended
|
||||
/// backtrace capabilities are available.
|
||||
//------------------------------------------------------------------
|
||||
virtual std::vector<ConstString>
|
||||
virtual const std::vector<ConstString> &
|
||||
GetExtendedBacktraceTypes ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
@ -158,13 +158,16 @@ class SystemRuntime :
|
||||
/// An empty ThreadSP will be returned if no thread origin is available.
|
||||
//------------------------------------------------------------------
|
||||
virtual lldb::ThreadSP
|
||||
GetExtendedBacktrace (lldb::ThreadSP thread, ConstString type);
|
||||
GetExtendedBacktraceThread (lldb::ThreadSP thread, ConstString type);
|
||||
|
||||
protected:
|
||||
//------------------------------------------------------------------
|
||||
// Member variables.
|
||||
//------------------------------------------------------------------
|
||||
Process *m_process;
|
||||
|
||||
std::vector<ConstString> m_types;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (SystemRuntime);
|
||||
};
|
||||
|
@ -189,8 +189,10 @@ class EvaluateExpressionOptions
|
||||
m_unwind_on_error(true),
|
||||
m_ignore_breakpoints (false),
|
||||
m_keep_in_memory(false),
|
||||
m_run_others(true),
|
||||
m_try_others(true),
|
||||
m_stop_others(true),
|
||||
m_debug(false),
|
||||
m_trap_exceptions(true),
|
||||
m_use_dynamic(lldb::eNoDynamicValues),
|
||||
m_timeout_usec(default_timeout)
|
||||
{}
|
||||
@ -201,11 +203,10 @@ class EvaluateExpressionOptions
|
||||
return m_execution_policy;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
void
|
||||
SetExecutionPolicy (ExecutionPolicy policy = eExecutionPolicyAlways)
|
||||
{
|
||||
m_execution_policy = policy;
|
||||
return *this;
|
||||
}
|
||||
|
||||
lldb::LanguageType
|
||||
@ -214,11 +215,10 @@ class EvaluateExpressionOptions
|
||||
return m_language;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
void
|
||||
SetLanguage(lldb::LanguageType language)
|
||||
{
|
||||
m_language = language;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -227,11 +227,10 @@ class EvaluateExpressionOptions
|
||||
return m_coerce_to_id;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
void
|
||||
SetCoerceToId (bool coerce = true)
|
||||
{
|
||||
m_coerce_to_id = coerce;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -240,11 +239,10 @@ class EvaluateExpressionOptions
|
||||
return m_unwind_on_error;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
void
|
||||
SetUnwindOnError (bool unwind = false)
|
||||
{
|
||||
m_unwind_on_error = unwind;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -253,11 +251,10 @@ class EvaluateExpressionOptions
|
||||
return m_ignore_breakpoints;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
void
|
||||
SetIgnoreBreakpoints (bool ignore = false)
|
||||
{
|
||||
m_ignore_breakpoints = ignore;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -266,11 +263,10 @@ class EvaluateExpressionOptions
|
||||
return m_keep_in_memory;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
void
|
||||
SetKeepInMemory (bool keep = true)
|
||||
{
|
||||
m_keep_in_memory = keep;
|
||||
return *this;
|
||||
}
|
||||
|
||||
lldb::DynamicValueType
|
||||
@ -279,11 +275,10 @@ class EvaluateExpressionOptions
|
||||
return m_use_dynamic;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
void
|
||||
SetUseDynamic (lldb::DynamicValueType dynamic = lldb::eDynamicCanRunTarget)
|
||||
{
|
||||
m_use_dynamic = dynamic;
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@ -292,24 +287,34 @@ class EvaluateExpressionOptions
|
||||
return m_timeout_usec;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
void
|
||||
SetTimeoutUsec (uint32_t timeout = 0)
|
||||
{
|
||||
m_timeout_usec = timeout;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
GetRunOthers () const
|
||||
GetTryAllThreads () const
|
||||
{
|
||||
return m_run_others;
|
||||
return m_try_others;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
SetRunOthers (bool run_others = true)
|
||||
void
|
||||
SetTryAllThreads (bool try_others = true)
|
||||
{
|
||||
m_run_others = run_others;
|
||||
return *this;
|
||||
m_try_others = try_others;
|
||||
}
|
||||
|
||||
bool
|
||||
GetStopOthers () const
|
||||
{
|
||||
return m_stop_others;
|
||||
}
|
||||
|
||||
void
|
||||
SetStopOthers (bool stop_others = true)
|
||||
{
|
||||
m_stop_others = stop_others;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -318,11 +323,22 @@ class EvaluateExpressionOptions
|
||||
return m_debug;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
void
|
||||
SetDebug(bool b)
|
||||
{
|
||||
m_debug = b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
GetTrapExceptions() const
|
||||
{
|
||||
return m_trap_exceptions;
|
||||
}
|
||||
|
||||
void
|
||||
SetTrapExceptions (bool b)
|
||||
{
|
||||
m_trap_exceptions = b;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -332,8 +348,10 @@ class EvaluateExpressionOptions
|
||||
bool m_unwind_on_error;
|
||||
bool m_ignore_breakpoints;
|
||||
bool m_keep_in_memory;
|
||||
bool m_run_others;
|
||||
bool m_try_others;
|
||||
bool m_stop_others;
|
||||
bool m_debug;
|
||||
bool m_trap_exceptions;
|
||||
lldb::DynamicValueType m_use_dynamic;
|
||||
uint32_t m_timeout_usec;
|
||||
};
|
||||
@ -741,8 +759,22 @@ class Target :
|
||||
SymbolsDidLoad (ModuleList &module_list);
|
||||
|
||||
void
|
||||
ClearModules();
|
||||
ClearModules(bool delete_locations);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Called as the last function in Process::DidExec().
|
||||
///
|
||||
/// Process::DidExec() will clear a lot of state in the process,
|
||||
/// then try to reload a dynamic loader plugin to discover what
|
||||
/// binaries are currently available and then this function should
|
||||
/// be called to allow the target to do any cleanup after everything
|
||||
/// has been figured out. It can remove breakpoints that no longer
|
||||
/// make sense as the exec might have changed the target
|
||||
/// architecture, and unloaded some modules that might get deleted.
|
||||
//------------------------------------------------------------------
|
||||
void
|
||||
DidExec ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Gets the module for the main executable.
|
||||
///
|
||||
@ -1009,6 +1041,12 @@ class Target :
|
||||
ClangASTImporter *
|
||||
GetClangASTImporter();
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Install any files through the platform that need be to installed
|
||||
// prior to launching or attaching.
|
||||
//----------------------------------------------------------------------
|
||||
Error
|
||||
Install(ProcessLaunchInfo *launch_info);
|
||||
|
||||
// Since expressions results can persist beyond the lifetime of a process,
|
||||
// and the const expression results are available after a process is gone,
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "lldb/Core/UserID.h"
|
||||
#include "lldb/Core/UserSettingsController.h"
|
||||
#include "lldb/Target/ExecutionContextScope.h"
|
||||
#include "lldb/Target/RegisterCheckpoint.h"
|
||||
#include "lldb/Target/StackFrameList.h"
|
||||
|
||||
#define LLDB_THREAD_MAX_STOP_EXC_DATA 8
|
||||
@ -130,79 +131,12 @@ class Thread :
|
||||
DISALLOW_COPY_AND_ASSIGN (ThreadEventData);
|
||||
};
|
||||
|
||||
// TODO: You shouldn't just checkpoint the register state alone, so this should get
|
||||
// moved to protected. To do that ThreadStateCheckpoint needs to be returned as a token...
|
||||
class RegisterCheckpoint
|
||||
{
|
||||
public:
|
||||
|
||||
RegisterCheckpoint() :
|
||||
m_stack_id (),
|
||||
m_data_sp ()
|
||||
{
|
||||
}
|
||||
|
||||
RegisterCheckpoint (const StackID &stack_id) :
|
||||
m_stack_id (stack_id),
|
||||
m_data_sp ()
|
||||
{
|
||||
}
|
||||
|
||||
~RegisterCheckpoint()
|
||||
{
|
||||
}
|
||||
|
||||
const RegisterCheckpoint&
|
||||
operator= (const RegisterCheckpoint &rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
this->m_stack_id = rhs.m_stack_id;
|
||||
this->m_data_sp = rhs.m_data_sp;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
RegisterCheckpoint (const RegisterCheckpoint &rhs) :
|
||||
m_stack_id (rhs.m_stack_id),
|
||||
m_data_sp (rhs.m_data_sp)
|
||||
{
|
||||
}
|
||||
|
||||
const StackID &
|
||||
GetStackID()
|
||||
{
|
||||
return m_stack_id;
|
||||
}
|
||||
|
||||
void
|
||||
SetStackID (const StackID &stack_id)
|
||||
{
|
||||
m_stack_id = stack_id;
|
||||
}
|
||||
|
||||
lldb::DataBufferSP &
|
||||
GetData()
|
||||
{
|
||||
return m_data_sp;
|
||||
}
|
||||
|
||||
const lldb::DataBufferSP &
|
||||
GetData() const
|
||||
{
|
||||
return m_data_sp;
|
||||
}
|
||||
|
||||
protected:
|
||||
StackID m_stack_id;
|
||||
lldb::DataBufferSP m_data_sp;
|
||||
};
|
||||
|
||||
struct ThreadStateCheckpoint
|
||||
{
|
||||
uint32_t orig_stop_id; // Dunno if I need this yet but it is an interesting bit of data.
|
||||
lldb::StopInfoSP stop_info_sp; // You have to restore the stop info or you might continue with the wrong signals.
|
||||
RegisterCheckpoint register_backup; // You need to restore the registers, of course...
|
||||
lldb::RegisterCheckpointSP register_backup_sp; // You need to restore the registers, of course...
|
||||
uint32_t current_inlined_depth;
|
||||
lldb::addr_t current_inlined_pc;
|
||||
};
|
||||
@ -339,18 +273,33 @@ class Thread :
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual void
|
||||
SetName (const char *name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual lldb::queue_id_t
|
||||
GetQueueID ()
|
||||
{
|
||||
return LLDB_INVALID_QUEUE_ID;
|
||||
}
|
||||
|
||||
virtual void
|
||||
SetQueueID (lldb::queue_id_t new_val)
|
||||
{
|
||||
}
|
||||
|
||||
virtual const char *
|
||||
GetQueueName ()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual void
|
||||
SetQueueName (const char *name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual uint32_t
|
||||
GetStackFrameCount()
|
||||
{
|
||||
@ -528,21 +477,6 @@ class Thread :
|
||||
virtual lldb::ThreadPlanSP
|
||||
QueueFundamentalPlan (bool abort_other_plans);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Queues the plan used to step over a breakpoint at the current PC of \a thread.
|
||||
/// The default version returned by Process handles trap based breakpoints, and
|
||||
/// will disable the breakpoint, single step over it, then re-enable it.
|
||||
///
|
||||
/// @param[in] abort_other_plans
|
||||
/// \b true if we discard the currently queued plans and replace them with this one.
|
||||
/// Otherwise this plan will go on the end of the plan stack.
|
||||
///
|
||||
/// @return
|
||||
/// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
|
||||
//------------------------------------------------------------------
|
||||
virtual lldb::ThreadPlanSP
|
||||
QueueThreadPlanForStepOverBreakpointPlan (bool abort_other_plans);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Queues the plan used to step one instruction from the current PC of \a thread.
|
||||
///
|
||||
@ -728,14 +662,6 @@ class Thread :
|
||||
bool stop_others,
|
||||
uint32_t frame_idx);
|
||||
|
||||
virtual lldb::ThreadPlanSP
|
||||
QueueThreadPlanForCallFunction (bool abort_other_plans,
|
||||
Address& function,
|
||||
lldb::addr_t arg,
|
||||
bool stop_other_threads,
|
||||
bool unwind_on_error = false,
|
||||
bool ignore_breakpoints = true);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Thread Plan accessors:
|
||||
//------------------------------------------------------------------
|
||||
@ -879,7 +805,7 @@ class Thread :
|
||||
|
||||
void
|
||||
SetTracer (lldb::ThreadPlanTracerSP &tracer_sp);
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Get the thread index ID. The index ID that is guaranteed to not
|
||||
// be re-used by a process. They start at 1 and increase with each
|
||||
@ -888,8 +814,25 @@ class Thread :
|
||||
//------------------------------------------------------------------
|
||||
uint32_t
|
||||
GetIndexID () const;
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Get the originating thread's index ID.
|
||||
// In the case of an "extended" thread -- a thread which represents
|
||||
// the stack that enqueued/spawned work that is currently executing --
|
||||
// we need to provide the IndexID of the thread that actually did
|
||||
// this work. We don't want to just masquerade as that thread's IndexID
|
||||
// by using it in our own IndexID because that way leads to madness -
|
||||
// but the driver program which is iterating over extended threads
|
||||
// may ask for the OriginatingThreadID to display that information
|
||||
// to the user.
|
||||
// Normal threads will return the same thing as GetIndexID();
|
||||
//------------------------------------------------------------------
|
||||
virtual uint32_t
|
||||
GetExtendedBacktraceOriginatingIndexID ()
|
||||
{
|
||||
return GetIndexID ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// The API ID is often the same as the Thread::GetID(), but not in
|
||||
// all cases. Thread::GetID() is the user visible thread ID that
|
||||
@ -1001,6 +944,33 @@ class Thread :
|
||||
void
|
||||
SetShouldReportStop (Vote vote);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// Sets the extended backtrace token for this thread
|
||||
///
|
||||
/// Some Thread subclasses may maintain a token to help with providing
|
||||
/// an extended backtrace. The SystemRuntime plugin will set/request this.
|
||||
///
|
||||
/// @param [in] token
|
||||
//----------------------------------------------------------------------
|
||||
virtual void
|
||||
SetExtendedBacktraceToken (uint64_t token) { }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// Gets the extended backtrace token for this thread
|
||||
///
|
||||
/// Some Thread subclasses may maintain a token to help with providing
|
||||
/// an extended backtrace. The SystemRuntime plugin will set/request this.
|
||||
///
|
||||
/// @return
|
||||
/// The token needed by the SystemRuntime to create an extended backtrace.
|
||||
/// LLDB_INVALID_ADDRESS is returned if no token is available.
|
||||
//----------------------------------------------------------------------
|
||||
virtual uint64_t
|
||||
GetExtendedBacktraceToken ()
|
||||
{
|
||||
return LLDB_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
friend class ThreadPlan;
|
||||
@ -1027,16 +997,6 @@ class Thread :
|
||||
|
||||
typedef std::vector<lldb::ThreadPlanSP> plan_stack;
|
||||
|
||||
virtual bool
|
||||
SaveFrameZeroState (RegisterCheckpoint &checkpoint);
|
||||
|
||||
virtual bool
|
||||
RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint);
|
||||
|
||||
// register_data_sp must be a DataSP passed to ReadAllRegisterValues.
|
||||
bool
|
||||
ResetFrameZeroRegisters (lldb::DataBufferSP register_data_sp);
|
||||
|
||||
virtual lldb_private::Unwind *
|
||||
GetUnwinder ();
|
||||
|
||||
@ -1058,12 +1018,6 @@ class Thread :
|
||||
lldb::StackFrameListSP
|
||||
GetStackFrameList ();
|
||||
|
||||
struct ThreadState
|
||||
{
|
||||
uint32_t orig_stop_id;
|
||||
lldb::StopInfoSP stop_info_sp;
|
||||
RegisterCheckpoint register_backup;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Classes that inherit from Process can see and modify these
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/Core/UserID.h"
|
||||
#include "lldb/Utility/Iterable.h"
|
||||
|
||||
|
||||
// FIXME: Currently this is a thread list with lots of functionality for use only by
|
||||
@ -69,6 +70,15 @@ friend class Process;
|
||||
// is a unique index assigned
|
||||
lldb::ThreadSP
|
||||
GetThreadAtIndex (uint32_t idx, bool can_update = true);
|
||||
|
||||
typedef std::vector<lldb::ThreadSP> collection;
|
||||
typedef LockingAdaptedIterable<collection, lldb::ThreadSP, vector_adapter> ThreadIterable;
|
||||
|
||||
ThreadIterable
|
||||
Threads ()
|
||||
{
|
||||
return ThreadIterable(m_threads, GetMutex());
|
||||
}
|
||||
|
||||
lldb::ThreadSP
|
||||
FindThreadByID (lldb::tid_t tid, bool can_update = true);
|
||||
@ -145,7 +155,6 @@ friend class Process;
|
||||
void
|
||||
NotifySelectedThreadChanged (lldb::tid_t tid);
|
||||
|
||||
typedef std::vector<lldb::ThreadSP> collection;
|
||||
//------------------------------------------------------------------
|
||||
// Classes that inherit from Process can see and modify these
|
||||
//------------------------------------------------------------------
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "lldb/Target/Thread.h"
|
||||
#include "lldb/Target/ThreadPlan.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
class ThreadPlanCallFunction : public ThreadPlan
|
||||
@ -29,25 +31,8 @@ class ThreadPlanCallFunction : public ThreadPlan
|
||||
ThreadPlanCallFunction (Thread &thread,
|
||||
const Address &function,
|
||||
const ClangASTType &return_type,
|
||||
lldb::addr_t arg,
|
||||
bool stop_other_threads,
|
||||
bool unwind_on_error = true,
|
||||
bool ignore_breakpoints = false,
|
||||
lldb::addr_t *this_arg = 0,
|
||||
lldb::addr_t *cmd_arg = 0);
|
||||
|
||||
ThreadPlanCallFunction (Thread &thread,
|
||||
const Address &function,
|
||||
const ClangASTType &return_type,
|
||||
bool stop_other_threads,
|
||||
bool unwind_on_error,
|
||||
bool ignore_breakpoints,
|
||||
lldb::addr_t *arg1_ptr = NULL,
|
||||
lldb::addr_t *arg2_ptr = NULL,
|
||||
lldb::addr_t *arg3_ptr = NULL,
|
||||
lldb::addr_t *arg4_ptr = NULL,
|
||||
lldb::addr_t *arg5_ptr = NULL,
|
||||
lldb::addr_t *arg6_ptr = NULL);
|
||||
llvm::ArrayRef<lldb::addr_t> args,
|
||||
const EvaluateExpressionOptions &options);
|
||||
|
||||
virtual
|
||||
~ThreadPlanCallFunction ();
|
||||
@ -171,10 +156,13 @@ class ThreadPlanCallFunction : public ThreadPlan
|
||||
|
||||
bool m_valid;
|
||||
bool m_stop_other_threads;
|
||||
bool m_unwind_on_error;
|
||||
bool m_ignore_breakpoints;
|
||||
bool m_debug_execution;
|
||||
bool m_trap_exceptions;
|
||||
Address m_function_addr;
|
||||
Address m_start_addr;
|
||||
lldb::addr_t m_function_sp;
|
||||
Thread::RegisterCheckpoint m_register_backup;
|
||||
lldb::ThreadPlanSP m_subplan_sp;
|
||||
LanguageRuntime *m_cxx_language_runtime;
|
||||
LanguageRuntime *m_objc_language_runtime;
|
||||
@ -187,9 +175,9 @@ class ThreadPlanCallFunction : public ThreadPlan
|
||||
ClangASTType m_return_type;
|
||||
lldb::ValueObjectSP m_return_valobj_sp; // If this contains a valid pointer, use the ABI to extract values when complete
|
||||
bool m_takedown_done; // We want to ensure we only do the takedown once. This ensures that.
|
||||
bool m_should_clear_objc_exception_bp;
|
||||
bool m_should_clear_cxx_exception_bp;
|
||||
lldb::addr_t m_stop_address; // This is the address we stopped at. Also set in DoTakedown;
|
||||
bool m_unwind_on_error;
|
||||
bool m_ignore_breakpoints;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunction);
|
||||
};
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "lldb/Target/ThreadPlan.h"
|
||||
#include "lldb/Target/ThreadPlanCallFunction.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
class ThreadPlanCallUserExpression : public ThreadPlanCallFunction
|
||||
@ -27,12 +29,8 @@ class ThreadPlanCallUserExpression : public ThreadPlanCallFunction
|
||||
public:
|
||||
ThreadPlanCallUserExpression (Thread &thread,
|
||||
Address &function,
|
||||
lldb::addr_t arg,
|
||||
bool stop_other_threads,
|
||||
bool unwind_on_error,
|
||||
bool ignore_breakpoints,
|
||||
lldb::addr_t *this_arg,
|
||||
lldb::addr_t *cmd_arg,
|
||||
llvm::ArrayRef<lldb::addr_t> args,
|
||||
const EvaluateExpressionOptions &options,
|
||||
ClangUserExpression::ClangUserExpressionSP &user_expression_sp);
|
||||
|
||||
virtual
|
||||
|
225
include/lldb/Utility/Iterable.h
Normal file
225
include/lldb/Utility/Iterable.h
Normal file
@ -0,0 +1,225 @@
|
||||
//===-- Iterable.h ----------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef liblldb_Iterable_h_
|
||||
#define liblldb_Iterable_h_
|
||||
|
||||
#include "lldb/Host/Mutex.h"
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
|
||||
template <typename I, typename E> E map_adapter(I &iter)
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
template <typename I, typename E> E vector_adapter(I &iter)
|
||||
{
|
||||
return *iter;
|
||||
}
|
||||
|
||||
template <typename C, typename E, E (*A)(typename C::const_iterator &)> class AdaptedConstIterator
|
||||
{
|
||||
public:
|
||||
typedef typename C::const_iterator BackingIterator;
|
||||
private:
|
||||
BackingIterator m_iter;
|
||||
public:
|
||||
// Wrapping constructor
|
||||
AdaptedConstIterator (BackingIterator backing_iterator) :
|
||||
m_iter(backing_iterator)
|
||||
{
|
||||
}
|
||||
|
||||
// Default-constructible
|
||||
AdaptedConstIterator () :
|
||||
m_iter()
|
||||
{
|
||||
}
|
||||
|
||||
// Copy-constructible
|
||||
AdaptedConstIterator (const AdaptedConstIterator &rhs) :
|
||||
m_iter(rhs.m_iter)
|
||||
{
|
||||
}
|
||||
|
||||
// Copy-assignable
|
||||
AdaptedConstIterator &operator= (const AdaptedConstIterator &rhs)
|
||||
{
|
||||
m_iter = rhs.m_iter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Destructible
|
||||
~AdaptedConstIterator () { }
|
||||
|
||||
// Comparable
|
||||
bool operator== (const AdaptedConstIterator &rhs)
|
||||
{
|
||||
return m_iter == rhs.m_iter;
|
||||
}
|
||||
|
||||
bool operator!= (const AdaptedConstIterator &rhs)
|
||||
{
|
||||
return m_iter != rhs.m_iter;
|
||||
}
|
||||
|
||||
// Rvalue dereferenceable
|
||||
E operator* ()
|
||||
{
|
||||
return (*A)(m_iter);
|
||||
}
|
||||
|
||||
E operator-> ()
|
||||
{
|
||||
return (*A)(m_iter);
|
||||
}
|
||||
|
||||
// Offset dereferenceable
|
||||
E operator[] (typename BackingIterator::difference_type offset)
|
||||
{
|
||||
return AdaptedConstIterator(m_iter + offset);
|
||||
}
|
||||
|
||||
// Incrementable
|
||||
AdaptedConstIterator &operator++ ()
|
||||
{
|
||||
m_iter++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Decrementable
|
||||
AdaptedConstIterator &operator-- ()
|
||||
{
|
||||
m_iter--;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Compound assignment
|
||||
AdaptedConstIterator &operator+= (typename BackingIterator::difference_type offset)
|
||||
{
|
||||
m_iter += offset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
AdaptedConstIterator &operator-= (typename BackingIterator::difference_type offset)
|
||||
{
|
||||
m_iter -= offset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Arithmetic
|
||||
AdaptedConstIterator operator+ (typename BackingIterator::difference_type offset)
|
||||
{
|
||||
return AdaptedConstIterator(m_iter + offset);
|
||||
}
|
||||
|
||||
AdaptedConstIterator operator- (typename BackingIterator::difference_type offset)
|
||||
{
|
||||
return AdaptedConstIterator(m_iter - offset);
|
||||
}
|
||||
|
||||
// Comparable
|
||||
bool operator< (AdaptedConstIterator &rhs)
|
||||
{
|
||||
return m_iter < rhs.m_iter;
|
||||
}
|
||||
|
||||
bool operator<= (AdaptedConstIterator &rhs)
|
||||
{
|
||||
return m_iter <= rhs.m_iter;
|
||||
}
|
||||
|
||||
bool operator> (AdaptedConstIterator &rhs)
|
||||
{
|
||||
return m_iter > rhs.m_iter;
|
||||
}
|
||||
|
||||
bool operator>= (AdaptedConstIterator &rhs)
|
||||
{
|
||||
return m_iter >= rhs.m_iter;
|
||||
}
|
||||
|
||||
friend AdaptedConstIterator operator+(typename BackingIterator::difference_type, AdaptedConstIterator &);
|
||||
friend typename BackingIterator::difference_type operator-(AdaptedConstIterator &, AdaptedConstIterator &);
|
||||
friend void swap(AdaptedConstIterator &, AdaptedConstIterator &);
|
||||
};
|
||||
|
||||
template <typename C, typename E, E (*A)(typename C::const_iterator &)>
|
||||
AdaptedConstIterator<C, E, A> operator+ (typename AdaptedConstIterator<C, E, A>::BackingIterator::difference_type offset, AdaptedConstIterator<C, E, A> &rhs)
|
||||
{
|
||||
return rhs.operator+(offset);
|
||||
}
|
||||
|
||||
template <typename C, typename E, E (*A)(typename C::const_iterator &)>
|
||||
typename AdaptedConstIterator<C, E, A>::BackingIterator::difference_type operator- (AdaptedConstIterator<C, E, A> &lhs, AdaptedConstIterator<C, E, A> &rhs)
|
||||
{
|
||||
return(lhs.m_iter - rhs.m_iter);
|
||||
}
|
||||
|
||||
template <typename C, typename E, E (*A)(typename C::const_iterator &)>
|
||||
void swap (AdaptedConstIterator<C, E, A> &lhs, AdaptedConstIterator<C, E, A> &rhs)
|
||||
{
|
||||
std::swap(lhs.m_iter, rhs.m_iter);
|
||||
}
|
||||
|
||||
template <typename C, typename E, E (*A)(typename C::const_iterator &)> class AdaptedIterable
|
||||
{
|
||||
private:
|
||||
const C &m_container;
|
||||
public:
|
||||
AdaptedIterable (const C &container) :
|
||||
m_container(container)
|
||||
{
|
||||
}
|
||||
|
||||
AdaptedConstIterator<C, E, A> begin ()
|
||||
{
|
||||
return AdaptedConstIterator<C, E, A>(m_container.begin());
|
||||
}
|
||||
|
||||
AdaptedConstIterator<C, E, A> end ()
|
||||
{
|
||||
return AdaptedConstIterator<C, E, A>(m_container.end());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename C, typename E, E (*A)(typename C::const_iterator &)> class LockingAdaptedIterable : public AdaptedIterable<C, E, A>
|
||||
{
|
||||
private:
|
||||
Mutex *m_mutex = nullptr;
|
||||
public:
|
||||
LockingAdaptedIterable (C &container, Mutex &mutex) :
|
||||
AdaptedIterable<C,E,A>(container),
|
||||
m_mutex(&mutex)
|
||||
{
|
||||
m_mutex->Lock();
|
||||
}
|
||||
|
||||
LockingAdaptedIterable (LockingAdaptedIterable &&rhs) :
|
||||
AdaptedIterable<C,E,A>(rhs),
|
||||
m_mutex(rhs.m_mutex)
|
||||
{
|
||||
rhs.m_mutex = NULL;
|
||||
}
|
||||
|
||||
~LockingAdaptedIterable ()
|
||||
{
|
||||
if (m_mutex)
|
||||
m_mutex->Unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(LockingAdaptedIterable);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -12,11 +12,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#if defined (__APPLE__)
|
||||
#include <Python/Python.h>
|
||||
#else
|
||||
#include <Python.h>
|
||||
#endif
|
||||
#include "lldb/lldb-python.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
|
@ -684,6 +684,48 @@ namespace lldb {
|
||||
eAddressClassRuntime
|
||||
} AddressClass;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// File Permissions
|
||||
//
|
||||
// Designed to mimic the unix file permission bits so they can be
|
||||
// used with functions that set 'mode_t' to certain values for
|
||||
// permissions.
|
||||
//----------------------------------------------------------------------
|
||||
typedef enum FilePermissions
|
||||
{
|
||||
eFilePermissionsUserRead = (1u << 8),
|
||||
eFilePermissionsUserWrite = (1u << 7),
|
||||
eFilePermissionsUserExecute = (1u << 6),
|
||||
eFilePermissionsGroupRead = (1u << 5),
|
||||
eFilePermissionsGroupWrite = (1u << 4),
|
||||
eFilePermissionsGroupExecute = (1u << 3),
|
||||
eFilePermissionsWorldRead = (1u << 2),
|
||||
eFilePermissionsWorldWrite = (1u << 1),
|
||||
eFilePermissionsWorldExecute = (1u << 0),
|
||||
|
||||
eFilePermissionsUserRW = (eFilePermissionsUserRead | eFilePermissionsUserWrite | 0 ),
|
||||
eFileFilePermissionsUserRX = (eFilePermissionsUserRead | 0 | eFilePermissionsUserExecute ),
|
||||
eFilePermissionsUserRWX = (eFilePermissionsUserRead | eFilePermissionsUserWrite | eFilePermissionsUserExecute ),
|
||||
|
||||
eFilePermissionsGroupRW = (eFilePermissionsGroupRead | eFilePermissionsGroupWrite | 0 ),
|
||||
eFilePermissionsGroupRX = (eFilePermissionsGroupRead | 0 | eFilePermissionsGroupExecute ),
|
||||
eFilePermissionsGroupRWX = (eFilePermissionsGroupRead | eFilePermissionsGroupWrite | eFilePermissionsGroupExecute ),
|
||||
|
||||
eFilePermissionsWorldRW = (eFilePermissionsWorldRead | eFilePermissionsWorldWrite | 0 ),
|
||||
eFilePermissionsWorldRX = (eFilePermissionsWorldRead | 0 | eFilePermissionsWorldExecute ),
|
||||
eFilePermissionsWorldRWX = (eFilePermissionsWorldRead | eFilePermissionsWorldWrite | eFilePermissionsWorldExecute ),
|
||||
|
||||
eFilePermissionsEveryoneR = (eFilePermissionsUserRead | eFilePermissionsGroupRead | eFilePermissionsWorldRead ),
|
||||
eFilePermissionsEveryoneW = (eFilePermissionsUserWrite | eFilePermissionsGroupWrite | eFilePermissionsWorldWrite ),
|
||||
eFilePermissionsEveryoneX = (eFilePermissionsUserExecute | eFilePermissionsGroupExecute | eFilePermissionsWorldExecute ),
|
||||
|
||||
eFilePermissionsEveryoneRW = (eFilePermissionsEveryoneR | eFilePermissionsEveryoneW | 0 ),
|
||||
eFilePermissionsEveryoneRX = (eFilePermissionsEveryoneR | 0 | eFilePermissionsEveryoneX ),
|
||||
eFilePermissionsEveryoneRWX = (eFilePermissionsEveryoneR | eFilePermissionsEveryoneW | eFilePermissionsEveryoneX ),
|
||||
eFilePermissionsFileDefault = eFilePermissionsUserRW,
|
||||
eFilePermissionsDirectoryDefault = eFilePermissionsUserRWX,
|
||||
} FilePermissions;
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
|
||||
|
@ -97,6 +97,7 @@ class FileSpecList;
|
||||
class Flags;
|
||||
class TypeCategoryImpl;
|
||||
class FormatManager;
|
||||
class FormattersMatchCandidate;
|
||||
class FuncUnwinders;
|
||||
class Function;
|
||||
class FunctionInfo;
|
||||
@ -162,6 +163,7 @@ class PythonDictionary;
|
||||
class PythonInteger;
|
||||
class PythonObject;
|
||||
class PythonString;
|
||||
class RegisterCheckpoint;
|
||||
class RegisterContext;
|
||||
class RegisterLocation;
|
||||
class RegisterLocationList;
|
||||
@ -329,6 +331,7 @@ namespace lldb {
|
||||
typedef std::shared_ptr<lldb_private::ProcessLaunchInfo> ProcessLaunchInfoSP;
|
||||
typedef std::weak_ptr<lldb_private::Process> ProcessWP;
|
||||
typedef std::shared_ptr<lldb_private::Property> PropertySP;
|
||||
typedef std::shared_ptr<lldb_private::RegisterCheckpoint> RegisterCheckpointSP;
|
||||
typedef std::shared_ptr<lldb_private::RegisterContext> RegisterContextSP;
|
||||
typedef std::shared_ptr<lldb_private::RegularExpression> RegularExpressionSP;
|
||||
typedef std::shared_ptr<lldb_private::ScriptInterpreterObject> ScriptInterpreterObjectSP;
|
||||
|
@ -133,7 +133,8 @@ typedef enum ExecutionResults
|
||||
eExecutionDiscarded,
|
||||
eExecutionInterrupted,
|
||||
eExecutionHitBreakpoint,
|
||||
eExecutionTimedOut
|
||||
eExecutionTimedOut,
|
||||
eExecutionStoppedForDebug
|
||||
} ExecutionResults;
|
||||
|
||||
typedef enum ObjCRuntimeVersions {
|
||||
|
@ -18,11 +18,7 @@
|
||||
|
||||
#else
|
||||
|
||||
#if defined (__APPLE__)
|
||||
#include <Python/Python.h>
|
||||
#else
|
||||
#include <Python.h>
|
||||
#endif
|
||||
|
||||
#endif // LLDB_DISABLE_PYTHON
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Core/State.h"
|
||||
#include "lldb/DataFormatters/DataVisualization.h"
|
||||
#include "lldb/Host/DynamicLibrary.h"
|
||||
#include "lldb/Interpreter/Args.h"
|
||||
#include "lldb/Interpreter/CommandInterpreter.h"
|
||||
#include "lldb/Interpreter/OptionGroupPlatform.h"
|
||||
@ -47,6 +48,41 @@
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
|
||||
static lldb::DynamicLibrarySP
|
||||
LoadPlugin (const lldb::DebuggerSP &debugger_sp, const FileSpec& spec, Error& error)
|
||||
{
|
||||
lldb::DynamicLibrarySP dynlib_sp(new lldb_private::DynamicLibrary(spec));
|
||||
if (dynlib_sp && dynlib_sp->IsValid())
|
||||
{
|
||||
typedef bool (*LLDBCommandPluginInit) (lldb::SBDebugger& debugger);
|
||||
|
||||
lldb::SBDebugger debugger_sb(debugger_sp);
|
||||
// This calls the bool lldb::PluginInitialize(lldb::SBDebugger debugger) function.
|
||||
// TODO: mangle this differently for your system - on OSX, the first underscore needs to be removed and the second one stays
|
||||
LLDBCommandPluginInit init_func = dynlib_sp->GetSymbol<LLDBCommandPluginInit>("_ZN4lldb16PluginInitializeENS_10SBDebuggerE");
|
||||
if (init_func)
|
||||
{
|
||||
if (init_func(debugger_sb))
|
||||
return dynlib_sp;
|
||||
else
|
||||
error.SetErrorString("plug-in refused to load (lldb::PluginInitialize(lldb::SBDebugger) returned false)");
|
||||
}
|
||||
else
|
||||
{
|
||||
error.SetErrorString("plug-in is missing the required initialization: lldb::PluginInitialize(lldb::SBDebugger)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (spec.Exists())
|
||||
error.SetErrorString("this file does not represent a loadable dylib");
|
||||
else
|
||||
error.SetErrorString("no such file");
|
||||
}
|
||||
return lldb::DynamicLibrarySP();
|
||||
}
|
||||
|
||||
void
|
||||
SBDebugger::Initialize ()
|
||||
{
|
||||
@ -57,7 +93,7 @@ SBDebugger::Initialize ()
|
||||
|
||||
SBCommandInterpreter::InitializeSWIG ();
|
||||
|
||||
Debugger::Initialize();
|
||||
Debugger::Initialize(LoadPlugin);
|
||||
}
|
||||
|
||||
void
|
||||
@ -804,6 +840,42 @@ SBDebugger::SetSelectedTarget (SBTarget &sb_target)
|
||||
}
|
||||
}
|
||||
|
||||
SBPlatform
|
||||
SBDebugger::GetSelectedPlatform()
|
||||
{
|
||||
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
||||
|
||||
SBPlatform sb_platform;
|
||||
DebuggerSP debugger_sp(m_opaque_sp);
|
||||
if (debugger_sp)
|
||||
{
|
||||
sb_platform.SetSP(debugger_sp->GetPlatformList().GetSelectedPlatform());
|
||||
}
|
||||
if (log)
|
||||
{
|
||||
log->Printf ("SBDebugger(%p)::GetSelectedPlatform () => SBPlatform(%p): %s", m_opaque_sp.get(),
|
||||
sb_platform.GetSP().get(), sb_platform.GetName());
|
||||
}
|
||||
return sb_platform;
|
||||
}
|
||||
|
||||
void
|
||||
SBDebugger::SetSelectedPlatform(SBPlatform &sb_platform)
|
||||
{
|
||||
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
||||
|
||||
DebuggerSP debugger_sp(m_opaque_sp);
|
||||
if (debugger_sp)
|
||||
{
|
||||
debugger_sp->GetPlatformList().SetSelectedPlatform(sb_platform.GetSP());
|
||||
}
|
||||
if (log)
|
||||
{
|
||||
log->Printf ("SBDebugger(%p)::SetSelectedPlatform (SBPlatform(%p) %s)", m_opaque_sp.get(),
|
||||
sb_platform.GetSP().get(), sb_platform.GetName());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SBDebugger::DispatchInput (void* baton, const void *data, size_t data_len)
|
||||
{
|
||||
|
@ -104,13 +104,25 @@ SBExpressionOptions::SetTimeoutInMicroSeconds (uint32_t timeout)
|
||||
bool
|
||||
SBExpressionOptions::GetTryAllThreads () const
|
||||
{
|
||||
return m_opaque_ap->GetRunOthers ();
|
||||
return m_opaque_ap->GetTryAllThreads ();
|
||||
}
|
||||
|
||||
void
|
||||
SBExpressionOptions::SetTryAllThreads (bool run_others)
|
||||
{
|
||||
m_opaque_ap->SetRunOthers (run_others);
|
||||
m_opaque_ap->SetTryAllThreads (run_others);
|
||||
}
|
||||
|
||||
bool
|
||||
SBExpressionOptions::GetTrapExceptions () const
|
||||
{
|
||||
return m_opaque_ap->GetTrapExceptions ();
|
||||
}
|
||||
|
||||
void
|
||||
SBExpressionOptions::SetTrapExceptions (bool trap_exceptions)
|
||||
{
|
||||
m_opaque_ap->SetTrapExceptions (trap_exceptions);
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions *
|
||||
|
@ -121,6 +121,24 @@ SBFileSpec::GetDirectory() const
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
SBFileSpec::SetFilename(const char *filename)
|
||||
{
|
||||
if (filename && filename[0])
|
||||
m_opaque_ap->GetFilename().SetCString(filename);
|
||||
else
|
||||
m_opaque_ap->GetFilename().Clear();
|
||||
}
|
||||
|
||||
void
|
||||
SBFileSpec::SetDirectory(const char *directory)
|
||||
{
|
||||
if (directory && directory[0])
|
||||
m_opaque_ap->GetDirectory().SetCString(directory);
|
||||
else
|
||||
m_opaque_ap->GetDirectory().Clear();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SBFileSpec::GetPath (char *dst_path, size_t dst_len) const
|
||||
{
|
||||
|
@ -162,6 +162,27 @@ SBModule::SetPlatformFileSpec (const lldb::SBFileSpec &platform_file)
|
||||
return result;
|
||||
}
|
||||
|
||||
lldb::SBFileSpec
|
||||
SBModule::GetRemoteInstallFileSpec ()
|
||||
{
|
||||
SBFileSpec sb_file_spec;
|
||||
ModuleSP module_sp (GetSP ());
|
||||
if (module_sp)
|
||||
sb_file_spec.SetFileSpec (module_sp->GetRemoteInstallFileSpec());
|
||||
return sb_file_spec;
|
||||
}
|
||||
|
||||
bool
|
||||
SBModule::SetRemoteInstallFileSpec (lldb::SBFileSpec &file)
|
||||
{
|
||||
ModuleSP module_sp (GetSP ());
|
||||
if (module_sp)
|
||||
{
|
||||
module_sp->SetRemoteInstallFileSpec(file.ref());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const uint8_t *
|
||||
|
632
source/API/SBPlatform.cpp
Normal file
632
source/API/SBPlatform.cpp
Normal file
@ -0,0 +1,632 @@
|
||||
//===-- SBPlatform.cpp ------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/API/SBPlatform.h"
|
||||
#include "lldb/API/SBError.h"
|
||||
#include "lldb/API/SBFileSpec.h"
|
||||
#include "lldb/Core/ArchSpec.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Host/File.h"
|
||||
#include "lldb/Interpreter/Args.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
#include "lldb/Target/Platform.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// PlatformConnectOptions
|
||||
//----------------------------------------------------------------------
|
||||
struct PlatformConnectOptions {
|
||||
PlatformConnectOptions(const char *url = NULL) :
|
||||
m_url(),
|
||||
m_rsync_options(),
|
||||
m_rsync_remote_path_prefix(),
|
||||
m_rsync_enabled(false),
|
||||
m_rsync_omit_hostname_from_remote_path(false),
|
||||
m_local_cache_directory ()
|
||||
{
|
||||
if (url && url[0])
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
~PlatformConnectOptions()
|
||||
{
|
||||
}
|
||||
|
||||
std::string m_url;
|
||||
std::string m_rsync_options;
|
||||
std::string m_rsync_remote_path_prefix;
|
||||
bool m_rsync_enabled;
|
||||
bool m_rsync_omit_hostname_from_remote_path;
|
||||
ConstString m_local_cache_directory;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// PlatformShellCommand
|
||||
//----------------------------------------------------------------------
|
||||
struct PlatformShellCommand {
|
||||
PlatformShellCommand(const char *shell_command = NULL) :
|
||||
m_command(),
|
||||
m_working_dir(),
|
||||
m_status(0),
|
||||
m_signo(0),
|
||||
m_timeout_sec(UINT32_MAX)
|
||||
{
|
||||
if (shell_command && shell_command[0])
|
||||
m_command = shell_command;
|
||||
}
|
||||
|
||||
~PlatformShellCommand()
|
||||
{
|
||||
}
|
||||
|
||||
std::string m_command;
|
||||
std::string m_working_dir;
|
||||
std::string m_output;
|
||||
int m_status;
|
||||
int m_signo;
|
||||
uint32_t m_timeout_sec;
|
||||
};
|
||||
//----------------------------------------------------------------------
|
||||
// SBPlatformConnectOptions
|
||||
//----------------------------------------------------------------------
|
||||
SBPlatformConnectOptions::SBPlatformConnectOptions (const char *url) :
|
||||
m_opaque_ptr(new PlatformConnectOptions(url))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SBPlatformConnectOptions::SBPlatformConnectOptions(const SBPlatformConnectOptions &rhs) :
|
||||
m_opaque_ptr(new PlatformConnectOptions())
|
||||
{
|
||||
*m_opaque_ptr = *rhs.m_opaque_ptr;
|
||||
}
|
||||
|
||||
SBPlatformConnectOptions::~SBPlatformConnectOptions ()
|
||||
{
|
||||
delete m_opaque_ptr;
|
||||
}
|
||||
|
||||
void
|
||||
SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs)
|
||||
{
|
||||
*m_opaque_ptr = *rhs.m_opaque_ptr;
|
||||
}
|
||||
|
||||
const char *
|
||||
SBPlatformConnectOptions::GetURL()
|
||||
{
|
||||
if (m_opaque_ptr->m_url.empty())
|
||||
return NULL;
|
||||
return m_opaque_ptr->m_url.c_str();
|
||||
}
|
||||
|
||||
void
|
||||
SBPlatformConnectOptions::SetURL(const char *url)
|
||||
{
|
||||
if (url && url[0])
|
||||
m_opaque_ptr->m_url = url;
|
||||
else
|
||||
m_opaque_ptr->m_url.clear();
|
||||
}
|
||||
|
||||
bool
|
||||
SBPlatformConnectOptions::GetRsyncEnabled()
|
||||
{
|
||||
return m_opaque_ptr->m_rsync_enabled;
|
||||
}
|
||||
|
||||
void
|
||||
SBPlatformConnectOptions::EnableRsync (const char *options,
|
||||
const char *remote_path_prefix,
|
||||
bool omit_hostname_from_remote_path)
|
||||
{
|
||||
m_opaque_ptr->m_rsync_enabled = true;
|
||||
m_opaque_ptr->m_rsync_omit_hostname_from_remote_path = omit_hostname_from_remote_path;
|
||||
if (remote_path_prefix && remote_path_prefix[0])
|
||||
m_opaque_ptr->m_rsync_remote_path_prefix = remote_path_prefix;
|
||||
else
|
||||
m_opaque_ptr->m_rsync_remote_path_prefix.clear();
|
||||
|
||||
if (options && options[0])
|
||||
m_opaque_ptr->m_rsync_options = options;
|
||||
else
|
||||
m_opaque_ptr->m_rsync_options.clear();
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
SBPlatformConnectOptions::DisableRsync ()
|
||||
{
|
||||
m_opaque_ptr->m_rsync_enabled = false;
|
||||
}
|
||||
|
||||
const char *
|
||||
SBPlatformConnectOptions::GetLocalCacheDirectory()
|
||||
{
|
||||
return m_opaque_ptr->m_local_cache_directory.GetCString();
|
||||
}
|
||||
|
||||
void
|
||||
SBPlatformConnectOptions::SetLocalCacheDirectory(const char *path)
|
||||
{
|
||||
if (path && path[0])
|
||||
m_opaque_ptr->m_local_cache_directory.SetCString(path);
|
||||
else
|
||||
m_opaque_ptr->m_local_cache_directory = ConstString();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// SBPlatformShellCommand
|
||||
//----------------------------------------------------------------------
|
||||
SBPlatformShellCommand::SBPlatformShellCommand (const char *shell_command) :
|
||||
m_opaque_ptr(new PlatformShellCommand(shell_command))
|
||||
{
|
||||
}
|
||||
|
||||
SBPlatformShellCommand::SBPlatformShellCommand (const SBPlatformShellCommand &rhs) :
|
||||
m_opaque_ptr(new PlatformShellCommand())
|
||||
{
|
||||
*m_opaque_ptr = *rhs.m_opaque_ptr;
|
||||
}
|
||||
|
||||
SBPlatformShellCommand::~SBPlatformShellCommand()
|
||||
{
|
||||
delete m_opaque_ptr;
|
||||
}
|
||||
|
||||
void
|
||||
SBPlatformShellCommand::Clear()
|
||||
{
|
||||
m_opaque_ptr->m_output = std::move(std::string());
|
||||
m_opaque_ptr->m_status = 0;
|
||||
m_opaque_ptr->m_signo = 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
SBPlatformShellCommand::GetCommand()
|
||||
{
|
||||
if (m_opaque_ptr->m_command.empty())
|
||||
return NULL;
|
||||
return m_opaque_ptr->m_command.c_str();
|
||||
}
|
||||
|
||||
void
|
||||
SBPlatformShellCommand::SetCommand(const char *shell_command)
|
||||
{
|
||||
if (shell_command && shell_command[0])
|
||||
m_opaque_ptr->m_command = shell_command;
|
||||
else
|
||||
m_opaque_ptr->m_command.clear();
|
||||
}
|
||||
|
||||
const char *
|
||||
SBPlatformShellCommand::GetWorkingDirectory ()
|
||||
{
|
||||
if (m_opaque_ptr->m_working_dir.empty())
|
||||
return NULL;
|
||||
return m_opaque_ptr->m_working_dir.c_str();
|
||||
}
|
||||
|
||||
void
|
||||
SBPlatformShellCommand::SetWorkingDirectory (const char *path)
|
||||
{
|
||||
if (path && path[0])
|
||||
m_opaque_ptr->m_working_dir = path;
|
||||
else
|
||||
m_opaque_ptr->m_working_dir.clear();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SBPlatformShellCommand::GetTimeoutSeconds ()
|
||||
{
|
||||
return m_opaque_ptr->m_timeout_sec;
|
||||
}
|
||||
|
||||
void
|
||||
SBPlatformShellCommand::SetTimeoutSeconds (uint32_t sec)
|
||||
{
|
||||
m_opaque_ptr->m_timeout_sec = sec;
|
||||
}
|
||||
|
||||
int
|
||||
SBPlatformShellCommand::GetSignal ()
|
||||
{
|
||||
return m_opaque_ptr->m_signo;
|
||||
}
|
||||
|
||||
int
|
||||
SBPlatformShellCommand::GetStatus ()
|
||||
{
|
||||
return m_opaque_ptr->m_status;
|
||||
}
|
||||
|
||||
const char *
|
||||
SBPlatformShellCommand::GetOutput ()
|
||||
{
|
||||
if (m_opaque_ptr->m_output.empty())
|
||||
return NULL;
|
||||
return m_opaque_ptr->m_output.c_str();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// SBPlatform
|
||||
//----------------------------------------------------------------------
|
||||
SBPlatform::SBPlatform () :
|
||||
m_opaque_sp ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SBPlatform::SBPlatform (const char *platform_name) :
|
||||
m_opaque_sp ()
|
||||
{
|
||||
Error error;
|
||||
m_opaque_sp = Platform::Create (platform_name, error);
|
||||
}
|
||||
|
||||
SBPlatform::~SBPlatform()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
SBPlatform::IsValid () const
|
||||
{
|
||||
return m_opaque_sp.get() != NULL;
|
||||
}
|
||||
|
||||
void
|
||||
SBPlatform::Clear ()
|
||||
{
|
||||
m_opaque_sp.reset();
|
||||
}
|
||||
|
||||
const char *
|
||||
SBPlatform::GetName ()
|
||||
{
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
return platform_sp->GetName().GetCString();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lldb::PlatformSP
|
||||
SBPlatform::GetSP () const
|
||||
{
|
||||
return m_opaque_sp;
|
||||
}
|
||||
|
||||
void
|
||||
SBPlatform::SetSP (const lldb::PlatformSP& platform_sp)
|
||||
{
|
||||
m_opaque_sp = platform_sp;
|
||||
}
|
||||
|
||||
const char *
|
||||
SBPlatform::GetWorkingDirectory()
|
||||
{
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
return platform_sp->GetWorkingDirectory().GetCString();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
SBPlatform::SetWorkingDirectory(const char *path)
|
||||
{
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
{
|
||||
if (path)
|
||||
platform_sp->SetWorkingDirectory(ConstString(path));
|
||||
else
|
||||
platform_sp->SetWorkingDirectory(ConstString());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
SBError
|
||||
SBPlatform::ConnectRemote (SBPlatformConnectOptions &connect_options)
|
||||
{
|
||||
SBError sb_error;
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp && connect_options.GetURL())
|
||||
{
|
||||
Args args;
|
||||
args.AppendArgument(connect_options.GetURL());
|
||||
sb_error.ref() = platform_sp->ConnectRemote(args);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_error.SetErrorString("invalid platform");
|
||||
}
|
||||
return sb_error;
|
||||
}
|
||||
|
||||
void
|
||||
SBPlatform::DisconnectRemote ()
|
||||
{
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
platform_sp->DisconnectRemote();
|
||||
}
|
||||
|
||||
bool
|
||||
SBPlatform::IsConnected()
|
||||
{
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
platform_sp->IsConnected();
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *
|
||||
SBPlatform::GetTriple()
|
||||
{
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
{
|
||||
ArchSpec arch(platform_sp->GetRemoteSystemArchitecture());
|
||||
if (arch.IsValid())
|
||||
{
|
||||
// Const-ify the string so we don't need to worry about the lifetime of the string
|
||||
return ConstString(arch.GetTriple().getTriple().c_str()).GetCString();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
SBPlatform::GetOSBuild()
|
||||
{
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
{
|
||||
std::string s;
|
||||
if (platform_sp->GetOSBuildString(s))
|
||||
{
|
||||
if (!s.empty())
|
||||
{
|
||||
// Const-ify the string so we don't need to worry about the lifetime of the string
|
||||
return ConstString(s.c_str()).GetCString();
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
SBPlatform::GetOSDescription()
|
||||
{
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
{
|
||||
std::string s;
|
||||
if (platform_sp->GetOSKernelDescription(s))
|
||||
{
|
||||
if (!s.empty())
|
||||
{
|
||||
// Const-ify the string so we don't need to worry about the lifetime of the string
|
||||
return ConstString(s.c_str()).GetCString();
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
SBPlatform::GetHostname ()
|
||||
{
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
return platform_sp->GetHostname();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SBPlatform::GetOSMajorVersion ()
|
||||
{
|
||||
uint32_t major, minor, update;
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
|
||||
return major;
|
||||
return UINT32_MAX;
|
||||
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SBPlatform::GetOSMinorVersion ()
|
||||
{
|
||||
uint32_t major, minor, update;
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
|
||||
return minor;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SBPlatform::GetOSUpdateVersion ()
|
||||
{
|
||||
uint32_t major, minor, update;
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
|
||||
return update;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
SBError
|
||||
SBPlatform::Get (SBFileSpec &src,
|
||||
SBFileSpec &dst)
|
||||
{
|
||||
SBError sb_error;
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
{
|
||||
sb_error.ref() = platform_sp->GetFile(src.ref(), dst.ref());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_error.SetErrorString("invalid platform");
|
||||
}
|
||||
return sb_error;
|
||||
}
|
||||
|
||||
SBError
|
||||
SBPlatform::Put (SBFileSpec &src,
|
||||
SBFileSpec &dst)
|
||||
{
|
||||
SBError sb_error;
|
||||
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
{
|
||||
if (src.Exists())
|
||||
{
|
||||
uint32_t permissions = src.ref().GetPermissions();
|
||||
if (permissions == 0)
|
||||
{
|
||||
if (src.ref().GetFileType() == FileSpec::eFileTypeDirectory)
|
||||
permissions = eFilePermissionsDirectoryDefault;
|
||||
else
|
||||
permissions = eFilePermissionsFileDefault;
|
||||
}
|
||||
|
||||
sb_error.ref() = platform_sp->PutFile(src.ref(),
|
||||
dst.ref(),
|
||||
permissions);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_error.ref().SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_error.SetErrorString("invalid platform");
|
||||
}
|
||||
return sb_error;
|
||||
}
|
||||
|
||||
SBError
|
||||
SBPlatform::Install (SBFileSpec &src,
|
||||
SBFileSpec &dst)
|
||||
{
|
||||
SBError sb_error;
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
{
|
||||
if (src.Exists())
|
||||
{
|
||||
sb_error.ref() = platform_sp->Install(src.ref(), dst.ref());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_error.ref().SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_error.SetErrorString("invalid platform");
|
||||
}
|
||||
return sb_error;
|
||||
}
|
||||
|
||||
|
||||
SBError
|
||||
SBPlatform::Run (SBPlatformShellCommand &shell_command)
|
||||
{
|
||||
SBError sb_error;
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
{
|
||||
if (platform_sp->IsConnected())
|
||||
{
|
||||
const char *command = shell_command.GetCommand();
|
||||
if (command)
|
||||
{
|
||||
const char *working_dir = shell_command.GetWorkingDirectory();
|
||||
if (working_dir == NULL)
|
||||
{
|
||||
working_dir = platform_sp->GetWorkingDirectory().GetCString();
|
||||
if (working_dir)
|
||||
shell_command.SetWorkingDirectory(working_dir);
|
||||
}
|
||||
sb_error.ref() = platform_sp->RunShellCommand(command,
|
||||
working_dir,
|
||||
&shell_command.m_opaque_ptr->m_status,
|
||||
&shell_command.m_opaque_ptr->m_signo,
|
||||
&shell_command.m_opaque_ptr->m_output,
|
||||
shell_command.m_opaque_ptr->m_timeout_sec);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_error.SetErrorString("invalid shell command (empty)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_error.SetErrorString("not connected");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_error.SetErrorString("invalid platform");
|
||||
}
|
||||
return sb_error;
|
||||
}
|
||||
|
||||
SBError
|
||||
SBPlatform::MakeDirectory (const char *path, uint32_t file_permissions)
|
||||
{
|
||||
SBError sb_error;
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
{
|
||||
sb_error.ref() = platform_sp->MakeDirectory(path, file_permissions);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_error.SetErrorString("invalid platform");
|
||||
}
|
||||
return sb_error;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SBPlatform::GetFilePermissions (const char *path)
|
||||
{
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
{
|
||||
uint32_t file_permissions = 0;
|
||||
platform_sp->GetFilePermissions(path, file_permissions);
|
||||
return file_permissions;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
SBError
|
||||
SBPlatform::SetFilePermissions (const char *path, uint32_t file_permissions)
|
||||
{
|
||||
SBError sb_error;
|
||||
PlatformSP platform_sp(GetSP());
|
||||
if (platform_sp)
|
||||
{
|
||||
sb_error.ref() = platform_sp->SetFilePermissions(path, file_permissions);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_error.SetErrorString("invalid platform");
|
||||
}
|
||||
return sb_error;
|
||||
|
||||
}
|
||||
|
@ -1278,7 +1278,7 @@ SBProcess::GetExtendedBacktraceTypeAtIndex (uint32_t idx)
|
||||
if (process_sp && process_sp->GetSystemRuntime())
|
||||
{
|
||||
SystemRuntime *runtime = process_sp->GetSystemRuntime();
|
||||
std::vector<ConstString> names = runtime->GetExtendedBacktraceTypes();
|
||||
const std::vector<ConstString> &names = runtime->GetExtendedBacktraceTypes();
|
||||
if (idx < names.size())
|
||||
{
|
||||
return names[idx].AsCString();
|
||||
|
@ -82,7 +82,7 @@ SBStream::RedirectToFile (const char *path, bool append)
|
||||
uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
|
||||
if (append)
|
||||
open_options |= File::eOpenOptionAppend;
|
||||
stream_file->GetFile().Open (path, open_options, File::ePermissionsDefault);
|
||||
stream_file->GetFile().Open (path, open_options, lldb::eFilePermissionsFileDefault);
|
||||
|
||||
m_opaque_ap.reset (stream_file);
|
||||
|
||||
|
@ -605,6 +605,19 @@ SBTarget::LaunchSimple
|
||||
error);
|
||||
}
|
||||
|
||||
SBError
|
||||
SBTarget::Install()
|
||||
{
|
||||
SBError sb_error;
|
||||
TargetSP target_sp(GetSP());
|
||||
if (target_sp)
|
||||
{
|
||||
Mutex::Locker api_locker (target_sp->GetAPIMutex());
|
||||
sb_error.ref() = target_sp->Install(NULL);
|
||||
}
|
||||
return sb_error;
|
||||
}
|
||||
|
||||
SBProcess
|
||||
SBTarget::Launch
|
||||
(
|
||||
|
@ -433,7 +433,6 @@ SBThread::SetThread (const ThreadSP& lldb_object_sp)
|
||||
m_opaque_sp->SetThreadSP (lldb_object_sp);
|
||||
}
|
||||
|
||||
|
||||
lldb::tid_t
|
||||
SBThread::GetThreadID () const
|
||||
{
|
||||
@ -1283,7 +1282,7 @@ SBThread::GetDescription (SBStream &description) const
|
||||
}
|
||||
|
||||
SBThread
|
||||
SBThread::GetExtendedBacktrace (const char *type)
|
||||
SBThread::GetExtendedBacktraceThread (const char *type)
|
||||
{
|
||||
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
||||
Mutex::Locker api_locker;
|
||||
@ -1295,24 +1294,50 @@ SBThread::GetExtendedBacktrace (const char *type)
|
||||
Process::StopLocker stop_locker;
|
||||
if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
|
||||
{
|
||||
ThreadSP real_thread(exe_ctx.GetThreadPtr());
|
||||
ThreadSP real_thread(exe_ctx.GetThreadSP());
|
||||
if (real_thread)
|
||||
{
|
||||
ConstString type_const (type);
|
||||
SystemRuntime *runtime = exe_ctx.GetProcessPtr()->GetSystemRuntime();
|
||||
if (runtime)
|
||||
Process *process = exe_ctx.GetProcessPtr();
|
||||
if (process)
|
||||
{
|
||||
ThreadSP origin_thread = runtime->GetExtendedBacktrace (real_thread, type_const);
|
||||
sb_origin_thread.SetThread (origin_thread);
|
||||
SystemRuntime *runtime = process->GetSystemRuntime();
|
||||
if (runtime)
|
||||
{
|
||||
ThreadSP new_thread_sp (runtime->GetExtendedBacktraceThread (real_thread, type_const));
|
||||
if (new_thread_sp)
|
||||
{
|
||||
// Save this in the Process' ExtendedThreadList so a strong pointer retains the
|
||||
// object.
|
||||
process->GetExtendedThreadList().AddThread (new_thread_sp);
|
||||
sb_origin_thread.SetThread (new_thread_sp);
|
||||
if (log)
|
||||
{
|
||||
const char *queue_name = new_thread_sp->GetQueueName();
|
||||
if (queue_name == NULL)
|
||||
queue_name = "";
|
||||
log->Printf ("SBThread(%p)::GetExtendedBacktraceThread() => new extended Thread created (%p) with queue_id 0x%" PRIx64 " queue name '%s'", exe_ctx.GetThreadPtr(), new_thread_sp.get(), new_thread_sp->GetQueueID(), queue_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("SBThread(%p)::GetExtendedBacktrace() => error: process is running", exe_ctx.GetThreadPtr());
|
||||
log->Printf ("SBThread(%p)::GetExtendedBacktraceThread() => error: process is running", exe_ctx.GetThreadPtr());
|
||||
}
|
||||
}
|
||||
|
||||
return sb_origin_thread;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SBThread::GetExtendedBacktraceOriginatingIndexID ()
|
||||
{
|
||||
ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
|
||||
if (thread_sp)
|
||||
return thread_sp->GetExtendedBacktraceOriginatingIndexID();
|
||||
return LLDB_INVALID_INDEX32;
|
||||
}
|
||||
|
@ -114,6 +114,12 @@ Breakpoint::GetLocationAtIndex (size_t index)
|
||||
return m_locations.GetByIndex(index);
|
||||
}
|
||||
|
||||
void
|
||||
Breakpoint::RemoveInvalidLocations (const ArchSpec &arch)
|
||||
{
|
||||
m_locations.RemoveInvalidLocations(arch);
|
||||
}
|
||||
|
||||
// For each of the overall options we need to decide how they propagate to
|
||||
// the location options. This will determine the precedence of options on
|
||||
// the breakpoint vs. its locations.
|
||||
|
@ -68,13 +68,21 @@ BreakpointList::Remove (break_id_t break_id, bool notify)
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
BreakpointList::RemoveInvalidLocations (const ArchSpec &arch)
|
||||
{
|
||||
Mutex::Locker locker(m_mutex);
|
||||
for (const auto &bp_sp : m_breakpoints)
|
||||
bp_sp->RemoveInvalidLocations(arch);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BreakpointList::SetEnabledAll (bool enabled)
|
||||
{
|
||||
Mutex::Locker locker(m_mutex);
|
||||
bp_collection::iterator pos, end = m_breakpoints.end();
|
||||
for (pos = m_breakpoints.begin(); pos != end; ++pos)
|
||||
(*pos)->SetEnabled (enabled);
|
||||
for (const auto &bp_sp : m_breakpoints)
|
||||
bp_sp->SetEnabled (enabled);
|
||||
}
|
||||
|
||||
|
||||
@ -163,10 +171,8 @@ BreakpointList::Dump (Stream *s) const
|
||||
s->Indent();
|
||||
s->Printf("BreakpointList with %u Breakpoints:\n", (uint32_t)m_breakpoints.size());
|
||||
s->IndentMore();
|
||||
bp_collection::const_iterator pos;
|
||||
bp_collection::const_iterator end = m_breakpoints.end();
|
||||
for (pos = m_breakpoints.begin(); pos != end; ++pos)
|
||||
(*pos)->Dump(s);
|
||||
for (const auto &bp_sp : m_breakpoints)
|
||||
bp_sp->Dump(s);
|
||||
s->IndentLess();
|
||||
}
|
||||
|
||||
@ -207,10 +213,8 @@ void
|
||||
BreakpointList::UpdateBreakpoints (ModuleList& module_list, bool added, bool delete_locations)
|
||||
{
|
||||
Mutex::Locker locker(m_mutex);
|
||||
bp_collection::iterator end = m_breakpoints.end();
|
||||
bp_collection::iterator pos;
|
||||
for (pos = m_breakpoints.begin(); pos != end; ++pos)
|
||||
(*pos)->ModulesChanged (module_list, added, delete_locations);
|
||||
for (const auto &bp_sp : m_breakpoints)
|
||||
bp_sp->ModulesChanged (module_list, added, delete_locations);
|
||||
|
||||
}
|
||||
|
||||
@ -218,10 +222,8 @@ void
|
||||
BreakpointList::UpdateBreakpointsWhenModuleIsReplaced (ModuleSP old_module_sp, ModuleSP new_module_sp)
|
||||
{
|
||||
Mutex::Locker locker(m_mutex);
|
||||
bp_collection::iterator end = m_breakpoints.end();
|
||||
bp_collection::iterator pos;
|
||||
for (pos = m_breakpoints.begin(); pos != end; ++pos)
|
||||
(*pos)->ModuleReplaced (old_module_sp, new_module_sp);
|
||||
for (const auto &bp_sp : m_breakpoints)
|
||||
bp_sp->ModuleReplaced (old_module_sp, new_module_sp);
|
||||
|
||||
}
|
||||
|
||||
@ -229,10 +231,8 @@ void
|
||||
BreakpointList::ClearAllBreakpointSites ()
|
||||
{
|
||||
Mutex::Locker locker(m_mutex);
|
||||
bp_collection::iterator end = m_breakpoints.end();
|
||||
bp_collection::iterator pos;
|
||||
for (pos = m_breakpoints.begin(); pos != end; ++pos)
|
||||
(*pos)->ClearAllBreakpointSites ();
|
||||
for (const auto &bp_sp : m_breakpoints)
|
||||
bp_sp->ClearAllBreakpointSites ();
|
||||
|
||||
}
|
||||
|
||||
|
@ -295,7 +295,7 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetUnwindOnError(true);
|
||||
options.SetIgnoreBreakpoints(true);
|
||||
options.SetRunOthers(true);
|
||||
options.SetTryAllThreads(true);
|
||||
|
||||
Error expr_error;
|
||||
|
||||
|
@ -13,8 +13,11 @@
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "lldb/Breakpoint/BreakpointLocationList.h"
|
||||
|
||||
#include "lldb/Breakpoint/BreakpointLocation.h"
|
||||
#include "lldb/Breakpoint/Breakpoint.h"
|
||||
#include "lldb/Core/ArchSpec.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/Section.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
@ -74,19 +77,25 @@ BreakpointLocationList::FindIDByAddress (const Address &addr)
|
||||
return LLDB_INVALID_BREAK_ID;
|
||||
}
|
||||
|
||||
static bool
|
||||
Compare (BreakpointLocationSP lhs, lldb::break_id_t val)
|
||||
{
|
||||
return lhs->GetID() < val;
|
||||
}
|
||||
|
||||
BreakpointLocationSP
|
||||
BreakpointLocationList::FindByID (lldb::break_id_t break_id) const
|
||||
{
|
||||
BreakpointLocationSP bp_loc_sp;
|
||||
Mutex::Locker locker (m_mutex);
|
||||
// We never remove a breakpoint locations, so the ID can be translated into
|
||||
// the location index by subtracting 1
|
||||
uint32_t idx = break_id - 1;
|
||||
if (idx <= m_locations.size())
|
||||
{
|
||||
bp_loc_sp = m_locations[idx];
|
||||
}
|
||||
return bp_loc_sp;
|
||||
|
||||
collection::const_iterator begin = m_locations.begin(), end = m_locations.end();
|
||||
collection::const_iterator result;
|
||||
result = std::lower_bound(begin, end, break_id, Compare);
|
||||
if (result == end)
|
||||
return bp_loc_sp;
|
||||
else
|
||||
return *(result);
|
||||
}
|
||||
|
||||
size_t
|
||||
@ -286,7 +295,41 @@ BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BreakpointLocationList::RemoveInvalidLocations (const ArchSpec &arch)
|
||||
{
|
||||
Mutex::Locker locker (m_mutex);
|
||||
size_t idx = 0;
|
||||
// Don't cache m_location.size() as it will change since we might
|
||||
// remove locations from our vector...
|
||||
while (idx < m_locations.size())
|
||||
{
|
||||
BreakpointLocation *bp_loc = m_locations[idx].get();
|
||||
if (bp_loc->GetAddress().SectionWasDeleted())
|
||||
{
|
||||
// Section was deleted which means this breakpoint comes from a module
|
||||
// that is no longer valid, so we should remove it.
|
||||
m_locations.erase(m_locations.begin() + idx);
|
||||
continue;
|
||||
}
|
||||
if (arch.IsValid())
|
||||
{
|
||||
ModuleSP module_sp (bp_loc->GetAddress().GetModule());
|
||||
if (module_sp)
|
||||
{
|
||||
if (!arch.IsCompatibleMatch(module_sp->GetArchitecture()))
|
||||
{
|
||||
// The breakpoint was in a module whose architecture is no longer
|
||||
// compatible with "arch", so we need to remove it
|
||||
m_locations.erase(m_locations.begin() + idx);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Only increment the index if we didn't remove the locations at index "idx"
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations)
|
||||
|
@ -363,13 +363,13 @@ CommandObjectExpression::EvaluateExpression
|
||||
bool keep_in_memory = true;
|
||||
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetCoerceToId(m_varobj_options.use_objc)
|
||||
.SetUnwindOnError(m_command_options.unwind_on_error)
|
||||
.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints)
|
||||
.SetKeepInMemory(keep_in_memory)
|
||||
.SetUseDynamic(m_varobj_options.use_dynamic)
|
||||
.SetRunOthers(m_command_options.try_all_threads)
|
||||
.SetDebug(m_command_options.debug);
|
||||
options.SetCoerceToId(m_varobj_options.use_objc);
|
||||
options.SetUnwindOnError(m_command_options.unwind_on_error);
|
||||
options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints);
|
||||
options.SetKeepInMemory(keep_in_memory);
|
||||
options.SetUseDynamic(m_varobj_options.use_dynamic);
|
||||
options.SetTryAllThreads(m_command_options.try_all_threads);
|
||||
options.SetDebug(m_command_options.debug);
|
||||
|
||||
if (m_command_options.timeout > 0)
|
||||
options.SetTimeoutUsec(m_command_options.timeout);
|
||||
|
@ -914,6 +914,311 @@ class CommandObjectMemoryRead : public CommandObjectParsed
|
||||
ClangASTType m_prev_clang_ast_type;
|
||||
};
|
||||
|
||||
OptionDefinition
|
||||
g_memory_find_option_table[] =
|
||||
{
|
||||
{ LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
|
||||
{ LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Use text to find a byte pattern."},
|
||||
{ LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "How many times to perform the search."},
|
||||
{ LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "dump-offset", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."},
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Find the specified data in memory
|
||||
//----------------------------------------------------------------------
|
||||
class CommandObjectMemoryFind : public CommandObjectParsed
|
||||
{
|
||||
public:
|
||||
|
||||
class OptionGroupFindMemory : public OptionGroup
|
||||
{
|
||||
public:
|
||||
OptionGroupFindMemory () :
|
||||
OptionGroup(),
|
||||
m_count(1),
|
||||
m_offset(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~OptionGroupFindMemory ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual uint32_t
|
||||
GetNumDefinitions ()
|
||||
{
|
||||
return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
|
||||
}
|
||||
|
||||
virtual const OptionDefinition*
|
||||
GetDefinitions ()
|
||||
{
|
||||
return g_memory_find_option_table;
|
||||
}
|
||||
|
||||
virtual Error
|
||||
SetOptionValue (CommandInterpreter &interpreter,
|
||||
uint32_t option_idx,
|
||||
const char *option_arg)
|
||||
{
|
||||
Error error;
|
||||
const int short_option = g_memory_find_option_table[option_idx].short_option;
|
||||
|
||||
switch (short_option)
|
||||
{
|
||||
case 'e':
|
||||
m_expr.SetValueFromCString(option_arg);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
m_string.SetValueFromCString(option_arg);
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
if (m_count.SetValueFromCString(option_arg).Fail())
|
||||
error.SetErrorString("unrecognized value for count");
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
if (m_offset.SetValueFromCString(option_arg).Fail())
|
||||
error.SetErrorString("unrecognized value for dump-offset");
|
||||
break;
|
||||
|
||||
default:
|
||||
error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
virtual void
|
||||
OptionParsingStarting (CommandInterpreter &interpreter)
|
||||
{
|
||||
m_expr.Clear();
|
||||
m_string.Clear();
|
||||
m_count.Clear();
|
||||
}
|
||||
|
||||
OptionValueString m_expr;
|
||||
OptionValueString m_string;
|
||||
OptionValueUInt64 m_count;
|
||||
OptionValueUInt64 m_offset;
|
||||
};
|
||||
|
||||
CommandObjectMemoryFind (CommandInterpreter &interpreter) :
|
||||
CommandObjectParsed (interpreter,
|
||||
"memory find",
|
||||
"Find a value in the memory of the process being debugged.",
|
||||
NULL,
|
||||
eFlagRequiresProcess | eFlagProcessMustBeLaunched),
|
||||
m_option_group (interpreter),
|
||||
m_memory_options ()
|
||||
{
|
||||
CommandArgumentEntry arg1;
|
||||
CommandArgumentEntry arg2;
|
||||
CommandArgumentData addr_arg;
|
||||
CommandArgumentData value_arg;
|
||||
|
||||
// Define the first (and only) variant of this arg.
|
||||
addr_arg.arg_type = eArgTypeAddress;
|
||||
addr_arg.arg_repetition = eArgRepeatPlain;
|
||||
|
||||
// There is only one variant this argument could be; put it into the argument entry.
|
||||
arg1.push_back (addr_arg);
|
||||
|
||||
// Define the first (and only) variant of this arg.
|
||||
value_arg.arg_type = eArgTypeValue;
|
||||
value_arg.arg_repetition = eArgRepeatPlus;
|
||||
|
||||
// There is only one variant this argument could be; put it into the argument entry.
|
||||
arg2.push_back (value_arg);
|
||||
|
||||
// Push the data for the first argument into the m_arguments vector.
|
||||
m_arguments.push_back (arg1);
|
||||
m_arguments.push_back (arg2);
|
||||
|
||||
m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
|
||||
m_option_group.Finalize();
|
||||
}
|
||||
|
||||
virtual
|
||||
~CommandObjectMemoryFind ()
|
||||
{
|
||||
}
|
||||
|
||||
Options *
|
||||
GetOptions ()
|
||||
{
|
||||
return &m_option_group;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
DoExecute (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
// No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
|
||||
const size_t argc = command.GetArgumentCount();
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
result.AppendError("two addresses needed for memory find");
|
||||
return false;
|
||||
}
|
||||
|
||||
Error error;
|
||||
lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
|
||||
if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
|
||||
{
|
||||
result.AppendError("invalid low address");
|
||||
return false;
|
||||
}
|
||||
lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
|
||||
if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
|
||||
{
|
||||
result.AppendError("invalid low address");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (high_addr <= low_addr)
|
||||
{
|
||||
result.AppendError("starting address must be smaller than ending address");
|
||||
return false;
|
||||
}
|
||||
|
||||
lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
|
||||
|
||||
DataBufferHeap buffer;
|
||||
|
||||
if (m_memory_options.m_string.OptionWasSet())
|
||||
buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
|
||||
else if (m_memory_options.m_expr.OptionWasSet())
|
||||
{
|
||||
StackFrame* frame = m_exe_ctx.GetFramePtr();
|
||||
ValueObjectSP result_sp;
|
||||
if (process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp) && result_sp.get())
|
||||
{
|
||||
uint64_t value = result_sp->GetValueAsUnsigned(0);
|
||||
switch (result_sp->GetClangType().GetByteSize())
|
||||
{
|
||||
case 1: {
|
||||
uint8_t byte = (uint8_t)value;
|
||||
buffer.CopyData(&byte,1);
|
||||
}
|
||||
break;
|
||||
case 2: {
|
||||
uint16_t word = (uint16_t)value;
|
||||
buffer.CopyData(&word,2);
|
||||
}
|
||||
break;
|
||||
case 4: {
|
||||
uint32_t lword = (uint32_t)value;
|
||||
buffer.CopyData(&lword,4);
|
||||
}
|
||||
break;
|
||||
case 8: {
|
||||
buffer.CopyData(&value, 8);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
result.AppendError("unknown type. pass a string instead");
|
||||
return false;
|
||||
default:
|
||||
result.AppendError("do not know how to deal with larger than 8 byte result types. pass a string instead");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError("expression evaluation failed. pass a string instead?");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError("please pass either a block of text, or an expression to evaluate.");
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t count = m_memory_options.m_count.GetCurrentValue();
|
||||
found_location = low_addr;
|
||||
bool ever_found = false;
|
||||
while (count)
|
||||
{
|
||||
found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
|
||||
if (found_location == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
if (!ever_found)
|
||||
{
|
||||
result.AppendMessage("Your data was not found within the range.\n");
|
||||
result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
|
||||
}
|
||||
else
|
||||
result.AppendMessage("No more matches found within the range.\n");
|
||||
break;
|
||||
}
|
||||
result.AppendMessageWithFormat("Your data was found at location: 0x%" PRIx64 "\n", found_location);
|
||||
|
||||
DataBufferHeap dumpbuffer(32,0);
|
||||
process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
|
||||
if (!error.Fail())
|
||||
{
|
||||
DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
|
||||
data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
|
||||
result.GetOutputStream().EOL();
|
||||
}
|
||||
|
||||
--count;
|
||||
found_location++;
|
||||
ever_found = true;
|
||||
}
|
||||
|
||||
result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
|
||||
return true;
|
||||
}
|
||||
|
||||
lldb::addr_t
|
||||
Search (lldb::addr_t low,
|
||||
lldb::addr_t high,
|
||||
uint8_t* buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
DataBufferHeap heap(buffer_size, 0);
|
||||
lldb::addr_t fictional_ptr = low;
|
||||
for (auto ptr = low;
|
||||
low < high;
|
||||
fictional_ptr++)
|
||||
{
|
||||
Error error;
|
||||
if (ptr == low || buffer_size == 1)
|
||||
process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
|
||||
else
|
||||
{
|
||||
memmove(heap.GetBytes(), heap.GetBytes()+1, buffer_size-1);
|
||||
process->ReadMemory(ptr, heap.GetBytes()+buffer_size-1, 1, error);
|
||||
}
|
||||
if (error.Fail())
|
||||
return LLDB_INVALID_ADDRESS;
|
||||
if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
|
||||
return fictional_ptr;
|
||||
if (ptr == low)
|
||||
ptr += buffer_size;
|
||||
else
|
||||
ptr += 1;
|
||||
}
|
||||
return LLDB_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
OptionGroupOptions m_option_group;
|
||||
OptionGroupFindMemory m_memory_options;
|
||||
};
|
||||
|
||||
|
||||
OptionDefinition
|
||||
g_memory_write_option_table[] =
|
||||
@ -922,7 +1227,6 @@ g_memory_write_option_table[] =
|
||||
{ LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Write memory to the inferior process
|
||||
//----------------------------------------------------------------------
|
||||
@ -948,13 +1252,13 @@ class CommandObjectMemoryWrite : public CommandObjectParsed
|
||||
{
|
||||
return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
|
||||
}
|
||||
|
||||
|
||||
virtual const OptionDefinition*
|
||||
GetDefinitions ()
|
||||
{
|
||||
return g_memory_write_option_table;
|
||||
}
|
||||
|
||||
|
||||
virtual Error
|
||||
SetOptionValue (CommandInterpreter &interpreter,
|
||||
uint32_t option_idx,
|
||||
@ -962,7 +1266,7 @@ class CommandObjectMemoryWrite : public CommandObjectParsed
|
||||
{
|
||||
Error error;
|
||||
const int short_option = g_memory_write_option_table[option_idx].short_option;
|
||||
|
||||
|
||||
switch (short_option)
|
||||
{
|
||||
case 'i':
|
||||
@ -973,7 +1277,7 @@ class CommandObjectMemoryWrite : public CommandObjectParsed
|
||||
error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'o':
|
||||
{
|
||||
bool success;
|
||||
@ -1374,6 +1678,7 @@ CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
|
||||
"A set of commands for operating on memory.",
|
||||
"memory <subcommand> [<subcommand-options>]")
|
||||
{
|
||||
LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
|
||||
LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
|
||||
LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "lldb/Interpreter/Args.h"
|
||||
#include "lldb/Interpreter/CommandInterpreter.h"
|
||||
#include "lldb/Interpreter/CommandReturnObject.h"
|
||||
#include "lldb/Interpreter/OptionGroupFile.h"
|
||||
#include "lldb/Interpreter/OptionGroupPlatform.h"
|
||||
#include "lldb/Target/ExecutionContext.h"
|
||||
#include "lldb/Target/Platform.h"
|
||||
@ -119,31 +120,31 @@ class OptionPermissions : public lldb_private::OptionGroup
|
||||
m_permissions = perms;
|
||||
}
|
||||
case 'r':
|
||||
m_permissions |= File::ePermissionsUserRead;
|
||||
m_permissions |= lldb::eFilePermissionsUserRead;
|
||||
break;
|
||||
case 'w':
|
||||
m_permissions |= File::ePermissionsUserWrite;
|
||||
m_permissions |= lldb::eFilePermissionsUserWrite;
|
||||
break;
|
||||
case 'x':
|
||||
m_permissions |= File::ePermissionsUserExecute;
|
||||
m_permissions |= lldb::eFilePermissionsUserExecute;
|
||||
break;
|
||||
case 'R':
|
||||
m_permissions |= File::ePermissionsGroupRead;
|
||||
m_permissions |= lldb::eFilePermissionsGroupRead;
|
||||
break;
|
||||
case 'W':
|
||||
m_permissions |= File::ePermissionsGroupWrite;
|
||||
m_permissions |= lldb::eFilePermissionsGroupWrite;
|
||||
break;
|
||||
case 'X':
|
||||
m_permissions |= File::ePermissionsGroupExecute;
|
||||
m_permissions |= lldb::eFilePermissionsGroupExecute;
|
||||
break;
|
||||
case 'd':
|
||||
m_permissions |= File::ePermissionsWorldRead;
|
||||
m_permissions |= lldb::eFilePermissionsWorldRead;
|
||||
break;
|
||||
case 't':
|
||||
m_permissions |= File::ePermissionsWorldWrite;
|
||||
m_permissions |= lldb::eFilePermissionsWorldWrite;
|
||||
break;
|
||||
case 'e':
|
||||
m_permissions |= File::ePermissionsWorldExecute;
|
||||
m_permissions |= lldb::eFilePermissionsWorldExecute;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -523,6 +524,65 @@ class CommandObjectPlatformDisconnect : public CommandObjectParsed
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// "platform settings"
|
||||
//----------------------------------------------------------------------
|
||||
class CommandObjectPlatformSettings : public CommandObjectParsed
|
||||
{
|
||||
public:
|
||||
CommandObjectPlatformSettings (CommandInterpreter &interpreter) :
|
||||
CommandObjectParsed (interpreter,
|
||||
"platform settings",
|
||||
"Set settings for the current target's platform, or for a platform by name.",
|
||||
"platform settings",
|
||||
0),
|
||||
m_options (interpreter),
|
||||
m_option_working_dir (LLDB_OPT_SET_1, false, "working-dir", 'w', 0, eArgTypePath, "The working directory for the platform.")
|
||||
{
|
||||
m_options.Append (&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
|
||||
}
|
||||
|
||||
virtual
|
||||
~CommandObjectPlatformSettings ()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
DoExecute (Args& args, CommandReturnObject &result)
|
||||
{
|
||||
PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
|
||||
if (platform_sp)
|
||||
{
|
||||
if (m_option_working_dir.GetOptionValue().OptionWasSet())
|
||||
platform_sp->SetWorkingDirectory (ConstString(m_option_working_dir.GetOptionValue().GetCurrentValue().GetPath().c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("no platform is currently selected");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
||||
virtual Options *
|
||||
GetOptions ()
|
||||
{
|
||||
if (m_options.DidFinalize() == false)
|
||||
{
|
||||
m_options.Append(new OptionPermissions());
|
||||
m_options.Finalize();
|
||||
}
|
||||
return &m_options;
|
||||
}
|
||||
protected:
|
||||
|
||||
OptionGroupOptions m_options;
|
||||
OptionGroupFile m_option_working_dir;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// "platform mkdir"
|
||||
//----------------------------------------------------------------------
|
||||
@ -552,15 +612,22 @@ class CommandObjectPlatformMkDir : public CommandObjectParsed
|
||||
{
|
||||
std::string cmd_line;
|
||||
args.GetCommandString(cmd_line);
|
||||
mode_t perms;
|
||||
uint32_t mode;
|
||||
const OptionPermissions* options_permissions = (OptionPermissions*)m_options.GetGroupWithOption('r');
|
||||
if (options_permissions)
|
||||
perms = options_permissions->m_permissions;
|
||||
mode = options_permissions->m_permissions;
|
||||
else
|
||||
perms = 0000700 | 0000070 | 0000007;
|
||||
uint32_t retcode = platform_sp->MakeDirectory(cmd_line,perms);
|
||||
result.AppendMessageWithFormat("Status = %d\n",retcode);
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX | lldb::eFilePermissionsWorldRX;
|
||||
Error error = platform_sp->MakeDirectory(cmd_line.c_str(), mode);
|
||||
if (error.Success())
|
||||
{
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError(error.AsCString());
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -619,7 +686,7 @@ class CommandObjectPlatformFOpen : public CommandObjectParsed
|
||||
if (options_permissions)
|
||||
perms = options_permissions->m_permissions;
|
||||
else
|
||||
perms = 0000700 | 0000070 | 0000007;
|
||||
perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW | lldb::eFilePermissionsWorldRead;
|
||||
lldb::user_id_t fd = platform_sp->OpenFile(FileSpec(cmd_line.c_str(),false),
|
||||
File::eOpenOptionRead | File::eOpenOptionWrite |
|
||||
File::eOpenOptionAppend | File::eOpenOptionCanCreate,
|
||||
@ -2129,82 +2196,6 @@ CommandObjectPlatformShell::CommandOptions::g_option_table[] =
|
||||
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
|
||||
};
|
||||
|
||||
struct RecurseCopyBaton
|
||||
{
|
||||
const std::string& destination;
|
||||
const PlatformSP& platform_sp;
|
||||
Error error;
|
||||
};
|
||||
|
||||
|
||||
static FileSpec::EnumerateDirectoryResult
|
||||
RecurseCopy_Callback (void *baton,
|
||||
FileSpec::FileType file_type,
|
||||
const FileSpec &spec)
|
||||
{
|
||||
RecurseCopyBaton* rc_baton = (RecurseCopyBaton*)baton;
|
||||
switch (file_type)
|
||||
{
|
||||
case FileSpec::eFileTypePipe:
|
||||
case FileSpec::eFileTypeSocket:
|
||||
// we have no way to copy pipes and sockets - ignore them and continue
|
||||
return FileSpec::eEnumerateDirectoryResultNext;
|
||||
break;
|
||||
|
||||
case FileSpec::eFileTypeSymbolicLink:
|
||||
// what to do for symlinks?
|
||||
return FileSpec::eEnumerateDirectoryResultNext;
|
||||
break;
|
||||
|
||||
case FileSpec::eFileTypeDirectory:
|
||||
{
|
||||
// make the new directory and get in there
|
||||
FileSpec new_directory(rc_baton->destination.c_str(),false);
|
||||
new_directory.AppendPathComponent(spec.GetLastPathComponent());
|
||||
uint32_t errcode = rc_baton->platform_sp->MakeDirectory(new_directory, 0777);
|
||||
std::string new_directory_path (new_directory.GetPath());
|
||||
if (errcode != 0)
|
||||
{
|
||||
rc_baton->error.SetErrorStringWithFormat("unable to setup directory %s on remote end",new_directory_path.c_str());
|
||||
return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
|
||||
}
|
||||
|
||||
// now recurse
|
||||
std::string local_path (spec.GetPath());
|
||||
RecurseCopyBaton rc_baton2 = { new_directory_path, rc_baton->platform_sp, Error() };
|
||||
FileSpec::EnumerateDirectory(local_path.c_str(), true, true, true, RecurseCopy_Callback, &rc_baton2);
|
||||
if (rc_baton2.error.Fail())
|
||||
{
|
||||
rc_baton->error.SetErrorString(rc_baton2.error.AsCString());
|
||||
return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
|
||||
}
|
||||
return FileSpec::eEnumerateDirectoryResultNext;
|
||||
}
|
||||
break;
|
||||
|
||||
case FileSpec::eFileTypeRegular:
|
||||
{
|
||||
// copy the file and keep going
|
||||
std::string dest(rc_baton->destination);
|
||||
dest.append(spec.GetFilename().GetCString());
|
||||
Error err = rc_baton->platform_sp->PutFile(spec, FileSpec(dest.c_str(), false));
|
||||
if (err.Fail())
|
||||
{
|
||||
rc_baton->error.SetErrorString(err.AsCString());
|
||||
return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
|
||||
}
|
||||
return FileSpec::eEnumerateDirectoryResultNext;
|
||||
}
|
||||
break;
|
||||
|
||||
case FileSpec::eFileTypeInvalid:
|
||||
case FileSpec::eFileTypeOther:
|
||||
case FileSpec::eFileTypeUnknown:
|
||||
rc_baton->error.SetErrorStringWithFormat("invalid file detected during copy: %s/%s", spec.GetDirectory().GetCString(), spec.GetFilename().GetCString());
|
||||
return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// "platform install" - install a target to a remote end
|
||||
@ -2236,10 +2227,9 @@ class CommandObjectPlatformInstall : public CommandObjectParsed
|
||||
return false;
|
||||
}
|
||||
// TODO: move the bulk of this code over to the platform itself
|
||||
std::string local_thing(args.GetArgumentAtIndex(0));
|
||||
std::string remote_sandbox(args.GetArgumentAtIndex(1));
|
||||
FileSpec source(local_thing.c_str(), true);
|
||||
if (source.Exists() == false)
|
||||
FileSpec src(args.GetArgumentAtIndex(0), true);
|
||||
FileSpec dst(args.GetArgumentAtIndex(1), false);
|
||||
if (src.Exists() == false)
|
||||
{
|
||||
result.AppendError("source location does not exist or is not accessible");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
@ -2252,75 +2242,21 @@ class CommandObjectPlatformInstall : public CommandObjectParsed
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
FileSpec::FileType source_type(source.GetFileType());
|
||||
if (source_type == FileSpec::eFileTypeDirectory)
|
||||
|
||||
Error error = platform_sp->Install(src, dst);
|
||||
if (error.Success())
|
||||
{
|
||||
if (platform_sp->GetSupportsRSync())
|
||||
{
|
||||
FileSpec remote_folder(remote_sandbox.c_str(), false);
|
||||
Error rsync_err = platform_sp->PutFile(source, remote_folder);
|
||||
if (rsync_err.Success())
|
||||
{
|
||||
result.SetStatus(eReturnStatusSuccessFinishResult);
|
||||
return result.Succeeded();
|
||||
}
|
||||
}
|
||||
FileSpec remote_folder(remote_sandbox.c_str(), false);
|
||||
remote_folder.AppendPathComponent(source.GetLastPathComponent());
|
||||
// TODO: default permissions are bad
|
||||
uint32_t errcode = platform_sp->MakeDirectory(remote_folder, 0777);
|
||||
if (errcode != 0)
|
||||
{
|
||||
result.AppendError("unable to setup target directory on remote end");
|
||||
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
||||
return result.Succeeded();
|
||||
}
|
||||
// now recurse
|
||||
std::string remote_folder_path (remote_folder.GetPath());
|
||||
Error err = RecurseCopy(source,remote_folder_path,platform_sp);
|
||||
if (err.Fail())
|
||||
{
|
||||
result.AppendError(err.AsCString());
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
}
|
||||
else
|
||||
result.SetStatus(eReturnStatusSuccessFinishResult);
|
||||
return result.Succeeded();
|
||||
}
|
||||
else if (source_type == FileSpec::eFileTypeRegular)
|
||||
{
|
||||
// just a plain file - push it to remote and be done
|
||||
remote_sandbox.append(source.GetFilename().GetCString());
|
||||
FileSpec destination(remote_sandbox.c_str(),false);
|
||||
Error err = platform_sp->PutFile(source, destination);
|
||||
if (err.Success())
|
||||
result.SetStatus(eReturnStatusSuccessFinishResult);
|
||||
else
|
||||
{
|
||||
result.AppendError(err.AsCString());
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
}
|
||||
return result.Succeeded();
|
||||
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError("source is not a known type of file");
|
||||
result.AppendErrorWithFormat("install failed: %s", error.AsCString());
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return result.Succeeded();
|
||||
}
|
||||
return result.Succeeded();
|
||||
}
|
||||
private:
|
||||
|
||||
Error
|
||||
RecurseCopy (const FileSpec& source,
|
||||
const std::string& destination,
|
||||
const PlatformSP& platform_sp)
|
||||
{
|
||||
std::string source_path (source.GetPath());
|
||||
RecurseCopyBaton baton = { destination, platform_sp, Error() };
|
||||
FileSpec::EnumerateDirectory(source_path.c_str(), true, true, true, RecurseCopy_Callback, &baton);
|
||||
return baton.error;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@ -2332,21 +2268,22 @@ CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) :
|
||||
"A set of commands to manage and create platforms.",
|
||||
"platform [connect|disconnect|info|list|status|select] ...")
|
||||
{
|
||||
LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter)));
|
||||
LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformList (interpreter)));
|
||||
LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter)));
|
||||
LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter)));
|
||||
LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter)));
|
||||
LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter)));
|
||||
LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformList (interpreter)));
|
||||
LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter)));
|
||||
LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter)));
|
||||
LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter)));
|
||||
LoadSubCommand ("settings", CommandObjectSP (new CommandObjectPlatformSettings (interpreter)));
|
||||
#ifdef LLDB_CONFIGURATION_DEBUG
|
||||
LoadSubCommand ("mkdir", CommandObjectSP (new CommandObjectPlatformMkDir (interpreter)));
|
||||
LoadSubCommand ("file", CommandObjectSP (new CommandObjectPlatformFile (interpreter)));
|
||||
LoadSubCommand ("get-file", CommandObjectSP (new CommandObjectPlatformGetFile (interpreter)));
|
||||
LoadSubCommand ("get-size", CommandObjectSP (new CommandObjectPlatformGetSize (interpreter)));
|
||||
LoadSubCommand ("put-file", CommandObjectSP (new CommandObjectPlatformPutFile (interpreter)));
|
||||
LoadSubCommand ("mkdir", CommandObjectSP (new CommandObjectPlatformMkDir (interpreter)));
|
||||
LoadSubCommand ("file", CommandObjectSP (new CommandObjectPlatformFile (interpreter)));
|
||||
LoadSubCommand ("get-file", CommandObjectSP (new CommandObjectPlatformGetFile (interpreter)));
|
||||
LoadSubCommand ("get-size", CommandObjectSP (new CommandObjectPlatformGetSize (interpreter)));
|
||||
LoadSubCommand ("put-file", CommandObjectSP (new CommandObjectPlatformPutFile (interpreter)));
|
||||
#endif
|
||||
LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter)));
|
||||
LoadSubCommand ("shell", CommandObjectSP (new CommandObjectPlatformShell (interpreter)));
|
||||
LoadSubCommand ("target-install", CommandObjectSP (new CommandObjectPlatformInstall (interpreter)));
|
||||
LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter)));
|
||||
LoadSubCommand ("shell", CommandObjectSP (new CommandObjectPlatformShell (interpreter)));
|
||||
LoadSubCommand ("target-install", CommandObjectSP (new CommandObjectPlatformInstall (interpreter)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -11,10 +11,6 @@
|
||||
|
||||
#include "CommandObjectPlugin.h"
|
||||
|
||||
#include "lldb/API/SBDebugger.h"
|
||||
#include "lldb/API/SBCommandInterpreter.h"
|
||||
#include "lldb/API/SBCommandReturnObject.h"
|
||||
|
||||
#include "lldb/Host/Host.h"
|
||||
|
||||
#include "lldb/Interpreter/CommandInterpreter.h"
|
||||
@ -79,8 +75,6 @@ class CommandObjectPluginLoad : public CommandObjectParsed
|
||||
bool
|
||||
DoExecute (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
typedef void (*LLDBCommandPluginInit) (lldb::SBDebugger debugger);
|
||||
|
||||
size_t argc = command.GetArgumentCount();
|
||||
|
||||
if (argc != 1)
|
||||
|
@ -251,9 +251,11 @@ class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach
|
||||
// then you'll pick up that incorrect value.
|
||||
bool synchronous_execution = m_interpreter.GetSynchronous ();
|
||||
|
||||
PlatformSP platform_sp (target->GetPlatform());
|
||||
|
||||
// Finalize the file actions, and if none were given, default to opening
|
||||
// up a pseudo terminal
|
||||
const bool default_to_use_pty = true;
|
||||
const bool default_to_use_pty = platform_sp ? platform_sp->IsHost() : false;
|
||||
m_options.launch_info.FinalizeFileActions (target, default_to_use_pty);
|
||||
|
||||
if (state == eStateConnected)
|
||||
@ -267,8 +269,6 @@ class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach
|
||||
|
||||
if (!m_options.launch_info.GetArchitecture().IsValid())
|
||||
m_options.launch_info.GetArchitecture() = target->GetArchitecture();
|
||||
|
||||
PlatformSP platform_sp (target->GetPlatform());
|
||||
|
||||
if (platform_sp && platform_sp->CanDebugProcess ())
|
||||
{
|
||||
|
@ -1796,10 +1796,8 @@ LookupTypeInModule (CommandInterpreter &interpreter,
|
||||
strm.Printf("%zu match%s found in ", num_matches, num_matches > 1 ? "es" : "");
|
||||
DumpFullpath (strm, &module->GetFileSpec(), 0);
|
||||
strm.PutCString(":\n");
|
||||
const uint32_t num_types = type_list.GetSize();
|
||||
for (uint32_t i=0; i<num_types; ++i)
|
||||
for (TypeSP type_sp : type_list.Types())
|
||||
{
|
||||
TypeSP type_sp (type_list.GetTypeAtIndex(i));
|
||||
if (type_sp)
|
||||
{
|
||||
// Resolve the clang type so that any forward references
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "lldb/Symbol/LineEntry.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
#include "lldb/Target/RegisterContext.h"
|
||||
#include "lldb/Target/SystemRuntime.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
#include "lldb/Target/Thread.h"
|
||||
#include "lldb/Target/ThreadPlan.h"
|
||||
@ -92,6 +93,13 @@ class CommandObjectThreadBacktrace : public CommandObjectParsed
|
||||
if (!success)
|
||||
error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
|
||||
}
|
||||
case 'e':
|
||||
{
|
||||
bool success;
|
||||
m_extended_backtrace = Args::StringToBoolean (option_arg, false, &success);
|
||||
if (!success)
|
||||
error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
|
||||
@ -106,6 +114,7 @@ class CommandObjectThreadBacktrace : public CommandObjectParsed
|
||||
{
|
||||
m_count = UINT32_MAX;
|
||||
m_start = 0;
|
||||
m_extended_backtrace = false;
|
||||
}
|
||||
|
||||
const OptionDefinition*
|
||||
@ -121,6 +130,7 @@ class CommandObjectThreadBacktrace : public CommandObjectParsed
|
||||
// Instance variables to hold the values for command options.
|
||||
uint32_t m_count;
|
||||
uint32_t m_start;
|
||||
bool m_extended_backtrace;
|
||||
};
|
||||
|
||||
CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
|
||||
@ -160,6 +170,32 @@ class CommandObjectThreadBacktrace : public CommandObjectParsed
|
||||
}
|
||||
|
||||
protected:
|
||||
void
|
||||
DoExtendedBacktrace (Thread *thread, CommandReturnObject &result)
|
||||
{
|
||||
SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime();
|
||||
if (runtime)
|
||||
{
|
||||
Stream &strm = result.GetOutputStream();
|
||||
const std::vector<ConstString> &types = runtime->GetExtendedBacktraceTypes();
|
||||
for (auto type : types)
|
||||
{
|
||||
ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread (thread->shared_from_this(), type);
|
||||
if (ext_thread_sp && ext_thread_sp->IsValid ())
|
||||
{
|
||||
const uint32_t num_frames_with_source = 0;
|
||||
if (ext_thread_sp->GetStatus (strm,
|
||||
m_options.m_start,
|
||||
m_options.m_count,
|
||||
num_frames_with_source))
|
||||
{
|
||||
DoExtendedBacktrace (ext_thread_sp.get(), result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool
|
||||
DoExecute (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
@ -178,29 +214,36 @@ class CommandObjectThreadBacktrace : public CommandObjectParsed
|
||||
num_frames_with_source))
|
||||
{
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
if (m_options.m_extended_backtrace)
|
||||
{
|
||||
DoExtendedBacktrace (thread, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
|
||||
{
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
Mutex::Locker locker (process->GetThreadList().GetMutex());
|
||||
uint32_t num_threads = process->GetThreadList().GetSize();
|
||||
for (uint32_t i = 0; i < num_threads; i++)
|
||||
uint32_t idx = 0;
|
||||
for (ThreadSP thread_sp : process->Threads())
|
||||
{
|
||||
ThreadSP thread_sp = process->GetThreadList().GetThreadAtIndex(i);
|
||||
if (idx != 0)
|
||||
result.AppendMessage("");
|
||||
|
||||
if (!thread_sp->GetStatus (strm,
|
||||
m_options.m_start,
|
||||
m_options.m_count,
|
||||
num_frames_with_source))
|
||||
{
|
||||
result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", i);
|
||||
result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", idx);
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
if (m_options.m_extended_backtrace)
|
||||
{
|
||||
DoExtendedBacktrace (thread_sp.get(), result);
|
||||
}
|
||||
|
||||
if (i < num_threads - 1)
|
||||
result.AppendMessage("");
|
||||
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -244,6 +287,10 @@ class CommandObjectThreadBacktrace : public CommandObjectParsed
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
if (m_options.m_extended_backtrace)
|
||||
{
|
||||
DoExtendedBacktrace (thread_sps[i].get(), result);
|
||||
}
|
||||
|
||||
if (i < num_args - 1)
|
||||
result.AppendMessage("");
|
||||
@ -260,6 +307,7 @@ CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
|
||||
{
|
||||
{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
|
||||
{ LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"},
|
||||
{ LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Show the extended backtrace, if available"},
|
||||
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
|
||||
};
|
||||
|
||||
|
@ -939,7 +939,7 @@ class CommandObjectWatchpointSetVariable : public CommandObjectParsed
|
||||
SetHelpLong(
|
||||
"Examples: \n\
|
||||
\n\
|
||||
watchpoint set variable -w read_wriate my_global_var \n\
|
||||
watchpoint set variable -w read_write my_global_var \n\
|
||||
# Watch my_global_var for read/write access, with the region to watch corresponding to the byte size of the data type.\n");
|
||||
|
||||
CommandArgumentEntry arg;
|
||||
@ -1256,11 +1256,11 @@ class CommandObjectWatchpointSetExpression : public CommandObjectRaw
|
||||
|
||||
// Use expression evaluation to arrive at the address to watch.
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(false)
|
||||
.SetRunOthers(true)
|
||||
.SetTimeoutUsec(0);
|
||||
options.SetCoerceToId(false);
|
||||
options.SetUnwindOnError(true);
|
||||
options.SetKeepInMemory(false);
|
||||
options.SetTryAllThreads(true);
|
||||
options.SetTimeoutUsec(0);
|
||||
|
||||
ExecutionResults expr_result = target->EvaluateExpression (expr,
|
||||
frame,
|
||||
|
@ -280,7 +280,7 @@ Address::GetFileAddress () const
|
||||
// address by adding the file base address to our offset
|
||||
return sect_file_addr + m_offset;
|
||||
}
|
||||
else if (SectionWasDeleted())
|
||||
else if (SectionWasDeletedPrivate())
|
||||
{
|
||||
// Used to have a valid section but it got deleted so the
|
||||
// offset doesn't mean anything without the section
|
||||
@ -308,7 +308,7 @@ Address::GetLoadAddress (Target *target) const
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (SectionWasDeleted())
|
||||
else if (SectionWasDeletedPrivate())
|
||||
{
|
||||
// Used to have a valid section but it got deleted so the
|
||||
// offset doesn't mean anything without the section
|
||||
@ -782,6 +782,14 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
|
||||
|
||||
bool
|
||||
Address::SectionWasDeleted() const
|
||||
{
|
||||
if (GetSection())
|
||||
return false;
|
||||
return SectionWasDeletedPrivate();
|
||||
}
|
||||
|
||||
bool
|
||||
Address::SectionWasDeletedPrivate() const
|
||||
{
|
||||
lldb::SectionWP empty_section_wp;
|
||||
|
||||
|
@ -53,6 +53,8 @@
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/RegularExpression.h"
|
||||
#include "lldb/Core/Timer.h"
|
||||
#include "lldb/Host/Host.h"
|
||||
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
@ -1209,6 +1211,7 @@ ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *err
|
||||
saddr_un.sun_len = SUN_LEN (&saddr_un);
|
||||
#endif
|
||||
|
||||
Host::Unlink (socket_name);
|
||||
if (::bind (listen_socket, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0)
|
||||
{
|
||||
if (::listen (listen_socket, 5) == 0)
|
||||
|
@ -9,8 +9,6 @@
|
||||
|
||||
#include "lldb/lldb-python.h"
|
||||
|
||||
#include "lldb/API/SBDebugger.h"
|
||||
|
||||
#include "lldb/Core/Debugger.h"
|
||||
|
||||
#include <map>
|
||||
@ -46,6 +44,7 @@
|
||||
#include "lldb/Target/TargetList.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
#include "lldb/Target/RegisterContext.h"
|
||||
#include "lldb/Target/SectionLoadList.h"
|
||||
#include "lldb/Target/StopInfo.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
#include "lldb/Target/Thread.h"
|
||||
@ -155,19 +154,7 @@ enum
|
||||
ePropertyAutoOneLineSummaries
|
||||
};
|
||||
|
||||
//
|
||||
//const char *
|
||||
//Debugger::GetFrameFormat() const
|
||||
//{
|
||||
// return m_properties_sp->GetFrameFormat();
|
||||
//}
|
||||
//const char *
|
||||
//Debugger::GetThreadFormat() const
|
||||
//{
|
||||
// return m_properties_sp->GetThreadFormat();
|
||||
//}
|
||||
//
|
||||
|
||||
Debugger::LoadPluginCallbackType Debugger::g_load_plugin_callback = NULL;
|
||||
|
||||
Error
|
||||
Debugger::SetPropertyValue (const ExecutionContext *exe_ctx,
|
||||
@ -373,8 +360,9 @@ Debugger::TestDebuggerRefCount ()
|
||||
}
|
||||
|
||||
void
|
||||
Debugger::Initialize ()
|
||||
Debugger::Initialize (LoadPluginCallbackType load_plugin_callback)
|
||||
{
|
||||
g_load_plugin_callback = load_plugin_callback;
|
||||
if (g_shared_debugger_refcount++ == 0)
|
||||
lldb_private::Initialize();
|
||||
}
|
||||
@ -412,31 +400,22 @@ Debugger::SettingsTerminate ()
|
||||
bool
|
||||
Debugger::LoadPlugin (const FileSpec& spec, Error& error)
|
||||
{
|
||||
lldb::DynamicLibrarySP dynlib_sp(new lldb_private::DynamicLibrary(spec));
|
||||
if (!dynlib_sp || dynlib_sp->IsValid() == false)
|
||||
if (g_load_plugin_callback)
|
||||
{
|
||||
if (spec.Exists())
|
||||
error.SetErrorString("this file does not represent a loadable dylib");
|
||||
else
|
||||
error.SetErrorString("no such file");
|
||||
return false;
|
||||
lldb::DynamicLibrarySP dynlib_sp = g_load_plugin_callback (shared_from_this(), spec, error);
|
||||
if (dynlib_sp)
|
||||
{
|
||||
m_loaded_plugins.push_back(dynlib_sp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
lldb::DebuggerSP debugger_sp(shared_from_this());
|
||||
lldb::SBDebugger debugger_sb(debugger_sp);
|
||||
// This calls the bool lldb::PluginInitialize(lldb::SBDebugger debugger) function.
|
||||
// TODO: mangle this differently for your system - on OSX, the first underscore needs to be removed and the second one stays
|
||||
LLDBCommandPluginInit init_func = dynlib_sp->GetSymbol<LLDBCommandPluginInit>("_ZN4lldb16PluginInitializeENS_10SBDebuggerE");
|
||||
if (!init_func)
|
||||
else
|
||||
{
|
||||
error.SetErrorString("cannot find the initialization function lldb::PluginInitialize(lldb::SBDebugger)");
|
||||
return false;
|
||||
// The g_load_plugin_callback is registered in SBDebugger::Initialize()
|
||||
// and if the public API layer isn't available (code is linking against
|
||||
// all of the internal LLDB static libraries), then we can't load plugins
|
||||
error.SetErrorString("Public API layer is not available");
|
||||
}
|
||||
if (init_func(debugger_sb))
|
||||
{
|
||||
m_loaded_plugins.push_back(dynlib_sp);
|
||||
return true;
|
||||
}
|
||||
error.SetErrorString("dylib refused to be loaded");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,9 @@
|
||||
|
||||
// FreeBSD9-STABLE requires this to know about size_t in cxxabi.h
|
||||
#include <cstddef>
|
||||
#if defined(_MSC_VER) || defined (__FreeBSD__)
|
||||
#if defined(_MSC_VER)
|
||||
// Cannot enable the builtin demangler on msvc as it does not support the cpp11 within the implementation.
|
||||
#elif defined (__FreeBSD__)
|
||||
#define LLDB_USE_BUILTIN_DEMANGLER
|
||||
#else
|
||||
#include <cxxabi.h>
|
||||
@ -4890,6 +4892,9 @@ Mangled::GetDemangledName () const
|
||||
// add it to our map.
|
||||
#ifdef LLDB_USE_BUILTIN_DEMANGLER
|
||||
char *demangled_name = __cxa_demangle (mangled_cstr, NULL, NULL, NULL);
|
||||
#elif defined(_MSC_VER)
|
||||
// Cannot demangle on msvc.
|
||||
char *demangled_name = nullptr;
|
||||
#else
|
||||
char *demangled_name = abi::__cxa_demangle (mangled_cstr, NULL, NULL, NULL);
|
||||
#endif
|
||||
|
@ -135,6 +135,7 @@ Module::Module (const ModuleSpec &module_spec) :
|
||||
m_uuid (),
|
||||
m_file (module_spec.GetFileSpec()),
|
||||
m_platform_file(module_spec.GetPlatformFileSpec()),
|
||||
m_remote_install_file(),
|
||||
m_symfile_spec (module_spec.GetSymbolFileSpec()),
|
||||
m_object_name (module_spec.GetObjectName()),
|
||||
m_object_offset (module_spec.GetObjectOffset()),
|
||||
@ -179,6 +180,7 @@ Module::Module(const FileSpec& file_spec,
|
||||
m_uuid (),
|
||||
m_file (file_spec),
|
||||
m_platform_file(),
|
||||
m_remote_install_file (),
|
||||
m_symfile_spec (),
|
||||
m_object_name (),
|
||||
m_object_offset (object_offset),
|
||||
|
@ -49,7 +49,7 @@ StreamFile::StreamFile (FILE *fh, bool transfer_ownership) :
|
||||
|
||||
StreamFile::StreamFile (const char *path) :
|
||||
Stream (),
|
||||
m_file (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate, File::ePermissionsDefault)
|
||||
m_file (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate, lldb::eFilePermissionsFileDefault)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "lldb/Core/ValueObject.h"
|
||||
#include "lldb/DataFormatters/FormatClasses.h"
|
||||
#include "lldb/DataFormatters/TypeSynthetic.h"
|
||||
|
||||
using namespace lldb_private;
|
||||
|
||||
|
@ -49,9 +49,9 @@ lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
|
||||
return false;
|
||||
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true);
|
||||
options.SetCoerceToId(false);
|
||||
options.SetUnwindOnError(true);
|
||||
options.SetKeepInMemory(true);
|
||||
|
||||
target->EvaluateExpression(expr.GetData(),
|
||||
stack_frame,
|
||||
@ -83,10 +83,10 @@ lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
|
||||
return false;
|
||||
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
options.SetCoerceToId(false);
|
||||
options.SetUnwindOnError(true);
|
||||
options.SetKeepInMemory(true);
|
||||
options.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
|
||||
target->EvaluateExpression(expr.GetData(),
|
||||
stack_frame,
|
||||
@ -121,10 +121,10 @@ lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
|
||||
return valobj_sp;
|
||||
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
options.SetCoerceToId(false);
|
||||
options.SetUnwindOnError(true);
|
||||
options.SetKeepInMemory(true);
|
||||
options.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
|
||||
target->EvaluateExpression(expr.GetData(),
|
||||
stack_frame,
|
||||
@ -158,10 +158,10 @@ lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
|
||||
return valobj_sp;
|
||||
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
options.SetCoerceToId(false);
|
||||
options.SetUnwindOnError(true);
|
||||
options.SetKeepInMemory(true);
|
||||
options.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
|
||||
target->EvaluateExpression(expr.GetData(),
|
||||
stack_frame,
|
||||
|
@ -7,7 +7,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/lldb-python.h"
|
||||
#include "lldb/DataFormatters/FormatClasses.h"
|
||||
|
||||
// C Includes
|
||||
|
||||
@ -16,17 +16,6 @@
|
||||
// Other libraries and framework includes
|
||||
|
||||
// Project includes
|
||||
#include "lldb/lldb-public.h"
|
||||
#include "lldb/lldb-enumerations.h"
|
||||
|
||||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Core/StreamString.h"
|
||||
#include "lldb/Core/Timer.h"
|
||||
#include "lldb/DataFormatters/FormatClasses.h"
|
||||
#include "lldb/Interpreter/CommandInterpreter.h"
|
||||
#include "lldb/Symbol/ClangASTType.h"
|
||||
#include "lldb/Target/StackFrame.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
@ -163,6 +163,139 @@ FormatManager::GetFormatAsCString (Format format)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
FormatManager::GetPossibleMatches (ValueObject& valobj,
|
||||
ClangASTType clang_type,
|
||||
uint32_t reason,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
FormattersMatchVector& entries,
|
||||
bool did_strip_ptr,
|
||||
bool did_strip_ref,
|
||||
bool did_strip_typedef,
|
||||
bool root_level)
|
||||
{
|
||||
clang_type = clang_type.RemoveFastQualifiers();
|
||||
ConstString type_name(clang_type.GetConstTypeName());
|
||||
if (valobj.GetBitfieldBitSize() > 0)
|
||||
{
|
||||
StreamString sstring;
|
||||
sstring.Printf("%s:%d",type_name.AsCString(),valobj.GetBitfieldBitSize());
|
||||
ConstString bitfieldname = ConstString(sstring.GetData());
|
||||
entries.push_back({bitfieldname,0,did_strip_ptr,did_strip_ref,did_strip_typedef});
|
||||
reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField;
|
||||
}
|
||||
entries.push_back({type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});
|
||||
|
||||
if (clang_type.IsReferenceType())
|
||||
{
|
||||
ClangASTType non_ref_type = clang_type.GetNonReferenceType();
|
||||
GetPossibleMatches(valobj,
|
||||
non_ref_type,
|
||||
reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
|
||||
use_dynamic,
|
||||
entries,
|
||||
did_strip_ptr,
|
||||
true,
|
||||
did_strip_typedef);
|
||||
}
|
||||
else if (clang_type.IsPointerType())
|
||||
{
|
||||
ClangASTType non_ptr_type = clang_type.GetPointeeType();
|
||||
GetPossibleMatches(valobj,
|
||||
non_ptr_type,
|
||||
reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
|
||||
use_dynamic,
|
||||
entries,
|
||||
true,
|
||||
did_strip_ref,
|
||||
did_strip_typedef);
|
||||
}
|
||||
bool canBeObjCDynamic = clang_type.IsPossibleDynamicType (NULL,
|
||||
false, // no C
|
||||
true); // yes ObjC
|
||||
|
||||
if (canBeObjCDynamic)
|
||||
{
|
||||
if (use_dynamic != lldb::eNoDynamicValues)
|
||||
{
|
||||
do
|
||||
{
|
||||
lldb::ProcessSP process_sp = valobj.GetProcessSP();
|
||||
ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime();
|
||||
if (runtime == nullptr)
|
||||
break;
|
||||
ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj));
|
||||
if (!objc_class_sp)
|
||||
break;
|
||||
ConstString name (objc_class_sp->GetClassName());
|
||||
entries.push_back({name,reason | lldb_private::eFormatterChoiceCriterionDynamicObjCDiscovery,did_strip_ptr,did_strip_ref,did_strip_typedef});
|
||||
} while (false);
|
||||
}
|
||||
|
||||
ClangASTType non_ptr_type = clang_type.GetPointeeType();
|
||||
GetPossibleMatches(valobj,
|
||||
non_ptr_type,
|
||||
reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
|
||||
use_dynamic,
|
||||
entries,
|
||||
true,
|
||||
did_strip_ref,
|
||||
did_strip_typedef);
|
||||
}
|
||||
|
||||
// try to strip typedef chains
|
||||
if (clang_type.IsTypedefType())
|
||||
{
|
||||
ClangASTType deffed_type = clang_type.GetTypedefedType();
|
||||
GetPossibleMatches(valobj,
|
||||
deffed_type,
|
||||
reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
|
||||
use_dynamic,
|
||||
entries,
|
||||
did_strip_ptr,
|
||||
did_strip_ref,
|
||||
true);
|
||||
}
|
||||
|
||||
if (root_level)
|
||||
{
|
||||
do {
|
||||
if (!clang_type.IsValid())
|
||||
break;
|
||||
|
||||
ClangASTType unqual_clang_ast_type = clang_type.GetFullyUnqualifiedType();
|
||||
if (!unqual_clang_ast_type.IsValid())
|
||||
break;
|
||||
if (unqual_clang_ast_type.GetOpaqueQualType() != clang_type.GetOpaqueQualType())
|
||||
GetPossibleMatches (valobj,
|
||||
unqual_clang_ast_type,
|
||||
reason,
|
||||
use_dynamic,
|
||||
entries,
|
||||
did_strip_ptr,
|
||||
did_strip_ref,
|
||||
did_strip_typedef);
|
||||
} while(false);
|
||||
|
||||
|
||||
// if all else fails, go to static type
|
||||
if (valobj.IsDynamic())
|
||||
{
|
||||
lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue());
|
||||
if (static_value_sp)
|
||||
GetPossibleMatches(*static_value_sp.get(),
|
||||
static_value_sp->GetClangType(),
|
||||
reason | lldb_private::eFormatterChoiceCriterionWentToStaticValue,
|
||||
use_dynamic,
|
||||
entries,
|
||||
did_strip_ptr,
|
||||
did_strip_ref,
|
||||
did_strip_typedef,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lldb::TypeFormatImplSP
|
||||
FormatManager::GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp)
|
||||
{
|
||||
|
@ -35,10 +35,10 @@ m_options()
|
||||
{
|
||||
if (valobj_sp)
|
||||
Update();
|
||||
m_options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
m_options.SetCoerceToId(false);
|
||||
m_options.SetUnwindOnError(true);
|
||||
m_options.SetKeepInMemory(true);
|
||||
m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
}
|
||||
|
||||
size_t
|
||||
|
@ -34,10 +34,10 @@ m_options()
|
||||
{
|
||||
if (valobj_sp)
|
||||
Update();
|
||||
m_options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
m_options.SetCoerceToId(false);
|
||||
m_options.SetUnwindOnError(true);
|
||||
m_options.SetKeepInMemory(true);
|
||||
m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
}
|
||||
|
||||
size_t
|
||||
@ -215,10 +215,10 @@ lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIte
|
||||
{
|
||||
if (valobj_sp)
|
||||
Update();
|
||||
m_options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
m_options.SetCoerceToId(false);
|
||||
m_options.SetUnwindOnError(true);
|
||||
m_options.SetKeepInMemory(true);
|
||||
m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -218,8 +218,10 @@ lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIn
|
||||
StreamString object_fetcher_expr;
|
||||
object_fetcher_expr.Printf("struct __lldb_autogen_nspair { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = %s; _lldb_valgen_item.value = %s; _lldb_valgen_item;",key_fetcher_expr.GetData(),value_fetcher_expr.GetData());
|
||||
lldb::ValueObjectSP child_sp;
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetKeepInMemory(true);
|
||||
m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(), m_backend.GetFrameSP().get(), child_sp,
|
||||
EvaluateExpressionOptions().SetKeepInMemory(true));
|
||||
options);
|
||||
if (child_sp)
|
||||
child_sp->SetName(ConstString(idx_name.GetData()));
|
||||
return child_sp;
|
||||
|
@ -249,6 +249,10 @@ lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
if (idx >= num_children)
|
||||
return lldb::ValueObjectSP();
|
||||
|
||||
ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
|
||||
if (!process_sp)
|
||||
return lldb::ValueObjectSP();
|
||||
|
||||
if (m_children.empty())
|
||||
{
|
||||
// do the scan phase
|
||||
@ -260,7 +264,6 @@ lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
while(tries < num_children)
|
||||
{
|
||||
obj_at_idx = m_data_ptr + (test_idx * m_ptr_size);
|
||||
ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
|
||||
if (!process_sp)
|
||||
return lldb::ValueObjectSP();
|
||||
Error error;
|
||||
@ -286,12 +289,34 @@ lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
SetItemDescriptor &set_item = m_children[idx];
|
||||
if (!set_item.valobj_sp)
|
||||
{
|
||||
// make the new ValueObject
|
||||
StreamString expr;
|
||||
expr.Printf("(id)%" PRIu64,set_item.item_ptr);
|
||||
auto ptr_size = process_sp->GetAddressByteSize();
|
||||
DataBufferHeap buffer(ptr_size,0);
|
||||
switch (ptr_size)
|
||||
{
|
||||
case 0: // architecture has no clue?? - fail
|
||||
return lldb::ValueObjectSP();
|
||||
case 4:
|
||||
*((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr;
|
||||
break;
|
||||
case 8:
|
||||
*((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr;
|
||||
break;
|
||||
default:
|
||||
assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
|
||||
}
|
||||
StreamString idx_name;
|
||||
idx_name.Printf("[%zu]",idx);
|
||||
set_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
|
||||
|
||||
DataExtractor data(buffer.GetBytes(),
|
||||
buffer.GetByteSize(),
|
||||
process_sp->GetByteOrder(),
|
||||
process_sp->GetAddressByteSize());
|
||||
|
||||
set_item.valobj_sp =
|
||||
ValueObject::CreateValueObjectFromData(idx_name.GetData(),
|
||||
data,
|
||||
m_exe_ctx_ref,
|
||||
m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
|
||||
}
|
||||
return set_item.valobj_sp;
|
||||
}
|
||||
@ -392,6 +417,10 @@ lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
if (idx >= num_children)
|
||||
return lldb::ValueObjectSP();
|
||||
|
||||
ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
|
||||
if (!process_sp)
|
||||
return lldb::ValueObjectSP();
|
||||
|
||||
if (m_children.empty())
|
||||
{
|
||||
// do the scan phase
|
||||
@ -403,7 +432,6 @@ lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
while(tries < num_children)
|
||||
{
|
||||
obj_at_idx = m_objs_addr + (test_idx * m_ptr_size);
|
||||
ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
|
||||
if (!process_sp)
|
||||
return lldb::ValueObjectSP();
|
||||
Error error;
|
||||
@ -429,12 +457,34 @@ lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
SetItemDescriptor &set_item = m_children[idx];
|
||||
if (!set_item.valobj_sp)
|
||||
{
|
||||
// make the new ValueObject
|
||||
StreamString expr;
|
||||
expr.Printf("(id)%" PRIu64,set_item.item_ptr);
|
||||
auto ptr_size = process_sp->GetAddressByteSize();
|
||||
DataBufferHeap buffer(ptr_size,0);
|
||||
switch (ptr_size)
|
||||
{
|
||||
case 0: // architecture has no clue?? - fail
|
||||
return lldb::ValueObjectSP();
|
||||
case 4:
|
||||
*((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr;
|
||||
break;
|
||||
case 8:
|
||||
*((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr;
|
||||
break;
|
||||
default:
|
||||
assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
|
||||
}
|
||||
StreamString idx_name;
|
||||
idx_name.Printf("[%zu]",idx);
|
||||
set_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
|
||||
|
||||
DataExtractor data(buffer.GetBytes(),
|
||||
buffer.GetByteSize(),
|
||||
process_sp->GetByteOrder(),
|
||||
process_sp->GetAddressByteSize());
|
||||
|
||||
set_item.valobj_sp =
|
||||
ValueObject::CreateValueObjectFromData(idx_name.GetData(),
|
||||
data,
|
||||
m_exe_ctx_ref,
|
||||
m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
|
||||
}
|
||||
return set_item.valobj_sp;
|
||||
}
|
||||
|
@ -39,15 +39,15 @@ m_name(name)
|
||||
|
||||
bool
|
||||
TypeCategoryImpl::Get (ValueObject& valobj,
|
||||
const FormattersMatchVector& candidates,
|
||||
lldb::TypeFormatImplSP& entry,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
uint32_t* reason)
|
||||
{
|
||||
if (!IsEnabled())
|
||||
return false;
|
||||
if (GetValueNavigator()->Get(valobj, entry, use_dynamic, reason))
|
||||
if (GetValueNavigator()->Get(candidates, entry, reason))
|
||||
return true;
|
||||
bool regex = GetRegexValueNavigator()->Get(valobj, entry, use_dynamic, reason);
|
||||
bool regex = GetRegexValueNavigator()->Get(candidates, entry, reason);
|
||||
if (regex && reason)
|
||||
*reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
|
||||
return regex;
|
||||
@ -55,25 +55,25 @@ TypeCategoryImpl::Get (ValueObject& valobj,
|
||||
|
||||
bool
|
||||
TypeCategoryImpl::Get (ValueObject& valobj,
|
||||
const FormattersMatchVector& candidates,
|
||||
lldb::TypeSummaryImplSP& entry,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
uint32_t* reason)
|
||||
{
|
||||
if (!IsEnabled())
|
||||
return false;
|
||||
if (GetSummaryNavigator()->Get(valobj, entry, use_dynamic, reason))
|
||||
if (GetSummaryNavigator()->Get(candidates, entry, reason))
|
||||
return true;
|
||||
bool regex = GetRegexSummaryNavigator()->Get(valobj, entry, use_dynamic, reason);
|
||||
bool regex = GetRegexSummaryNavigator()->Get(candidates, entry, reason);
|
||||
if (regex && reason)
|
||||
*reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
|
||||
return regex;
|
||||
}
|
||||
|
||||
bool
|
||||
TypeCategoryImpl::Get(ValueObject& valobj,
|
||||
lldb::SyntheticChildrenSP& entry_sp,
|
||||
lldb::DynamicValueType use_dynamic,
|
||||
uint32_t* reason)
|
||||
TypeCategoryImpl::Get (ValueObject& valobj,
|
||||
const FormattersMatchVector& candidates,
|
||||
lldb::SyntheticChildrenSP& entry,
|
||||
uint32_t* reason)
|
||||
{
|
||||
if (!IsEnabled())
|
||||
return false;
|
||||
@ -82,16 +82,16 @@ TypeCategoryImpl::Get(ValueObject& valobj,
|
||||
bool regex_filter = false;
|
||||
// first find both Filter and Synth, and then check which is most recent
|
||||
|
||||
if (!GetFilterNavigator()->Get(valobj, filter_sp, use_dynamic, &reason_filter))
|
||||
regex_filter = GetRegexFilterNavigator()->Get (valobj, filter_sp, use_dynamic, &reason_filter);
|
||||
if (!GetFilterNavigator()->Get(candidates, filter_sp, &reason_filter))
|
||||
regex_filter = GetRegexFilterNavigator()->Get (candidates, filter_sp, &reason_filter);
|
||||
|
||||
#ifndef LLDB_DISABLE_PYTHON
|
||||
bool regex_synth = false;
|
||||
uint32_t reason_synth = 0;
|
||||
bool pick_synth = false;
|
||||
ScriptedSyntheticChildren::SharedPointer synth;
|
||||
if (!GetSyntheticNavigator()->Get(valobj, synth, use_dynamic, &reason_synth))
|
||||
regex_synth = GetRegexSyntheticNavigator()->Get (valobj, synth, use_dynamic, &reason_synth);
|
||||
if (!GetSyntheticNavigator()->Get(candidates, synth, &reason_synth))
|
||||
regex_synth = GetRegexSyntheticNavigator()->Get (candidates, synth, &reason_synth);
|
||||
if (!filter_sp.get() && !synth.get())
|
||||
return false;
|
||||
else if (!filter_sp.get() && synth.get())
|
||||
@ -111,27 +111,26 @@ TypeCategoryImpl::Get(ValueObject& valobj,
|
||||
{
|
||||
if (regex_synth && reason)
|
||||
*reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter;
|
||||
entry_sp = synth;
|
||||
entry = synth;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (regex_filter && reason)
|
||||
*reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter;
|
||||
entry_sp = filter_sp;
|
||||
entry = filter_sp;
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
if (filter_sp)
|
||||
{
|
||||
entry_sp = filter_sp;
|
||||
entry = filter_sp;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -11,6 +11,9 @@
|
||||
|
||||
#include "lldb/DataFormatters/TypeCategoryMap.h"
|
||||
|
||||
#include "lldb/DataFormatters/FormatClasses.h"
|
||||
#include "lldb/DataFormatters/FormatManager.h"
|
||||
|
||||
// C Includes
|
||||
// C++ Includes
|
||||
// Other libraries and framework includes
|
||||
@ -187,13 +190,15 @@ TypeCategoryMap::GetFormat (ValueObject& valobj,
|
||||
|
||||
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
|
||||
|
||||
FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
|
||||
|
||||
for (begin = m_active_categories.begin(); begin != end; begin++)
|
||||
{
|
||||
lldb::TypeCategoryImplSP category_sp = *begin;
|
||||
lldb::TypeFormatImplSP current_format;
|
||||
if (log)
|
||||
log->Printf("\n[TypeCategoryMap::GetFormat] Trying to use category %s", category_sp->GetName());
|
||||
if (!category_sp->Get(valobj, current_format, use_dynamic, &reason_why))
|
||||
if (!category_sp->Get(valobj, matches, current_format, &reason_why))
|
||||
continue;
|
||||
return current_format;
|
||||
}
|
||||
@ -213,13 +218,15 @@ TypeCategoryMap::GetSummaryFormat (ValueObject& valobj,
|
||||
|
||||
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
|
||||
|
||||
FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
|
||||
|
||||
for (begin = m_active_categories.begin(); begin != end; begin++)
|
||||
{
|
||||
lldb::TypeCategoryImplSP category_sp = *begin;
|
||||
lldb::TypeSummaryImplSP current_format;
|
||||
if (log)
|
||||
log->Printf("\n[CategoryMap::GetSummaryFormat] Trying to use category %s", category_sp->GetName());
|
||||
if (!category_sp->Get(valobj, current_format, use_dynamic, &reason_why))
|
||||
if (!category_sp->Get(valobj, matches, current_format, &reason_why))
|
||||
continue;
|
||||
return current_format;
|
||||
}
|
||||
@ -241,13 +248,15 @@ TypeCategoryMap::GetSyntheticChildren (ValueObject& valobj,
|
||||
|
||||
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
|
||||
|
||||
FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
|
||||
|
||||
for (begin = m_active_categories.begin(); begin != end; begin++)
|
||||
{
|
||||
lldb::TypeCategoryImplSP category_sp = *begin;
|
||||
lldb::SyntheticChildrenSP current_format;
|
||||
if (log)
|
||||
log->Printf("\n[CategoryMap::GetSyntheticChildren] Trying to use category %s", category_sp->GetName());
|
||||
if (!category_sp->Get(valobj, current_format, use_dynamic, &reason_why))
|
||||
if (!category_sp->Get(valobj, matches, current_format, &reason_why))
|
||||
continue;
|
||||
return current_format;
|
||||
}
|
||||
|
@ -394,14 +394,9 @@ ClangFunction::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_add
|
||||
|
||||
ThreadPlan *
|
||||
ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
|
||||
lldb::addr_t func_addr,
|
||||
lldb::addr_t &args_addr,
|
||||
Stream &errors,
|
||||
bool stop_others,
|
||||
bool unwind_on_error,
|
||||
bool ignore_breakpoints,
|
||||
lldb::addr_t *this_arg,
|
||||
lldb::addr_t *cmd_arg)
|
||||
lldb::addr_t args_addr,
|
||||
const EvaluateExpressionOptions &options,
|
||||
Stream &errors)
|
||||
{
|
||||
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
|
||||
|
||||
@ -418,16 +413,15 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
|
||||
|
||||
// Okay, now run the function:
|
||||
|
||||
Address wrapper_address (func_addr);
|
||||
Address wrapper_address (m_jit_start_addr);
|
||||
|
||||
lldb::addr_t args = { args_addr };
|
||||
|
||||
ThreadPlan *new_plan = new ThreadPlanCallFunction (*thread,
|
||||
wrapper_address,
|
||||
ClangASTType(),
|
||||
args_addr,
|
||||
stop_others,
|
||||
unwind_on_error,
|
||||
ignore_breakpoints,
|
||||
this_arg,
|
||||
cmd_arg);
|
||||
args,
|
||||
options);
|
||||
new_plan->SetIsMasterPlan(true);
|
||||
new_plan->SetOkayToDiscard (false);
|
||||
return new_plan;
|
||||
@ -478,113 +472,24 @@ ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_
|
||||
exe_ctx.GetProcessRef().DeallocateMemory(args_addr);
|
||||
}
|
||||
|
||||
ExecutionResults
|
||||
ClangFunction::ExecuteFunction(ExecutionContext &exe_ctx, Stream &errors, Value &results)
|
||||
{
|
||||
return ExecuteFunction (exe_ctx, errors, 1000, true, results);
|
||||
}
|
||||
|
||||
ExecutionResults
|
||||
ClangFunction::ExecuteFunction(ExecutionContext &exe_ctx, Stream &errors, bool stop_others, Value &results)
|
||||
{
|
||||
const bool try_all_threads = false;
|
||||
const bool unwind_on_error = true;
|
||||
const bool ignore_breakpoints = true;
|
||||
return ExecuteFunction (exe_ctx, NULL, errors, stop_others, 0UL, try_all_threads,
|
||||
unwind_on_error, ignore_breakpoints, results);
|
||||
}
|
||||
|
||||
ExecutionResults
|
||||
ClangFunction::ExecuteFunction(
|
||||
ExecutionContext &exe_ctx,
|
||||
lldb::addr_t *args_addr_ptr,
|
||||
const EvaluateExpressionOptions &options,
|
||||
Stream &errors,
|
||||
uint32_t timeout_usec,
|
||||
bool try_all_threads,
|
||||
Value &results)
|
||||
{
|
||||
const bool stop_others = true;
|
||||
const bool unwind_on_error = true;
|
||||
const bool ignore_breakpoints = true;
|
||||
return ExecuteFunction (exe_ctx, NULL, errors, stop_others, timeout_usec,
|
||||
try_all_threads, unwind_on_error, ignore_breakpoints, results);
|
||||
}
|
||||
|
||||
// This is the static function
|
||||
ExecutionResults
|
||||
ClangFunction::ExecuteFunction (
|
||||
ExecutionContext &exe_ctx,
|
||||
lldb::addr_t function_address,
|
||||
lldb::addr_t &void_arg,
|
||||
bool stop_others,
|
||||
bool try_all_threads,
|
||||
bool unwind_on_error,
|
||||
bool ignore_breakpoints,
|
||||
uint32_t timeout_usec,
|
||||
Stream &errors,
|
||||
lldb::addr_t *this_arg)
|
||||
{
|
||||
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
|
||||
|
||||
if (log)
|
||||
log->Printf("== [ClangFunction::ExecuteFunction] Executing function ==");
|
||||
|
||||
lldb::ThreadPlanSP call_plan_sp (ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
|
||||
function_address,
|
||||
void_arg,
|
||||
errors,
|
||||
stop_others,
|
||||
unwind_on_error,
|
||||
ignore_breakpoints,
|
||||
this_arg));
|
||||
if (!call_plan_sp)
|
||||
return eExecutionSetupError;
|
||||
|
||||
// <rdar://problem/12027563> we need to make sure we record the fact that we are running an expression here
|
||||
// otherwise this fact will fail to be recorded when fetching an Objective-C object description
|
||||
if (exe_ctx.GetProcessPtr())
|
||||
exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
|
||||
|
||||
ExecutionResults results = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, call_plan_sp,
|
||||
stop_others,
|
||||
try_all_threads,
|
||||
unwind_on_error,
|
||||
ignore_breakpoints,
|
||||
timeout_usec,
|
||||
errors);
|
||||
|
||||
if (log)
|
||||
{
|
||||
if (results != eExecutionCompleted)
|
||||
{
|
||||
log->Printf("== [ClangFunction::ExecuteFunction] Execution completed abnormally ==");
|
||||
}
|
||||
else
|
||||
{
|
||||
log->Printf("== [ClangFunction::ExecuteFunction] Execution completed normally ==");
|
||||
}
|
||||
}
|
||||
|
||||
if (exe_ctx.GetProcessPtr())
|
||||
exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
ExecutionResults
|
||||
ClangFunction::ExecuteFunction(
|
||||
ExecutionContext &exe_ctx,
|
||||
lldb::addr_t *args_addr_ptr,
|
||||
Stream &errors,
|
||||
bool stop_others,
|
||||
uint32_t timeout_usec,
|
||||
bool try_all_threads,
|
||||
bool unwind_on_error,
|
||||
bool ignore_breakpoints,
|
||||
Value &results)
|
||||
{
|
||||
using namespace clang;
|
||||
ExecutionResults return_value = eExecutionSetupError;
|
||||
|
||||
// ClangFunction::ExecuteFunction execution is always just to get the result. Do make sure we ignore
|
||||
// breakpoints, unwind on error, and don't try to debug it.
|
||||
EvaluateExpressionOptions real_options = options;
|
||||
real_options.SetDebug(false);
|
||||
real_options.SetUnwindOnError(true);
|
||||
real_options.SetIgnoreBreakpoints(true);
|
||||
|
||||
lldb::addr_t args_addr;
|
||||
|
||||
if (args_addr_ptr != NULL)
|
||||
@ -600,17 +505,44 @@ ClangFunction::ExecuteFunction(
|
||||
if (!InsertFunction(exe_ctx, args_addr, errors))
|
||||
return eExecutionSetupError;
|
||||
}
|
||||
|
||||
return_value = ClangFunction::ExecuteFunction (exe_ctx,
|
||||
m_jit_start_addr,
|
||||
args_addr,
|
||||
stop_others,
|
||||
try_all_threads,
|
||||
unwind_on_error,
|
||||
ignore_breakpoints,
|
||||
timeout_usec,
|
||||
errors);
|
||||
|
||||
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
|
||||
|
||||
if (log)
|
||||
log->Printf("== [ClangFunction::ExecuteFunction] Executing function ==");
|
||||
|
||||
lldb::ThreadPlanSP call_plan_sp (GetThreadPlanToCallFunction (exe_ctx,
|
||||
args_addr,
|
||||
real_options,
|
||||
errors));
|
||||
if (!call_plan_sp)
|
||||
return eExecutionSetupError;
|
||||
|
||||
// <rdar://problem/12027563> we need to make sure we record the fact that we are running an expression here
|
||||
// otherwise this fact will fail to be recorded when fetching an Objective-C object description
|
||||
if (exe_ctx.GetProcessPtr())
|
||||
exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
|
||||
|
||||
return_value = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
|
||||
call_plan_sp,
|
||||
real_options,
|
||||
errors);
|
||||
|
||||
if (log)
|
||||
{
|
||||
if (return_value != eExecutionCompleted)
|
||||
{
|
||||
log->Printf("== [ClangFunction::ExecuteFunction] Execution completed abnormally ==");
|
||||
}
|
||||
else
|
||||
{
|
||||
log->Printf("== [ClangFunction::ExecuteFunction] Execution completed normally ==");
|
||||
}
|
||||
}
|
||||
|
||||
if (exe_ctx.GetProcessPtr())
|
||||
exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
|
||||
|
||||
if (args_addr_ptr != NULL)
|
||||
*args_addr_ptr = args_addr;
|
||||
|
||||
|
@ -716,35 +716,6 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
|
||||
return true;
|
||||
}
|
||||
|
||||
ThreadPlan *
|
||||
ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
|
||||
ExecutionContext &exe_ctx)
|
||||
{
|
||||
lldb::addr_t struct_address;
|
||||
|
||||
lldb::addr_t object_ptr = 0;
|
||||
lldb::addr_t cmd_ptr = 0;
|
||||
|
||||
PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr);
|
||||
|
||||
// FIXME: This should really return a ThreadPlanCallUserExpression, in order to make sure that we don't release the
|
||||
// ClangUserExpression resources before the thread plan finishes execution in the target. But because we are
|
||||
// forcing unwind_on_error to be true here, in practical terms that can't happen.
|
||||
|
||||
const bool stop_others = true;
|
||||
const bool unwind_on_error = true;
|
||||
const bool ignore_breakpoints = false;
|
||||
return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
|
||||
m_jit_start_addr,
|
||||
struct_address,
|
||||
error_stream,
|
||||
stop_others,
|
||||
unwind_on_error,
|
||||
ignore_breakpoints,
|
||||
(m_needs_object_ptr ? &object_ptr : NULL),
|
||||
(m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL);
|
||||
}
|
||||
|
||||
bool
|
||||
ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
|
||||
ExecutionContext &exe_ctx,
|
||||
@ -852,27 +823,22 @@ ClangUserExpression::Execute (Stream &error_stream,
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t timeout_usec = options.GetTimeoutUsec();
|
||||
const bool debug = options.GetDebug();
|
||||
const bool unwind_on_error = debug ? false : options.DoesUnwindOnError();
|
||||
const bool ignore_breakpoints = debug ? false : options.DoesIgnoreBreakpoints();
|
||||
const bool stop_others = true;
|
||||
const bool try_all_threads = options.GetRunOthers();
|
||||
lldb::BreakpointSP debug_bkpt_sp;
|
||||
if (debug)
|
||||
{
|
||||
// TODO: push this down into the thread plan and let the plan manage it
|
||||
debug_bkpt_sp = exe_ctx.GetTargetRef().CreateBreakpoint(m_jit_start_addr, false, false);
|
||||
}
|
||||
Address wrapper_address (m_jit_start_addr);
|
||||
|
||||
llvm::SmallVector <lldb::addr_t, 3> args;
|
||||
|
||||
if (m_needs_object_ptr) {
|
||||
args.push_back(object_ptr);
|
||||
if (m_objectivec)
|
||||
args.push_back(cmd_ptr);
|
||||
}
|
||||
|
||||
args.push_back(struct_address);
|
||||
|
||||
lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
|
||||
wrapper_address,
|
||||
struct_address,
|
||||
stop_others,
|
||||
unwind_on_error,
|
||||
ignore_breakpoints,
|
||||
(m_needs_object_ptr ? &object_ptr : NULL),
|
||||
((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
|
||||
args,
|
||||
options,
|
||||
shared_ptr_to_me));
|
||||
|
||||
if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
|
||||
@ -890,19 +856,10 @@ ClangUserExpression::Execute (Stream &error_stream,
|
||||
exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
|
||||
|
||||
ExecutionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
|
||||
call_plan_sp,
|
||||
stop_others,
|
||||
try_all_threads,
|
||||
unwind_on_error,
|
||||
ignore_breakpoints,
|
||||
timeout_usec,
|
||||
call_plan_sp,
|
||||
options,
|
||||
error_stream);
|
||||
|
||||
if (debug_bkpt_sp)
|
||||
{
|
||||
exe_ctx.GetTargetRef().RemoveBreakpointByID(debug_bkpt_sp->GetID());
|
||||
}
|
||||
|
||||
if (exe_ctx.GetProcessPtr())
|
||||
exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
|
||||
|
||||
@ -922,16 +879,22 @@ ClangUserExpression::Execute (Stream &error_stream,
|
||||
if (error_desc)
|
||||
error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
|
||||
else
|
||||
error_stream.Printf ("Execution was interrupted.");
|
||||
error_stream.PutCString ("Execution was interrupted.");
|
||||
|
||||
if ((execution_result == eExecutionInterrupted && unwind_on_error)
|
||||
|| (execution_result == eExecutionHitBreakpoint && ignore_breakpoints))
|
||||
error_stream.Printf ("\nThe process has been returned to the state before expression evaluation.");
|
||||
if ((execution_result == eExecutionInterrupted && options.DoesUnwindOnError())
|
||||
|| (execution_result == eExecutionHitBreakpoint && options.DoesIgnoreBreakpoints()))
|
||||
error_stream.PutCString ("\nThe process has been returned to the state before expression evaluation.");
|
||||
else
|
||||
error_stream.Printf ("\nThe process has been left at the point where it was interrupted, use \"thread return -x\" to return to the state before expression evaluation.");
|
||||
error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, use \"thread return -x\" to return to the state before expression evaluation.");
|
||||
|
||||
return execution_result;
|
||||
}
|
||||
else if (execution_result == eExecutionStoppedForDebug)
|
||||
{
|
||||
error_stream.PutCString ("Execution was halted at the first instruction of the expression function because \"debug\" was requested.\n"
|
||||
"Use \"thread return -x\" to return to the state before expression evaluation.");
|
||||
return execution_result;
|
||||
}
|
||||
else if (execution_result != eExecutionCompleted)
|
||||
{
|
||||
error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
|
||||
|
@ -492,7 +492,10 @@ class EntityVariable : public Materializer::Entity
|
||||
}
|
||||
else
|
||||
{
|
||||
err.SetErrorStringWithFormat("size of variable %s disagrees with the ValueObject's size", m_variable_sp->GetName().AsCString());
|
||||
err.SetErrorStringWithFormat("size of variable %s (%" PRIu64 ") disagrees with the ValueObject's size (%" PRIu64 ")",
|
||||
m_variable_sp->GetName().AsCString(),
|
||||
m_variable_sp->GetType()->GetByteSize(),
|
||||
data.GetByteSize());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- FileSpec.cpp --------------------------------------------*- C++ -*-===//
|
||||
//===-- File.cpp ------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -7,7 +7,6 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#include "lldb/Host/File.h"
|
||||
|
||||
#include <errno.h>
|
||||
@ -237,6 +236,11 @@ File::Open (const char *path, uint32_t options, uint32_t permissions)
|
||||
else if (read)
|
||||
{
|
||||
oflag |= O_RDONLY;
|
||||
|
||||
#ifndef _WIN32
|
||||
if (options & eOpenoptionDontFollowSymlinks)
|
||||
oflag |= O_NOFOLLOW;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
@ -249,15 +253,15 @@ File::Open (const char *path, uint32_t options, uint32_t permissions)
|
||||
mode_t mode = 0;
|
||||
if (oflag & O_CREAT)
|
||||
{
|
||||
if (permissions & ePermissionsUserRead) mode |= S_IRUSR;
|
||||
if (permissions & ePermissionsUserWrite) mode |= S_IWUSR;
|
||||
if (permissions & ePermissionsUserExecute) mode |= S_IXUSR;
|
||||
if (permissions & ePermissionsGroupRead) mode |= S_IRGRP;
|
||||
if (permissions & ePermissionsGroupWrite) mode |= S_IWGRP;
|
||||
if (permissions & ePermissionsGroupExecute) mode |= S_IXGRP;
|
||||
if (permissions & ePermissionsWorldRead) mode |= S_IROTH;
|
||||
if (permissions & ePermissionsWorldWrite) mode |= S_IWOTH;
|
||||
if (permissions & ePermissionsWorldExecute) mode |= S_IXOTH;
|
||||
if (permissions & lldb::eFilePermissionsUserRead) mode |= S_IRUSR;
|
||||
if (permissions & lldb::eFilePermissionsUserWrite) mode |= S_IWUSR;
|
||||
if (permissions & lldb::eFilePermissionsUserExecute) mode |= S_IXUSR;
|
||||
if (permissions & lldb::eFilePermissionsGroupRead) mode |= S_IRGRP;
|
||||
if (permissions & lldb::eFilePermissionsGroupWrite) mode |= S_IWGRP;
|
||||
if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP;
|
||||
if (permissions & lldb::eFilePermissionsWorldRead) mode |= S_IROTH;
|
||||
if (permissions & lldb::eFilePermissionsWorldWrite) mode |= S_IWOTH;
|
||||
if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH;
|
||||
}
|
||||
|
||||
do
|
||||
@ -284,7 +288,7 @@ File::GetPermissions (const char *path, Error &error)
|
||||
else
|
||||
{
|
||||
error.Clear();
|
||||
return file_stats.st_mode; // All bits from lldb_private::File::Permissions match those in POSIX mode bits
|
||||
return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -309,7 +313,7 @@ File::GetPermissions(Error &error) const
|
||||
else
|
||||
{
|
||||
error.Clear();
|
||||
return file_stats.st_mode; // All bits from lldb_private::File::Permissions match those in POSIX mode bits
|
||||
return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "lldb/Core/StreamString.h"
|
||||
#include "lldb/Host/File.h"
|
||||
#include "lldb/Host/FileSpec.h"
|
||||
#include "lldb/Host/Host.h"
|
||||
#include "lldb/Core/DataBufferHeap.h"
|
||||
#include "lldb/Core/DataBufferMemoryMap.h"
|
||||
#include "lldb/Core/RegularExpression.h"
|
||||
@ -646,6 +647,15 @@ FileSpec::GetFileType () const
|
||||
return eFileTypeInvalid;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
FileSpec::GetPermissions () const
|
||||
{
|
||||
uint32_t file_permissions = 0;
|
||||
if (*this)
|
||||
Host::GetFilePermissions(GetPath().c_str(), file_permissions);
|
||||
return file_permissions;
|
||||
}
|
||||
|
||||
TimeValue
|
||||
FileSpec::GetModificationTime () const
|
||||
{
|
||||
@ -1161,26 +1171,26 @@ FileSpec::CopyByRemovingLastPathComponent () const
|
||||
return FileSpec(m_directory.GetCString(),resolve);
|
||||
}
|
||||
|
||||
const char*
|
||||
ConstString
|
||||
FileSpec::GetLastPathComponent () const
|
||||
{
|
||||
if (m_filename.IsEmpty() && m_directory.IsEmpty())
|
||||
return NULL;
|
||||
if (m_filename.IsEmpty())
|
||||
if (m_filename)
|
||||
return m_filename;
|
||||
if (m_directory)
|
||||
{
|
||||
const char* dir_cstr = m_directory.GetCString();
|
||||
const char* last_slash_ptr = ::strrchr(dir_cstr, '/');
|
||||
if (last_slash_ptr == NULL)
|
||||
return m_directory.GetCString();
|
||||
return m_directory;
|
||||
if (last_slash_ptr == dir_cstr)
|
||||
{
|
||||
if (last_slash_ptr[1] == 0)
|
||||
return last_slash_ptr;
|
||||
return ConstString(last_slash_ptr);
|
||||
else
|
||||
return last_slash_ptr+1;
|
||||
return ConstString(last_slash_ptr+1);
|
||||
}
|
||||
if (last_slash_ptr[1] != 0)
|
||||
return last_slash_ptr+1;
|
||||
return ConstString(last_slash_ptr+1);
|
||||
const char* penultimate_slash_ptr = last_slash_ptr;
|
||||
while (*penultimate_slash_ptr)
|
||||
{
|
||||
@ -1190,10 +1200,10 @@ FileSpec::GetLastPathComponent () const
|
||||
if (*penultimate_slash_ptr == '/')
|
||||
break;
|
||||
}
|
||||
ConstString new_path(penultimate_slash_ptr+1,last_slash_ptr-penultimate_slash_ptr);
|
||||
return new_path.AsCString();
|
||||
ConstString result(penultimate_slash_ptr+1,last_slash_ptr-penultimate_slash_ptr);
|
||||
return result;
|
||||
}
|
||||
return m_filename.GetCString();
|
||||
return ConstString();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <grp.h>
|
||||
#include <netdb.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if !defined (__GNU__) && !defined (_WIN32)
|
||||
@ -33,6 +34,7 @@
|
||||
#include <mach/mach_port.h>
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <AvailabilityMacros.h>
|
||||
#endif
|
||||
|
||||
#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
||||
@ -978,6 +980,7 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
|
||||
// on linux this is assumed to be the "lldb" main executable. If LLDB on
|
||||
// linux is actually in a shared library (liblldb.so) then this function will
|
||||
// need to be modified to "do the right thing".
|
||||
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST);
|
||||
|
||||
switch (path_type)
|
||||
{
|
||||
@ -988,6 +991,8 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
|
||||
{
|
||||
FileSpec lldb_file_spec (Host::GetModuleFileSpecForHostAddress ((void *)Host::GetLLDBPath));
|
||||
g_lldb_so_dir = lldb_file_spec.GetDirectory();
|
||||
if (log)
|
||||
log->Printf("Host::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_lldb_so_dir.GetCString());
|
||||
}
|
||||
file_spec.GetDirectory() = g_lldb_so_dir;
|
||||
return (bool)file_spec.GetDirectory();
|
||||
@ -1011,7 +1016,11 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
|
||||
if (framework_pos)
|
||||
{
|
||||
framework_pos += strlen("LLDB.framework");
|
||||
#if !defined (__arm__)
|
||||
#if defined (__arm__)
|
||||
// Shallow bundle
|
||||
*framework_pos = '\0';
|
||||
#else
|
||||
// Normal bundle
|
||||
::strncpy (framework_pos, "/Resources", PATH_MAX - (framework_pos - raw_path));
|
||||
#endif
|
||||
}
|
||||
@ -1019,6 +1028,8 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
|
||||
FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
|
||||
g_lldb_support_exe_dir.SetCString(resolved_path);
|
||||
}
|
||||
if (log)
|
||||
log->Printf("Host::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", g_lldb_support_exe_dir.GetCString());
|
||||
}
|
||||
file_spec.GetDirectory() = g_lldb_support_exe_dir;
|
||||
return (bool)file_spec.GetDirectory();
|
||||
@ -1051,6 +1062,8 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
|
||||
// TODO: Anyone know how we can determine this for linux? Other systems??
|
||||
g_lldb_headers_dir.SetCString ("/opt/local/include/lldb");
|
||||
#endif
|
||||
if (log)
|
||||
log->Printf("Host::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_lldb_headers_dir.GetCString());
|
||||
}
|
||||
file_spec.GetDirectory() = g_lldb_headers_dir;
|
||||
return (bool)file_spec.GetDirectory();
|
||||
@ -1096,6 +1109,10 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
|
||||
FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
|
||||
g_lldb_python_dir.SetCString(resolved_path);
|
||||
}
|
||||
|
||||
if (log)
|
||||
log->Printf("Host::GetLLDBPath(ePathTypePythonDir) => '%s'", g_lldb_python_dir.GetCString());
|
||||
|
||||
}
|
||||
file_spec.GetDirectory() = g_lldb_python_dir;
|
||||
return (bool)file_spec.GetDirectory();
|
||||
@ -1136,6 +1153,10 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
|
||||
g_lldb_system_plugin_dir.SetCString(lldb_file_spec.GetPath().c_str());
|
||||
}
|
||||
#endif // __APPLE__ || __linux__
|
||||
|
||||
if (log)
|
||||
log->Printf("Host::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", g_lldb_system_plugin_dir.GetCString());
|
||||
|
||||
}
|
||||
|
||||
if (g_lldb_system_plugin_dir)
|
||||
@ -1194,6 +1215,8 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
|
||||
|
||||
if (lldb_file_spec.Exists())
|
||||
g_lldb_user_plugin_dir.SetCString(lldb_file_spec.GetPath().c_str());
|
||||
if (log)
|
||||
log->Printf("Host::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", g_lldb_user_plugin_dir.GetCString());
|
||||
}
|
||||
file_spec.GetDirectory() = g_lldb_user_plugin_dir;
|
||||
return (bool)file_spec.GetDirectory();
|
||||
@ -1546,7 +1569,7 @@ Host::RunShellCommand (const char *command,
|
||||
return error;
|
||||
}
|
||||
|
||||
#if defined(__linux__) or defined(__FreeBSD__)
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
// The functions below implement process launching via posix_spawn() for Linux
|
||||
// and FreeBSD.
|
||||
|
||||
@ -1826,11 +1849,168 @@ Host::LaunchApplication (const FileSpec &app_file_spec)
|
||||
return LLDB_INVALID_PROCESS_ID;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Host::MakeDirectory (const char* path, mode_t mode)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LLDB_DISABLE_POSIX
|
||||
|
||||
Error
|
||||
Host::MakeDirectory (const char* path, uint32_t mode)
|
||||
{
|
||||
return UINT32_MAX;
|
||||
Error error;
|
||||
error.SetErrorStringWithFormat("%s in not implemented on this host", __PRETTY_FUNCTION__);
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
Host::GetFilePermissions (const char* path, uint32_t &file_permissions)
|
||||
{
|
||||
Error error;
|
||||
error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
Host::SetFilePermissions (const char* path, uint32_t file_permissions)
|
||||
{
|
||||
Error error;
|
||||
error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
Host::Symlink (const char *src, const char *dst)
|
||||
{
|
||||
Error error;
|
||||
error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
Host::Readlink (const char *path, char *buf, size_t buf_len)
|
||||
{
|
||||
Error error;
|
||||
error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
Host::Unlink (const char *path)
|
||||
{
|
||||
Error error;
|
||||
error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
|
||||
return error;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
Error
|
||||
Host::MakeDirectory (const char* path, uint32_t file_permissions)
|
||||
{
|
||||
Error error;
|
||||
if (path && path[0])
|
||||
{
|
||||
if (::mkdir(path, file_permissions) != 0)
|
||||
{
|
||||
error.SetErrorToErrno();
|
||||
switch (error.GetError())
|
||||
{
|
||||
case ENOENT:
|
||||
{
|
||||
// Parent directory doesn't exist, so lets make it if we can
|
||||
FileSpec spec(path, false);
|
||||
if (spec.GetDirectory() && spec.GetFilename())
|
||||
{
|
||||
// Make the parent directory and try again
|
||||
Error error2 = Host::MakeDirectory(spec.GetDirectory().GetCString(), file_permissions);
|
||||
if (error2.Success())
|
||||
{
|
||||
// Try and make the directory again now that the parent directory was made successfully
|
||||
if (::mkdir(path, file_permissions) == 0)
|
||||
error.Clear();
|
||||
else
|
||||
error.SetErrorToErrno();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EEXIST:
|
||||
{
|
||||
FileSpec path_spec(path, false);
|
||||
if (path_spec.IsDirectory())
|
||||
error.Clear(); // It is a directory and it already exists
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error.SetErrorString("empty path");
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
Host::GetFilePermissions (const char* path, uint32_t &file_permissions)
|
||||
{
|
||||
Error error;
|
||||
struct stat file_stats;
|
||||
if (::stat (path, &file_stats) == 0)
|
||||
{
|
||||
// The bits in "st_mode" currently match the definitions
|
||||
// for the file mode bits in unix.
|
||||
file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
}
|
||||
else
|
||||
{
|
||||
error.SetErrorToErrno();
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
Host::SetFilePermissions (const char* path, uint32_t file_permissions)
|
||||
{
|
||||
Error error;
|
||||
if (::chmod(path, file_permissions) != 0)
|
||||
error.SetErrorToErrno();
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
Host::Symlink (const char *src, const char *dst)
|
||||
{
|
||||
Error error;
|
||||
if (::symlink(dst, src) == -1)
|
||||
error.SetErrorToErrno();
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
Host::Unlink (const char *path)
|
||||
{
|
||||
Error error;
|
||||
if (::unlink(path) == -1)
|
||||
error.SetErrorToErrno();
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
Host::Readlink (const char *path, char *buf, size_t buf_len)
|
||||
{
|
||||
Error error;
|
||||
ssize_t count = ::readlink(path, buf, buf_len);
|
||||
if (count < 0)
|
||||
error.SetErrorToErrno();
|
||||
else if (count < (buf_len-1))
|
||||
buf[count] = '\0'; // Success
|
||||
else
|
||||
error.SetErrorString("'buf' buffer is too small to contain link contents");
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
typedef std::map<lldb::user_id_t, lldb::FileSP> FDToFileMap;
|
||||
@ -1843,7 +2023,7 @@ FDToFileMap& GetFDToFileMap()
|
||||
lldb::user_id_t
|
||||
Host::OpenFile (const FileSpec& file_spec,
|
||||
uint32_t flags,
|
||||
mode_t mode,
|
||||
uint32_t mode,
|
||||
Error &error)
|
||||
{
|
||||
std::string path (file_spec.GetPath());
|
||||
|
@ -38,24 +38,70 @@ OptionParser::EnableError(bool error)
|
||||
}
|
||||
|
||||
int
|
||||
OptionParser::Parse(int argc, char * const argv [],
|
||||
const char *optstring,
|
||||
const Option *longopts, int *longindex)
|
||||
OptionParser::Parse (int argc,
|
||||
char * const argv [],
|
||||
const char *optstring,
|
||||
const Option *longopts,
|
||||
int *longindex)
|
||||
{
|
||||
return getopt_long_only(argc, argv, optstring, (const option*)longopts, longindex);
|
||||
}
|
||||
|
||||
char* OptionParser::GetOptionArgument()
|
||||
char*
|
||||
OptionParser::GetOptionArgument()
|
||||
{
|
||||
return optarg;
|
||||
}
|
||||
|
||||
int OptionParser::GetOptionIndex()
|
||||
int
|
||||
OptionParser::GetOptionIndex()
|
||||
{
|
||||
return optind;
|
||||
}
|
||||
|
||||
int OptionParser::GetOptionErrorCause()
|
||||
int
|
||||
OptionParser::GetOptionErrorCause()
|
||||
{
|
||||
return optopt;
|
||||
}
|
||||
|
||||
std::string
|
||||
OptionParser::GetShortOptionString(struct option *long_options)
|
||||
{
|
||||
std::string s;
|
||||
int i=0;
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
if (long_options[i].name == 0 &&
|
||||
long_options[i].has_arg == 0 &&
|
||||
long_options[i].flag == 0 &&
|
||||
long_options[i].val == 0)
|
||||
{
|
||||
done = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (long_options[i].flag == NULL &&
|
||||
isalpha(long_options[i].val))
|
||||
{
|
||||
s.append(1, (char)long_options[i].val);
|
||||
switch (long_options[i].has_arg)
|
||||
{
|
||||
default:
|
||||
case no_argument:
|
||||
break;
|
||||
|
||||
case optional_argument:
|
||||
s.append(2, ':');
|
||||
break;
|
||||
case required_argument:
|
||||
s.append(1, ':');
|
||||
break;
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
@ -61,9 +61,9 @@ Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
|
||||
uuid_str = uuid_str + ".debug";
|
||||
}
|
||||
|
||||
// Get full path to our module. Needed to check debug files like this:
|
||||
// /usr/lib/debug/usr/lib/libboost_date_time.so.1.46.1
|
||||
std::string module_filename = module_spec.GetFileSpec().GetPath();
|
||||
// Get directory of our module. Needed to check debug files like this:
|
||||
// /usr/lib/debug/usr/lib/library.so.debug
|
||||
std::string module_directory = module_spec.GetFileSpec().GetDirectory().AsCString();
|
||||
|
||||
size_t num_directories = debug_file_search_paths.GetSize();
|
||||
for (size_t idx = 0; idx < num_directories; ++idx)
|
||||
@ -79,7 +79,7 @@ Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
|
||||
files.push_back (dirname + "/" + symbol_filename);
|
||||
files.push_back (dirname + "/.debug/" + symbol_filename);
|
||||
files.push_back (dirname + "/.build-id/" + uuid_str);
|
||||
files.push_back (dirname + module_filename);
|
||||
files.push_back (dirname + module_directory + "/" + symbol_filename);
|
||||
|
||||
const uint32_t num_files = files.size();
|
||||
for (size_t idx_file = 0; idx_file < num_files; ++idx_file)
|
||||
|
@ -815,7 +815,7 @@ Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::add
|
||||
options.SetCoerceToId(false);
|
||||
options.SetUnwindOnError(true);
|
||||
options.SetKeepInMemory(false);
|
||||
options.SetRunOthers(true);
|
||||
options.SetTryAllThreads(true);
|
||||
|
||||
ExecutionResults expr_result = target->EvaluateExpression(s,
|
||||
exe_ctx->GetFramePtr(),
|
||||
|
@ -1434,12 +1434,12 @@ CommandInterpreter::PreprocessCommand (std::string &command)
|
||||
ValueObjectSP expr_result_valobj_sp;
|
||||
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetIgnoreBreakpoints(true)
|
||||
.SetKeepInMemory(false)
|
||||
.SetRunOthers(true)
|
||||
.SetTimeoutUsec(0);
|
||||
options.SetCoerceToId(false);
|
||||
options.SetUnwindOnError(true);
|
||||
options.SetIgnoreBreakpoints(true);
|
||||
options.SetKeepInMemory(false);
|
||||
options.SetTryAllThreads(true);
|
||||
options.SetTimeoutUsec(0);
|
||||
|
||||
ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
|
||||
exe_ctx.GetFramePtr(),
|
||||
@ -1498,6 +1498,9 @@ CommandInterpreter::PreprocessCommand (std::string &command)
|
||||
case eExecutionTimedOut:
|
||||
error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
|
||||
break;
|
||||
case eExecutionStoppedForDebug:
|
||||
error.SetErrorStringWithFormat("expression stop at entry point for debugging for the expression '%s'", expr_str.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,11 +15,7 @@
|
||||
|
||||
#else
|
||||
|
||||
#if defined (__APPLE__)
|
||||
#include <Python/Python.h>
|
||||
#else
|
||||
#include <Python.h>
|
||||
#endif
|
||||
#include "lldb/lldb-python.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -15,12 +15,7 @@
|
||||
|
||||
#else
|
||||
|
||||
#if defined (__APPLE__)
|
||||
#include <Python/Python.h>
|
||||
#else
|
||||
#include <Python.h>
|
||||
#endif
|
||||
|
||||
#include "lldb/lldb-python.h"
|
||||
#include "lldb/Interpreter/ScriptInterpreterPython.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -198,12 +198,7 @@ ABIMacOSX_arm::PrepareTrivialCall (Thread &thread,
|
||||
addr_t sp,
|
||||
addr_t function_addr,
|
||||
addr_t return_addr,
|
||||
addr_t *arg1_ptr,
|
||||
addr_t *arg2_ptr,
|
||||
addr_t *arg3_ptr,
|
||||
addr_t *arg4_ptr,
|
||||
addr_t *arg5_ptr,
|
||||
addr_t *arg6_ptr) const
|
||||
llvm::ArrayRef<addr_t> args) const
|
||||
{
|
||||
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
|
||||
if (!reg_ctx)
|
||||
@ -215,50 +210,45 @@ ABIMacOSX_arm::PrepareTrivialCall (Thread &thread,
|
||||
|
||||
RegisterValue reg_value;
|
||||
|
||||
if (arg1_ptr)
|
||||
const char *reg_names[] = { "r0", "r1", "r2", "r3" };
|
||||
|
||||
llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
|
||||
|
||||
for (size_t i = 0; i < (sizeof(reg_names) / sizeof(reg_names[0])); ++i)
|
||||
{
|
||||
reg_value.SetUInt32(*arg1_ptr);
|
||||
if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("r0"), reg_value))
|
||||
if (ai == ae)
|
||||
break;
|
||||
|
||||
reg_value.SetUInt32(*ai);
|
||||
if (!reg_ctx->WriteRegister(reg_ctx->GetRegisterInfoByName(reg_names[i]), reg_value))
|
||||
return false;
|
||||
|
||||
if (arg2_ptr)
|
||||
|
||||
++ai;
|
||||
}
|
||||
|
||||
if (ai != ae)
|
||||
{
|
||||
// Spill onto the stack
|
||||
size_t num_stack_regs = ae - ai;
|
||||
|
||||
sp -= (num_stack_regs * 4);
|
||||
// Keep the stack 8 byte aligned, not that we need to
|
||||
sp &= ~(8ull-1ull);
|
||||
|
||||
// just using arg1 to get the right size
|
||||
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
|
||||
|
||||
addr_t arg_pos = sp;
|
||||
|
||||
for (; ai != ae; ++ai)
|
||||
{
|
||||
reg_value.SetUInt32(*arg2_ptr);
|
||||
if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("r1"), reg_value))
|
||||
reg_value.SetUInt32(*ai);
|
||||
if (reg_ctx->WriteRegisterValueToMemory(reg_info, arg_pos, reg_info->byte_size, reg_value).Fail())
|
||||
return false;
|
||||
|
||||
if (arg3_ptr)
|
||||
{
|
||||
reg_value.SetUInt32(*arg3_ptr);
|
||||
if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("r2"), reg_value))
|
||||
return false;
|
||||
if (arg4_ptr)
|
||||
{
|
||||
reg_value.SetUInt32(*arg4_ptr);
|
||||
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3");
|
||||
if (!reg_ctx->WriteRegister (reg_info, reg_value))
|
||||
return false;
|
||||
if (arg5_ptr)
|
||||
{
|
||||
// Keep the stack 8 byte aligned, not that we need to
|
||||
sp -= 8;
|
||||
sp &= ~(8ull-1ull);
|
||||
reg_value.SetUInt32(*arg5_ptr);
|
||||
if (reg_ctx->WriteRegisterValueToMemory (reg_info, sp, reg_info->byte_size, reg_value).Fail())
|
||||
return false;
|
||||
if (arg6_ptr)
|
||||
{
|
||||
reg_value.SetUInt32(*arg6_ptr);
|
||||
if (reg_ctx->WriteRegisterValueToMemory (reg_info, sp + 4, reg_info->byte_size, reg_value).Fail())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
arg_pos += reg_info->byte_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TargetSP target_sp (thread.CalculateTarget());
|
||||
Address so_addr;
|
||||
|
||||
|
@ -30,12 +30,7 @@ class ABIMacOSX_arm : public lldb_private::ABI
|
||||
lldb::addr_t sp,
|
||||
lldb::addr_t func_addr,
|
||||
lldb::addr_t returnAddress,
|
||||
lldb::addr_t *arg1_ptr = NULL,
|
||||
lldb::addr_t *arg2_ptr = NULL,
|
||||
lldb::addr_t *arg3_ptr = NULL,
|
||||
lldb::addr_t *arg4_ptr = NULL,
|
||||
lldb::addr_t *arg5_ptr = NULL,
|
||||
lldb::addr_t *arg6_ptr = NULL) const;
|
||||
llvm::ArrayRef<lldb::addr_t> args) const;
|
||||
|
||||
virtual bool
|
||||
GetArgumentValues (lldb_private::Thread &thread,
|
||||
|
@ -260,12 +260,7 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread,
|
||||
addr_t sp,
|
||||
addr_t func_addr,
|
||||
addr_t return_addr,
|
||||
addr_t *arg1_ptr,
|
||||
addr_t *arg2_ptr,
|
||||
addr_t *arg3_ptr,
|
||||
addr_t *arg4_ptr,
|
||||
addr_t *arg5_ptr,
|
||||
addr_t *arg6_ptr) const
|
||||
llvm::ArrayRef<addr_t> args) const
|
||||
{
|
||||
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
|
||||
if (!reg_ctx)
|
||||
@ -287,114 +282,25 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread,
|
||||
RegisterValue reg_value;
|
||||
|
||||
// Write any arguments onto the stack
|
||||
if (arg1_ptr)
|
||||
{
|
||||
sp -= 4;
|
||||
if (arg2_ptr)
|
||||
{
|
||||
sp -= 4;
|
||||
if (arg3_ptr)
|
||||
{
|
||||
sp -= 4;
|
||||
if (arg4_ptr)
|
||||
{
|
||||
sp -= 4;
|
||||
if (arg5_ptr)
|
||||
{
|
||||
sp -= 4;
|
||||
if (arg6_ptr)
|
||||
{
|
||||
sp -= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sp -= 4 * args.size();
|
||||
|
||||
// Align the SP
|
||||
sp &= ~(16ull-1ull); // 16-byte alignment
|
||||
|
||||
if (arg1_ptr)
|
||||
addr_t arg_pos = sp;
|
||||
|
||||
for (addr_t arg : args)
|
||||
{
|
||||
reg_value.SetUInt32(*arg1_ptr);
|
||||
error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
|
||||
sp,
|
||||
reg_info_32->byte_size,
|
||||
reg_value.SetUInt32(arg);
|
||||
error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
|
||||
arg_pos,
|
||||
reg_info_32->byte_size,
|
||||
reg_value);
|
||||
if (error.Fail())
|
||||
return false;
|
||||
|
||||
if (arg2_ptr)
|
||||
{
|
||||
reg_value.SetUInt32(*arg2_ptr);
|
||||
// The register info used to write memory just needs to have the correct
|
||||
// size of a 32 bit register, the actual register it pertains to is not
|
||||
// important, just the size needs to be correct. Here we use "eax"...
|
||||
error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
|
||||
sp + 4,
|
||||
reg_info_32->byte_size,
|
||||
reg_value);
|
||||
if (error.Fail())
|
||||
return false;
|
||||
|
||||
if (arg3_ptr)
|
||||
{
|
||||
reg_value.SetUInt32(*arg3_ptr);
|
||||
// The register info used to write memory just needs to have the correct
|
||||
// size of a 32 bit register, the actual register it pertains to is not
|
||||
// important, just the size needs to be correct. Here we use "eax"...
|
||||
error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
|
||||
sp + 8,
|
||||
reg_info_32->byte_size,
|
||||
reg_value);
|
||||
if (error.Fail())
|
||||
return false;
|
||||
|
||||
if (arg4_ptr)
|
||||
{
|
||||
reg_value.SetUInt32(*arg4_ptr);
|
||||
// The register info used to write memory just needs to have the correct
|
||||
// size of a 32 bit register, the actual register it pertains to is not
|
||||
// important, just the size needs to be correct. Here we use "eax"...
|
||||
error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
|
||||
sp + 12,
|
||||
reg_info_32->byte_size,
|
||||
reg_value);
|
||||
if (error.Fail())
|
||||
return false;
|
||||
if (arg5_ptr)
|
||||
{
|
||||
reg_value.SetUInt32(*arg5_ptr);
|
||||
// The register info used to write memory just needs to have the correct
|
||||
// size of a 32 bit register, the actual register it pertains to is not
|
||||
// important, just the size needs to be correct. Here we use "eax"...
|
||||
error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
|
||||
sp + 16,
|
||||
reg_info_32->byte_size,
|
||||
reg_value);
|
||||
if (error.Fail())
|
||||
return false;
|
||||
if (arg6_ptr)
|
||||
{
|
||||
reg_value.SetUInt32(*arg6_ptr);
|
||||
// The register info used to write memory just needs to have the correct
|
||||
// size of a 32 bit register, the actual register it pertains to is not
|
||||
// important, just the size needs to be correct. Here we use "eax"...
|
||||
error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
|
||||
sp + 20,
|
||||
reg_info_32->byte_size,
|
||||
reg_value);
|
||||
if (error.Fail())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
arg_pos += 4;
|
||||
}
|
||||
|
||||
|
||||
// The return address is pushed onto the stack (yes after we just set the
|
||||
// alignment above!).
|
||||
sp -= 4;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user