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:
Ed Maste 2013-12-03 18:51:59 +00:00
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
149 changed files with 6611 additions and 2727 deletions

View File

@ -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 ();

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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 ();

View 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_

View File

@ -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.
///

View File

@ -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;

View File

@ -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.

View File

@ -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);

View File

@ -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;

View File

@ -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;
};

View File

@ -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;

View File

@ -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;

View File

@ -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"

View File

@ -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 {

View File

@ -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:

View File

@ -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;

View File

@ -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;
}
};

View File

@ -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

View File

@ -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

View File

@ -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
View 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 &reg_value) = 0;
virtual Error WriteRegister (uint32_t reg, const RegisterValue &reg_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_

View File

@ -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 ();

View File

@ -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;
//------------------------------------------------------------------

View File

@ -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

View File

@ -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);
};
}

View File

@ -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 {

View File

@ -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"

View File

@ -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;

View File

@ -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,

View File

@ -66,6 +66,12 @@ class LanguageRuntime :
{
}
virtual bool
ExceptionBreakpointsAreSet ()
{
return false;
}
virtual bool
ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
{

View File

@ -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;

View File

@ -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;

View 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_

View File

@ -59,6 +59,18 @@ class RegisterContext :
virtual bool
WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_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 &reg_checkpoint);
virtual bool
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) = 0;
WriteAllRegisterValues (const lldb_private::RegisterCheckpoint &reg_checkpoint);
bool
CopyFromRegisterContext (lldb::RegisterContextSP context);

View File

@ -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);
};

View File

@ -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,

View File

@ -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

View File

@ -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
//------------------------------------------------------------------

View File

@ -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);
};

View File

@ -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

View 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

View File

@ -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 {

View File

@ -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

View File

@ -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;

View File

@ -133,7 +133,8 @@ typedef enum ExecutionResults
eExecutionDiscarded,
eExecutionInterrupted,
eExecutionHitBreakpoint,
eExecutionTimedOut
eExecutionTimedOut,
eExecutionStoppedForDebug
} ExecutionResults;
typedef enum ObjCRuntimeVersions {

View File

@ -18,11 +18,7 @@
#else
#if defined (__APPLE__)
#include <Python/Python.h>
#else
#include <Python.h>
#endif
#endif // LLDB_DISABLE_PYTHON

View File

@ -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)
{

View File

@ -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 *

View File

@ -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
{

View File

@ -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
View 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;
}

View File

@ -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();

View File

@ -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);

View 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
(

View File

@ -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;
}

View File

@ -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.

View File

@ -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 ();
}

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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)));
}

View File

@ -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)));
}

View File

@ -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)

View File

@ -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 ())
{

View File

@ -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

View File

@ -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 }
};

View File

@ -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,

View File

@ -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;

View File

@ -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)

View File

@ -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;
}

View File

@ -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

View File

@ -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),

View File

@ -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)
{
}

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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)
{

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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));

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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());

View File

@ -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;
}

View File

@ -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)

View 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(),

View File

@ -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;
}
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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;

View File

@ -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,

View File

@ -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